letterport

How to give an AI agent its own email address

Guide · 23 October 2026

Create an inbox for the agent with one API call: letterport's POST /v1/inboxes returns a real address, such as research@letterport.dev, that receives mail at once. A webhook tells your agent when mail arrives; it reads the message as JSON and answers with /reply, which keeps the conversation in one thread on both sides.

What you need

A letterport account (the free plan needs no card) and an API key. In the console, under Integrations, create a key with the permissions the agent needs: read to read mail, send to send and reply, manage to create inboxes and webhooks. Limit it to one inbox when you can, and keep it in an environment variable, never in code.

1. Create the inbox

curl https://api.letterport.dev/v1/inboxes \
  -H "Authorization: Bearer $LETTERPORT_API_KEY" \
  --json '{"local_part":"research"}'

The answer is the inbox, receiving already:

{
  "id": "inb_01a15eb69aa6…",
  "address": "research@letterport.dev",
  "display_name": null,
  "status": "active"
}

Addresses are never reused: once deleted, a name is gone for good, so no one else receives your agent's mail.

2. Know when mail arrives

Register a webhook, and letterport POSTs to it the moment mail lands:

curl https://api.letterport.dev/v1/webhooks \
  -H "Authorization: Bearer $LETTERPORT_API_KEY" \
  --json '{"url":"https://your-app.example.com/letterport","event_types":["message.received"]}'

The answer includes a signing secret (whsec_…). Verify every request with the Standard Webhooks scheme, reject old timestamps, answer 2xx within 10 seconds, and dedupe on webhook-id: delivery is at least once, retried for about 24 hours. Payloads carry ids, not bodies.

No public URL? Poll instead: GET /v1/inboxes/{inboxId}/messages lists the newest first, and after (an ISO time) returns only newer mail.

3. Read the message

curl https://api.letterport.dev/v1/inboxes/$INBOX_ID/messages/$MESSAGE_ID \
  -H "Authorization: Bearer $LETTERPORT_API_KEY"

Read extracted_text: only what the sender just wrote, with the quoted history removed. text and html are the whole body, thread_id is the conversation, and each attachment downloads through a short-lived link from /messages/{messageId}/attachments/{attachmentId}. Mail is scanned for spam and viruses on arrival, and HTML is made safe.

Treat incoming mail as untrusted input. Anyone can email your agent, and an email can contain instructions meant to steer it: the agent should follow its user, not the email.

4. Reply in the same thread

const api = 'https://api.letterport.dev/v1';

const reply = await fetch(`${api}/inboxes/${inboxId}/messages/${messageId}/reply`, {
  method: 'POST',
  headers: {
    authorization: `Bearer ${process.env.LETTERPORT_API_KEY}`,
    'content-type': 'application/json',
    'idempotency-key': crypto.randomUUID(),
  },
  body: JSON.stringify({ text: 'Thanks Maya, confirming 40 units.' }),
}).then((response) => response.json());

// 202: reply.send_status is "queued"

The reply goes out from the inbox's own address with the headers that keep it in the conversation, for your agent and for the person reading it. reply_all: true answers everyone on the thread. Sending answers 202: queued, not yet sent. send_status moves to sent, and each recipient's deliveries entry to delivered, bounced or complained; a message.delivered webhook tells you when. Retry with the same Idempotency-Key: it never sends twice.

5. Start a new conversation

curl https://api.letterport.dev/v1/inboxes/$INBOX_ID/messages \
  -H "Authorization: Bearer $LETTERPORT_API_KEY" \
  -H "Idempotency-Key: $(uuidgen)" \
  --json '{"to":["maya@example.com"],"subject":"Your report","text":"It is ready."}'

cc, bcc, html and base64 attachments work the same way; /forward passes a message on with its attachments.

Rules and limits

Every error is {"error": {"code", "message", "hint"}}: act on the code, and read the hint.

Using Claude Code or another MCP client?

The same inboxes, permissions and limits are a hosted MCP server: see Give Claude Code an email inbox with MCP. The full contract is in the API reference.

Give your agent an address today.

Free, no card, and it receives mail the moment you create it.