402 insufficient_credits: read required and available credits
The Sume 402 body gives details.required_credits and details.available_credits, whole credits. Compute the shortfall in Python and stop a batch cleanly.

When a Sume paid request returns 402 insufficient_credits, the error body tells you the exact gap: details.required_credits is what the request needs and details.available_credits is what the workspace has now, both as whole credits. Subtract one from the other to get the shortfall, stop submitting, and retry only after credits are added (docs.sume.com, read 2026-10-13).
Sume answers this before any provider work starts, so a 402 at submit means nothing ran. The docs say all usage is in credits, so the body carries no dollar or cents field to convert.
What does the 402 body contain?
The envelope is the standard Sume error object with a request_id. On Format runs it also carries next_action: "add_funds". An organization workspace without a provisioned wallet gets a different code, organization_wallet_not_provisioned, with the same details.
| Field | Meaning | Source page |
|---|---|---|
| error.code | insufficient_credits | Errors and rate limits |
| error.details.required_credits | Credits the request needs | Errors and rate limits |
| error.details.available_credits | Credits the workspace has now | Errors and rate limits |
| error.next_action | add_funds (Format runs) | Formats errors and spend |
| error.code (org, no wallet) | organization_wallet_not_provisioned | Errors and rate limits |
How do I compute the shortfall in Python?
This helper takes the HTTP status and raw body, returns the missing credits for an insufficient_credits error, and returns None for anything else. It uses only the standard library.
With the documented example body (150 required, 40 available) it returns 110.
import json
def shortfall(status: int, body: str):
"""Return missing credits for a 402 insufficient_credits, else None."""
if status != 402:
return None
err = json.loads(body).get("error", {})
if err.get("code") != "insufficient_credits":
return None
d = err["details"]
return max(0, d["required_credits"] - d["available_credits"])What should the caller do next?
Treat the 402 as a stop signal, not a retry signal. The Formats docs say that if you retry before you add credits, you get the same answer. Credits come from a plan upgrade, or from a purchase on a team workspace; buying credits is a dashboard operation, not an API call.
- Stop launching new submits in the batch and record the
request_idof the 402. - Log the shortfall so a person knows how many credits to add.
- After credits arrive, resubmit with the same
Idempotency-Key. A failed create releases its key on Format runs. - Do not confuse it with
429 queue_fullor429 rate_limited: those are retried with backoff, a 402 is not.
Why not parse the message text?
The message is for people and can change. Branch on the HTTP status and error.code, and read numbers only from details. The Formats docs make the same point for every code.
Sources
Related posts
More in Developers
- k6 2.3 --once and --scenario: smoke-test the Sume API without spend
Use k6 --once and --scenario for a Sume API smoke test that costs nothing: models, a deliberate 400, and a paced balance read that counts 429s.
- Kling 4 or Vidu Q4 on Sume: model_not_found and what to call
Sume has no kling-4 or vidu-q4 row, so a submit with those ids fails with 404 model_not_found. Call kling-3, wan-3.0 or sume/auto. Read 2026-10-13.
- Launch-day checklist before moving off kling-3 on Sume
Before you swap kling-3 for a newer Kling or another family, check the catalog, 1080p-only output, 4-15 s, no references, and ratio support. Read 2026-10-13.
- LinkedIn Posts API video post body: the fields and a Python builder
A LinkedIn video post needs author, commentary, visibility, distribution, a urn:li:video media id and lifecycleState PUBLISHED. Version 202510 sunsets Oct 15.
Written by Sume