Skip to main content
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:
Available credit is 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)betweenthem.With0.10) between them. With 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 402 means 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/runs or the usage ledger.
  • The Idempotency-Key is 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 a 402.
  • 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 (200 or 202) 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 (5to5 to 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

Treat 402 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:
  1. On 402, pause every worker that sends runs.
  2. Alert a person once, with the request_id.
  3. Poll the balance until at least 20,000 micros per run you plan to have in flight is available.
  4. Resume, re-sending the refused requests with their original keys.
The poll uses 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.
With several workers, share one paused flag between them and call 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/billing on a schedule and alert when balance_micros falls 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: