What happens at zero credits mid-batch: 402 on Sume
When a Sume balance cannot cover a generation the API returns 402 insufficient_credits. Failed jobs are refunded before capture. Cap a batch locally.

When the balance cannot cover a generation, Sume returns HTTP 402 with the error code insufficient_credits, and the job is not accepted. A job that fails or is canceled before generation starts is refunded before capture. So a batch that runs out of credit stops at the first rejected submit, not halfway through a clip.
The 402 case
The errors page lists 402 insufficient_credits as: the balance is not sufficient for the requested generation. The catalog's reservation policy explains the mechanics: at submit time the estimated amount is stored in USD micros, rounded up to cents for the balance check, captured on completion, and refunded when a job fails or is canceled before generation.
The practical effect is that the balance check is against the estimate of the job you are submitting plus the holds of jobs already in flight. A 100-clip batch can therefore fail at clip 80 even if the balance looked large at the start.
| Situation | What Sume does | What you do |
|---|---|---|
| Balance below the job's estimate | 402 insufficient_credits | Add funds or reduce the request cost |
| Too many requests | 429 rate_limited, with retry-after | Back off, reuse the Idempotency-Key |
| Workspace queue full | 429 queue_full | Wait for a job to finish or cancel one |
| Job fails or is canceled before generation | Refunded before capture | Retry with the same key if retryable |
| Job category quota | Add funds, or decrease the request cost | Check the job error metadata |
Cap it yourself
The cheapest guard is a local counter. For 8-second Seedance 2.5 clips at 720p, each is 8 x $0.5778 = $4.6224. With a $100 cap, 21 clips cost $97.07 and a 22nd would reach $101.69, so the loop stops after 21.
The script below does that. It refuses to run without a key, keeps a running estimate, stops at the cap, and also stops on any HTTP error, including 402. An Idempotency-Key per clip is there so a retry of the same submit does not create a duplicate.
After the stop
Check the jobs you did submit with the job status endpoint, then top up and resume from the next index. Keep a record of which indexes were accepted so you resume from the next one; deterministic keys (batch-0 to batch-99) make retries of the same index safe to attempt.
Queue behavior is separate: a full queue returns 429 queue_full, not 402. Full concurrency alone is not an error while queue capacity remains.
A second scenario
Size the cap for a different clip. For 8-second 720p clips at $4.6224 each, a $250 cap allows $250 / $4.6224 = 54.08, so 54 clips costing $249.6096. If you also want a 10 percent reserve for retakes, set the loop cap to $225 and it stops at 48 clips ($221.88). Change PRICE and CAP in the script to match your plan.
A local cap with a stop on 402
A minimal loop using only the standard library and a $100 cap:
import asyncio, os, urllib.request, urllib.error, json
KEY = os.environ.get("SUME_API_KEY", "")
PRICE = 0.5778 * 8 # seedance-2.5, 720p, 8 s
CAP = 100.0
def submit(i):
body = json.dumps({"model": "seedance-2.5", "prompt": f"clip {i}",
"resolution": "720p", "duration": 8, "mode": "async"}).encode()
req = urllib.request.Request("https://api.sume.com/v1/video-router/generate", body,
{"Authorization": f"Bearer {KEY}", "Content-Type": "application/json",
"Idempotency-Key": f"batch-{i}"})
return urllib.request.urlopen(req).status
async def main():
if not KEY:
raise SystemExit("SUME_API_KEY is empty")
spent = 0.0
for i in range(100):
if spent + PRICE > CAP:
print("local cap reached at", i); break
try:
await asyncio.to_thread(submit, i)
spent += PRICE
except urllib.error.HTTPError as e:
print("stopped:", e.code); break
print("held about", round(spent, 4))
asyncio.run(main())Reproduce the numbers
Open https://api.sume.com/v1/catalog, which needs no key, and find the entry for the product. Each model_pricing row carries price, unit, pricing_basis and the estimated, minimum and maximum cents. Multiply the unit price by your quantity and round only at the end. The catalog also has applied_* fields that include an agent fee of 550 basis points; the figures in this post use the base prices.
Sources
Related posts
More in Pricing
- Where Sume documents plans, wallet and rates: which page answers what
Eight billing questions mapped to the docs page that answers each: the wallet, top-ups, list x 1.25, plan concurrency, 402 vs 429 and refunds, read 2026-10-09.
- Why a 5-second Wan 3.0 480p job reserves 32 cents on Sume
Sume reserves the estimated price at submit and rounds up to a whole cent: 5 x $0.0625 = $0.3125 becomes 32 cents. Six worked examples from the catalog.
- Why Seedance 2.5 costs 4.6x Wan 3.0 per second at 720p
At 720p Seedance 2.5 is $0.578 per second on Sume and Wan 3.0 is $0.125. The gap comes from billing by video tokens (21,600 per second) versus a flat rate.
- Does audio off make AI video cheaper? Kling 3 yes, Wan 3.0 no
Turning generate_audio off cuts Kling 3 by a third on Sume but changes nothing on Wan 3.0, Seedance 2.5 or Omni. Which rows price sound, with a 5 s example.
Written by Sume