Banking
Build accounts, bank records, reconciliation, and bank-rule workflows
Mental Model
Accounts define where amounts post, and bank records represent imported financial activity. Reconciliation links those records to transactions; bank rules turn matching records into transaction proposals or automatic actions.
Resources and Lifecycle
Accounts and Assignments
Account types are ledger, bank, recurring fee, and non-posting. Categories, system assignments, active status, and banking configuration add behavior.
Bank accounts distinguish trust, operating, and external accounts plus deposit and credit-card behavior. Bank records can be transaction or balance records, active or inactive, reconciled, or matched by a rule.
Plaid credit feeds default to credit-card behavior. Relay Financial accounts
whose names end in Credit Account receive the same classification even when
Plaid reports them as checking/depository accounts.
Bank Records and Matching
Imported records retain source and account identity. Reconciliation and rule matching are relationships with their own state and recovery actions.
Read Model
Render returned account category and assignments, banking capability issues, bank-record source and reconciliation state, delete locks, matching candidates, and rule preview results. Historical postings retain inactive account identity.
Decision Table
Accounts and Feeds
| Decision | Rule |
|---|---|
| Immutable category | Disable category selector |
| Feed connect conflict | onConflict=error (default), replace, or replace-and-detach-history |
| Feed disconnect | mode=preserve-history (default) or detach-history |
Accounts return categoryLock with status: locked and reason: immutable;
respect it and disable the category selector instead of submitting a
classification change. A
feed connect conflict
occurs when the target accounting account already has a connected bank feed:
replace deactivates the old feed, and replace-and-detach-history also
detaches its unreconciled bank-record history. On
feed disconnect,
preserve-history keeps imported records attached while detach-history
detaches the unreconciled ones.
Bank Rules
| Decision | Rule |
|---|---|
| Internal transfer account | Internal bank account; never external |
| Rule condition | Description or amount comparison |
| Multiple conditions | `matchMode=all |
| Allocation | Flat, percentage, or one remainder line |
| Automatic mode | Create and match only after valid preview/configuration |
Flat and percentage rule lines cannot be mixed, and a percentage rule must satisfy the full percentage allocation without a remainder line. Every line needs an account or supported assignment.
Editability
Bank-record lock.delete.reasons[] can include notCsvSource, plaidSource,
reconciled, balanceRecord, or bankRuleMatched. Disable deletion and show
the corresponding recovery instead of trying the request repeatedly.
Reconciliation constrains transaction payment edits independently from line locks. Account assignment and category changes can affect future journal construction and party rules.
Preview and Preflight
Use Preview a bank rule
(POST /bank-rules/preview) to show
matching records and allocations. Run a saved bank rule
(POST /bank-rules/{id}/run)
supports dry run. Rule configuration has schema validation but no generic
mutation dry run.
Database-backed bank account and record mutations expose dry run where declared. Feed connections, Plaid, and provider actions have external side effects and do not.
Mutation Recipe
- Load account, category, assignment, capability, and current issue data.
- Validate bank classification and internal/external eligibility.
- Load bank-record locks and reconciliation candidates.
- Validate rule conditions and allocation shape locally.
- Preview the rule or matching proposal.
- Dry-run the final supported database mutation or saved rule run.
- Confirm and apply.
- Re-read account, record, transaction payment, and sync state.
Failure and Recovery
Use account issues[] for setup repair, such as a last-four mismatch or an
operating bank account on a team where the Operations Accounting feature is not
enabled (see the issue catalog). For delete locks, direct
the user to unreconcile,
preserve imported history, or remove the matching relationship as the reason
requires. Provider failures belong in connection health, not a local database
rollback flow.
Common Recipes
Match an imported expense
Load candidates, select the transaction, verify record totals, dry-run the supported match/update, apply, and re-read both the record and payment lock.
PUT /transactions/{transactionId}?dryRun=true
Content-Type: application/json
{
"payment": {
"status": "paid",
"date": "2026-07-18",
"bankRecordIds": ["55555555-5555-4555-8555-555555555555"]
}
}Create a percentage bank rule
Choose conditions and source accounts, use only percentage allocation lines,
validate the full allocation, preview matches, then create the rule
(POST /bank-rules) and test it.
Send this payload to /bank-rules/preview first, then to /bank-rules after
the proposed matches and allocations are confirmed:
POST /bank-rules/preview
Content-Type: application/json
{
"name": "Split cleaning charges",
"transactionType": "expense",
"mode": "suggest",
"matchMode": "all",
"conditions": [
{
"type": "description",
"operator": "contains",
"value": "cleaning"
}
],
"vendorContactId": "33333333-3333-4333-8333-333333333333",
"accountIds": ["22222222-2222-4222-8222-222222222222"],
"lines": [
{
"type": "percentage",
"amount": 60000,
"accountId": "44444444-4444-4444-8444-444444444444"
},
{
"type": "percentage",
"amount": 40000,
"accountId": "66666666-6666-4666-8666-666666666666"
}
]
}API Reference
- List accounts —
GET /accounts - List bank records —
GET /bank-records POST /accounts/{id}/connect-bank-account— Connect a bank feedPOST /accounts/{id}/disconnect-bank-account— Disconnect a bank feed- Create a bank rule —
POST /bank-rules - Preview a bank rule —
POST /bank-rules/preview - Run a bank rule —
POST /bank-rules/{id}/run
