Free audit · Cross-border platforms
FX slippage: the leak you cannot claw back
This one is different from the other three. There is no missing flag, no forgotten reversal, and nothing to claw back. The money was converted at a rate, the rate carried a spread, and the spread is gone. What you can do is measure it — and measurement is what turns an invisible cost into a negotiable one.
Where the spread appears
If your platform settles in one currency and pays connected accounts in another, Stripe converts at the rate in effect when the transfer is created. That rate includes a conversion spread.
On any single transfer the spread is unremarkable — a fraction of a percent on a few hundred dollars. Across thousands of cross-border payouts it becomes a line item worth having a conversation about.
Because no API call ever fails and no webhook reports a problem, nothing in your own monitoring will ever mention it. It is the purest form of silent leak in the Connect model.
Measuring it without a third-party FX feed
The obvious approach — compare Stripe's rate against a mid-market feed — mostly restates the fact that Stripe charges a spread. That is a pricing negotiation, not a reconciliation finding, and it introduces an external dependency with its own spread into a number you need to trust.
The more useful measure is relative slippage: how did this transfer's realised rate compare to the rate the same currency pair achieved on comparable transfers the same day?
That comparison isolates outliers — the transfers where something actually went wrong — rather than reporting a constant you already agreed to. Stripe exposes the realised rate on the balance transaction behind each transfer, as exchange_rate.
const balanceTx = await stripe.balanceTransactions.retrieve(
transfer.balance_transaction as string,
);
// Populated when the transfer crossed currencies
const realisedRate = balanceTx.exchange_rate;
// Compare against the day's baseline for this pair.
// Deviations beyond ~0.8% are worth investigating.What a genuine outlier usually means
A deviation several times your normal spread rarely indicates a bad conversion. It usually indicates a misconfigured settlement currency — and that misconfiguration will keep costing money on every future transfer until someone changes a setting.
That is why FX findings are worth surfacing despite being unrecoverable: the individual loss is sunk, but the cause is often still live.
- Monthly cross-border transfer volume
- $200,000
- Typical spread
- ~0.5%
- Observed on affected transfers
- ~1.7%
- Excess cost per month
- $2,400
- Annualised, if left unchanged
- $28,800
How to reduce it
Hold a balance in the destination currency where volume justifies it, so payouts settle without conversion.
Batch cross-border payouts rather than converting per transaction, reducing the number of spread events.
Once you can quantify annual conversion cost, negotiate it. Stripe's conversion pricing is not always fixed for platforms at volume, and a documented figure is the only thing that makes that conversation productive.
What FeeGuard does about it
FeeGuard sweeps recent cross-border transfers on every balance.available and payout.failed event, comparing each realised rate against that day's baseline for the same currency pair and flagging deviations beyond 0.8%.
FX findings are explicitly excluded from automated recovery, and the dashboard says so — there is no transfer to reverse. The guidance on a FX finding is about reducing future cost, not recovering past cost. Being honest about that is the whole point of surfacing it.
Run the check yourself
Seven steps, no signup. If the number at step 6 is greater than zero, you have a leak — and you did not need us to prove it.
- 1
Export all charge.refunded events for the last 90 days.
- 2
For each charge that has a transfer, retrieve the transfer and sum reversals.
- 3
Calculate expected reversal = (amount_refunded / amount) × transfer.amount. Flag if actual < expected.
- 4
For every application_fee on those charges, confirm amount_refunded is proportional.
- 5
Pull all charge.dispute.closed with status=lost; verify transfer reversal + fee refund occurred.
- 6
Sum missing amounts. That number is your recoverable baseline.
- 7
Connect FeeGuard if you would rather this ran continuously than once.