Reserve, capture, refund: a 20-clip batch with 3 failures, 2 cancels
Worked example of how a Sume balance moves across a 20-job batch when 3 jobs fail and 2 are canceled while queued: what is held, captured and released.

Across 20 ten-second Wan 3.0 clips at 720p ($1.25 each), Sume holds $25.00 at submit. If 3 jobs fail and 2 are canceled while still queued, the 15 that completed capture $18.75 and the other $6.25 is released. The balance is touched at three moments: submit, completion, and failure or cancel.
That timeline comes from the cancellation-and-billing section of Generation admission: paid generation reserves the estimate when accepted, a success captures it, and failed jobs and cancellations before capture release or refund it.
The balance step by step
| Moment | Jobs | Held | Captured |
|---|---|---|---|
| After 20 submits | 20 accepted | $25.00 | $0.00 |
| 2 canceled while queued | 18 left | $22.50 | $0.00 |
| 3 jobs fail | 15 left | $18.75 | $0.00 |
| 15 complete | 0 pending | $0.00 | $18.75 |
Cancel only works early
Cancellation succeeds only before generation starts. After that, POST /v1/jobs/{id}/cancel returns 409 job_generation_already_started with details.cancelable: false, and the job runs to a normal end. A cancel on an already canceled job is idempotent.
What to record
- The job id for every accepted submit, so a crash does not orphan a hold.
- The terminal
sume_statusper job, which is what turns a hold into a charge or a refund. - The
request_idof any failed submit, for support.
Reading the ledger
Use GET /v1/balance and GET /v1/usage to check the numbers rather than trusting the arithmetic above. The balance shows what is spendable, and the usage ledger shows the entries behind it, so you can match every captured amount to a job id. If a held amount seems to linger, the usual cause is a job that is still queued or processing, not a leak.
- A job in
processingkeeps its hold until it reaches a terminal state. - A failed job releases its hold; the job error tells you the category and the next action.
- A rejected admission, such as
queue_full, releases or refunds the reservation for that attempt.
Keep the arithmetic as a test in your own code: for any batch, held plus captured plus released should equal what you reserved at submit. When it does not, look for jobs whose terminal status you never read.
Sources
Related posts
More in Developers
- Retry a timed-out Omni Flash submit without paying twice (Node)
Node 18+ code that retries a Gemini Omni Flash 1.1 POST to Sume's /v1/videos on timeout or 429 with one Idempotency-Key, so a retry returns the same job.
- Retry a timed-out POST /v1/videos with one Idempotency-Key, pay once
A Python submit wrapper that retries network errors, 429 and 5xx with a stable Idempotency-Key, so a replay returns the original job instead of a second charge.
- Review a 30-second Wan 3.0 clip: video inspect caps at 24 stills
Video inspect returns at most 24 stills per call, so a 30-second clip needs a sample rate of 0.8 fps or an explicit list of 24 times. Python builds the request.
- Rotate the Sume webhook secret without dropping events
After POST /v1/webhooks/signing-secret/rotate, Sume signs with both secrets for 24 hours. How verifyWebhook handles the two-entry header, and the deploy order.
Written by Sume