Cancel every queued Sume job without cancelling a running one
A Python script that lists queued jobs, checks the cancelable flag, posts the cancel, and handles 409 job_generation_already_started when the race is lost.

List the jobs with status=queued, read each job's status snapshot, and POST /v1/jobs/:id/cancel only when cancelable is true. Cancel works only before generation work starts, so a job that moved to processing between your read and your write answers 409 job_generation_already_started and runs to completion. Treat that 409 as a normal outcome of the race, not as a bug.
Which answer means what
| Situation | What the API does |
|---|---|
| Job is queued, cancelable true | Cancel succeeds and the job becomes canceled |
| Generation already started | 409 job_generation_already_started with details.cancelable false |
| Job already canceled | Idempotent: returns the same canceled job |
| Job is another member's | Only the member who created a job can cancel it |
The script
The helper reads the status snapshot first, because the snapshot carries both terminal and cancelable. It reports one line per job. Use it when a bad batch is queued and you want to stop the jobs that have not started.
import json, os, urllib.error, urllib.request
BASE = "https://api.sume.com/v1"
def call(method, path):
req = urllib.request.Request(BASE + path, method=method,
headers={"x-api-key": os.environ["SUME_API_KEY"]})
try:
with urllib.request.urlopen(req, timeout=30) as r:
return r.status, json.load(r)
except urllib.error.HTTPError as e:
return e.code, json.load(e)
def cancel_if_possible(job_id):
_, body = call("GET", f"/jobs/{job_id}/status")
snap = body["data"]
if snap["terminal"]:
return f"{job_id}: already {snap['status']}"
if not snap["cancelable"]:
return f"{job_id}: generation started, it will finish and bill"
code, body = call("POST", f"/jobs/{job_id}/cancel")
if code == 409:
return f"{job_id}: lost the race ({body['error']['code']})"
return f"{job_id}: canceled" if code < 300 else f"{job_id}: HTTP {code}"
if __name__ == "__main__":
_, listing = call("GET", "/jobs?status=queued&limit=100")
for job in listing["data"]["jobs"]:
print(cancel_if_possible(job["id"]))Cautions
Run a dry run first by printing the ids instead of posting the cancel. A cancel script that targets the wrong key's queue is easy to write and slow to undo.
- Jobs that already started keep running and bill. Cancel is not a way to stop a running render.
- The status cancel_url is null after generation starts and after terminal states, which is the same signal as cancelable false.
- Page through the queue if you have more than 100 queued jobs. The list returns next_cursor while more jobs remain.
- Check the cancellation and billing section of the admission docs for what happens to the reserved amount.
Why read the status first
You could post the cancel to every id and let 409 sort it out, but the status read makes the log far clearer. A terminal job shows its final status, a started job shows that it will bill, and only the jobs that are really cancelable cause a write. Writes have the smaller rate budget, 120 a minute on Free and 300 on Pro, while reads are 40 times larger, so spending a read to save a write is the right trade when you clean up a large queue.
Sources
Related posts
More in Developers
- Cancel queued Sume jobs after queue_full; handle 409 already started
How to free capacity after a 429 queue_full: cancel queued jobs, read job_generation_already_started on running ones, and why a cancel releases the reserve.
- Cancel queued video jobs when the offer changes: Pro plan example
On Pro, 4 jobs process and 20 wait in the queue (24 accepted). Only queued jobs can be canceled; a started job returns 409 job_generation_already_started.
- Can't choose a video model? Send sume/auto and let Sume pick
model: sume/auto lets Sume select the video family for you: 3 to 10 seconds, 16:9 or 9:16, default 720p and 8 seconds. What it does and does not tell you.
- Caption files: YouTube UTF-8, LinkedIn text-only SRT, Sume burns in
YouTube takes SRT, SBV and more as UTF-8; LinkedIn wants text-only SRT. Sume burns captions in and exports no SRT, so build the file from segments.
Written by Sume