Skip to main content
POST /v1/runs is synchronous: it returns the finished run, so most integrations never poll. This page is for the cases where you do not get that response: a client timeout, a dropped connection, a 202 on a replay, or a second process that holds a run_id and needs the answer.

You usually do not need to poll

The request waits until the run settles, then returns it with 200. The wait is bounded by the run’s deadline: for a decision, 30,000 ms plus 120,000 ms per 262,144 input tokens by default, at most 150,000 ms. When the deadline passes, the request ends with 504 deadline_exceeded. Set your HTTP client timeout above the deadline you send, at least 160 seconds, and most of what this page covers never happens.

Run states

A run goes straight from pending to completed or failed. There is no intermediate state to watch for.

Recover after a client timeout

When your client gives up before the response arrives, you do not know whether the run exists. You have two ways back. Send the same request with the same Idempotency-Key. This is the simplest, because you do not need the run_id: Or read the run by id, if you stored the run_id from an earlier response:
GET /v1/runs/{run_id} needs the runs_read scope. A completed run comes back with its answer:
A stored run is thinner than the live POST response. It has no cost_basis and no schema_enforcement, and a decision has no model, stages, thought_tokens or thought_closed. replayed is always true here, because the body comes from storage. A run that is not completed returns the row only, without an answer. If you need cost_basis or the decision stages, keep the original POST response. They are not stored.

A 202 that stays pending

A pending run has one of two causes:
  1. The first request is still being served. It settles within its deadline, at most 150 seconds after it was sent.
  2. The run failed before a model call. For example, no route was available, the deadline passed while routing, or the upstream model refused the call. Such a run is never moved out of pending, and the same key answers 202 with it for good.
Tell them apart with the deadline: poll until the run settles or until the deadline of the original request has passed. A run still pending after that will not settle. Send the request again with a new Idempotency-Key. Nothing was charged for the stuck run: its reservation was released when it failed.

A polling loop

This waits for a run you hold the id of, and gives up once the deadline has clearly passed.
sent_at is the time you sent the original POST. If you do not know it, use the maximum deadline, 150 seconds, from when you first saw the run.

Errors

Reads never return 429.
  • Idempotency - how replays answer 200 or 202, and when a key must be replaced.
  • Streaming - the same stored state as a server-sent events snapshot.
  • Error handling - a retry helper that uses the same key after a timeout and a new key after a 5xx.
  • Runs - the run lifecycle and what each field means.
  • API reference - the GET /v1/runs/{run_id} schema.