Banking API

List connected bank accounts and read or manually match bank transactions via the API.

What this does

The Banking API exposes the bank-feed view that /dashboard/banking is built on: the list of connected accounts, the running list of imported transactions, and a single endpoint to manually match a transaction to an invoice, a bill, a payment-on-account, or a categorised bank entry.

It is deliberately read-mostly — feeds are still imported via TrueLayer (or CSV upload through the in-app UI). The bot can answer questions like "show me unmatched transactions over £100" and resolve a single match when the user confirms.

When to use it

  • A bot wants to summarise recent bank activity ("£3,420 came in this week").
  • The bot needs to surface unmatched transactions for the user to act on.
  • The user confirms which invoice or bill a transaction relates to and the bot books the match.

Authentication and scopes

Requests must include Authorization: Bearer rly_your_key_here. Each endpoint requires:

  • banking:read — list accounts, list and read transactions
  • banking:write — only required for the manual-match endpoint

Endpoints

List connected accounts

GET /api/v1/banking/accounts

Returns the bank connections for the calling key's entity, with display_name, account_type, currency, last-known balance + balance_updated_at, and the id you'll pass as account_id to the transactions list.

List bank transactions

GET /api/v1/banking/transactions

Newest-first paginated list. Query params:

  • account_id — filter to a single connection
  • statusunmatched, matched, or ignored
  • from / to — inclusive date range (YYYY-MM-DD)
  • min_amount / max_amount — numeric thresholds against amount
  • page, limit — standard cursor (default 50, max 100)

Example — "unmatched over £100 in the last 30 days":

GET /api/v1/banking/transactions?status=unmatched&min_amount=100&from=2026-03-26

The response includes joined invoice_number (when matched to an invoice) and bill_supplier (when matched to a bill) for convenience.

Get a single transaction

GET /api/v1/banking/transactions/:id

Returns a single transaction scoped to the calling key's user. Same shape as the list rows.

Match a transaction

POST /api/v1/banking/transactions/:id/match

Manually match a transaction. Body shape depends on the match type:

{ "type": "invoice_match", "invoice_id": "0a1b…" }
{ "type": "bill_match",    "bill_id":    "0a1b…" }
{ "type": "payment_on_account", "poa_name": "Acme Ltd advance" }
{ "type": "bank_entry",    "category":   "Bank charges" }

invoiceId / billId / poaName (camelCase) are also accepted as aliases. After the match lands, the server runs an asynchronous mismatch check (against invoice or bill total) to flag amount discrepancies — the response is not blocked on this.

Returns { "id": "...", "matched": true } on success, 404 not_found if the transaction doesn't belong to the calling key's user, and 400 validation_error if type and the matching id field don't agree.

Test mode

Test-mode keys validate the request and return a stubbed response with "test": true in the envelope; no transaction is updated.

Notes

  • The API does not expose the underlying TrueLayer access/refresh tokens; only the connection metadata users see in /dashboard/banking.
  • Imports (CSV upload, TrueLayer sync) remain UI-only for now — the bot reads the resulting feed, it doesn't push transactions in.