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.

5 min readSume
All posts

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.

Cancel behavior on a Sume video job (read 2026-10-07)
Job state when you cancelResultWhat to do
queued, generation not startedJob becomes canceledFix the request and resubmit with a new idempotency key
generation already started409 job_generation_already_started, details.cancelable falseLet it finish; read the result
already canceledSame canceled job returnedNothing; the call is idempotent
completed or failedNo cancel pathRead 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_started for 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

All Developers posts

Written by Sume