Skip to main content

Reports

Generate financial reports for analysis, compliance, and decision-making.

Reports in SpeyBooks are derived views over the ledger. They are generated on demand from posted transactions — nothing is pre-calculated, cached, or manually adjusted.

Authentication

All endpoints require a valid API key. See Authentication.

How reports work

  • Reports are read-only
  • All values are derived from transactions
  • Results are deterministic for a given ledger state
  • Changing historical transactions will change historical reports
  • There is no separate "reporting database"

Available reports

ReportEndpointDescription
Profit & Loss/v1/reports/profit-lossIncome and expenses for a period
Balance Sheet/v1/reports/balance-sheetFinancial position at a point in time
Trial Balance/v1/reports/trial-balanceAll account balances for verification
VAT Return/v1/reports/vatVAT summary for MTD submission
General Ledger/v1/reports/general-ledgerDetailed ledger by account
Dashboard/v1/reports/dashboardHigh-level financial overview
Aged Debtors/v1/reports/aged-debtorsOutstanding receivables by age
Aged Creditors/v1/reports/aged-creditorsOutstanding payables by age
Financial Periods/v1/reports/periodsConfigured financial periods

Profit & Loss

GET /v1/reports/profit-loss

Income statement showing revenue, expenses, and net profit for a date range.

curl "https://api.speybooks.com/v1/reports/profit-loss?from=2026-01-01&to=2026-03-31" \
-H "Authorization: Bearer sk_live_your_api_key"

Parameters

ParameterTypeRequiredDescription
fromstringYesStart date (YYYY-MM-DD)
tostringYesEnd date (YYYY-MM-DD)
comparativebooleanNoInclude prior period comparison

Response

{
"success": true,
"data": {
"period": {
"from": "2026-01-01",
"to": "2026-03-31"
},
"revenue": {
"accounts": [
{ "id": "acc_4000", "code": "4000", "name": "Sales", "balance": 5000000 },
{ "id": "acc_4100", "code": "4100", "name": "Consulting", "balance": 1500000 }
],
"total": 6500000
},
"expenses": {
"accounts": [
{ "id": "acc_5100", "code": "5100", "name": "Office Expenses", "balance": 250000 },
{ "id": "acc_5200", "code": "5200", "name": "Software", "balance": 500000 },
{ "id": "acc_5300", "code": "5300", "name": "Professional Fees", "balance": 750000 }
],
"total": 1500000
},
"grossProfit": 6500000,
"netProfit": 5000000,
"comparative": null
}
}

Response with comparative

When comparative=true, includes the equivalent prior period:

{
"success": true,
"data": {
"period": { "from": "2026-01-01", "to": "2026-03-31" },
"revenue": { "total": 6500000 },
"expenses": { "total": 1500000 },
"netProfit": 5000000,
"comparative": {
"period": { "from": "2025-10-01", "to": "2025-12-31" },
"totalRevenue": 5200000,
"totalExpenses": 1300000,
"netProfit": 3900000
}
}
}

Notes

  • Revenue accounts normally carry credit balances
  • Expense accounts normally carry debit balances
  • Net profit = revenue − expenses

Balance Sheet

GET /v1/reports/balance-sheet

Statement of financial position as at a specific date.

curl "https://api.speybooks.com/v1/reports/balance-sheet?asOf=2026-03-31" \
-H "Authorization: Bearer sk_live_your_api_key"

Parameters

ParameterTypeRequiredDescription
asOfstringYesReport date (YYYY-MM-DD)

Response

{
"success": true,
"data": {
"asOf": "2026-03-31",
"assets": {
"accounts": [
{ "id": "acc_1100", "code": "1100", "name": "Accounts Receivable", "balance": 1250000 },
{ "id": "acc_1200", "code": "1200", "name": "Bank Account", "balance": 8500000 },
{ "id": "acc_1500", "code": "1500", "name": "Equipment", "balance": 2000000 }
],
"total": 11750000
},
"liabilities": {
"accounts": [
{ "id": "acc_2100", "code": "2100", "name": "Accounts Payable", "balance": 450000 },
{ "id": "acc_2200", "code": "2200", "name": "VAT Payable", "balance": 350000 }
],
"total": 800000
},
"equity": {
"accounts": [
{ "id": "acc_3000", "code": "3000", "name": "Share Capital", "balance": 100000 },
{ "id": "acc_3100", "code": "3100", "name": "Retained Earnings", "balance": 5850000 },
{ "id": "acc_3200", "code": "3200", "name": "Current Year Profit", "balance": 5000000 }
],
"total": 10950000
},
"netAssets": 10950000,
"checksum": true
}
}

Checksum

The checksum field confirms: Assets = Liabilities + Equity

If checksum is false, the ledger is inconsistent (this should never occur).


Trial Balance

GET /v1/reports/trial-balance

Lists all account balances for verification. Total debits must equal total credits.

curl "https://api.speybooks.com/v1/reports/trial-balance?asOf=2026-03-31" \
-H "Authorization: Bearer sk_live_your_api_key"

Parameters

ParameterTypeRequiredDescription
asOfstringNoReport date (default: today)

Response

{
"success": true,
"data": {
"asOf": "2026-03-31",
"accounts": [
{ "id": "acc_1100", "code": "1100", "name": "Accounts Receivable", "debit": 1250000, "credit": 0 },
{ "id": "acc_1200", "code": "1200", "name": "Bank Account", "debit": 8500000, "credit": 0 },
{ "id": "acc_2100", "code": "2100", "name": "Accounts Payable", "debit": 0, "credit": 450000 },
{ "id": "acc_2200", "code": "2200", "name": "VAT Payable", "debit": 0, "credit": 350000 },
{ "id": "acc_3000", "code": "3000", "name": "Share Capital", "debit": 0, "credit": 100000 },
{ "id": "acc_4000", "code": "4000", "name": "Sales", "debit": 0, "credit": 6500000 },
{ "id": "acc_5100", "code": "5100", "name": "Office Expenses", "debit": 250000, "credit": 0 }
],
"totals": {
"debit": 12500000,
"credit": 12500000
},
"balanced": true
}
}

Purpose

  • Verifies ledger integrity
  • Total debits must equal total credits
  • Used by accountants to validate postings

VAT Return

GET /v1/reports/vat

VAT summary in MTD-compatible 9-box format.

curl "https://api.speybooks.com/v1/reports/vat?from=2026-01-01&to=2026-03-31" \
-H "Authorization: Bearer sk_live_your_api_key"

Parameters

ParameterTypeRequiredDescription
fromstringYesPeriod start date (YYYY-MM-DD)
tostringYesPeriod end date (YYYY-MM-DD)

Response

{
"success": true,
"data": {
"period": {
"from": "2026-01-01",
"to": "2026-03-31"
},
"boxes": {
"box1": 130000,
"box2": 0,
"box3": 130000,
"box4": 30000,
"box5": 100000,
"box6": 650000,
"box7": 150000,
"box8": 0,
"box9": 0
},
"description": {
"box1": "VAT due on sales",
"box2": "VAT due on acquisitions from EU",
"box3": "Total VAT due (Box 1 + Box 2)",
"box4": "VAT reclaimed on purchases",
"box5": "Net VAT to pay/reclaim (Box 3 - Box 4)",
"box6": "Total sales excluding VAT",
"box7": "Total purchases excluding VAT",
"box8": "Total value of EU supplies",
"box9": "Total value of EU acquisitions"
}
}
}

Notes

  • Derived directly from VAT control accounts
  • No manual adjustments
  • Suitable for submission via HMRC MTD APIs

See VAT Returns Guide for submission details.


General Ledger

GET /v1/reports/general-ledger

Detailed transaction listing by account. This is the authoritative audit trail.

curl "https://api.speybooks.com/v1/reports/general-ledger?from=2026-01-01&to=2026-01-31&accountId=acc_1200" \
-H "Authorization: Bearer sk_live_your_api_key"

Parameters

ParameterTypeRequiredDescription
fromstringYesStart date (YYYY-MM-DD)
tostringYesEnd date (YYYY-MM-DD)
accountIdstringNoFilter by account (e.g., acc_1200)

Response

{
"success": true,
"data": {
"period": { "from": "2026-01-01", "to": "2026-01-31" },
"accounts": [
{
"id": "acc_1200",
"code": "1200",
"name": "Bank Account",
"accountType": "asset",
"openingBalance": 5000000,
"transactions": [
{
"id": "txn_52",
"date": "2026-01-15",
"description": "Payment received - INV-0001",
"reference": "BACS-123",
"debit": 120000,
"credit": 0,
"runningBalance": 5120000
},
{
"id": "txn_53",
"date": "2026-01-20",
"description": "Office supplies",
"reference": "AMZN-456",
"debit": 0,
"credit": 5000,
"runningBalance": 5115000
}
],
"closingBalance": 5115000,
"totalDebit": 3500000,
"totalCredit": 385000
}
]
}
}

What this shows

  • Opening balance
  • All transactions in date order
  • Running balance per transaction
  • Closing balance

Dashboard

GET /v1/reports/dashboard

High-level financial snapshot intended for quick status checks.

curl https://api.speybooks.com/v1/reports/dashboard \
-H "Authorization: Bearer sk_live_your_api_key"

Response

{
"success": true,
"data": {
"currentPeriod": {
"from": "2026-01-01",
"to": "2026-01-31"
},
"bankBalance": 8500000,
"accountsReceivable": 1250000,
"accountsPayable": 450000,
"revenue": {
"current": 2150000,
"prior": 1800000,
"change": 19.4
},
"expenses": {
"current": 500000,
"prior": 420000,
"change": 19.0
},
"netProfit": {
"current": 1650000,
"prior": 1380000,
"change": 19.6
},
"overdueInvoices": {
"count": 3,
"total": 245000
},
"upcomingBills": {
"count": 5,
"total": 180000
}
}
}

Includes

  • Bank balance
  • Receivables / payables
  • Revenue and expense trends
  • Overdue invoices
  • Upcoming bills

Aged Debtors

GET /v1/reports/aged-debtors

Outstanding receivables broken down by age buckets. Used for credit control and cash-flow management.

curl "https://api.speybooks.com/v1/reports/aged-debtors?asOfDate=2026-01-31" \
-H "Authorization: Bearer sk_live_your_api_key"

Parameters

ParameterTypeRequiredDescription
asOfDatestringNoReport date (default: today)

Aging buckets

  • Current
  • 1–30 days
  • 31–60 days
  • 61–90 days
  • 90+ days

Response

{
"success": true,
"data": {
"reportDate": "2026-01-31",
"reportTitle": "Aged Debtors",
"contacts": [
{
"contactId": "cont_17",
"contactName": "Acme Corporation",
"invoices": [
{
"id": "inv_42",
"invoiceNumber": "INV-2026-0001",
"issueDate": "2026-01-15",
"dueDate": "2026-02-14",
"total": 120000,
"amountPaid": 0,
"outstanding": 120000,
"daysOverdue": 0,
"agingBucket": "current"
}
],
"current": 120000,
"days1to30": 0,
"days31to60": 0,
"days61to90": 0,
"days90plus": 0,
"total": 120000
},
{
"contactId": "cont_18",
"contactName": "TechStart Ltd",
"invoices": [
{
"id": "inv_38",
"invoiceNumber": "INV-2025-0042",
"issueDate": "2025-11-15",
"dueDate": "2025-12-15",
"total": 85000,
"amountPaid": 0,
"outstanding": 85000,
"daysOverdue": 47,
"agingBucket": "31-60"
}
],
"current": 0,
"days1to30": 0,
"days31to60": 85000,
"days61to90": 0,
"days90plus": 0,
"total": 85000
}
],
"totals": {
"current": 120000,
"days1to30": 0,
"days31to60": 85000,
"days61to90": 0,
"days90plus": 0,
"total": 205000
},
"summary": {
"totalContacts": 2,
"totalInvoices": 2
}
}
}

Aged Creditors

GET /v1/reports/aged-creditors

Outstanding payables using the same aging buckets as debtors. Used to manage upcoming obligations and supplier payments.

curl "https://api.speybooks.com/v1/reports/aged-creditors?asOfDate=2026-01-31" \
-H "Authorization: Bearer sk_live_your_api_key"

Parameters

ParameterTypeRequiredDescription
asOfDatestringNoReport date (default: today)

Response

Same structure as Aged Debtors, but for purchase invoices (amounts you owe to suppliers).

{
"success": true,
"data": {
"reportDate": "2026-01-31",
"reportTitle": "Aged Creditors",
"contacts": [
{
"contactId": "cont_25",
"contactName": "Office Supplies Ltd",
"current": 15000,
"days1to30": 0,
"days31to60": 0,
"days61to90": 0,
"days90plus": 0,
"total": 15000
}
],
"totals": {
"current": 15000,
"days1to30": 0,
"days31to60": 0,
"days61to90": 0,
"days90plus": 0,
"total": 15000
},
"summary": {
"totalContacts": 1,
"totalInvoices": 1
}
}
}

Financial Periods

GET /v1/reports/periods

Lists configured financial periods.

curl https://api.speybooks.com/v1/reports/periods \
-H "Authorization: Bearer sk_live_your_api_key"

Response

{
"success": true,
"data": {
"periods": [
{
"id": "period_1",
"name": "FY 2025-26",
"startDate": "2025-04-01",
"endDate": "2026-03-31",
"isCurrent": true,
"isClosed": false
},
{
"id": "period_2",
"name": "FY 2024-25",
"startDate": "2024-04-01",
"endDate": "2025-03-31",
"isCurrent": false,
"isClosed": true
}
]
}
}

Notes

  • Periods define reporting boundaries
  • Closed periods are read-only
  • Current period is used by default where applicable

Key guarantees

  • Reports are pure functions of the ledger
  • No report stores its own state
  • Results are reproducible and auditable
  • Historical reports change only if history changes

Error codes

CodeHTTPDescription
validation_error400Missing required date parameters
validation_error400Invalid date format (expected YYYY-MM-DD)
validation_error400from date is after to date
invalid_id400Malformed account ID in filter

Amount format

All monetary values in reports are in minor units (pence for GBP):

5000000 = £50,000.00
130000 = £1,300.00

Divide by 100 for display.