Skip to main content
View as Markdown
Version: v2

Error Codes

When a payment fails, ODUS reports the reason as a standardized error code. Where the failure came from a payment processor, the processor-specific error is normalized into that same set — so regardless of whether the payment was routed through Stripe, Adyen, PayPal, or any other gateway, the error response uses the same codes. This lets you build a single error-handling path in your integration instead of mapping each processor's errors individually.

Error information is returned in the outcome object on the transaction.

note

These are declines — a request the API processed successfully, reporting a payment that did not go through. Usually the issuer refused it. Some codes instead report a payment that was never authorized against the payment method and cannot be by trying again; those carry declineType not_attempted. For requests the API refuses to process at all (validation failures, wrong resource state, missing permissions), see Error Responses.

The outcome object​

When a transaction fails, the response includes an outcome object with the following fields:

FieldTypeVisibilityDescription
statusstringPublicOperation result: success, partial, or failure.
errorCodestringSensitiveStandardized error code from the table below.
errorMessagestringSensitiveDetailed error message. May contain sensitive information (e.g. fraud).
safeErrorMessagestringPublicCustomer-safe error message that can be displayed in your UI.
declineTypestringSensitiveEither soft_decline, hard_decline or not_attempted.
retryStrategystringPublicRecommended retry strategy for the client.
processorCodestringSensitiveRaw error code returned by the payment processor.
processorMessagestringSensitiveRaw error message returned by the payment processor.
specialCodestring | nullPublicSpecial status codes such as confirmation_requested for 3DS redirects. null when no special status applies.
warning

Sensitive fields are only visible when using a secret API key. They are not returned to a checkout key, which is what the Checkout SDK uses. Never expose sensitive fields to the customer — use safeErrorMessage instead of errorMessage.

Decline types​

Every error code carries a decline type: whether the payment method was refused, and whether repeating the same attempt could work.

TypeMeaning
soft_declineThe payment may succeed if retried. The issue is potentially temporary or resolvable by the customer.
hard_declineThe payment method was refused and will not succeed on retry — it is blocked, restricted, or revoked.
not_attemptedThis payment was not authorized against the payment method, so the issuer refused nothing. The cause lies elsewhere — the stored payment method, your account, the request, the order, a policy rule, or a capture that already happened. Read errorCode for which, and the remedy. Repeating the same operation unchanged cannot succeed.

Error code reference​

The table below lists every standardized error code, grouped by decline type.

Moving from v1

Eight codes and the not_attempted decline type are new in v2. v1 reports each of those payments as a broader code with a different decline type, and for three of them a different retry strategy. If your integration branches on errorCode or declineType, see Codes added in v2.

Hard declines​

These are non-recoverable. Do not retry the same payment method.

CodeDescriptionRetry StrategySafe Message
fraud_suspectedThe processor flagged the transaction as potentially fraudulent.never_retryThe payment was declined. Please use a different payment method.
card_restrictedThe payment method or account is restricted — for a card, lost, stolen, or blocked by the issuer.never_retryThe payment was declined.
generic_hard_declineAuthorization was revoked or another non-recoverable decline occurred.never_retryThe payment was declined.
authentication_rejectedThe issuer's authentication server refused the authentication outright, or the card has already used up its allowed challenges.never_retryThe payment was declined. Please use a different payment method.

Soft declines — payment method issues​

The customer can resolve these by correcting or changing their payment method.

CodeDescriptionRetry StrategySafe Message
insufficient_fundsThe payment method does not have enough funds to cover the transaction.retry_after_delayThere aren't enough funds available for this payment. Please use a different payment method.
invalid_card_detailsThe payment details were rejected as invalid — for a card, the number, security code or expiry.retry_with_new_payment_methodSome of the payment details are incorrect. Please check them and try again.
expired_cardThe payment method is past its expiry date.retry_with_new_payment_methodThis payment method has expired. Please use a different one.
authentication_failedAuthentication was required but could not be completed — a wrong one-time code, or a card the issuer will not authenticate.retry_with_new_payment_methodThe payment couldn't be verified. Please try again or use a different payment method.
transaction_not_permittedThe payment method or account does not allow this transaction type.retry_with_new_payment_methodThe payment was declined. Please use a different payment method.

Soft declines — processor / issuer errors​

These are transient. Retrying may succeed without any customer action.

CodeDescriptionRetry StrategySafe Message
generic_issuer_errorThe issuer or funding provider returned a generic error. Typically temporary.retry_immediatelyWe couldn't confirm this payment in time. Please check whether it went through before trying again.
generic_processor_errorThe payment processor returned a generic error.retry_immediatelyWe couldn't confirm this payment in time. Please check whether it went through before trying again.
processor_rate_limitedThe processor is rate-limiting requests.retry_immediatelyWe're busy right now. Please try again in a few moments.
processor_timeoutThe processor did not respond in time.retry_immediatelyWe couldn't confirm this payment in time. Please check whether it went through before trying again.
authentication_unavailableAuthentication never ran — the issuer's authentication server timed out or failed technically.retry_immediatelySomething went wrong. Please try again.
authentication_requiredThe issuer requires the payment to be authenticated and refused it without 3D Secure.retry_immediatelyThis payment needs to be verified. Please try again to continue.
info

authentication_cancelled, authentication_rejected and authentication_unavailable each describe a specific way a 3D Secure authentication did not succeed. A processor may report all of them under a single refusal reason — Adyen's "3D Not Authenticated" is one — so ODUS separates them from the authentication result on the response, because the right response differs: a customer who dismissed the challenge stopped the payment themselves and can start it again, an authentication server that never answered can be retried without involving them, and an issuer that refused outright must not be retried at all. authentication_cancelled is listed under Soft declines — other, alongside cancelled, because the two describe the same customer action.

authentication_required is the one case where authentication has not happened yet rather than failed. The issuer refused an exemption and wants the payment authenticated, so retrying it with 3D Secure is the documented remedy — there is nothing wrong with the payment method, and asking the customer to change it will not help.

authentication_failed is the general case, and is not limited to 3D Secure: it also covers a card the issuer will not authenticate at all, and approval failures on other payment methods such as a PayPal billing agreement.

Soft declines — other​

CodeDescriptionRetry StrategySafe Message
generic_declineA general decline with no specific reason from the processor.retry_after_delayThe payment was declined. Please try again or use a different payment method.
cancelledThe customer cancelled the payment, at a 3DS challenge or at another approval step such as a PayPal approval. Where the processor identifies a cancelled 3DS challenge specifically, authentication_cancelled is reported instead.retry_after_delayThe payment was cancelled. You can try again when you're ready.
authentication_cancelledThe customer dismissed the authentication challenge. Reported instead of cancelled where the processor identifies a cancelled 3DS challenge specifically; both describe the same customer action and carry the same strategy.retry_after_delayThe payment was cancelled. You can try again when you're ready.
not_supportedThe payment method or currency is not supported by the processor.retry_after_delayThis payment method isn't available for this payment. Please use a different one.
internal_errorAn error occurred within ODUS while processing the payment.retry_after_delaySomething went wrong. Please try again.

Codes added in v2​

Some of the codes above cover more than one outcome, and the advice attached to them cannot be true of all of them at once. generic_hard_decline reports a payment that has already been captured alongside genuine refusals, so "use a different payment method" invites a second charge for the same order. card_restricted reports a problem with the store's own processor account alongside a blocked card, so no payment method your customer chooses gets past it. And generic_processor_error and generic_issuer_error mean the payment was left unresolved and needs reconciling before a retry — but they also carry requests that were refused outright, where nothing is unresolved at all.

v2 gives each of those outcomes its own code, and adds two more — payment_method_unusable, for a stored payment method that can no longer be charged, and stored_credential_revoked, for one the processor now refuses to let you charge. v1 is unchanged: it keeps reporting all eight as the broader code in the last column, with that code's decline type and retry strategy.

All eight are not_attempted with never_retry. None is a decision by the issuer about your customer's payment method, and none is resolved by another attempt at the same thing. For all but payment_method_unusable and stored_credential_revoked, the remedy is in the store's hands rather than the customer's.

Code (v2)DescriptionSafe MessageReported in v1 as
payment_method_unusableThe stored payment method can no longer be charged and has to be replaced. Ask the customer for a new one; retrying this one cannot succeed.The payment was declined. Please use a different payment method.generic_hard_decline
stored_credential_revokedPermission to charge a stored payment method has been withdrawn, so the processor refuses it without asking the funding source. Ask the customer to authorize a new payment method; this one cannot be charged again.The payment was declined. Please use a different payment method.generic_hard_decline
already_capturedThe payment has already been taken. Nothing is owed, and charging again would take it twice.This payment has already gone through. You don't need to pay again.generic_hard_decline
merchant_account_restrictedYour account with the processor is locked, closed or restricted, so it cannot accept payments.This store can't take this payment right now.card_restricted
merchant_configuration_errorYour account is not set up to accept this payment — the payment method, country or currency is not enabled on it.This store can't take this payment right now.generic_issuer_error
invalid_requestThe processor refused the request as malformed or invalid. It never reached an authorization, so nothing is unresolved.This payment can't be completed.generic_processor_error
blocked_by_policyA risk or compliance rule blocked the payment. It is not a fraud signal about your customer's payment method.The payment was declined.fraud_suspected
order_not_permittedSomething about the order is not accepted — where it ships to, what it contains, or how its amount is expressed.This payment can't be completed.transaction_not_permitted
info

invalid_request and merchant_configuration_error are the definitive counterparts to generic_processor_error and generic_issuer_error. Where those two warn you that the payment may have gone through and needs checking before a retry, these two tell you it did not: the request was refused before any money moved, so you can act on the failure immediately instead of reconciling first.

Retry strategies​

Each error code maps to a recommended retry strategy. Use this to decide how your integration should respond to a failure.

StrategyMeaning
never_retryDo not repeat this operation unchanged — it cannot succeed. Check errorCode for the remedy: a hard_decline means the payment method is blocked, restricted or flagged for fraud and retrying it may incur network penalties, while a not_attempted code points at the stored method, your account, or the request instead.
retry_with_new_payment_methodThe current payment method cannot be used. Ask the customer to provide a different one.
retry_after_delayThe issue may resolve on its own (e.g. insufficient funds). Wait before retrying.
retry_immediatelyThe failure is transient and no decision was reached. Your integration may retry at once only after authentication_required, authentication_unavailable or processor_rate_limited, where the request is known to have been turned away before authorisation — for authentication_required, retry with 3D Secure rather than unchanged. The other codes carrying this strategy — processor_timeout, generic_processor_error, generic_issuer_error — cover cases the processor never resolved, so the payment may already have been processed: check its current status and reconcile before retrying, or your customer can be charged twice.
tip

For subscription payments, ODUS uses the retry strategy automatically when scheduling retries. When a subscription renewal fails with authentication_unavailable or processor_rate_limited, ODUS also resends it unchanged within minutes, before your retry policy starts. See the retry policy guide for details.

Example response​

A failed authorization returns the outcome on the latest transaction:

Failed payment response (secret key)
{
"id": "pay_a1b2c3",
"status": "open",
"displayStatus": "failed",
"latestTransaction": {
"outcome": {
"status": "failure",
"errorCode": "insufficient_funds",
"errorMessage": "The payment method has insufficient funds.",
"safeErrorMessage": "There aren't enough funds available for this payment. Please use a different payment method.",
"declineType": "soft_decline",
"retryStrategy": "retry_after_delay",
"processorCode": "card_declined",
"processorMessage": "Your card has insufficient funds.",
"specialCode": null
}
}
}
info

When read with a checkout key, the response only includes status, safeErrorMessage, retryStrategy, and specialCode. Sensitive fields like errorCode, errorMessage, declineType, processorCode, and processorMessage are omitted.