See llms.txt for all machine-readable content.

Back to Templates

Match bank transactions to ledger entries with OpenAI embeddings, Slack, and Postgres

Quick overview

This workflow matches records from two HTTP APIs (for example, bank transactions and ledger entries) using fuzzy scoring and optional OpenAI-compatible embeddings, stores results in PostgreSQL, and sends ambiguous matches to Slack for signed-link human approval via n8n webhooks.

How it works

  1. Runs on a manual trigger, a 4-hour schedule, or a POST webhook call and loads matching state plus an approval secret from PostgreSQL.
  2. Fetches the left and right record sets from two configured HTTP APIs, normalizes and de-duplicates them, and stops the run if either source fails.
  3. Generates candidate pairs using amount/date blocking, applies fuzzy similarity features (amount, date, counterparty, description, references, and learned aliases), and selects which items need embeddings.
  4. Loads cached vectors from PostgreSQL, calls an OpenAI-compatible embeddings endpoint only for missing texts, and fuses semantic similarity into the text score without overriding numeric mismatches.
  5. Performs one-to-one assignment, auto-matches only high-confidence non-ambiguous pairs, and creates a review queue with the top candidates and reasons for the rest.
  6. Saves the run summary, auto-matches, review items, and any new embedding vectors to PostgreSQL, then posts review requests to Slack with HMAC-signed, expiring approval links.
  7. Serves a GET review page and a POST decision endpoint that apply the reviewer’s approval or rejection in PostgreSQL and updates learned aliases to improve future matching.

Setup

  1. Add a PostgreSQL credential (PostgreSQL 13+ recommended for UUID generation) and ensure the workflow can create/write the tm_* tables.
  2. Update the CONFIG block with your two source API URLs, headers/tokens, query parameters, and field mappings for left and right records.
  3. Provide a Slack incoming webhook URL and set approval.publicBaseUrl to your public n8n webhook base so the tm-review and tm-decide links resolve externally.
  4. If embeddings are enabled, set an OpenAI-compatible /embeddings URL, API key, model, and dimensions, or disable embeddings to run fuzzy-only.
  5. Activate the workflow so the production webhook URLs for transaction-matching, tm-review, and tm-decide are available to your callers and reviewers.