Skip to content

TypeScript SDK

TypeScript/JavaScript SDK for feature flags and secrets with SSE streaming.

Terminal window
npm install @getsoup/sdk

Works with Node.js, Deno, and Bun.

import { SoupClient } from '@getsoup/sdk';
const client = new SoupClient({
apiKey: 'sk_project_xxx',
projectSlug: 'my-app',
environmentSlug: 'production',
});
// Feature flags
client.flags.identify({ key: 'user-123', attributes: { plan: 'pro' } });
if (await client.flags.boolFlag('new-checkout', false)) {
showNewCheckout();
}
// Secrets
const dbUrl = await client.secrets.get('DATABASE_URL');
client.close();

Boolean flags:

const enabled = await client.flags.boolFlag('dark-mode', false);

Typed flag helpers:

const limit = await client.flags.numberFlag('rate-limit', 100);
const cta = await client.flags.stringFlag('cta-text', 'Sign up');
const config = await client.flags.jsonFlag('ui-config', {});

Evaluation context:

client.flags.identify({
key: 'user-123',
attributes: {
plan: 'enterprise',
betaTester: true,
signupDate: '2025-01-15',
},
});

Context persists for all subsequent flag evaluations.

Get secret:

const apiKey = await client.secrets.get('API_KEY');

Returns null if not found.

Load into process.env:

await client.secrets.injectEnv();
const dbUrl = process.env.DATABASE_URL;

Loads all secrets into process.env.

Fetch content entries:

// Get all entries of a type
const posts = await client.cms.entries('blog-post', { status: 'published' });
// Get single entry
const post = await client.cms.entry('blog-post', 'getting-started');
console.log(post.data.title);

Query with filters:

const posts = await client.cms.entries('blog-post', {
status: 'published',
page: 1,
limit: 10,
});

Content types:

// List all content types
const types = await client.cms.types();
// Get single type
const blogType = await client.cms.type('blog-post');
console.log(blogType.fields);

Evaluate segment:

const matched = await client.segments.evaluate('enterprise-users', {
context: { userId: 'user-123', plan: 'enterprise' },
});
if (matched) {
showEnterpriseFeatures();
}

List segments:

const segments = await client.segments.list();
segments.forEach(segment => {
console.log(segment.key, segment.name);
});

List cron jobs:

const jobs = await client.cron.list();
jobs.forEach(job => {
console.log(`${job.name}: ${job.schedule}`);
});

Get job runs:

const runs = await client.cron.runs('daily-sync');
runs.forEach(run => {
console.log(`Status: ${run.status}, Duration: ${run.duration_ms}ms`);
});

Trigger manually:

const run = await client.cron.trigger('daily-sync');
console.log(`Run ID: ${run.id}`);

List workflows:

const workflows = await client.workflows.list();
workflows.forEach(wf => {
console.log(`${wf.name}: ${wf.trigger_type}`);
});

Trigger workflow:

const run = await client.workflows.trigger('user-onboarding', {
payload: { email: '[email protected]', name: 'Alice' },
});
console.log(`Run ID: ${run.id}`);

Get workflow runs:

const runs = await client.workflows.runs('user-onboarding');
runs.forEach(run => {
console.log(`Status: ${run.status}, Steps: ${run.steps.length}`);
});

SSE streaming is enabled by default. Flags update automatically when changed in dashboard.

Listen for updates:

client.flags.on('flags_updated', (keys: string[]) => {
console.log(`Flags changed: ${keys}`);
});
client.flags.on('connection', (status: 'connected' | 'disconnected') => {
console.log(`SSE ${status}`);
});
client.flags.on('error', (error: Error) => {
console.error('Flag error:', error);
});

Disable streaming:

const client = new SoupClient({
apiKey: 'sk_project_xxx',
projectSlug: 'my-app',
environmentSlug: 'production',
streaming: false,
});
import { SoupClient } from '@getsoup/sdk';
const client = new SoupClient({
apiKey: 'sk_project_xxx',
projectSlug: 'my-app',
environmentSlug: 'production',
baseUrl: 'https://api.getsoup.dev', // default
streaming: true, // default
});
import type {
SoupConfig,
EvalContext,
EvalResult,
FlagEventListener,
ConnectionEventListener,
ErrorEventListener,
} from '@getsoup/sdk';

EvalContext:

interface EvalContext {
key: string; // user ID, session ID, etc.
attributes?: Record<string, string | number | boolean>;
}

EvalResult:

interface EvalResult {
enabled: boolean;
value: string;
reason: 'TARGETING' | 'ROLLOUT' | 'DEFAULT' | 'ERROR';
}
try {
const enabled = await client.flags.boolFlag('feature', false);
} catch (error) {
console.error('Flag evaluation failed:', error);
}

Defaults are returned if evaluation fails.

Generate project API keys in dashboard:

  • Settings → API Keys → Create Key
  • Format: sk_project_xxx

For self-hosted, use master API key from soup-engine config.