The task lifecycle
A task is ordered in one call that returns immediately with a reference, worked by a person over an hour to a day, and collected in a second call. Every read tells you when it is worth asking again. Nothing about it is synchronous, and a client written as though it were is the most common integration mistake.
The shape of a job
Quote, order, wait, collect. The order call returns in well under a second with a reference; a person then does the work over an hour to a day. No call ever blocks until a task is finished, and a client written as though one might is the single most common integration mistake.
| Status | Means |
|---|---|
queued | Ordered and waiting to be offered to someone. |
offered | Sent to one or more verified people. |
accepted | Someone has taken it and is on their way. |
in_progress | Being performed now. |
submitted | Evidence is in; verification has not run yet. |
verifying | Evidence is being checked. |
review | A person is looking at it. Rare, and slower. |
completed | There is an answer, with its confidence and evidence. |
failed | We could not do it. Refunded in full, automatically. |
cancelled | You cancelled it while that was still possible. |
expired | The deadline passed without a result. Refunded. |
poll_after_s is not a suggestion
Every read carries it. Before it elapses nothing can have changed, so an earlier call spends your rate limit to learn exactly what you already knew. Register a webhook and you can stop polling altogether.
Idempotency
Idempotency-Key is REQUIRED on create. A repeat with the same key and the same body returns the original task with 200 instead of 201, so a retry after a timeout cannot order twice. The same key with a DIFFERENT body is a 409 — including a different max_price_cents, because a changed ceiling is a changed request, and a replay that reported success for a limit it exceeded would make the guard meaningless.
Over MCP there are no per-call headers, so the key is derived from the arguments: an identical repeat replays, and you pass idempotency_key explicitly when you genuinely want a second, identical task.
max_price_cents is a hard ceiling
It is required, and a quote above it fails rather than charging you. Above that, each agent has a spend policy — per-task cap, daily limit, allowed capabilities and geographies — enforced before any money moves. The money is held when the task is created, in the same transaction that inserts it, and released in full if the task is cancelled or fails.
A refusal is not a failure
Ask for a city we do not cover and you get a 200 with created: false, the reason, the nearest live city with its distance, and a waitlist URL. That is something a machine can reason about; a 4xx is something it gives up on.
Cancelling
Possible while a task is queued or offered, and the whole hold returns. After someone has accepted it they have begun travelling, and what applies then is the refund matrix rather than an API call — contact us.