Skip to content
All posts

What Stripe returns and what it keeps on a refund

Stripe returns the refunded principal only; original processing fees are never returned — here is the precise statement and the platform-side math.

FeeGuard13 min read

What Stripe returns and what it keeps on a refund

This article states, from Stripe's own documentation, exactly which amounts come back when you issue a refund and which never do — then works the platform-side arithmetic so founders, platform engineers, and finance teams can book refund losses correctly instead of rediscovering them in the balance.

The rule, verbatim

Stripe's refund documentation states the rule in one sentence:

Stripe's processing fees from the original transaction aren't returned.

That sentence governs every refund you ever issue, full or partial. Here is the complete inventory of what moves when you call the refunds API or click Refund in the Dashboard.

What comes back:

  • The refund amount itself — the principal — to the buyer's original payment method. Refunds go only to that method; you cannot redirect them to a different card or bank account.
  • Nothing else. No proportional slice of the fee comes back on a partial refund, and no fee at all comes back on a full one.

What never comes back:

  • The processing fee Stripe charged when the payment succeeded. On the standard US card pricing used below, that is 2.9% of the amount plus $0.30 per charge, per Stripe's published pricing.
  • Any currency-conversion fee charged on the original payment. Stripe's FX documentation is explicit that refunds convert at the live rate on refund day and that Stripe does not refund the FX fee taken on the original transaction.

One clarification on scope: "processing fees" means the whole charge, the percentage component and the per-charge fixed component alike. Both are assessed when the payment succeeds, and neither comes back in any proportion under any refund size.

One mechanical aside that belongs in the same inventory: refunds draw on your available balance, not pending funds, and a shortfall turns a card refund into a pending one until your balance covers it. Failed refunds return the money to your balance — a process that can take up to 30 days — rather than reaching the customer, and on destination charges they deposit back to the platform balance. All of that concerns the principal. None of it touches the fee.

The early-refund exception that is not one

Some refunds settle differently at the card networks. The same documentation explains:

Some refunds—those issued shortly after the original charge—appear in the form of a reversal instead of a refund. In the case of a reversal, the original charge drops off the customer's statement, and a separate credit isn't issued.

Three operational facts follow from that paragraph:

  • You can detect which path a refund took. Consume the refund.updated event or retrieve the refund and inspect destination_details[card][type]: the value 'reversal' marks the network-reversal path, 'refund' the ordinary one. In the Dashboard, open the payment details page, click View Details on the refund entry in the Timeline, and a message states when a refund processed as a reversal.
  • Traceability differs. An Acquirer Reference Number (ARN) does not exist for reversals, because no new credit transaction moves through the network — the original charge is simply canceled.
  • Cost differs at the network layer. The documentation notes that IC+ users might see a difference in cost between reversals and refunds, because reversals usually incur lower network fees.

It is tempting to read the reversal path as Stripe handing fees back. It is not. A reversal replaces the refund leg with a cancellation of the original charge, which is why it can carry lower network cost going forward and why no ARN exists. The processing fee your platform was charged when the payment succeeded was assessed at capture time and stays assessed. You can verify the mechanics yourself:

import Stripe from 'stripe';
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY);

const refund = await stripe.refunds.retrieve('re_4242424242424242');
console.log(refund.destination_details?.card?.type);
// prints 'reversal' or 'refund'

Cheaper settlement mechanics are a discount on the return trip, not a rebate on the outbound one. Booked fees stay booked.

Who paid the fee at sale

The fee Stripe keeps on a refund was paid by someone at sale time, and Connect's three charge patterns split that role differently. The table below shows where the charge object lives, who pays Stripe's processing fee at sale, and whose balance a refund debits, per the Connect charges documentation.

PatternCharge created onProcessing fee paid at saleRefund debits
Direct (Stripe-Account header)Connected accountConnected accountConnected account balance
Destination (transfer_data[destination])PlatformPlatformPlatform balance
Separate charges and transfersPlatformPlatformPlatform balance

Two notes worth pinning down. First, on_behalf_of does not move the debit side: for destination and separate charges, with or without on_behalf_of, the platform balance is debited for refunds. Second, the pattern determines who is exposed after the unwind. On direct charges the seller absorbs the refund shock directly, and fee recovery is a conversation between platform and seller. On destination and separate charges the platform pays first and recovers from the seller only through transfer reversals. When someone asks why a single Connect refund showed up as a loss, the answer starts with this table.

What a perfect unwind leaves behind

Now put numbers on it. The assumptions, stated so you can rerun them with your own:

  • US platform, USD, standard US card pricing of 2.9% + $0.30 per charge, per Stripe's published pricing.
  • One charge of $100.00 (10,000 cents) carrying an application_fee_amount of $10.00 (1,000 cents).
  • Processing fee: 2.9% × $100.00 = $2.90, plus the $0.30 fixed component, totaling $3.20 (320 cents).
  • Destination pattern: the seller receives $100.00 − $10.00 = $90.00 via the automatic transfer.
  • Columns show net cash across sale plus refund. Goods kept are excluded from the cash view, so a buyer made whole nets zero.

Even a flawless unwind — every flag set correctly, every reversal executed in full — leaves somebody holding the processing fee. The table computes final positions for each pattern and flag set:

Pattern and flagsPlatformSellerStripeBuyerCheck
Destination, reverse_transfer=true−$3.20$0.00+$3.20$0.00sums to 0
Destination, both flags true−$13.20+$10.00+$3.20$0.00sums to 0
Destination, no flags (defaults)−$93.20+$90.00+$3.20$0.00sums to 0
Direct, refund_application_fee=true$0.00−$3.20+$3.20$0.00sums to 0
Direct, no flags (defaults)+$10.00−$13.20+$3.20$0.00sums to 0
Separate, full $70.00 reversal executed−$3.20$0.00+$3.20$0.00sums to 0
Separate, reversal not yet executed−$73.20+$70.00+$3.20$0.00sums to 0

Every row derives from the same opening position: on destination charges the platform nets +$96.80 on the charge, pays out the $90.00 transfer, and sits at +$6.80 margin; the seller holds +$90.00; Stripe holds +$3.20. Each row's arithmetic, in order:

  1. $6.80 − $100.00 + $90.00 reversal = −$3.20
  2. $6.80 − $100.00 + $90.00 − $10.00 fee refund to seller = −$13.20
  3. $6.80 − $100.00 = −$93.20
  4. Direct sale puts the seller at +$86.80 ($100.00 − $3.20 − $10.00) and the platform at +$10.00; then $86.80 − $100.00 + $10.00 = −$3.20 for the seller and $10.00 − $10.00 = $0.00 for the platform
  5. $86.80 − $100.00 = −$13.20 for the seller; the platform keeps its $10.00
  6. Separate sale puts the platform at +$26.80 ($96.80 − $70.00 transfer); then $26.80 − $100.00 + $70.00 = −$3.20
  7. $26.80 − $100.00 = −$73.20 until the manual reversal lands

The pattern to notice: in the two best cases, someone is still down exactly $3.20 — the processing fee. Every worse number is an allocation failure stacked on that constant: an unreversed transfer that leaves $90.00 sitting with the seller, an unreturned application fee, or both. Those failures are mechanical and detectable, and the destination-charge leak family is catalogued in full elsewhere. The $3.20 is not a failure. It is the documented price of the sale, and no flag setting changes it.

Partial refunds follow the same shape with proportional machinery. Refund $40.00 — 40% of the destination charge — with both flags true: the proportional reversal returns 0.40 × $90.00 = $36.00, the fee refund returns 0.40 × $10.00 = $4.00, so the platform lands at $6.80 − $40.00 + $36.00 − $4.00 = −$1.20 and the seller at $90.00 − $36.00 + $4.00 = +$58.00, while the buyer keeps the goods at a net cost of $60.00. Scan every term: the processing fee appears nowhere on the return side, in any proportion.

Refunded-volume margin arithmetic

Scale the constant up to book level. Define two rates:

  • r = refund rate: refunded dollars divided by gross sales volume.
  • f = average fee rate per refunded dollar: the all-in processing fee percentage carried by the charges being refunded.

With pricing of p percent plus a fixed c cents per charge and an average order value A, f = p + (c ÷ A). Every refunded dollar drags f along and gets none of it back, so refunds impose a floor cost of r × f per revenue dollar before any allocation mistakes — before unreversed transfers, unreturned application fees, or dispute losses enter the picture.

Illustrative inputs, labeled as assumptions rather than measurements:

  • Monthly volume of $10,000.00 at an average order value A = $50.00, meaning N = 200 charges in the period.
  • Refund rate r = 10%, meaning $1,000.00 refunded across 20 of those 200 charges (N_r = 20).

The arithmetic:

f                              = 2.9% + ($0.30 / $50.00) = 2.9% + 0.6% = 3.5%
percentage fees stranded       = 2.9% x $1,000.00        = $29.00
fixed components stranded      = 20 x $0.30              = $6.00
total fees never returning     = $29.00 + $6.00          = $35.00
cross-check                    = 3.5% x $1,000.00        = $35.00

So on this illustrative book of business, $35.00 of monthly processing fees leave with the refunds — equivalent to r × f = 10% × 3.5% = 0.35% of revenue — before a single allocation mistake is counted. Framed against unit economics: if contribution margin before refunds is m, the refund floor alone consumes r × f points of revenue margin, and the question your pricing has to answer is whether m − r × f still clears your fixed costs. Partial refunds complicate the per-charge arithmetic because the fixed component attaches to the original charge no matter how little of it you refund, and the proportional machinery around transfers follows specific rounding conventions; the partial-refund transfer math walkthrough covers that case with the same canonical numbers. Your inputs will differ. The expression will not.

Cost optimization levers Stripe documents

Stripe's refund documentation carries a short cost optimization note aimed at exactly this problem:

If your business processes a large volume of refunds close to the time of transaction, we recommend using manual authorization and capture to reduce your refund costs. Manual authorization and capture lets you better control costs by canceling payments before they're captured, or by reducing your captured amount rather than processing a refund.

The mechanism: authorize at checkout, capture when you fulfill. A PaymentIntent still in requires_capture cannot be refunded directly — you cancel the PaymentIntent instead — and cancellation moves no refund money at all, because the charge never completed. Reducing the capture amount shrinks the fee base the same way. Some refunds never come into existence, so no processing fee is stranded behind them.

Where it fits: goods and services with short fulfillment latency — same-day delivery, downloads, bookings confirmed quickly. Where it does not: the window between authorization and capture is bounded, so long lead times can outlive the hold and the payment disappears before you ever capture it.

The operational price is real. Your integration must handle the two-step flow, your order pipeline must cope with lapsed authorizations, and your reconciliation must treat canceled and reduced captures as distinct from refunds. It is a genuine lever, documented by Stripe, and it prevents the loss rather than recovering it.

Pricing and policy responses

If the fee never returns, the remaining moves are commercial:

  • Budget it. Treat r × f as a known cost-of-goods line rather than a surprise. Expected refund-driven fee loss belongs next to expected refund volume in every forecast, and the controller's close should reconcile stranded fees the way it reconciles any other realized cost.
  • Price for it. If your take rate or product margin was set assuming refunds come back whole, it is mispriced by roughly r × f. Correct it once, deliberately, instead of discovering the gap in refund-heavy weeks.
  • Watch small tickets. The fixed $0.30 component divides by order value, so f climbs as tickets shrink. A refunded $5.00 order strands 2.9% × $5.00 + $0.30 = $0.445, which is 8.9% of the ticket — nearly three times the 2.9% headline rate. Minimum-order thresholds or bundled pricing blunt that edge.
  • Write the policy down. Decide per fault class who absorbs the fee, encode the decision in your refund tooling's defaults, and let finance leadership track actual versus budgeted stranded fees. The two flags that allocate everything else — the transfer and the application fee — get their own audit in this companion reference.

None of these moves recovers the $3.20. They stop it from masquerading as an anomaly each time it appears.

Frequently asked questions

Does Stripe ever return the processing fee on a full refund?

No. Stripe's documentation is categorical: processing fees from the original transaction aren't returned, and that sentence covers full refunds without qualification. Early refunds that settle as network reversals change how money returns to the cardholder and can lower network costs on IC+ pricing, but they do not reopen the original fee. Once a charge is processed, its fee is Stripe's.

Do partial refunds return pro-rata processing fees?

No. The proportional language in Stripe's documentation applies to transfer reversals and application fee refunds, not to Stripe's own processing fee. Refund $40.00 of the $100.00 example charge and the full $3.20 stays gone — including the $0.30 fixed component, which belonged to the original charge and not to any slice of it.

Who keeps the processing fee under each charge pattern?

Stripe keeps it under all three patterns; the difference is who paid it at sale. Direct charges bill the connected account, so the seller absorbs the stranded fee when a refund lands. Destination charges and separate charges and transfers bill the platform, so the platform absorbs it and can claw back only the transfer portion from the seller through reversals — never the fee.

Does refunding the application fee put money back in the buyer's hands?

No. Application fee refunds move the platform's collected fee to the connected account, never to the cardholder. On the $100.00 destination example, setting both flags true sends $100.00 to the buyer and pushes the $10.00 fee back to the seller, which is precisely why that combination ends with the seller $10.00 positive after a full unwind.

Check your own last 90 days

FeeGuard exists because this arithmetic runs silently on every refund your platform issues. The free audit reads your last 90 days of Connect activity through a restricted, read-only API key and reports every unreclaimed application fee, unreversed transfer, and uncovered dispute loss with the amounts attached. You get the answer first; monitoring is optional afterward.

Run the free 90-day audit.

FeeGuard is an independent product and is not affiliated with, endorsed by, or sponsored by Stripe, Inc.