PAYMENT_REQUIRED
You're past the plan cap AND your credit balance is zero.
| Code | HTTP status | Retryable? |
|---|---|---|
| PAYMENT_REQUIRED | 402 | No |
What this means
PAYMENT_REQUIRED is returned when two conditions are true at once: your monthly plan quota has been exhausted, AND your credit balance is zero. Onto tries to bill plan first, then falls through to credits — only when both are empty does the call fail with 402. Free-tier users hit `RATE_LIMITED` instead because Free has a hard monthly cap (no credit overflow allowed).
When you'll see it
HTTP 402. Body always includes code: "PAYMENT_REQUIRED". Branch on code, never on the human-readable message — wording can change without notice; the code is the stable contract.
Example response
{
"status": "error",
"code": "PAYMENT_REQUIRED",
"message": "Plan quota exhausted and credit balance is 0"
}How to handle
Top up credits from app.buildonto.dev/read/billing (packs from $5 to $200) or upgrade to a higher subscription tier. Credits never expire and stack with any plan, so they're the right answer for spike handling. If you're consistently exhausting plan + credits, the plan upgrade is the cheaper long-term move.
Suggested handling in a Node client:
if (data.code === 'PAYMENT_REQUIRED') {
// Out of plan + credits. Don't retry blindly — escalate.
notifyOps('Onto quota exhausted; top up credits or upgrade plan');
throw new Error(data.message);
}Related errors
| Code | Status | What it means |
|---|---|---|
| RATE_LIMITED | HTTP 429 | Monthly request quota exceeded — your plan is hard-capped (typically Free). |
| CONCURRENT_LIMIT | HTTP 429 | Too many in-flight requests for your tier — backoff for ~1 second and retry. |
| PLAN_RESTRICTED | HTTP 403 | The action requires a higher plan tier — e.g. purchasing credits on the Free tier. |
See the full error index for the complete catalog with the handling switch statement covering every code at once.