Browse the knowledge base

How the bank-transaction matching pipeline works

Each bank transaction is scored against every open invoice on four signals: reference (40 pts), amount (25 pts), date (20 pts), counterparty (15 pts). 90+ silently auto-matches. 70–89 auto-matches with a review flag. 50–69 appears in the suggestion inbox. Below 50 is ignored. A separate IBAN-exact + amount-exact shortcut overrides the score to auto-match.

What this article is about

You're looking at your books and trying to understand why one bank transaction matched the right invoice silently, another one shows up as a suggestion needing your click, and a third one isn't matching anything at all. The pipeline that decides is the bank-transaction matching pipeline, and it follows a deterministic scoring model that's worth knowing.

The article covers the four-signal score, the four behaviour tiers based on the score, the IBAN+amount shortcut, when matching runs, and how to override the system when it gets it wrong. For role-based access and rule creation on top of matching, see creating a custom matching rule.

The four scoring signals

When a bank transaction lands (CSV import today; Open Banking via a pan-EU PSD2 aggregator on the 2026 roadmap), the pipeline scores it against every open invoice in your books that hasn't already been matched. The score is a weighted sum of four signals:

Signal Max points What it checks
Reference 40 The bank reference text contains the invoice number, exactly or as a partial token.
Amount 25 Exact match (25), within 5 cents (20), within 1% (15), within 5% (10).
Date 20 The bank transaction date is within ±14 days of the invoice date (or due date).
Counterparty 15 The bank counterparty name matches the vendor name (exact = 15, fuzzy = up to 12).

Total possible: 100. The invoice with the highest score (above the relevant threshold) wins.

Reference (40 points) — the strongest signal

The reference is the most reliable signal because invoice numbers are usually unique. A bank reference text of INV-2026-005047 Hetzner directly points to invoice number INV-2026-005047. Even partial matches earn points: R-005047 matches R-005047 whole, or 005047 matches the tail of the invoice number.

The reference parser handles common formats: hyphenated, slash-separated, with prefix codes (e.g. INV/2026/005047). Punctuation is normalised before matching. Some banks truncate the reference field at 30 characters; the parser handles trailing-truncated references gracefully.

Amount (25 points) — graceful tolerance

Exact match earns the full 25. Tolerance bands earn less:

  • Within 5 cents: 20 points (covers rounding differences between vendor systems and your bank)
  • Within 1%: 15 points (covers small currency-conversion drift)
  • Within 5%: 10 points (covers partial-payment scenarios)
  • Beyond 5%: 0 points

Negative amounts (refunds) are treated separately — they score against credit notes, not against invoices.

Date (20 points) — wide window

Bank transactions usually post 0–14 days after the invoice date for outgoing payments, and 0–60 days after the due date for incoming payments. We use a ±14-day window around either invoice date or due date, whichever is wider. Within the window, full 20 points; outside it, 0.

For invoices with no detected due date, the window is centred on the invoice date.

Counterparty (15 points) — fuzzy name match

The bank counterparty name (the human-readable name your bank shows for the counterparty, often a slightly mangled vendor name) is matched against your Trading Partner records.

  • Exact match: 15 points
  • Fuzzy match (Levenshtein distance scaled to length, capped at ~80% similarity): up to 12 points
  • IBAN match: 15 points (even if the counterparty name is "REF-001 SEPA")

The fuzzy match handles common bank-side mangling: truncated names, abbreviations, transliterations of non-ASCII characters, missing legal-form suffixes ("GmbH" / "Ltd" / "Inc" stripped by the bank).

The IBAN + amount shortcut

A special override: if the bank transaction's IBAN exactly matches the stored IBAN of a vendor in your Trading Partners, and the amount is an exact hit against one of that vendor's open invoices, we promote the match to Strong (score ≥ 90) regardless of other signals.

This catches the common case where the bank text is purely numeric (REF-001 with no vendor name), but the IBAN unambiguously identifies the vendor. Banks often strip the human-readable counterparty when the IBAN is provided, on the theory that the IBAN is more authoritative.

For the shortcut to fire, the IBAN has to be stored on the vendor's Trading Partner record (Trading Partners → vendor → Edit → IBAN). The first time you match a transaction to an invoice from a new vendor, the IBAN is captured and stored; from then on the shortcut accelerates future matches.

The four behaviour tiers based on score

  • Score ≥ 90 (Strong) — silent auto-match. The invoice is marked as paid; the transaction is marked as matched. Nothing in your notifications. The audit log records the auto-match with the score and the contributing signals.
  • Score 70–89 (Likely) — auto-match with a review flag. Same data outcome as Strong, but it appears in the daily-digest email so you can spot-check. The review flag clears after 7 days unless you explicitly accept or reject; an unrejected auto-match is treated as accepted.
  • Score 50–69 (Possible) — suggestion created. Does not auto-match. The transaction appears in the /matching suggestion inbox with the proposed invoice; you click Accept (confirms the match) or Reject (cancels the suggestion). Multiple suggestions per transaction are shown ranked by score.
  • Score 30–49 (Weak) — hidden suggestion. The match doesn't auto-create a suggestion; it's only visible via the "show weak matches" toggle in the matching inbox. Useful for power-users who want to surface low-confidence-but-possible matches.
  • Score < 30 — ignored. No suggestion. No match.

When matching runs

Matching is event-driven and runs automatically:

  • On bank statement import — when a CSV is uploaded, every new transaction is scored against all open invoices. Older transactions (already imported) are not re-scored.
  • On new invoice upload — when a document is extracted and shown to be an invoice, the new invoice is scored against all open transactions of the past 90 days. This catches the case where you receive an invoice for a payment you already made.
  • Nightly safety sweep at 03:00 UTC — re-runs the matcher on any transactions or invoices from the past 30 days that weren't matched yet. Catches anything missed by event-driven runs (e.g. an invoice that initially scored 49 but became a match after you corrected the vendor name and the counterparty score increased).

You don't need to manually run matching. The /matching page shows the current state (auto-matched, suggested, unmatched) and lets you adjust.

Overriding the pipeline

Three override paths, in order of how much they change:

  • Per-transaction override — open a transaction, click Unmatch to break an auto-match, or Link to invoice to manually associate it with one. Doesn't affect other transactions or future scoring.
  • Per-vendor rule — see creating a custom matching rule. Rules can pre-assign categories, auto-link to recurring invoices, or ignore specific transactions (e.g. transfers between your own accounts). Rules fire before scoring, so they bypass it for the cases they cover.
  • Master-record IBAN/VAT-ID edits — updating the canonical Trading Partners record with the right IBAN and VAT ID gives all future matches a stronger signal mix. Often the highest-leverage one-time fix.

Troubleshooting

It matched a transaction to the wrong invoice. Open the transaction, click Unmatch. Then either accept a different suggestion or manually link to the correct invoice. The matched invoice goes back to "unpaid" status; the transaction goes back to "unmatched". The original auto-match is recorded in the audit log with the score and signals, so you can investigate which signal misfired.

It missed an obvious match. Most often: the bank reference text doesn't contain the invoice number, and the amount is for a partial payment. The default scoring gives 0 reference + 10 amount (within 5%) + 20 date + 15 counterparty = 45, which is below the 50 threshold. Manually link them (in /matching UI, drag transaction onto invoice, or use the link icon on the invoice detail page). If the same pattern recurs (same vendor, always partial payments), create a matching rule for that vendor.

Same vendor sends 4 invoices at €100 each, bank shows one transfer of €400. That's partial-payment matching across multiple invoices. Currently you link them manually (one transaction → multiple invoices). Multi-invoice payment matching is on the 2026 roadmap.

I want different scoring thresholds. The 50 / 70 / 90 thresholds aren't user-adjustable. Create matching rules for the specific cases where the defaults don't work — that's the supported way to override.

Many transactions are showing up in my suggestion inbox and I want to clear them. Bulk-accept from the suggestion inbox if they're all correct (the bulk-accept respects the highest-scoring suggestion per transaction). For repeated false positives from one vendor, create a rule to suppress the suggestion or to auto-match against a recurring invoice.

The same transaction matched two different invoices in a row. Shouldn't happen — once a transaction is matched, it doesn't re-score. If you unmatched it manually, the next nightly sweep will score it again. If you're seeing duplicate matches, write to [email protected] with the transaction ID.

Bank reference contains my invoice number but it's still not matching. Check whether the invoice is open (unpaid). Already-paid invoices are excluded from the matcher to prevent double-matching. If the invoice was incorrectly marked paid earlier, unmark it to make it available again.

Open Banking is on the roadmap — when does it ship? A pan-EU PSD2 aggregator integration is planned for late 2026 / early 2027. Until then, CSV import is the live path; the matching pipeline is provider-agnostic and works identically once the aggregator is live.

Related

Didn't answer your question? Write to [email protected] · the AI chat in the bottom-right corner answers most common questions.