Originally published on the RetryFix blog.
A soft decline is a refused card charge where the issuer has not said the card itself is finished. The charge failed this time. The same card might still pay later, or the customer might need to do one specific thing first: add funds, authenticate, or use another payment method. A hard decline is the other case. This card cannot complete the charge, and another attempt on it will not collect.
This page is the practical half: how to have fewer soft declines in the first place, and when a retry is worth running. Which codes are which, and the slice of failed payments a retry will never collect, is in hard declines vs soft declines.
What a soft decline means
Stripe's decline codes page does not group codes under a heading called "soft declines." Subscription operators use the term for the declines that are not a finished card. On a renewal, the codes this page treats as soft declines are:
-
insufficient_funds. The card did not have enough for this charge. Stripe's next step is that the customer needs another payment method. The code is not on the list Stripe refuses to retry, so a later attempt is still allowed. -
do_not_honorandgeneric_decline. The issuer declined and did not say why. Stripe's next step for both is that the customer contacts their card issuer. These are also not on Stripe's do-not-retry list. -
processing_error,issuer_not_available, andreenter_transaction. Something in the path failed. Stripe's next step is to attempt the payment again, and to involve the customer if it still will not go through. -
authentication_required. The issuer wants the customer to authenticate, often with 3D Secure. Stripe's decline-code page uses "soft decline" for the issuer response that, on Stripe's front ends, in most cases starts an authentication flow.authentication_requiredis the code when that step is still outstanding, and it is on the list of codes Stripe will not run a live automatic retry against until a new payment method is attached.
The sharper signal, when the issuer sends one, is the advice code on the charge, not the decline name alone. Stripe documents three:
-
try_again_later. You can retry. -
do_not_try_again. Do not use this card again for the same transaction. -
confirm_card_data. Some of the card data was wrong. Fix it before you charge again.
A retry only helps if something can still change. That is what payment retry logic is deciding: whether to charge again, when, how many times, and when to stop.
How to reduce soft declines before the renewal
A retry recovers a charge that already failed. The cheaper result is a renewal that never declines. The steps below are the ones Stripe documents. A longer retry list is not one of them.
Let the network update the card
When an issuer replaces a card, the number and expiry you have saved can be wrong before the customer tells you. Stripe works with the card networks and automatically attempts to update saved card details when the customer receives a new card, including a replacement for one that expired or was reported lost or stolen. The next renewal can then use the new details instead of failing.
That only happens when the issuer participates. Stripe says support is wide for American Express, Visa, Mastercard, and Discover cards issued in the United States. Support in other countries varies. You cannot tell in advance which saved cards will update. If you keep your own copy of the last four and the expiry, listen for payment_method.automatically_updated.
This prevents a decline. It is not a retry. If the update never arrives and the charge comes back expired_card, the customer needs another card. That code is a hard decline, covered on the hard vs soft page.
Email before a default card expires
Send emails about expiring cards, in Stripe's revenue recovery email settings, sends one email a month before a card expires, when that card is the customer's default payment method or default source. The renewal should not be the moment anyone learns the card is ending.
That email does not replace the note after a charge has already failed. Send emails when card payments fail is a separate switch, and it sends after each failed payment. If you also send your own failed-payment mail, the customer gets two threads. Pick one sender. What those notes should say is in what dunning is, including the day 1, day 3, and day 7 reminder ladder RetryFix describes publicly. Treat that ladder as an example of the emails, not as a recovery rate.
Put a second card where the retry will actually use it
A backup card helps only if the next attempt charges it. When Stripe retries a subscription invoice, it uses one payment method, in this order: the subscription's default payment method, then the subscription's default source, then the customer's default payment method, then the customer's default source. It does not try every card saved on the customer.
There is a trap in that order. If the subscription has its own default payment method, and a card update only changes the customer's invoice default, Stripe keeps retrying the subscription's card. Update the field the failed attempt used.
Asking for a second card at signup, or in the product before renewal, is what makes an insufficient_funds decline recoverable without waiting on a balance that may not change. Stripe's written next step for that code is an alternative payment method.
Use a recognisable descriptor, and authenticate while the customer is present
A statement descriptor is the text on the bank or card statement. Stripe's docs say a clear, accurate descriptor can reduce chargebacks and disputes, and that it should reflect the name you do business under. For card charges the account has a short prefix. A per-charge suffix is for one-time card payments. Stripe creates subscription charges itself, so you cannot set that suffix on the subscription's PaymentIntent. Subscription and invoice charges use the account descriptor unless you set one on the invoice.
A clearer name will not turn an insufficient-funds decline into an approval. It is still worth setting, because a renewal the customer does not recognise is how a real charge gets queried or stopped. Most banks show the descriptor. Some do not.
Authentication is the other step you can take before the decline. Some issuers, especially in Europe and India, want the customer to confirm the payment. Stripe's card declines guide says using 3D Secure can lower decline rates in countries that support it. On Stripe's front ends, an issuer soft decline that wants authentication usually becomes a prompt while the customer is still there.
A renewal is off-session. The customer is not on a page to complete a prompt. An authentication_required result then needs a message, not another silent charge. Stripe can email a hosted confirmation link when Send a Stripe-hosted link for customers to confirm their payments when required is on. While the customer is still in checkout, Stripe's front ends can turn the issuer's soft decline into an authentication step instead.
When a retry will actually work
Retry the same card when the issuer has left the door open. Stop when they have not.
A later attempt on the same card can be worth it
- The advice code is
try_again_later. - The decline is
processing_error,issuer_not_available, orreenter_transaction. Stripe's next step is to attempt again. - The decline is
insufficient_funds,do_not_honor, orgeneric_decline, and you still have a sensible number of attempts left. These codes are not on Stripe's do-not-retry list. They are also not a promise. For insufficient funds, the written next step is still another payment method. For a do-not-honor or a generic decline, the written next step is that the customer contacts the issuer. A spaced retry can catch a balance that has been topped up, or a temporary block that has cleared. It cannot make the customer call their bank. - The decline is
card_velocity_exceeded: a balance, credit, or amount limit on the card. Stripe's next step is that the customer contacts the issuer. Waiting is reasonable. Charging again immediately is how you hit the same limit.
The customer has to act
- The advice code is
do_not_try_againorconfirm_card_data. - The code is
authentication_required. Ask the customer to confirm the payment. Stripe keeps the retry on the schedule, and it will not run the charge until a new payment method is attached. - The card cannot pay:
expired_card, or a code on Stripe's do-not-retry list such aslost_card,stolen_card, orincorrect_number. Stop charging this card and ask for a new one. Stripe already withholds a live retry on that published list.expired_cardis not on the list, so an expired card can still be charged again unless something else in your setup stops it.
What Stripe Smart Retries are: a Billing setting that picks each attempt time from Stripe's network data, inside a window you choose, from 1 week up to 2 months. The recommended default is 8 tries within 2 weeks. A custom schedule is the other option: up to three retries, each a set number of days after the previous attempt. Card networks limit how often a single charge can be reattempted. Stripe recommends a maximum of eight retries for charges that permit retries, and says issuers may treat further retries as possible fraud, which can increase declines on legitimate charges.
Space matters more than adding attempts. Several charges a few hours apart do not create funds on an insufficient-funds card. They use up attempts the network will tolerate. A practical shape for which soft decline to leave for a few days is in how to retry failed Stripe payments. Put the customer email in the gap before the next attempt, so that attempt can use an updated card.
Common questions
What is a soft decline? A card charge the issuer refused without saying the card is finished. For a subscription renewal, that means insufficient funds, a generic or do-not-honor response, a processing error, or a request to authenticate.
How do you reduce soft declines? Keep the saved card current, with network card updates and an email a month before a default card expires. Store a second payment method on the field Stripe will actually charge. Authenticate while the customer is present. Set a statement descriptor the customer can recognise, so a real renewal is less likely to be queried or stopped. Then retry only where a later attempt is allowed, with space between tries.
Should you retry every soft decline? No. Retry when the advice code is try_again_later, or when the decline is a processing or issuer-unavailable error. For insufficient funds, do-not-honor, or a generic decline, a small number of spaced retries can be worth it, and the customer may still have to act. Do not retry when the advice code says not to. Do not keep charging a card that needs authentication or a new number.
Does Stripe retry soft declines for you? On subscription invoices, Smart Retries will retry many of them inside the window you set. It will not run a live charge for a code on its published hard-decline list, which includes authentication_required. It also will not retry when no payment method is available, when the card is India-issued, or when the Connect account has been disconnected. After the final attempt, Stripe makes no further payment attempts.
What is the difference between a soft decline and a hard decline? A soft decline can still clear later, or after the customer does one thing. A hard decline means this card cannot pay, so the path is a new payment method. How to split the codes in your own Stripe data is in hard declines vs soft declines.
Where to start
In the Stripe Dashboard, open Billing → Revenue recovery. Confirm Smart Retries are on, and that the window is the one you meant rather than a long run of extra attempts. Turn on Send emails about expiring cards. On a handful of recent failures, read the decline code and the advice code, and separate the ones that can wait from the ones that need the customer today.
Then open one subscription that failed for insufficient funds. If it has its own default payment method, that is the card the next retry will charge, including when the customer has just added a different card on their profile.
Try the demo: https://retryfix.com/demo/start
Top comments (1)
The advice-code point is the one that saves the most money: a decline name alone rarely tells you whether a second attempt is worth the retry fee, while try_again_later versus do_not_try_again changes the whole dunning plan. The insufficient_funds case is interesting too, since the outcome often depends on when the customer gets paid rather than anything the merchant controls, so spacing retries around typical payday cycles usually beats aggressive same-day retries.