Cancel a Format run: cancel_effect canceled vs no_op

POST /v1/format-runs/{run_id}/cancel is idempotent and returns the current receipt. Read cancel_effect to know if you stopped it, and what still bills.

5 min readSume
All posts

To stop a Sume Format run, call POST /v1/format-runs/{run_id}/cancel with a key that has formats:write. The call is idempotent and always returns the run's current receipt, and the cancel_effect field tells you which thing happened: canceled means this call stopped a run in flight, no_op means the run had already finished.

That distinction matters because cancel is not a refund button. Generation the run completed before the cancel is billed, and the receipt's usage reports it. This post covers how to read the answer, what a canceled run does and does not send you, and how cancel behaves inside a bulk queue.

What does cancel return?

The runs page says the current receipt comes back either way. You do not get an error for canceling a run that is already done; you get a receipt with cancel_effect: no_op. That makes the call safe to retry after a network failure, and safe to call from a cleanup job that does not know which runs are still alive.

The cancelable field on any receipt is true while the run is queued or processing. Check it before you call if you want to avoid a pointless write, but you do not have to: the no-op answer is the contract.

cancel_effect values, read 2026-10-02
cancel_effectMeaningWhat to do next
canceledThis call stopped a run that was in flightRead usage for what was already generated and billed
no_opThe run had already finished before the callUse the receipt as it is; the run is completed, failed or canceled already

What still bills after a cancel?

Anything the run finished generating before the cancel is billed. The errors page states the same rule for failures: a later step failing, or a cancel, does not refund generation that already finished. A 4xx at create, an idempotent replay and a skipped run cost nothing, but a canceled run can.

Read usage.billable_amount_usd_micros for the generation spend attributed to the run, and usage.debited_usd_micros for what the wallet actually deducted. If you canceled because a run looked wrong, check artifacts[] too: it lists every durable file the run made, and a canceled run's pieces are still yours. See the billing post for the full what-bills table.

Will I get a webhook for a canceled run?

No. A canceled or skipped run never delivers format.run.terminal. The webhook fires once, on completed or failed. If your integration is webhook-only, cancel is the one path where nothing will arrive, so use the receipt that the cancel call returns and mark the run canceled in your own records at that moment.

This is the opposite of generation jobs, which do send a canceled webhook, as covered in the jobs versus runs post.

How does cancel work inside a bulk queue?

A bulk queue has no cancel endpoint and no list endpoint. You cancel children one at a time with the same POST /v1/format-runs/{run_id}/cancel. Canceling a child marks its queue item canceled and frees its slot, so the next queued item starts immediately and the window stays full.

If you want to stop an entire batch, you have to cancel the running children and also prevent the remaining queued items from starting, which the public API gives you no direct way to do. Plan batch size with that in mind: the bulk queue post explains the limit.

RUN_ID="arun_e43e6c5cb2b74052"
curl -sS -X POST "https://api.sume.com/v1/format-runs/$RUN_ID/cancel" \
  -H "Authorization: Bearer $SUME_API_KEY" | jq .

What errors can cancel return?

A key without formats:write gets 403 insufficient_scope, a run id that is unknown or belongs to another owner gets 404 format_run_not_found, and a 429 or 503 is transient. For a transient failure, send the cancel again: the call is idempotent, and the run keeps spending until it actually stops.

Sources

Related posts

More in Formats

All Formats posts

Written by Sume