# Bank Reconciliation

**Bank Reconciliation** closes the last gap in the revenue lifecycle: a deposit has landed in your bank, and something in Suger says it should have. This page matches the two, automatically where it is confident enough and through a human review queue where it is not.

---

## Overview

Open **Revenue → Bank Reconciliation**, under **Operations** in the sidebar. The page has four summary cards, a reconciliation summary panel, and two tabs — **All Transactions** and **Review Queue**.

It reads the bank accounts you connected on the **Bank Accounts** tab of [Revenue Settings](/revenue/revenue-settings/). Until at least one account is linked there, there is nothing here to reconcile.

## How a bank transaction gets matched

Matching runs in three tiers. A transaction only reaches a person once the two automatic tiers have declined to settle it:

```d2
direction: down

bank: "Connected bank account\nPlaid or Stripe Financial Connections"
sync: "Transaction sync\nevery 15 minutes\nfirst import: 24 months\nthen a 7-day overlap window"
txn: "Bank transaction"

rules: "Tier 1 — rule-based match\namount within 0.5% or 1.00,\nwhichever is larger\nsettlement date within 3 days"
ruleok: "Rule matched?" { shape: diamond }

ai: "Tier 2 — AI-assisted scoring\nranks candidate payments, invoices,\ndisbursements and revenue records\nwithin a 7-day window"
conf: "Score at or above\n0.94 confidence?" { shape: diamond }

auto: "Auto-matched"
queue: "Tier 3 — Review Queue\nsuggestions kept with their scores"

review: "Reviewer opens Review Match" { shape: diamond }
approve: "Approve Match\npick a candidate, add a comment"
reject: "Reject Suggestion\nadd a comment"

matched: "Matched"
back: "Returned to the queue\nfor a different candidate"

bank -> sync
sync -> txn
txn -> rules
rules -> ruleok
ruleok -> auto: "yes"
ruleok -> ai: "no"
ai -> conf
conf -> auto: "yes"
conf -> queue: "no"
queue -> review
review -> approve
review -> reject
approve -> matched
reject -> back
```

The thresholds are fixed, not configurable:

| Control | Value | What it governs |
|---------|-------|-----------------|
| **Auto-match confidence** | **0.94** | The minimum score at which an AI-assisted match is accepted without review. |
| **Amount tolerance** | the larger of **0.5%** or **$1.00** | How far a deposit may differ from the expected amount and still be treated as the same money. The fixed $1.00 floor stops tiny transactions from being rejected over rounding. |
| **Date window (scoring)** | **7 days** | How far apart a transaction and a candidate revenue record may be dated. |
| **Date window (payment rules)** | **3 days** | The tighter settlement-date window the rule-based tier uses. |
| **First import** | **24 months** | History pulled when an account has never completed a sync. |
| **Overlap window** | **7 days** | Re-read before the last cursor on every later sync, so late-posted and corrected transactions are picked up. |

## Summary cards

| Card | Meaning |
|------|---------|
| **Match Rate** | The share of transactions in scope that are neither awaiting review nor carrying a variance. |
| **Needs Review** | Transactions that still need a decision. **Read the number, not the subtitle** — see the warning below. |
| **Variances** | Transactions matched to something, but for an amount that does not agree. |
| **Total Transactions** | Every bank transaction in scope. |

:::caution
**Needs Review counts three states, but its subtitle names only two.** The card's number is `unmatched + in review + AI-matched`. The line beneath it reads *N unmatched · N in review* and omits the AI-matched transactions, so the two will not add up. The **card value** is the one to trust; the subtitle is a partial breakdown, not a total.
:::

## All Transactions

The **All Transactions** tab lists every imported bank transaction with its **date**, **amount**, **currency**, **bank account**, **reference**, **description**, **match status**, **confidence**, **matched to**, and **variance**.

**Confidence** is how sure the matcher is about the match it proposed, so a low-confidence match can be reviewed before it is accepted. **Matched To** names what it was matched against. When the matched record belongs to a payout, it shows that payout's reference — or its disbursement ID — as a link that opens the same **Disbursement detail** as [Cash & Disbursements](/revenue/cash-and-disbursements/), with the payout summary, linked invoices, refund activity, and source payload; a record paid out across several payouts links to the earliest. Otherwise it shows the matched record's ID.

Narrow the list with the **bank account**, **currency** and **status** filters, or search by **amount or description**.

## Unmatched

The **Unmatched** tab is scoped to transactions with no match at all, and its label carries the count. It is deliberately separate from the Review Queue: a transaction with nothing proposed for it is a different problem from one with a proposal awaiting your decision.

## Review Queue

The **Review Queue** tab is scoped to the transactions still awaiting a decision, and its tab label carries that count. It is a table of each transaction's **Date**, **Description**, **Amount**, **Match Status**, **Confidence**, **Variance**, and **Why flagged**, and each row offers **Review Match**, which opens the review dialog.

**Why flagged** says what sent the transaction to a person:

| Why flagged | What it means |
|-------------|---------------|
| **LOW CONFIDENCE** | A match was proposed, but it was not confident enough to be accepted automatically. |
| **MANUAL REQUIRED** | Suger could not settle on a candidate automatically — none was found, or a check could not complete. |
| **AMBIGUOUS INVOICE** | The deposit refers to an AWS invoice ID that more than one revenue record shares, so Suger will not pick one on its own. |
| **VARIANCE** | The transaction matched, but the amounts differ by more than the tolerance. |
| **REVIEW REQUIRED** | No specific reason was recorded. |

To work one transaction:

1. Open the **Review Queue** tab.
2. Select **Review Match** on the transaction you want to settle.
3. Review the suggested matches. Each suggestion was saved when the transaction was scored, and shows its **confidence percentage** and the reason it was suggested.
4. If none of them is right, choose a **target type** and search for the correct record yourself.
5. Add a **comment** explaining the decision.
6. Select **Approve Match** to bind the transaction to the selected candidate, or **Reject Suggestion** to decline the suggestions without binding anything.

**Approve Match** requires a selected candidate. **Reject Suggestion** does not — it records that the suggestions were wrong and returns the transaction to the queue.

### What a transaction can be matched to

| Target type | What it is |
|-------------|------------|
| **Payment** | A payment transaction. This is the default target type. |
| **Invoice** | An invoice from [Invoices](/revenue/invoices/). |
| **Disbursement** | A marketplace or Stripe payout from [Cash & Disbursements](/revenue/cash-and-disbursements/). |
| **Revenue record** | A normalized row from [Revenue Records](/revenue/revenue-records/). |

## KPI calculation formulas

Counts are over the bank transactions in scope. Amounts are converted to USD at the rate for the reporting date; if a rate is unavailable for any currency present, the summary is not returned rather than being reported with a gap.

| KPI | Formula | Calculation details |
|-----|---------|---------------------|
| Total Transactions | `count(bank transactions in scope)` | The denominator for Match Rate. |
| Needs Review | `unmatched + in review + AI-matched` | **Includes AI-matched transactions**, which the card's subtitle does not mention. |
| Variances | `count(transactions in variance status)` | Matched, but for a disagreeing amount. |
| Review queue | `needs review + variances` | Backs the count on the **Review Queue** tab label. |
| Matched | `max(0, total transactions − review queue)` | Never negative. |
| Match Rate | `matched ÷ total transactions × 100` | Zero when there are no transactions in scope. |
| Unmatched amount | `Σ unmatched transaction amounts, converted to USD` | Summed per currency, then converted. |
| Variance amount | `Σ variance amounts, converted to USD` | Same conversion. |

## Freshness

Bank reconciliation runs on its own schedule — **every 15 minutes**, for every organization with an active bank account — and does not wait for a channel sync. Provider upserts and the overlap window make repeated runs idempotent, so a transaction is never double-imported. See [Revenue Settings](/revenue/revenue-settings/) for the accounts that feed it.
