Bank Rules
Bank rules auto-categorize your transactions so you never categorize the same kind of activity twice. Each rule is a set of conditions (merchant, amount, description, direction, or source account) plus the actions to apply when it matches — a ledger, vendor, customer, tags, or memo. Rules run in priority order with a first-match-wins engine, fire automatically on new activity, and can be bulk-applied to history. AI can even mine your past categorizations and propose rules for you.
Key capabilities
- Multi-condition matching with
all(AND) orany(OR) logic - Match on description, counterparty/merchant, amount, transaction type (inflow/outflow), or source bank account
- Eight operators: contains, starts_with, ends_with, equals, regex, greater_than, less_than, between — plus a smart
word_overlapoperator - Actions: assign a ledger, vendor, customer, registry link, tags, a memo, or mark personal
- Priority ordering with first-match-wins; drag to reorder, and pin rules above the learned bands
- Direction guard that stops an expense rule from re-booking a deposit (and vice versa), with a per-rule opt-out
- Preview any condition set against real transactions before saving
- Bulk apply to existing transactions with dry-run, date filters, and uncategorized-only scoping
- "Create rule from transaction" to turn a correctly categorized txn into a reusable rule
- AI rule suggestions from your history, surfaced as a proactive banner you can accept or skip
- Per-rule stats (lifetime matches, last matched) and a full audit panel with health and override signals
- Enable/disable without deleting; rules and matches are stamped onto each transaction for traceability
How it works
Each transaction is checked against your enabled rules in priority order (lowest number first). The first rule whose conditions match — and which passes the direction guard — wins, applies its actions, and is recorded on the transaction. Anything unmatched falls back to AI suggestion or manual categorization.
flowchart TD
txn["New transaction"] --> sort["Enabled rules sorted by priority"]
sort --> match{"Conditions match? (all / any)"}
match -->|"No"| next["Try next rule"]
next --> match
match -->|"Yes"| guard{"Direction guard ok?"}
guard -->|"Blocked"| next
guard -->|"Pass"| apply["Apply actions + tag transaction"]
match -->|"None left"| fallback["AI suggestion / manual"]How to use it
- Go to Bank Rules (under Books, at
/books/bank-rules) and click New Rule. - Add one or more conditions — e.g.
counterparty contains "Amazon"andamount less_than 100. - Pick the match logic: all (every condition) or any (at least one).
- Choose the actions: target ledger, vendor/customer, tags, memo, or mark personal.
- Click Preview to see the count and a sample of matching transactions, then save.
- Set the priority (lower = evaluated first) or drag rules to reorder; the first matching rule wins.
- Use Apply / bulk apply to backfill history — run with dry run first, then apply to uncategorized transactions or a date range.
- Toggle rules on/off anytime, and check the Audit tab for health and override signals.
Pro tips
- Always Preview before saving — it shows exactly what a rule would match and prevents an over-broad rule from miscategorizing dozens of transactions.
- Use word_overlap instead of
containsfor messy ACH/wire descriptors; it ignores corporate suffixes and bank boilerplate so "Wilson" no longer matches "Wilson Tennis". - Create rules for your top 10 recurring vendors first — that typically auto-categorizes the majority of routine activity.
- Put specific rules above general ones; because the first match wins, a narrow
amount betweenrule should sit above a broad merchant rule. - Let the direction guard do its job — an expense rule won't book an inflow. Only enable
allow_cross_directionfor legitimate cases like refunds posted back to the original expense ledger. - Review the Audit tab periodically: high override rates or
never_matchedrules are signals to rewrite or disable.
In-depth guide
Condition fields
| Field | Matches against | Notes |
|---|---|---|
description |
Raw transaction description | lowercased |
counterparty |
Clean merchant name | uses the registry canonical name when linked |
amount |
Transaction amount | compared as a positive value for positive thresholds; signed when the threshold is ≤ 0 |
transaction_type |
inflow or outflow |
derived from amount sign |
bank_account |
Source ledger | matches the source ledger or its display name |
Operators
| Operator | Applies to | Behavior |
|---|---|---|
contains / starts_with / ends_with |
text | case-insensitive substring / prefix / suffix |
equals |
text or amount | exact match (numeric for amount) |
regex |
text | case-insensitive regular expression |
greater_than / less_than |
amount | numeric comparison |
between |
amount | inclusive [min, max] range |
word_overlap |
text | requires ≥ min_matches significant tokens to overlap (default 2) |
word_overlap tokenizes both sides and drops short tokens, corporate suffixes (inc, llc, corp), pure numbers, ID/trace tokens, and ACH/wire boilerplate (orig, trace, ach, wire, etc.), so a rule learned from one ACH descriptor doesn't spuriously fire on every other ACH for the business.
Actions
| Action | Effect |
|---|---|
| Ledger | Categorize to this ledger (cannot be a bank/source account) |
| Vendor / Customer | Assign the counterparty |
| Registry link | Link to a counterparty registry entry |
| Tags | Apply tags (merged with existing tags) |
| Memo | Set the transaction memo (≤ 500 chars) |
| Mark personal | Flag as a personal expense |
| Allow cross-direction | Opt out of the direction guard for this rule |
Rule matching criteria & auto-categorization
- Enabled rules are evaluated in priority order, and the same matching logic runs whether rules fire on new activity or during bulk apply — so results never drift.
- The first rule that matches and passes the direction guard wins: its actions are applied and the transaction is tagged as categorized by rules.
- Bulk apply checks each rule so a direction-blocked high-priority rule doesn't shadow a compatible lower-priority one.
Rule ordering & precedence
Priority is 1–10000, lower runs first, and the first match wins. Learned rules occupy conventional bands; pin a rule below 100 to force it ahead of everything learned.
| Band (priority) | Source | Meaning |
|---|---|---|
| 1–99 | user-pinned | always evaluated first |
| 100–199 | user | rules you created |
| 200–299 | historical | learned from your past categorizations |
| 300–499 | ai | AI-suggested patterns |
| 500–10000 | merchant | broad merchant defaults |
Reordering via the UI rewrites priorities as 10, 20, 30, … by position.
Direction guard
To protect the books:
- A rule targeting an expense ledger will not fire on an inflow.
- A rule targeting a revenue ledger will not fire on an outflow.
- Asset, liability, and equity ledgers are direction-agnostic (transfers, owner draws, and debt paydowns can flow either way).
- Set
allow_cross_directionon a rule to bypass the guard for legitimate edge cases. - Validation also blocks targeting a bank/source account as the rule's ledger.
Statuses (audit panel)
The Audit tab triages every rule into a health status over a rolling window (default 30 days):
| Status | Meaning |
|---|---|
healthy |
matching as expected with a low override rate |
stale |
hasn't matched in ~90+ days |
noisy |
over-broad (e.g. a word_overlap rule with too few real tokens) |
high_override |
users frequently re-categorize its matches (> 25%) |
never_matched |
has never matched a transaction |
The panel also surfaces per-counterparty drift (one merchant booked to multiple categories, or unlinked merchants), a "which rules would match this transaction?" debugger, the rule a user overrode on a given transaction, and the transactions each rule currently owns. These roll-ups also feed the close score's rule-quality component.
AI suggestions
Suggestanalyzes categorized transactions and returns counterparty patterns with a ready-to-create rule payload and confidence.- A nightly refresh (and an on-demand Refresh) saves these as suggestions that drive a proactive banner.
- Accept a suggestion (optionally overriding name, priority, match logic, or actions) to materialize a real rule, or skip it to dismiss it.
- Accepted/skipped suggestions keep their status across refreshes.
Edge cases & limits
- Bulk apply caps the number of transactions per run — use date filters to process large histories in batches.
- A malformed condition evaluates to
falserather than erroring, so one bad rule can't break the whole batch. - Disabled rules are skipped during bulk apply and reported as a warning.
- Rules and stats are scoped per business, and the feature requires the AI Pro add-on.
Start free and stop categorizing the same transactions over and over.