Examples

Code Examples

Copy-paste examples in Python, JavaScript, and curl. Python examples use the multimail SDK (pip install multimail). JavaScript uses native fetch.

Authentication

All authenticated endpoints require a Bearer token in the Authorization header. Your API key starts with mm_live_.

from multimail import MultiMail

client = MultiMail(api_key="mm_live_YOUR_API_KEY")

# Verify authentication
account = client.get_account()
print(account["name"], account["plan"])
const API_KEY = "mm_live_YOUR_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 mm_live_YOUR_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

result = client.send_email(
    mailbox_id="MAILBOX_ID",
    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"
)

print(result["id"], result["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 mm_live_YOUR_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

emails = client.check_inbox(
    mailbox_id="MAILBOX_ID",
    status="unread",
    limit=10,
    direction="inbound"
)

for e in emails["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 mm_live_YOUR_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 = client.read_email(
    mailbox_id="MAILBOX_ID",
    email_id="EMAIL_ID"
)

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 mm_live_YOUR_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 = client.reply_email(
    mailbox_id="MAILBOX_ID",
    email_id="EMAIL_ID",
    markdown="Thanks for the update. I'll process this and follow up by EOD."
)

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 mm_live_YOUR_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 = client.list_pending()

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 mm_live_YOUR_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 = client.decide_email(
    email_id="EMAIL_ID",
    action="approve"
)
print(result["status"])  # "approved_and_sent" or "approved"

# Reject an email
result = client.decide_email(
    email_id="EMAIL_ID",
    action="reject"
)
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 mm_live_YOUR_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 mm_live_YOUR_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 = client.create_webhook(
    url="https://your-server.com/hooks/multimail",
    events=[
        "message.received",
        "message.delivered",
        "message.bounced",
        "oversight.pending"
    ]
)

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 mm_live_YOUR_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 = client.search_contacts(q="alice")

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 mm_live_YOUR_API_KEY"