@subscribeflow/sdk
v1.0.33
Published
TypeScript SDK for SubscribeFlow API - Email subscription management
Downloads
523
Maintainers
Readme
@subscribeflow/sdk
Official TypeScript SDK for SubscribeFlow — full type safety, tree-shakeable, zero dependencies. Manage email subscriptions, campaigns, and GDPR-compliant preference centers.
Dashboard | Documentation | API Reference | MCP Integration
Installation
From npm (Recommended)
Install the SDK using your preferred package manager:
# npm
npm install @subscribeflow/sdk
# yarn
yarn add @subscribeflow/sdk
# bun
bun add @subscribeflow/sdkOr add it directly to your package.json:
{
"dependencies": {
"@subscribeflow/sdk": "^1.0.0"
}
}Local Development
If you are developing the SDK alongside your application, you can link it locally instead of installing from the registry.
Option 1: file: Protocol (Simplest)
Point your dependency directly at the local SDK directory:
# npm/yarn/pnpm
npm install /path/to/subscribeflow/sdk/typescript
# bun
bun add /path/to/subscribeflow/sdk/typescriptIn package.json:
{
"dependencies": {
"@subscribeflow/sdk": "file:../subscribeflow/sdk/typescript"
}
}Option 2: npm link / bun link (Symlink)
Create a global symlink so changes to the SDK are reflected immediately without reinstalling:
# In the SDK directory
cd /path/to/subscribeflow/sdk/typescript
npm link # or: bun link
# In your project
cd /path/to/your/project
npm link @subscribeflow/sdk # or: bun link @subscribeflow/sdkAdvantage: Any change you make to the SDK source is immediately available in your project without reinstalling.
Option 3: Workspace (Monorepo)
For projects within the same repository, use workspaces:
// package.json (root)
{
"workspaces": ["apps/*", "sdk/*"]
}Best Practices for Local Development
- During development: Use
npm linkorfile:for fast iteration - Before committing: Switch back to the npm registry version
- CI/CD: Always use the npm registry
Quick Start
The following example shows how to initialize the client and create your first subscriber. You need an API key, which you can generate from your SubscribeFlow admin dashboard.
import { SubscribeFlowClient } from '@subscribeflow/sdk';
const client = new SubscribeFlowClient({
apiKey: process.env.SUBSCRIBEFLOW_API_KEY!,
baseUrl: 'https://api.subscribeflow.net', // optional, this is the default
});
// Create a subscriber with tags and metadata
const subscriber = await client.subscribers.create({
email: '[email protected]',
tags: ['newsletter', 'product-updates'],
metadata: { source: 'website' },
});
console.log('Created subscriber:', subscriber.id);Usage
Subscribers
Subscribers are the core entity in SubscribeFlow. Each subscriber represents a person identified by their email address. You can list, create, update, and delete subscribers, as well as manage their tag subscriptions and metadata.
// List subscribers with optional filters
// Returns paginated results with items, total count, and cursor for pagination
const { items, total, cursor } = await client.subscribers.list({
limit: 50,
status: 'active',
});
// Get a single subscriber by ID
const subscriber = await client.subscribers.get('subscriber-id');
// Update subscriber metadata
// Only the fields you pass will be changed; everything else stays the same
const updated = await client.subscribers.update('subscriber-id', {
metadata: { plan: 'premium' },
});
// Permanently delete a subscriber and all associated data
await client.subscribers.delete('subscriber-id');Tags
Tags represent topics or categories that subscribers can opt into. They are the building block of SubscribeFlow's granular preference management. Unlike traditional mailing lists, subscribers can actively discover and subscribe to tags they are interested in.
// Create a new tag with a human-readable name and a URL-safe slug
const tag = await client.tags.create({
name: 'Product Updates',
slug: 'product-updates',
description: 'Get notified about new features and improvements',
});
// List all tags in your organization
const { items } = await client.tags.list();
// Update a tag's description or other properties
await client.tags.update('tag-id', {
description: 'Updated description',
});
// Delete a tag (subscribers will be automatically unsubscribed)
await client.tags.delete('tag-id');Templates
Templates define the content and layout of your emails. SubscribeFlow uses MJML for responsive email rendering and supports Mustache-style variables for dynamic content.
// Create a new email template with MJML content
// Variables like {{company}} will be replaced when sending
const template = await client.templates.create({
name: 'Welcome Email',
subject: 'Welcome to {{company}}!',
mjml_content: '<mjml><mj-body>...</mj-body></mjml>',
category: 'transactional',
});
// List templates, optionally filtered by category
const { items } = await client.templates.list({ category: 'transactional' });
// Look up a template by its slug (useful for send operations)
const tmpl = await client.templates.getBySlug('welcome-email');
// Preview how a template will look with specific variable values
const preview = await client.templates.preview('template-id', {
company: 'Acme Inc',
});
console.log(preview.html);
// Update a template's subject or content
await client.templates.update('template-id', { subject: 'New Subject' });
// Delete a template
await client.templates.delete('template-id');Email Send
Send individual transactional emails using a template. Each send requires a template slug and recipient. The optional idempotency_key prevents duplicate sends if the same request is retried.
// Send a transactional email to a single recipient
const result = await client.emails.send({
template_slug: 'welcome-email',
to: '[email protected]',
variables: { company: 'Acme Inc' },
idempotency_key: 'unique-key-123', // prevents duplicate sends on retry
});
console.log('Email queued:', result.id);Campaigns
Campaigns let you send emails to groups of subscribers based on tag filters. Create a draft, preview the recipient count, and then send it. Running campaigns can be cancelled.
// Create a campaign draft targeting subscribers with specific tags
const campaign = await client.campaigns.create({
name: 'February Newsletter',
template_id: 'template-uuid',
tag_filter: { include_tags: ['newsletter'], match: 'any' },
});
// List campaigns filtered by status
const campaigns = await client.campaigns.list({ status: 'draft' });
// Preview how many subscribers will receive this campaign
const count = await client.campaigns.countRecipients('campaign-id');
console.log(`Will send to ${count.count} subscribers`);
// Send the campaign (moves from draft to sending)
const sendResult = await client.campaigns.send('campaign-id');
// Cancel a running campaign (emails already sent cannot be recalled)
await client.campaigns.cancel('campaign-id');Email Triggers
Triggers automatically send emails in response to events. For example, you can send a welcome email whenever a new subscriber is created. Triggers can be activated or deactivated without deleting them.
// Create a trigger that fires when a subscriber is created
const trigger = await client.triggers.create({
event_type: 'subscriber.created',
template_id: 'welcome-template-uuid',
description: 'Send welcome email on signup',
});
// List all triggers
const triggers = await client.triggers.list();
// Deactivate a trigger without deleting it
await client.triggers.update('trigger-id', { is_active: false });
// Permanently delete a trigger
await client.triggers.delete('trigger-id');Webhooks
Webhooks let your application receive real-time notifications when events occur in SubscribeFlow. Each webhook endpoint receives signed HTTP POST requests that you can verify using the signing secret.
// Register a new webhook endpoint for specific event types
const webhook = await client.webhooks.create({
url: 'https://your-app.com/webhooks/subscribeflow',
events: ['subscriber.created', 'tag.subscribed'],
description: 'Main webhook endpoint',
});
// Important: the signing secret is only returned on creation — store it securely
console.log('Signing secret:', webhook.signing_secret);
// List all registered webhook endpoints
const { items } = await client.webhooks.list();
// Update the events a webhook listens to
await client.webhooks.update('webhook-id', {
events: ['subscriber.created', 'subscriber.deleted'],
});
// Test a webhook by sending a sample payload to your endpoint
const result = await client.webhooks.test('webhook-id', 'subscriber.created');
if (result.success) {
console.log('Webhook is working!');
}
// Rotate the signing secret (invalidates the old one immediately)
const rotated = await client.webhooks.rotateSecret('webhook-id');
console.log('New secret:', rotated.signing_secret);
// View delivery history to debug failed deliveries
const deliveries = await client.webhooks.listDeliveries('webhook-id');
// Get aggregate delivery statistics
const stats = await client.webhooks.getDeliveryStats('webhook-id');
console.log(`Success rate: ${stats.success_rate}%`);
// Retry a specific failed delivery
await client.webhooks.retryDelivery('webhook-id', 'delivery-id');
// Remove a webhook endpoint
await client.webhooks.delete('webhook-id');Preference Center
The Preference Center allows subscribers to manage their own email preferences. Generate a secure token for a subscriber, then use it to access their preferences. This powers the self-service UI where subscribers can subscribe to new tags, unsubscribe, export their data, or delete their account (GDPR compliance).
// Generate a time-limited preference center token for a subscriber
const tokenResponse = await client.subscribers.generatePreferenceToken('subscriber-id');
// Create a preference center client using the token
const prefCenter = client.preferenceCenter(tokenResponse.token);
// Retrieve the subscriber's current preferences and all available tags
const info = await prefCenter.getInfo();
// Subscribe or unsubscribe from individual tags
await prefCenter.subscribeTag('tag-id');
await prefCenter.unsubscribeTag('tag-id');
// Export all subscriber data as JSON (GDPR Art. 20 — Right to Data Portability)
const exportData = await prefCenter.exportData();
// Permanently delete the subscriber account (GDPR Art. 17 — Right to Erasure)
await prefCenter.deleteAccount();Error Handling
All API errors are thrown as SubscribeFlowError instances with structured error details. You can use instanceof checks to handle specific error types.
import { SubscribeFlowClient, SubscribeFlowError } from '@subscribeflow/sdk';
try {
await client.subscribers.get('non-existent-id');
} catch (error) {
if (error instanceof SubscribeFlowError) {
console.error('API Error:', error.message);
console.error('Status:', error.status); // HTTP status code (e.g. 404)
console.error('Type:', error.type); // Machine-readable error type
console.error('Detail:', error.detail); // Human-readable description
}
}Configuration
The client accepts configuration options when initialized. Only the apiKey is required.
const client = new SubscribeFlowClient({
// Required: Your API key (starts with sf_live_ or sf_test_)
apiKey: 'sf_live_xxx',
// Optional: API base URL (default: https://api.subscribeflow.net)
baseUrl: 'https://api.subscribeflow.net',
});Local API Instance
When developing against a local SubscribeFlow backend, point the client to your local server:
const client = new SubscribeFlowClient({
apiKey: 'sf_dev_xxx',
baseUrl: 'http://localhost:8000',
});TypeScript Support
This SDK is written in TypeScript and provides full type definitions out of the box. You can import component schemas directly for use in your own type declarations.
import type { paths, components } from '@subscribeflow/sdk';
// Use component schemas for your own types
type Subscriber = components['schemas']['SubscriberResponse'];
type Tag = components['schemas']['TagResponse'];
// All API operations are fully type-safe
const subscriber: Subscriber = await client.subscribers.get('id');Regenerating Types
If the API changes, you can regenerate the TypeScript types from the OpenAPI schema:
# Make sure the backend is running
make backend
# Fetch OpenAPI schema and generate types
curl http://localhost:8000/openapi.json -o openapi.json
bunx openapi-typescript openapi.json -o src/api-types.tsMCP Server (Claude Integration)
The MCP server for Claude Desktop and Claude Code is available via the Python SDK. Install subscribeflow[mcp] to use natural-language commands with your SubscribeFlow account.
See the MCP Integration Guide for setup instructions.
Links
License
MIT
