Register a durable verification wait on an inbox
Opens a durable background wait that watches the inbox's inbound mail and resolves the awaited email for you, returning immediately with status: pending.
Opens a durable background wait that watches the inbox's inbound mail and resolves the awaited email for you, returning immediately with status: pending. An EU-resident AI matcher evaluates each incoming message against your natural-language instruction — for example wait for the GitHub sign-in code and return it — and, on a match, resolves the wait with the extracted value in result (a code, a link, or a quoted line); omit instruction and it defaults to matching any verification, OTP, or confirmation code. Set fromHint to the sender's address (matched exactly) or domain (which also matches its subdomains) — anything else is a 400 — so only that sender, authenticated by DMARC, can resolve the wait (a wait without a hint resolves from any sender except one that failed its domain's DMARC policy); and timeoutSec (30–1800 seconds, default 300) to size the window, where expiresAt is now + timeoutSec. The outcome later arrives as a verification.resolved (carrying result, from, and messageId) or verification.expired event on your webhook and the durable event ledger, or by polling the wait. Pass idempotencyKey to make retries safe — a repeat with the same key returns the original wait, scoped to this inbox, without opening a second one. An inbox allows at most 50 open waits at once; registering beyond that returns 429, and an unknown or non-owned {inbox} returns 404.
Scope: inboxes:write. Send the API key as a bearer token; Scopes lists what each one reaches.
Request
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
inbox | string | yes | Inbox UUID or full address (e.g. agent@dairo.app). |
Body
Required, application/json: RegisterVerificationWaitRequest.
| Field | Type | Required | Description |
|---|---|---|---|
timeoutSec | integer | yes | How long the wait stays open, 30..=1800 seconds. expiresAt = now + timeoutSec. (minimum 30, maximum 1800) |
fromHint | string or null | no | Optional sender to accept, case-insensitive: a full address (matched exactly) or a domain (matches that domain and its subdomains, e.g. 'github.com' matches 'noreply@mail.github.com'). Never a substring match. Anything that is not an address or a domain is a 400. A hinted wait resolves only from an authenticated sender: an email whose From domain passed DMARC, or an A2A message from a Dairo inbox on a verified domain or a Dairo address. Null/absent accepts any sender except an email that failed its From domain's DMARC policy. (max length 255) |
instruction | string or null | no | Natural-language instruction for the AI matcher: which email to wait for and what to extract (e.g. 'wait for the Telnyx password-reset email and return the reset link'). An EU-resident model evaluates each inbound email against it and, on a match, resolves the wait with the extracted value in result. Absent defaults to extracting any verification/OTP/confirmation code. (max length 2000) |
idempotencyKey | string or null | no | Optional idempotency key; a retried register with the same key returns the same wait. (max length 255) |
Response
200 Success. Body: application/json, VerificationWait.
| Field | Type | Required | Description |
|---|---|---|---|
waitId | string (uuid) | yes | |
inboxId | string (uuid) | yes | |
agentId | string (uuid) or null | no | The Agent Passport that registered this wait, when the API key was agent-bound. |
status | "pending", "resolved", "expired" | yes | |
fromHint | string or null | no | |
instruction | string or null | no | The natural-language matcher instruction this wait was registered with. |
result | string or null | no | The value the AI matcher extracted per the instruction (present once resolved) — a code, a link, or a quoted line. |
from | string or null | no | The From address of the message that resolved the wait. |
messageId | string (uuid) or null | no | The inbound message that resolved the wait. |
idempotencyKey | string or null | no | |
expiresAt | string (date-time) | yes | |
createdAt | string (date-time) | yes | |
resolvedAt | string (date-time) or null | no | |
expiredAt | string (date-time) or null | no |
201 Created. Body: application/json, VerificationWait.
| Field | Type | Required | Description |
|---|---|---|---|
waitId | string (uuid) | yes | |
inboxId | string (uuid) | yes | |
agentId | string (uuid) or null | no | The Agent Passport that registered this wait, when the API key was agent-bound. |
status | "pending", "resolved", "expired" | yes | |
fromHint | string or null | no | |
instruction | string or null | no | The natural-language matcher instruction this wait was registered with. |
result | string or null | no | The value the AI matcher extracted per the instruction (present once resolved) — a code, a link, or a quoted line. |
from | string or null | no | The From address of the message that resolved the wait. |
messageId | string (uuid) or null | no | The inbound message that resolved the wait. |
idempotencyKey | string or null | no | |
expiresAt | string (date-time) | yes | |
createdAt | string (date-time) | yes | |
resolvedAt | string (date-time) or null | no | |
expiredAt | string (date-time) or null | no |
Errors
Every error has the same body, {"error": {"type", "code", "message", "param"}}; branch on code. Errors lists every code.
| Status | Meaning |
|---|---|
400 | The request is malformed or a value is invalid (invalid_request, invalid_domain, idempotency_key_mismatch). |
401 | The API key is missing or invalid. |
403 | The key lacks the scope this endpoint needs (scope_missing) or may not do this (not_permitted). |
404 | No such resource in this account (resource_not_found). |
409 | The resource already exists or its state does not allow this (duplicate_resource or a condition-specific code). |
422 | The request is well-formed but a field failed validation (validation_failed). |
429 | Rate limit, plan limit, budget or spend cap reached (rate_limited, plan_limit_reached, budget_exceeded, spend_cap_reached). |
500 | An unexpected error; retry with backoff, then contact support (internal_error). |
List recent verification waits for an inbox
Returns the inbox's verification waits, most recent first, across every status (pending, resolved, expired, canceled).
Poll a single verification wait
Fetches one verification wait by waitId so you can poll for its outcome instead of, or alongside, the webhook event.