Compare GET /v1/balance micros with a clip total, in integers
Balance comes as USD micros and cents. A 30 s Seedance 720p clip is 17,334,000 micros, 1,733 cents rounded down. Integer compare, plus the expiring-soon fields.

GET /v1/balance returns the amount as available_amount_usd_micros and as rounded-down available_amount_usd_cents, and the cents value hides money: a 30 s Seedance 2.5 clip at 720p is $17.334, which is 17,334,000 micros but only 1,733 cents. Compare in micros, as integers, and a balance of $17.33 will not pass a check for $17.334.
Micros versus cents
One US dollar is 1,000,000 micros. Converting a clip total to micros makes the compare exact, and rounding down to cents is how the API reports the cents field.
The response is wrapped as data.balance and also carries state (funded or empty) and an expiration summary.
| Clip | Total | Micros | Cents, rounded down |
|---|---|---|---|
| wan-3.0 720p, 30 s | $3.75 | 3,750,000 | 375 |
| gemini-omni-flash-1.1 1080p, 10 s | $1.875 | 1,875,000 | 187 |
| seedance-2.5 720p, 30 s, 9:16 | $17.334 | 17,334,000 | 1,733 |
| seedance-2.5 480p, 30 s, 9:16 | $8.06031 | 8,060,310 | 806 |
The check
The expiring-soon fields tell you how much of the spendable balance leaves soon. They are informational: the credits are still spendable now.
import os
import requests
need = 17_334_000 # 30 s Seedance 2.5, 720p, 9:16
r = requests.get(
"https://api.sume.com/v1/balance",
headers={"Authorization": f"Bearer {os.environ['SUME_API_KEY']}"},
timeout=30,
)
r.raise_for_status()
bal = r.json()["data"]["balance"]
exp = bal["expiration"]
print("available:", bal["available_amount_usd_micros"])
print("expiring in", exp["expiring_soon_days"], "days:",
exp["expiring_soon_amount_usd_micros"])
print("enough" if bal["available_amount_usd_micros"] >= need else "top up")Gotchas
The cents field is rounded down and available_credits is a legacy rounded cent amount, so neither is safe for an exact compare. Amounts exclude expired, reserved, captured and depleted credits, so a job in flight already lowered the number.
A balance that passes the check can still hit 402 if another client spends first. Keep the handler.
Sources
Related posts
More in Developers
- Contract test for 1:4, 4:1, 1:8, 8:1: pytest on /v1/images/models
A 12-line pytest that fails CI if Sume stops listing the Nano Banana 2.1 strip ratios. It reads GET /v1/images/models, so it generates nothing.
- Video Router body to /v1/videos: frame_images, input_references
Map Video Router image_url, end_image_url and reference_image_urls to /v1/videos frame_images and input_references, with a Node converter.
- Count queued and processing jobs with GET /v1/jobs before a wave
Page GET /v1/jobs with status=queued and status=processing, subtract from concurrency_limit, and submit only that many Seedance 2.5 or Omni clips.
- createSumeClient sends x-api-key only: an extra header gives 401
The Sume API accepts Bearer or x-api-key but rejects both at once with 401. A fetch wrapper for createSumeClient that drops the extra header, tested offline.
Written by Sume