Developer API

Mailbase REST API

A workspace-scoped API for transactional email, audience sync, campaign visibility, and operational checks. Tokens are generated in Settings → Developer API.

Authentication

Every request uses a bearer token. Tokens are shown once, stored hashed by Mailbase, can be created with an expiry, and can be revoked from the workspace settings screen.

Authorization: Bearer mb_live_...
ScopeAllows
email:sendSend transactional email through the workspace sender setup.
campaigns:readList campaigns and delivery stats.
audiences:readList audiences and contact counts.
audiences:writeCreate audiences and import contacts.
contacts:readRead contact profiles and suppression status.
contacts:writeCreate, update, suppress, or resubscribe contacts.
events:readRead delivery, engagement, and reply events.
events:writeRecord behavioural contact events, including conversion value.
templates:readRead email templates.
templates:writeCreate and update email templates.
webhooks:writeCreate and manage outgoing webhook endpoints.
prospecting:readRead prospecting targets, the prospect pool, drafts and sequence state.
prospecting:writeCreate targets, approve or reject prospect drafts, and pause or resume the sequence.
analytics:readRead workspace, deliverability and prospecting analytics and the sent-email log.
campaigns:writeCreate, edit, duplicate and delete draft campaigns and their A/B variants.
campaigns:sendLaunch, schedule, cancel and test-send campaigns.
workflows:readRead automation workflows and their enrollments.
workflows:writeCreate, edit, pause and delete workflows (as drafts).
workflows:sendActivate workflows, enroll contacts and fire workflow events — these email people.
inbox:readRead reply threads, notes, the pipeline and follow-ups.
inbox:writeUpdate reply threads (status, tags, notes, pipeline stage) and schedule or cancel follow-ups.
forms:readRead signup forms and subscription topics.
forms:writeCreate, edit and delete signup forms and subscription topics.
sending:readRead sending domains, their DNS health, sender addresses and connected mailboxes.
sending:writeConnect, verify and remove domains, and manage sender addresses and mailboxes.

OpenAPI

GET /api/v1/openapi.json

The current machine-readable API contract is available as OpenAPI 3.1. It is checked against the implemented /api/v1 routes in tests.

curl https://mailbase.studio/api/v1/openapi.json

Idempotency

Mutating API requests that send or create records accept an Idempotency-Key header. Reusing the same key with the same payload returns the original response; reusing it with a different payload returns a conflict.

Rate limits

Authenticated API requests are limited by both bearer token and workspace. Successful and limited responses include RateLimit-* plus token/workspace-specific headers so integrations can back off safely.

SubjectDefault limitNotes
Token120 requests / minuteEach bearer token has its own request window.
Workspace600 requests / minuteAll API tokens in a workspace share this ceiling.
Response
HTTP/1.1 429 Too Many Requests
Retry-After: 42
RateLimit-Limit: 120
RateLimit-Remaining: 0
RateLimit-Reset: 42
X-RateLimit-Token-Limit: 120
X-RateLimit-Workspace-Limit: 600

Health check

GET /api/v1/me

Use this endpoint to verify a token and identify the workspace it belongs to.

Request
curl https://mailbase.studio/api/v1/me \
  -H "Authorization: Bearer mb_live_..."
Response
{
  "workspace": { "id": "...", "name": "Acme", "slug": "acme" },
  "scopes": ["email:send", "campaigns:read"]
}

Send transactional email

POST /api/v1/send

Sends through the workspace's sending connection (Amazon SES by default) and default sender. Mailbase records the send for quota, analytics, and future webhook matching.

Request
curl https://mailbase.studio/api/v1/send \
  -H "Authorization: Bearer mb_live_..." \
  -H "Idempotency-Key: invoice-123" \
  -H "Content-Type: application/json" \
  -d '{
    "to": "customer@example.com",
    "subject": "Your invoice is ready",
    "html": "<p>Your invoice is ready.</p>",
    "text": "Your invoice is ready.",
    "transactional": true
  }'

For non-transactional sends, Mailbase adds one-click List-Unsubscribe headers and skips contacts already marked unsubscribed, bounced, complained, or suppressed. Use transactional: true only for service messages that do not require marketing unsubscribe handling.

Every message is screened for scams and phishing before it is sent. A message that is clearly abusive is refused with 422 and code blocked_scam. A message the screening is unsure about is held for review by our team: nothing is sent, and the response is 409 with code held_for_review. Retry the same request later (the Idempotency-Key stays reusable); it goes through once the review has cleared the message. If screening is temporarily unavailable for a workspace under review, the response is 503 with code screening_unavailable; retry in a few minutes.

FieldTypeRequiredNotes
tostring or string[]YesRecipient email address or batch list.
subjectstringYesEmail subject.
htmlstringOne of html/textHTML body.
textstringOne of html/textPlain-text body.
senderIduuidNoOptional configured sender; default sender is used otherwise.
tagsobjectNoForwarded to the sending provider when supported.
transactionalbooleanNoSet true for service email; marketing sends default to suppression enforcement.

Campaigns

GET /api/v1/campaigns

List campaigns in the token's workspace.

curl https://mailbase.studio/api/v1/campaigns \
  -H "Authorization: Bearer mb_live_..."

Audiences

GET · POST /api/v1/audiences

List audiences or create a new static audience with contacts.

List
curl https://mailbase.studio/api/v1/audiences \
  -H "Authorization: Bearer mb_live_..."
Create
curl https://mailbase.studio/api/v1/audiences \
  -H "Authorization: Bearer mb_live_..." \
  -H "Idempotency-Key: audience-launch-list-1" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Launch list",
    "contacts": [
      { "email": "marie@example.com", "firstName": "Marie" }
    ]
  }'

Prospecting

/api/v1/prospecting/*

The prospecting engine is available over the API: create targets, read the pool and the review queue, approve or reject drafts, and pause or resume the sequence. It uses the prospecting:read and prospecting:write scopes; neither is part of the default token. The same operations are MCP tools with the same scopes.

MethodPath and scopeWhat it does
GET/prospecting/targetsprospecting:readList targets with their progress.
POST/prospecting/targetsprospecting:writeCreate a target from an ICP spec (NAF codes, departments, headcount). Starts discovery; contacts nobody.
GET/prospecting/countsprospecting:readPool by stage, drafts by status, rates, quota and the sequence state.
GET/prospecting/companiesprospecting:readThe pool, one stage at a time (status, fit, target, limit, offset).
GET/prospecting/companies/{id}prospecting:readOne company with every draft written for it.
GET/prospecting/draftsprospecting:readDrafts at one status; proposed is the review queue.
POST/prospecting/drafts/{id}/approveprospecting:writeApprove a proposed draft, optionally with an edited subject and body. Queues it; does not send.
POST/prospecting/drafts/{id}/rejectprospecting:writeReject a proposed or approved draft, with an optional reason.
GET/prospecting/sequenceprospecting:readSequence settings, today's send count and draft counts.
POST/prospecting/sequence/pauseprospecting:writeStop drafting and sending.
POST/prospecting/sequence/resumeprospecting:writeStart again. Refused until a signature and a call to action are set.

The rules are the app's, not a second set: a draft can only be approved while it is proposed (otherwise 409), and approving only queues it. When the email actually leaves, the sequence still applies its sending window, its daily cap, the human review of the first batch and scam screening. Listing the pool is paginated with limit and offset; the response says whether has_more and gives next_offset.

Create a target
curl https://mailbase.studio/api/v1/prospecting/targets \
  -H "Authorization: Bearer mb_live_..." \
  -H "Idempotency-Key: electricians-71" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Électriciens Saône-et-Loire",
    "naf_codes": ["43.21A"],
    "departments": ["71"],
    "headcount_min": 1,
    "headcount_max": 9
  }'
Review and approve
curl "https://mailbase.studio/api/v1/prospecting/drafts?status=proposed&limit=20" \
  -H "Authorization: Bearer mb_live_..."

curl -X POST https://mailbase.studio/api/v1/prospecting/drafts/DRAFT_ID/approve \
  -H "Authorization: Bearer mb_live_..."

Outgoing webhooks

Configure signed event webhooks in Settings → Developer API. Mailbase sends JSON envelopes for email, reply, audience, and campaign events to each active endpoint.

Headers
Mailbase-Event: email.delivered
Mailbase-Delivery: 0f6f...
Mailbase-Timestamp: 1779624000
Mailbase-Signature: v1=<hex hmac sha256>

Verify the signature by computing HMAC-SHA256 over timestamp + "." + rawBody with the endpoint signing secret, then compare it with the v1= value from Mailbase-Signature.

Webhook events

Besides the email, audience and campaign events, the prospecting engine and the inbox emit the events below. Subscribe to them like any other event, from Settings or with the REST Hooks API (/api/hooks/subscribe). The full payload schemas are in the webhooks section of the OpenAPI document. Each fires once per underlying fact, even when the work that detects it runs twice.

EventFires when
reply.receivedAn inbound reply was received and read. Carries intent (hot, warm, cold, objection, ooo) or null if it could not be classified.
reply.interestedThe reply was read as hot or warm. Same payload as reply.received.
prospect.verifiedA prospect company got a verified email address. Nothing has been sent to it yet.
prospect.draft_readyA prospect email was written and awaits review.
prospect.draft_approvedA prospect email was approved and queued.
prospect.sentA prospect email was sent.
meeting.bookedA meeting was booked.
reply.interested
{
  "id": "0f6f...",
  "type": "reply.interested",
  "created_at": "2026-01-15T09:24:11.000Z",
  "workspace_id": "...",
  "data": {
    "thread_id": "...",
    "message_id": "...",
    "contact_id": "...",
    "email": "ada@example.com",
    "from_name": "Ada Lovelace",
    "subject": "Re: Une idée pour votre atelier",
    "preview": "Oui, pourquoi pas, appelez-moi jeudi.",
    "intent": "hot",
    "intent_label": "Hot lead",
    "prospect": {
      "company_id": "...",
      "siren": "123456789",
      "company_name": "Atelier Exemple",
      "domain": "atelier-exemple.fr",
      "role": "Gérante"
    },
    "occurred_at": "2026-01-15T09:24:11.000Z"
  }
}

prospect is null unless the conversation came from the prospecting engine. Message bodies are never sent, only a short preview.

Error format

Errors return JSON with a stable error string.

{
  "error": "Missing scope: email:send"
}