Sume video poll usage.cost: reserved while running, captured at end
The usage.cost number is the Sume billable amount: the reservation while a job runs and the captured amount once it settles. wan-3.0 at 720p, 10 s, as math.

usage.cost on a Sume /v1/videos poll is in dollars and is the Sume billable amount: list price times 1.25, rounded up to a cent. While the job is in flight it shows the amount reserved at submit, and after the job settles it shows what was captured. Read it as the cost of that clip, not as the account balance.
The arithmetic
Take wan-3.0 at 720p. The catalog lists it at $0.10 per second at that resolution. For a 10-second clip the list is $1.00, Sume bills 1.25 times that, so $1.25, and the cents round up to 125. At 15 seconds the product is $1.875, which rounds up to $1.88 (188 cents).
For models priced per video token, such as Seedance 2.5, the rule is the same (list x 1.25, ceil to cents), but the list amount comes from the token count, so use the grid values in the catalog instead of computing by hand. Seedance 2.5 at 720p, 9:16 and 10 seconds is 578 cents.
| Duration | List | x 1.25 | usage.cost |
|---|---|---|---|
| 5 s | $0.50 | $0.625 | 0.63 |
| 10 s | $1.00 | $1.25 | 1.25 |
| 12 s | $1.20 | $1.50 | 1.50 |
| 15 s | $1.50 | $1.875 | 1.88 |
Reading it in code
The field can be absent. A submit response never has it, and a poll only carries it once an amount exists. Treat null and a missing key the same way. Keep money as integer cents on your side, so 0.63 does not drift through a float.
from decimal import Decimal
def cents(poll: dict) -> int | None:
usage = poll.get("usage") or {}
cost = usage.get("cost")
if cost is None:
return None
return int((Decimal(str(cost)) * 100).to_integral_value())
# {"status": "in_progress", "usage": {"cost": 1.25}} -> 125 (reserved)
# {"status": "completed", "usage": {"cost": 1.25}} -> 125 (captured)What to show a customer
If your app resells clips, show the amount only when the job is completed. Before that, show nothing or a clearly labelled hold, because an in-flight amount is a reservation. Round for display with the same rule Sume uses (up to the cent), so your invoice lines match the poll.
If you charge a fixed price per clip, compare it with the usage.cost of the cheapest and the most expensive model you allow, and set the price from the high end.
Why the number can move
For a clip that succeeds, the reserved and captured amounts are normally the same, but read the field again after completed instead of caching the first value. Check the usage endpoint or the balance for the settled picture of spend, and use usage.cost for per-clip display only.
Reservation needs enough balance at submit. If the balance is short, the submit fails with 402 insufficient_credits; see the credits table. For the same arithmetic on a different clip, try the Sora replacement price table.
- Do not add up
usage.costof in-flight jobs as spent money. - Treat a missing
usageas unknown, not as zero. - Show cost only on
completedjobs in a customer-facing UI.
Sources
Related posts
More in Developers
- Validate a Gemini Omni Flash 1.1 request in Python before sending
A 28-line Python check for Sume's gemini-omni-flash-1.1 rules: 3-10 s, 10 reference images, 3 reference videos, no audio off, and edit mode exclusions.
- A Veo 3.1 call becomes a Sume Omni job in under 30 lines of Python
Replace a Veo 3.1 request with a Sume gemini-omni-flash-1.1 job: submit, poll every 30 seconds, download the mp4 and read usage.cost. Standard library only.
- Veo 3.1 previews end in 14 days: a dated checklist, Oct 8 to Oct 22
Google's three Veo 3.1 preview ids shut down on October 22, 2026. A day-by-day checklist from today, with the Sume model id and limits to test against.
- Vercel 800 s max duration: do you still need a Sume webhook?
Vercel Pro allows 800 s functions and a 30-minute beta. A Sume video job can still outlast one request, so use async or webhook mode and return in seconds.
Written by Sume