POST /v1/runs answers 402 insufficient_credits when your organization’s credit cannot cover the run’s hold. This page is for anyone running OpenType unattended: it explains the exact rule, what the refusal leaves behind (nothing), and how to write a client that stops cleanly, tells a person, and resumes with the same Idempotency-Key once credit is back.
The rule
Every run holds its spend ceiling, 20,000 micros ($0.02), from admission until it settles. Before a run is admitted, the server checks:balance_micros from GET /v1/billing, which already has the holds of runs in flight subtracted. So:
- You need at least 20,000 micros available to start a run, even when the run will cost 19 micros once it settles.
- Concurrency counts. Twenty runs in flight hold 100,000 micros (0.10 of credit and twenty runs in flight, the twenty-first run is refused even though the settled costs would be tiny.
- The check happens late in admission, after the body, scope, idempotency key and quota are checked. A
402means the request itself was valid.
What a 402 leaves behind
- No run. The run and its hold are rolled back. Nothing is charged, and nothing appears in
GET /v1/runsor the usage ledger. - The
Idempotency-Keyis still free. Retry with the same key and the same body once credit is back; it is admitted as a new run. You do not need to mint a new key after a402. - An auto-recharge attempt is queued. If auto-recharge is on and a card is saved, the refusal triggers a background charge (at most one per organization per clock hour). The refused request is not held for it: send it again after the credit has landed.
- Replays are never refused for credit. If the key already owns a run, the server returns that run (
200or202) without checking the balance.
Resolve it
1
Check the balance
GET /v1/billing with a billing_read key. Read balance_micros, auto_recharge and has_payment_method.2
Add credit
Buy credit with
POST /v1/billing/checkout or the console Billing page (1,000). The credit arrives after the payment succeeds, as a purchase transaction. See Credits and billing.3
Or let auto-recharge land
If auto-recharge is on, wait for a new
purchase row described Auto-recharge. If has_payment_method is false, no charge can happen: add a card in the billing portal.4
Retry with the same key
Send the same body with the same
Idempotency-Key.Code pattern
Treat402 as a stop signal for the whole queue, not as a per-request retry. Retrying in a tight loop only produces more 402s. The pattern:
- On
402, pause every worker that sends runs. - Alert a person once, with the
request_id. - Poll the balance until at least 20,000 micros per run you plan to have in flight is available.
- Resume, re-sending the refused requests with their original keys.
GET /v1/billing, which needs billing_read. Every role holds it, so create the key for this client with runs_write and billing_read, or use a second read-only key for the poll.
waitForCredit with the number of workers, so the balance covers every hold they will take at once.
Prevent it
- Turn on auto-recharge with a threshold above one charge’s worth of spend and an amount above your busiest hour. See Auto-recharge.
- Watch the balance. Poll
GET /v1/billingon a schedule and alert whenbalance_microsfalls below a floor you choose, before runs start failing. - Size the balance for concurrency. Keep at least 20,000 micros per run you allow in flight.
402 versus 429
Both refuse a run before any model call, and both leave the same key reusable. They mean different things:Related
- insufficient_credits - the reference entry for this code.
- Credits and billing - read the balance and buy credit.
- Auto-recharge - top up automatically so runs do not stop.
- Idempotency - why the same key is safe to reuse after a
402. - Error handling - how
402fits in the full retry policy.