# API · wait_for_email

{/* // POST /v1/inboxes/{inbox_id}/wait + POST /v1/wait */}

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`

### Request

```json
{
  "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. |

```bash frame="terminal"
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`)

```json
{
  "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`)

```json
{ "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.
**Set the client read timeout above timeout_seconds:** This endpoint long-polls. Your HTTP client (and any reverse proxy between you and the API) must allow
  a read timeout greater than `timeout_seconds`, or the connection will be cut before the email arrives.
  The SDK and MCP server handle this automatically.

## 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.

```json
{ "address": "signup-agent@extrovertmail.com", "subject": "verification" }
```

## 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.

## Next

- [Quickstart · wait_for_email](https://docs.extrovert.dev/quickstart/wait-for-email/) shows the full flow.
- [MCP · wait_for_email](https://docs.extrovert.dev/mcp/wait-for-email/) documents the tool form.
- [Messages & threads](https://docs.extrovert.dev/api/messages-and-threads/) covers non-blocking reads.