Stop an Omni draft batch at $5: sum usage.cost from each poll

A Python loop that submits 360p Omni drafts one at a time, adds the Sume usage.cost of each finished job, and stops before the next one would cross a $5 cap.

5 min readSume
All posts

To stop an Omni draft batch at $5 on Sume, submit one job at a time, wait for it, add its usage.cost to a running total, and skip the next submit when the total plus the next job's estimate would pass the cap. The poll response of /v1/videos reports usage.cost as the Sume billable amount. A 10-second 360p draft is about $0.375 in the worked example below, so $5 buys about 13 of them.

Why one at a time

At submit, Sume reserves the estimated amount, and a successful completion captures it (Sume docs: Generation admission, read 2026-10-05). If you submit 40 drafts at once, 40 reservations are open at once, and the cap is not yours to enforce in code. A sequential loop gives the cap a meaning. It costs wall-clock time; Google's 360p draft mode is described as up to 60% faster than 720p, which helps (Google, read 2026-10-05). If you need parallel drafts, bound the fan-out by the cap divided by the per-job estimate.

The loop

EST is the per-job estimate you set from the catalog. The example uses $0.375 for 10 seconds at 360p; replace it with the live number.

Where the cap number comes from matters. Pick it from the budget for the whole project, then split it: drafts first, finals second. A common split is to spend at most a third of the cap on drafts, because Google describes the 360p mode as a third of the cost of standard 720p, so the draft pass of an entire storyboard should be small beside the finals.

Treat the estimate constant as a placeholder. Read the live per-second rate for the model and resolution from GET /v1/videos/models and multiply by the clip length before the loop starts, so a price change does not silently move your cap.

Last, handle errors. A 402 means the balance cannot cover the reservation, and a 429 means a queue or rate limit. Neither is a reason to retry in a tight loop. Stop the batch on 402, and wait and retry once on 429 with the same Idempotency-Key, which replays the original job if the first call actually landed.

Print the running total on every line, as the loop does. When a batch stops early, the last line is your report: how many drafts you got, and how much of the cap is left for finals.

import os, time, requests

URL = "https://api.sume.com/v1/videos"
AUTH = {"Authorization": f"Bearer {os.environ['SUME_API_KEY']}"}
CAP, EST = 5.00, 0.375
prompts = ["A kettle boils on a stove", "Rain on a window at night",
           "A cyclist crosses a bridge at dawn"]

spent = 0.0
for i, p in enumerate(prompts):
    if spent + EST > CAP:
        print("cap reached, stopping at", i)
        break
    body = {"model": "gemini-omni-flash-1.1", "prompt": p,
            "resolution": "360p", "duration": 10, "aspect_ratio": "16:9"}
    job = requests.post(URL, json=body,
                        headers={**AUTH, "Idempotency-Key": f"batch-{i}-v1"}).json()
    while True:
        s = requests.get(job["polling_url"], headers=AUTH).json()
        if s["status"] in ("completed", "failed", "cancelled"):
            break
        time.sleep(5)
    spent += (s.get("usage") or {}).get("cost", 0) or 0
    print(i, s["status"], round(spent, 4))

What the total means

A guard in your code is not a platform limit. If you want a hard spend limit on the Sume side, the MCP tools offer max_spend_usd on paid calls; for plain REST, this loop and a low balance are your controls.

  • A failed or cancelled job is refunded, so it adds nothing you owe. The loop adds whatever usage.cost reports.
  • The loop's total is Sume's billable amount, not the provider's price. For the account-level view, GET /v1/usage?job_id=... folds every ledger row for one job into a summary (Sume docs: Usage, read 2026-10-05).
  • A crash mid-loop loses the running total. Write it to a file after each job, and use the batch index in the Idempotency-Key so a restart does not double-submit job 3.

Sources

Related posts

More in Developers

All Developers posts

Written by Sume