Waiting for mail
GET /v1/inboxes/{id}/wait is a long-poll on one inbox. It answers as soon as matching mail is there, or with status: "timeout" when the time is up. It is made for “I just signed up somewhere, now give me the verification email”. To watch every inbox with one call, use the event feed.
Parameters
Section titled “Parameters”| Parameter | Default | Rules |
|---|---|---|
since |
now − 10 minutes | ISO 8601 time. Only messages received at or after it |
from |
none | Case-insensitive pattern for the whole sender address: * = any characters, ? = one character. Example: *@accounts.example.com |
subject |
none | Case-insensitive part of the subject |
thread_id |
none | Only messages of that thread |
exclude_returned |
false |
true skips messages already returned (see “Read flag”) |
limit |
10 |
1–50 messages in one answer |
timeout |
25 |
0–60 seconds to hold. 0 checks once and answers at once |
extract |
none | otp, link or otp,link: add the code and links to each message. See Get a verification code |
All filters must match. Messages without a sender or subject never match from or subject.
What happens
Section titled “What happens”waitchecks at once. If anything matches, it answers immediately with all matches, newest first, up tolimit. It never waits to filllimit.- Otherwise it holds. Every new message of the account wakes it to check again, until something matches or
timeoutpasses. - Both outcomes are HTTP
200:
{ "status": "timeout", "messages": [], "next": "No matching mail yet. Call wait again." }An ok answer has status: "ok" and the messages (see the Quickstart).
The 10-minute lookback
Section titled “The 10-minute lookback”sincedefaults to 10 minutes back, so a code that arrived just before the call is returned at once.- Within those 10 minutes the same message comes back on every call (with
returned_before: true), unless you passexclude_returned=trueor a latersince. - A message becomes visible a little after its
received_at. Do not setsinceto the exact moment of your call: use the default, or a time a minute or two before you triggered the email (this also covers clock differences).
The read flag
Section titled “The read flag”A message counts as read once wait, GET /v1/messages/{id} or POST /v1/messages/{id}/extract has returned it. Listing messages, threads, the event feed and attachment downloads never mark anything. Each message carries returned_before: whether it had been returned before this call.
With exclude_returned=true, a message whose earlier answer your agent never processed (for example after a crash) is skipped too. Find it with the message list.
Up to 5 holds per account
Section titled “Up to 5 holds per account”- An account can hold at most 5 long-polls at the same time,
waitandevents?wait=together. - A call that answers at once (mail already there, or
timeout=0) does not use a slot. - A 6th hold gets
429too_many_waitswithRetry-After: 1. A long hold can also end with it after 20 or 40 seconds if all slots were taken in between.
Client timeout
Section titled “Client timeout”Set your HTTP client timeout above the timeout you ask for, for example timeout + 15 seconds (curl --max-time 65 for timeout=50). If your agent’s HTTP tool has a fixed shorter limit, lower timeout to fit under it.
Good to know
Section titled “Good to know”waitlooks at the 500 newest messages that match the inbox,since,thread_idandexclude_returned, then appliesfromandsubject. Keepsincerecent.- Two
waitcalls running at the same time can both return the same message, each withreturned_before: false. - An
expiredorsuspendedaccount never holds: it answers at once with mail already stored, ortimeout. waiton a deleted inbox answers404not_found.
No push delivery: webhooks are not offered. An MCP and a CLI version of wait are coming soon.
Reference: GET /v1/inboxes/{id}/wait.