Transactions

Transactions are the core of SpeyBooks' double-entry bookkeeping system. Every transaction consists of two or more lines that must balance — the sum of all line amounts must equal zero. Positive amounts represent debits, negative amounts represent credits.

Balance Constraint

The balance equation is absolute and enforced at validation:

∑ line amounts = 0

If the submitted lines do not sum to zero, the API rejects the request with a 400 error before any database writes occur. There are no exceptions, tolerances, or auto-balancing. The API consumer is responsible for sending a mathematically complete journal.

VAT on Transaction Lines

Each line optionally accepts vatRate and vatTreatment fields. These are tax reporting metadata — they tell the API how to calculate the VAT component of that line's amount for HMRC reporting purposes. They do not create additional balancing lines or modify the journal balance.

When vatRate and vatTreatment are provided on a line, the API calculates and stores vatAmount as follows:

  • inclusive — the line amount already contains VAT. vatAmount = |amount| - (|amount| / (1 + rate))
  • exclusive — the line amount is net of VAT. vatAmount = |amount| × rate
  • none or omitted — no VAT calculation is performed.

For example, on a £100 net sale with 20% VAT, the API consumer must send three explicit lines:

  1. Trade Debtors (acc_1200): +12000 (debit)
  2. Sales (acc_4000): -10000, vatRate: 20, vatTreatment: "exclusive"
  3. VAT Output (acc_2201): -2000 (credit)

The API will compute vatAmount: 2000 on the Sales line for tax reporting, but it will not inject the VAT Output line — that is the consumer's responsibility.

Transaction Statuses

  • draft — editable, excluded from reports and balances
  • posted — immutable, included in reports and balances. Posted transactions can be reconciled to confirm they match bank statements

Source Types

Each transaction records its origin:

  • manual — user-created entries
  • invoice — journals generated by invoice finalisation
  • bank_import — entries created by the bank import pipeline

System-generated transactions cannot be deleted directly — delete the source document instead.

Bank Import Categorisation

Bank import transactions initially land with one line against the Suspense account (code 9999). The categorise endpoint moves this line to the correct account, and the suggest-category endpoint uses the categorisation rules engine to propose a match.

Account Ledger

The account ledger endpoint provides a traditional ledger view for any account, with opening balance, running balance, and date-range filtering. All monetary values throughout the API are in minor units (pence).

→ The Transactions object

Endpoints