API v1
Categorize transactions
Recommended agent workflow using stable category codes, counterparties, and evidence.
Always discover the chart before proposing changes. Prefer categoryCode (e.g. 5300) over free-text labels. Include confidence, reason, and structured evidence for human review. Keep list batches small (limit≤50).
Ontology
See Reference → Ontology for chart codes, synonyms, and seed counterparties (AWS → 5300). Public JSON-LD: GET /api/v1/ontology.jsonld
Workflow
- GET /categories — load codes, names, synonyms, parentCode
- GET /transactions?status=uncategorized&limit=50 — find work items
- Match description to counterparties (AWS, Figma, …) or category synonyms
- GET /transactions/:id — read notes and receipts when unsure
- POST /proposals/categorization with categoryCode, confidence, reason, evidence
- GET /proposals — verify proposals are pending
- Tell the user: pending in Ledger → Approvals; durable trail in Log (/log)
/api/v1/categoriesreadlist_categories
Chart of accounts with stable codes, synonyms, and parent links. Call before proposing categorizations. Prefer categoryCode over display names.
Response
{
"data": [
{
"code": "5100",
"name": "Software & tools",
"type": "expense",
"parentCode": "5000",
"synonyms": ["Software", "SaaS", "Subscriptions"],
"inUse": true
}
]
}/api/v1/transactionsreadlist_transactions
List ledger transactions for the token's organization. Results are ordered by date descending. Agents should keep limit≤50 unless exporting.
Parameters
| Name | Type | Description |
|---|---|---|
| status | enum | uncategorized, matched, receipt_missing, agent_suggested, reconciled |
| source | enum | nordea, stripe, manual_csv |
| date | date | Exact date (YYYY-MM-DD) |
| dateFrom | date | Inclusive start date |
| dateTo | date | Inclusive end date |
| category | string | Exact category name, or __uncategorized__ |
| description | string | Case-insensitive substring on description |
| limit | integer | Default 50 (agent-lean), max 500 |
| offset | integer | Default 0 |
Response
{
"data": [ { "id": "…", "date": "2026-08-28", "amount": -842, "currency": "EUR", … } ],
"meta": { "totalCount": 42, "limit": 50, "offset": 0 }
}/api/v1/proposals/categorizationpropose-writepropose_categorization
Suggest a category for a transaction. Prefer categoryCode. Creates a pending proposal — the ledger is not updated until a human approves in Ledger → Approvals.
Request body
{
"transactionId": "uuid",
"categoryCode": "5300",
"confidence": 0.91,
"reason": "Description matches counterparty AWS",
"evidence": [
{ "type": "counterparty_match", "value": "aws" }
]
}Response
{ "data": { "id": "…", "status": "pending", "type": "categorization", … } }{
"transactionId": "550e8400-e29b-41d4-a716-446655440000",
"categoryCode": "5300",
"confidence": 0.91,
"reason": "Description matches counterparty AWS",
"evidence": [
{ "type": "counterparty_match", "value": "aws" }
]
}On approval, the transaction receives the canonical category name, status matched, and your proposedBy, confidence, and reason metadata. The propose and approve/reject events both appear in Log.