Cancel a wrong video job after a Sora port: only before it starts
Ported prompts on the wrong model burn money. Sume cancels a video job only before generation starts; later you get 409 job_generation_already_started.

To stop a Sume video job you call POST /v1/jobs/{id}/cancel, and it works only while the job has not started generating. Once generation has started the API answers 409 job_generation_already_started with details.cancelable: false, and the job runs to completion. That is the rule to design around when a ported Sora batch goes out with the wrong model or the wrong duration.
The call and the two outcomes
Cancel uses the same bearer key as submit. The docs add that only the member whose key created the job can cancel it, so a different teammate's key gets no access to the job at all (reads of other members' jobs return 404 not_found).
curl -X POST https://api.sume.com/v1/jobs/job_123/cancel \
-H "Authorization: Bearer $SUME_API_KEY"What each state means for you
A job in queued has not started, so cancellation is the useful case: a batch that overshoots a plan's queue still has its waiting jobs cancelable. A job in processing may or may not have crossed into generation; the response tells you. Cancelling a job that is already canceled is idempotent and returns the same canceled job, so a retry after a network error is safe.
| Job state when you cancel | Result | What to do |
|---|---|---|
| queued, generation not started | Job becomes canceled | Fix the request and resubmit with a new idempotency key |
| generation already started | 409 job_generation_already_started, details.cancelable false | Let it finish; read the result |
| already canceled | Same canceled job returned | Nothing; the call is idempotent |
| completed or failed | No cancel path | Read the result or the error |
A spelling trap in the status check
The /v1/videos job statuses table in the docs spells the terminal state cancelled, with two l's. The /v1/jobs surface and the error codes use canceled. A ported loop that tests only one spelling will keep polling a dead job. Treat both as terminal, or normalize at the edge. The post on status vocabularies has a small mapper.
Do not resubmit after a timeout
The jobs docs are blunt on one point: do not submit the original paid request again only because a local process timed out. A second submit is a second job. Look the first one up by id, or send the original Idempotency-Key, which makes the replay return the original job. Cancel is for jobs you actually want gone, not for ones your client lost track of.
A practical checklist for a migration batch
Run one prompt first. If the output is wrong, cancel the queued remainder before it starts rather than after.
- Keep the job id of every submit in your own table before you do anything else.
- Cancel queued jobs from that table when you spot a bad parameter, using the creating key.
- Expect
409 job_generation_already_startedfor jobs that were already running, and read their results rather than retrying the cancel. - Check usage afterwards; the cancel page does not describe refunds, so verify what you were charged instead of assuming.
Cancel in a batch loop
When a whole wave is wrong, loop over the ids you stored and cancel each one, treating a 409 job_generation_already_started as information rather than an error. Count how many were canceled and how many had already started; the second number is what you will still be billed for and what you should still download. Run the loop with the key that created the jobs, because a different member's key cannot touch them.
Pair this with the queue limits for your plan. On the Free plan only one job processes at a time, so most of an over-eager batch is still queued and cancelable. On a plan with higher concurrency more of the batch is already running by the time you notice.
Sources
Related posts
More in Developers
- Cancel a Format run: cancel_effect canceled vs no_op, and the bill
Cancel is idempotent. cancel_effect says canceled or no_op, a canceled run never sends a webhook, and generation that finished is still billed.
- Cap Sume spend from an agent loop: dry_run, max_spend_usd and run caps
Four optional guards cap what an automated Sume caller can spend: dry_run, max_spend_usd, generation_spend_cap_usd on Formats, and a balance check.
- Caption design colors: hex, rgb(), rgba() or transparent only
Sume caption design colors take hex, rgb(), rgba() or transparent. Other CSS syntax is rejected at request time, so a bad color costs nothing.
- Captions out of sync with the audio: check STT word times and offsets
Captions running early or late usually trace to an unapplied offset. How Sume STT word times work, which offset to add, and a Python merge that applies it.
Written by Sume