Preflight a mixed 30 s batch: 2 Seedance and 4 Wan needs $49.67
Sum the reserve for two Seedance 2.5 720p clips and four Wan 3.0 720p clips (49,668,000 micros), compare with GET /v1/balance in integers, then submit.

Two 30 s Seedance 2.5 clips at 720p ($17.334 each) and four 30 s Wan 3.0 clips at 720p ($3.75 each) reserve $49.668 at submit, which is 49,668,000 USD micros. Read GET /v1/balance, compare the integer available_amount_usd_micros, and a 402 insufficient_credits never lands in the middle of the batch.
The reserve, line by line
Six jobs also fit inside the Free plan's 6 accepted jobs (1 processing plus 5 queued), so the batch is not blocked by admission on any plan.
A 402 means no job was started for that request. Earlier jobs in the batch are already reserved, which is why checking first is cleaner than failing at job five.
| Line | Clips | Rate per second | Per clip | Subtotal |
|---|---|---|---|---|
| seedance-2.5 720p, 9:16 | 2 | $0.5778 | $17.334 | $34.668 |
| wan-3.0 720p | 4 | $0.125 | $3.75 | $15.00 |
| Batch total | 6 | $49.668 |
The preflight
The balance response is wrapped as data.balance. Keep the amounts as integers so there is no float comparison.
import os
import requests
H = {"Authorization": f"Bearer {os.environ['SUME_API_KEY']}"}
need_micros = 2 * 17_334_000 + 4 * 3_750_000 # 49_668_000
r = requests.get("https://api.sume.com/v1/balance", headers=H, timeout=30)
r.raise_for_status()
bal = r.json()["data"]["balance"]
have = bal["available_amount_usd_micros"]
if bal["state"] == "empty" or have < need_micros:
raise SystemExit(f"need {need_micros} micros, have {have}")
print("ok to submit 6 clips")Gotchas
The check is advisory: other clients on the same workspace can spend between your read and your first submit. Keep the 402 handler anyway, and send an Idempotency-Key on every submit so a retry cannot double-book.
Estimates from the pricing code are a forecast. The poll's usage.cost is the receipt, so compare the two after the first job.
Sources
Related posts
More in Developers
- Fresh Idempotency-Key per proxy call: why a Sume retry bills twice
If your server proxy mints a new Idempotency-Key on every request, a browser retry becomes a second paid Sume job. Forward the client's key instead; TypeScript.
- Python asyncio loop for a Sume job: next_poll_after_seconds
A runnable httpx and asyncio loop for GET /v1/jobs/{id}/status that honors next_poll_after_seconds, backs off otherwise, and leaves the job running on timeout.
- Python cost cap for a mixed media job: round up, then refuse
A 25-line Python estimator with Decimal prices that rounds the total up to the cent, as Sume's reservation does, and exits before submit if it is over your cap.
- Python httpx 429 handler for Sume: retry-after, then ratelimit-reset
A small async Python wrapper for the Sume API that waits on retry-after, falls back to ratelimit-reset, and never retries a POST that lacks an Idempotency-Key.
Written by Sume