# The rule

MachineMail’s `/v0` API is wire-compatible with [AgentMail](https://docs.agentmail.to/)’s. Code written against AgentMail’s API or SDKs works against MachineMail by changing the base URL and the API key. For the products rather than the API, see [MachineMail vs AgentMail](/content/compare/agentmail/index.html).

## The rule

Wherever AgentMail’s published API defines a path, an enum value or a field name, MachineMail uses exactly that. MachineMail-only features use their own names and never change the meaning of an AgentMail field.

In practice:

- JSON is snake_case: `organization_id`, `api_key_id`, `pod_id`, `inbox_id`, `thread_id`, `message_id`, `draft_id`, `webhook_id`, `domain_id`.
- `inbox_id` is the email address, as in AgentMail.
- Pagination is `limit` and `page_token`; responses carry `count`, `limit` and `next_page_token`.
- `client_id` on create is an idempotency key: the same `client_id` returns the existing resource.
- Enums match AgentMail: domain `status` (`NOT_STARTED`, `PENDING`, `INVALID`, `FAILED`, `VERIFYING`, `VERIFIED`), DNS record `status` (`MISSING`, `INVALID`, `VALID`) and `type` (`TXT`, `CNAME`, `MX`), inbox `status` (`active`, `paused`), draft `send_status` (`scheduled`, `sending`, `failed`), list `direction` (`send`, `receive`) and `type` (`allow`, `block`).
- API key permissions use AgentMail’s names (`inbox_read`, `message_send`, …) and its object-of-booleans format.

## Switching from AgentMail

1. Create an API key in the MachineMail dashboard (or let your agent onboard itself through `https://api.machinemail.dev/auth.md`).

2. Point your client at `https://api.machinemail.dev`. With AgentMail’s SDKs, set the base URL option to that value and the API key to your `mm_live_...` key.

3. Use addresses on `machinemail.dev`, or add your own domain with `POST /v0/domains`.

## Supported

| Area        | Endpoints                                                                                                       |
|-------------|-----------------------------------------------------------------------------------------------------------------|
| Inboxes     | list, create, get, update (including pause), delete, search                                                    |
| Messages    | list, get, send, reply, reply-all, forward, update labels, delete, raw, attachments, `batch-get`, `batch-update`, search |
| Threads     | list, get, update labels, delete, search; at `/v0/threads` and `/v0/inboxes/{inbox_id}/threads`               |
| Drafts      | list, create, get, update, delete, send; scheduled sends with `send_at`                                       |
| Domains     | list, create, get, update, delete, verify, `zone-file`                                                       |
| Webhooks    | list, create, get, update, delete                                                                               |
| Lists       | allow and block lists at `/v0/lists`, `/v0/pods/{pod_id}/lists` and `/v0/inboxes/{inbox_id}/lists`           |
| Pods        | list, create, get, update, delete                                                                               |
| API keys    | list, create, get, update, delete; organization, pod and inbox keys                                             |
| Organization | `GET /v0/organizations`                                                                                        |
| Metrics     | `/v0/metrics/events`, `/v0/metrics/usage`, `/v0/metrics/rates`                                               |
| Scoped routes| every resource under `/v0/pods/{pod_id}/...`; webhooks, lists, metrics, events and API keys under `/v0/inboxes/{inbox_id}/...` |

## Differences

| Topic                      | AgentMail               | MachineMail                                                                                                         |
|---------------------------|------------------------|-------------------------------------------------------------------------------------------------------------------|
| Error body                | AgentMail’s error shapes | One envelope on every `/v0` route: `{"error": {"type", "message", "param"?}}`. See [Errors](/content/docs/reference/errors/index.html). |
| Agent sign-up             | `/v0/agent/sign-up`, `/v0/agent/human`, `/v0/agent/verify` | The auth.md protocol: `POST /agent/identity`, `POST /agent/identity/claim`, `POST /oauth2/token`. See [Authentication](/content/docs/reference/authentication#agent-access-tokens/index.html). |
| Webhook signatures         | AgentMail’s own signing scheme | `X-MachineMail-Signature: t=...,v1=...` (HMAC-SHA256 over `<t>.<body>`) plus `X-MachineMail-Event`, `-Event-Id`, `-Delivery-Id`. See [Webhook events](/content/docs/reference/webhook-events#verifying-signatures/index.html). |
| Webhook body              | event payload          | Same keys at the top level, plus `type: "event"`, `event_id`, `event_type`, `timestamp`, and the payload again under `data`. |
| Creating keys             | body may carry `pod_id` / `inbox_id` | The route sets the scope: `POST /v0/pods/{pod_id}/api-keys`, `POST /v0/inboxes/{inbox_id}/api-keys`. `pod_id` and `inbox_id` in the body are ignored. |
| Status codes              | `200` on create (per AgentMail’s spec) | `201` on create and on sends, `200` when a `client_id` matches. Deletes return `{"ok": true}`. |
| Inbox events              | `GET /v0/inboxes/{inbox_id}/events` is a label-event log | The same path returns MachineMail’s event log narrowed to the inbox. |
| Labels                    |                        | System labels are uppercase: `INBOX`, `SENT`, `UNREAD`, `SPAM`, `BLOCKED`, `UNAUTHENTICATED`, `QUARANTINE`, `TRASH`. Other labels are free strings. |
| Recipients                | no published per-message cap | At most 50 recipients per message across `to`, `cc` and `bcc`, each address counted once; more is a `400` `validation` error. See [Limits](/content/docs/reference/limits#messages-and-attachments/index.html). |
| Authentication results     | `authentication_results` withholds SPF unless its domain aligns with the sender, and can report verdicts sealed by a trusted forwarder (`arc_sealer`) | Same field, values and domain keys, and the same withholding: SPF only when its domain aligns with the sender, DKIM and DMARC only when `From` names one domain. The verdicts are the ones recorded by the receiving provider or MachineMail’s receiving server. ARC results are not used, so `arc_sealer` is not sent. |
| Organization              | billing and limit fields | `domain_limit` is the plan’s custom-domain allowance. `inbox_limit`, billing and authentication fields are not returned. Inbox count is not a quota. |

## Not available

| AgentMail feature                                         | Status        |
|---------------------------------------------------------|---------------|
| Calendar (`/v0/inboxes/{inbox_id}/calendar/...`)       | Out of scope  |
| Apps and accounts (`/v0/apps`, `/v0/accounts`, `.../accounts`) | Out of scope  |
| Domain `setup-link`                                    | Not planned; MachineMail offers Domain Connect instead (`GET /v0/domains/{domain_id}/domain-connect`) |
| `POST /v0/inboxes/{inbox_id}/authorize`                 | Not yet       |
| Draft and thread attachment routes                       | Not yet; use the message attachment route |
| Open tracking (`track_opens`, `message.opened`)        | Not available; `track_opens` is ignored |
| Fields accepted but ignored                              | `forward_of` and `reply_all` on draft create, `quarantine_threshold` on inboxes, `subdomains_enabled`, `tracking_enabled` and `allow_conflicting_provider` on domains |

## MachineMail extensions

| Extension                          | Where                                                         |
|-----------------------------------|--------------------------------------------------------------|
| Trust reports                      | `trust` on every inbound message, `trust_level` on list items, `GET /v0/inboxes/{inbox_id}/messages/{message_id}/trust`. Verdicts `verified`, `known`, `unknown`, `suspicious`, `quarantined`, with SPF/DKIM/DMARC results, classifier scores for spam, phishing and prompt injection, link and attachment analysis, and an agent-safe `trust.content.text`. |
| Quarantine                         | Mail that looks like prompt injection or phishing gets the `QUARANTINE` label and the `message.received.quarantined` event, and is hidden from lists unless asked for. |
| Ephemeral inboxes                  | `ttl_seconds`, `ephemeral`, `expires_at` on inboxes; `inbox.created` and `inbox.expired` events. |
| Catch-all domains                  | `catch_all` and `catch_all_ttl_seconds` on domains: mail to an unknown address creates an inbox. Also `inbound_enabled`, `feedback_enabled`, `nameservers`, `dns_provider`, `dns_provider_url`. |
| Domain Connect                     | `GET /v0/domains/{domain_id}/domain-connect` returns a one-click DNS setup link where the DNS provider supports it. |
| Event log and streams              | `GET /v0/events` (with `after=<event_id>` cursors), `GET /v0/events/{event_id}`, server-sent events at `GET /v0/events/stream`, WebSocket at `/v0/ws`. |
| Delivery inspection and replay      | `GET /v0/webhooks/{webhook_id}/deliveries`, `POST .../deliveries/{delivery_id}/replay`, `POST /v0/webhooks/{webhook_id}/test`. |
| Webhook custom headers             | `headers` on `PATCH /v0/webhooks/{webhook_id}` replaces or clears the whole set (AgentMail’s `/headers` endpoints, also served, merge). The webhook object lists `header_names` and `headers_updated_at`; values are never returned. |
| Suppressions                       | `/v0/suppressions`: addresses that bounced, complained or were added by hand. |
| Export                             | `GET /v0/inboxes/{inbox_id}/export?format=mbox|jsonl`. |
| Extra event types                  | `message.received.quarantined`, `message.received.blocked`, `inbox.created`, `inbox.expired`, `draft.sent`, `webhook.test`. |
| Extra fields                       | `direction`, `delivery_status`, `received_via` and `pod_id` on messages; `organization_id` on inboxes, domains and keys. |
| Remote MCP server                  | `/mcp`, with agent-safe tools such as `wait_for_message`. See [MCP tools](/content/docs/reference/mcp-tools/index.html). |
| Agent onboarding                   | auth.md (`/auth.md`, `/agent/identity`, `/oauth2/token`), `/v0/agent-registrations`. |
| Raw injection                      | `POST /inbound/raw` with the `inbound_raw` permission, for testing with real MIME. |
| Lists                              | A `reply` list direction, and `entry_type` (`email` or `domain`) on entries.
