2xx has this body:
{
"error": {
"type": "invalid_request_error",
"code": "parameter_invalid",
"message": "Too small: expected number to be >0",
"param": "amount",
"request_id": "8f0c2b1e-4a7d-4c1e-9b8a-2f6d3e5a1c90"
}
}
string
required
The category of error. One of the values in the table below.
string
required
A short, stable identifier for the specific error.
string
required
A human-readable explanation. It can change; do not match on it.
string
The request parameter the error relates to, when there is one.
string
required
The id of the request. Include it when you contact Payra support.
Request-Id header with the same id, except a replay, whose body
keeps the original request’s id.
Error types
| HTTP | type | Common codes | What to do |
|---|---|---|---|
| 400 | invalid_request_error | parameter_invalid, idempotency_key_invalid, payment_method_session_inactive, payment_method_session_used, card_not_tokenized, bank_account_not_tokenized, ach_authorization_required, ach_terms_version_unsupported, pad_terms_version_unsupported, payment_provider_not_configured, payment_method_unusable, webhook_endpoint_limit_reached, payment_not_refundable, refund_amount_exceeds_balance, terminal_busy, payment_not_cancelable, terminal_checked_out, terminal_confirmation_declined, terminal_confirmation_timed_out, terminal_confirmation_cancelled | Fix the request. param names the field. payment_method_session_inactive on a session that has not been confirmed yet: let Elements confirm it, then retry with a new Idempotency-Key; an expired or canceled session, or one that succeeded more than 30 minutes ago, needs a new one. payment_method_unusable: the payment method was already spent, expired, or detached from its customer; collect another. card_not_tokenized / bank_account_not_tokenized: card or account details reached a session’s confirm in the clear; submit them through Elements, the only way a Canadian account is accepted (where Payra enabled it, a US account your server holds can go to POST /payment-methods instead). ach_authorization_required: the bank account payment method carries no accepted ACH authorization; collect the account again through Elements. ach_terms_version_unsupported / pad_terms_version_unsupported: the accepted ACH authorization, or a Canadian account’s pre-authorized debit agreement, is a version this server no longer defines; reload Elements. payment_provider_not_configured: card payments, ACH debits, or Canadian pre-authorized debits are not set up for the workspace (a Canadian debit is refused when the session is created). payment_not_refundable: the payment is not succeeded (a bank debit still processing, say), or its processor transaction cannot be refunded. refund_amount_exceeds_balance: amount is more than what is left to refund; the message says how much. terminal_busy: the terminal is still on another payment; nothing was created, so retry with the same Idempotency-Key once it is free. payment_not_cancelable: only a terminal payment still waiting for the card can be canceled. terminal_checked_out: someone else has the terminal; the error’s checked_out_to says who, so check it in first or pick a free one. terminal_confirmation_*: a check-out with confirm_on_terminal was declined, timed out or was cancelled on the terminal’s screen; the terminal is as it was, so ask again or check out without confirming. |
| 400 | idempotency_error | idempotency_key_required, idempotency_key_reused | POST /payments, POST /refunds, and POST /payment-methods with bank details need an Idempotency-Key; use a new one for a different request. |
| 400 | card_error | card_expired | The collected card’s expiry month has passed. Collect another card. |
| 402 | card_error | card_verification_failed, card_authentication_failed, bank_account_verification_failed, card_declined, refund_failed | The processor refused the card, the bank account, the charge or the refund (card_authentication_failed: the cardholder’s bank refused to authenticate a card you asked to save with 3-D Secure). For a card or a bank account, collect the details again with a new session and retry (for bank details your server sent, send corrected details with a new key); for a charge, error.payment names the failed payment and error.decline_code says why (with error.decline_reason when the processor names the exact cause); for a refund, error.refund names the failed refund and error.failure_code says why; refund again later with a new key. |
| 401 | authentication_error | api_key_missing, invalid_api_key, publishable_key_not_allowed, api_key_environment_mismatch, client_secret_missing, invalid_client_secret | Check the key and the Authorization header. A browser must send the session’s client_secret. |
| 403 | permission_error | insufficient_scope, developer_integrations_disabled, refunds_disabled, customers_managed_by_erp, direct_bank_details_disabled | Use a key with the scope, or ask Payra to enable the API. refunds_disabled: refunds are switched off for this workspace. customers_managed_by_erp: the workspace’s customers come from its ERP integration and cannot be created through the API. direct_bank_details_disabled: the workspace does not take bank details sent from your server; ask Payra to enable it, then send the same request with the same Idempotency-Key. |
| 404 | invalid_request_error | resource_missing | Check the URL or the object id. |
| 409 | idempotency_error | idempotency_key_in_flight | Retry shortly with the same key. |
| 409 | api_error | conflict, refund_in_flight, checkout_session_payment_in_flight | The object changed under the request, or a webhook resend named an endpoint whose earlier delivery is still being retried. If you sent an Idempotency-Key, the answer is stored under it, so read the object back first, then retry with a new key; a conflict on a terminal payment’s cancel is the exception and can be retried with the same key. refund_in_flight: a refund of this payment is still pending; wait for it to succeed or fail before refunding again. checkout_session_payment_in_flight: the customer is paying on the checkout page you tried to expire; retrieve the session once that payment is done. |
| 429 | rate_limit_error | rate_limit_exceeded | Wait Retry-After seconds, then retry. |
| 500 | api_error | internal_error | If you sent an Idempotency-Key on a POST, the 500 is stored under it: read the object back (retrieve or list) before retrying with a new key. Quote request_id to support. |
| 502 | api_error | bank_account_tokenization_failed, terminal_unreachable, terminal_confirmation_unavailable | The bank details your server sent could not be put in Payra’s vault. None of the account was stored: retry with the same Idempotency-Key. terminal_unreachable: the terminal never answered a confirm_on_terminal check-out, likely offline; terminal_confirmation_unavailable: its screen cannot be asked for your account right now. In both cases the terminal was not checked out: check out without confirming, or retry later. |
type and code, never by message.