Reconciling payouts you don't control
Card reconciliation is a solved shape. One counterparty, one settlement file a day, one clock, one definition of settled. You match rows, you age the exceptions, you go home.
Cross-border payouts break those assumptions at once. Your balance is in dollars and delivery is not. The rails close at different hours, in different time zones, on holidays that are not on your calendar. Two of them will report a payout complete at moments hours apart and both will be telling the truth about their own system.
Reconciliation stops being a matching exercise and becomes a question about definitions.
Reconcile in the currency the money moved in
Start here, because it is the mistake that generates the most noise.
Balances, amounts and fees are in USD. The exception is the field that names a local currency — the amount your customer actually paid or received. Those are two different numbers about the same event, and only one of them was directly observed by both sides.
If you match dollar totals, you are comparing two figures that each passed through a conversion, and any drift in that conversion appears as a break on every row rather than as the FX question it actually is. Match the local amount against the local amount. Then check the conversion separately, against the rate the movement settled at.
Two clean checks find the cause. One merged check finds noise. This is also why fees being fixed in dollars is useful: the fee is a firm figure and the conversion is not, so they should never be reconciled as one number. When the rate settles, and why, is its own subject — a quote is not a lock.
Three clocks
Every payout carries several timestamps that people casually call "when it happened". The timeline names them properly: when the request was received, when your balance was debited, when it was handed to the destination, when the recipient was credited.
On a fast rail those collapse into the same minute and nobody notices the distinction exists. On a slow one they span days — and a report that silently picks one of them will disagree with a report that picked another, while both are labelled "payouts, Tuesday".
The stages are already there and already ordered. Decide once, explicitly, which stage your financial reporting treats as the event date, and then do not let a dashboard quietly use a different one because that column was easier to join on.
Two directions, not one
Most reconciliation code checks one direction: for each payout we made, did it land. That catches the loss you were expecting.
The other direction catches the loss you were not. For each movement the rail reports, does your system know about it. That is how you find the dispatch that succeeded downstream while your side recorded a timeout — the case an idempotency key structurally cannot reach, because the duplicate came from your own uncertainty rather than from your caller.
A one-directional reconciliation runs clean for months and then misses the only class of break that costs real money.
Age breaks, do not count them
A break count is a number that goes up and down and tells you almost nothing. Most breaks are timing: a payout dispatched at 18:05 against a rail that cut off at 18:00 is a break until the next morning, and it is not a problem.
What matters is how long a break has been open relative to what is normal for that corridor. Each corridor publishes its own methods and limits, and its own delivery behaviour follows from them. A break older than the slowest legitimate window on its own corridor is no longer timing — it is something else, and it should page someone. The same row, at two different ages, is two entirely different events.
Which means the threshold is per corridor. A single global "alert after 24 hours" is simultaneously too twitchy for the slow corridors and far too patient for the fast ones.
Keep the stage, not just the verdict
A transaction summarises to success or failed, and that summary is what your product logic should read. It is not what your reconciliation should store.
Two failures that both summarise to failed are entirely different events if one failed before the debit and the other failed after being handed to the destination. The first is a rejected instruction. The second is money in flight that needs to come back — and there is a distinct reversed stage precisely because reversal after the fact is a real outcome rather than a variant of failure.
Persist the stage the movement reached alongside the verdict. A reconciliation that only records the verdict throws away the information that tells you which of these you are looking at, at the exact moment somebody is asking.
It has to be continuous
Daily batch reconciliation is reasonable when payouts are large and few. It stops being reasonable when they are small and many, because a full day of breaks arrives at once, in a pile, with no signal about which started first — and small and many is the normal shape here, for reasons that have nothing to do with your volume.
Reconcile continuously and let the aging logic decide what deserves attention. The batch job then becomes what it should have been: a slower, more thorough sweep that catches what the continuous pass cannot, rather than the only pass there is.
Questions, or a break you cannot explain? hi@spendfigo.com, or start in the docs.
Common questions
What is payment reconciliation?
Proving that every movement your system believes it made corresponds to money that actually moved, and that nothing moved which your system does not know about. It is a two-way check: your records against the rail, and the rail against your records.
Why is cross-border payout reconciliation harder than card reconciliation?
A card network gives you one counterparty, one settlement file and one clock. Cross-border payouts touch rails with different cut-off times, different definitions of settled, and different reporting granularity — so "the same day" is not the same day on any two of them.
What is a reconciliation break?
Any row that appears on one side of the comparison and not the other, or appears on both with different amounts, states or timestamps. Most breaks are timing rather than loss, which is exactly why they must be aged rather than merely counted.