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_...| Scope | Allows |
|---|---|
| email:send | Send transactional email through the workspace sender setup. |
| campaigns:read | List campaigns and delivery stats. |
| audiences:read | List audiences and contact counts. |
| audiences:write | Create audiences and import contacts. |
| contacts:read | Read contact profiles and suppression status. |
| contacts:write | Create, update, suppress, or resubscribe contacts. |
| events:read | Read delivery, engagement, and reply events. |
| events:write | Record behavioural contact events, including conversion value. |
| templates:read | Read email templates. |
| templates:write | Create and update email templates. |
| webhooks:write | Create and manage outgoing webhook endpoints. |
| prospecting:read | Read prospecting targets, the prospect pool, drafts and sequence state. |
| prospecting:write | Create targets, approve or reject prospect drafts, and pause or resume the sequence. |
| analytics:read | Read workspace, deliverability and prospecting analytics and the sent-email log. |
| campaigns:write | Create, edit, duplicate and delete draft campaigns and their A/B variants. |
| campaigns:send | Launch, schedule, cancel and test-send campaigns. |
| workflows:read | Read automation workflows and their enrollments. |
| workflows:write | Create, edit, pause and delete workflows (as drafts). |
| workflows:send | Activate workflows, enroll contacts and fire workflow events — these email people. |
| inbox:read | Read reply threads, notes, the pipeline and follow-ups. |
| inbox:write | Update reply threads (status, tags, notes, pipeline stage) and schedule or cancel follow-ups. |
| forms:read | Read signup forms and subscription topics. |
| forms:write | Create, edit and delete signup forms and subscription topics. |
| sending:read | Read sending domains, their DNS health, sender addresses and connected mailboxes. |
| sending:write | Connect, verify and remove domains, and manage sender addresses and mailboxes. |
OpenAPI
GET /api/v1/openapi.jsonThe 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.jsonIdempotency
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.
| Subject | Default limit | Notes |
|---|---|---|
| Token | 120 requests / minute | Each bearer token has its own request window. |
| Workspace | 600 requests / minute | All API tokens in a workspace share this ceiling. |
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: 600Health check
GET /api/v1/meUse this endpoint to verify a token and identify the workspace it belongs to.
curl https://mailbase.studio/api/v1/me \
-H "Authorization: Bearer mb_live_..."{
"workspace": { "id": "...", "name": "Acme", "slug": "acme" },
"scopes": ["email:send", "campaigns:read"]
}Send transactional email
POST /api/v1/sendSends through the workspace's sending connection (Amazon SES by default) and default sender. Mailbase records the send for quota, analytics, and future webhook matching.
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.
| Field | Type | Required | Notes |
|---|---|---|---|
| to | string or string[] | Yes | Recipient email address or batch list. |
| subject | string | Yes | Email subject. |
| html | string | One of html/text | HTML body. |
| text | string | One of html/text | Plain-text body. |
| senderId | uuid | No | Optional configured sender; default sender is used otherwise. |
| tags | object | No | Forwarded to the sending provider when supported. |
| transactional | boolean | No | Set true for service email; marketing sends default to suppression enforcement. |
Campaigns
GET /api/v1/campaignsList campaigns in the token's workspace.
curl https://mailbase.studio/api/v1/campaigns \
-H "Authorization: Bearer mb_live_..."Audiences
GET · POST /api/v1/audiencesList audiences or create a new static audience with contacts.
curl https://mailbase.studio/api/v1/audiences \
-H "Authorization: Bearer mb_live_..."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.
| Method | Path and scope | What it does |
|---|---|---|
| GET | /prospecting/targetsprospecting:read | List targets with their progress. |
| POST | /prospecting/targetsprospecting:write | Create a target from an ICP spec (NAF codes, departments, headcount). Starts discovery; contacts nobody. |
| GET | /prospecting/countsprospecting:read | Pool by stage, drafts by status, rates, quota and the sequence state. |
| GET | /prospecting/companiesprospecting:read | The pool, one stage at a time (status, fit, target, limit, offset). |
| GET | /prospecting/companies/{id}prospecting:read | One company with every draft written for it. |
| GET | /prospecting/draftsprospecting:read | Drafts at one status; proposed is the review queue. |
| POST | /prospecting/drafts/{id}/approveprospecting:write | Approve a proposed draft, optionally with an edited subject and body. Queues it; does not send. |
| POST | /prospecting/drafts/{id}/rejectprospecting:write | Reject a proposed or approved draft, with an optional reason. |
| GET | /prospecting/sequenceprospecting:read | Sequence settings, today's send count and draft counts. |
| POST | /prospecting/sequence/pauseprospecting:write | Stop drafting and sending. |
| POST | /prospecting/sequence/resumeprospecting:write | Start 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.
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
}'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.
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.
| Event | Fires when |
|---|---|
| reply.received | An inbound reply was received and read. Carries intent (hot, warm, cold, objection, ooo) or null if it could not be classified. |
| reply.interested | The reply was read as hot or warm. Same payload as reply.received. |
| prospect.verified | A prospect company got a verified email address. Nothing has been sent to it yet. |
| prospect.draft_ready | A prospect email was written and awaits review. |
| prospect.draft_approved | A prospect email was approved and queued. |
| prospect.sent | A prospect email was sent. |
| meeting.booked | A meeting was booked. |
{
"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"
}