Errors
One error shape for every failure. Switch on its code, quote its request id.
Every failure has the same body:
{
"error": {
"type": "conflict",
"code": "invoice_not_open",
"message": "The invoice is paid; only an open invoice can be paid.",
"request_id": "req_4f1c9a2e7b3d4c5e8f9a0b1c2d3e4f5a"
}
}typeis a broad category, andcodethe specific reason. Both are stable: write your code againstcode.messageis for a person reading logs. It may be reworded at any time, so never match on it.request_idis also on every response, error or not, as theRequest-Idheader. Quote it when you write to us about a request.
Codes worth handling
| Status | Code | What to do |
|---|---|---|
| 400 | invalid_request, unknown_parameter | A field is missing, malformed, or not one the endpoint takes. The message names it. |
| 400 | invalid_amount, amount_too_large | An invoice is for $0.01 to $100,000.00, as a string with at most two decimals. |
| 400 | customer_email_required | The checkout needs a payer email, because the invoice names no customer. |
| 400 | customer_mismatch | The invoice is for another customer_email. |
| 400 | invalid_url | Return URLs must be https in live mode. |
| 400 | idempotency_key_required | Send an Idempotency-Key with this POST. |
| 401 | invalid_api_key | The key is missing, wrong or revoked. |
| 403 | live_access_required | Live mode opens once Volume activates the account. |
| 403 | account_suspended | A suspended account can read, but not create. |
| 403 | test_mode_only | A test helper was called with a live key. |
| 404 | invoice_not_found, checkout_session_not_found | No such object in this mode. A test object is invisible to a live key. |
| 409 | invoice_not_open | The invoice is already paid. Do not open another checkout for it. |
| 409 | idempotency_key_reuse_mismatch | The key was used for a different request. |
| 409 | no_payment_method | A test checkout can be paid only once the payer has chosen a coin. |
| 429 | too_many_requests | Wait for the Retry-After header's seconds, then retry. |
| 5xx | internal_error | Something failed on our side. Retry with the same Idempotency-Key. |
Another account's object is 404, exactly as a missing one is, so ids cannot be
probed.
Retrying
Retry a 429 after Retry-After, and a 5xx or a network failure with backoff. With
the same Idempotency-Key a retry cannot create anything twice. Do not retry a 4xx
other than 429 unchanged: it will fail the same way.
Rate limits
Requests are counted per key. Ordinary use is far below the limit; a refusal is
429 too_many_requests with a Retry-After header, in seconds, and the same number
as error.retry_after.