When a payment fails on Stripe, the card issuer returns a decline code explaining why. These codes are your most valuable signal for deciding what to do next: retry the payment, contact the customer, or stop trying altogether.
This guide covers every common Stripe decline code, what it actually means, whether the payment is recoverable, and the best strategy for each.
Where to Find Decline Codes in Stripe
Decline codes appear in several places in your Stripe account:
- Payments page: Go to Payments, filter by "Failed," and click any failed payment. The decline code appears in the payment details under "Failure reason."
- Invoice details: For subscription payments, check the invoice. Failed invoices show the decline code from the most recent charge attempt.
- Stripe API: In the PaymentIntent or Charge object, the decline code is available at
last_payment_error.decline_code. - Webhooks: The
invoice.payment_failedwebhook event includes the decline code, which is how dunning tools detect and classify failures automatically.
Soft Declines vs. Hard Declines
The single most important distinction in payment recovery is whether a decline is soft or hard.
Soft declines are temporary. The payment method is still valid, but something prevented the charge from going through right now. These are highly recoverable with proper retry timing. Examples: insufficient funds, processing errors, rate limits.
Hard declines are permanent. The payment method cannot be used, and no amount of retrying will change that. The customer must provide a new payment method. Examples: expired card, stolen card, invalid card number.
Treating all declines the same is one of the biggest mistakes in payment recovery. Retrying a hard decline wastes API calls and can increase your decline rate with card networks. Emailing a customer about a temporary processing error is premature and unnecessary.
Common Stripe Decline Codes Reference
| Code | Meaning | Type | Recovery Strategy |
|---|---|---|---|
| insufficient_funds | The card does not have enough balance to cover the charge | Soft | Retry near common pay dates (1st, 15th of the month) |
| expired_card | The card has passed its expiration date | Hard | Do not retry. Contact the customer to update their card. |
| card_declined | Generic decline from the card issuer with no specific reason | Soft | Retry in 24-72 hours. If it fails again, contact the customer. |
| generic_decline | The issuer declined the charge without providing a specific reason | Soft | Retry after 24 hours. If repeated, request a card update. |
| do_not_honor | The issuer has flagged the transaction. Often a fraud or risk signal. | Soft | Retry once after 24 hours. May clear on its own, but do not retry aggressively. |
| authentication_required | The bank requires 3D Secure authentication (SCA) | Soft | Send the customer a 3D Secure payment link to complete authentication. |
| fraudulent | The issuer suspects fraud on this card | Hard | Do not retry. Do not contact the customer about this card. |
| stolen_card | The card has been reported stolen | Hard | Do not retry. Cancel the payment method immediately. |
| processing_error | A temporary error occurred while processing the charge | Soft | Retry immediately or within a few hours. |
| card_not_supported | The card does not support this type of transaction | Hard | Do not retry. Ask the customer for a different payment method. |
| incorrect_number | The card number is incorrect | Hard | Do not retry. Customer must re-enter their card details. |
| try_again_later | Temporary issuer issue. The payment should succeed if retried. | Soft | Retry in 2-4 hours. |
The Two Most Common Decline Codes
insufficient_funds and generic_decline together account for over 60% of all payment failures. Both are soft declines and both are highly recoverable, but they require different timing.
Insufficient funds is the most straightforward. The customer does not have enough money in their account right now. The optimal strategy is to retry near common payroll dates. For most customers, the 1st and 15th of the month are when funds are deposited. Retrying the day after a failed payment is almost always pointless for this code.
Generic decline is trickier because the issuer does not tell you why. It could be a temporary fraud flag, a spending limit, or an internal bank policy. The best approach is to retry after 24 hours. If it fails again, send the customer a message asking them to contact their bank or provide a different card.
Hard Declines: When to Stop Retrying
Hard declines require a different playbook. Retrying will not work, and excessive retries can actually harm your business:
- Higher decline rates with card networks. Visa and Mastercard track your decline-to-transaction ratio. Repeatedly retrying hard declines inflates this ratio and can lead to higher processing fees or account restrictions.
- Wasted webhook and API capacity. Every retry triggers webhooks and API calls. For hard declines, these are entirely wasted resources.
- Delayed customer outreach. While you are waiting for retries to fail, the customer could be updating their card if you had contacted them immediately.
For hard declines (expired_card, stolen_card, fraudulent, card_not_supported, incorrect_number), the correct action is to skip retries entirely and contact the customer right away with a link to update their payment method.
Using Decline Codes to Improve Recovery
The difference between a 40% recovery rate and a 70%+ recovery rate often comes down to how well you use decline code data. Here is how to apply it:
Customize retry timing by code. Do not use a fixed retry schedule for all failures. Insufficient funds should be retried on the 1st or 15th. Processing errors should be retried in hours. Generic declines should be retried after 24 hours.
Adjust email urgency by code. A customer with an expired card needs to take action immediately. A customer with a temporary processing error does not need to do anything. Sending a "your payment failed, update your card now" email for a processing error creates unnecessary alarm.
Route hard declines to immediate outreach. When the decline code indicates the card is permanently unusable, skip the retry queue and send the customer a message right away. Every day of delay increases the chance of churn.
Track recovery rates by code. Monitor which decline codes you are recovering and which you are losing. If your insufficient_funds recovery rate is low, your retry timing may be off. If expired_card recovery is low, your customer outreach is not reaching them.
How Rebounce Classifies Decline Codes
Rebounce automatically classifies every failed payment by its Stripe decline code and applies the optimal recovery strategy. Soft declines are retried with timing specific to the decline type. Hard declines skip retries and trigger immediate customer outreach via email and WhatsApp.
This classification happens automatically when a payment fails. There is no manual setup required. You can see the decline code breakdown in your Rebounce dashboard, including recovery rates by code type, so you always know where your revenue is being recovered and where it is being lost.
For a broader look at how dunning tools handle payment recovery, see our comparison of the best dunning tools in 2026.