Cancel a Sume schedule run: actions:write, idempotent, 200 on terminal

POST /v1/action-runs/{run_id}/cancel needs actions:write and is idempotent: canceling a finished run returns its terminal receipt. What happens to spend.

4 min readSume
All posts

To stop a Sume schedule run, send POST /v1/action-runs/{run_id}/cancel with a key that has actions:write. The call is idempotent, and canceling a run that already reached a terminal state returns that terminal receipt with 200, so a retry is safe. The receipt's cancel_url gives the exact path.

From Runs and results, Run a schedule via API and Run webhooks, read on 2026-10-03.

The call and what it returns

The receipt of an accepted run includes cancelable and cancel_url. Check cancelable before calling, though a call on a terminal run is harmless. A canceled run ends with status canceled, spelled with one l.

Cancel needs actions:write, while reading a run needs only actions:read. A monitoring key can therefore hold read access and never stop work.

Cancel behavior for a schedule run (read 2026-10-03)
SituationResult
Run is queued or processingRun is canceled; status becomes canceled
Run is already terminal200 with that terminal receipt
Key has only actions:readCannot cancel; cancel needs actions:write
Cancel called twiceSame outcome both times

Webhooks and cancellation

Run webhooks send one terminal event per run family, but a canceled run does not deliver a webhook. After you POST the cancel, trust the cancel response and poll status_url until payload.status is canceled; do not wait for a POST. A skipped run never delivers a webhook either.

Keep this in the state machine: a run you canceled has no inbound event to close it, so your own code must mark it closed.

Spend after a cancel

Every run carries a generation spend cap, $1.00 by default when unset, and the cap bounds what the run can spend on generation. The cap can be lowered per run but never raised. Whether a canceled run spent anything is a question for usage data, not an assumption: the MCP usage_get tool takes a run_id and reports what the wallet debited, with holds and refunds shown separately from spend.

If your automation cancels runs on a timer, log the run id, the cancel response status and the usage read afterwards. That gives an audit trail without relying on any guess about cost.

Service-account keys

Service-account keys cannot create schedule runs and fail with 403 insufficient_scope. Use a regular key with actions:write for the component that starts and stops runs, and keep the key in an environment variable, never in the repository or in a prompt.

A cancel routine you can run unattended

Because cancel is idempotent, an unattended routine can call it without checking state first. Send the cancel, read the returned receipt, and branch on its status: canceled means the stop worked, and any other terminal status means the run finished before the cancel arrived.

Do not retry a cancel in a tight loop. One call is enough, and repeating it returns the same receipt. If the status is still processing after the call, poll status_url at a sensible interval instead.

Sources

Related posts

More in Developers

All Developers posts

Written by Sume