SDKs

TypeScript SDK

The official TypeScript SDK for zend.sh. Full type definitions, namespaced resources, and works in Node.js, Bun, and Deno.

Installation

npm install zend-sh

Initialization

import { ZendClient } from 'zend-sh'

const zend = new ZendClient({
  apiKey: 'zk_live_...',
  baseUrl: 'https://app.zend.sh', // optional, defaults to production
})

Resources

Accounts

Manage connected mailbox accounts.

// List all accounts
const { accounts } = await zend.accounts.list()

// Connect a new mailbox
const account = await zend.accounts.create({
  email: 'outreach@yourcompany.com',
  provider: 'google', // 'google' | 'microsoft' | 'smtp'
  smtp_host: 'smtp.gmail.com',
  smtp_port: 465,
  smtp_username: 'outreach@yourcompany.com',
  smtp_password: 'your-app-password',
  imap_host: 'imap.gmail.com',
  imap_port: 993,
  imap_username: 'outreach@yourcompany.com',
  imap_password: 'your-app-password',
})

// Get a single account
const acct = await zend.accounts.get('account-id')

// Update an account
const updated = await zend.accounts.update('account-id', {
  daily_send_limit: 50,
})

// Delete an account
await zend.accounts.delete('account-id')

// Send a test email
const result = await zend.accounts.test('account-id')
// { success: true, message: 'Test email sent' }

Campaigns

Create and manage email campaigns with multi-step sequences.

// List campaigns
const { campaigns } = await zend.campaigns.list()

// Create a campaign
const campaign = await zend.campaigns.create({
  name: 'Q1 Outreach',
  stop_on_reply: true,
  send_window: {
    timezone: 'America/New_York',
    days: ['monday', 'tuesday', 'wednesday', 'thursday', 'friday'],
    start_hour: 9,
    end_hour: 17,
  },
})

// Get, update, delete
const c = await zend.campaigns.get(campaign.id)
await zend.campaigns.update(campaign.id, { name: 'Updated Name' })
await zend.campaigns.delete(campaign.id) // only draft/archived

// Start and pause
await zend.campaigns.start(campaign.id)
await zend.campaigns.pause(campaign.id)

Campaign Steps

Add email and delay steps to a campaign sequence.

// List steps
const { steps } = await zend.campaigns.steps.list(campaign.id)

// Add an email step
await zend.campaigns.steps.create(campaign.id, {
  type: 'email',
  position: 1,
  subject: 'Hi {{first_name|there}}',
  body: 'Your email body with {{company}} variables...',
})

// Add a delay step
await zend.campaigns.steps.create(campaign.id, {
  type: 'delay',
  position: 2,
  delay_days: 3,
})

Campaign Leads

Enroll leads into campaigns.

// List enrolled leads
const { leads } = await zend.campaigns.leads.list(campaign.id)

// Add leads
const { enrolled } = await zend.campaigns.leads.add(campaign.id, {
  leads: [
    { email: 'jane@acme.com', first_name: 'Jane', company: 'Acme' },
    { email: 'bob@globex.com', first_name: 'Bob', company: 'Globex' },
  ],
})

// Import leads (with duplicate handling)
const result = await zend.campaigns.leads.import(campaign.id, {
  leads: [
    { email: 'jane@acme.com', first_name: 'Jane', company: 'Acme' },
  ],
})
// { imported: 1, skipped: 0, errors: [] }

Analytics

Retrieve campaign and account performance metrics.

// Team-wide overview
const overview = await zend.analytics.overview()
// { sent: 1200, delivered: 1150, bounced: 12, replied: 89, ... }

// Per-campaign analytics
const campaignStats = await zend.analytics.campaign(campaign.id)

// Per-account health
const health = await zend.analytics.account('account-id')
// { health_score: 92, bounce_rate: 0.01, ... }

Webhooks

Subscribe to real-time events.

// List webhooks
const { webhooks } = await zend.webhooks.list()

// Create a webhook
const webhook = await zend.webhooks.create({
  url: 'https://yourapp.com/webhooks/zend',
  events: ['email.sent', 'email.bounced', 'email.replied'],
})

// Update a webhook
await zend.webhooks.update(webhook.id, {
  events: ['email.replied', 'lead.completed'],
})

// Delete a webhook
await zend.webhooks.delete(webhook.id)

Events

Query the event log.

const { events, pagination } = await zend.events.list({
  type: 'email.replied',
  limit: 50,
  offset: 0,
})

Suppressions

Manage the global suppression list.

// List suppressions
const { suppressions } = await zend.suppressions.list()

// Add a suppression
await zend.suppressions.create({ email: 'unsubscribed@example.com' })

// Check if suppressed
const { suppressed } = await zend.suppressions.check('user@example.com')

// Remove a suppression
await zend.suppressions.delete('unsubscribed@example.com')

API Keys

Manage API keys programmatically.

// List keys (masked)
const { keys } = await zend.keys.list()

// Create a new key
const { key, ...metadata } = await zend.keys.create({
  name: 'Production Key',
})
// key is only shown once: 'zk_live_...'

// Revoke a key
await zend.keys.delete('key-id')

Health

Check API availability.

const status = await zend.health.check()
// { status: 'ok', version: '1.0.0' }

Error handling

All API errors throw a ZendError with structured error information:

import { ZendClient, ZendError } from 'zend-sh'

const zend = new ZendClient({ apiKey: 'zk_live_...' })

try {
  await zend.campaigns.start('nonexistent-id')
} catch (error) {
  if (error instanceof ZendError) {
    console.error(error.type)    // 'not_found'
    console.error(error.message) // 'Campaign not found'
    console.error(error.status)  // 404
  }
}

TypeScript types

All request and response types are exported from the package:

import type {
  Account,
  CreateAccountInput,
  Campaign,
  CreateCampaignInput,
  Lead,
  EnrollLeadInput,
  Webhook,
  CreateWebhookInput,
  AnalyticsOverview,
  CampaignAnalytics,
  AccountHealth,
  Event,
  EventsQuery,
} from 'zend-sh'