API v1

API overview

All v1 endpoints at a glance.

Markdown version · llms.txt

The BennyBooks API v1 is RESTful, JSON-only, and org-scoped. All paths are relative to /api/v1.

Read endpoints

GET/api/v1/transactionsread

list_transactions

List ledger transactions for the token's organization. Results are ordered by date descending. Agents should keep limit≤50 unless exporting.

Parameters

NameTypeDescription
statusenumuncategorized, matched, receipt_missing, agent_suggested, reconciled
sourceenumnordea, stripe, manual_csv
datedateExact date (YYYY-MM-DD)
dateFromdateInclusive start date
dateTodateInclusive end date
categorystringExact category name, or __uncategorized__
descriptionstringCase-insensitive substring on description
limitintegerDefault 50 (agent-lean), max 500
offsetintegerDefault 0

Response

json
{
  "data": [ { "id": "…", "date": "2026-08-28", "amount": -842, "currency": "EUR", … } ],
  "meta": { "totalCount": 42, "limit": 50, "offset": 0 }
}
GET/api/v1/transactions/{id}read

get_transaction

Full transaction with linked notes and receipts. Prefer this over list_notes for investigation.

Parameters

NameTypeDescription
id*uuidTransaction ID

Response

json
{
  "data": {
    "transaction": { … },
    "notes": [ { "id": "…", "content": "…", "createdAt": "…" } ],
    "receipts": [ { "id": "…", "fileName": "invoice.pdf", … } ]
  }
}
GET/api/v1/categoriesread

list_categories

Chart of accounts with stable codes, synonyms, and parent links. Call before proposing categorizations. Prefer categoryCode over display names.

Response

json
{
  "data": [
    {
      "code": "5100",
      "name": "Software & tools",
      "type": "expense",
      "parentCode": "5000",
      "synonyms": ["Software", "SaaS", "Subscriptions"],
      "inUse": true
    }
  ]
}
GET/api/v1/connectorsread

list_connectors

Bank and payment connector sync status for the organization.

Response

json
{
  "data": [
    { "id": "…", "name": "Stripe", "provider": "stripe", "syncStatus": "ok", "lastSyncAt": "…" }
  ]
}
GET/api/v1/dashboard/summaryread

get_dashboard_summary

Revenue, expenses, cash position, workload counts, monthly trend, and notifications.

Response

json
{
  "data": {
    "currency": "EUR",
    "revenue": 26500,
    "expenses": 8420,
    "cashPosition": 18080,
    "uncategorized": 4,
    "missingReceipts": 2,
    "agentSuggested": 2,
    "pendingReview": 3,
    "recentTransactions": [ … ],
    "monthlyTrend": [ … ],
    "notifications": [ … ]
  }
}
GET/api/v1/proposalsread

list_pending_proposals

Pending agent proposals awaiting human approval.

Response

json
{
  "data": [ { "id": "…", "type": "categorization", "status": "pending", … } ],
  "meta": { "count": 2 }
}
GET/api/v1/proposals/{id}read

get_proposal

Single proposal by ID.

Parameters

NameTypeDescription
id*uuidProposal ID

Response

json
{ "data": { "id": "…", "type": "categorization", "status": "pending", … } }
GET/api/v1/notesread

list_notes

Notes attached to a transaction.

Parameters

NameTypeDescription
transactionId*uuidTransaction ID

Response

json
{ "data": [ { "id": "…", "content": "…", "createdAt": "…" } ] }
GET/api/v1/receipts/searchread

search_receipts

Search receipts by file name or OCR text. Returns up to 50 results.

Parameters

NameTypeDescription
q*stringSearch query

Response

json
{ "data": [ … ], "meta": { "count": 3, "limit": 50 } }
GET/api/v1/receipts/{id}read

get_receipt

Receipt metadata (not file bytes). Use session API to download files.

Parameters

NameTypeDescription
id*uuidReceipt ID

Response

json
{ "data": { "id": "…", "fileName": "invoice.pdf", "transactionId": null, … } }

Write endpoints

All writes require propose-write scope. Most writes create proposals — nothing commits until a human approves.

POST/api/v1/proposals/categorizationpropose-write

propose_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

json
{
  "transactionId": "uuid",
  "categoryCode": "5300",
  "confidence": 0.91,
  "reason": "Description matches counterparty AWS",
  "evidence": [
    { "type": "counterparty_match", "value": "aws" }
  ]
}

Response

json
{ "data": { "id": "…", "status": "pending", "type": "categorization", … } }
POST/api/v1/proposals/journal-entrypropose-write

propose_journal_entry

Propose a new manual ledger entry. Creates a pending proposal — a transaction is created only after human approval.

Request body

json
{
  "date": "2026-08-28",
  "description": "Office supplies",
  "amount": -42.50,
  "currency": "EUR",
  "categoryCode": "5200",
  "source": "manual_csv",
  "confidence": 0.88,
  "reason": "One-off office purchase"
}

Response

json
{ "data": { "id": "…", "status": "pending", "type": "journal_entry", … } }
POST/api/v1/notespropose-write

attach_note

Create a proposal to attach a note. Approval required.

Request body

json
{ "transactionId": "uuid", "content": "Client project: ACME-42" }

Response

json
{ "data": { "id": "…", "status": "pending", "type": "note", … } }
PUT/api/v1/notespropose-write

create_note

Directly create a note without approval. For trusted automation only.

Request body

json
{ "transactionId": "uuid", "content": "Client project: ACME-42" }

Response

json
{ "data": { "id": "…", "content": "…", "createdAt": "…" } }