Skip to content

Automation  ·  Finance

How to build bank reconciliation automation

Ninety percent of transactions match themselves and somebody spends two days on the rest. The shape of automating the ninety and surfacing the rest properly, the prompts that build it, and the production detail that decides whether it holds.

Built with Tray Headless

  1. System Bank feed
  2. Step Exact match
  3. Step Rule match
  4. Step Fuzzy propose
  5. System NetSuite
Also Unmatched queue

Matching runs in passes from exact to fuzzy, and anything unmatched stays visible and ageing rather than being written off.

The short answer

What is bank reconciliation automation?

There are four parts to bank reconciliation automation: matching in passes from exact to fuzzy instead of one algorithm, rules that a person can read and extend instead of a model nobody can audit, an unmatched queue that ages visibly, and a firm rule against writing a plug. The mistake that costs most is the plug. A balancing entry to make the reconciliation tie hides the real difference permanently, and the next person inherits a reconciliation that reconciles and is wrong.

What matters here

  • Match in passes. Exact on reference and amount clears most of it; only what survives needs cleverness.
  • Keep the rules readable. An auditor will ask why two records matched, and a model that cannot explain itself is a problem.
  • Never write a balancing entry. A plug makes the reconciliation tie and hides the difference permanently.
  • Age the unmatched queue. An item unmatched for sixty days is a different problem from one unmatched today.
  • Propose fuzzy matches, do not apply them. A wrong match is harder to find than no match.

Who this is for

You run finance operations or the close. Bank reconciliation is a spreadsheet exercise, most of it is mechanical, and the exceptions take the time.

How it works in practice

From a bank statement arriving to the reconciliation being done, in order.

  1. 1

    Statements are fetched daily, not at close

    Reconciling daily makes the exceptions small and recent instead of large and forgotten.

  2. 2

    Exact matches clear first

    Reference and amount, which is most of the volume and needs no cleverness at all.

  3. 3

    Rules handle the recurring patterns

    Standing orders, fees, FX differences, and the ones somebody adds after seeing them twice.

  4. 4

    Fuzzy candidates are proposed, never applied

    With the evidence shown, for a person to accept.

  5. 5

    Unmatched items age visibly

    With their age and value, because sixty days unmatched is a different problem from today.

  6. 6

    Nothing is ever plugged

    A difference that cannot be explained stays open and visible until somebody explains it.

What reconciliation is made of

Four parts, though the last is a discipline instead of a mechanism.

Passes from exact to fuzzy

Exact reference and amount first, then rules, then fuzzy proposals. Running one clever algorithm over everything makes the easy cases unexplainable.

Readable rules

Conditions a person can read, extend and audit. When somebody asks why two records matched, the answer has to be a sentence.

An ageing unmatched queue

Every open item with its age and value. A queue with no age is a queue nobody prioritises.

No plugs

A balancing entry hides a real difference permanently, and the reconciliation then reconciles while being wrong.

The Tray Headless prompts

Paste these into Claude Code or Codex with the Tray Headless plugin installed. Each stage runs on its own. The systems named in them are the worked example rather than a requirement, and every prompt says so.

Once per project, run /tray-workflows:set-workspace to pick the workspace these build in. Point it at a sandbox first.

  1. 1

    First, fetch statements daily

    Daily reconciliation makes exceptions small and recent.

    Headless skills build-workflow

    Use build-workflow. The systems in play are NetSuite and the bank
    feed, or whatever we run in those seats.
    
    Fetch statements daily rather than at period end, for every account and
    every currency.
    
    Validate on arrival: the account, the period, opening balance continuity
    against the previous statement, and that the file has not been received
    before.
    
    Daily is the whole difference. Reconciling monthly means facing four
    weeks of exceptions at once, each of which has been forgotten by whoever
    caused it. Reconciling daily means facing a handful, while somebody still
    remembers.
  2. 2

    Match in passes, easy first

    Most of the volume needs no cleverness at all.

    Headless skills build-workflow

    Use build-workflow. Match in passes, each recording which pass matched:
    
      1. Exact: reference and amount and date within a day
      2. Exact amount and date, unique on both sides
      3. Rules: known recurring patterns, standing orders, bank fees,
         merchant name patterns
      4. Aggregation: one bank line matching several ledger entries, such as
         a batched payment run
      5. Fuzzy: close amount within a tolerance, or similar reference
    
    Passes one to four apply automatically. Pass five proposes only.
    
    Record which pass matched each item. When an auditor asks why two records
    were matched, the answer needs to be a sentence rather than a model
    output.

    The aggregation pass is worth building properly. A payment run appearing as one bank line and forty ledger entries is otherwise forty unmatched items.

  3. 3

    Keep the rules readable and extendable

    Somebody will ask why two records matched.

    Hold match rules as readable conditions instead of as logic: a name
    pattern, an amount range, an account, a frequency, and what to match it
    against.
    
    Let finance add a rule after seeing the same exception twice, without a
    deployment. That is how the automatic match rate actually improves, and
    it is the only route that does not depend on an engineer.
    
    When a person matches something manually, offer to create a rule from it
    and show what that rule would have matched historically. Most recurring
    exceptions are visible after two occurrences and nobody ever gets round
    to writing the rule.
  4. 4

    Age the unmatched queue, and never plug

    A plug makes a reconciliation tie while being wrong.

    Headless skills tray-gotchas

    Use tray-gotchas, then handle the unmatched properly.
    
    Every unmatched item stays visible with its age, value and side. Sort by
    age and value together, because a small item unmatched for ninety days is
    frequently more interesting than a large one from yesterday.
    
    Never write a balancing entry to make a reconciliation tie. Not as a
    suspense posting, not as a rounding adjustment beyond a tiny tolerance,
    not at all.
    
    A plug makes the reconciliation reconcile and hides the real difference
    permanently. The next person inherits something that looks correct and is
    not, and the original difference is now unfindable.
    
    Handle: a duplicate bank line, which happens; a reversal matching an
    earlier item; FX differences on a foreign currency account, which should
    post to the FX account instead of being treated as unmatched; and a
    timing difference across a period end, which is expected rather than an
    exception.
  5. 5

    Report the rate and the ageing

    Both numbers say something different and useful.

    Report daily: automatic match rate by pass, unmatched count and value by
    age band, items over 30 and 60 days, manual matches made and whether a
    rule was created from them, and any proposed fuzzy match rejected.
    
    The automatic match rate is the efficiency number and the ageing is the
    risk number. A high match rate with a growing old queue is a
    reconciliation that is fast and getting worse.
    
    Alert on: an old item crossing a threshold, a sharp fall in match rate
    which usually means a bank changed a reference format, and any account
    whose statement did not arrive.
  6. 6

    Validate it, then hand the rules to finance

    Because new payment patterns appear constantly.

    Run the per-step schema checks and the whole-workflow audit before this
    touches production. Run it alongside the manual process for one period
    and compare every match.
    
    Then open the same workflow in Tray Build so finance operations can add
    match rules and adjust tolerances in the visual canvas. New payment
    patterns appear every month and each one should be a rule somebody writes
    in a minute.

What it connects to

Statements come from the bank and entries live in the ledger.

NetSuite

Read ledger entries and post matches, and hold the reconciliation status per account and period.

Reads and writes

Stripe

Read payouts and their constituent transactions, so a single payout line matches many ledger entries.

Reads

Brex

Read card settlements, which arrive batched and otherwise generate large numbers of unmatched items.

Reads

Slack

Alert on an ageing item, a fall in match rate, or a statement that did not arrive.

Writes

Snowflake

Land match history, so the automatic rate by pass and the ageing profile are trendable.

Writes

Same build, other stacks

The design does not change if you run something else in one of these seats. The same prompts build it against SAP S/4HANA, Google BigQuery, Microsoft Teams, Oracle, Databricks or Google Chat.

Named systems are the ones most teams run, not the only ones that work. Each is an authentication in your Tray workspace, referenced by name, so the workflow never holds a credential. Where we have a connector page, the name links to it.

Running it in production

This produces a control an auditor tests directly. Explicability matters as much as accuracy.

The platform runs it, not a laptop under a desk

Daily statement fetch and matching run on the same engine, so exceptions are handled while they are small and somebody remembers them.

Every match records which pass made it

Exact, rule, aggregation or accepted proposal. When an auditor asks why two records matched, that is the answer.

Credentials are managed, never in code

Bank feed access reads every transaction the company makes. Read-only, scoped per account, and held in your workspace.

Finance owns the rules

Match rules and tolerances open in Tray Build, extended by the people who see the exceptions rather than by whoever wrote the workflow.

No plug, ever

A difference that cannot be explained stays open. A reconciliation that ties because somebody balanced it is worse than one that visibly does not.

Questions people ask

Why match in passes?

Because most of the volume matches exactly on reference and amount and needs no cleverness. Running one clever algorithm over everything makes the easy cases as unexplainable as the hard ones.

Why keep the rules readable?

Because an auditor will ask why two records were matched, and the answer has to be a sentence. A model that matched them on a similarity score is a control nobody can evidence.

Why never write a plug?

Because a balancing entry makes the reconciliation tie while hiding a real difference permanently. The next person inherits something that looks correct, and the original difference is now unfindable.

Why reconcile daily?

Because monthly means facing four weeks of exceptions at once, each forgotten by whoever caused it. Daily means a handful, while somebody can still explain them.

Should fuzzy matches apply automatically?

No. Propose them with the evidence and let a person accept. A wrong match is considerably harder to find later than no match at all.

Vibe-coding app guides

Vibe-code an entire app with Helix

This moves the data between systems. It does not give anybody a screen to work in. Build that app in Claude Code, Codex or Cursor, then deploy and run it governed on Tray Helix. Same kind of guide, same kind of prompts.

How to build a budget vs actuals tracker (opens helix.tray.ai in a new tab)

Last reviewed September 2026.