Friendly fraud is a customer disputing a charge they authorized. They signed up, they paid with their own card, they logged in for three months, and then they opened their banking app and tapped "I don't recognize this." Their issuer refunds them on the spot, debits you, and files the case under a fraud reason code, which means that from the network's point of view the money was stolen until you prove it was not.
There is nothing friendly about it. The name comes from the issuer's side, where the person filing is a customer in good standing rather than a thief with a stolen number. From your side the mechanics are the same as any chargeback: the funds leave, a fee lands, and a form appears with a deadline.
This post covers what the form needs for a product that never shipped in a box, and then the part that matters more: the second dispute from the same person is the one you can prevent.
Why it is most of your disputes now
Three things line up against you.
The dispute button lives in the banking app. Cancelling a subscription means finding your settings page, your billing tab, and possibly a retention flow. Disputing it means tapping a transaction and picking a reason from a list. One of the reasons is always a variant of "I don't recognize this," and the cardholder does not have to justify it.
The issuer's customer is the cardholder, not you. A commenter on the Hacker News thread about the madness of SaaS chargebacks, blibble, described the incentive plainly: "if they decline the chargeback they then take on a load of risk ... but if they just pass it on then you take all the pain." The issuer that declines a dispute is arguing with its own customer. The issuer that passes it on is arguing with nobody.
The network rules put the evidence burden on the merchant. Under Visa's scheme a claim of "I did not authorize this" on an online charge is filed as reason code 10.4, card-absent fraud, and "I paid but never got it" is 13.1, merchandise or services not received, per Stripe's reason code mapping. Both are the cardholder's assertion. Neither requires the cardholder to show anything. The merchant must show everything.
The result is that first-party misuse, the Merchant Risk Council's term for what others call first-party fraud, "represents up to 80% of all fraud-related chargebacks for many of our merchant members," per the MRC's advocacy page. Stripe's own guidance notes that fraudulent disputes are over half of all disputes, in its evidence best practices. Put the two together and the "fraud" you are fighting is, more often than not, your own customer.
Friendly fraud vs chargeback fraud
The phrase covers three people, and the response to each is different.
The accidental disputer. They saw SP*ACME1234 on a statement, did not connect it to your product, and filed. This is a statement descriptor problem and a receipt problem. Respond, but also fix the descriptor, because every one of these counts against your dispute rate regardless of outcome.
The buyer's-remorse disputer. They used the product, decided they did not want to pay, and found the dispute button before the cancel button. This is the majority. They are not a professional; they will fold if the issuer pushes back with evidence, and they usually do not come back.
The professional. They were never going to pay. They start a trial, extract the value, dispute the conversion charge, and return next month under a fresh email with the same card or the same phone. The dispute response does nothing to this person. Only memory does.
The three-way split, the fee schedule, and the network monitoring thresholds are covered in the chargeback fraud post, so this one skips ahead to the evidence and to the repeat.
The evidence that wins for SaaS and digital goods
Start with what the reviewer is looking at. Stripe's guidance is blunt about the odds: even a five-dot win likelihood in the dashboard is about a 60% chance, and "it's very difficult to overturn a disputed payment," per Stripe's best practices. A bank analyst is reading a PDF, quickly, against a reason code. Your job is to make the specific claim look false in the first page.
For a 10.4 claim, the claim is "not me." Proof of use is proof of authorization when the use is tied to the cardholder's identity: the same email as the card's billing contact, the same IP as earlier undisputed charges, the same device. Another commenter in the same Hacker News thread, jasonlotito, put the bar where it sits: "You need evidence that the card holder authorized the payment. I promise you, nothing you submitted proves that." A screenshot of your admin panel showing a user existed does not clear that bar. A login log showing the account was accessed from the card's billing city, forty times, over ninety days, does.
For a 13.1 claim, the claim is "never received it." For software, receipt is access. Show the first login after payment, the features used, the API calls made, the files downloaded, with timestamps.
The items that carry weight, roughly in order:
- Login history with timestamp, IP, and device for each session, especially sessions after the disputed charge. This is the single strongest item for both reason codes.
- Usage timestamps on things a stranger would not do: a project created, an integration connected, an export run, an API key generated.
- Support conversations where the person asks for help with the thing they now claim not to recognize. Include the relevant excerpt only, with their name and email visible.
- Terms and cancellation policy acceptance, as a screenshot of the checkout where they agreed, with the relevant clause marked, not the whole document.
- Prior undisputed charges from the same card, same email, same device or IP. This is the material Visa's Compelling Evidence 3.0 is built on.
CE 3.0 is the closest thing to a rule in your favour. For a Visa 10.4 dispute, it lets you counter with two prior transactions on the same payment credential, each between 120 and 365 days before the disputed one, with no fraud reported, where at least one of customer email, delivery address, device fingerprint, or IP address matches across all three, per Stripe's CE 3.0 support page. A subscriber on their fifth monthly charge who disputes as "not me" is exactly this shape. Stripe checks eligibility automatically, flags it in the dispute email, and pre-populates what it has, per its responding to disputes guide. The support page is careful to add that it is not an auto-win; issuers keep their discretion.
The catch is the phrase "what it has." Stripe can only match on IP, email, and device it received. If your integration never passed the customer's IP and email to the PaymentIntent, the two prior charges cannot be matched to the disputed one, and the eligibility check fails silently.
What to log before the dispute exists
Most of the win is decided before the dispute arrives. The evidence fields on Stripe's dispute object are fixed: access_activity_log, customer_purchase_ip, customer_email_address, customer_communication, cancellation_policy, cancellation_policy_disclosure, service_date, service_documentation, per the Dispute object reference. You get one submission, no edits. If the data is not in your database on the day the dispute lands, it does not exist.
So store, on every session and every purchase:
- The IP and a device identifier for every login and every checkout, keyed to the user. A stable browser fingerprint is far better than a user agent string, because the user agent changes with every browser update and is identical across everyone on the same build.
- The email and the processor's card fingerprint on each charge, so you can find the prior charges CE 3.0 needs without scrolling the Stripe dashboard.
- A timestamp on the terms acceptance, with the version of the terms that was shown.
- Product-level events with timestamps: first login after payment, key feature uses, API calls, downloads.
- Support tickets linked to the user record, not only to an email address.
Pass the IP and email through to the PaymentIntent as well, so Stripe can run the CE 3.0 match on its side.
If those five things are in your database, the evidence pack for a dispute is a query and a PDF export. If they are not, you are reconstructing a person from server logs at eleven at night, two days before the deadline.
The second dispute is the one you can prevent
Two pieces of standard advice are wrong for this reader.
"Refund everything to protect your dispute ratio." A dispute counts whether you win or lose it, so the refund reflex has a logic. But a proactive refund on request is one thing; refunding at the first sign of a complaint to head off a dispute is another. It trains the customer that the threat works, and it erases the evidence trail: a refunded charge is closed, and the prior-charge history CE 3.0 needs on the next dispute is thinner for it. Refund where the customer has a point. Do not refund because you are afraid of the form.
"Require a phone number, or 3DS, on every checkout." 3DS shifts liability for a fraud-coded dispute to the issuer, which sounds like a fix. It is a fix for stolen cards. Friendly fraud happens after purchase, by the cardholder, who will pass the 3DS challenge on their own phone and dispute anyway. What you have added is a step that fails for a share of every legitimate checkout, to stop a behaviour that is not at checkout.
The behaviour worth stopping is the repeat. The buyer's-remorse disputer mostly does not come back. The professional always does, and the email they used last time is gone. They have a new one in ten seconds. What they cannot replace as cheaply is the card, the phone number they verified with, and the browser they are sitting at.
So the mechanism is memory keyed to the durable identifiers. When a dispute lands, record the outcome against the card fingerprint, the device, and the phone, not only the account. When a new signup or a trial conversion arrives, check those keys before anything else. If the card fingerprint that disputed in June shows up on a new account in September, that account is the same person, and the right response is to decline the trial quietly rather than to let them run it and lose the next dispute too.
This is the tool I built for it. Portreeve returns allow, review, or block at signup, trial start, trial conversion, checkout, and login, and its identity graph links accounts across hashed email, device fingerprint, card fingerprint, phone, and payer wallet, so a chargeback outcome reported through the feedback API on one event marks the whole linked cluster; IP alone never links accounts, because shared egress makes it untrustworthy. Feedback is idempotent per event and outcome, so a retry from a Stripe webhook handler cannot double-mark anyone, and review never blocks a user: the flow proceeds, the event sits in a queue, and a later deny arrives as a signed webhook you can act on. The test mode and feedback docs show the loop end to end.
Whatever you use, the property to check for is that the memory survives the email change. A blocklist of email addresses is a blocklist of things the attacker has already discarded.
A dispute workflow that fits a small team
Nobody at a four-person company should be spending an afternoon on a $19 dispute. Stripe's US schedule charges $15 when the dispute arrives and another $15 if you counter, and only the second comes back, and only if you win, per Stripe's dispute pricing. Where the amount is small, the logs are thin, and CE 3.0 does not apply, accepting is often the rational choice. The workflow should make that decision quick and make the memory automatic.
- On
charge.dispute.created, pull the user by the charge, and check for CE 3.0 eligibility on the dispute object'senhanced_eligibility_types. If eligible, always counter; Stripe has done most of the assembly. - If not eligible, apply a threshold: counter when the amount justifies risking the second fee and your logs show use after the charge. Accept otherwise, and do it before the deadline so it does not become a default loss with the same fee.
- Either way, record the outcome against the identity, not only the account. Cancel the subscription, revoke access, and mark the card fingerprint, device, and phone so the next signup from any of them is screened.
- On
charge.dispute.closed, log won or lost against the user. Over a few months this tells you which evidence works for your product and which disputes were never worth the fee.
The feedback call in step three is the whole point of the workflow. With the SDK from the previous section it is one line, and it can address the account rather than a specific event when the dispute arrives out of band:
await portreeve.feedback(
{ kind: "external_user_id", value: userId },
"chargeback",
`stripe dispute ${dispute.id}`
);
Handle the Stripe webhook idempotently, since Stripe retries and so does everyone else. The handling verdicts reference covers what to do with block and review on the next signup, and the reason codes tell you which linked key triggered it.
Winning the dispute in front of you is a matter of what you logged last quarter. Not receiving the next one from the same person is a matter of what you remember about them now.
If you want the second half handled, create a free Portreeve account and screen 1,000 events a month with no card required.