Troubleshoot billing recovery codes
Every billing 402 is one of four rungs on a single recovery ladder: your wallet ran out (INSUFFICIENT_BALANCE), a payment failed (PAYMENT_REQUIRED), the
wallet hit a hard block (INSUFFICIENT_FUNDS), or auto-top-up stopped topping
up (AUTO_TOPUP_PAYMENT_FAILED / AUTO_TOPUP_MONTHLY_CAP_REACHED). The
INSUFFICIENT_BALANCE page covers the
first rung; this page is the parent runbook for the rest.
Match on the
code field, not the HTTP status — every rung returns 402. A
PAYMENT_REQUIRED does not mean the wallet is empty: it means the recharge
attempt itself failed, so a top-up remains the fix but the diagnosis path is
different.1. The billing-recovery ladder
INSUFFICIENT_CREDITS is the deprecated alias on the wallet-exhausted rung and
PAYMENT_REQUIRED is the generic name the API returns for the
payment-failure rung — both are stable contract strings you can match on in
client code.
2. Detect the state — balance query and wallet-balance alerts
GET /api/v1/billing/balance is the single state query you gate retries on:
balance_cents— single most reliable detector. A low but positive balance withPAYMENT_REQUIREDorINSUFFICIENT_FUNDS402s means the pre-flight estimate is larger than your available balance (see the INSUFFICIENT_BALANCE branch table).outbound_paused/outbound_block_reason— distinguishes a wallet-exhausted ladder rung from a tenant-configured billing-alert pause/block (see billing-gate outbound blocks).
POST /api/v1/billing/alerts with threshold_type: "balance_floor") fires
email/SMS the moment balance drops below the floor you choose, so the first
402 never surprises you — see spend caps and budget
alerts.
3. Fix per code
PAYMENT_REQUIRED — update the payment method
- Open Billing and check Payment method: the saved card bank-declined the last auto-top-up (or the pay-by-link checkout you opened lapsed).
- Replace the saved card, or mint a new hosted checkout link
(
POST /api/v1/billing/balance/top-up) and complete it. - Retry the rejected send once, not repeatedly — the same code still fires while the method is in a dispute window.
INSUFFICIENT_FUNDS — fund the wallet
GET /api/v1/billing/balanceand readbalance_cents.- If it sits at or near zero: top up (one-off Stripe Checkout or crypto) and resend. The code is thrown fail-closed on the API side even when it is the only blocking rung — Verify fallback advance and bulk-verify surfaces name it explicitly.
- If it reads comfortably above zero, the estimate pre-flight on the specific
surface (a long call, an expensive destination) exceeded available balance;
gate the estimate (shorter
max_minutes) or top up past the estimate.
AUTO_TOPUP_PAYMENT_FAILED — fix the saved method, auto-recover
Auto-top-up recharges the wallet on a 15-minute tick once the balance crosses
threshold_minor. You get this code when the scheduled charge against the
saved default payment method is declined and auto-top-up was enabled.
- In Billing → Payment, replace the saved default method — the next tick re-runs the recharge with the new method, no manual re-arm required.
- Confirm with
GET /api/v1/billing/auto-topup(the returned config keepsenabled: true; only the charge fails, the config does not disable).
AUTO_TOPUP_MONTHLY_CAP_REACHED — raise or clear the cap
The optional max_monthly_minor ceiling auto-charges stop when hit, so the
wallet can run dry mid-month while the cap is enforced.
GET /api/v1/billing/auto-topupreturns the savedmax_monthly_minor.- Raise it in place:
PUT /api/v1/billing/auto-topupwith a largermax_monthly_minor(must remain ≥recharge_amount_minor). - To remove the cap entirely you must pass
"clear_cap": trueon the samePUT— omitting the field, or sending it asnull, preserves the saved cap (that is by design — a blanked form field cannot silently drop a limit). - If a manual top-up is safer for the rest of the month, use a one-off checkout and leave auto-top-up capped.
4. When to escalate
Open a support ticket when:- the ladder loops across several codes while
balance_centsreads well above the failing estimates — that points at a hold-ledger fault, not a funding fault. - an
AUTO_TOPUP_MONTHLY_CAP_REACHEDappears even though the savedmax_monthly_minorreadsnull(i.e. you never set a cap) — the platform guard is tripping a default it should not have. - a
PAYMENT_REQUIREDpersists across several payment-method swaps.
GET /me
organizationId), the exact code(s), and the checkout/payment reference from
the Billing ledger when payment failures are involved.
See also
- INSUFFICIENT_BALANCE (402) — the wallet-exhausted rung of this ladder
- Billing-gate outbound blocks — tenant-configured pause/block flags and provider faults
- Billing overview — wallet model, ledger, top-ups, invoices, auto-top-up
- Spend caps and budget alerts — wallet-balance alerts, spend ceilings, auto-cutoff
- Auto-top-up API — config read/write/cap-clear
- Error codes reference —
INSUFFICIENT_BALANCE,PAYMENT_REQUIRED,INSUFFICIENT_FUNDS,AUTO_TOPUP_PAYMENT_FAILED,AUTO_TOPUP_MONTHLY_CAP_REACHED