Reconcile a mixed project with GET /v1/usage: debited, held, refunded
How to read what one job or run really cost: debited, held and refunded fields, with the arithmetic for a project where one of six shots fails and is refunded.

To see what a mixed project cost, read GET /v1/usage with a job_id, run_id or thread_id, and quote summary.debited_usd. That field is what the wallet actually deducted. held_usd_micros is money still reserved and not yet spent, and refunded_usd_micros is money given back after a failure, a cancel or queue_full. Do not add up the ledger rows yourself; the docs say never to.
The three numbers
The usage summary folds over every ledger row the scope caused. Debited is the captured rows. Held covers reservations that are still open. Refunded is a reservation that Sume released. A refunded row keeps its hold amount in billable_amount_usd_micros, which is why summing raw rows overstates the cost. final: true means no hold is open, so the numbers will not move again.
A worked example
Take six 5-second wan-3.0 shots at 720p: $0.6250 each, $3.7500 reserved if all are accepted. Suppose shot 5 fails at the provider. The expected figures are below; they are arithmetic from list prices (catalog read 2026-10-08), not a recorded response.
| Moment | Held | Debited | Refunded | Final |
|---|---|---|---|---|
| All six submitted | $3.7500 | $0.0000 | $0.0000 | false |
| Shots 1-4 and 6 captured, shot 5 failed | $0.0000 | $3.1250 | $0.6250 | true |
| Shot 5 resubmitted and captured | $0.0000 | $3.7500 | $0.6250 | true |
Where to read it
Each shot is a job, so read the usage of the whole project by thread_id or run_id when one exists. For direct API calls, query each job_id and add the debited_usd values on your side. In the example the video step costs $3.1250 after the failure, and $3.7500 after the retry, while the $0.6250 refund is never spend.
For a project built from several runs, keep one table: step, job id, estimate, debited. After the last step, the sum of debited should match the drop in GET /v1/balance over the same window, apart from other work on the workspace. If the two differ, look for open holds (held_usd_micros) before you suspect a billing error.
A cap compares against reserved plus captured generation rows, which is a different total from debited. In a run receipt, usage.cap splits that into limit, counted and remaining. Use debited for cost reports and the cap fields for headroom.
Common reading mistakes
Three mistakes recur. First, quoting a receipt's billable amount as the cost: for a run it counts reserved and captured generation, and it excludes the agent's own LLM turn, so it is a cap measure and not an invoice. Second, summing raw rows, which counts a refunded hold as spend. Third, reading while a hold is open: if final is false, wait and read again.
The balance and the ledger are the billing records. Keep job ids for each step of the project so a single job_id read can answer the question 'what did shot 5 cost' without scanning the ledger.
Sources
Related posts
More in Developers
- Refresh 1,200 SKU video ads before Black Friday: waves by plan
On an empty workspace, 1,200 jobs take 300 submission waves on Free, 67 on Pro and 14 on Scale, using Sume's wave_size_hint of 75% of accepted capacity.
- Replace line 7 of 12 voiceover lines: one TTS job and a concat
Fixing one 180-character line of a 12-line voiceover costs $0.02 (one TTS job at the 1-cent floor plus a $0.01 concat) vs $0.12 to redo all 12. Read 2026-10-08.
- 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.
- 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.
Written by Sume