Bank reconciliation automation that matches on the three things which actually have to agree: the transactions in your source system, the payouts your processor sends, and the lines on your bank statement. Fees, refunds, chargebacks and settlement timing are resolved by rule. Everything else lands in an exception queue with a reason a controller can act on.
Source transaction to payout to bank line. Matching only two of the three is why most reconciliations leave a residual
Settlement lag and month-end cutoff are predictable. They should not generate a queue item every day
Filterable, assignable, with the source document attached and the reason in accounting terms
An unexplained difference cleared to suspense is a control finding waiting to happen
Almost every failed reconciliation project starts from the wrong assumption about this. A payout is not a batch of charges minus fees. It is a batch of balance movements.
| Reason | What it does to the number | How it is handled |
|---|---|---|
| Fees | Netted inside the batch, so gross, fee and net are separate values | Posted as their own expense line, matched to the payout rather than to a charge |
| Refunds and partial refunds | Reduce the payout, often for a charge settled in an earlier period | Matched to the original transaction by reference, not to the current day's activity |
| Disputes and chargebacks | Hit the balance as adjustments, sometimes with a separate fee, and reverse later if won | Tracked as an open item with its own lifecycle until resolved, not written off on arrival |
| Batching and settlement timing | Today's payout clears earlier activity on a schedule that varies by country | A rule, not an exception. The match is to the settlement date, not the capture date |
| Reserves, top-ups and currency conversion | Move money with no corresponding customer transaction at all | Mapped to their own accounts, so they never pollute the transaction match |
Take Stripe as the worked example, because it is the clearest documented case. A Stripe payout settles a batch of balance transactions, which can carry charges, refunds, dispute adjustments, fees, currency conversion, reserve holds and releases, top-ups and reversals set against a settlement lag, so a payout arriving today is clearing activity captured days earlier. Any reconciliation built on payout equals today's charges minus fees produces a difference every single day. Teams then either investigate the same explainable difference repeatedly, or stop looking, which is how a real discrepancy gets missed inside the noise of an expected one.
Three separate matches, done in order. Most implementations do the first and the third and treat the middle one as a reporting problem. That is where the residual comes from.
Every order, invoice or booking in your own system matched to the corresponding charge at the processor. This is where metadata earns its place: a reference written onto the payment at creation makes the match deterministic instead of probabilistic. Catches orders that never took payment, payments with no order, and amount mismatches.
Every balance movement in the batch reconciled to the payout total: charges, refunds, adjustments, fees, reserves and conversions. This is the match that makes the other two meaningful, and the one most often skipped because the processor already reports a total. Catches disputes nobody logged and unexpected reserve activity.
The payout matched to the deposit that actually arrived. The join is the trace reference the processor provides, not the amount and date. Two payouts of the same value in the same week are common and amount-matching will pair them wrongly. Catches failed and returned payouts, and deposits that never arrived.
A constraint worth knowing before you design. Stripe's payout reconciliation report is available to accounts using automatic payouts; accounts on manual payouts use the balance report instead. For instant payouts, Stripe states it cannot identify which transactions are included at all, so those reconcile differently. If your business uses instant payouts, that belongs in the first conversation rather than being discovered during build.
An illustrative scenario rather than a client engagement, showing the shape of the problem. The figures are chosen to be legible, not to represent any particular customer.
A subscription business takes several thousand card payments a day through Stripe, bills through its own platform, and posts to Sage Intacct. On the 31st the controller sees a bank deposit that does not match anything obvious. Working through it by hand takes most of a morning, every month. Here is what is actually inside that difference.
| In the difference | Why it is there | What the automation does |
|---|---|---|
| Charges captured on the 29th and 30th | Settlement lag, so they are in this payout, not in the 29th or 30th's | Matched on settlement date. Not an exception |
| A refund issued on the 30th against a July charge | Reduces this payout; the original settled months ago | Matched to the original by reference and posted as a contra, not a reduction in current revenue |
| Two chargebacks and their fees | Posted as adjustments when the dispute was opened | Raised as open items with their own lifecycle, carried until won or lost |
| Processor fees for the batch | Netted inside the payout | Posted to the fee account, matched to the payout rather than to individual charges |
| A reserve release | Moves money with no customer transaction behind it | Mapped to its own account so it never reaches the transaction match |
| A payout scheduled for the 31st that landed on 1 November | The 31st was a Saturday; the deposit posted the next business day | Matched on trace reference, and reported in the correct period with the timing difference stated |
| One genuine discrepancy: a charge with no corresponding order | A real problem, previously invisible inside the noise | The only item in the exception queue, surfaced on the day |
The point of the example is the last row. Six of those seven lines are explainable and mechanical, and a person was spending a morning each month re-deriving them. The seventh is the one that matters, and it was being found, when it was found at all, by accident. A documented engagement at larger scale: automated settlement reconciliation across 12 banks for a payment processor.
A reconciliation engine is a rule set plus a queue. The queue is where your team actually works, so it is designed as a product rather than as a log view.
Your own identifier, written onto the payment at creation and carried through to the processor report. Deterministic, and it should clear the large majority of volume on its own.
Amount, currency, date window and customer, used where a reference is absent, on legacy transactions, for instance. Never amount and date alone: two payouts of the same value in the same week will be paired wrongly.
Explicit, versioned and finance-approved. A tolerance that nobody chose is a control weakness rather than a convenience. Many-to-one and one-to-many are both normal and both handled.
Each queue item says what it is in accounting language, such as a refund against a charge settled in a prior period, with the source document and processor record attached, so investigation does not start with opening three systems.
An exception queue nobody clears is just a slower version of the problem. Ageing is visible as a number finance watches, so a growing queue is a signal rather than a discovery.
What was decided, by whom, and when, held against the item. That record is what makes the queue audit evidence rather than a cleared row.
On the residual. Where a difference genuinely cannot be explained, it is reported as unexplained. Automatically clearing a residual to a suspense account makes the reconciliation look complete while removing the one signal that something is wrong, and an auditor will find it.
Stripe as the most common case, using balance transactions and the payout reconciliation report with trace reference and payment metadata. Other processors follow the same shape with different object names
Statement data via the bank's own API where one exists, or a supported file format such as BAI2, MT940 or CAMT.053 where it does not. Screen scraping a banking portal is the last resort, not the default
Sage Intacct, NetSuite, Dynamics 365 Business Central and QuickBooks Online, posting cash receipts, fee entries and adjustments in a shape the reconciliation can later match
Power Automate where the organisation already runs Microsoft 365, or a scheduled service where volume and error handling need more control than a flow gives
The shape of the cash posting decides whether reconciliation is possible at all, which is why the Intacct integration and the reconciliation are usually designed together rather than in sequence. Technical standards for both are on how we build finance automations.
What finance teams ask before automating payment and bank reconciliation.
Bank reconciliation automation is software that matches the transactions in your source system to the payouts your payment processor sends and to the lines on your bank statement, clearing everything a rule can explain and routing the rest to an exception queue. Done properly it is a three-way match rather than a two-way one, and it treats settlement timing, fees, refunds and disputes as rules rather than as exceptions a person re-derives each month.
Because a payout is not a batch of charges. It settles a batch of balance transactions, which can include refunds against charges from earlier periods, dispute adjustments, Stripe fees, currency conversion, reserve holds and releases, and top-ups. There is also a settlement lag, so a payout arriving today clears activity captured days earlier. Both the composition and the timing have to be modelled, or you will see a difference every day.
It needs a different approach. Stripe's payout reconciliation report is available to accounts using automatic payouts, and Stripe states that for instant payouts it cannot identify which transactions are included in each one. That does not make reconciliation impossible, but the match has to be built from balance transaction data against a reconstructed batch rather than from the report. Raise it in the first conversation, because it changes the design.
They go to an exception queue with a reason stated in accounting language, an owner, an age, and the source document and processor record attached. The resolution is recorded against the item: what was decided, by whom and when. That is what makes it audit evidence rather than a cleared row. What does not happen is an automatic write-off to suspense, because that makes the reconciliation look complete while hiding the one signal worth having.
For bank data we use the bank's API where one exists and a supported statement format such as BAI2, MT940 or CAMT.053 where it does not. On the ledger side we work with Sage Intacct, NetSuite, Dynamics 365 Business Central and QuickBooks Online. Where a bank offers only a web portal, RPA is the route, with monitoring, because screen automation breaks when the portal changes. The interface assessment establishes which applies before anything is scoped.
The variable is the interface surface rather than your transaction volume. A processor with a documented reporting API, a bank with a usable feed and a ledger with a current REST API is a short project. A bank that only offers a portal, or a processor whose reports need reconstructing, is a longer one. We assess all three before quoting, because a reconciliation priced without knowing what the bank exposes is a guess.
We start by assessing what your processor, your bank and your ledger each expose, then model where your current difference actually comes from. That assessment tells you what can clear automatically and what will always need a person, before any build is scoped.
Tell us what you need. We will send curated profiles within 4 days.