Cancel a Format run: cancel_effect, no_op and what you still pay

POST cancel on a Format run is idempotent. cancel_effect says canceled or no_op. You pay for generation done before the cancel, and no webhook is sent.

5 min readSume
All posts

Cancel a Format run with POST /v1/format-runs/{run_id}/cancel, using a key with formats:write. The call is idempotent and returns the current receipt either way. The cancel_effect field tells you what happened: canceled means this call stopped a run in progress, and no_op means the run had already finished before the call. You pay for the generation that completed before the cancel.

What each outcome means

Read cancel_effect first, then status and usage on the same receipt.

Cancel outcomes from the Runs and results docs, as of 2026-10-09
Case`cancel_effect`Receipt `status`Billing
Run still queued or processingcanceledcanceledGeneration already finished is billed
Run finished firstno_opcompleted or failedUnchanged
Repeat cancel on a canceled runSame current receiptcanceledUnchanged

Two details that surprise people

The word is spelled canceled, with one l, in the status and in the code values. A string match on cancelled will never fire.

A canceled run never delivers a webhook. If your integration is webhook-only, cancel is the one path with no delivery, so take the state from the receipt the cancel call returns. Skipped runs also never deliver, but a skipped run is already terminal on the create response.

Using cancel with queues and costs

A bulk queue has no cancel endpoint. To stop a queue, cancel its children one by one with their run ids. The queue marks the item canceled and frees its slot, and the next queued item starts, so cancel the queued items you want to stop quickly, or accept that the window will pick up the next one.

cancelable on the receipt is true only while the run is queued or processing, so check it before you call. After the cancel, read usage.billable_amount_usd_micros for the generation spend counted against the run's cap and usage.debited_usd_micros for the wallet amount. A cancel does not refund generation that had already completed. To redo only part of a canceled run's work, a run that left artifacts and has a thread_id can be continued with previous_run_id.

A cancel helper

A reliable helper does four steps. It reads the receipt and checks cancelable. It posts to cancel_url. It reads cancel_effect from the answer and logs the value with the run id. It then reads usage and records the spend so the books match the wallet. Because the call is idempotent, the helper can retry after a timeout without a second effect.

Cancel is also the right tool when a run has plainly gone wrong: a bad brief that you see in the first receipt, or a duplicate you started by mistake. Do it quickly, since every minute of processing can add generation spend. Remember that skipped runs are different: on_active_run: "skip" records a skipped run without starting it, costs nothing, and has nothing to cancel.

Log request_id from the cancel response too. If a cancel seems not to have worked, for example the spend keeps rising, support asks for that value together with the run id.

Sources

Related posts

More in Formats

All Formats posts

Written by Sume