Blog Open the app

How to Match Bank Transactions to Invoices with Fuzzy Matching (For Finance Teams)

July 13, 2026 · 11 min read · Written by Sam Kale

Every finance team goes through the same cycle. The bank statement download lands in a folder. Someone opens the AR aging report next to it. And then a person — usually the most experienced person on the AR team — spends two or three days matching payments to invoices by eye.

The frustrating part is that it's not that the work is hard. It's that the tools don't help. VLOOKUP needs exact matches. Bank descriptions never contain exact matches. So the whole thing falls back to human effort, month after month.

Fuzzy matching is what actually fits this problem. Amount narrows the candidates. Description ↔ customer name confirms the match. Date breaks ties. In practice you can go from three days of manual reconciliation to about 20 minutes of review. Here's how to set it up.

Why Bank Descriptions Never Match Invoices

Look at a typical bank statement line for an incoming payment:

ACH CREDIT ACME COR REF#9834 ID:934821 06/28/26

Now look at the corresponding invoice:

INV-2026-4471 ACME Corporation Due 07/15/26 $4,821.00

The bank line has none of the invoice fields in a form that matches. The invoice number isn't there. The customer name is truncated. The reference number is either the bank's internal ID or something the customer typed that has no relation to your invoice number.

Common noise you'll see in bank descriptions:

The invoice side is usually clean — it comes out of your accounting system with structured customer names, invoice numbers, and amounts. So the reconciliation problem is really: how do I match a clean invoice record to a messy bank line?

Why VLOOKUP and Filters Fall Short

Most AR teams have tried three things before landing on manual reconciliation:

  1. VLOOKUP on invoice number. Works for 20-30% of payments (the ones where the customer actually referenced the invoice). Silently fails on the rest.
  2. Filter by amount. Fast when amounts are unique. Falls apart when multiple invoices are for the same amount (subscription customers, standard SKU prices).
  3. Sort by date and eyeball it. Works for a small volume. Doesn't scale beyond ~50 transactions a month.

All three break in the same place: the customer paid, the amount is unique-ish, the date is close, but the description doesn't contain the invoice number. Fuzzy matching is designed for exactly this: match on multiple noisy signals at once.

The Approach: Multi-Column Match on Amount + Description + Date

Reconciliation matches best when you use three signals blended together:

Why amount as primary? On most AR files, the amount is the single strongest signal. A payment of $4,821.00 lines up with one or two open invoices in the whole aging report. Description then confirms which one. Date is only needed as a tiebreaker.

Step 1: Prepare Your Two Files

File 1: Bank transactions

Export your bank statement (or download from your bank feed / Plaid integration) as CSV. Filter to just credit/incoming transactions if you're reconciling AR, or debit/outgoing if you're reconciling AP. Columns you want:

File 2: Open invoices

Export your AR aging report or open invoices list from QuickBooks, Xero, NetSuite, or whatever you use. Columns you want:

One tip: clean the amount columns to be plain numbers ("4821.00", not "$4,821.00"). Fuzzy matchers handle string amounts, but they compare them as strings, so "4821" vs "4,821.00" scores lower than it should.

Step 2: Configure the Match

Upload both files. Configure the match like this:

SettingValue
Left fileBank transactions
Right fileOpen invoices
Primary (left)Bank amount
Primary (right)Invoice amount
Primary weight50%
Helper 1Bank description ↔ Invoice customer — 35%
Helper 2Bank date ↔ Invoice due_date — 15%
Match typeGeneric / text

Run the match. Every bank transaction gets a ranked list of possible invoices with a similarity score. Above 90 is a confident match. 70-90 is likely correct but worth eyeballing. Below 70 is either a bad match or a bank line that doesn't correspond to any current invoice (bank fees, refunds, non-invoice deposits).

Step 3: Review the 70-90 Band

This is where the tool earns its keep. Instead of scanning every transaction, you only look at the ones in the "possibly correct" band. Typical distribution:

On a batch of 500 transactions, that leaves about 125 lines to eyeball. At 5 seconds each, you're done in 10 minutes.

Handling Bulk Payments

Bulk payments are the hardest case. Big customer wires $18,450, which is the sum of five invoices they owed you: $4,821 + $3,200 + $6,109 + $2,120 + $2,200. No single invoice matches the amount.

The workflow:

  1. Match the bulk payment to the customer first — fuzzy matching on the description will still identify "ACME LOGISTICS" as the payer.
  2. Pull that customer's list of open invoices.
  3. Try combinations of open invoices that sum to the payment amount. In most accounting systems there's an "apply payment" screen that does this — use it after fuzzy matching narrows the candidate customer.

You can't fully automate bulk payment allocation with fuzzy matching alone, but you can go from "which customer even sent this?" (the slow question) to "which of their open invoices does it cover?" (the fast question) — and the fast question is a 2-minute manual task instead of a 30-minute detective hunt.

Handling Payment Processors (Stripe, PayPal, Wise, Square)

Payment processor payouts create a specific headache: a single deposit of $12,489.42 on your bank statement represents dozens of individual customer payments that were batched by Stripe. The bank description just says STRIPE PAYOUT.

Two approaches:

  1. Match against the processor's payout report, not the invoice list. Stripe, PayPal, and Wise all provide payout reports that break each payout into its underlying transactions. Match your bank deposit to the payout total, then reconcile each processor transaction to an invoice separately.
  2. Treat processor deposits as their own bucket. Some teams reconcile them as one lump sum to a Stripe clearing account and only break them out for period-end reporting.

Either way, don't try to match "STRIPE PAYOUT" bank lines directly against individual invoices — the description carries no information that would help.

Handling Refunds, Bank Fees, and Non-Invoice Deposits

Not every bank line corresponds to an invoice. You'll see:

These will score very low on the invoice match (nothing matches, of course), which is exactly what you want. Any bank line scoring below 40 is a candidate for a non-invoice category. Have a lookup rule ("if description contains 'FEE' or 'INTEREST' → GL account 6200") for the common ones and manually assign the rest.

Common Mistakes to Avoid

Weighting description too high. Bank descriptions are so noisy that giving them 60%+ weight actively hurts accuracy. Amount is a much stronger signal — keep description as a helper.

Matching by invoice number. Only 20-30% of customers reference the invoice number in their payment. If invoice number matches, great, but don't rely on it as the primary column. Use amount instead.

Not filtering to open invoices. If you match against every invoice in the AR file (including paid ones), the tool will happily match new payments to already-closed invoices. Filter to open + partial before matching.

Ignoring the date signal. Payments usually land within 30 days of the due date. Giving date a 10-15% weight prevents the tool from matching a payment to an invoice from 2 years ago just because the amount happens to match.

Doing it once and giving up when it's not 100%. The goal isn't to eliminate manual work — it's to reduce it from days to minutes. 95% auto-matched with 5% manual review is the win. Chasing 100% is a bad use of time.

How Often to Run It

Most teams run bank reconciliation weekly. Fuzzy matching doesn't change that cadence — it just makes each run take 20 minutes instead of half a day. Some teams shift to daily reconciliation once the tool is fast enough, which improves cash visibility and catches issues faster.

The setup work (choosing weights, deciding thresholds, mapping bank fee categories) is one-time. After the first month, every subsequent reconciliation is drag-and-drop: export bank CSV, export open invoices, upload, match, review the 70-90 band, apply payments. Done.

The Bigger Picture

AR reconciliation is one of the last big finance workflows that hasn't been automated in most companies. The reason is straightforward: exact-match tools don't work on bank data, and the alternatives (enterprise cash application platforms, ML-based reconciliation engines) start at $50k/year and take 6 months to implement.

Fuzzy matching on amount plus description plus date is a much smaller step. It doesn't automate the workflow end-to-end, but it does the hard part — identifying which payment belongs to which invoice — in seconds instead of hours. Everything downstream (applying payments, closing invoices, updating the ledger) is fast once you know the match.

If your AR team is spending three days a month reconciling bank statements to invoices, they shouldn't be. The pattern is boring, the data is fuzzy, and fuzzy matching is exactly the tool for it. Give them their afternoons back.

Ready to try fuzzy reconciliation on your own AR data? Upload your bank CSV and open invoices, match on amount plus description plus date, and see how many transactions auto-match. Free for 500 rows, no signup.

Try DedupFuzzy Free