Muin is in private beta.Watch the public release announcement —talk to us.
Falaah Falaah AI

Bank Reconciliation

Import a CSV, OFX, or QFX bank statement and let Muin auto-match transactions against your invoices and expenses, with AI suggestions for the remainder.

Bank Reconciliation is where the month-end close actually happens. You import a bank statement, Muin auto-matches the obvious transactions against your existing invoices and expenses, and an AI review drawer walks you through the remainder — suggesting ranked matches with a confidence score so you are confirming, not typing. Everything the bank sent stays in the system; nothing gets silently dropped.

If Payments Received is where money lands on an invoice and Bills is where it leaves on a payable, Reconciliation is where you prove the bank’s ledger and yours agree.

The Flow at a Glance

Import Statement (CSV / OFX / QFX / QBO) → Start Reconciliation Session →
Auto-Match (rules + AI) → Review Unmatched (per-transaction drawer) →
Confirm Matches → Session Marked Complete
StageSurface
ImportFinance > Reconciliation, Import Statement button (also bound to the R keyboard shortcut)
Statements listTable of imported statements with period, transaction count, closing balance, status
Start sessionStart Reconciliation action on an imported statement row
Auto-matchAuto-Match action on an in_progress session row
Review drawerReview action on an in_progress session row
CompleteSession status flips to completed once all transactions are matched or excluded

Every stage is durable — you can close the page mid-session, come back tomorrow, and resume exactly where you left off.


Importing a Statement

Click Import Statement (or press R) and pick a file. The file input accepts .csv, .ofx, .qfx, and .qbo. Muin handles each format natively — no conversion step, no third-party upload service.

Limits are enforced at the API boundary:

LimitValueWhy
Maximum file size20 MBLarge-bank monthly statements comfortably fit; anything larger is almost certainly the wrong file
Maximum transactions per import10,000Keeps the per-import memory footprint reasonable; forces very large banks to be split into monthly chunks
Duplicate detectionSHA-256 of the file bytesUploading the same CSV twice returns the original statement instead of creating a duplicate — no phantom transactions

If your file exceeds the transaction limit, split it by month and import separately. If the file type is not supported, the banner will tell you what was rejected and you can retry with a different file without re-opening the picker.

Success and error states

The panel above the statements table shows exactly one banner per import:

  • Success — green, shows immediately after a successful import. The new statement appears in the table with status imported.
  • Error — red with a Retry button that resets the upload and re-opens the file picker. The error text surfaces the underlying reason (unsupported format, empty file, too many transactions, file too large).

The Statements Table

Once imported, every statement has a row in the Bank Statements view. The columns are deliberately the ones you need to spot a wrong import:

ColumnWhat It Shows
BankParsed bank name + original file name
AccountMasked account number (****1234) — Muin never stores the full number
PeriodThe statement’s start and end dates, parsed from the transactions
TransactionsCount of parsed transaction rows
BalanceClosing balance, formatted in the statement’s currency
Statusimported, processing, reconciled, or failed
ActionsStart Reconciliation when imported; a ✓ Reconciled marker when the session is reconciled

Click Start Reconciliation to create a session for the statement. The statement stays linked to the session — you can see which session closed which statement from the history.


Auto-Match: Rules + AI

Once a session is running, click Auto-Match. Muin runs every unmatched transaction through a two-stage matcher:

Stage 1 — rule-based scoring (0–100)

Each potential match (an invoice, expense, or donation in the tenant) gets a confidence score built from three signals:

SignalWeightRule
Amount matchup to 50 pointsExact match = 50, within 1% = 45, within 5% = 35, within 10% = 20
Date proximityup to 30 pointsSame day = 30, within 1 day = 25, within 3 days = 20, within 7 days = 10
Description similarityup to 20 pointsInvoice number in description = 20; shared keywords with the entity description = 10–15

Any candidate scoring below 50 is dropped — suggesting a 40% match is worse than suggesting nothing. The top five remaining candidates advance.

Stage 2 — AI re-ranking

When the rule-based stage produces multiple plausible candidates, Muin sends the bank transaction plus the candidate summaries to the AI ranker, which can adjust scores based on semantic cues the keyword matcher misses (“ACME Corp Inc” vs. “ACME Corporation” on an invoice). The AI ranker is budget-limited per session to keep costs bounded — once the session budget is consumed, the remaining transactions fall back to rule-based scoring alone.

What gets applied

A threshold (default 80) decides what auto-applies vs. what surfaces as a suggestion:

ConfidenceOutcome
≥ threshold (default 80)Automatically applied — transaction is matched to the entity, no review needed
50 – thresholdLeft unmatched with ranked suggestions available in the review drawer
< 50Dropped — transaction stays unmatched with no suggestions

You can adjust the threshold from the API (min_confidence query parameter, range 50–100), but the UI defaults to 80 and most users leave it there. The session’s match rate on the sessions table shows how well the auto-matcher did at a glance.


The Review Drawer

Click Review on an in_progress session to open the reconciliation review drawer. This is where you work through transactions the auto-matcher could not confidently resolve.

Every unmatched bank transaction appears as a row. Expand a row to see up to five ranked match suggestions pulled live from the reconciliation API. Each suggestion shows:

ElementWhat It Means
Entity-type badgeinvoice, expense, donor, etc. — which record this suggestion is pointing at
Confidence badgeColor-coded: green ≥ 80, amber ≥ 60, blue otherwise
Reason textA short human-readable explanation of why this candidate was suggested (amount match, date proximity, description keyword)
Confirm buttonOne click matches the transaction to the suggested entity and records who confirmed it
AI feedback buttonThumb-up / thumb-down on the AI’s suggestion — the feedback is scoped to the reconciliation_match feature and feeds future model tuning

Confirming a suggestion posts a single match action to the bulk match endpoint. The session’s match counters update immediately and the transaction moves out of the unmatched list. You can confirm as many as you want in one sitting, or just the ones you are sure of — the session stays in_progress and waits for you to come back to the rest.

Nonprofit tenants — donor suggestions

If the organization has the nonprofit module enabled and the matcher finds a donor candidate (rather than an invoice or expense), the confirm flow opens a dedicated nonprofit reconciliation tab that lets you record the match as a donation with the right receipt metadata. This keeps donations out of the generic invoice/expense paths where they would otherwise produce an accountant-confusing ledger entry.


The Sessions Table

Switch the header filter to Reconciliation Sessions to see every session — in-progress, completed, partial, or cancelled. The columns mirror what a reviewer needs to pick up someone else’s work:

ColumnShows
SessionSession name + start timestamp
PeriodStatement start / end date
ProgressN matched / M total transactions, plus unmatched and excluded counts
Match RateA bar + percentage of transactions matched against total
Statusin_progress, completed, partial, or cancelled
ActionsAuto-Match + Review while in progress; View Report once completed

The review button disables itself once there are no unmatched transactions left, so a reviewer does not wander into an empty drawer.


What Reconciliation Does Not Do (Today)

  • Live bank-feed sync. Reconciliation is statement-file-based today. Automatic transaction sync from Plaid or the bank’s API is tracked as external work and not part of this flow.
  • Create invoices or expenses on the fly. The matcher matches against entities that already exist. If a transaction has no plausible match, you excluded it or create the invoice/expense separately first.
  • Edit parsed transactions. The raw transactions are trusted as the bank sent them. If the parse is wrong, fix the statement at the bank and re-import; the duplicate-detection will keep the original out of your way.
  • POS receipt reconciliation. POS orders have their own payment settlement path — this flow is for bank-statement transactions, not individual POS receipts.

Where Reconciliation Fits

You are hereYou might also want
ReconciliationPayments Received — to record a payment against an invoice before matching
ReconciliationBills — to record an expense before matching it to a bank debit
ReconciliationAR Aging — to see which invoices are still unpaid after reconciling

The goal: at the end of every month, every transaction on the bank statement is either matched to a Muin record or explicitly excluded — and the two ledgers agree without a spreadsheet.