Reconciling UPI Settlements

UPI settles in seconds and reconciles on a different clock entirely. The payer sees a success screen immediately, but the merchant credit arrives on a later settlement cycle, net of returns, and identified by a reference your application probably never stored. Almost every UPI reconciliation problem I have been called into traces back to that one gap: a system that recorded the callback as the moment money arrived.

Why it feels reconciled and is not

The success callback is a statement about authorisation, not about funds. It says the payer’s bank agreed to move money. It does not say the money reached your account, and it certainly does not say it stayed there.

Between that callback and your bank balance sit several things that can change the number: reversals where the payer’s bank later fails the debit, adjustments raised through the dispute process, and the ordinary fact that settlement happens in cycles rather than continuously. A merchant processing a few hundred transactions a day will not notice. At a few thousand, the difference stops being a rounding error and starts being a recurring meeting.

The tell is always the same. Someone opens the payment dashboard, opens the bank statement, and the two numbers are close but not equal — and nobody can say which transactions account for the gap.

Three identifiers, and which one to trust

A single UPI payment carries several references, and choosing the wrong one as your key makes matching impossible later.

There is your own order ID, which is meaningful to you and invisible to everyone else. There is the UPI transaction ID, generated by the app or PSP. And there is the RRN, the retrieval reference number, which travels with the transaction through the network.

Key the ledger on the RRN. It is the identifier that shows up in the settlement file and in the bank statement narration, which makes it the only one present on all three sides of a three-way match. Store the others too — the order ID connects the payment to your business, the transaction ID helps when talking to the PSP — but the RRN is the join column.

I have seen a team spend two weeks building a reconciliation engine keyed on their internal order ID, then discover it could not match anything in the bank file because the bank had never heard of their order ID. The engineering was fine. The join was impossible.

The state nobody models: deemed approved

Real UPI traffic contains transactions that are neither cleanly successful nor cleanly failed. The payer’s bank did not respond in time, and the network resolved the transaction by rule rather than by answer. The customer may have been debited while your system recorded a failure. Sometimes the reverse.

At low volume these look like anomalies and get handled by someone in operations. At volume they are a category, and they need somewhere to live. A ledger with two terminal states — success and failure — has no honest place to record “we do not yet know”, so it picks one, and it will be wrong for a predictable fraction of transactions.

Model the pending state explicitly, with an age. A transaction that has been indeterminate for four minutes is normal. One that has been indeterminate for four days is an operational item with money attached.

What the settlement cycle actually settles

The credit that lands in your bank account is not the sum of that day’s successful payments. It is a net figure: gross collections, minus reversals, minus adjustments, plus or minus corrections raised through the dispute process, for a window that does not align with your calendar day.

Two consequences follow, and both surprise people.

Reversals raised after the cut-off land in the next cycle, so a payment collected on Monday and reversed on Tuesday appears as a Monday credit and a Tuesday deduction. If you reconcile day by day without carrying exceptions forward, both days look wrong and neither explains the other.

And the window boundary is the network’s, not yours. Transactions near the cut-off will land on the settlement date you did not expect. This is not an error to be fixed; it is a fact to be modelled, by reconciling against the settlement file’s own dates rather than your application’s.

The reconciliation that actually works

Three positions, matched pairwise, every day, without exception.

Your ledger says what you believe happened. The settlement file says what the network is paying you. The bank statement says what actually arrived. Match ledger against settlement first, then settlement against bank. Two-way matching is where most teams stop, and it is exactly enough to be confidently wrong: your ledger and your PSP dashboard can agree perfectly while the bank tells a different story.

Every unmatched item gets a row with a reason code — reversal, timing, fee, duplicate, unknown — an age, and an owner. The reason codes matter more than the matching. A month of coded exceptions tells you where the money is actually going; a month of “unmatched: 47” tells you nothing you can act on.

Run it daily. Not weekly, not month-end. The cost of investigating a discrepancy rises steeply with age, because the people involved have forgotten the context and the supporting data has rolled off. Kal karenge is how a two-hour investigation becomes a two-day one.

What to build first

If you are starting from nothing, build in this order, because each step is independently valuable and the sequence is cheapest-first.

Store the RRN on every transaction, from today. This costs nothing and is the prerequisite for everything else. Ingest the settlement file into a table with its own dates. Write the ledger-to-settlement match and let it produce exceptions with reason codes. Then add the bank leg.

You will know it is working when month-end stops being an event. The books either balance daily or they tell you precisely which transactions do not and why — which is the same standard I apply to any ledger I build, and the same one that turned a client’s drifted books into daily balance.

If your numbers already do not match and you cannot say by how much, that is the diagnosis, not the failure — and it is worth a conversation before it becomes a rebuild.

Questions I actually get

Why does UPI need reconciliation if it settles instantly?

Because the customer experience and the money movement are two different events. The payer sees success in seconds, but the merchant credit arrives on the next settlement cycle, net of returns and adjustments. Anything that treats the success callback as the moment money arrived will drift from the bank by exactly the amount of the timing gap plus every reversal that happened afterwards.

Which identifier should the ledger key on?

The RRN, with the UPI transaction ID stored alongside it. The RRN is the identifier that appears in the settlement file and in the bank statement narration, which makes it the only one present on all three sides of the match. Your own order ID belongs in the ledger too, but it never leaves your system, so it cannot join anything.

What is a deemed-approved transaction?

One where the payer's bank never returned a definitive response in time and the network resolved it by rule rather than by answer. The customer may have been debited while your system recorded a failure, or the reverse. These are not rare edge cases at volume, and a ledger that only handles success and failure has no state to put them in.

How long should an unmatched UPI transaction stay open?

Until it is explained, with an age and an owner. A discrepancy that has been open for eleven days is a different operational problem from one opened this morning, and lumping them together hides the pattern. Auto-close after a fixed window only works if the closure writes a reason code.

Do I still need reconciliation if I use a payment gateway?

Yes, and arguably more, because the gateway adds a third position between you and the bank. The gateway's dashboard shows what the gateway believes; your ledger shows what you believe; the bank shows what actually moved. Two of those can agree while all three are wrong.

Can this be retrofitted without rebuilding the ledger?

Usually. Daily three-way reconciliation can run against an existing ledger as a read-only process and will tell you the size of the problem within a week. The rebuild question only arises if the ledger cannot represent an exception at all, which is when reconciliation has nowhere to write its findings.