Skip to content
machinemail

What is MachineMail

MachineMail is an email API for AI agents. Every agent gets its own address, every inbound message carries a trust report, and the API is wire-compatible with AgentMail's /v0.

MachineMail gives an AI agent its own email address and a REST API to send, receive and reply. It also inspects every inbound message before your agent sees it, so a hostile email cannot quietly take over the agent that reads it.

It is a hosted service. The API lives at https://api.machinemail.dev, the dashboard at machinemail.dev, and the MCP server at https://mcp.machinemail.dev/mcp.

What you get

  • Inboxes on demand. Create an address on the shared machinemail.dev domain with one call, or on your own domain. Inbox count is not a billing quota. On the shared domain each organization can hold up to 1,000 addresses.
  • Ephemeral and catch-all inboxes. Give an inbox a ttl_seconds and it deletes itself, messages and all, when it expires. Turn on catch-all for a custom domain and any address on it works the moment mail arrives.
  • A trust report on every inbound message. Authentication results (SPF, DKIM, DMARC), what MachineMail knows about the sender, an agent-safe version of the body with quotes, signatures and hidden text removed, link and attachment checks, and classifier scores for phishing and prompt injection. Mail that tries to instruct your agent is quarantined. See Trust.
  • Threads, drafts and replies. Standard email threading, reply, reply-all, forward, drafts and scheduled sends.
  • Events three ways. Signed webhooks with retries and replay, a Server-Sent Events stream, and a WebSocket. Every event is also stored in a replayable log.
  • A CLI. machinemail (or mm) covers every endpoint from a terminal, with commands for agents such as wait --otp, and prints JSON when piped. See CLI.
  • MCP. A hosted Streamable HTTP MCP server with tools such as wait_for_message, so an agent can block until a verification code arrives. See MCP server.
  • Agent self-registration. An agent can sign itself up by reading /auth.md, get a sandbox inbox straight away, and later be claimed by a human. See auth.md.
  • AgentMail compatibility. MachineMail serves AgentMail’s /v0 paths, field names and enum values. The AgentMail SDKs work with a base URL change. See Switching from AgentMail.

How it fits an agent

An agent typically uses MachineMail in a loop:

  1. Get an address. Create an inbox for the agent, or one per task.
  2. Use it. Sign up for a service, email a person, or wait for someone to write in.
  3. Wait for mail. Receive a webhook, listen on the event stream, poll the messages list, or call the MCP wait_for_message tool.
  4. Check trust before acting. Read trust.level and trust.reasons, and hand the model trust.content.text instead of the raw body.
  5. Act and reply. Reply in the same thread, label the message, or ignore it.
The loop
create inbox ──► mail arrives ──► trust report ──► agent decides ──► reply in thread
                      │
                      ├─ webhook (signed POST)
                      ├─ SSE / WebSocket
                      └─ polling or MCP wait_for_message

Core objects

ObjectIDWhat it is
Organizationorg_...Your account. Owns everything below.
Podpod_...A partition inside an organization, for example one per end customer. Every organization has a default pod.
Inboxthe email addressAn address that can send and receive. inbox_id is the address itself, for example support-agent@machinemail.dev.
Threadthd_...A conversation, grouped by In-Reply-To and References.
Messagemsg_...One email, inbound or outbound. Inbound messages carry trust.
Draftdrf_...An unsent message, optionally scheduled with send_at.
Domaindom_...A custom domain with its DNS records and verification state.
Webhookwhk_...An HTTPS endpoint that receives signed events.
Eventevt_...One entry in the event log.
API keykey_...A bearer credential scoped to an organization, pod or inbox.

Read more in Organizations and pods, Inboxes and Threads and messages.

API basics

  • Authenticate with Authorization: Bearer <api key>. Keys look like mm_live_ followed by 32 characters.
  • Bodies and responses are JSON with snake_case fields. Timestamps are ISO 8601 in UTC.
  • Lists take limit (default 50, max 500) and page_token, and return count, limit and next_page_token.
  • client_id on create calls is an idempotency key: send the same one twice and you get the existing resource back with 200 instead of 201.
  • Errors look like {"error": {"type": "not_found", "message": "...", "param": "..."}}. Resources outside your key’s scope return 404, not 403.

Details are in the API reference.

Next