Read a verification code (OTP) via API
What you'll build: a short blocking loop that waits for a one-time code (OTP / 2FA) to land in your agent's mailbox and pulls the code out - fetched live from the source so the agent isn't blocked by cache lag. This is the canonical "confirm a signup" / "pass a 2FA gate" flow for an agent that owns a real inbox.
Last updated June 30, 2026
How it works in one paragraph
OTP emails are time-sensitive, so you read them with live=true - an on-demand fetch straight from the source rather than the cache. You poll the inbound list until a matching message appears, then read the code from the message (often visible in the snippet preview; pull the full body by id when you need certainty). A read-scoped key is enough - the agent never needs to send.
Before you start
- A provisioned mailbox (
mbx_…) whose address you'll use as the signup/login email. - A
read-scopedsm_live_…key, set asSAIRAPH_MAIL_KEY.
Steps
1. Trigger the email
Have your agent (or the system under test) submit the mailbox's address to whatever sends the code - a signup form, a login 2FA step, a CI sign-in. The code is now in flight to your mailbox.
2. Poll the inbox, live
Read inbound mail with live=true so you get the freshest state rather than a cached snapshot:
This returns the Stripe-style list envelope. Inbound rows arrive as live_message (fresh) or cached_message, each with from_addr, subject, and a snippet preview. Loop this call on a short interval (e.g. every 2-3 seconds) with a sensible timeout (e.g. 60 seconds), filtering by the expected from_addr or subject until the code's message appears.
3. Extract the code
Most providers put the code in the subject or the first line, so the snippet preview usually contains it - match it with a regex such as \b\d{6}\b (adjust for your code length/format). When you need the complete body to be certain, fetch the message by id:
Use the id from the matched list row (a cmsg_… id). The default response returns the quote-stripped body_text; include=html adds the raw body_html if the code is only in an HTML part. Then run your regex over the body.
A Python sketch of the poll loop
The read call itself comes from the SSOT (READ_INBOUND_PY reads direction=inbound&live=true); wrap it in a timed loop and a regex:
Troubleshooting
- Code never arrives: confirm you submitted the mailbox's exact address; check the right
from_addr; widen the timeout. Re-read withlive=true(a cached read can lag). - Code is in the body, not the snippet: fetch the message by id and add
include=htmlif the code is HTML-only. - Polling too aggressively: back off to 2-3 second intervals;
live=truehits the source server each time. - Multiple codes / stale code: sort by
received_atand take the newest matching message so you never use an expired code. - `429`: you're over the rate limit - honor the
Retry-Afterheader before the next poll.
Next steps
- The use-case overview: OTP & verification codes for agents.
- The general read pattern: Receive email via API.
- Full reference: the API docs.
Related
Give your agent a real mailbox
Two-way email over REST and a native MCP server, EU-resident by default.
EU data residencyPer-customer encryptionNative MCP