An email inbox for your AI agent
An agent that signs up for things needs an address that receives mail, and a way to get the code out of it without polling. Here is the whole flow in three steps.
Updated 3 min read
On this page (7)
Why agents need their own inbox
A browser agent that signs up for a service hits the same wall every time: “we sent you a code”. Using your personal inbox means giving the agent your mail, and parsing a shared inbox means guessing which message belongs to which run. An inbox per agent, or an address per run, keeps the agent's mail apart from yours and makes the right message easy to find.
Mailbay is built for this. Every workspace gets a private domain like k7m3qz.mailbay.email that works before you touch DNS, and one call waits for the email and hands back the code.
The flow
- Create an inbox (or make up an address on the Catch-all).
- The agent types that address into the sign up form.
- Call
wait. It returns when the email arrives, withcodesandlinksalready pulled out.
1. Get an API key
Sign in to the dashboard and create a key on the API keys page. Keys look like mb_live_… and are shown once. Put it in your environment:
export MAILBAY_API_KEY=mb_live_xxxxxxxxx2. Create an inbox
curl https://api.mailbay.dev/v1/inboxes \
-H "Authorization: Bearer $MAILBAY_API_KEY" \
-H "Content-Type: application/json" \
-d '{"local_part": "agent-signup"}'{
"id": "ibx_01m4x446p1x736eqmjgh4k7f34",
"address": "agent-signup@s8k6ed.mailbay.email",
"local_part": "agent-signup",
"domain": "s8k6ed.mailbay.email",
"catch_all": false,
"created_at": "2026-10-14T11:43:49.734211Z"
}The address receives mail immediately. Leave out local_part for a random one. To put the inbox on your own domain, add "domain": "acme.com" after verifying it (see Domains).
3. Wait for the email
After the agent submits the form, one request blocks until a message arrives, up to 120 seconds. Filter with from or subject (each matches part of the value) if other mail might land first.
curl "https://api.mailbay.dev/v1/inboxes/ibx_01m4x446p1x736eqmjgh4k7f34/wait?from=example.com&timeout=120" \
-H "Authorization: Bearer $MAILBAY_API_KEY"{
"message": {
"id": "msg_…",
"from": "no-reply@example.com",
"subject": "Your verification code",
"text": "Your code is 482913. Or confirm with https://example.com/verify?token=abc123",
"spam": false,
"auth_results": { "spf": "pass", "dkim": "pass", "dmarc": "pass", "spam_score": 0.4 }
},
"codes": ["482913"],
"links": ["https://example.com/verify?token=abc123"]
}codes holds standalone 4 to 8 digit numbers in order of appearance, without years from footers. links holds the https links in the message. If nothing arrives in time the answer is wait_timeout, and calling again is safe.
wait only matches mail received after the call starts. If the email might arrive before you start waiting, pass after with the inbox's created_at, or a time you noted before submitting the form.The whole thing in Python, with only the standard library:
import json, os, urllib.parse, urllib.request
API = "https://api.mailbay.dev"
KEY = os.environ["MAILBAY_API_KEY"]
def call(method, path, body=None):
req = urllib.request.Request(API + path, method=method,
data=json.dumps(body).encode() if body else None,
headers={"Authorization": f"Bearer {KEY}", "Content-Type": "application/json"})
with urllib.request.urlopen(req, timeout=130) as r:
return json.load(r)
inbox = call("POST", "/v1/inboxes", {"local_part": "agent-signup"})
print("sign up with", inbox["address"])
# ... the agent submits inbox["address"] to the sign up form here ...
q = urllib.parse.urlencode({"after": inbox["created_at"], "timeout": 120})
mail = call("GET", f"/v1/inboxes/{inbox['id']}/wait?{q}")
print("code:", mail["codes"][0] if mail["codes"] else None)
print("link:", mail["links"][0] if mail["links"] else None)One address per run
Agents that sign up often do not need an inbox each. Any address under your code that is not a named inbox lands in the Catch-all inbox, which Mailbay creates in your Playground project and which does not count against your inbox limit. Make up an address per run and wait for exactly that address with to:
ADDRESS="run-$(date +%s)@s8k6ed.mailbay.email"
# the agent signs up with $ADDRESS, then:
curl "https://api.mailbay.dev/v1/inboxes/$CATCH_ALL_ID/wait?to=$ADDRESS&timeout=120" \
-H "Authorization: Bearer $MAILBAY_API_KEY"Your code and full domain are in GET /v1/me as shared_domain, and the Catch-all appears in GET /v1/inboxes with "catch_all": true. The same filter works in the CLI: mailbay wait ibx_… --to run-42@s8k6ed.mailbay.email.
Limit what the agent can touch
Give the agent a key that reaches one inbox and nothing else. An inbox key can read, wait and reply in its inbox; listing other inboxes, creating inboxes or sending from a domain answers 403 insufficient_scope.
curl https://api.mailbay.dev/v1/keys \
-H "Authorization: Bearer $MAILBAY_API_KEY" \
-H "Content-Type: application/json" \
-d '{"name": "signup agent", "permissions": "inbox", "inbox_id": "ibx_01m4x446p1x736eqmjgh4k7f34"}'- Until your workspace has a verified domain, mail sent from
mailbay.emailaddresses can only reach your own team and the test addresses, so an agent cannot email strangers from a fresh account. - Received mail carries SPF, DKIM and DMARC results and a spam flag, so an agent can ignore mail that fails them.
- Prefer tools to code? The same flow is two MCP tool calls: see give an MCP agent its own email.
One paste per agent tool, from Claude Code to the OpenAI Agents SDK, is on Mailbay for AI agent builders.
Read next
- Give an MCP agent its own email addressMCP lets an agent use email the way it uses any other tool. Add one server to your client and the agent can create an inbox, send, reply and wait for a code.
- Giving AI agents an email address: design notesAn agent is not a person with a mail client. It cannot glance at an inbox or click around. These are the decisions we made so an agent can use email in as few steps as possible.
- Mailbay vs AgentMailBoth give agents their own inboxes over an API and MCP. AgentMail is further along; Mailbay adds sending for apps, a support inbox and custom domains on the free plan.
Join the beta
Mailbay is in private beta and free while the beta runs: inboxes, sending, your own domains and MCP. We invite people in small batches and read every note on the form.