API · wait_for_email
Wait for a matching message without writing a polling loop. The request stays open until a message
arrives or the timeout expires. A matched response includes any OTP code and verification link
found in the message. Requires mailbox:read.
POST /v1/inboxes/{inbox_id}/wait
Section titled “POST /v1/inboxes/{inbox_id}/wait”Request
Section titled “Request”{ "from": "no-reply@acme.test", // optional; match sender (substring, case-insensitive) "subject": "verification", // optional; match subject (substring, case-insensitive) "match": "\\b\\d{6}\\b", // optional; regex over subject + body "folder": "INBOX", // optional; folder to watch "link_hint": "verify", // optional; bias verification-link extraction "timeout_seconds": 120, // optional; default 300, capped at 600 "since_now": true // optional; default true; match only new arrivals}| Field | Type | Notes |
|---|---|---|
from | string? | Substring match on the From header. |
subject | string? | Substring match on the Subject header. |
match | string? | Regex matched over subject + body. |
folder | string? | IMAP folder to watch (default INBOX). |
link_hint | string? | Hint to bias which link is returned as the verification link. |
timeout_seconds | int? | Max seconds to block. Default 300, capped at 600. |
since_now | bool? | When true (default), match only arrivals after the wait begins. |
curl -sS -X POST \ "$EXTROVERT_API_BASE_URL/v1/inboxes/signup-agent%40extrovertmail.com/wait" \ -H "Authorization: Bearer $EXTROVERT_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "from": "no-reply@acme.test", "subject": "verification", "timeout_seconds": 120 }'Matched response (200)
Section titled “Matched response (200)”{ "timed_out": false, "message": { "id": "msg_8Tz", "thread_id": "thread_9aB", "inbox": "signup-agent@extrovertmail.com", "direction": "inbound", "from": { "email": "no-reply@acme.test" }, "to": [{ "email": "signup-agent@extrovertmail.com" }], "subject": "Verify your email", "text": "Your code is 492013…", "html": "<p>Your code is <strong>492013</strong>…</p>", "extracted_text": "Your code is 492013…", "extracted_html": "<p>Your code is <strong>492013</strong>…</p>", "date": "Wed, 18 Jun 2026 18:05:42 +0000", "message_id": "<abc@acme.test>", "folder": "INBOX", "seen": false }, "extracted": { "otp": "492013", "link": "https://acme.test/verify?token=…" }}Timeout response (200)
Section titled “Timeout response (200)”{ "timed_out": true, "message": null, "extracted": { "otp": null, "link": null } }A timeout is a normal 200, not an error. The caller can retry, lengthen the wait, or trigger another
upstream sign-up message.
Legacy body-addressed form: POST /v1/wait
Section titled “Legacy body-addressed form: POST /v1/wait”Identical to the inbox-scoped form, but the inbox is supplied in the body as address instead of in
the path. Prefer the inbox-scoped path; this alias exists for older clients.
{ "address": "signup-agent@extrovertmail.com", "subject": "verification" }Extraction
Section titled “Extraction”| Field | Meaning |
|---|---|
extracted.otp | The one-time code, if found (else null). |
extracted.link | The first click-through verification URL, if found (else null). |
These top-level credential fields are separate from the message’s body derivatives. Inside
message, text and html are nullable source MIME alternatives; extracted_text and
extracted_html are nullable, best-effort quote/signature-stripped versions of those alternatives.
No missing alternative is synthesized. Treat source HTML as untrusted and sanitize it before browser
rendering.
- Quickstart · wait_for_email shows the full flow.
- MCP · wait_for_email documents the tool form.
- Messages & threads covers non-blocking reads.