zend.shzend.sh
TypeScript SDK
Create a campaign, add leads, and start sending. The SDK handles mailbox rotation, scheduling, health monitoring, and reply detection.
import { ZendClient } from 'zend-sh'
const zend = new ZendClient({
apiKey: 'zk_live_...'
})
// Create campaign
const campaign = await zend.campaigns.create({
name: 'Q1 Outreach',
stop_on_reply: true,
})
// Add leads
await zend.campaigns.leads.add(campaign.id, {
leads: [
{ email: 'cto@acme.com', first_name: 'Sarah' },
{ email: 'vp@corp.io', first_name: 'Alex' },
]
})
// Start sending
await zend.campaigns.start(campaign.id)Interfaces
REST API for full control. SDKs for quick integration. CLI for your terminal. MCP server for AI agents. Dashboard for humans. All six expose the complete platform surface.
REST API
80+ endpoints covering accounts, campaigns, leads, analytics, webhooks, and warmup. Bearer auth. Sandbox mode.
TypeScript SDK
Full type definitions. Namespaced resources. Published to npm as zend-sh.
Python SDK
Sync and async clients. Pydantic v2 models. Published to PyPI as zend-sh.
CLI
Manage everything from your terminal. Pipe JSON output to jq. Script your workflows.
MCP Server
58 tools. Streamable HTTP transport. AI agents create campaigns, manage leads, and monitor deliverability conversationally.
Dashboard
For when you want a UI. Warmup status, account health, and campaign stats at a glance.
Endpoints
RESTful. Consistent error format. IETF rate-limit headers. Bearer auth. Sandbox mode via zk_test_* keys for integration testing without sending real emails.
GET /accounts # List mailboxes
POST /accounts # Connect mailbox
GET /accounts/:id/warmup # Warmup status
POST /campaigns # Create campaign
POST /campaigns/:id/start # Start sending
POST /campaigns/:id/leads # Add leads
GET /analytics # Team overview
GET /events # Event stream
POST /webhooks # Register webhook
GET /suppressions/check/:email # Check suppression
# View all 80+ endpoints in the docs → /docs/api-referenceCLI
List accounts, check warmup status, start campaigns, tail events — all from the command line. Pipe to jq for scripting.
# Check warmup progress
$ zend accounts warmup acct-1234
state: warming | day 14/28 | health 94
# List campaigns
$ zend campaigns list --json | jq '.[].name'
"Q1 Outreach"
"Follow-up Sequence"
# Start a campaign
$ zend campaigns start camp-5678
Campaign camp-5678 started.
# Stream events
$ zend events --type email.replied --limit 5
2026-03-28 sarah@acme.com → interested
2026-03-28 alex@corp.io → meeting_bookedBearer token auth. Production keys use the prefix zk_live_* and send real emails. Sandbox keys use zk_test_* and are safe for integration testing — requests go through the full pipeline but no emails are delivered. Keys are scoped to your team and can be rotated from the dashboard.
Yes. Use a zk_test_* API key instead of zk_live_*. All endpoints behave identically — campaign creation, lead ingestion, warmup status — but sends do not leave the system. This makes it safe to run integration tests and CI pipelines against the real API without worrying about live email delivery.