REST Bearer keys · per-workspace webhooks · same resources as the app

The dashboard's engine,
exposed as an HTTP API.

Every resource you drive in the NuMail app — campaigns, leads, mailboxes, the unibox, A/B tests, workspaces — is a clean REST resource. Bearer auth with a nm_live_ key. HMAC-signed inbound webhooks for Gmail and Microsoft Graph. Honest about what's shipped, ambitious about the DX.

Get an API key →Resource reference
▸ Quickstart

One curl. First campaign.

Generate a key in Settings · API Keys, then talk to the same endpoints the app uses.

Authentication

Every request carries an Authorization: Bearer nm_live_••• header. Keys are minted per workspace from Settings · API Keys, and you can revoke and re-issue them at any time.

  • Auth scheme Bearer nm_live_•••
  • Scope Per workspace
  • Content type application/json
  • Webhook signing HMAC-SHA256
  • Inbound events Gmail · MS Graph
  • OAuth connect Google · Microsoft
# List your campaigns
curl https://api.numail.ai/campaigns \
  -H "Authorization: Bearer nm_live_•••"

# → {
#   "data": [
#     { "id": "cmp_3f9", "name": "Q2 outbound · cohort B",
#       "status": "active", "leads": 4820 }
#   ]
# }
# Create a campaign (sequence steps live inside it)
curl -X POST https://api.numail.ai/campaigns \
  -H "Authorization: Bearer nm_live_•••" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Q2 outbound · cohort B",
    "mailbox_ids": ["mbx_3a9","mbx_7c1"],
    "steps": [
      { "delay_days": 0, "subject": "Quick q on {{company}}", "body": "Hey {{first_name}}…" },
      { "delay_days": 3, "subject": "Re: {{company}}", "body": "Bumping this up…" }
    ]
  }'

# Then start it
curl -X POST https://api.numail.ai/campaigns/cmp_3f9/start \
  -H "Authorization: Bearer nm_live_•••"
# Import leads in a batch, then enroll one
curl -X POST https://api.numail.ai/leads/import/batch \
  -H "Authorization: Bearer nm_live_•••" \
  -H "Content-Type: application/json" \
  -d '{
    "rows": [
      { "email": "sarah@mercer-group.com", "first_name": "Sarah", "company": "Mercer Group" }
    ]
  }'

# Enroll a lead into a campaign
curl -X POST https://api.numail.ai/leads/lead_9a2/enroll \
  -H "Authorization: Bearer nm_live_•••" \
  -d '{ "campaign_id": "cmp_3f9" }'
# Pull positive threads, approve the AI draft
curl "https://api.numail.ai/threads?classification=positive" \
  -H "Authorization: Bearer nm_live_•••"

# Approve & send the draft NuMail already wrote
curl -X POST https://api.numail.ai/threads/thr_2c1/approve-draft \
  -H "Authorization: Bearer nm_live_•••"

# → { "thread_id": "thr_2c1", "sent": true,
#     "detected_in_ms": 2400 }
Honest

Today these endpoints are the same Next.js routes the dashboard calls, authenticated with your workspace key. We're hardening them into a stable, documented public surface — versioned paths under /v1, an OpenAPI spec, and official SDKs are on the roadmap below, not shipped yet. The shapes here are real; we'll keep them backwards-compatible as the public contract firms up.

▸ Resource reference

Six resources. One pattern.

List / get / create / update / delete, plus action sub-routes for the verbs that matter (/start, /approve-draft, /declare-winner). Sequences live inside campaigns — there's no separate sequences resource.

Campaigns sequences live here
GET/campaignsList with filters
POST/campaignsCreate (with steps)
GET/campaigns/:idGet one + stats
POST/campaigns/:id/startDraft → active
POST/campaigns/:id/pauseHalt sending
POST/campaigns/:id/resumeRe-arm the schedule
POST/campaigns/:id/archiveArchive (soft remove)
POST/campaigns/:id/duplicateClone steps + mailbox pool
GET/campaigns/:id/exportExport results (CSV)
GET/campaigns/:id/leadsLeads enrolled in this campaign
Leads import + enroll
GET/leadsList with filters
GET/leads/:idFull lead + activity
POST/leads/:id/enrollEnroll into a campaign
POST/leads/import/checkDry-run + dedupe preview
POST/leads/import/batchBulk import rows
Mailboxes Gmail · Graph · SMTP
GET/mailboxesList + health
GET/mailboxes/:idTier, schedule, reputation
POST/mailboxes/connect-smtpAdd an SMTP/IMAP mailbox
POST/mailboxes/test-connectionValidate credentials
POST/mailboxes/:id/test-sendFire a single test email
Unibox threads + AI drafts
GET/threadsList with classification filter
GET/threads/:idFull thread + AI draft
GET/threads/unread-countUnread badge count
GET/threads/draft-countPending AI drafts
POST/threads/:id/approve-draftApprove & send the AI draft
POST/threads/:id/replySend an arbitrary reply
POST/threads/:id/classifyRe-run / override classification
POST/threads/:id/snoozeSnooze for a timespan
POST/threads/:id/readMark read
POST/threads/:id/archiveArchive the thread
A/B tests declare a winner
GET/ab-testsList with status
GET/ab-tests/:idVariants + significance
POST/ab-tests/:id/declare-winnerPromote a variant
POST/ab-tests/:id/pausePause the test
POST/ab-tests/:id/resumeResume the test
Workspaces members + sub-billing
GET/workspacesList accessible workspaces
GET/workspaces/:idGet one + plan
GET/workspaces/:id/membersList members
POST/workspaces/:id/members/inviteInvite a member
POST/workspaces/:id/pause-allPause every campaign at once
Paths shown without a version prefix — a stable /v1 gateway and OpenAPI spec are on the roadmap.
▸ Auth & connect

Bearer keys. OAuth for inboxes.

Two distinct things: keys that authenticate your API calls, and OAuth flows that let NuMail send from real mailboxes.

API keys nm_live_

Mint a key in Settings · API Keys and pass it as a Bearer token. Keys are scoped to a single workspace — agencies issue one per client workspace.

  • Header Authorization: Bearer nm_live_•••
  • One key, one workspace — clean blast radius on rotation
  • Revoke & re-issue from the settings screen anytime
  • Separate nm_test_ prefix planned for sandbox keys

Mailbox OAuth Google · Microsoft

Connecting a sending inbox is a hosted OAuth handoff. Kick it off, send the user through, and the callback stores tokens against the workspace.

  • GET /auth/google — start the Gmail API consent flow
  • GET /auth/microsoft — start the Microsoft Graph flow
  • SMTP/IMAP inboxes skip OAuth via /mailboxes/connect-smtp
  • Tokens are per-workspace and refreshed automatically
▸ Inbound webhooks

Gmail & Graph. Signed, per workspace.

NuMail receives provider push notifications — Gmail and Microsoft Graph — at dedicated inbound endpoints. Each is verified with a per-workspace HMAC-SHA256 secret before the reply pipeline runs and fires the 2.4s draft.

Inbound endpoints

  • POST /webhooks/gmailGmail Pub/Sub push
  • POST /webhooks/graphMS Graph change notification

What a reply triggers

  • reply detected2.4s median, inbound parsed
  • classificationpositive · neutral · objection · OOO
  • ai_draft readyClaude writes in your voice
  • thread surfacedlands in the unibox to approve
reply pipeline · internal event shapeHMAC verified
# Inbound: Gmail Pub/Sub hits /webhooks/gmail
# NuMail verifies the per-workspace HMAC, then
# parses the reply and emits an internal event:
{
  "event": "reply.received",
  "workspace_id": "wks_anchor",
  "source": "gmail",
  "created_at": "2026-06-24T13:32:11.043Z",
  "data": {
    "thread_id": "thr_2c1",
    "campaign_id": "cmp_3f9",
    "lead_id": "lead_9a2",
    "classification": "positive",
    "detected_in_ms": 2400,
    "ai_draft": {
      "id": "drf_9a4",
      "body": "Hey Sarah — usually a week…"
    }
  }
}

# Signature header:
# X-NuMail-Signature: t=1750771931,v1=…
Note

The Gmail and Graph receivers are live and HMAC-verified today. Outbound webhooks — where NuMail pushes events like reply.received to your endpoint — are on the roadmap; for now, poll /threads or watch /threads/unread-count.

▸ Roadmap

Where the public surface is headed.

Straight about what's shipped versus what's coming. The resources above work now; the polish below is in flight.

Live

Resource endpoints

Campaigns, leads, mailboxes, unibox threads, A/B tests and workspaces — all callable now with a workspace key.

Live

Bearer key auth

Mint, scope and rotate nm_live_ keys from Settings · API Keys today.

Live

Inbound webhooks

Gmail Pub/Sub and Microsoft Graph receivers, HMAC-verified per workspace, powering 2.4s reply detection.

Building

Versioned /v1 gateway

A stable public path prefix with documented, backwards-compatible contracts and consistent error shapes.

Building

OpenAPI 3.1 + SDKs

A published spec at /v1/openapi.json and generated TypeScript & Python clients.

Planned

Outbound webhooks & MCP

Push events to your endpoints, plus an MCP server so AI agents can run campaigns conversationally.

Build on the
same engine.

Grab a workspace key from Settings · API Keys and start driving campaigns, leads and the unibox over HTTP.