reverse_transfer defaults to false
The parameter that decides whether your platform or your seller absorbs a refund defaults to false. Why that default is defensible, and what happens when you set it and the balance is not there.
reverse_transfer is a boolean on a Connect refund that decides whether the connected account gives back what it received. It defaults to false, which means that unless you say otherwise, your platform absorbs the refund and the seller keeps the transfer.
That much is well covered, including in our own writing. This post is about the two questions that come next and get asked far less often: why the default is false rather than true, and what actually happens when you set it and the money is not there.
What the flag does
A destination charge creates a transfer to the connected account as a side effect of the charge succeeding. Refunding the charge does not touch that transfer, because they are separate objects. reverse_transfer: true instructs Stripe to also create a reversal against the linked transfer, pulling the funds back out of the connected account's balance.
await stripe.refunds.create({
charge: chargeId,
reverse_transfer: true,
});
With the flag, the money comes back from the seller. Without it, the money comes out of your platform balance and stays with the seller. There is no third option and no default that splits the difference.
Why false is a defensible default
It is tempting to read the default as a trap, and I do not think that is fair. There is no answer to "who should absorb this refund" that is correct for every platform, and a payments API that guessed would be wrong more expensively than one that asks.
The cases where the platform should absorb it
If the refund exists because of something the platform did, taking the money back from the seller is the wrong outcome and would rightly damage the relationship.
- A booking cancelled because your availability calendar was wrong.
- A duplicate charge created by a retry in your own checkout.
- A goodwill refund your support team offered to retain a customer, for a service that was in fact delivered.
- A pricing or tax error introduced on your side after the seller had already fulfilled.
In all of these the seller did their job. They should keep the money, and reverse_transfer: false is not a bug — it is the correct commercial answer expressed as a parameter.
The cases where it should not
If the refund exists because the service was not delivered, or was delivered badly, or the buyer never received what they paid for, then the platform absorbing it means you are underwriting seller performance out of a 10% take rate. That is not sustainable and almost certainly is not what your terms say.
The practical failure is not that teams choose wrongly. It is that most refund paths never make the choice at all. The flag is absent, so every refund of every kind — platform fault, seller fault, fraud, goodwill, duplicate — resolves the same way, and the way it resolves is the expensive one. The fix is rarely "set it to true everywhere". It is to make the refund path take a reason, and derive the flag from the reason.
const platformAtFault =
reason === 'duplicate' || reason === 'platform_error' || reason === 'goodwill';
await stripe.refunds.create({
charge: chargeId,
reverse_transfer: !platformAtFault,
refund_application_fee: !platformAtFault,
});
Stripe does not error when you leave money on the table. Your margin just shrinks.
Setting it, and what happens if the balance is short
Here is the part that surprises people who have just fixed their refund code and consider the matter closed. A reversal is not a bookkeeping entry. It is an actual movement of funds out of the connected account's Stripe balance, and that balance is a real thing that can be insufficient.
Negative balances
If you reverse a $2,000 transfer against an account holding $300, the account does not refuse. It goes negative.
A negative connected account balance is recovered from that account's future earnings — subsequent charges are applied against the deficit before anything is paid out. That works if the seller keeps trading. If they do not, or if they were already leaving, the deficit sits there, and in most platform arrangements the party that ultimately makes it whole is the platform. You have converted an immediate loss into a receivable, which is genuinely better, but it is not the same as having the money.
This is why the size of the reversal window matters more than it appears. On the day of the refund the funds are usually still in the account. Two months later, after several payouts, they frequently are not — and the reversal that would have been clean becomes a debt.
What to do when you cannot reverse cleanly
Three options, roughly in order of preference. Which one is right depends on the relationship and the amount, not on the code.
- Reverse anyway and let the balance go negative, if the seller is active and will earn it back quickly. This is the normal case and it usually resolves itself within a payout cycle.
- Net it against the next transfer, by reducing the amount you send on their following sale. This needs to be something your terms allow and something the seller has been told about, but it avoids a negative balance and it tends to feel fairer to the person on the other end.
- Write it off and fix the code, if the amount is small or the account is gone. The write-off is annoying. Continuing to generate new ones because the refund path never changed is worse.
The one option I would argue against is silent, automatic clawback across a historical backlog. Technically it is the easiest of the three. Commercially it is how you turn a payments bug into a support crisis, because the first a seller hears about it is a balance that dropped overnight.
Common questions
Does reverse_transfer work on partial refunds?
Yes, and it reverses proportionally by default — refund half the charge and roughly half the transfer comes back. You can also specify the reversal amount independently if your commercial split is not proportional. Be aware that Stripe's proportional rounding is computed independently of yours, so a charge with several partial refunds against it can differ from your own arithmetic by a cent or two. That is normal and not worth alerting on.
What if the charge was a direct charge rather than a destination charge?
Then there is no linked transfer and the flag does not apply. On direct charges the funds settle in the connected account from the start, and a refund is taken from their balance rather than yours — the exposure runs the other way. Knowing which charge type you are on is a prerequisite for every other decision here.
Can I set it retroactively on refunds I already issued?
Not on the refund itself, but you can create a transfer reversal directly against the original transfer, which achieves the same movement of funds. Whether it succeeds depends entirely on the connected account's balance, which is the constraint described above.
FeeGuard is an independent product and is not affiliated with, endorsed by, or sponsored by Stripe, Inc. "Stripe" and "Stripe Connect" are trademarks of Stripe, Inc., referenced descriptively.