<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Mathieu Chambaud</title>
    <description>The latest articles on DEV Community by Mathieu Chambaud (@freki_managarm).</description>
    <link>https://dev.to/freki_managarm</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F593799%2Fc283ae1a-dd8b-4346-b100-e52ec114b16d.jpg</url>
      <title>DEV Community: Mathieu Chambaud</title>
      <link>https://dev.to/freki_managarm</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/freki_managarm"/>
    <language>en</language>
    <item>
      <title>Stripe failure codes – the complete guide</title>
      <dc:creator>Mathieu Chambaud</dc:creator>
      <pubDate>Fri, 12 Jun 2026 13:22:26 +0000</pubDate>
      <link>https://dev.to/freki_managarm/stripe-failure-codes-the-complete-guide-10cb</link>
      <guid>https://dev.to/freki_managarm/stripe-failure-codes-the-complete-guide-10cb</guid>
      <description>&lt;h2&gt;
  
  
  What each Stripe failure code means and what to do about it
&lt;/h2&gt;

&lt;p&gt;When a Stripe payment fails, most SaaS founders send the same email to everyone.&lt;/p&gt;

&lt;p&gt;"Your payment failed. Please update your billing information."&lt;/p&gt;

&lt;p&gt;It's the wrong move — and it's costing you recoverable revenue every month.&lt;/p&gt;

&lt;p&gt;Every failed payment in Stripe comes with a reason code. That code tells you exactly what went wrong: whether the card expired, whether the bank blocked the charge, whether it was a temporary funds issue. Each situation calls for a completely different response, different timing, and different tone.&lt;/p&gt;

&lt;p&gt;This guide covers every Stripe failure code you're likely to encounter, what it means, and precisely what to do — so you can stop treating all failed payments the same way.&lt;/p&gt;




&lt;h2&gt;
  
  
  How Stripe Failure Codes Work
&lt;/h2&gt;

&lt;p&gt;When a charge fails, Stripe returns two pieces of data:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;decline_code&lt;/code&gt;&lt;/strong&gt; — the specific reason the card network or bank declined the charge (e.g., &lt;code&gt;card_expired&lt;/code&gt;, &lt;code&gt;insufficient_funds&lt;/code&gt;, &lt;code&gt;do_not_honor&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;failure_code&lt;/code&gt;&lt;/strong&gt; — a broader category code on the charge or PaymentIntent object&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For dunning purposes, &lt;code&gt;decline_code&lt;/code&gt; is what matters. It's the most granular signal you have about what actually went wrong.&lt;/p&gt;

&lt;p&gt;You can access it in two ways:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Via webhook (recommended):&lt;/strong&gt;&lt;br&gt;
Listen for &lt;code&gt;invoice.payment_failed&lt;/code&gt; events. The charge object inside the event contains &lt;code&gt;failure_code&lt;/code&gt; and &lt;code&gt;last_payment_error.decline_code&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"invoice.payment_failed"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"data"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"object"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"last_payment_error"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"code"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"card_declined"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"decline_code"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"insufficient_funds"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"message"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Your card has insufficient funds."&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Via Stripe Dashboard:&lt;/strong&gt;&lt;br&gt;
Go to Payments → find the failed charge → look under "Failure reason" in the charge detail view.&lt;/p&gt;




&lt;h2&gt;
  
  
  The 4 Failure Codes You'll See Most Often
&lt;/h2&gt;

&lt;p&gt;These four codes account for the vast majority of failed payments in SaaS billing. Get these right and you'll recover most of your involuntary churn.&lt;/p&gt;




&lt;h3&gt;
  
  
  1. &lt;code&gt;card_expired&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;What it means:&lt;/strong&gt; The expiration date on the card has passed. The card number is still valid, the customer still has the account — they just haven't updated their card details with you.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How common:&lt;/strong&gt; Very common. Cards typically expire every 2–3 years, and customers rarely update their details proactively. Expiry-related failures tend to cluster around January (post-holiday card refreshes) and throughout the year as individual cards hit their expiry dates.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What the customer needs to do:&lt;/strong&gt; Update to a new card. That's it. They almost certainly already have a replacement card from their bank.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The right recovery approach:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Timing:&lt;/strong&gt; Send immediately — within an hour of the failure. The customer is likely at their desk, and this is an easy fix. Don't wait.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tone:&lt;/strong&gt; Friendly, zero pressure. Frame it as a quick admin task, not a billing crisis. "Happens to everyone" goes a long way here.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Action:&lt;/strong&gt; One clear call to action — a direct link to update their payment method. Don't ask them to log in, navigate to billing, and find the update button. Give them a one-click link.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Subject line example:&lt;/strong&gt; &lt;code&gt;Quick note about your [Product] subscription, [Name]&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Email template:&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Hey [Name],&lt;/p&gt;

&lt;p&gt;The card we have on file for your [Product] subscription expired at the end of [month] — totally normal, happens to everyone.&lt;/p&gt;

&lt;p&gt;Here's a one-click link to update it: &lt;strong&gt;[Update payment method →]&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Takes about 30 seconds. Once updated, your subscription continues without any interruption.&lt;/p&gt;

&lt;p&gt;Let me know if you run into any issues.&lt;/p&gt;

&lt;p&gt;[Your name]&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;What not to do:&lt;/strong&gt; Don't send an urgent, high-pressure email. The customer didn't do anything wrong — their card just expired. Treat it as a helpful nudge, not a warning.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Stripe Smart Retries effectiveness:&lt;/strong&gt; Low. The underlying issue (expiry) doesn't resolve itself, so retries will keep failing until the card is updated. Email outreach is essential here.&lt;/p&gt;




&lt;h3&gt;
  
  
  2. &lt;code&gt;insufficient_funds&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;What it means:&lt;/strong&gt; The customer's account didn't have enough balance to cover the charge at the time of the attempt. The card itself works fine — it was just a bad moment to charge it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How common:&lt;/strong&gt; Very common, especially for consumer-facing and lower-price-point SaaS. Also spikes at end-of-month when billing cycles from other services have already hit.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What the customer needs to do:&lt;/strong&gt; Usually nothing. Wait for their account to replenish. The card will work again in a few days.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The right recovery approach:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Timing:&lt;/strong&gt; Do NOT send an email immediately. Wait 3 days before reaching out. Emailing someone the same day their card declined for insufficient funds piles on at the worst possible moment and can damage the relationship.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tone:&lt;/strong&gt; Calm, non-judgmental, no urgency. They know what happened. They don't need it spelled out.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Action:&lt;/strong&gt; Let them know there was an issue with their payment, without making them feel bad about it. Offer a retry or a payment link — but don't make the email feel like a collections notice.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Subject line example:&lt;/strong&gt; &lt;code&gt;A quick note about your [Product] subscription&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Email template:&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Hey [Name],&lt;/p&gt;

&lt;p&gt;Just a heads up — we had a small issue processing your [Product] subscription payment recently.&lt;/p&gt;

&lt;p&gt;It's likely just a timing thing. If you'd like to retry the payment now, you can do that here: &lt;strong&gt;[Retry payment →]&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Otherwise, we'll try again automatically in a few days. No action needed if you'd prefer to wait.&lt;/p&gt;

&lt;p&gt;[Your name]&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;What not to do:&lt;/strong&gt; Don't send an urgent email the same day. Don't tell them their card "was declined for insufficient funds" — they know, and spelling it out is embarrassing. Don't suggest they update their payment method (their card works fine).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Stripe Smart Retries effectiveness:&lt;/strong&gt; High. This is exactly the scenario Smart Retries is designed for — Stripe will wait and retry when the probability of success is higher. Enable Smart Retries and let it do its job before escalating to email.&lt;/p&gt;




&lt;h3&gt;
  
  
  3. &lt;code&gt;do_not_honor&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;What it means:&lt;/strong&gt; The customer's bank rejected the transaction without giving a specific reason. This is one of the most frustrating codes for customers because it's vague — their card appears to work, and they may not understand why the charge failed.&lt;/p&gt;

&lt;p&gt;Common causes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The bank's fraud detection flagged the transaction (especially common for SaaS subscriptions billed from unfamiliar merchant names or foreign entities)&lt;/li&gt;
&lt;li&gt;The card has international transaction restrictions&lt;/li&gt;
&lt;li&gt;The bank has a temporary hold on the card&lt;/li&gt;
&lt;li&gt;A security freeze the customer may not be aware of&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;How common:&lt;/strong&gt; Second most common decline code after &lt;code&gt;insufficient_funds&lt;/code&gt;. Particularly frequent for international customers or businesses with generic merchant names on statements.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What the customer needs to do:&lt;/strong&gt; Either call their bank to authorize the transaction, or use a different card.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The right recovery approach:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Timing:&lt;/strong&gt; Send within a few hours. This is time-sensitive — the longer you wait, the more likely the customer assumes everything is fine or mentally moves on.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tone:&lt;/strong&gt; Explanatory. The customer is likely confused. Your job is to explain what happened in plain language and give them two clear options.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Action:&lt;/strong&gt; Two paths — call your bank, or use a different card. Don't give them one option; some customers can't or won't call their bank, and giving them an alternative increases recovery significantly.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Subject line example:&lt;/strong&gt; &lt;code&gt;Issue with your [Product] payment — here's what happened&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Email template:&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Hey [Name],&lt;/p&gt;

&lt;p&gt;We had an issue processing your [Product] subscription payment, and I wanted to explain what happened.&lt;/p&gt;

&lt;p&gt;Your bank blocked the transaction — this is pretty common with subscription billing and usually isn't caused by anything on your end. Banks occasionally flag recurring charges from unfamiliar merchant names as a precaution.&lt;/p&gt;

&lt;p&gt;You have two options to fix it:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Option 1:&lt;/strong&gt; Call the number on the back of your card and ask them to authorize recurring payments from [Your Company/Merchant Name]. Then click here to retry: &lt;strong&gt;[Retry payment →]&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Option 2:&lt;/strong&gt; Update to a different card: &lt;strong&gt;[Update payment method →]&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Either works. Let me know if you have any questions — happy to help sort this out.&lt;/p&gt;

&lt;p&gt;[Your name]&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;What not to do:&lt;/strong&gt; Don't just send a generic "update your card" email. The card works — that's not the problem. Customers who try to update to the same card will see it fail again and give up entirely.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Stripe Smart Retries effectiveness:&lt;/strong&gt; Low to moderate. If the bank's fraud filter clears (which sometimes happens automatically), a retry may succeed. But in most cases, the customer needs to take action before the charge will go through.&lt;/p&gt;




&lt;h3&gt;
  
  
  4. &lt;code&gt;card_declined&lt;/code&gt; (generic)
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;What it means:&lt;/strong&gt; The card was declined, but Stripe didn't receive (or can't share) a more specific reason. This is the catch-all decline code — it covers situations where the bank declines without providing detailed information.&lt;/p&gt;

&lt;p&gt;Possible causes include: card restrictions, account issues, temporary bank holds, or decline policies that banks don't expose to merchants.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How common:&lt;/strong&gt; Common, but less informative than the specific codes above. When you see this, you know something went wrong but not exactly what.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What the customer needs to do:&lt;/strong&gt; Try a different card, or contact their bank to understand why it was declined.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The right recovery approach:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Timing:&lt;/strong&gt; Same day — within a few hours.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tone:&lt;/strong&gt; Helpful and low-pressure. You don't know exactly what happened, so don't pretend you do.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Action:&lt;/strong&gt; Offer two paths (retry with a different card, or contact support) without creating urgency.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Subject line example:&lt;/strong&gt; &lt;code&gt;We had trouble processing your [Product] payment&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Email template:&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Hey [Name],&lt;/p&gt;

&lt;p&gt;We had trouble processing your [Product] subscription payment. Unfortunately, we don't have more detail on the specific reason — these things happen occasionally.&lt;/p&gt;

&lt;p&gt;If you'd like to try a different card, you can update your payment method here: &lt;strong&gt;[Update payment method →]&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Or if you'd prefer to retry with the same card: &lt;strong&gt;[Retry payment →]&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Either way, let me know if you need any help sorting this out.&lt;/p&gt;

&lt;p&gt;[Your name]&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Stripe Smart Retries effectiveness:&lt;/strong&gt; Variable. Depends on the underlying reason. Smart Retries may succeed if it was a temporary bank issue; it won't succeed if the underlying issue persists.&lt;/p&gt;




&lt;h2&gt;
  
  
  Less Common But Important Failure Codes
&lt;/h2&gt;

&lt;p&gt;You'll see these less frequently, but knowing how to handle them prevents recoverable payments from slipping through.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;code&gt;card_velocity_exceeded&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;What it means:&lt;/strong&gt; The customer exceeded the balance, credit limit, transaction amount limit, or card velocity limit available on their card. Some teams shorten this in notes as &lt;code&gt;card_velocity_exceed&lt;/code&gt;, but Stripe's decline code is &lt;code&gt;card_velocity_exceeded&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What to do:&lt;/strong&gt; Wait at least 24 hours before attempting any retry. Do not email the customer urgently. A calm notification is appropriate, but the main action is on your side: pause retries, let the issuer limit clear, and ask the customer to approve the charge or use another card if the code repeats.&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;code&gt;fraudulent&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;What it means:&lt;/strong&gt; The bank has flagged this transaction as potentially fraudulent. In some cases, this may indicate a stolen or compromised card.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What to do:&lt;/strong&gt; This is one of the few codes where caution is warranted on your end. Don't retry aggressively. Send a single gentle email asking the customer to update their payment method, framed as a security precaution. If you receive multiple &lt;code&gt;fraudulent&lt;/code&gt; codes from the same customer account, consider flagging for manual review.&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;code&gt;lost_card&lt;/code&gt; / &lt;code&gt;stolen_card&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;What it means:&lt;/strong&gt; The card has been reported lost or stolen. The bank will not authorize any further charges.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What to do:&lt;/strong&gt; The customer needs to provide a new card. They may not be aware their card was flagged as lost/stolen (bank fraud systems sometimes act before the customer reports it). Send a polite email asking them to update their payment method, without referencing "lost" or "stolen" — that can create unnecessary alarm.&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;code&gt;expired_card&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;What it means:&lt;/strong&gt; Functionally identical to &lt;code&gt;card_expired&lt;/code&gt;. Handle the same way — immediate email, friendly tone, one-click update link.&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;code&gt;processing_error&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;What it means:&lt;/strong&gt; A technical error occurred during processing — not a customer issue, not a card issue. Usually transient.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What to do:&lt;/strong&gt; Retry immediately (or let Smart Retries handle it). If the retry succeeds, no email needed. If it fails again with a different code, treat the new code as the primary issue.&lt;/p&gt;




&lt;h3&gt;
  
  
  &lt;code&gt;currency_not_supported&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;What it means:&lt;/strong&gt; The card doesn't support the currency you're charging in.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What to do:&lt;/strong&gt; Email the customer explaining that their current card doesn't support the billing currency, and ask them to update to a card that does. Include your billing currency in the email so they know what to look for.&lt;/p&gt;




&lt;h2&gt;
  
  
  Quick Reference: Failure Code Action Table
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Decline code&lt;/th&gt;
&lt;th&gt;Email timing&lt;/th&gt;
&lt;th&gt;Tone&lt;/th&gt;
&lt;th&gt;Primary action&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;card_expired&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Immediate&lt;/td&gt;
&lt;td&gt;Friendly, low pressure&lt;/td&gt;
&lt;td&gt;Update card link&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;insufficient_funds&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;D+3&lt;/td&gt;
&lt;td&gt;Calm, no judgment&lt;/td&gt;
&lt;td&gt;Retry link, or wait&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;do_not_honor&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Within hours&lt;/td&gt;
&lt;td&gt;Explanatory&lt;/td&gt;
&lt;td&gt;Call bank OR new card&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;card_declined&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Same day&lt;/td&gt;
&lt;td&gt;Helpful&lt;/td&gt;
&lt;td&gt;New card OR retry&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;card_velocity_exceeded&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;D+1&lt;/td&gt;
&lt;td&gt;Calm&lt;/td&gt;
&lt;td&gt;Pause retries 24h&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;fraudulent&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Same day&lt;/td&gt;
&lt;td&gt;Security-framed&lt;/td&gt;
&lt;td&gt;Update card&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;lost_card&lt;/code&gt; / &lt;code&gt;stolen_card&lt;/code&gt;
&lt;/td&gt;
&lt;td&gt;Same day&lt;/td&gt;
&lt;td&gt;Neutral&lt;/td&gt;
&lt;td&gt;Update card (no alarm)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;processing_error&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Only if retry fails&lt;/td&gt;
&lt;td&gt;Matter-of-fact&lt;/td&gt;
&lt;td&gt;Retry first&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;currency_not_supported&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Same day&lt;/td&gt;
&lt;td&gt;Informational&lt;/td&gt;
&lt;td&gt;Card that supports currency&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Implementing Failure-Code-Specific Dunning
&lt;/h2&gt;

&lt;p&gt;The most direct path to implementing this:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Option 1: Build it yourself&lt;/strong&gt;&lt;br&gt;
Listen for &lt;code&gt;invoice.payment_failed&lt;/code&gt; webhooks, parse the &lt;code&gt;last_payment_error.decline_code&lt;/code&gt; field, and trigger the appropriate email sequence via your email provider (Resend, Postmark, etc.). A day or two of development work.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Option 2: Use a dedicated tool&lt;/strong&gt;&lt;br&gt;
&lt;a href="https://dunlo.io" rel="noopener noreferrer"&gt;Dunlo&lt;/a&gt; handles this automatically — it reads the failure code from Stripe, routes to the right email sequence, handles timing, and flags high-value accounts for personal escalation. Free during beta.&lt;/p&gt;

&lt;p&gt;Either way, the principle is the same: the failure code is the most valuable signal you have. Use it.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Bottom Line
&lt;/h2&gt;

&lt;p&gt;Stripe tells you exactly why every payment failed. Most founders ignore that information and send the same generic email to everyone.&lt;/p&gt;

&lt;p&gt;The difference between a 20% recovery rate and a 70% recovery rate isn't marketing sophistication or technical complexity. It's reading the failure code and responding appropriately.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;card_expired&lt;/code&gt; → immediate, friendly, one-click link.&lt;br&gt;
&lt;code&gt;insufficient_funds&lt;/code&gt; → wait 3 days, calm email, no urgency.&lt;br&gt;
&lt;code&gt;do_not_honor&lt;/code&gt; → explain what happened, give two options.&lt;br&gt;
&lt;code&gt;card_declined&lt;/code&gt; → same day, helpful, low pressure.&lt;/p&gt;

&lt;p&gt;That's it. Four different responses to four different problems. Start there, and you'll recover most of what you're currently losing.&lt;/p&gt;




&lt;p&gt;Want this handled automatically? &lt;a href="https://dunlo.io" rel="noopener noreferrer"&gt;Dunlo&lt;/a&gt; connects to Stripe, reads every failure code, and sends the right email at the right time — without you having to think about it. Free during beta.&lt;/p&gt;

&lt;p&gt;Originally published on &lt;a href="https://dunlo.io/blog/stripe-failure-codes" rel="noopener noreferrer"&gt;dunlo.io&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>stripe</category>
      <category>saas</category>
      <category>webdev</category>
      <category>startup</category>
    </item>
  </channel>
</rss>
