How to Fight a Stripe Chargeback (and Win)
November 5, 2025
The average merchant wins about 30% of chargebacks they contest. Most lose because they submit the wrong evidence, or no evidence at all. With the right data attached to each transaction, you can push your win rate above 50%.
This guide covers the Stripe-specific workflow: what happens when a dispute is filed, which reason codes you can realistically win, and exactly what evidence to submit.
How Stripe Chargebacks Work
When a customer disputes a charge with their bank, Stripe:
- Debits the transaction amount plus a $15 dispute fee from your account
- Sends a
charge.dispute.createdwebhook event - Gives you 7-21 days to submit evidence
- Forwards your evidence to the card network for a decision
- Returns the funds if you win (the $15 fee is non-refundable either way)
The entire process takes 60-90 days from dispute filing to resolution.
Which Disputes Can You Win?
Not all chargeback reason codes are equally contestable. Focus your effort where evidence matters most:
| Reason Code | Dispute Type | Win Probability | Key Evidence |
|---|---|---|---|
fraudulent |
Customer claims unauthorized | Medium (40%) | IP match, email validation, usage logs |
product_not_received |
Claims non-delivery | High (60%) | Delivery tracking, access logs |
duplicate |
Claims charged twice | High (70%) | Transaction records showing distinct charges |
subscription_canceled |
Claims they cancelled | Medium (50%) | Cancellation policy, no cancellation record |
unrecognized |
Doesn't recognize charge | High (55%) | Clear billing descriptor, receipt email |
The fraudulent reason code is the most common and also the most important to contest. This is where pre-transaction data makes the biggest difference.
The Evidence That Wins Disputes
For "Fraudulent" Disputes
This is where fraud prevention data becomes your strongest weapon:
- Email validation proof, Show that the email passed validation: not disposable, valid DNS, low risk score. This demonstrates the customer used a real email address.
- IP address and geolocation, Show the purchase IP matches the customer's billing country. Include VPN/proxy detection results.
- Login and usage logs, Timestamps showing the customer logged in and used the product after purchase. This is your strongest evidence for digital products.
- Device consistency, Same device/browser used for signup and purchase.
// Example evidence data from Fidro validation
{
"email": "customer@gmail.com",
"disposable": false,
"dns_valid": true,
"risk_score": 0.12,
"ip": "203.0.113.42",
"ip_country": "US",
"vpn": false,
"proxy": false,
"validated_at": "2025-09-15T14:23:00Z"
}
For "Unrecognized" Disputes
These are often the easiest to win:
- Billing descriptor, Show what appears on their statement. If it's unclear, fix it in Stripe.
- Receipt email, Proof the customer received a receipt at their email address.
- Account activity, Login records showing continued use of the service.
For "Product Not Received" Disputes
- Access logs, For digital products, show the customer accessed the service.
- Delivery tracking, For physical products, provide shipping confirmation and tracking number.
- Download records, If applicable, show file downloads or content access.
Automating Evidence Collection
Set up a Stripe webhook listener that automatically gathers evidence when a dispute is filed:
// Stripe webhook handler
app.post('/webhooks/stripe', async (req, res) => {
const event = req.body;
if (event.type === 'charge.dispute.created') {
const dispute = event.data.object;
const charge = await stripe.charges.retrieve(dispute.charge);
// Retrieve stored Fidro validation data
const fraudData = await getFraudCheckForCustomer(charge.customer);
// Retrieve usage/access logs
const accessLogs = await getAccessLogs(charge.customer);
// Submit evidence automatically
await stripe.disputes.update(dispute.id, {
evidence: {
customer_email_address: charge.receipt_email,
customer_purchase_ip: fraudData?.ip,
access_activity_log: formatAccessLogs(accessLogs),
uncategorized_text: formatFraudEvidence(fraudData),
},
});
}
res.sendStatus(200);
});
The Prevention-First Approach
Fighting chargebacks is expensive even when you win. The $15 fee is non-refundable, and the operational cost of gathering evidence adds up.
The most effective strategy is preventing chargebacks before they happen:
- Validate emails at signup, Block disposable emails and flag high-risk addresses using Fidro's API
- Check IPs at checkout, Catch geographic mismatches and VPN usage
- Use clear billing descriptors, Set this in your Stripe dashboard
- Send receipt emails, Immediate confirmation reduces "unrecognized" disputes
- Offer easy refunds, A self-service refund is cheaper than a chargeback
Next Steps
- Set up the
charge.dispute.createdwebhook in Stripe - Start collecting fraud prevention data at signup with Fidro's free plan
- Attach validation data to every Stripe customer record
- Build your automated evidence submission pipeline