Skip to content

API Reference

Complete reference for the @featsync/sdk package.

Class: Featsync

The main SDK class.

Constructor

new Featsync(config: FeatsyncConfig)

FeatsyncConfig

PropertyTypeDefaultDescription
apiKeystringrequiredYour API key from the dashboard
environmentstring'production'Environment name (informational)
cacheMsnumber60000Cache duration in milliseconds
timeoutMsnumber5000Request timeout in milliseconds
prefetchbooleanfalseFetch all flags on initialization
persistbooleantruePersist cache to localStorage
baseUrlstring'https://featsync.io'API base URL
storageKeystring'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 key
  • defaultValue - 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 evaluate
  • context - User context for targeting evaluation
  • defaultValue - 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 evaluate
  • context - 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); // true
console.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 key
  • userId - A unique, stable user identifier
  • defaultValue - 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); // true
console.log(flag.percentage); // 50 or null

getAllFlags()

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(): void

Example:

featsync.clearCache();
// Next call will fetch from API

setEnvironment(environment)

Change the environment at runtime.

setEnvironment(environment: string): void

Parameters:

  • 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;
}
PropertyTypeDescription
keystringThe flag key
enabledbooleanWhether the flag is enabled
percentagenumber | nullRollout 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>;
}
PropertyTypeDescription
userIdstringUser ID for percentage consistency
emailstringUser’s email address
countrystringISO country code (e.g., “US”, “GB”)
customRecord<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;
}
PropertyTypeDescription
enabledbooleanWhether the flag is enabled for this context
reasonstringWhy this result was returned
ruleIdstringID of matching rule (if reason is “rule”)
ruleNamestringName of matching rule
segmentIdstringID 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 error
const enabled = await featsync.isEnabled('my-flag');
// For explicit error handling
try {
const flags = await featsync.getAllFlags();
} catch (error) {
console.error('Failed to fetch flags:', error);
}

Caching Behavior

  1. Memory Cache - Flags are cached in memory for cacheMs milliseconds
  2. Persistent Cache - If persist: true, flags are also saved to localStorage
  3. Stale-While-Revalidate - If a fetch fails, stale cached data is used
  4. Never Breaks - Even if the API is down, the SDK returns cached values

Bundle Size

  • ~4KB minified + gzipped
  • No external dependencies
  • Tree-shakeable exports