You're viewing the agent-readable version of this page. Switch to human view

MultiMail: Email for AI Agents

MultiMail gives you a real email address. Send and receive email as markdown, 15x fewer tokens than raw HTML email. Human oversight is handled for you.

OpenAPI spec: GET https://api.multimail.dev/v1/openapi.json for full machine-readable API details.

Base URL: https://api.multimail.dev

Auth: Authorization: Bearer mm_live_...

What this does for you

Verify before you communicate

Every outbound email from a MultiMail address includes a signed X-MultiMail-Identity header. The header contains a base64url-encoded JSON payload and an ECDSA P-256 signature, separated by a dot. To verify: decode both parts, fetch the public key from GET /.well-known/multimail-signing-key, and verify the signature using ECDSA with SHA-256. Identity is delivered exclusively via this signed header. No separate lookup endpoint is needed or available.

Reputation data is delivered separately via the X-MultiMail-Reputation header on every outbound email.

Getting started

1. Sign up

Web setup (recommended): After your account is approved, follow the setup link in your approval email. The guided flow walks you through account creation, activation, and client configuration.

API signup: Alternatively, create an account programmatically:

POST /v1/account
{
  "operator_name": "Greenline Studios",
  "slug": "greenline",
  "accepted_tos": true,
  "accepted_operator_agreement": true,
  "accepted_anti_spam_policy": true,
  "email_use_type": "transactional",
  "oversight_email": "[email protected]"
}

Response includes a default_mailbox address (e.g. [email protected]) and a pending status. Check your oversight email for an activation code, then confirm via POST /v1/confirm to activate and receive your API key (shown once). Manage your account at /dashboard.

Note: operator_name is published in the signed X-MultiMail-Identity header on every outbound email and visible to email recipients.

2. Upgrade (optional)

PlanPriceMailboxesEmails/moStorage
StarterFree2200100 MB
Builder$9/mo55,00010 GB
Pro$29/mo2530,00050 GB
Scale$99/mo100150,000150 GB

See full pricing with annual discounts and subscribe →

// Stripe (card) — supports monthly or annual billing
POST /v1/billing/checkout
{ "plan": "builder", "interval": "annual" }  // builder | pro | scale

// More payment options coming soon

Returns { "url": "https://..." }. Complete payment at that URL or pass it to your operator.

3. Send an email

POST /v1/mailboxes/{mailbox_id}/send
{
  "to": ["[email protected]"],
  "subject": "Weekly summary",
  "markdown": "## Completed\n\n- Task A\n- Task B\n\nAll items resolved."
}

Returns 200 if sent, 202 if held for operator approval (gated mode), or 403 if the mailbox is in read_only mode.

4. Read your inbox

GET /v1/mailboxes/{mailbox_id}/emails?status=unread

Returns emails as markdown. Each email includes thread_id, from, to, subject, and attachment metadata.

5. Reply in-thread

POST /v1/mailboxes/{mailbox_id}/reply/{email_id}
{
  "markdown": "Acknowledged. I'll follow up tomorrow."
}

Oversight modes

Each mailbox has an oversight mode set via the API or by an admin. Modes form a trust ladder: start restrictive, upgrade as you earn trust.

If you receive a 202, the email is queued. Do not retry. The oversight address will be notified.

Requesting an upgrade

If your mailbox is in a restrictive mode and you need more autonomy, request an upgrade:

POST /v1/mailboxes/{mailbox_id}/request-upgrade
{ "target_mode": "gated_all" }

This emails a one-time upgrade code to your operator. Ask your operator to share it with you, then:

POST /v1/mailboxes/{mailbox_id}/upgrade
{ "code": "A7X-29K" }

Codes expire after 24 hours and can only be used once. No code is needed for downgrades. Use PATCH /v1/mailboxes/:id to move to a more restrictive mode at any time.

Handling attachments

Webhooks

Configure webhooks on your mailbox to receive push notifications instead of polling. Two webhook types are available:

Set either via POST /v1/mailboxes or PATCH /v1/mailboxes/:id. Both must use HTTPS.

Webhook payload

All webhooks deliver a POST request with a JSON body:

{
  "event": "email.received",
  "timestamp": "2026-02-26T12:00:00.000Z",
  "data": {
    "email_id": "em_abc123",
    "from": "[email protected]",
    "to": ["[email protected]"],
    "subject": "Weekly report",
    "direction": "inbound",
    "has_attachments": false
  }
}

For email.pending_approval, the data object also includes an approval_url for one-click approve/reject.

Signature verification

Every webhook request includes an X-MultiMail-Signature header containing an HMAC-SHA256 signature of the raw request body. Verify it server-side to confirm the request came from MultiMail.

Retries and delivery history

Failed deliveries (non-2xx response) are retried up to 3 times with exponential backoff. View delivery history and debug failures via GET /v1/webhook-deliveries (requires admin scope).

If you don't use webhooks, poll GET /v1/mailboxes/:id/emails?status=unread instead.

MCP Server

If your framework supports the Model Context Protocol (MCP), use our MCP server instead of direct API calls. One config line gives you forty email tools.

Option A: Remote server (recommended)

No install required. Connect directly to our hosted MCP server at mcp.multimail.dev. Authenticates via OAuth in the browser — paste your API key once and you're connected. Works with Claude.ai, Claude Desktop, Claude Code, and any client that supports remote MCP.

{
  "mcpServers": {
    "multimail": {
      "type": "url",
      "url": "https://mcp.multimail.dev/mcp"
    }
  }
}

Option B: Local server (stdio)

Run the server locally via npm. API key is passed as an environment variable. Works with all MCP-compatible clients. Package: @multimail/mcp-server

{
  "mcpServers": {
    "multimail": {
      "command": "npx",
      "args": ["-y", "@multimail/mcp-server"],
      "env": {
        "MULTIMAIL_API_KEY": "mm_live_...",
        "MULTIMAIL_MAILBOX_ID": "01KJ1NHN8J..."
      }
    }
  }
}

Environment variables (local server only)

Tools

list_mailboxes: List all mailboxes available to this API key. Returns each mailbox's ID, email address, oversight mode, and display name. No arguments.

send_email: Send an email with a markdown body. Supports scheduled delivery and idempotency. Args: to (string[]), subject (string), markdown (string), cc (string[], optional), bcc (string[], optional), attachments (array of {name, content_base64, content_type}, optional), idempotency_key (string, optional), send_at (ISO 8601 UTC string ending in Z, optional — schedules delivery for a future time), gate_timing ("gate_first" or "schedule_first", optional — controls whether human approval happens before or after scheduling), mailbox_id (string, optional). Returns { id, status, thread_id } where status is "pending_scan" or "scheduled". For gated mailboxes, transitions to "pending_send_approval". Do not retry or resend. Use idempotency_key to prevent duplicate sends (24h TTL).

check_inbox: List email summaries with filtering. Args: status (unread/read/archived/deleted/pending_send_approval/pending_inbound_approval/rejected/cancelled/send_failed/scheduled, optional), sender (string, partial match, optional), subject_contains (string, optional), date_after / date_before (ISO datetime, optional), direction (inbound/outbound, optional), has_attachments (boolean, optional), since_id (string, for incremental polling, optional), limit (number, max 100, optional), cursor (string, pagination cursor, optional), mailbox_id (string, optional). Returns array of { id, from, to, subject, status, received_at, has_attachments, delivered_at, bounced_at, bounce_type }. Does NOT include the email body. Call read_email for full content.

read_email: Get full email content including markdown body, attachment metadata, delivery timestamps, and tags. Args: email_id (string), mailbox_id (string, optional). Automatically marks unread emails as read. Returns delivered_at, bounced_at, bounce_type, approved_at, approved_by, and tags.

reply_email: Reply to an email in its existing thread. Threading headers set automatically. Args: email_id (string), markdown (string), cc (string[], optional), bcc (string[], optional), attachments (array, optional), idempotency_key (string, optional), mailbox_id (string, optional). Returns { id, status, thread_id }. Same scanning and approval behavior as send_email.

download_attachment: Download an email attachment. Small files (<50KB) return inline base64. Larger files return a presigned download URL valid for 1 hour. Args: email_id (string), filename (string, from read_email attachment list), mailbox_id (string, optional).

get_thread: Get all emails in a conversation thread, ordered chronologically. Args: thread_id (string, from check_inbox or read_email), mailbox_id (string, optional). Returns participants, message_count, last_activity, has_unanswered_inbound, and the full email list.

cancel_message: Cancel a pending or scheduled email. Args: email_id (string), mailbox_id (string, optional). Works on emails with status pending_scan, pending_send_approval, pending_inbound_approval, or scheduled. Returns 409 if already sent. Idempotent on already-cancelled emails.

tag_email: Set, get, or delete key-value tags on emails. Tags persist across sessions. Args: email_id (string), action (set/get/delete), tags (Record<string, string>, for set), key (string, for delete), mailbox_id (string, optional). Use for priority flags, follow-up dates, extracted data, or any agent metadata.

add_contact: Add a contact to your address book. Args: name (string), email (string), tags (string[], optional). Build contacts organically from processed messages.

search_contacts: Search address book by name or email (partial match). Args: query (string, optional). Returns matching contacts with tags. Call with no query to list all.

update_mailbox: Update mailbox settings. All fields optional — only include what you want to change. Args: mailbox_id (string, optional), display_name (string, optional), oversight_mode (string, optional), auto_cc (string, optional), auto_bcc (string, optional), forward_inbound (boolean, optional), webhook_url (string, optional), oversight_webhook_url (string, optional), signature_block (string, optional).

update_account: Update account settings. Args: name (string, optional), oversight_email (string, optional), physical_address (string, optional). Requires admin scope.

delete_mailbox: Permanently delete a mailbox and all associated data. Args: mailbox_id (string). Requires admin scope. This action cannot be undone.

resend_confirmation: Resend the operator activation email with a new code. No arguments. Rate limited to 1 request per 5 minutes. Only works for unconfirmed accounts.

activate_account: Activate your account using the code from the confirmation email. Args: code (string, e.g. "SKP-7D2-4V8"). Accepts with or without dashes. Rate limited to 5 attempts per hour.

get_account: Get account status, plan, quota used/remaining, sending enabled, and enforcement tier. No arguments. Use for self-diagnosis when sends fail.

create_mailbox: Create a new mailbox. Requires admin scope and operator email approval. Returns 202 with an approval code sent to the oversight email; resubmit with the code to complete creation.

request_upgrade: Request an oversight mode upgrade. Args: mailbox_id (string, optional), target_mode (string). Sends upgrade request to operator. Requires admin scope.

apply_upgrade: Apply an upgrade code from operator. Args: mailbox_id (string, optional), code (string).

get_usage: Check quota and usage stats. Args: period (summary/daily, optional). Returns emails sent, received, storage used, plan limits.

list_pending: List emails awaiting oversight decision. No arguments. Requires oversight or oversight_read scope.

decide_email: Approve or reject a pending email. Args: email_id (string), action (approve/reject), reason (string, optional). Requires oversight scope.

delete_contact: Delete a contact. Args: contact_id (string).

check_suppression: List suppressed email addresses. Args: limit (number, optional), cursor (string, optional).

remove_suppression: Remove address from suppression list. Args: email_address (string).

list_api_keys: List all API keys with metadata. No arguments. Requires admin scope.

create_api_key: Create a new API key. Requires admin scope and operator email approval. Key value returned only once after approval code is provided.

revoke_api_key: Revoke an API key. Args: key_id (string). Requires admin scope. Cannot be undone.

get_audit_log: Get account audit log. Args: limit (number, optional), cursor (string, optional). Requires admin scope.

delete_account: Permanently delete account and all data. No arguments. Requires admin scope. Cannot be undone.

wait_for_email: Block until a new email arrives matching optional filters, or timeout. Args: mailbox_id (string, optional), timeout_seconds (number, 5–120, default 30), filter ({sender?, subject_contains?}, optional). Returns immediately when mail arrives.

create_webhook: Create a webhook subscription. Requires admin scope and operator email approval. Args: url (HTTPS string), events (string[]), mailbox_id (string, optional). Returns subscription with signing_secret after approval.

list_webhooks: List all webhook subscriptions for this account. No arguments.

delete_webhook: Delete a webhook subscription. Args: webhook_id (string).

configure_mailbox: Set up mailbox preferences on first run. Args: oversight_mode ("gated_all", "gated_send", "monitored", "autonomous", optional), display_name (string, optional), default_cc (string[], optional), default_bcc (string[], optional), scheduling_enabled (boolean, optional), default_gate_timing ("gate_first" or "schedule_first", optional), signature (string, optional), mailbox_id (string, optional). On first use, MultiMail nudges your agent to run this tool before proceeding.

schedule_email: Schedule an email for future delivery. Same as send_email but send_at is required. Args: to (string[]), subject (string), markdown (string), send_at (ISO 8601 UTC, required — must end with Z), cc (string[], optional), bcc (string[], optional), attachments (array, optional), gate_timing ("gate_first" or "schedule_first", optional), idempotency_key (string, optional), mailbox_id (string, optional). Returns { id, status, thread_id }. Use edit_scheduled_email to modify or cancel_message to cancel.

edit_scheduled_email: Edit a scheduled email before it sends. Args: email_id (string), send_at (ISO 8601 UTC, optional), to (string[], optional), cc (string[], optional), bcc (string[], optional), subject (string, optional), markdown (string, optional), mailbox_id (string, optional). Only works on emails with status "scheduled".

Error handling

All endpoints

Fetch GET /v1/openapi.json for full request/response schemas.

Authentication

Include your API key in every request:

Authorization: Bearer mm_live_...

API keys have scopes: read, send, admin, oversight, oversight_read. The oversight_read scope allows viewing pending emails without approve/reject permission. If a request returns 403, the key lacks the required scope.


Support: [email protected]

Lean 4 Verified

Your agent can send email.
No one receiving it can verify who's behind it.

Any API can deliver a message. None of them tell the recipient who built the agent, who's responsible for what it sends, or whether a human reviewed the output before it went out.

Get Started See Pricing

Cryptographically signed identity on every email

Every outbound email carries a signed X-MultiMail-Identity header: the operator, oversight mode, and verification status, signed with ECDSA P-256.

Every outbound email from a MultiMail address carries a cryptographically signed X-MultiMail-Identity header. The header contains a base64url-encoded JSON payload (operator name, oversight mode, capabilities, and verification status) plus an ECDSA P-256 signature. Recipients verify the signature against the public key at /.well-known/multimail-signing-key.

A separate X-MultiMail-Reputation header (an HMAC hash) links to reputation data with bounce rates, complaint rates, and account age. Updated daily, privacy-preserving, no raw addresses exposed.

The signature binding is formally verified in Lean 4 — we proved that changing any identity field breaks the signature, and that signatures are cryptographically bound to the operator's key.

X-MultiMail-Identity header
X-MultiMail-Identity: <payload>.<signature> Decoded payload: { "ai_generated": true, "operator": "Greenline Studios", "oversight": "monitored", "capabilities": ["receive", "send", "reply"], "verified_operator": true, "created": "2026-02-22", "service": "multimail", "iat": 1740500000 }

Three steps from signup to sending

Sign up, get an email address with signed identity on every email, and start sending. Use the web dashboard or go fully programmatic via API.

1

Create your account

Follow the setup link from your approval email, or POST to /v1/account with your operator details. Confirm via email to get your API key and a default mailbox like [email protected].

2

Send & receive as markdown

Outbound markdown becomes properly formatted HTML email. Inbound HTML is converted to clean markdown. Never touch raw MIME.

3

Oversight is built in

Every mailbox has configurable human oversight. Mirror copies, send-gating, or full approval flows. The oversight mode is published in the signed identity header on every outbound email.


A trust ladder for agent autonomy

Every mailbox has a configurable oversight mode. Start read-only, graduate through gated modes as you build trust, or let experienced agents run autonomously. Agents can request upgrades; you approve via a one-time code.

In gated modes, the approval flow is formally verified in Lean 4 — we proved that no email can reach delivery without passing through operator approval, for every possible path through the system.

read_only
Agent can receive and read email only. All sends blocked with upgrade instructions.
gated_all
Both inbound and outbound require human approval. Maximum control for sensitive use cases.
gated_send (default)
Outbound emails require human approval before delivery. Inbound delivered immediately.
monitored
Agent operates freely. All outbound emails BCC'd and inbound forwarded to your oversight address.
autonomous
Full send/receive without approval. For trusted, battle-tested agents.

Built for how agents work

Markdown-native, thread-aware, and designed for machine-speed operation.

Format

Markdown in, markdown out

Send markdown and it arrives as formatted HTML. Receive email and HTML is converted to clean markdown. A typical email goes from ~12,000 tokens to under 1,000. No MIME decoding, no HTML parsing.

Conversation

Threaded conversations

Automatic thread tracking via Message-ID and In-Reply-To headers. Follow and reply to email threads naturally.

Files

Attachments

Send and receive attachments. Files stored with zero egress fees. Download on demand, never inlined as base64.

Events

Webhooks & polling

Get notified via webhook when new email arrives, or poll the inbox. Webhook deliveries tracked with automatic retries on failure.

Performance

Globally fast

Distributed edge infrastructure. Fast API responses no matter where your agent runs.

Access

Scoped API keys

Granular permissions: read, send, admin, oversight, oversight_read. Give your agent send access. Keep oversight and admin scopes for humans. Agents can't approve their own emails.


Trust the identity. Trust that the message arrives.

Identity is meaningless if the email lands in spam. We take deliverability and sender reputation seriously.

Emails that arrive

Every outbound email is signed with DKIM. SPF records and DMARC policies are published for every tenant subdomain. Bounce handling and suppression lists maintained automatically. Emails land in inboxes, not spam.

Reputation you build

Each tenant subdomain builds its own sending reputation independently. MultiMail's platform-wide abuse prevention keeps the parent domain clean, giving new subdomains a head start. Your agent's behavior matters: bounce rates, complaint rates, and rejection rates are tracked per-mailbox daily. Abuse triggers automatic sending suspension.

CAN-SPAM compliant

Unsubscribe headers, physical address footers, and one-click opt-out built into every outbound email. Legally compliant by default.

EU AI Act Article 50 ready

Every AI-sent email carries a cryptographically signed provenance certificate disclosing AI involvement — the mechanism recommended by the EU Code of Practice. Machine-readable, tamper-evident, formally verified. Compliant before the August 2026 deadline. Learn more.

US state disclosure laws

Maine, New York, California, and Illinois already require AI chatbot disclosure. MultiMail's signed identity headers and body disclosure text provide compliance infrastructure across all state requirements. See coverage.

Insurable by design

As insurers retreat from AI agent coverage — Verisk exclusions in 82% of P&C templates — MultiMail provides the audit evidence underwriters need: oversight modes, signed provenance, gated human approval, and per-mailbox risk metrics. Learn more.

Standards aligned

NIST's agent identity framework, the EU Product Liability Directive, and Google's A2A protocol all converge on the same requirements: federated, cryptographic, domain-anchored agent identity. MultiMail's email authentication infrastructure already meets all four criteria. See the mapping.

Audit trail

Every email sent, received, approved, and rejected is logged. Full audit history available via API for compliance and debugging.

Always on

No single server to go down. Inbound email is queued even during maintenance. Never miss a message because of infrastructure.

Tenant isolation

Each account is fully isolated. Per-tenant subdomains with independent DKIM signing. One account's bounce rate can't affect another's deliverability.


One config line,
forty email tools

Skip the API integration. Connect to our hosted server or run locally — either way, one config line gets you email tools instantly.

Zero-code setup

Add the server to your MCP config. The tools handle authentication, error handling, and the pending-approval flow automatically. Just call send_email and check_inbox.

Variable Description
MULTIMAIL_API_KEY Your API key (mm_live_...) required
MULTIMAIL_MAILBOX_ID Default mailbox ID. Skip passing it on every call. optional
MULTIMAIL_API_URL Override base URL for local development optional
mcp config
{ "mcpServers": { "multimail": { "type": "url", "url": "https://mcp.multimail.dev/mcp" } } }
Send & Reply
Compose in markdown, deliver as HTML. Attachments, CC/BCC, scheduled send, idempotency keys.
send_email · reply_email · schedule_email
Inbox & Threads
Filter by sender, date, status, direction. Full thread view with participants. Real-time polling.
check_inbox · read_email · get_thread · wait_for_email
Oversight & Trust
Graduated autonomy from read-only to fully autonomous. Formally verified approval flow.
list_pending · decide_email · request_upgrade
Contacts & Tags
Address book with search. Key-value tags on emails for persistent agent memory.
add_contact · search_contacts · tag_email
Webhooks & Events
Real-time notifications for received, sent, bounced, and oversight events.
create_webhook · list_webhooks
Account & Billing
Manage mailboxes, API keys, domains, usage. Self-service plan upgrades.
get_account · create_mailbox · get_usage

40 tools total. See the full tool reference →


REST endpoints

Full OpenAPI spec at /v1/openapi.json

POST
/v1/account
Create tenant + get API key
GET
/v1/account
Tenant info, quota, plan limits
PATCH
/v1/account
Update tenant settings
DELETE
/v1/account
Delete account and all data
POST
/v1/mailboxes/:id/send
Send markdown email
GET
/v1/mailboxes/:id/emails
List inbox, filter by status
GET
/v1/mailboxes/:id/emails/:eid
Full email with body + attachments
POST
/v1/mailboxes/:id/emails/:eid/reply
Reply in-thread
POST
/v1/oversight/decide
Approve or reject gated emails
POST
/v1/mailboxes/:id/request-upgrade
Request oversight mode upgrade
GET
/.well-known/multimail-signing-key
Public key for verifying identity signatures
GET
/v1/usage
Billing period usage stats

Sending in 3 minutes

Create an account, pick your path, send your first email.