Decline code

Card Declined

`card_declined` is Stripe's bare, no-detail decline outcome: the card was declined and no more specific reason code came back with it. It is a soft decline. Stripe sometimes returns this outcome alongside a Radar risk_level flag in the raw event data, but that risk_level is separate metadata, not part of the decline code itself. It helps to know how this differs from `generic_decline`. Both describe an unspecified decline, but `generic_decline` is the label Stripe applies when it has identified a broader unknown-reason scenario (including cases where Stripe's own Radar or Adaptive Acceptance system made the call). `card_declined` is the plainer, more literal "the card was declined" outcome, used when the network or issuer hands back a decline with essentially nothing attached beyond the fact of the decline. The distinction matters for engineers reading raw Stripe events, but for a merchant deciding what to do next, the practical response is the same either way: treat it as a soft, retryable decline rather than a dead end.

Back to decline codes
card_declinedRetries automatically
Draft content: this page's explanatory copy is Pass 3 template writing pending a dedicated content pass. The classification badge above and the recovery behavior described below are live, not draft: both come directly from the recovery engine.

Why it happens

As with other soft, unspecified decline codes, recurring billing sees this more often than one-time checkout because automated bank fraud screening treats scheduled, merchant-initiated charges differently from customer-initiated ones. A charge that arrives at an odd hour as part of a batch billing run, or one that follows closely after other charges on the same card, is statistically more likely to get flagged without explanation. Because the code carries no specific detail, there's no way to distinguish a fraud-related decline from a limit-related one just by looking at the code string.

How to fix it

Yes. Without more specific information, the safe assumption is that whatever triggered the decline is transient: a momentary risk flag, a system-level check, a limit brushed up against. Retrying immediately rarely helps for the same reason it doesn't help with other soft codes: the condition that caused the first decline is usually unchanged seconds later. A delayed retry gives whatever triggered the block time to clear. Because this code carries no diagnostic detail, avoid building retry logic that assumes a specific cause. Treat it as a general soft decline: retry on a delay, watch card network retry caps, and don't jump straight to a customer email before giving at least one spaced-out retry attempt a chance to succeed.

How Foxhound recovers it

A Foxhound-scheduled silent retry runs first, timed for the specific decline pattern rather than an immediate repeat. If the retry succeeds, the customer never sees anything happened. If it does not, Foxhound moves to a dunning email sequence across the following weeks, written in the merchant's own brand voice, with a hosted card-update link on every email as a passive fallback channel.

Questions

  • Both are unspecified soft declines. `generic_decline` covers Stripe's broader unknown-reason category, including cases where Stripe's own risk systems intervened. `card_declined` is the plainer bare-decline outcome with even less attached detail.

  • Foxhound's classifier keys on the code string alone, not on risk_level, so this code is treated the same regardless of what risk_level shows up in the raw event.

  • Yes. It's treated as a soft decline, meaning a delayed automatic retry is the right first move rather than treating it as a permanent block.

  • No. Give a spaced-out retry a chance first. An immediate email over a decline that resolves itself on retry creates unnecessary customer friction.

  • Retries run automatically in the background on a spaced schedule. The customer only hears from the merchant if that schedule finishes without a successful charge.

See what this looks like on your account

The free audit shows what Stripe already recovered and what is still dying, no signup required.

Run your free audit