TypeScript SDK

Install and use @senderz/sdk — the official TypeScript client for the senderZ API.

The @senderz/sdk package is the official TypeScript client for the senderZ API. It wraps every REST endpoint in typed methods, handles authentication, retries failed requests, and verifies webhook signatures — so you write less boilerplate and ship faster.

Installation

npm install @senderz/sdk
pnpm add @senderz/sdk
yarn add @senderz/sdk

The SDK requires Node.js 18 or later and supports both ESM and CommonJS imports.

Quick Start

import { SenderZ } from '@senderz/sdk'

const client = new SenderZ({
  apiKey: process.env.SENDERZ_API_KEY!,
})

// Send a message
const message = await client.messages.send({
  to: '+15551234567',
  channel: 'auto',
  body: 'Hello from senderZ!',
})

console.log(message.id)     // "01JCNS789GHI"
console.log(message.status) // "queued"

Constructor Options

OptionTypeDefaultDescription
apiKeystringRequiredYour senderZ API key (sz_live_... or sz_test_...)
baseUrlstringhttps://api.senderz.comCustom API URL for self-hosted instances
timeoutnumber30000Request timeout in milliseconds
retriesnumber2Number of automatic retries on 5xx errors

Methods Overview

Messages

// Send a message
const msg = await client.messages.send({
  to: '+15551234567',
  channel: 'auto',       // 'auto' | 'imessage' | 'sms'
  body: 'Hello!',
})

// Send using a template
const otp = await client.messages.send({
  to: '+15551234567',
  channel: 'auto',
  template: 'otp_verify',
  data: { code: '483920' },
})

// Get message status
const status = await client.messages.get('01JCNS789GHI')

// List messages with filters
const recent = await client.messages.list({
  status: 'failed',
  since: '7days',
  limit: 50,
})

Templates

// Create a template
const tmpl = await client.templates.create({
  name: 'appointment_reminder',
  body: 'Hi {{name}}, your appointment is on {{date}} at {{time}}.',
  type: 'alert',
  channel: 'both',
})

// List templates
const templates = await client.templates.list({ type: 'marketing' })

Contacts

// Add a contact
const contact = await client.contacts.create({
  phone_number: '+15551234567',
  name: 'Jane Smith',
  group: 'VIP Clients',
})

// List contacts
const contacts = await client.contacts.list({
  search: 'Smith',
  limit: 25,
})

Webhooks

// Register a webhook
const hook = await client.webhooks.register({
  url: 'https://myapp.com/hooks/senderz',
  events: ['message.delivered', 'message.failed', 'message.received'],
})

// List webhooks
const hooks = await client.webhooks.list()

// Remove a webhook
await client.webhooks.remove('webhook_01ABC')

Compliance

// Log consent
await client.compliance.logConsent({
  phone_number: '+15551234567',
  consent_type: 'express_written',
  consent_source: 'web_form',
  ip_address: '203.0.113.42',
})

// Check opt-out status
const optOut = await client.compliance.checkOptOut('+15551234567')
console.log(optOut.opted_out) // true or false

// List opt-outs
const optOuts = await client.compliance.listOptOuts({ limit: 100 })

Billing

// Get current usage
const usage = await client.billing.usage()
console.log(usage.new_contacts.used_this_month) // 487
console.log(usage.new_contacts.limit_this_month) // 1250

Capabilities

// Check iMessage support (Growth and Scale plans)
const caps = await client.capabilities.check('+15551234567')
console.log(caps.imessage) // true

Pagination

List methods return paginated results. Use the page and limit parameters to navigate through pages.

// Page 1
const page1 = await client.messages.list({ limit: 25, page: 1 })

// Page 2
const page2 = await client.messages.list({ limit: 25, page: 2 })

// Check if more pages exist
if (page1.meta.total > page1.meta.page * page1.meta.limit) {
  // More pages available
}

Every list response includes a meta object with total, page, and limit fields so you can calculate pagination state.

Webhook Signature Verification

When senderZ sends a webhook to your server, it includes an X-Senderz-Signature header containing an HMAC-SHA256 signature. The SDK provides a built-in verification method:

import { SenderZ } from '@senderz/sdk'

const client = new SenderZ({ apiKey: process.env.SENDERZ_API_KEY! })

// In your webhook handler (Express example)
app.post('/hooks/senderz', (req, res) => {
  const signature = req.headers['x-senderz-signature'] as string
  const rawBody = req.body // raw string, not parsed JSON

  const isValid = client.webhooks.verify(rawBody, signature)

  if (!isValid) {
    return res.status(401).send('Invalid signature')
  }

  const event = JSON.parse(rawBody)
  // Process the event...
  res.status(200).send('OK')
})

Always verify webhook signatures before processing events. This prevents spoofed requests from triggering actions in your application.

Retry Handling

The SDK automatically retries requests that fail with 5xx server errors. By default, it retries up to 2 times with exponential backoff (1 second, then 2 seconds). You can customize this:

const client = new SenderZ({
  apiKey: process.env.SENDERZ_API_KEY!,
  retries: 3, // retry up to 3 times
})

The SDK does not retry 4xx client errors (bad request, unauthorized, not found) because these indicate a problem with your request that retrying will not fix.

Error Types

All API errors throw a SenderZError with a structured code field that you can switch on:

import { SenderZ, SenderZError } from '@senderz/sdk'

try {
  await client.messages.send({
    to: '+15551234567',
    channel: 'auto',
    body: 'Hello!',
  })
} catch (err) {
  if (err instanceof SenderZError) {
    switch (err.code) {
      case 'OPTED_OUT':
        console.log('Recipient has opted out')
        break
      case 'QUOTA_EXCEEDED':
        console.log('New contact limit reached')
        break
      case 'TRIAL_EXPIRED':
        console.log('Subscribe to a plan to continue')
        break
      case 'INVALID_API_KEY':
        console.log('Check your API key')
        break
      case 'MISSING_TEMPLATE_VAR':
        console.log(`Missing variable: ${err.message}`)
        break
      default:
        console.log(`API error: ${err.message}`)
    }
  }
}

The SenderZError object includes:

  • code — Machine-readable error code (e.g. OPTED_OUT, QUOTA_EXCEEDED)
  • message — Human-readable error description
  • status — HTTP status code (e.g. 400, 401, 429)