Can an AI agent use AgentMail?
As of 14 Oct 2026, an AI agent gets into AgentMail on its own and does 100% of the core work.
- Find: Docs for agents: llms.txt, an OpenAPI and an MCP server; a docs page for each core task.
- Access: Key by API.
- Use: 100% of the work.
- Pay: Reaches the checkout: An agent payment on its API, none made yet.
- Leave: Nothing to cancel: Can't delete its account.
To reach L5 · Autonomous: pay without a person.
What the levels meanDriven 14 Oct 2026Same level in 6 drives in a rowRules of 15 Oct 2026Claim this page
Written and checked by our agents from this drive's record. How we write.
Who gets in
- Agents on a serverGet in on their own.
- Signed agentsThe site opens.
- Agents in a person's browserNot measured yet.
Sign-up page checked 12 Oct 2026. Signed agents: the ones Cloudflare verifies. Where agents come from
What an agent can do in AgentMail.
On its own
- Create its own email account and inbox with no setup help
- Send and receive email, including file attachments
- Reply to, forward, and organize email conversations into threads
3 more
- Write drafts and schedule emails to send later
- Search its mail and tag messages
- Do all of this through a chat-assistant connector or a command-line tool as well as the API
What it can't, and why
- Delete its account entirelythere is no delete option for the whole account, only for individual emails and keys
- Buy a paid plan on its ownthe purchase page is behind a security check it couldn't pass
- Pay per email with cryptocurrencythe price per email was higher than its spending limit
Can an AI agent sign up for AgentMail on its own?
Yes, over the API, without a browser. POST /v0/agent/sign-up with human_email and username returned an org, an inbox and an API key in one call.
Every way in it offers, as our agent tried them
| Way in | What happened |
|---|---|
| Pay per call | Not tried: over our payment cap |
| Sign‑up by API | Got in, 2 min |
| Sign in with AgentID | Not tried: the same as another way |
| Email and password | Stopped by a CAPTCHA |
| Sign‑in for apps (OAuth, MCP) | Stopped by a CAPTCHA |
| Company single sign‑on | Not tried: needs a person's account |
| A key from a person | Not tried: needs a person's account |
Does AgentMail have an MCP server, and can an agent connect to it?
Yes. AgentMail has an official MCP server.
A new agent can get in on its own: in the drive of 14 Oct 2026, our agent signed up, verified and got its key without a person. Through the MCP server, 13 of our agent's 15 attempts worked.
What the drive found
APIOpenAPIMCP · officialCLISDKllms.txtWebhooks–SandboxHow does an AI agent get an AgentMail API key?
In the drive of 14 Oct 2026, our agent got its AgentMail API key over the API, without a browser or a person. The API key comes in the sign-up response; a scoped key via POST /v0/api-keys worked once the verify had propagated (first try 403 with a clear 'wait up to 5 minutes' fix), was used and revoked.
Can an AI agent delete its AgentMail account?
Not on its own: blocked. No documented way to delete an organization (API, CLI, MCP or docs). We deleted every inbox, webhook and key headless; the last key's revoke made the next call 401, but the empty organization stays.
Can an AI agent pay for AgentMail?
Reaches the checkout: an agent payment on its API, none made yet.
Plan and price: Developer, $20 a month.
A visible CAPTCHA at checkoutOffers x402 payment- Stripe Projects on its own domain
- x402 on its own domain · Base, Solana, Avalanche, X Layer, Polygon
- MPP on its own domain · listed or named only
- Agentic Commerce Protocol on its own domain · listed or named only
No card needed to start.
What would let agents pay on their own
- Sell the plan or credits over the rail, not only side endpoints. Let the paid call buy what the product sells, so the rail covers the whole product.
- Let a verified agent finish your checkout. Show signed agents no visible CAPTCHA at checkout, accept virtual and prepaid cards, and don't ask for a phone number to pay.Step-by-step guide
AgentMail's own hosts offer agent-payable rails: x402 v2 on x402.api.agentmail.to (2 USDC/call, exact, Base/Avalanche/Polygon/Solana) and MPP on mpp.api.agentmail.to (tempo, charge). Both sell only inbox creation per call. We read the 402 and decoded it but paid nothing because 2 USDC is over our $1 cap, this is the most agentic route (agent_rail) and nothing blocked it except our own cap. Separately, buying the $20/month Developer plan is console-only: the upgrade URL redirects to accounts.console.agentmail.to/sign-in behind a Cloudflare interstitial that never cleared and that our agent-made org has no console user to get past; that is a product wall, not a person-solvable CAPTCHA, and is unrelated to the agentic rail's checkout fields.
Ways to pay checked 14 Oct 2026.
For the team behind AgentMail.
Where agents stop in AgentMail today, and the fixes that get them further, highest impact first.
The fixes, highest impact first
- Add an organization delete endpoint
- Let verified agents through the console checkStep-by-step guide
- Sell plans through a billing API
3 more fixes
- Give DCR clients the device grant Step-by-step guide
- Answer bad keys with a 401 body
- Serve the MCP server card at /server-card Step-by-step guide
- Claim it free and reply next to the result.
- A Drive, $49: your private report, with where agents stop, the evidence and the fixes that move your level.
- Fixed something? Order a Drive ($49) any time, or the Monthly drive ($29/month).
Details
Your API, MCP server or CLI is the product? An Audit ($299) also checks every documented route, MCP tool and CLI command against your docs. Compare plans.
Already claimed it? Open it in your dashboard.
Rather not be driven? Block AgentDrivesAgent in robots.txt or write to us. We stop driving it ourselves; this page stays, with its date.
Embed the badge on your site
Behind the level.
The part scores and the measures behind them.
Part scores and the measures · the docs · level history · paid plans
Part scores
- Holds up: 82 of 100, fair
Agent-ready setup
- llms.txt: found
- OpenAPI: found
- MCP server: found
- CLI: found
Not measured in this drive: Docs match (part of an Audit).
The measures
- Work done100
- Reliability71
- Crash test94
The docs
357 of 833 pages read. Complete.
- A getting-started page
- An auth page
- Errors listed with their codes
- Code examples on most pages
- Newest page updated 13 Oct 2026
- A page for 9 of 9 core tasks
Read on 14 Oct 2026.
Tried as documented
27 of 27 documented ways to do the core work worked when tried.
| What happened | Ways |
|---|---|
| Worked when tried | 27 |
| Documented, didn't work | 0 |
| Not tried (a paid plan, or no way to reach it) | 0 |
| Worked, but not in the docs | 0 |
Level history
- 1 Oct 20262 drivesL4Runs on its own
- 2 Oct 20262 drivesL4Runs on its own
- 3 Oct 2026L4Runs on its own
- 14 Oct 2026L4Runs on its own
Needs a paid plan
Not counted in the level. Our drive used free plan.
| Capability | Plan |
|---|---|
| Custom sending domain | Developer ($20/month) |
| Remove 'Sent via AgentMail' footer | Developer+ |
| /31/32 White-label, dedicated IPs, EU/BYO cloud | Enterprise |
| SOC 2 report | Startup ($200/month) |
| Team seats | Developer+ (2 seats) |
How AgentMail handles an agent's mistakes · 11 probes · core run 3×
Malformed requests, a retry, a wrong key and a short burst of reads on our agent's own account, and how AgentMail answered.
- Clear errors86
- Recovery92
- Safe retries100
- Rate limits100
- SilentPATCH webhook with unknown field add_event_typesCreate and manage webhook endpoints for email events200, webhook returned unchanged (unknown field silently ignored)
- SilentRepeat inbox create with same client_id, changed usernameCreate an email inbox for an agent200, returns the original adt-idem inbox; no error that the body differs
- VagueWrong API keyCreate an email inbox for an agent403 {"message":"Forbidden"} (API gateway; not 401, no fix/docs unlike other errors)
- ClearSend to a 4th distinct recipient in the first hour (free plan)Send an email from an inbox429 rate_limit_exceeded, Retry-After: 2806, application/json {name,code,message,fix,docs}: "sending ramp restarted ... at most 3 distinct recipients in its first hour (5 in its first 24 hours) ... lif
- ClearRepeat a send with the same Idempotency-KeySend an email from an inbox200 + 200, same message_id, one message stored; changed body -> 409 IdempotencyKeyConflictError with fix
- ClearSend without any recipientSend an email from an inbox400 validation_error, errors[].message "to, cc, or bcc must be specified", fix text
- ClearGET a well-formed inbox id that does not existCreate an email inbox for an agent404 not_found "Inbox not found" + fix naming id/scope/permissions
- ClearDraft with send_at "tomorrow"Schedule a draft to send at a future time400 validation_error invalid_format datetime (path send_at, regex shown)
- ClearBurst 15 quick GET /v0/inboxes?limit=1Receive incoming email into an inboxstatuses ['200', '200', '200', '200', '200', '200', '200', '200', '200', '200', '200', '200', '200', '200', '200']; no RateLimit/X-RateLimit headers
- ClearSend to two recipients, one on the block listSend an email from an inbox403 message_rejected naming the blocked recipient; the other recipient got nothing (search in adt-mcp-1: 0 hits): all-or-nothing, consistent
- ClearCall with a revoked keyCreate an email inbox for an agent401 unknown_api_key "Unknown or revoked API key" + fix + docs link (contrast: a made-up key gets 403 {"message":"Forbidden"})
For agents and builders.
The drive as data, every checkpoint and all 140 attempts.
How an agent connects · 7 tips
/api/tools/agentmail.json/tools/agentmail.mdMCP get_tool {"slug":"agentmail"}
- Follow llms.txt: POST /v0/agent/sign-up with a human_email you can read, then POST /v0/agent/verify with the emailed code.
- Wait ~5 minutes after verify before creating scoped keys; the 403 says so.
- On the free plan you can mail only 3 new recipients in the first hour; replies to people who wrote to you don't count.
- Use Idempotency-Key unquoted (A-Z a-z 0-9 -. _ ~) on sends, client_id on creates.
- MCP: send x-api-key to https://mcp.agentmail.to/mcp; the OAuth path hits a Cloudflare check.
- Polling webhooks need no public URL but events arrive with a delay; WebSockets are instant.
- Errors carry a fix field that names the next step: read it.
Every checkpoint, in detail · 9 checkpoints
- DocsHeadlessllms.txt opens with agent sign-up steps; OpenAPI 3.1.0 (113 paths) at docs.agentmail.to/openapi.json; every docs page as Markdown (.md, and Accept: text/markdown redirects to it).
- Sign upHeadlessPOST /v0/agent/sign-up with human_email and username returned an org, an inbox and an API key in one call.
- VerifyHeadlessThe 6-digit code reached the agent's inbox in seconds; POST /v0/agent/verify answered verified:true.
- KeyHeadlessThe API key comes in the sign-up response; a scoped key via POST /v0/api-keys worked once the verify had propagated (first try 403 with a clear 'wait up to 5 minutes' fix), was used and revoked.
- First callHeadlessGET /v0/inboxes 200 with the new inbox.
- First actionHeadlessPOST /v0/inboxes created a second inbox, read back with GET.
- PayNot triedAgentMail's own hosts offer agent-payable rails: x402 v2 on x402.api.agentmail.to (2 USDC/call, exact, Base/Avalanche/Polygon/Solana) and MPP on mpp.api.agentmail.to (tempo, charge). Both sell only inbox creation per call. We read the 402 and decoded it but paid nothing because 2 USDC is over our $1 cap, this is the most agentic route (agent_rail) and nothing blocked it except our own cap. Separately, buying the $20/month Developer plan is console-only: the upgrade URL redirects to accounts.console.agentmail.to/sign-in behind a Cloudflare interstitial that never cleared and that our agent-made org has no console user to get past; that is a product wall, not a person-solvable CAPTCHA, and is unrelated to the agentic rail's checkout fields.
- CancelNot neededNothing to cancel: our agent used the free plan.
- DeleteBlockedNo documented way to delete an organization (API, CLI, MCP or docs). We deleted every inbox, webhook and key headless; the last key's revoke made the next call 401, but the empty organization stays.
The attempt log · 140 attempts
| Capability | Route | Result | Evidence |
|---|---|---|---|
| Docs: llms.txt, robots.txt | none | done ✓ | https://www.agentmail.to/llms.txt 200 (27.5 KB, agent sign-up steps at top); robots.txt: User-Agent * Allow / Disallow /internal/, no Content-Usage/Content-signal lines |
| Docs: MCP server/discover 2026-07-28 | mcp | failed ✓ | POST https://mcp.agentmail.to/mcp server/discover -> 401 {"error":"Unauthorized"}, WWW-Authenticate: Bearer resource_metadata=https://mcp.agentmail.to/.well-known/oauth-protected-resource/mcp (retry with key later) |
| Docs: MCP server card / AI catalog / A2A card | none | partial ✓ | <mcp>/server-card 404; /.well-known/ai-catalog.json 404; /.well-known/mcp/server-card.json 200 application/json (older draft path, oauth2 via clerk.console.agentmail.to); agent-card.json 404; agent.json 404 |
| Docs: OAuth PRM + AS metadata | none | done ✓ | PRM at /.well-known/oauth-protected-resource/mcp 200; AS clerk.console.agentmail.to: registration_endpoint (DCR), device_authorization_endpoint, device_code grant; client_id_metadata_document_supported absent (no CIMD) |
| Docs: Markdown docs | none | done ✓ | docs.agentmail.to/welcome with Accept: text/markdown -> 303 to /welcome.md, Vary: Accept; /welcome.md 200 text/markdown |
| Docs: OpenAPI | api | done ✓ | https://docs.agentmail.to/openapi.json 200 application/json, openapi 3.1.0, 113 paths, servers api/x402.api/mpp.api/api.agentmail.eu |
| Docs: Find docs | none | done ✓ | docs.agentmail.to + llms.txt + OpenAPI; docs_pass.json verdict found getting started/auth/errors/examples |
| Sign up: POST /v0/agent/sign-up with human_email | api | done ✓ | 200 returned organization_id, inbox [redacted], api_key (am_us_••••) |
| Verify: Read OTP mail, POST /v0/agent/verify | api | done ✓ | OTP mail arrived in ~5 s from yes-reply@agentmail.to; verify 200 {"verified":true} |
| Key: API key from sign-up response | api | done ✓ | api_key returned in sign-up body; GET /v0/auth/me 200 credential_scope_type organization |
| First call: GET /v0/inboxes | api | done ✓ | 200 count 1, the sign-up inbox listed |
| Create inbox: POST /v0/inboxes username adt-cap01-a | api | done | 200 {"organization_id": "[redacted]", "pod_id": "[redacted]", "inbox_id": "adt-cap01-a@agentmail.to", "email": "adt-cap01-a@agentmail.to", "client_id": |
| Create inbox: GET /v0/inboxes/{id} | api | done ✓ | 200 email=adt-cap01-a@agentmail.to display_name=AgentDrives Test |
| Create inbox: PATCH display_name, read back | api | done ✓ | PATCH 200; GET display_name=AgentDrives Test Updated |
| First action: Create a second inbox via POST /v0/inboxes | api | done ✓ | adt-cap01-a@agentmail.to created 200 and read back via GET 200 |
| Send email: Send mail with attachment to the agent's inbox the agent's inbox | api | done ✓ | POST send 200 message_id+thread_id; GET message labels [sent, adtest]; mail arrived at the agent's inbox 05:17:30 (token [redacted]) |
| Attachments: Send note.txt as base64 attachment | api | done ✓ | send 200; GET message lists attachment note.txt size 62 |
| Attachments: GET attachment, download file and extracted text | api | done ✓ | GET attachment 200 with download_url + text_url (signed, expires 1h); both returned the exact file content (alpha-bravo-7731) |
| Receive email: Mail sent over SMTP from inbox A to inbox B, list inbox B messages | api | done ✓ | GET /v0/inboxes/adt-cap01-a/messages after 15 s: count 1, labels [received, unread], subject "Inbound test for ", SPF pass header (went via SES) |
| Create inbox: Receive mail in the new inbox | api | done ✓ | adt-cap01-a received the mail (see) |
| Reply: Reply from inbox B to the received message | api | done ✓ | POST reply 200 thread_id [id]; GET /v0/threads/[id] shows original + reply [sent]; sender inbox thread eea9db77 shows the reply [received] appended |
| Quote stripping / text extraction: Read received reply: text vs extracted_text | api | done ✓ | received reply text contains "On ... wrote: > Inbound body..." quoted history; extracted_text holds only the new reply body (plus signature footer); attachment text_url gave extracted file text |
| Reply: reply-all back to inbox B | api | done ✓ | POST reply-all 200; inbox B thread now has 3 messages |
| Forward: Forward the received message to the agent's inbox | api | done ✓ | POST forward 200; GET message to [the agent's inbox] labels [sent] subject "Fwd: Inbound test for "; arrived in the agent's inbox with fig-6060 and the original kiwi-5521 body |
| Threads: List threads of inbox B, get thread | api | done ✓ | GET threads 200 count 1; GET /v0/threads/[id] earlier returned messages grouped as one conversation (original, reply, reply-all, forward) |
| Threads: PATCH thread add/remove labels, read back | api | done ✓ | add -> labels ['received', 'unread', 'needs-followup', 'adtest', 'sent']; remove -> ['received', 'unread', 'adtest', 'sent'] |
| Labels: Add then remove a custom label on a thread | api | done ✓ | add -> ['received', 'unread', 'needs-followup', 'adtest', 'sent']; remove -> ['received', 'unread', 'adtest', 'sent'] |
| Labels: PATCH message: remove unread, add processed | api | done ✓ | PATCH 200; GET labels ['received', 'adtest', 'processed'] |
| Search: Search messages for "zebra" and threads for "kiwi" | api | done ✓ | messages/search?q=zebra 200 count 1 = the message; threads/search?q=kiwi 200 count 1 = the thread |
| Drafts: Create draft | api | done | 200 draft_id [id] |
| Drafts: GET draft | api | done ✓ | 200 text='Draft v1 lemon-1111' |
| Drafts: PATCH draft text, read back | api | done ✓ | PATCH 200; GET text='Draft v2 lemon-2222' |
| Drafts: Send draft, read back as message | api | done ✓ | POST drafts/send 200; GET message labels ['sent'] text "Draft v2 lemon-2222"; GET draft afterwards 404 (draft consumed by send) |
| Schedule: Create draft with send_at +3 min | api | done ✓ | 200 send_status scheduled, labels [draft, scheduled], send_at 2026-10-14T05:23:12Z |
| Drafts: Create + DELETE a draft, read back | api | done ✓ | DELETE 204; GET 404 |
| Schedule: PATCH send_at of a scheduled draft, read back | api | done ✓ | PATCH 200; GET send_at 2026-10-14T06:50:26Z status scheduled |
| Schedule: Cancel scheduled send by DELETE draft, read back | api | done ✓ | DELETE 204; GET 404 |
| Forward: DELETE the forwarded message, read back | api | done ✓ | DELETE 204; GET 404 |
| Reply: DELETE the reply message, read back | api | done ✓ | DELETE 204; GET 404 |
| Receive email: DELETE the received message, read back | api | done ✓ | DELETE 204; GET 404 |
| Threads: DELETE thread, read back | api | done ✓ | DELETE 202; GET 404 |
| Send email: DELETE the sent message (with attachment), read back | api | done ✓ | DELETE 204; GET 404 |
| Attachments: Delete message, check attachment gone | api | done ✓ | GET attachment after message delete -> 404 |
| Key: POST /v0/api-keys scoped read-only key (1st try, ~5 min after verify) | api | failed ✓ | 403 missing_permission; fix: "organization has not completed agent verification ... If you just verified, the credential's cached permissions can lag for up to 5 minutes: wait and retry." |
| Scoped API keys: Create read-only key (1st try) | api | failed ✓ | 403 missing_permission, cached permissions lag after verify (documented in the fix text) |
| Allow/block lists: Block send to our own address, try a send, unblock | api | done ✓ | POST lists/send/block 200; GET lists count 1; send to blocked address -> 403 message_rejected with fix naming the DELETE path; DELETE 204; GET count 0 |
| Webhooks: Create webhook, read back, PATCH event_types+enabled, read back | api | done ✓ | POST /v0/webhooks 200 (secret returned); GET url+events match; PATCH 200 -> events ['message.bounced', 'message.received', 'message.sent'] enabled False. Delivery not observed: we have no public receiver. |
| Schedule: Wait for the scheduled draft to send | api | done ✓ | send_at 05:23:12Z; draft gone (404) and message "AgentDrives scheduled test" in sent at 05:23:42Z; arrived in an inbox inbox: True |
| Drafts: Draft send delivered to the agent's inbox | api | done ✓ | lemon-2222 (draft v2 text) arrived at an inbox: True |
| WebSockets: TS SDK websockets.connect, subscribe inbox, send mail into it | sdk | done ✓ | WS frames: subscribed, then event (message.received) with subject "WS test " within seconds of the send |
| Webhooks: Polling webhook: create, read events with Svix AutoConfigConsumer | sdk | partial | POST /v0/webhooks/polling 200 with token; consumer.receive returned done:true, 0 events ~1 min after a message.received in the covered inbox (WS saw it) |
| Key: POST /v0/api-keys read-only key (retry ~8 min after verify) | api | done ✓ | 200 api_key_id c042f563…, permissions inbox_read+message_read only; GET /v0/api-keys/{id} 200 |
| Key: Use scoped key: list inboxes (allowed), create inbox (not allowed) | api | done ✓ | GET /v0/inboxes 200 count 2; POST /v0/inboxes 403 missing_permission naming inbox_create; used_at set on the key |
| Scoped API keys: Create read-only key, use it within and outside scope | api | done ✓ | create 200; GET key 200; read 200, create 403 missing_permission |
| Docs claim: Create an email inbox for an agent: create_inbox | mcp | done ✓ | tools/call create_inbox on https://mcp.agentmail.to/mcp (2026-07-28, x-api-key) -> {'inboxId': 'adt-mcp-1@agentmail.to'} |
| Docs claim: Send an email from an inbox: send_message | mcp | done ✓ | tools/call send_message on https://mcp.agentmail.to/mcp (2026-07-28, x-api-key) -> {'messageId': '<010001a138df08cf-[id]-000000@email.amazonses.com>', 'threadId': '76626cb |
| Docs claim: Receive incoming email into an inbox: list_messages | mcp | done ✓ | tools/call list_messages on https://mcp.agentmail.to/mcp (2026-07-28, x-api-key) -> {'count': 2, 'limit': 10, 'messages': [{'inboxId': 'adt-mcp-1@agentmail.to', 'threadId': 'e223f1d5-9b4d-4a22-8633-ac1c77 |
| Docs claim: Reply to a message (reply or reply-all) within its thread: reply_to_message | mcp | done ✓ | tools/call reply_to_message on https://mcp.agentmail.to/mcp (2026-07-28, x-api-key) -> {'messageId': '<010001a138df85a4-[id]-000000@email.amazonses.com>', 'threadId': 'e223f1d |
| Docs claim: Forward a message to new recipients: forward_message | mcp | done ✓ | tools/call forward_message on https://mcp.agentmail.to/mcp (2026-07-28, x-api-key) -> {'messageId': '<010001a138df8b16-[id]-000000@email.amazonses.com>', 'threadId': 'e223f1d |
| Docs claim: View and manage threaded conversations across an inbox: list_threads | mcp | done ✓ | tools/call list_threads on https://mcp.agentmail.to/mcp (2026-07-28, x-api-key) -> {'count': 1, 'limit': 10, 'threads': [{'inboxId': 'adt-mcp-1@agentmail.to', 'threadId': 'e223f1d5-9b4d-4a22-8633-ac1c770 |
| Docs claim: View and manage threaded conversations across an inbox: get_thread | mcp | done ✓ | tools/call get_thread on https://mcp.agentmail.to/mcp (2026-07-28, x-api-key) -> {'inboxId': 'adt-mcp-1@agentmail.to', 'threadId': '[id]', 'labels': ['received', 'unread |
| Docs claim: Send and download file attachments on messages: get_attachment | mcp | done ✓ | tools/call get_attachment on https://mcp.agentmail.to/mcp (2026-07-28, x-api-key) -> {'attachmentId': '[id]', 'filename': 'a.txt', 'size': 62, 'contentType': 'text/plain', ' |
| Docs claim: Create, edit and send a draft email: create_draft | mcp | done ✓ | tools/call create_draft on https://mcp.agentmail.to/mcp (2026-07-28, x-api-key) -> {'inboxId': 'adt-mcp-1@agentmail.to', 'draftId': '[id]', 'labels': ['draft'], 'to': ['dr |
| Docs claim: Create, edit and send a draft email: update_draft | mcp | done ✓ | tools/call update_draft on https://mcp.agentmail.to/mcp (2026-07-28, x-api-key) -> {'inboxId': 'adt-mcp-1@agentmail.to', 'draftId': '[id]', 'labels': ['draft'], 'to': ['dr |
| Docs claim: Create, edit and send a draft email: send_draft | mcp | done ✓ | tools/call send_draft on https://mcp.agentmail.to/mcp (2026-07-28, x-api-key) -> {'messageId': '<010001a138df9d2e-[id]-000000@email.amazonses.com>', 'threadId': '1fead67 |
| Docs claim: Schedule a draft to send at a future time: create_draft (sendAt) | mcp | done ✓ | tools/call create_draft (sendAt) on https://mcp.agentmail.to/mcp (2026-07-28, x-api-key) -> {'inboxId': 'adt-mcp-1@agentmail.to', 'draftId': '[id]', 'labels': ['draft', 'scheduled' |
| Docs claim: Create an email inbox for an agent: POST /v0/inboxes | api | done ✓ | create 200, GET read back |
| Docs claim: Send an email from an inbox: POST /v0/inboxes/{inbox_id}/messages/send | api | done ✓ | 200, delivered to an inbox |
| Docs claim: Receive incoming email into an inbox: GET /v0/inboxes/{inbox_id}/messages | api | done ✓ | lists received mail |
| Docs claim: Reply to a message (reply or reply-all) within its thread: POST .../reply and /reply-all | api | done ✓ | both 200, threaded |
| Docs claim: Forward a message to new recipients: POST .../forward | api | done ✓ | 200, delivered |
| Docs claim: View and manage threaded conversations across an inbox: GET /v0/inboxes/{inbox_id}/threads, GET /v0/threads/{thread_id} | api | done ✓ | both 200 |
| Docs claim: Send and download file attachments on messages: send attachments + GET attachment | api | done ✓ | download_url and text_url work |
| Docs claim: Create, edit and send a draft email: POST/PATCH drafts, POST drafts/send | api | done ✓ | all 200 |
| Docs claim: Schedule a draft to send at a future time: POST drafts send_at | api | done ✓ | scheduled, sent 30 s after send_at |
| Create inbox: DELETE inbox adt-cap01-a, read back | api | done ✓ | DELETE 202; GET 404 |
| Docs claim: Create an email inbox for an agent: agentmail inboxes create | cli | done ✓ | agentmail-cli 1.9.0 (npm), exit 0: {'created_at': '2026-10-14T05:26:06.665Z', 'display_name': 'AgentDrives CLI', 'email': 'adt-cli-1@ag |
| Docs claim: Send an email from an inbox: agentmail inboxes messages send --attachments | cli | done ✓ | agentmail-cli 1.9.0 (npm), exit 0: {'message_id': '<010001a138e01f88-[id]-000000@email.amazonses.com>', | map names "--attachment"; the real flag is --attachments <JSON_OBJECT> |
| Docs claim: Receive incoming email into an inbox: agentmail inboxes messages list | cli | done ✓ | agentmail-cli 1.9.0 (npm), exit 0: {'count': 6, 'messages': [{'attachments': [{'attachment_id': '[id]', |
| Docs claim: Reply to a message (reply or reply-all) within its thread: agentmail inboxes messages reply | cli | done ✓ | agentmail-cli 1.9.0 (npm), exit 0: {'message_id': '<010001a138e05279-[id]-000000@email.amazonses.com>', |
| Docs claim: Forward a message to new recipients: agentmail inboxes messages forward | cli | done ✓ | agentmail-cli 1.9.0 (npm), exit 0: {'message_id': '<010001a138e055c8-[id]-000000@email.amazonses.com>', |
| Docs claim: View and manage threaded conversations across an inbox: agentmail inboxes threads list | cli | done ✓ | agentmail-cli 1.9.0 (npm), exit 0: {'count': 2, 'threads': [{'attachments': [{'attachment_id': '[id]', |
| Docs claim: Send and download file attachments on messages: agentmail inboxes messages get-attachment | cli | done ✓ | agentmail-cli 1.9.0 (npm), exit 0: {'attachment_id': '[id]', 'content_disposition': 'attachment', 'cont |
| Docs claim: Create, edit and send a draft email: agentmail inboxes drafts create | cli | done ✓ | agentmail-cli 1.9.0 (npm), exit 0: {'created_at': '2026-10-14T05:26:29.563Z', 'draft_id': '[id]', 'inbo |
| Docs claim: Schedule a draft to send at a future time: agentmail inboxes drafts create --send-at | cli | done ✓ | agentmail-cli 1.9.0 (npm), exit 0: {'created_at': '2026-10-14T05:26:29.939Z', 'draft_id': '[id]', 'inbo |
| Docs claim: Send an email from an inbox: client.inboxes.messages.send (TypeScript SDK agentmail) | sdk | done ✓ | sent "WS test ", received in the target inbox |
| Create an email inbox for an agent: Repeat core task, fresh objects (trial 2) | api | done ✓ | create 200 GET 200; DELETE 202 GET 404 |
| Send an email from an inbox: Repeat core task, fresh objects (trial 2) | api | failed | send 429; GET labels None |
| Receive incoming email into an inbox: Repeat core task, fresh objects (trial 2) | api | failed | received after polling: False |
| Create, edit and send a draft email: Repeat core task, fresh objects (trial 2) | api | done ✓ | create 200 update 200 text v2 send 200 |
| Schedule a draft to send at a future time: Repeat core task, fresh objects (trial 2) | api | done ✓ | create 200 status scheduled send_at 2026-10-14T05:30:28Z (send checked later) |
| Create an email inbox for an agent: Repeat core task, fresh objects (trial 3) | api | done ✓ | create 200 GET 200; DELETE 202 GET 404 |
| Send an email from an inbox: Repeat core task, fresh objects (trial 3) | api | failed | send 429; GET labels None |
| Receive incoming email into an inbox: Repeat core task, fresh objects (trial 3) | api | failed | received after polling: False |
| Create, edit and send a draft email: Repeat core task, fresh objects (trial 3) | api | done ✓ | create 200 update 200 text v2 send 200 |
| Schedule a draft to send at a future time: Repeat core task, fresh objects (trial 3) | api | done ✓ | create 200 status scheduled send_at 2026-10-14T05:31:22Z (send checked later) |
| Reply to a message (reply or reply-all) within its thread: Repeat core task, fresh message (trial 2); sender is a fresh inbox, recipient an inbox already mailed (sending ramp) | api | done ✓ | reply 200; thread msgs 2 |
| Forward a message to new recipients: Repeat core task, fresh message (trial 2); sender is a fresh inbox, recipient an inbox already mailed (sending ramp) | api | done ✓ | forward 200; GET 200 to ['the agent's inbox'] |
| View and manage threaded conversations across an inbox: Repeat core task, fresh message (trial 2); sender is a fresh inbox, recipient an inbox already mailed (sending ramp) | api | done ✓ | thread get 200 msgs 3 |
| Send and download file attachments on messages: Repeat core task, fresh message (trial 2); sender is a fresh inbox, recipient an inbox already mailed (sending ramp) | api | done ✓ | attachment GET 200; download matches True |
| Reply to a message (reply or reply-all) within its thread: Repeat core task, fresh message (trial 3); sender is a fresh inbox, recipient an inbox already mailed (sending ramp) | api | done ✓ | reply 200; thread msgs 2 |
| Forward a message to new recipients: Repeat core task, fresh message (trial 3); sender is a fresh inbox, recipient an inbox already mailed (sending ramp) | api | done ✓ | forward 200; GET 200 to ['the agent's inbox'] |
| View and manage threaded conversations across an inbox: Repeat core task, fresh message (trial 3); sender is a fresh inbox, recipient an inbox already mailed (sending ramp) | api | done ✓ | thread get 200 msgs 3 |
| Send and download file attachments on messages: Repeat core task, fresh message (trial 3); sender is a fresh inbox, recipient an inbox already mailed (sending ramp) | api | done ✓ | attachment GET 200; download matches True |
| Pods: Create pod, inbox in pod, list pod inboxes, delete | api | done ✓ | POST /v0/pods 200; POST /v0/pods/{id}/inboxes 200; GET pod inboxes lists only adt-pod-inbox; DELETE inbox 202, DELETE pod 204, GET pod 404 |
| Metrics: GET metrics usage/events/rates | api | done ✓ | all 200; events shows message.sent count 26, message.received 13, message.delivered present, matching the drive's activity; rates bounce/complaint empty |
| Raw MIME: GET message raw, download .eml | api | done ✓ | GET raw 200 returns size 4961 + signed download_url (not inline MIME); .eml downloaded (4885 bytes) with headers ['From: AgentMail <adt-trial-4@agentmail.to>', 'Subject: trial 3 r', 'Message-ID: <010001a138e3e1fe-[id]-000000@email.amazonses.com>'] |
| Idempotency: Send twice with Idempotency-Key; create inbox twice with client_id | api | done ✓ | send x2 same Idempotency-Key -> both 200 with the same message_id, search shows one message; changed body with same key -> 409 conflict with fix. Inbox create x2 same client_id -> same inbox; a changed username with same client_id silently returned the original inbox (200). Quoted SF-string key form ("...") rejected 400 with clear character rule. |
| Custom domain: POST /v0/domains amtest.agentdrives.com | api | plan_gated ✓ | 403 limit_exceeded "Your plan's domain limit is 0 ... Developer raises it to 10 for $20.00/month", upgrade_url console.agentmail.to/dashboard/upgrade |
| App catalog: GET /v0/apps and /v0/apps/search | api | done ✓ | GET /v0/apps 200 count 5 with app_id, slug, name (Firecrawl first) and next_page_token; search q=firecrawl count 1; q=search count 0 |
| Create account at third-party app (AgentID): POST /v0/apps/{app_id}/connect | api | skipped | Not tested: connecting creates an account at another company's product (e.g. Firecrawl): outside this drive's scope (only account at AgentMail). Endpoint and MCP tool connect_app exist in OpenAPI / tools/list. |
| Public-key credentials: Register P-256 JWK via POST /v0/api-keys, read, delete | api | done ✓ | 200 type public_key with fingerprint; GET 200; DELETE 204; GET 404. No pending/active status field seen (map check mentions one); the AgentID sign-in with it was not exercised (third-party app). |
| IMAP/SMTP: Connect over IMAP with inbox id + API key, list messages | api | done ✓ | IMAP4_SSL imap.agentmail.to:993 login(adt-mcp-1@agentmail.to, API key) OK; select INBOX OK; 1 messages; last Subject: For MCP claims |
| IMAP/SMTP: Compare IMAP INBOX with the API list | api | partial ✓ | IMAP INBOX showed 1 message; GET messages?labels=received lists 5 for the same inbox (4 arrived after the first one, minutes before). Docs say a missing permission stops updates; our key is unrestricted. |
| Team seats: Check against docs/pricing | none | plan_gated | pricing: Free "Team Members" listed; Developer 2 organization seats, Startup 10; console-only, no API route in OpenAPI |
| Remove footer: Check against docs/pricing | none | plan_gated | pricing table row "Sent via AgentMail" footer (free plan carries it: our sent mail had "--\nSent via AgentMail"); removal on paid plans |
| White-label: Check against docs/pricing | none | plan_gated | llms.txt + pricing: "White-label platform" in Enterprise (custom pricing, contact) |
| SSO: Check against docs/pricing | none | skipped | pricing: "Social SSO" on all plans; llms.txt: OIDC/SAML SSO on Enterprise; console settings only, not tried (console sign-in not used on this drive) |
| SOC 2 report: Check against docs/pricing | none | plan_gated | docs page soc-2-compliance.md: 2025 SOC 2 Type II completed, 2026 audit with A-LIGN; report on Startup ($200/mo) |
| Dedicated IPs: Check against docs/pricing | none | plan_gated | pricing: "Dedicated IPs: Contact us" (Enterprise) |
| EU / BYO cloud: Check against docs/pricing | none | plan_gated | llms.txt + pricing: EU region cloud, BYO cloud on Enterprise; OpenAPI lists server https://api.agentmail.eu (eu-prod) |
| Agent sign-up + human OTP verify: POST /v0/agent/sign-up, OTP mail, POST /v0/agent/verify | api | done ✓ | sign-up 200 (unverified org, send limited to the human email); OTP arrived in seconds; verify 200 verified:true; sends to other recipients then worked (after which the 3-recipient first-hour ramp applies) |
| Webhooks: Polling webhook: receive again ~10 min later | sdk | done ✓ | Svix AutoConfigConsumer.receive returned 6 events (message.sent x5, message.received "Re: For MCP claims"), committed; first receive minutes earlier had returned 0 (events queue with delay) |
| Sign up: x402/MPP pay-per-call inbox create without account | api | skipped | pay_tx.json: x402 v2 402 on https://x402.api.agentmail.to/v0/inboxes asks 2 USDC (exact, eip155:8453), over our $1 per-payment cap, refused by us, nothing paid |
| Sign up: Sign in with AgentID at AgentMail | none | skipped | AgentID is AgentMail's product for agents signing in to OTHER apps; the console sign-up shows only Google and email/password, no AgentID button. Not a way into AgentMail itself. |
| Sign up: Console sign-up with email+password (the agent's inbox) | browser | blocked ✓ | https://console.agentmail.to/sign-up: after Continue the form is replaced by a Cloudflare Turnstile "Verify you are human" widget (Clerk bot protection). Not solved, not retried. |
| Sign up: Stripe Projects | none | skipped | Listed in the Stripe Projects catalog (door_probe, lead); our agent has no Stripe Projects account |
| Key: MCP OAuth (DCR + authorize, PKCE, resource) | browser | blocked ✓ | DCR at /oauth/register 200 (client_id issued). /oauth/authorize redirects to accounts.console.agentmail.to/sign-in, which shows a Cloudflare "Performing security verification" interstitial that did not clear after 15 s; and the agent-created org has no console user to consent with. MCP with x-api-key works instead. |
| Sign up: OIDC/SAML SSO | none | skipped | Enterprise plan only (llms.txt) |
| Sign up: Human creates key in console | none | skipped | llms.txt Step 2 fallback: developer generates a key at console.agentmail.to |
| Pay: Public pay probes | api | done ✓ | x402 v2 on x402.api.agentmail.to (PAYMENT-REQUIRED header, 2 USDC exact on Base eip155:8453 + Avalanche/Polygon/Solana/eip155:196; realm api.paysponge.com) and MPP on mpp.api.agentmail.to (WWW-Authenticate: Payment method="tempo" intent="charge", 2000000 of token 0x20C0…b50 on chainId 4217, problem+json body). OpenAPI servers list both. No billing/subscription endpoint in OpenAPI (113 paths). GET /v0/organizations: billing_plan_id free. Domain create 403 names upgrade_url console.agentmail.to/dashboard/upgrade ($20/mo Developer). Pricing: Free plan, no card. |
| Pay: Walk to the last click: console.agentmail.to/dashboard/upgrade | browser | blocked ✓ | Upgrade URL redirects to accounts.console.agentmail.to/sign-in behind a Cloudflare interstitial that does not clear; our agent-made org has no console user, and console sign-up shows Turnstile. Checkout not reached; processor unknown. |
| Cancel: Cancel plan | none | skipped | Nothing to cancel: free plan, no trial, nothing paid. Docs/OpenAPI show no billing API; plan changes are in the console. |
| Schedule a draft to send at a future time: Scheduled draft sends (trial 2) | api | done ✓ | send_at 2026-10-14T05:30:28Z; draft GET 404; sent message [('trial sched 2', ['sent'], '2026-10-14T05:30:44.868Z')] |
| Schedule a draft to send at a future time: Scheduled draft sends (trial 3) | api | done ✓ | send_at 2026-10-14T05:31:22Z; draft GET 404; sent message [('trial sched 3', ['sent'], '2026-10-14T05:31:42.830Z')] |
| Key: DELETE /v0/api-keys/{id}, use the key again | api | done ✓ | DELETE 204; GET /v0/inboxes with the revoked key -> 403 {'message': 'Forbidden'} |
| Webhooks: DELETE webhook and polling webhook, read back | api | done ✓ | webhook DELETE 204 GET 404; polling DELETE 204 GET 404 |
| Docs claim: Create an email inbox for an agent: delete_inbox | mcp | failed | tools/call delete_inbox -> GET inbox 409 |
| Docs claim: Create an email inbox for an agent: delete_inbox | mcp | done ✓ | read back: GET inbox -> 409 resource_deleting "Inbox is being deleted" (asynchronous delete, DELETE answers 202); list no longer shows it |
| Delete: Delete account: delete all inboxes, webhooks, keys; look for an org delete | api | partial ✓ | No documented account/organization delete (OpenAPI 113 paths: /v0/organizations is GET only; docs and llms.txt name none; privacy policy lists a right to request deletion, no route). Deleted every inbox (DELETE 202, GET 404, list count 0), both webhooks, the scoped key, then the org's own key: DELETE 204, next call 401 unknown_api_key. The empty organization (agent-type, the agent's inbox) stays; the console that might delete it is behind Cloudflare checks and the org has no console user. |
Also in Email infrastructure.
MailgunL1Can't sign up on its ownAgentMail vs Mailgun
MailtrapL1Can't sign up on its ownAgentMail vs Mailtrap
PostmarkL1Can't sign up on its ownAgentMail vs Postmark
ResendL1Can't sign up on its ownAgentMail vs Resend