Errors
Updated:
The x402 API uses real HTTP status codes. Every error has the same JSON body, and retry_action tells your agent what to do next.
Error body
Name | Type | Description |
|---|---|---|
error | String | Error code, see the table below |
message | String | Short human-readable message |
retryable | Boolean | Whether repeating can help |
retry_action | String | What to do: |
retry_after_seconds | Integer | When to retry; equals the |
payment_state | String |
|
authorization_expires_at | String | Until when your authorization can still be executed; do not sign a new one before |
order_id, operation_id, poll_url | String | The order and the operation the payment belongs to, when they exist |
bound_wallet | String |
|
facilitator_reason | String | Reason of a payment check failure, from a fixed list, or |
detail | String | Details, for example the path of the invalid field: |
Responses with a new quote (quote_expired, payment_expired, quote_bound_to_other_wallet) also contain the quote fields and the PAYMENT-REQUIRED header.
{
"error": "payment_not_settleable",
"message": "The presented authorization can still be settled",
"retryable": true,
"retry_action": "wait_and_retry",
"retry_after_seconds": 512,
"payment_state": "unused",
"authorization_expires_at": "2026-11-02T10:16:00Z"
}Retry actions
retry_action | What to do |
|---|---|
| Sign the new requirements from this response ( |
| Send the same request with the same |
| In |
| Start over (new quote, new signature) not earlier than |
| Repeating the same request will not help |
| Contact support. Do not sign a new authorization |
Error codes
error | HTTP | retry_action | When |
|---|---|---|---|
| 402 |
| A paid endpoint was called without |
| 402 |
| The payment header is malformed or not x402 version 2 ( |
| 402 |
| The wallet does not have enough USDC. Top up the wallet and repeat the same request while the authorization is valid |
| 402 |
| The quote is expired or already paid, and your authorization has expired too. A new quote is in the response |
| 402 |
| The authorization expired unused or was cancelled. Nothing was taken. A new quote is in the response |
| 400 |
| Invalid field, unknown field, invalid JSON, body larger than 64 KiB; country, period, quantity, tier, package or options not available; a second residential package; rules of the specific endpoint |
| 400 |
|
|
| 403 |
|
|
| 403 |
| The wallet is blocked or on a sanctions list |
| 401 |
| No |
| 404 |
| The order does not exist, or the token is not valid for it |
| 404 |
| The top-up or the challenge does not exist, or the token is not valid for it |
| 409 |
| The same authorization (payer and nonce) came with different content |
| 409 |
| The quote is no longer valid, but your authorization can still be executed. Wait until |
| 409 |
| The payment is being reviewed by our staff |
| 409 |
| Another wallet has already used this quote. A new quote is in the response |
| 409 |
| Another payment for this quote is being processed |
| 409 |
| The body of the paid request does not match the quote, or a repeat of a paid authorization carries another request |
| 409 |
| Your wallet has already used this |
| 429 |
| A limit is exceeded (Limits) |
| 503 |
| The payment is still being processed. Repeat the same request in |
| 503 |
| The service is temporarily not accepting new payments |
| 503 |
| A temporary failure: the price, the catalog, the payment check or another service is unavailable |
| 500 |
| Unexpected error |
A wrong HTTP method returns 405 with the code invalid_request.
Every response from the service has the X-Request-Id header. Give it to support when you report a problem.