npm package: @subscribeflow/sdk
Description: TypeScript SDK for SubscribeFlow API - Email subscription management
Author: SubscribeFlow Team
Latest version: 1.0.32

# @subscribeflow/sdk

<p align="center">
  <a href="https://subscribeflow.net">
    <img src="https://docs.subscribeflow.net/assets/sdk-hero.svg" alt="SubscribeFlow" width="100%">
  </a>
</p>

Official TypeScript SDK for SubscribeFlow — full type safety, tree-shakeable, zero dependencies. Manage email subscriptions, campaigns, and GDPR-compliant preference centers.

[![npm Version](https://img.shields.io/npm/v/@subscribeflow/sdk)](https://www.npmjs.com/package/@subscribeflow/sdk)
[![npm Downloads](https://img.shields.io/npm/dm/@subscribeflow/sdk)](https://www.npmjs.com/package/@subscribeflow/sdk)
[![Node Version](https://img.shields.io/badge/node-%3E%3D18-brightgreen)](https://www.npmjs.com/package/@subscribeflow/sdk)
[![License](https://img.shields.io/npm/l/@subscribeflow/sdk)](https://www.npmjs.com/package/@subscribeflow/sdk)
[![Works with Claude](https://img.shields.io/badge/Works%20with-Claude-blueviolet)](https://docs.subscribeflow.net/sdk/mcp)

[Dashboard](https://subscribeflow.net) | [Documentation](https://docs.subscribeflow.net) | [API Reference](https://docs.subscribeflow.net/api/reference) | [MCP Integration](https://docs.subscribeflow.net/sdk/mcp)

---

## Installation

### From npm (Recommended)

Install the SDK using your preferred package manager:

```bash
# npm
npm install @subscribeflow/sdk

# yarn
yarn add @subscribeflow/sdk

# bun
bun add @subscribeflow/sdk
```

Or add it directly to your `package.json`:

```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:

```bash
# npm/yarn/pnpm
npm install /path/to/subscribeflow/sdk/typescript

# bun
bun add /path/to/subscribeflow/sdk/typescript
```

In `package.json`:
```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:

```bash
# 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/sdk
```

**Advantage:** 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:

```json
// package.json (root)
{
  "workspaces": ["apps/*", "sdk/*"]
}
```

### Best Practices for Local Development

1. **During development:** Use `npm link` or `file:` for fast iteration
2. **Before committing:** Switch back to the npm registry version
3. **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.

```typescript
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: 'user@example.com',
  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.

```typescript
// 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.

```typescript
// 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.

```typescript
// 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.

```typescript
// Send a transactional email to a single recipient
const result = await client.emails.send({
  template_slug: 'welcome-email',
  to: 'user@example.com',
  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.

```typescript
// 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.

```typescript
// 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.

```typescript
// 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).

```typescript
// 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.

```typescript
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.

```typescript
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:

```typescript
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.

```typescript
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:

```bash
# 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.ts
```

## MCP 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](https://docs.subscribeflow.net/sdk/mcp) for setup instructions.

## Links

- [Dashboard](https://subscribeflow.net)
- [Documentation](https://docs.subscribeflow.net)
- [API Reference](https://docs.subscribeflow.net/api/reference)
- [MCP Integration](https://docs.subscribeflow.net/sdk/mcp)
- [Feedback](https://subscribeflow.net/feedback)

## License

MIT