Errors
Failed requests return a non-2xx HTTP status and a JSON body with one error object:
{
"error": {
"type": "card_error",
"code": "no_eligible_terminal",
"decline_code": "card_not_supported",
"param": null,
"message": "No terminal can take this card.",
"request_id": "req_01J9ZQ4V8K2M3N5P7R9T1W3Y5F"
}
}
| Field | Meaning |
|---|---|
type |
The class of error; decide your handling on it. |
code |
A stable, machine-readable reason. May be null. |
decline_code |
For card declines, the normalized reason from the issuer or bank. |
param |
The request parameter at fault, when there is one. |
message |
A human-readable explanation for developers. Not stable; do not parse it and do not show it to customers. |
request_id |
The id of the request. Also in the Request-Id response header; quote it to support and find the request in Developers → Logs. |
payment_intent |
On a card error during confirm, the payment as it stands. |
HTTP status codes
| HTTP | Meaning |
|---|---|
| 200 | Success. |
| 400 | The request is invalid (invalid_request_error) or breaks a rule. |
| 401 | The API key is missing or invalid (authentication_error). |
| 402 | The request was valid but could not be carried out: a card decline, a fraud rejection or a balance problem. |
| 403 | Not allowed (permission_error): scope, IP allowlist, product, merchant state. |
| 404 | The object does not exist, or belongs to another merchant. |
| 409 | Idempotency conflict, or a change that is already pending. |
| 429 | Rate limited. Back off and retry. |
| 5xx | A problem on the platform or at the bank. Check the payment before you retry (see the idempotency guide). |
Error types
error.type |
Meaning |
|---|---|
card_error |
The card was declined or cannot be used (see decline_code). |
invalid_request_error |
The request is malformed or breaks a rule; fix the request, do not retry unchanged. |
api_error |
A problem on the platform or at a downstream system; safe to retry with the same Idempotency-Key. |
idempotency_error |
The Idempotency-Key was reused with a different body, or the first request is still running. |
authentication_error |
The API key is missing, malformed, revoked or of the wrong kind. |
permission_error |
The key or user is not allowed to do this (scope, IP allowlist, product, merchant state). |
rate_limit_error |
Too many requests; back off and retry. |
balance_error |
Your available balance does not cover the operation. |
fraud_error |
The payment was stopped by fraud screening. |
Error codes
The table below is generated from the API contract and lists every code the API documents. error.type follows from the class of the error; a few codes appear with more than one.
| Code | HTTP | Meaning |
|---|---|---|
non_secure_not_allowed |
400 | 3-D Secure was set to none but non-secure payments are not allowed for your account or this amount. |
payment_intent_unexpected_state |
400 | The payment is not in a state that allows this call (for example capturing a payment that is not requires_capture). |
no_eligible_terminal |
402 (card_error) | No terminal can take this card or payment; nothing was charged. |
installments_not_available |
402 (card_error) | No terminal runs the requested installment count for this card. Call the installment preview first. |
insufficient_available_balance |
402 (balance_error) | Available balance is too low (for a refund, payout or similar). |
fraudulent |
402 (fraud_error) | Fraud screening rejected the payment. |
idempotency_conflict |
409 | Same Idempotency-Key with a different request body. |
idempotency_in_progress |
409 | The first request with this Idempotency-Key has not finished; retry shortly. |
capture_failed |
502 (api_error) | The bank could not capture; the payment is unchanged and the call may be retried. |
void_failed |
502 (api_error) | The bank could not void; the payment is unchanged and the call may be retried. |
resource_missing |
404 | The object does not exist (or belongs to another merchant). |
parameter_invalid |
400 | A parameter has an invalid value; param names it. |
parameter_missing |
400 | A required parameter is missing; param names it. |
payouts_frozen |
403 | Payouts are frozen for your account; contact support. |
manual_payouts_not_allowed |
403 | Your account pays out on a schedule; manual payout requests are not enabled. |
amount_exceeds_refundable |
400 | The refund is larger than amount_refundable of the payment. |
card_data_in_unexpected_field |
400 | A card number was found outside payment_method_data[card]; the request is refused before anything is stored. |
card_data_in_url |
400 | A card number was found in the URL or query string; never put card data in a URL. |
card_vault_unavailable |
503 | The card vault is temporarily unavailable; retry with the same Idempotency-Key. |
token_invalid |
404 | The token or link is invalid or expired. |
password_too_weak |
400 | The password does not meet the strength rules. |
mfa_code_invalid |
400 | The one-time code is wrong or expired. |
invitation_not_accepted |
409 | The invitation has not been accepted yet. |
evidence_rejected |
400 | The dispute evidence was refused (closed dispute, too large or wrong type). |
amount_below_minimum |
400 | The amount is below the minimum allowed. |
settlement_account_unavailable |
403 | No approved settlement account is available for this operation. |
merchant_not_active |
403 | Your merchant account is not active (not yet approved, or suspended). |
currency_not_supported |
400 | The currency is not enabled for your account. |
payouts_not_configured |
403 | Payouts are not configured for your account. |
ip_not_allowed |
403 | The request came from an IP address that is not on your allowlist (see the authentication guide). |
product_not_enabled |
403 | The product is not enabled for your account (for example online card payments need the virtual POS product). |
website_not_registered |
403 | The website is not registered for your account. |
return_url_not_allowed |
400 | return_url is not a registered callback URL (see the 3-D Secure guide). |
webhook_url_not_allowed |
400 | The webhook url is not a registered callback URL. |
change_pending |
409 | An earlier change of the same kind still waits for approval. |
user_not_authorized |
403 | The user is not a company partner and holds no approved authorization for this role. |
billing_details_required |
400 | Billing details are required to confirm: name, address.line1, address.city, address.country. |
line_items_required |
400 | Line items are required for this account. |
line_items_amount_mismatch |
400 | The sum of the line items is not equal to amount. |
Card decline codes
On a card_error the decline_code says why. Show the customer a generic message ("your card was declined, try another card"); the exact reason is for your logs and your support team.
decline_code |
Meaning |
|---|---|
insufficient_funds |
The card has insufficient funds. |
do_not_honor |
The issuer declined without a specific reason. |
lost_card |
The card was reported lost. |
stolen_card |
The card was reported stolen. |
expired_card |
The card has expired. |
incorrect_cvc |
The CVC is wrong. |
invalid_card |
The card number or data is invalid. |
card_not_supported |
The card brand or type cannot be accepted. |
installment_not_supported |
The card or terminal does not support the requested installment count. |
authentication_failed |
3-D Secure authentication failed or was not completed. |
issuer_unavailable |
The issuer could not be reached; retry later. |
processing_error |
A processing error at the bank; retry later. |
fraudulent |
The issuer suspects fraud. |
limit_exceeded |
A card limit (amount or count) was exceeded. |
restricted_card |
The card is restricted. |
transaction_not_allowed |
The card does not allow this kind of transaction (for example online use). |
Decline codes are normalized: banks use many different raw codes, and the platform maps them to the list above. Declines are either hard (retrying the same card will not help, for example lost_card, stolen_card, expired_card) or technical (issuer_unavailable, processing_error; the customer may try again later).
Handling errors in code
- Branch on
error.typeanderror.code, never onmessage. - On
402 card_error, ask for another payment method and start a new attempt with a newIdempotency-Key. - On
5xxor a timeout, do not create a new payment: look the original up (by yourmetadatareference) and use the sameIdempotency-Keyonly when you received no response at all. - Log
request_idwith every failure.