api · v1 · stable

REST API. Versioned. Public. Documented.

Full CRUD on campaigns, leads, inboxes, analytics. OpenAPI 3.1 spec. Available on Surge+ tiers. Hand-curated docs — no auto-generated bloat.

base url · https://api.imail.now/v1 openapi · 3.1 auth · bearer token

Quick start

The imail API uses standard REST conventions: JSON bodies, predictable URLs, HTTP verbs that mean what you think they mean. Available on Surge and above.

1. Get an API key

Generate a key in Settings → API keys. Keys are scoped to a workspace. Rotate any time.

2. Make a request

# list active campaigns curl https://api.imail.now/v1/campaigns \ -H "Authorization: Bearer $IMAIL_API_KEY"

3. Parse the response

{ "data": [ { "id": "cmp_01HZ8K...", "name": "Q2 outbound — SaaS CTOs", "status": "active", "sent_today": 412, "reply_rate_7d": 0.048 } ], "pagination": { "next_cursor": "cur_xyz", "has_more": true } }

Authentication

All requests must include a bearer token in the Authorization header. Keys are scoped to a single workspace — to access multiple workspaces, generate one key per workspace.

Authorization: Bearer imk_live_01HZ8K7XQ9VFRSGT3W2YBNMPDLC

Test mode keys start with imk_test_ and operate against a separate ledger — useful for CI without burning real warmup quota.

Error handling

Errors use standard HTTP codes plus a structured body. We try to make the error message actionable, not just descriptive.

// 400 Bad Request { "error": { "code": "invalid_field", "message": "daily_limit must be between 1 and 5000 on Surge tier", "field": "daily_limit", "doc": "https://api.imail.now/docs/errors/invalid_field" }, "request_id": "req_01HZ8KABC..." }
StatusWhen
400Malformed request, validation failed
401Missing or invalid API key
403Key valid but workspace lacks the feature (tier gate)
404Resource doesn't exist or isn't yours
409Conflict (e.g. duplicate inbox connection)
429Rate limited — see Retry-After header
5xxOur fault. Includes request_id — send it to support and we'll dig.

Rate limits

Per API key. Token bucket. Burst-friendly.

TierSustainedBurst
Surge100 req/min240 req
Velocity500 req/min1,200 req
ApexNegotiatedNegotiated

Every response includes X-RateLimit-Remaining and X-RateLimit-Reset headers. On a 429, retry after the value in Retry-After (seconds).

Campaigns

A campaign is a multi-step sequence sent to a list of leads from one or more connected inboxes.

get/v1/campaignslist
get/v1/campaigns/{id}retrieve
post/v1/campaignscreate
patch/v1/campaigns/{id}update
post/v1/campaigns/{id}/pausepause
post/v1/campaigns/{id}/resumeresume
del/v1/campaigns/{id}delete (and archive)

Create a campaign

FieldTypeDescription
namestringrequiredDisplay name. Max 120 chars.
inbox_idsstring[]requiredConnected inboxes to send from.
stepsStep[]requiredSequence of up to 20 steps with conditional branches.
daily_limitintegerCap emails/day. Default: tier max.
send_windowSendWindowLocal timezone send hours. Default: 9–17 weekdays in lead's tz.
track_opensbooleanDefault: true.
track_clicksbooleanDefault: true.

Leads

Leads are the recipients in a campaign. Bring your own (CSV / Apollo / Hunter / scraping pipeline) — imail doesn't host a lead database.

get/v1/leadslist (paginated)
get/v1/leads/{id}retrieve
post/v1/leadscreate (single)
post/v1/leads/bulkcreate (up to 5000 per call)
patch/v1/leads/{id}update
del/v1/leads/{id}delete (GDPR — also adds to suppression)

Inboxes

Sending mailboxes connected via SMTP/IMAP. Adding an inbox returns a setup_url for OAuth providers.

get/v1/inboxeslist with health scores
get/v1/inboxes/{id}retrieve
post/v1/inboxesconnect new inbox
post/v1/inboxes/{id}/reconnectforce reconnect
post/v1/inboxes/{id}/warmup/startstart warmup
post/v1/inboxes/{id}/warmup/pausepause warmup

Analytics

Per-campaign, per-inbox, per-day. Returns raw counts; you compute rates. CSV export available via ?format=csv.

get/v1/analytics/campaigns/{id}campaign breakdown
get/v1/analytics/inboxes/{id}inbox performance
get/v1/analytics/workspaceworkspace-wide rollup
get/v1/analytics/funnelsent → opened → replied → interested → meeting

Public metrics

No auth required. Used to power the public metrics page. Cached 30s at the edge.

get/v1/metrics/publiclive platform stats · 30s cache
get/v1/status/fullcomponent health · 30s cache

Webhooks

Subscribe to real-time events. HMAC-signed (SHA-256) using your webhook secret. Retries on failure: exponential backoff up to 24h.

get/v1/webhookslist endpoints
post/v1/webhooksregister endpoint
del/v1/webhooks/{id}unregister

Event types

EventFires when
email.sentEmail successfully handed to SMTP
email.delivered250 OK from recipient ESP
email.openedTracking pixel hit
email.clickedTracked link clicked
email.bounced.hardHard bounce (auto-suppressed)
email.bounced.softSoft bounce with category
reply.receivedNew reply from a lead
reply.classifiediBrain finished classifying
warmup.threshold_pausedAuto-pause triggered on warmup
inbox.disconnectedIMAP/SMTP connection lost
inbox.reconnectedConnection restored

Verifying signatures

// node.js example const crypto = require("crypto"); const expected = crypto.createHmac("sha256", secret) .update(rawBody) .digest("hex"); if (crypto.timingSafeEqual( Buffer.from(expected), Buffer.from(req.headers["x-imail-signature"]) )) { // valid }

Versioning

Major versions in the path: /v1/.... Within a major version, we never break existing fields — only add new ones. Deprecations get a minimum 12-month sunset with email warnings starting at 6 months out.

Pinning to a specific minor: set the Imail-Version header to a date string, e.g. 2026-03-01. We'll route to that snapshot of the API.

API changelog

API-specific changes. Product changelog is at /changelog.

DateChange
2026-05-10Added email.bounced.soft and warmup.threshold_paused webhook events.
2026-04-22New endpoint POST /v1/leads/bulk (up to 5000 per call).
2026-03-10v1 stable. Public OpenAPI 3.1 spec at /openapi.json.