Claim your first agent mailbox
This is the happy path from zero to a two-way conversation: claim an inbox on inbox.ai, receive a message into a thread, read it, and reply. No domain to verify and no mail server to run.
1. Create an API key
In the dashboard, go to Developers → API keys and create a key — under the Email group, enable the mailbox and mailbox_management scopes. Keys look like bk_us1_... or bk_eu1_...; the region in the prefix picks the API host.
Codebeispiel
export BIRD_API_KEY="bk_us1_..."2. Claim a mailbox
Create a mailbox on the shared inbox.ai domain. Omit the local part and Bird mints a free, collision-free address; receive_policy: open accepts any authenticated mail so you can see the loop work.
curl
Codebeispiel
curl -X POST https://us1.platform.bird.com/v1/email/mailboxes \
-H "Authorization: Bearer $BIRD_API_KEY" \
-H "Content-Type: application/json" \
-d '{"display_name": "My Agent", "receive_policy": "open"}'TypeScript
Codebeispiel
import { BirdClient } from "@messagebird/sdk";
const bird = new BirdClient({ apiKey: process.env.BIRD_API_KEY! });
const mailbox = await bird.mailbox.create({
display_name: "My Agent",
receive_policy: "open",
});
console.log(mailbox.id, mailbox.address); // "mbx_…", "abc123@inbox.ai"The response carries the mailbox id and the address claimed for you. Send an email to that address from any mail client to give the next step something to read.
3. Read the thread
Inbound mail becomes a thread on the mailbox. List threads, then read the messages in the first one, asking for the extracted plain-text body.

curl
Codebeispiel
curl "https://us1.platform.bird.com/v1/email/threads?mailbox_id=<mailbox_id>" \
-H "Authorization: Bearer $BIRD_API_KEY"
curl "https://us1.platform.bird.com/v1/email/threads/<thread_id>/messages?include=extracted_text" \
-H "Authorization: Bearer $BIRD_API_KEY"TypeScript
Codebeispiel
for await (const thread of bird.mailboxThread.list()) {
for await (const msg of bird.mailboxThreadMessage.list(thread.id, {
include: "extracted_text",
})) {
console.log(msg.direction, msg.extracted_text);
}
}Each message carries its direction (inbound), its id (a received message is prefixed rem_), and the quote-stripped extracted_text — the new content, without the quoted history an agent would otherwise have to strip itself.
Rather than poll, subscribe to the email_mailbox.message_received webhook to be told the moment mail lands — see the events reference. Or hold open the mailbox's event stream: GET /v1/email/mailboxes/{id}/events pushes a notification the moment anything arrives.
4. Reply
Reply to the received message. The reply folds into the same thread and sends from your mailbox's address:
curl
Codebeispiel
curl -X POST https://us1.platform.bird.com/v1/email/threads/<thread_id>/messages/<message_id>/reply \
-H "Authorization: Bearer $BIRD_API_KEY" \
-H "Content-Type: application/json" \
-d '{"text": "Thanks — I am on it."}'TypeScript
Codebeispiel
await bird.mailboxThreadMessage.reply(threadId, messageId, {
text: "Thanks — I am on it.",
});That is the whole loop: claim, receive, read, reply. To start a conversation instead of answering one, compose a new message on the mailbox (POST /v1/email/mailboxes/{id}/messages), which opens a fresh thread.
Next steps
- Agent mailboxes — how threads, receive rules, sending, and retention work.
- MCP server — drive the same loop from an AI agent via the MCP server, no HTTP glue.
- CLI — bird email mailboxes and bird email threads for the terminal.
- SDK quickstarts — Go, Python, and TypeScript SDK walkthroughs.