Code Examples
Copy-paste examples in Python, JavaScript, and curl. Python examples call the REST API directly with httpx. JavaScript uses native fetch. For a richer agent surface, use the MCP server at mcp.multimail.dev.
Authentication
All authenticated endpoints require a Bearer token in the Authorization header. Your API key starts with mm_live_.
import httpx API_KEY = "$MULTIMAIL_API_KEY" BASE = "https://api.multimail.dev/v1" HEADERS = {"Authorization": f"Bearer {API_KEY}"} # Verify authentication account = httpx.get(f"{BASE}/account", headers=HEADERS).json() print(account["name"], account["plan"])
const API_KEY = "$MULTIMAIL_API_KEY"; const BASE = "https://api.multimail.dev/v1"; // Verify authentication const res = await fetch(`${BASE}/account`, { headers: { "Authorization": `Bearer ${API_KEY}` } }); const account = await res.json(); console.log(account.name, account.plan);
curl https://api.multimail.dev/v1/account \
-H "Authorization: Bearer $MULTIMAIL_API_KEY"Send an Email
Send markdown-formatted email through a mailbox. In gated modes, the email is held for operator approval.
POST /v1/mailboxes/{mailbox_id}/send
res = httpx.post( f"{BASE}/mailboxes/MAILBOX_ID/send", headers=HEADERS, json={ "to": ["[email protected]"], "subject": "Weekly report ready", "markdown": "Hi Alice,\n\nYour weekly report is attached.\n\n**Key metrics:**\n- Revenue: $42k\n- Growth: +12%", "cc": ["[email protected]"], "idempotency_key": "report-2026-w10" } ) email = res.json() print(email["id"], email["status"]) # "pending_scan" — queued for threat scan, then approval or delivery
const res = await fetch(`${BASE}/mailboxes/MAILBOX_ID/send`, { method: "POST", headers: { "Authorization": `Bearer ${API_KEY}`, "Content-Type": "application/json" }, body: JSON.stringify({ to: ["[email protected]"], subject: "Weekly report ready", markdown: "Hi Alice,\n\nYour weekly report is attached.\n\n**Key metrics:**\n- Revenue: $42k\n- Growth: +12%", cc: ["[email protected]"], idempotency_key: "report-2026-w10" }) }); const email = await res.json(); console.log(email.id, email.status);
curl -X POST https://api.multimail.dev/v1/mailboxes/MAILBOX_ID/send \ -H "Authorization: Bearer $MULTIMAIL_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "to": ["[email protected]"], "subject": "Weekly report ready", "markdown": "Hi Alice,\n\nYour weekly report is attached.\n\n**Key metrics:**\n- Revenue: $42k\n- Growth: +12%", "cc": ["[email protected]"], "idempotency_key": "report-2026-w10" }'
Check Inbox
List emails in a mailbox with optional filters for status, sender, date range, and direction.
GET /v1/mailboxes/{mailbox_id}/emails
res = httpx.get( f"{BASE}/mailboxes/MAILBOX_ID/emails", headers=HEADERS, params={"status": "unread", "limit": 10, "direction": "inbound"} ) for e in res.json()["emails"]: print(f"{e['from']}: {e['subject']}")
const params = new URLSearchParams({ status: "unread", limit: "10", direction: "inbound" }); const res = await fetch( `${BASE}/mailboxes/MAILBOX_ID/emails?${params}`, { headers: { "Authorization": `Bearer ${API_KEY}` } } ); const { emails } = await res.json(); emails.forEach(e => console.log(e.from, e.subject));
curl "https://api.multimail.dev/v1/mailboxes/MAILBOX_ID/emails?status=unread&limit=10&direction=inbound" \ -H "Authorization: Bearer $MULTIMAIL_API_KEY"
Read an Email
Fetch a single email with its full markdown body, attachments, and delivery status. Automatically marks unread emails as read.
GET /v1/mailboxes/{mailbox_id}/emails/{email_id}
email = httpx.get( f"{BASE}/mailboxes/MAILBOX_ID/emails/EMAIL_ID", headers=HEADERS ).json() print(email["from"]) print(email["subject"]) print(email["markdown"]) # Check attachments for att in email.get("attachments", []): print(f" {att['name']} ({att['size']} bytes)")
const res = await fetch( `${BASE}/mailboxes/MAILBOX_ID/emails/EMAIL_ID`, { headers: { "Authorization": `Bearer ${API_KEY}` } } ); const email = await res.json(); console.log(email.from, email.subject); console.log(email.markdown); // Check attachments email.attachments?.forEach(att => console.log(` ${att.name} (${att.size} bytes)`) );
curl https://api.multimail.dev/v1/mailboxes/MAILBOX_ID/emails/EMAIL_ID \
-H "Authorization: Bearer $MULTIMAIL_API_KEY"Reply to an Email
Reply to an existing email. Automatically sets the recipient, subject line (Re: ...), and thread ID.
POST /v1/mailboxes/{mailbox_id}/reply/{email_id}
reply = httpx.post( f"{BASE}/mailboxes/MAILBOX_ID/reply/EMAIL_ID", headers=HEADERS, json={"markdown": "Thanks for the update. I'll process this and follow up by EOD."} ).json() print(reply["id"], reply["status"], reply["thread_id"])
const res = await fetch( `${BASE}/mailboxes/MAILBOX_ID/reply/EMAIL_ID`, { method: "POST", headers: { "Authorization": `Bearer ${API_KEY}`, "Content-Type": "application/json" }, body: JSON.stringify({ markdown: "Thanks for the update. I'll process this and follow up by EOD." }) } ); const reply = await res.json(); console.log(reply.id, reply.status, reply.thread_id);
curl -X POST https://api.multimail.dev/v1/mailboxes/MAILBOX_ID/reply/EMAIL_ID \ -H "Authorization: Bearer $MULTIMAIL_API_KEY" \ -H "Content-Type: application/json" \ -d '{"markdown": "Thanks for the update. I'\''ll process this and follow up by EOD."}'
List Pending Approvals
Fetch all emails waiting for operator approval. Requires oversight or oversight_read scope.
GET /v1/oversight/pending
pending = httpx.get(f"{BASE}/oversight/pending", headers=HEADERS).json() for e in pending["emails"]: print(f"{e['direction']} | {e['from']} -> {e['to']} | {e['subject']}") print(f" Body: {e['body_markdown'][:100]}...")
const res = await fetch(`${BASE}/oversight/pending`, { headers: { "Authorization": `Bearer ${API_KEY}` } }); const { emails } = await res.json(); emails.forEach(e => { console.log(`${e.direction} | ${e.from} -> ${e.to} | ${e.subject}`); console.log(` Body: ${e.body_markdown?.slice(0, 100)}...`); });
curl https://api.multimail.dev/v1/oversight/pending \
-H "Authorization: Bearer $MULTIMAIL_API_KEY"Approve or Reject an Email
Decide on a pending email. Approved outbound emails are sent immediately. Requires oversight scope.
POST /v1/oversight/decide
# Approve an email result = httpx.post( f"{BASE}/oversight/decide", headers=HEADERS, json={"email_id": "EMAIL_ID", "action": "approve"} ).json() print(result["status"]) # "approved_and_sent" or "approved" # Reject an email result = httpx.post( f"{BASE}/oversight/decide", headers=HEADERS, json={"email_id": "EMAIL_ID", "action": "reject"} ).json() print(result["status"]) # "rejected"
// Approve an email const res = await fetch(`${BASE}/oversight/decide`, { method: "POST", headers: { "Authorization": `Bearer ${API_KEY}`, "Content-Type": "application/json" }, body: JSON.stringify({ email_id: "EMAIL_ID", action: "approve" }) }); const result = await res.json(); console.log(result.status); // "approved_and_sent"
# Approve curl -X POST https://api.multimail.dev/v1/oversight/decide \ -H "Authorization: Bearer $MULTIMAIL_API_KEY" \ -H "Content-Type: application/json" \ -d '{"email_id": "EMAIL_ID", "action": "approve"}' # Reject curl -X POST https://api.multimail.dev/v1/oversight/decide \ -H "Authorization: Bearer $MULTIMAIL_API_KEY" \ -H "Content-Type: application/json" \ -d '{"email_id": "EMAIL_ID", "action": "reject"}'
Set Up a Webhook
Subscribe to events like incoming emails, deliveries, and bounces. Webhook payloads are signed with a unique secret.
POST /v1/webhooks
webhook = httpx.post( f"{BASE}/webhooks", headers=HEADERS, json={ "url": "https://your-server.com/hooks/multimail", "events": [ "message.received", "message.delivered", "message.bounced", "oversight.pending" ] } ).json() print(f"Webhook ID: {webhook['id']}") print(f"Signing secret: {webhook['signing_secret']}") # Save the signing_secret to verify incoming webhook payloads
const res = await fetch(`${BASE}/webhooks`, { method: "POST", headers: { "Authorization": `Bearer ${API_KEY}`, "Content-Type": "application/json" }, body: JSON.stringify({ url: "https://your-server.com/hooks/multimail", events: [ "message.received", "message.delivered", "message.bounced", "oversight.pending" ] }) }); const webhook = await res.json(); console.log(`Webhook ID: ${webhook.id}`); console.log(`Signing secret: ${webhook.signing_secret}`);
curl -X POST https://api.multimail.dev/v1/webhooks \ -H "Authorization: Bearer $MULTIMAIL_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "url": "https://your-server.com/hooks/multimail", "events": [ "message.received", "message.delivered", "message.bounced", "oversight.pending" ] }'
Search Contacts
Search your contact list by name or email address. Returns matching contacts with tags.
GET /v1/contacts?q={query}
contacts = httpx.get( f"{BASE}/contacts", headers=HEADERS, params={"q": "alice"} ).json() for c in contacts["contacts"]: print(f"{c['name']} <{c['email']}> tags={c['tags']}")
const res = await fetch( `${BASE}/contacts?q=alice`, { headers: { "Authorization": `Bearer ${API_KEY}` } } ); const { contacts } = await res.json(); contacts.forEach(c => console.log(`${c.name} <${c.email}> tags=${c.tags}`) );
curl "https://api.multimail.dev/v1/contacts?q=alice" \ -H "Authorization: Bearer $MULTIMAIL_API_KEY"