Cancel a queued avatar creation job before generation starts
Cancel a Sume avatar creation job with POST /v1/jobs/{id}/cancel. It works only before generation starts; later you get 409. Only the creator can cancel.
You can cancel a queued avatar creation job on Sume with POST /v1/jobs/{job_id}/cancel, but only before generation work starts. If generation has begun, the API returns 409 job_generation_already_started with details.cancelable: false, and the job runs to completion. A cancel on a job that is already canceled is idempotent and returns the same canceled job. Only the member who created the job can cancel it.
This is the rule in Jobs and results, read 2026-10-05, and avatar creation uses the same jobs as every other submit endpoint, as shown on Create new avatar.
The three responses
Three outcomes are possible, and your code should handle each of them.
The first row is the only one where the cancel changes anything. The second is a safe no-op, which lets you call cancel twice, for example from a retry, without an error. The third and fourth are information: the job is not yours to stop, or it is already past the point where stopping is possible. Build the client so that all four are expected outcomes, with a message for each, rather than treating anything but success as an exception.
| Job state when you cancel | Response | What to do |
|---|---|---|
| Queued, generation not started | Job becomes canceled | Stop polling; a job.canceled webhook is sent if you set one |
| Already canceled | Same canceled job, idempotent | Treat as success |
| Generation started | 409 job_generation_already_started, cancelable false | Let it finish and use or ignore the result |
| Created by a different member | Not cancelable by you; reads return 404 | Ask the creating member or use their key |
Cancel from Python
The script below sends the cancel, reads the outcome, and prints what to do. It refuses to run with no API key and takes the job id as an argument.
import json, os, sys, urllib.request, urllib.error
key = os.environ.get("SUME_API_KEY", "")
if not key or len(sys.argv) < 2:
sys.exit("Usage: SUME_API_KEY=... python3 cancel.py JOB_ID")
req = urllib.request.Request(
"https://api.sume.com/v1/jobs/%s/cancel" % sys.argv[1],
method="POST", headers={"Authorization": "Bearer " + key})
try:
job = json.loads(urllib.request.urlopen(req).read().decode())
print("status:", job.get("status"))
except urllib.error.HTTPError as e:
err = json.loads(e.read().decode()).get("error", {})
d = err.get("details") or {}
print(e.code, err.get("code"), "cancelable:", d.get("cancelable"))What a 409 means
Do not treat a 409 as a failure of your job. It means the work was handed over and now runs on its own schedule. The job will complete, fail or be canceled by the system, and you will see the terminal state through polling or a webhook of type job.completed, job.failed or job.canceled.
Also remember that a client-side timeout is not a cancel. The docs say a timeout in your process does not stop the job, and that you should poll the status URL or cancel explicitly. If you gave up waiting on an avatar, either poll until it is terminal or send the cancel yourself while it is still queued.
For a job that did start, you still have choices. You can ignore the result and let it be one more asset in your library, or you can use it. The docs say the job runs to completion, so plan for the cost of a started job to be incurred. What you control is what you do next, and whether your system submits another job for the same photo.
When the window is short
Cancel as early as you can. The docs say only that a cancel works before generation work starts, and they do not state how long that window lasts, so do not build a flow that depends on it. A realistic use is a user who uploads the wrong photo and corrects it in seconds. For a longer decision, such as comparing candidates, do not rely on a cancel: use the free preflight and previews, covered in the ten photo post.
See where the job is
Watch the job's events if you need to know where it is. The events post shows how to read them, and the 409 post covers the same error for video jobs.
Sources
Related posts
More in Developers
- Cancel video jobs still queued after 10 minutes: handle the 409
A Python sweeper that cancels Sume video jobs queued too long. POST /v1/jobs/{id}/cancel works only before generation starts; the 409 means keep waiting.
- canceled vs cancelled: one letter that breaks video status checks
Sume native jobs say canceled and send job.canceled. The OpenRouter-shaped /v1/videos response says cancelled. Normalize the spelling before you branch.
- Sume 501 capability_not_configured: no job started, no credits spent
501 capability_not_configured means that feature is not connected on the platform. No job starts and nothing is charged. Do not retry; contact support.
- Caption 40 clips in six languages with no language hint: $8
Leave `language` off and Sume's caption job detects it. Forty clips of up to 60 seconds cost $8.00 at $0.20 each; here is the loop and the style trap.
Written by Sume