Public API v1
Available on Growth+ plans. Settings → API & webhooks shows your API key (created on demand; never displayed twice).
Base URL: https://api.defrost.email/v1
Authentication: Bearer token in the Authorization header.
Common endpoints
Campaigns
GET /v1/campaigns— list campaigns (paginated;?status=filter;?page=+?page_size=)POST /v1/campaigns— create a campaign with goal + ICP overrides + sequence (use?autolaunch=trueto immediately kick the pipeline)GET /v1/campaigns/:id— fetch campaign state including step status, ICP snapshot, and metrics
Contacts
GET /v1/contacts— list contacts (paginated;?page=+?page_size=)POST /v1/contacts— bulk upsert contacts (max 500 per request; requires GDPRlawful_basis; pre-filters against org-level suppressions)
Replies
GET /v1/replies— list replies (paginated;?classification=filter; body text transparently decrypted)
Webhooks
GET /v1/webhooks— list registered outbound webhooksPOST /v1/webhooks— register an outbound webhook (target_url,events[], optionaldescription)DELETE /v1/webhooks/:id— unregister an outbound webhook
Limited beta (contact support to enable)
POST /v1/leads/discover— kick off ad-hoc lead discovery for a campaign (currently returns501 Not Implemented; full implementation in v2.4)POST /v1/campaigns/:id/send— manually trigger send for a specific campaign (currently returns501 Not Implemented; full implementation in v2.4)
Planned for v2.4 — NOT yet shipped:
POST /v1/campaigns/:id/launch(use?autolaunch=trueon POST-create today),GET /v1/campaigns/:id/leads,POST /v1/leads/:id/replies,GET /v1/workspaces,POST /v1/workspaces/:id/icp.
Full reference (interactive Swagger UI): /docs/api
Rate limits
- Limits are aggregated per organization across all API keys belonging to the same org. Minting additional API keys does NOT multiply your plan's rate limit.
- Plan-tier ceilings (requests per minute, per org):
- Free: 60/min
- Starter: 1,000/min
- Growth: 5,000/min
- Scale: 10,000/min
- Enterprise: 30,000/min
Exceeded limits return 429 Too Many Requests with a Retry-After header.
Errors
JSON errors with shape { "error": { "code": "...", "message": "...", "details": {...} } }. Codes:
unauthorized— bad or missing API keyforbidden— key valid but no access to the resource (e.g., wrong workspace, missing scope)not_found— resource doesn't existvalidation_failed— invalid request body;detailslists which fieldsrate_limit— see Retry-After headernot_implemented— endpoint accepted but business logic deferred to v2.4internal— Defrost-side issue; safe to retry with backoff
Webhooks
Outbound webhooks fire on key events. Settings → API & webhooks → Add endpoint to register a URL.
Supported events
The following events are supported today and emit live deliveries:
lead.verified— email verification completed (whether passed or failed)send.bounced— recipient mailbox rejected an outgoing sendreply.received— inbound reply (raw, before classification)reply.classified— Haiku classifier finished labeling the replycampaign.completed— all sequence touches finished or campaign was paused
Coming soon (enum registered; dispatcher pending — do not subscribe yet):
meeting.booked— booking detected (no live fire-site today)
Planned for v2.4 — NOT yet shipped:
lead.discovered,email.sent,email.delivered,email.opened,email.clicked. These events do not currently emit deliveries.
Payload shape
Each event POSTs JSON: { "event": "lead.verified", "occurred_at": "...", "organization_id": "...", "data": { ... } }.
Signing
Webhooks are signed with HMAC-SHA256 over the request body. The signature is in the X-Defrost-Signature header (format: sha256=<hex>). Verify before trusting:
const expected = hmacSha256(yourSigningSecret, requestBody)
if (!constantTimeCompare(`sha256=${expected}`, headers['x-defrost-signature'])) reject()
Additional headers:
x-defrost-event— event typex-defrost-delivery-id— UUID that is stable across retry attempts for idempotent dedupx-defrost-timestamp— unix seconds (reject events older than ~5 min to defend against replay)
Retry policy
Defrost retries failed webhooks (non-2xx response or timeout) with exponential backoff: 1m, 5m, 30m, 2h, 12h. After 5 failed retries the endpoint is auto-disabled and you receive an email alert.
Use x-defrost-delivery-id to deduplicate — the header value is the same UUID across all retries of the same event.
What to read next
- Team management — granting API access via roles
- Troubleshooting — when integrations misbehave