API Reference
Complete reference for the @featsync/sdk package.
Class: Featsync
The main SDK class.
Constructor
new Featsync(config: FeatsyncConfig)FeatsyncConfig
| Property | Type | Default | Description |
|---|---|---|---|
apiKey | string | required | Your API key from the dashboard |
environment | string | 'production' | Environment name (informational) |
cacheMs | number | 60000 | Cache duration in milliseconds |
timeoutMs | number | 5000 | Request timeout in milliseconds |
prefetch | boolean | false | Fetch all flags on initialization |
persist | boolean | true | Persist cache to localStorage |
baseUrl | string | 'https://featsync.io' | API base URL |
storageKey | string | 'featsync' | localStorage key prefix |
Methods
isEnabled(key, defaultValue?)
Check if a flag is enabled.
isEnabled(key: string, defaultValue?: boolean): Promise<boolean>Parameters:
key- The flag keydefaultValue- Value to return if flag doesn’t exist (default:false)
Returns: Promise<boolean>
Example:
const enabled = await featsync.isEnabled('new-feature');const beta = await featsync.isEnabled('beta-feature', true);evaluate(key, context, defaultValue?)
Evaluate a flag with user context for targeting rules. Makes a server-side API call to evaluate targeting rules.
evaluate( key: string, context: EvaluationContext, defaultValue?: boolean): Promise<boolean>Parameters:
key- The flag key to evaluatecontext- User context for targeting evaluationdefaultValue- Value to return on error (default:false)
Returns: Promise<boolean>
Example:
const enabled = await featsync.evaluate('new-checkout', { userId: 'user_123', email: 'john@acme.com', country: 'US', custom: { plan: 'enterprise', beta_tester: true, },});evaluateWithDetails(key, context)
Evaluate a flag with user context and get detailed result including the reason.
evaluateWithDetails( key: string, context: EvaluationContext): Promise<EvaluationResult>Parameters:
key- The flag key to evaluatecontext- User context for targeting evaluation
Returns: Promise<EvaluationResult>
Example:
const result = await featsync.evaluateWithDetails('new-checkout', { userId: 'user_123', email: 'john@acme.com',});
console.log(result.enabled); // trueconsole.log(result.reason); // "rule"console.log(result.ruleName); // "Enterprise users"isEnabledForUser(key, userId, defaultValue?)
Check if a flag is enabled for a specific user. Essential for percentage rollouts.
isEnabledForUser( key: string, userId: string, defaultValue?: boolean): Promise<boolean>Parameters:
key- The flag keyuserId- A unique, stable user identifierdefaultValue- Value to return if flag doesn’t exist (default:false)
Returns: Promise<boolean>
Example:
const userId = getCurrentUserId();const enabled = await featsync.isEnabledForUser('gradual-rollout', userId);Notes:
- For boolean flags, behaves the same as
isEnabled() - For percentage flags, uses consistent hashing to determine if the user is in the rollout
- Same user always gets the same result for the same flag
getFlag(key)
Get detailed information about a flag.
getFlag(key: string): Promise<Flag>Parameters:
key- The flag key
Returns: Promise<Flag>
Example:
const flag = await featsync.getFlag('my-flag');console.log(flag.key); // 'my-flag'console.log(flag.enabled); // trueconsole.log(flag.percentage); // 50 or nullgetAllFlags()
Fetch all flags in a single API call.
getAllFlags(): Promise<FlagsMap>Returns: Promise<FlagsMap>
Example:
const flags = await featsync.getAllFlags();
if (flags['feature-a']?.enabled) { // Feature A is on}clearCache()
Clear the local cache. The next flag check will fetch fresh data from the API.
clearCache(): voidExample:
featsync.clearCache();// Next call will fetch from APIsetEnvironment(environment)
Change the environment at runtime.
setEnvironment(environment: string): voidParameters:
environment- The new environment name
Example:
featsync.setEnvironment('staging');featsync.clearCache();Note: You’ll also need to update your API key to match the new environment.
Types
Flag
interface Flag { key: string; enabled: boolean; percentage: number | null;}| Property | Type | Description |
|---|---|---|
key | string | The flag key |
enabled | boolean | Whether the flag is enabled |
percentage | number | null | Rollout percentage (0-100) or null for boolean flags |
FlagsMap
type FlagsMap = Record<string, Flag>;A map of flag keys to Flag objects.
FeatsyncConfig
interface FeatsyncConfig { apiKey: string; environment?: string; cacheMs?: number; timeoutMs?: number; prefetch?: boolean; persist?: boolean; baseUrl?: string; storageKey?: string;}EvaluationContext
User context for targeting rule evaluation.
interface EvaluationContext { userId?: string; email?: string; country?: string; custom?: Record<string, string | number | boolean>;}| Property | Type | Description |
|---|---|---|
userId | string | User ID for percentage consistency |
email | string | User’s email address |
country | string | ISO country code (e.g., “US”, “GB”) |
custom | Record<string, string|number|boolean> | Custom attributes for targeting rules |
EvaluationResult
Result from evaluateWithDetails().
interface EvaluationResult { enabled: boolean; reason: 'default' | 'rule' | 'segment' | 'percentage' | 'disabled' | 'not_found' | 'error'; ruleId?: string; ruleName?: string; segmentId?: string;}| Property | Type | Description |
|---|---|---|
enabled | boolean | Whether the flag is enabled for this context |
reason | string | Why this result was returned |
ruleId | string | ID of matching rule (if reason is “rule”) |
ruleName | string | Name of matching rule |
segmentId | string | ID of matching segment (if reason is “segment”) |
Error Handling
The SDK is designed to be resilient and won’t throw errors during normal operation:
// Won't throw - returns false on errorconst enabled = await featsync.isEnabled('my-flag');
// For explicit error handlingtry { const flags = await featsync.getAllFlags();} catch (error) { console.error('Failed to fetch flags:', error);}Caching Behavior
- Memory Cache - Flags are cached in memory for
cacheMsmilliseconds - Persistent Cache - If
persist: true, flags are also saved to localStorage - Stale-While-Revalidate - If a fetch fails, stale cached data is used
- Never Breaks - Even if the API is down, the SDK returns cached values
Bundle Size
- ~4KB minified + gzipped
- No external dependencies
- Tree-shakeable exports