lettera mail
Real email for AI agents
An agent gets a persistent mailbox and a real lettera.dev address. It sends and receives mail, threads replies, keeps drafts for human approval, and fires webhooks when something changes. One API key, one base URL: https://api.lettera.dev.
Why a mailbox, not a webhook
An inbound webhook is a fire-and-forget push: the provider POSTs to your URL and forgets. If your service is down, restarting, or just slow at that instant, the message is gone — or worse, retried into a queue you have to drain. A persistent mailbox inverts the relationship. The mailbox is the source of truth: every message is stored until you ask for it, replies are threaded into the conversation they belong to, and a draft can sit for an hour or a week until a human approves it.
The webhook is still useful — it tells you the mailbox changed the moment it does, so you do not have to poll. But it is a notification, not the store. Lose a webhook and the mail is still there; lose the only copy in a webhook handler and it is not. Lettera gives you the mailbox first, and the webhook as an opt-in second channel.
The inbox object
One POST /v1/mail/inboxes provisions a real address. The returned object is the handle you pass to every other call. metadata is free-form JSON you own — tag it with a customer id, a routing key, whatever your agent needs.
{ "id": "ibx_8f3a1c2e7b9d4f0a6e1c2d3b4a5c6d7e", "address": "support@lettera.dev", "display_name": "Support", "metadata": {}, "created_at": "2026-08-26T12:00:00.000000Z"}List with GET /v1/mail/inboxes, update display name or metadata with PATCH /v1/mail/inboxes/{id}, soft-delete with DELETE.
Threading
Replies are grouped by References and In-Reply-To headers (RFC 5322), the way every mail client does it. A thread detail returns its messages in chronological order with quoted history stripped, so an agent reads the new content without re-reading the thread it already knows.
GET /v1/mail/threads/thr_3c1f... (Authorization: Bearer lm_sk_...)-> 200{ "id": "thr_3c1f...", "inbox_id": "ibx_8f3a...", "subject": "order #4821", "participants": ["support@lettera.dev", "jane@example.com"], "message_count": 3, "unread_count": 1, "last_message_at": "2026-08-26T12:14:02Z", "messages": [ { "id": "msg_...", "direction": "outbound", "from": "support@lettera.dev", "text": "your order shipped.", "created_at": "2026-08-26T12:00:00Z" }, { "id": "msg_...", "direction": "inbound", "from": "jane@example.com", "text": "thanks! when will it arrive?", "created_at": "2026-08-26T12:09:00Z" }, { "id": "msg_...", "direction": "outbound", "from": "support@lettera.dev", "text": "tomorrow by 6pm.", "created_at": "2026-08-26T12:14:02Z" } ]}Drafts and human approval
An agent writes a draft instead of sending; a human reviews it in the console and presses send. Sending a draft deletes it, so it can never be sent twice. This is the approval step for any mail where you want a human in the loop — refunds, outbound to customers, anything with consequences.
# agent writes a draft, does not sendPOST /v1/mail/inboxes/ibx_.../draftsAuthorization: Bearer lm_sk_...content-type: application/json{ "thread_id": "thr_3c1f...", "text": "refund of $12.50 issued — ok to send?" } # human reviews in the console and presses sendPOST /v1/mail/drafts/dft_.../sendAuthorization: Bearer lm_sk_...# -> 201 (draft deleted; double-send impossible)Webhooks
Register an HTTPS URL and the event types you want. Deliveries are Svix-signed; the signing secret is shown exactly once at creation. The mailbox is still the store — the webhook is the push.
POST /v1/mail/webhooksAuthorization: Bearer lm_sk_...content-type: application/json{ "url": "https://your-app.example/hooks/lettera", "event_types": ["message.received"] }-> 201{ "id": "wh_...", "url": "https://your-app.example/hooks/lettera", "event_types": ["message.received"], "secret": "lmwh_...", // shown once; verifies Svix-signed deliveries "enabled": true }MCP
Six tools at https://api.lettera.dev/mcp/mail: create_inbox, check_inbox, read_thread, send_email, reply_to_message, search_mail. Any MCP client connects with one config entry.
{ "mcpServers": { "lettera-mail": { "url": "https://api.lettera.dev/mcp/mail" } }}Access and limits
Free while in beta. Mail runs on a shared sending domain, so one abusive account degrades delivery for everyone — the abuse policy is short and enforced. Each org has a daily send cap; the count is surfaced in the usage view.
Continue to the Mail quickstart or the full Mail API reference. For agent-to-agent messaging, see Relay.