Cancel 12 queued Sume jobs: 12 writes, and a 409 that is not an error
Cancel is a write, only works before generation starts, and returns 409 job_generation_already_started after. A Python sweep that treats 409 as fine.

Cancelling a Sume job is one write request each, so 12 queued jobs cost 12 writes. On Free that is 10% of the 120 writes per minute. Cancellation only succeeds before generation work starts; afterward the API returns 409 job_generation_already_started with details.cancelable: false, and the job runs to completion and bills. Treat that 409 as information, not as a failure.
Write cost by plan
The Authentication page counts cancellation as a write. The table shows a full queued backlog at the default queue capacity from Generation admission.
| Plan | Default queue capacity | Writes per minute | Cancel writes as a share of one minute |
|---|---|---|---|
| Free | 5 | 120 | 5 / 120 = 4.2% |
| Pro | 20 | 300 | 20 / 300 = 6.7% |
| Startup | 40 | 600 | 40 / 600 = 6.7% |
| Scale | 100 | 1,200 | 100 / 1,200 = 8.3% |
A sweep that tolerates the 409
The function returns a label for each job. A cancel of a job that is already canceled is idempotent and returns the same canceled job, so a second pass is safe. Any other error is raised. Set QUEUED_JOB_IDS to a comma-separated list to run it.
import json
import os
import urllib.error
import urllib.request
def cancel(job_id: str) -> str:
req = urllib.request.Request(
f"https://api.sume.com/v1/jobs/{job_id}/cancel",
method="POST",
headers={"Authorization": f"Bearer {os.environ.get('SUME_API_KEY', '')}"},
)
try:
urllib.request.urlopen(req, timeout=20).read()
return "canceled"
except urllib.error.HTTPError as err:
code = json.load(err).get("error", {}).get("code")
if err.code == 409 and code == "job_generation_already_started":
return "running: will finish and bill"
raise
if __name__ == "__main__":
ids = os.environ.get("QUEUED_JOB_IDS", "").split(",")
for job_id in filter(None, ids):
print(job_id, cancel(job_id)) # one write eachWhat cancel does to the bill
At submit Sume reserves the estimated amount. A cancel before generation starts releases the reservation where applicable, while a job that already started completes or fails normally and captures usage on success. That is why you cancel queued jobs you no longer need, rather than letting them reach processing.
The same rule holds when you stop waiting. A client timeout or an aborted wait does not cancel the job. Store the job id and cancel explicitly.
Avoiding the 409
Cancel soon after you decide. A queued job that moves to processing can no longer be canceled, so the window is the time spent waiting in the queue, which depends on your concurrency. On a Free workspace with one slot, the queue is longer than on Scale.
If you need many cancellations, pace them: 100 cancels on Scale is 100 of 1,200 writes, which leaves room for the rest of your traffic in the same minute.
Sources
Related posts
More in Developers
- Caption a 61-second clip: the $0.20 Sume price is for 60 seconds
Sume's docs say the $0.20 caption job price is for videos of at most 60 seconds. For a 61-second clip, trim first for $0.02 or check the live catalog price.
- chat-latest moved on Oct 7: pinning the model in a nightly job
OpenAI refreshed its chat-latest snapshot on Oct 7. Sume Agent Completions take only sume-agent. What that means for a CI job that must give stable output.
- Cheapest legal Wan 3.0 call: 2 s at 480p is $0.125, 15x less than 30 s
Wan 3.0 runs 2 to 30 s. The minimum call costs $0.125 at 480p, $0.25 at 720p and $0.50 at 1080p. A curl body, and why client-side length checks beat a 400.
- Check a GPT Image 2.5 size before you call it: a Python validator
Sume rejects GPT Image 2.5 sizes that break four rules: multiples of 16, edge 3840, ratio 3:1, 655,360 to 8,294,400 pixels. A Python check, run on 8 sizes.
Written by Sume