cancel_url is null on a processing job: when Sume allows cancel
Why a Sume job in processing can show cancelable false and cancel_url null: cancel depends on whether generation work started, not the status label.

A Sume job can be processing and still show cancelable: false with cancel_url: null. In the API, cancelability is true only for queued or processing jobs whose generation submission has not started, so the status label alone does not tell you.
Read cancelable and cancel_url off the job envelope instead of guessing from status. The generation admission page says cancellation succeeds only before generation work starts.
What decides cancelable?
The job-action metadata in the API computes cancelable from two things: the status is queued or processing, and the job has not yet started provider submission. When it is false, cancel_url is null rather than a link that would answer 409.
That is why the envelope is better than the status for UI: a cancel button bound to cancel_url !== null never offers an action the server will refuse.
What happens if you call cancel anyway?
The route answers 409 job_generation_already_started with details.cancelable: false, and the job completes or fails normally. See the jobs docs. The reservation for a job that completes is captured; one that fails releases or refunds it where applicable, per the docs.
| Field | Cancelable job | After generation starts |
|---|---|---|
| cancelable | true | false |
| cancel_url | URL | null |
| POST cancel | Job becomes canceled | 409 job_generation_already_started |
How should a queue UI use this?
Jobs sitting in queued are the ones you can almost always cancel, which is how you free capacity after a 429 queue_full: the docs suggest cancelling queued jobs you no longer need before they start processing.
Sume does not expose a per-job queue position or ETA today, only counts and remaining capacity, so do not build a progress bar from queue order.
Check the field before you render a button
The check is one line against the status read, so there is no reason to call cancel speculatively.
curl -s https://api.sume.com/v1/jobs/job_123 \
-H "Authorization: Bearer $SUME_API_KEY" \
| jq '{status: (.data.job.status // .job.status // .status), cancelable: (.data.cancelable // .cancelable), cancel_url: (.data.cancel_url // .cancel_url)}'What Sume does not do
Sume does not interrupt a started generation. If a job is going to be wrong, cancel it while it is queued, or accept the result and re-run with a corrected request.
Quick checklist
The points above reduce to a short list you can paste into a runbook.
- Bind your cancel button to cancel_url being non-null.
- Expect queued jobs to be cancelable; expect started jobs not to be.
- Free capacity after queue_full by cancelling queued jobs you no longer need.
- Do not infer queue position: Sume exposes counts, not positions.
- Store status_url, result_url, events_url and cancel_url when present.
Sources
Related posts
More in Developers
- Check a video request against /v1/videos/models before you submit
Duration, resolution, size and seed errors cost a round trip. A short Python validator reads the model catalog and refuses a bad request locally first.
- Check a transparent GPT Image 2.5 PNG for real alpha in Python
A transparent GPT Image 2.5 result can still look opaque. Ask for background transparent as PNG, then check the alpha channel in Python: a 20-line script.
- China's implicit AI label: provider name and content ID in metadata
China's implicit AI label is metadata with the provider name and a content ID. Why a re-encode can drop it, and how to check a delivered file with ffprobe.
- Choose an image model in code: filter GET /v1/images/models
Pick a Sume image model by what the job needs: references, 4:5, a mask, transparency. A Python filter over the catalog descriptors, with the price lookup.
Written by Sume