Request errors

A refused request answers a 4xx or 5xx with a JSON body:

Transaction failures

202 means accepted, not done. A transaction that later ends without moving its money has status: failed (or expired) and a failure block — on GET /transactions/{id}, in its row of GET /transactions, and in the operation.failed webhook:
reason comes from a closed set: retryable: true means it is safe to submit again with a new idempotency key. Anything else would fail the same way: look before resubmitting. cancelled is not retryable on purpose: a retry loop that resubmits every retryable failure would undo your cancel. On TON, window_expired is declared only once the chain index provably serves every transaction of the sending wallet through the window. Should a transaction still land after window_expired, the chain wins: the same operation gets operation.confirmed with corrected: { from: "expired", failure, at }, and GET /transactions/{id} carries the same corrected from then on.

Workflow failures

A run that stops has status: failed and a free-text failure_reason on GET /runs/{id}, in its row of GET /runs, and in run.failed. A run you cancelled with POST /runs/{id}/cancel has status: cancelled, failure_reason: cancelled through the API, and run.cancelled.