Guides

The Complete Guide to Stripe Decline Codes and SMS Payment Recovery

Every failed subscription payment carries a specific decline code — and each code demands a different recovery strategy. Learn how to map every Stripe decline code to the optimal SMS recovery approach.

Published March 5, 202621 min read

Every failed subscription payment carries a specific decline code — and each code demands a different recovery strategy. For SaaS businesses running on Stripe, understanding these codes is the difference between silently retrying a temporary glitch and losing a customer forever. Failed payments cause 20–40% of all subscription churn, costing the industry an estimated $129 billion annually. Yet only 17% of subscription businesses actively track decline codes. This guide maps every Stripe decline code to its meaning, classification, and optimal recovery approach — with a focus on why SMS-first recovery outperforms traditional email dunning by 3–4x.

RecoverPing integrates with Stripe webhooks to detect failures in real time, classify the decline, and trigger the right recovery sequence — SMS, email, or intelligent retry — within minutes, not days.


How Stripe classifies payment failures

Stripe organizes every failed payment into exactly three categories, each surfaced through the outcome object on the Charge:

Failure Typeoutcome.typenetwork_statusWhat happened
Issuer declinesissuer_declineddeclined_by_networkThe cardholder's bank rejected the charge
Blocked paymentsblockednot_sent_to_networkStripe Radar, custom rules, or Adaptive Acceptance blocked it before reaching the network
Invalid API callsinvalidnot_sent_to_networkMalformed request (wrong card format, missing params)

Within issuer declines, Stripe provides an advice_code field that is the most reliable retryability signal per transaction:

  • try_again_later — The issuer says retry is permitted
  • do_not_try_again — The card should not be retried for this transaction
  • confirm_card_data — The card details provided are incorrect; customer must fix them

Stripe does not officially label each decline code as "soft" or "hard" in its documentation. Instead, it relies on advice_code per transaction. The soft/hard classifications in the tables below reflect industry-standard consensus from multiple payment recovery platforms and practical integration experience.

Generic declines versus specific declines

The most common — and most frustrating — code is generic_decline. This is a catch-all the issuer returns when it doesn't disclose a specific reason. It can represent anything from a temporary fraud flag to a spending limit. About 50–60% of all declines fall into this bucket, making it critical to retry these rather than treat them as permanent failures.

Specific codes like insufficient_funds or expired_card give you actionable intelligence. The recovery strategy should differ dramatically: insufficient funds is a timing problem (retry around payday), while expired card requires the customer to update their payment method.

Stripe-blocked payments versus issuer declines

When outcome.type is blocked, the charge never reached the card network. Stripe's Radar fraud system or Adaptive Acceptance engine intercepted it. The outcome.reason field reveals why:

  • highest_risk_level — Radar flagged the transaction as too risky
  • low_probability_of_authorization — Adaptive Acceptance blocked it to avoid unnecessary network decline fees
  • Custom Radar rules configured by the merchant

These blocks appear as fraudulent or merchant_blacklist decline codes. Never reveal fraud-related decline reasons to the customer — always present them as a generic decline.


Every Stripe card decline code: soft vs. hard

The following is the complete list of 44+ card decline codes Stripe returns, organized by retryability. This classification drives whether you should retry silently, contact the customer, or request a new payment method.

Soft declines — temporary and retryable

These represent 80–90% of all declines. The underlying issue is often transient — insufficient funds, a temporary hold, network latency, or an overzealous issuer fraud filter.

Decline CodeWhat It MeansRecovery Strategy
insufficient_fundsNot enough money in the accountMost recoverable code (~68% recovery rate). Retry in 2–7 days, ideally around payday (1st/15th of month). If second retry fails, send SMS with payment update link.
generic_declineIssuer gave no specific reasonRetry once after 24 hours. If it fails again, SMS the customer — the issuer may require them to authorize the charge.
do_not_honorBlanket refusal from issuerRetry after 24–48 hours. If persistent, customer must call their bank. SMS with clear instructions.
processing_errorTemporary system errorRetry immediately or within a few hours. Usually resolves on its own.
issuer_not_availableCard network couldn't reach issuerRetry in 1–4 hours. Purely a connectivity issue.
approve_with_idNeeds additional authorizationRetry; often succeeds on second attempt.
call_issuerIssuer wants the cardholder to callSMS the customer immediately — they need to contact their bank before retry will work.
card_velocity_exceededHit spending/transaction limitCustomer may need to wait or call their bank. Retry in 24–48 hours.
withdrawal_count_limit_exceededBalance or credit limit hitSame as above — retry after a few days.
reenter_transactionIssuer asks for re-submissionRetry immediately.
try_again_later (deprecated)Temporary declineRetry in a few hours.
no_action_takenUnknown reasonRetry; if persistent, customer contacts issuer.
not_permittedPayment type not allowedCustomer contacts issuer to enable this payment type.
restricted_cardCard restricted (possibly lost/stolen flag)Customer must contact issuer. Present as generic decline.
security_violationSecurity check failedCustomer contacts issuer.
service_not_allowedCard doesn't allow this serviceCustomer contacts issuer.
stop_payment_orderStop payment placedCustomer contacts issuer.
transaction_not_allowedTransaction type blockedCustomer contacts issuer.
duplicate_transactionSame charge submitted recentlyVerify no duplicate — this is usually a system issue, not a customer problem.
currency_not_supportedCard doesn't support this currencyMay need alternative payment method.
invalid_amountAmount exceeds limitCheck with issuer about purchase limits.
incorrect_cvcWrong CVC enteredSMS customer to re-enter card details.
incorrect_zipWrong postal codeSMS customer to update billing address.
incorrect_pinWrong PIN (in-person only)Customer retries with correct PIN.
invalid_cvc / invalid_pinCVC or PIN format invalidCustomer re-enters correct info.
invalid_expiry_month / invalid_expiry_yearBad expiration dateCustomer updates card details.
invalid_numberCard number format invalidCustomer re-enters card.
invalid_accountAccount invalidCustomer contacts issuer.
incorrect_addressAddress mismatchCustomer updates billing address.
card_not_supportedCard type not acceptedCustomer uses different card.
new_account_information_availableCard details changedCard updater may resolve; otherwise customer updates.
mobile_device_authentication_requiredNeeds mobile authCustomer re-authenticates on device.
offline_pin_required / online_or_offline_pin_requiredPIN requiredIn-person only — customer inserts card.
pin_try_exceededToo many PIN attemptsCustomer uses different card.
testmode_declineTest card used in productionDeveloper error — use real card.
do_not_try_again (deprecated)Unknown reasonCustomer contacts issuer.

Hard declines — permanent, require new payment method

These represent 10–20% of declines. Retrying will not help. The customer must provide a new card or resolve the issue with their bank.

Decline CodeWhat It MeansRecovery Strategy
expired_cardCard has passed its expiration dateSMS immediately with a link to update their card. Stripe's card updater may auto-resolve this, but don't wait — proactive SMS recovers faster.
lost_cardReported lost to the bankPresent as generic decline. Customer needs a replacement card. SMS with update link.
stolen_cardReported stolenPresent as generic decline. Never reveal this code to the customer. SMS asking them to update payment method.
pickup_cardBank flagged for retrievalPresent as generic decline. Customer contacts bank.
fraudulentStripe suspects fraudPresent as generic decline. Review in Radar dashboard.
merchant_blacklistOn your Stripe block listPresent as generic decline. Review your Radar rules.
incorrect_numberCard number is wrongCustomer must re-enter card details.
authentication_required3D Secure / SCA neededTrigger an on-session authentication flow. SMS customer with a link to complete 3DS.
authentication_not_handledAuth required but not performedMust run the EMV 3DS / SCA flow.
revocation_of_authorizationCardholder revoked permissionCustomer must re-authorize or use new card.
revocation_of_all_authorizationsAll authorizations revokedCustomer must use a completely new payment method.

Local payment method decline codes

Stripe returns 18 additional codes for non-card payment methods (SEPA, BACS, ACH, iDEAL, etc.):

CodeMeaningRetryable?
partner_generic_declinePayment provider declinedPossibly
invalid_customer_accountCan't charge this accountAfter customer fixes
payment_limit_exceededExceeds account limitAfter customer adjusts
invalid_billing_agreementAgreement invalidNo
compliance_violationViolates terms/lawsNo
invalid_authorizationAuthorization invalid or revokedNo
invalid_payment_informationBad payment dataNo
expired_payment_informationUnderlying instrument expiredAfter customer updates
partner_high_risk_customerProvider flagged high riskUnlikely
payment_disputedActive disputeAfter resolution

For ACH, SEPA, and BACS, Stripe maps network return codes (like ACH R01 for insufficient funds or SEPA AC04 for account closed) to its own standardized failure reasons. These bank debit methods are not retried by Smart Retries by default — you must opt in.


How decline codes surface in the Stripe API

Understanding where to find decline data in the API response is essential for building automated recovery logic. The information lives in three places: the PaymentIntent's last_payment_error, the Charge's outcome object, and the error response on a synchronous API call.

The PaymentIntent error object

When a PaymentIntent fails, the last_payment_error field contains:

{
  "id": "pi_3MtwBwLkdIwHu7ix28a3tqPa",
  "status": "requires_payment_method",
  "last_payment_error": {
    "type": "card_error",
    "code": "card_declined",
    "decline_code": "insufficient_funds",
    "message": "Your card has insufficient funds.",
    "doc_url": "https://stripe.com/docs/error-codes/card-declined"
  }
}

The decline_code field (e.g., insufficient_funds) is the specific issuer reason. The code field (e.g., card_declined) is Stripe's broader error category. For your recovery logic, route on decline_code first, falling back to code.

The Charge outcome object

The Charge object (via payment_intent.latest_charge) provides deeper network-level data:

{
  "outcome": {
    "type": "issuer_declined",
    "network_status": "declined_by_network",
    "network_decline_code": "51",
    "advice_code": "try_again_later",
    "risk_level": "normal",
    "risk_score": 24,
    "reason": "insufficient_funds",
    "seller_message": "The bank declined this charge."
  }
}

The network_decline_code is the raw ISO 8583 code from the card network (e.g., 51 = insufficient funds on Visa/Mastercard). The advice_code is the single most reliable indicator of whether to retry. When advice_code is try_again_later, schedule a retry. When it's do_not_try_again, request a new payment method immediately.

Critical webhook events for payment recovery

Your integration should listen for these events to trigger recovery workflows:

Webhook EventWhen It FiresRecovery Action
invoice.payment_failedEvery failed payment attempt on an invoicePrimary trigger. Check attempt_count and decline_code. Route to retry or customer outreach.
payment_intent.payment_failedAny PaymentIntent failureAccess last_payment_error.decline_code for routing.
charge.failedA charge attempt failsAccess outcome for network-level detail.
customer.subscription.updatedSubscription status changesWatch for status: "past_due" to trigger escalated recovery.
customer.subscription.deletedSubscription canceled after all retries exhaustedFinal notification — offer reactivation.
invoice.payment_action_requiredPayment needs 3DS authenticationSMS customer with authentication link immediately.

The invoice.payment_failed event is the workhorse. It fires on every retry attempt, and the attempt_count field tells you which attempt just failed. The next_payment_attempt timestamp tells you when Stripe will try again — coordinate your SMS timing around this to avoid messaging a customer right before a successful retry.

Important behaviors: Events are not guaranteed in order. Design handlers idempotently. Stripe retries failed webhook deliveries for up to 3 days with exponential backoff.


Smart retry strategies that actually recover revenue

The data is clear: 50% of payment recovery comes from retries alone before any customer communication is needed. The other 50% requires the customer to take action — update a card, add funds, or call their bank. Getting the retry strategy right is foundational.

Stripe Smart Retries versus custom logic

Stripe's built-in Smart Retries uses a stacked ensemble ML model trained on billions of transactions across the entire Stripe network. It analyzes 500+ signals including cross-merchant payment patterns, time-of-day success rates by issuer, whether updated card data is available, and even debit-card payday patterns (e.g., debit cards in certain countries succeed more at 12:01 AM local time).

The numbers are compelling: Smart Retries recovers 57% of failed recurring payments on average and delivers $9 in revenue for every $1 spent on Stripe Billing. The recommended default configuration is 8 retries within 2 weeks.

However, Smart Retries has limitations. It won't retry hard declines until a new payment method is detected. It doesn't send customer communications. And it doesn't retry bank debit methods (ACH, SEPA, BACS) by default. This is where third-party tools like RecoverPing add value — by layering SMS outreach on top of Stripe's retry engine to recover the 50% of failures that require customer action.

When to retry silently versus contact the customer

The optimal approach separates retry logic from customer communication:

  1. First 1–3 attempts (Day 0–3): Retry silently. Don't email or text the customer about soft declines — many resolve automatically. A first retry succeeds 25–35% of the time.
  2. After 2–3 failed retries (Day 3–7): Send the first SMS. By now, the easy recoveries are done. The customer likely needs to take action.
  3. Day 7–14: Escalate messaging urgency. Second SMS plus email. Emphasize what they'll lose access to.
  4. Day 14–28: Final warnings via SMS. Clear deadline for service cancellation.

For hard declines (expired card, stolen card, authentication required), skip straight to customer outreach. Retries won't help — the customer must update their payment method. Speed matters here: PYMNTS research shows 27% of subscribers cancel immediately after receiving a payment failure notification. Reaching them in minutes via SMS, not hours via email, is the difference.

Card network retry limits

Visa allows 15 reattempts within 30 days for soft declines and zero for hard declines. Mastercard permits 10 retries within 24 hours. Exceeding these limits can result in penalties from the card networks. Stripe's Smart Retries respects these limits automatically, but custom retry logic must account for them.


The data behind payment recovery

How much revenue is actually at risk

Failed payments affect every subscription business, but the scale is often underestimated. 7.9% of all recurring transactions fail on average, reaching 14.7% in some industries. For a SaaS company with $10M ARR, that puts $790,000 in revenue at risk every year.

The breakdown of who recovers and who doesn't is stark:

Recovery ApproachRecovery Rate
No dunning (passive processor retries only)10–20%
Single retry attempt23%
Automated email dunning (fixed schedule)40–60%
Smart/ML-powered retries57–68%
AI-powered multi-channel (retries + email + SMS)70–85%

B2B SaaS companies recover at higher rates (53.5%) than B2C (34.6%), likely because higher contract values justify more aggressive recovery and because business customers have stronger intent to maintain service. The median recovery across all subscription businesses is 47–53%, meaning roughly half of failed payments go unrecovered with standard approaches.

Recovery rates by decline type

Not all declines are equally recoverable. Insufficient funds has the highest recovery rate at ~68% — it's fundamentally a timing problem. Generic declines recover well within short timeframes. Fraud and call-issuer codes have the lowest recovery rates and longest resolution times.

Recovered subscribers aren't just a one-time win. They continue paying for an average of 7 additional months after recovery, with 38% of their total customer lifetime occurring post-recovery. This makes every recovered payment worth far more than its face value.

The ROI of systematic recovery

Top-performing subscription businesses recover ~61% of failed payments and use an average of 3.1 recovery methods (retries + email + SMS + in-app). They are 12x more likely to use dedicated third-party recovery tools. The ROI is consistently 10–15x for effective dunning systems, with some platforms reporting 67x returns for individual customers.


Why SMS-first recovery outperforms email dunning

The channel you use to reach customers about failed payments matters enormously. The data overwhelmingly favors SMS as the primary recovery channel.

The engagement gap is massive

MetricSMSEmail
Open rate98%20–30%
Time to read90 seconds90 minutes
Click-through rate19–20%0.8–4.4%
Response rate45%10%

95% of SMS messages are read within 3 minutes of delivery. Early pilot data from Churnkey's SMS Payment Recovery feature showed 3–4x more recoveries from SMS compared to equivalent email campaigns. Pairing email with SMS increases recovery rates by an additional 15–20%.

Beyond engagement, SMS solves a critical problem that plagues email dunning: deliverability. Nearly half of dunning email senders report spam filtering as their top challenge. Payment failure emails from automated systems routinely land in promotions tabs or spam folders. SMS bypasses this entirely — there is no spam folder for text messages.

The speed advantage compounds

The first hours after a payment failure are the most critical window for recovery. Baremetrics data shows that Day 0 communications achieve a 13.25% recovery rate — the highest of any touchpoint. That rate decays steadily: by Day 30, it drops to 4.2%. SMS delivers the notification in seconds versus hours for email, compressing the entire recovery timeline.

For a payment declined due to insufficient funds, the customer may have the money the same day — they just need to know the charge failed. An SMS at 10 AM gets acted on by noon. An email sent at 10 AM might not be opened until the next day, by which time the customer may have spent those funds elsewhere.

The optimal multi-channel sequence

SMS works best as the primary channel with email as reinforcement:

StageTimingChannelMessage Tone
Immediate alertDay 0 (within minutes)SMSFriendly, factual: "Your payment didn't go through"
First reminderDay 3SMSHelpful: one-tap link to update card
Follow-upDay 7Email + SMSSlightly more urgent
EscalationDay 14SMS"Your access will be paused"
Final noticeDay 21–28Email + SMSClear deadline, loss framing

Pre-dunning is also powerful: sending an SMS before a card expires achieves a 47% open rate and 14.4% recovery rate — higher than even Day 0 post-failure messages.


TCPA compliance for SMS payment recovery

Sending automated SMS for payment recovery in the US requires careful compliance with the Telephone Consumer Protection Act (TCPA), state-level regulations, and carrier requirements. The good news: payment failure notifications occupy a legally favorable position.

Payment failure SMS qualifies as transactional

Failed payment notifications are generally classified as transactional/informational messages — not marketing. This is a significant compliance advantage. Transactional messages require only prior express consent (PEC), which can be obtained through a customer providing their phone number during signup. Marketing messages require the stricter prior express written consent (PEWC) with an explicit signature.

The critical caveat: this classification holds only if the message contains zero promotional content. Adding "Upgrade to annual billing for 20% off" or "Check out our new features" instantly reclassifies the entire message as marketing, triggering the higher consent standard. Every payment recovery SMS must be purely informational.

Core compliance requirements

Consent: When a customer provides their phone number during Stripe subscription signup, this can constitute implied consent for transactional SMS. Best practice is to include explicit language at checkout: "By providing your phone number, you consent to receive account-related text messages including payment notifications. Message and data rates may apply. Reply STOP to opt out."

Opt-out handling: Every SMS must include opt-out instructions. As of April 2025, the FCC requires businesses to accept consent revocation "in any reasonable manner" — not just the keyword STOP. Natural language opt-outs like "please stop texting me" must be honored within 10 business days (immediately is best practice).

Time-of-day restrictions: Federal TCPA allows messages between 8 AM and 9 PM in the recipient's local time. Florida and several other states restrict this further to 8 AM–8 PM. Apply the most restrictive standard (8 AM–8 PM) when the recipient's state is uncertain.

10DLC registration: As of February 2025, all US carriers block unregistered A2P 10DLC traffic. Every business sending SMS through RecoverPing must register their brand and campaign with The Campaign Registry (TCR) through the SMS provider (Twilio). Register campaigns under "Account Notifications" or "Customer Care" — not "Marketing."

State-level considerations

Florida (FTSA) imposes the strictest rules: maximum 3 contact attempts per 24 hours, 8 AM–8 PM quiet hours, and a private right of action with $500–$1,500 per violation. California requires CCPA privacy disclosures. Connecticut restricts hours to 9 AM–8 PM. TCPA litigation surged 95% in 2025, with Florida, California, and Texas as the highest-risk jurisdictions.

The safest approach: treat all payment recovery SMS as requiring explicit consent, never include promotional content, apply the most restrictive state rules universally, and maintain a comprehensive audit trail of consent (timestamp, method, exact language shown) for at least 4 years.


Where RecoverPing fits in the competitive landscape

The payment recovery space includes several established players, each with a distinct approach — and a shared blind spot around SMS.

Churn Buster (premium, strategic-partnership model) separates retries from customer communication and offers SMS as an optional secondary channel. Strong thought leadership content but no comprehensive decline code reference. Baremetrics Recover (email-only dunning add-on to their analytics platform) publishes dunning email guides but offers no SMS capability. Gravy Solutions ($997–$8,000/month) uses human agents who manually text and email customers — effective but expensive and inaccessible to SMBs. Paddle Retain (formerly ProfitWell Retain) uses algorithmic retries and email but requires Paddle platform lock-in. Churnkey is the closest competitor on SMS, recently launching SMS recovery with early results showing 3–4x more recoveries than email, but positions SMS as an add-on to their multi-product retention platform rather than a primary channel.

The content gap RecoverPing can own

No competitor has published a comprehensive Stripe decline code guide paired with SMS-specific recovery strategies. Churnkey publishes individual decline code explainer posts, but no one maps every code to an SMS recovery action with message templates. This represents a major SEO opportunity: developers and SaaS operators actively search for "[decline code] + how to fix" queries.

The decline-code-to-SMS-template approach is particularly powerful. For example:

  • insufficient_funds: "Hi [Name], your $[amount] payment for [Product] didn't go through — looks like a temporary issue. We'll retry in a few days, or you can update your card here: [link]. Reply STOP to opt out."
  • expired_card: "Hi [Name], your card ending in [last4] has expired. Update it in 10 seconds to keep your [Product] subscription active: [link]. Reply STOP to opt out."
  • authentication_required: "Hi [Name], your bank needs you to verify your $[amount] payment for [Product]. Complete verification here: [link]. Reply STOP to opt out."

No true SMS-first player exists in this market. Every competitor treats SMS as secondary to email. RecoverPing can own the "recover in minutes, not weeks" narrative backed by the 98% open rate data and the 3–4x recovery multiplier. The underserved $5K–$200K MRR segment — too small for Gravy's human agents or Churnkey's mid-market pricing — is where transparent, affordable SMS-first recovery can win.


Conclusion: building a decline-code-aware recovery engine

The most effective payment recovery systems treat decline codes as routing logic, not just error messages. A insufficient_funds decline on Day 1 should trigger a silent retry schedule aligned with paydays. An expired_card should fire an immediate SMS with a one-tap card update link. An authentication_required should push a 3DS verification link within minutes.

Three insights stand out from this research. First, the advice_code field (try_again_later, do_not_try_again, confirm_card_data) is more reliable than any static soft/hard classification — use it as your primary routing signal. Second, the first 5 minutes after a decline are the highest-leverage window for recovery, and SMS is the only channel fast enough to exploit it. Third, the 50/50 split — half of recoveries come from retries, half from customer action — means that Smart Retries alone will always leave half of recoverable revenue on the table. The customer communication layer is not optional; it's where the remaining revenue lives.

For RecoverPing, the strategic play is clear: own the intersection of Stripe decline code intelligence and SMS-first outreach. No competitor occupies this position today. The data supports it, the compliance framework permits it, and the $129 billion involuntary churn problem demands it.

Ready to stop losing revenue to failed payments?

Stop losing revenue to failed payments. RecoverPing automatically recovers them via SMS and email — so you don't have to chase customers manually.