Skip to main content
When a payment fails, Dodo Payments provides a standardized error_code and human-readable error_message. This guide shows how to read those fields, decide whether to retry, and recover the payment safely.

How Dodo Payments Reports a Failure

Every failed payment carries these fields on the payment object:
error_code and error_message are null until a payment fails. Always check status first.
error_message is merchant-facing and can reveal fraud-related reasons. Never show it to customers. Map error_code to customer-safe wording instead (see Surface Errors to Customers Safely).

The payment.failed Webhook

The payment.failed webhook is the most reliable way to detect a failure. The event wraps the full payment object in data:
payment.failed payload
A minimal handler reads error_code and routes based on it:
Always verify the webhook signature before processing. See the Webhooks guide for the full setup, including signature verification and idempotency.

Decide Whether to Retry: Soft vs. Hard Declines

The error_code tells you whether retrying the same payment method is worthwhile. See Transaction Failures for the full list of decline types and recommended actions.

Handling Failures at Checkout vs. on Renewal

How you recover depends on whether the customer is present.
The customer is actively checking out. Surface a clear message and let them retry or use another card.
  • requires_payment_method — the customer never provided a payment method. This is usually a checkout drop-off, not a decline. Re-engage the customer to complete payment (see Abandoned Cart Recovery).
  • requires_customer_action — additional authentication (such as 3DS) is needed. Have the customer complete it. See 3D Secure.

Retrying a Failed Payment

Subscriptions: Enable Subscription Payment Retries to recover soft declines automatically. To retry immediately instead of waiting for the schedule, use Manual Payment Retry from the dashboard or API. You can also trigger recovery by having the customer update their payment method via the Update Payment Method API, which charges any outstanding dues. One-time payments: Resend the checkout or payment_link so the customer can try again with a different method. There is no automatic retry for one-time payments.
Do not retry hard declines against the same card. Card networks flag repeated declines as abusive, which hurts your authorization rate.

Surface Errors to Customers Safely

Show customers a friendly message, never the raw error_code or merchant-facing error_message.
On Dodo Payments-controlled surfaces (checkout, Customer Portal, dunning emails), this mapping is already done for you, including fallback to a generic message for fraud-related declines. You only need the mapping below where you render failures in your own product.
Customer-facing messaging
Never reveal the real reason for STOLEN_CARD, LOST_CARD, PICKUP_CARD, or FRAUDULENT. Surfacing these can tip off a fraudulent actor. Show a generic decline message and log the specific error_code internally only.

Transaction Failures

Every decline code, its type, and the recommended action.

Error Codes

API and business-logic errors that are not card declines.

Subscription Payment Retries

Automatic recovery of soft declines on subscription renewals.

Subscription Dunning

Email sequences that recover hard declines.

Payment Webhooks

Full payload schema for payment events.

Testing Failures

Test cards that simulate declines and renewal failures.
Last modified on September 25, 2026