BlogAnton Ignashev

Automating Bank Statement Reconciliation — MT940, PSD2, and the End of Manual Matching

Automating Bank Statement Reconciliation — MT940, PSD2, and the End of Manual Matching

Most of the conversation about automating accounting stops at the document. Pull the invoice, read it, book it — done. But ask anyone who closes the books what actually eats the week, and the answer is rarely invoice entry. It's the bank statement: four hundred lines, and the question isn't what each line says, it's which invoice it belongs to.

That distinction matters, because it decides what kind of tool can help you. Reading is a data problem, and it's largely solved — KSeF now delivers purchase invoices as structured data through one API, no recognition required. Matching is a reasoning problem, and it's the part that survived every wave of OCR tooling. Reconciliation is the work that starts after extraction ends.

The line is already data — that was never the bottleneck

Your bank statement has been machine-readable for decades. MT940 is a SWIFT-era text format that every Polish business bank exports: date, amount, counterparty account, the transfer title, a transaction type code. There's nothing to recognise. PSD2 open banking gives you the same content through an API instead of a file, closer to real time.

So the raw material is clean on both sides now — invoices from KSeF, payments from the bank. And yet month-end still takes days. The reason is that the two datasets don't join on anything reliable. A transfer title says FV 244/07 when the invoice number is FV/244/2026/07. Or it says platnosc za towar. Or nothing at all. The join key exists only in a human's head, reconstructed from amount, date, counterparty and habit.

What the agent actually does

A reconciliation agent runs a candidate-and-score loop rather than a lookup:

  1. Ingest the statement — an MT940 file dropped on a schedule, or a PSD2 feed polled through the day. Positions are normalised: amount, value date, counterparty IBAN, title, direction.
  2. Resolve the counterparty — the IBAN is the strongest signal you have, far better than the name string, because it's already tied to a supplier or client in your books from previous payments.
  3. Generate candidates — all open items for that counterparty within a plausible date window, plus fuzzy matches on any invoice-number-like fragment in the title.
  4. Score each candidate across the signals: exact amount, sum-of-subset amount, number similarity, date proximity, payment history patterns.
  5. Post the confident ones as drafts — a proposed booking, fully filled in, waiting for a human click.
  6. Send the rest to an exception queue with the candidates it considered and why none won.

Everything above the confidence threshold becomes a draft entry; nothing becomes a final entry on its own. This is the same discipline I apply to invoice booking, and it's non-negotiable: draft-only writes, human approval, full audit trail. If you've read how an AI agent differs from a chatbot, reconciliation is the clearest example — multi-step work with a decision at the end, not a question-answering box.

Realistic outcome on a normal Polish SMB or accounting-office portfolio: 80–90% of statement lines match automatically; the remaining 10–20% land in the queue. That last slice is not failure — it's the part that always needed a person, now isolated instead of buried.

The cases that break naive matching

Any tool can match a transfer that pays exactly one invoice with the number in the title. The value is in everything else, and this is where Polish specifics bite:

  • One transfer, several invoices. A client pays five open items with one round transfer. Amount-matching finds nothing; subset-matching finds the combination and proposes the split.
  • Partial payments. 8 000 zł against a 12 400 zł invoice. The invoice must stay open for the remainder, not get closed with a silent difference.
  • Split payment (MPP). Net to the settlement account, VAT to the VAT account — one invoice, two statement entries, one payment. A matcher that doesn't model this flags every MPP transfer as a mismatch.
  • Bank fees and FX differences. The incoming amount is 40 zł short because of a correspondent fee, or 60 zł off because it's a EUR invoice settled at a different rate. These need rule-based tolerance plus an automatic difference posting, not a human retyping.
  • Factoring and third-party payers. The money arrives from a factor, not the client on the invoice. Only counterparty-aware logic survives this.
  • Compensations and refunds. Netting against an open payable, or a returned transfer that should reopen an item rather than create income.

None of these are exotic. In a real portfolio they're a double-digit share of the statement, and they're precisely the lines that get "sorted out later" and quietly turn into the balance you can't explain in December.

The confidence threshold is a business decision, not a setting

People ask what accuracy the matching gets, which is the wrong question — it implies a single number you either accept or reject. What you actually control is where the line sits between "post as draft" and "send to a human", and that line has a cost on both sides. Set it too low and someone spends their morning correcting confident nonsense. Set it too high and the exception queue swells until the agent is just a slower inbox.

You calibrate it with your own data, not with a vendor's benchmark. Run a month in shadow mode, then look at the two distributions: how often high-score matches were right, and how often the queue contained something the agent could obviously have handled. In practice the threshold ends up different per client and even per counterparty — a supplier who always writes a clean invoice number in the title earns more trust than one who writes przelew.

This is also why accounting offices see the effect faster than single companies. A biuro rachunkowe runs the same reconciliation ritual across dozens of client portfolios, so a threshold learned on one client transfers to the next, and the payoff compounds with every portfolio added. One implementation, many months closed. For an in-house finance team the win is real but bounded by your own volume.

MT940 or PSD2: pick the boring one first

Teams over-engineer this. Start with MT940. Every bank exports it, there's no extra licensing, and a daily file is aligned with how bookkeeping actually works. Bring in PSD2 open banking when you have a reason: same-day cash position, many accounts across several banks, or a payment-triggered process where waiting until tomorrow costs something. PSD2 also carries operational overhead most people underestimate — consents expire, they have to be re-authorised, and access runs through a licensed provider.

The matching engine doesn't care which feed you use. Choose based on how fresh the data has to be, not on which acronym sounds more modern.

What you get beyond a closed statement

Once payments are reconciled continuously instead of in a month-end sprint, several things become free that nobody budgets for:

  • Overdue detection the day it happens, with a drafted payment reminder including statutory interest — instead of a quarterly discovery that a client stopped paying in May.
  • Bad-debt relief flagging — unpaid items crossing the 90-day mark from the due date get surfaced while the VAT relief is still actionable.
  • Missing-document chasing. An outgoing payment with no matching cost invoice is a strong signal that a document never reached the books — a gap that's normally found in December, if at all.
  • A cash position that's true today, because open items and actual bank balance are the same dataset.

This is the same pattern I keep running into: once the integration surface is open, the second automation is much cheaper than the first. The KSeF work opened your ERP. The invoice agent and the reconciliation agent then share one plumbing job.

How to start without a leap of faith

Take one bank account and one month. Run the agent in shadow mode: it proposes matches, a human books as usual, and you compare at the end. You'll learn two things fast — your real auto-match rate, and which of your recurring counterparties have title conventions worth teaching it.

Then switch on drafts for that account only, keep the exception queue in front of a human, and widen once the drafts are boringly correct. Same rule as everywhere else in this work: automate the volume, keep the judgment.


I build these reconciliation agents for Polish accounting offices and finance teams — MT940 or PSD2 in, drafts and an exception queue out, wired to enova365, Optima, Symfonia or your SaaS invoicing tool. If you want to know what your real auto-match rate would be, let's talk.

Let’s talk about your project

Free 30-minute consultation. We’ll figure out if and how I can help.

Book a Free 30-Minute Call

Select a date

July 2026
Mon
Tue
Wed
Thu
Fri
Sat
Sun
Back to Blog

Related Posts

Auto-Pulling Purchase Invoices From KSeF — Turning the Inbox Into Ready-to-Book Entries
Blog

Auto-Pulling Purchase Invoices From KSeF — Turning the Inbox Into Ready-to-Book Entries

KSeF already collects every purchase invoice you receive in one place, behind one API. Here's how an AI agent pulls them from KSeF, checks the counterparty against the official VAT registry, and drops ready-to-review draft entries into your books — no OCR, no re-typing.

Read more
Integrating Comarch Optima with a B2B Portal — How It Actually Works
Blog

Integrating Comarch Optima with a B2B Portal — How It Actually Works

Comarch Optima has no clean REST API like enova365. Three real integration routes to a B2B portal: distributed-work XML, direct SQL access, middleware. What to pick, how long it takes, where the traps are.

Read more
Wholesale Order Automation — From Phone Calls and Excel to a System That Runs Itself
Blog

Wholesale Order Automation — From Phone Calls and Excel to a System That Runs Itself

Your sales rep spends half the day retyping email orders into the ERP? Here's wholesale order automation broken down: B2B portal, AI email parsing, ERP integration with enova365, Subiekt and Optima — with real costs and timelines.

Read more