Errors
Every error is JSON with a stable error code and sometimes a hint or extra fields:
json
{ "error": "insufficient_credits", "priceCents": 2 }
Match on error, not on the HTTP status text. Calls that fail are never charged.
#Auth and accounts
| Status | error | What to do |
|---|
| 401 | api_key_required | Send Authorization: Bearer <key>, or pay with x402 |
| 401 | invalid_api_key | The key is wrong or revoked. Create a new one |
| 401 | invalid_credentials | Wrong email or password |
| 401 | session_expired | Log in again |
| 403 | bad_origin | Browser request from a site that is not allowed |
| 409 | email_taken | That email already has an account; log in instead |
| 409 | too_many_keys | 20 active keys max; revoke one first |
| 400 | invalid_email / invalid_password | Password needs 12+ characters |
#Calling APIs
| Status | error | What to do |
|---|
| 400 | invalid_input | The body does not match the API's schema. The response lists each issue |
| 400 | invalid_json | The body is not a JSON object |
| 400 | invalid_idempotency_key | 8 to 64 characters: letters, digits, _, - |
| 402 | insufficient_credits | Add credits. priceCents says what the call costs |
| 402 | payment_required | x402: pay the accepts requirements and retry with X-PAYMENT |
| 402 | payment_invalid | x402: see reason (for example wrong_network, invalid_exact_evm_signature) |
| 402 | settlement_failed | x402: the payment did not settle; retryable: true. No result was returned |
| 404 | unknown_api | Check the id in the catalog |
| 413 | body_too_large | Max 64 KB |
| 429 | rate_limited | Slow down; retry after a short wait |
| 502 | upstream_error and similar | The data source failed. Not charged; retry later |
| 503 | not_configured | That API's provider is not set up right now. Not charged |
| 503 | facilitator_unavailable | x402 payment service down; retry. Not charged |
#Top-ups and plans
| Status | error | What to do |
|---|
| 400 | invalid_usd | 1 to 1000, at most 2 decimals |
| 400 | invalid_plan | Use solo or builder (see GET /v1/plans) |
| 400 | invalid_tx_hash | 0x + 64 hex characters |
| 404 | tx_not_found | Not mined yet, or sent on the wrong network. Retry in a minute |
| 404 | intent_not_found | Create an intent first and send its exact amount |
| 409 | pending_confirmations | Seen on-chain; waiting for 3 confirmations. Retry shortly |
| 409 | intent_already_claimed / tx_already_used | That payment was already credited |
| 422 | no_matching_transfer | The transaction does not send USDC to payTo |
| 422 | outside_intent_window | Paid before the quote or after it expired (24 h). Contact us |
| 422 | tx_failed | The transaction reverted on-chain |
| 429 | too_many_open_intents | 10 open quotes max; pay or let some expire |
| 503 | topup_disabled | Top-ups are paused |
#Coupons
| Status | error | Meaning |
|---|
| 400 | invalid_code | Codes are 4 to 32 letters, digits or dashes |
| 404 | coupon_not_found | No such code |
| 409 | already_redeemed | Each account can use a code once |
| 410 | coupon_expired / coupon_used_up / coupon_disabled | The code no longer works |
| 403 | new_accounts_only | This code is for accounts created after it |