Accounts
Manage your chart of accounts.
Accounts define the structure of your ledger. Transactions post amounts into accounts, but accounts themselves are long-lived, mostly immutable objects.
Authentication
All endpoints require a valid API key. See Authentication.
Overview
Accounts are the categories used to organise financial data. SpeyBooks supports hierarchical accounts with parent/child relationships.
When you register, SpeyBooks provisions a UK-standard chart of accounts suitable for sole traders and limited companies.
Account types
Each account has a type which defines its normal balance.
| Type | Description | Normal balance |
|---|---|---|
asset | Things you own (bank, receivables, equipment) | Debit |
liability | Things you owe (payables, VAT, loans) | Credit |
equity | Owner's stake (capital, retained earnings) | Credit |
revenue | Income (sales, interest) | Credit |
expense | Costs (rent, wages, software) | Debit |
Normal balance determines how net balances should be interpreted in reports.
The account object
{
"id": "acc_1200",
"code": "1200",
"name": "Bank Account",
"accountType": "asset",
"parentId": "acc_1000",
"description": "Main business current account",
"defaultVatRate": null,
"isActive": true,
"isSystem": true,
"isControlAccount": true,
"controlType": "bank",
"createdAt": "2026-01-01T00:00:00Z",
"updatedAt": "2026-01-15T10:30:00Z"
}
Attributes
| Field | Type | Description |
|---|---|---|
id | string | Unique identifier (acc_*) |
code | string | Account code |
name | string | Account name |
accountType | string | asset, liability, equity, revenue, expense |
parentId | string | null | Parent account ID |
description | string | Account description |
defaultVatRate | integer | null | Default VAT rate (0–100) |
isActive | boolean | Whether account is active |
isSystem | boolean | System-created (restricted) |
isControlAccount | boolean | Control account flag |
controlType | string | null | bank, receivables, payables, vat |
createdAt | string | Creation timestamp |
updatedAt | string | Last update timestamp |
List accounts
GET /v1/accounts
Returns accounts as a hierarchy by default, or as a flat list with ?flat=true.
curl "https://api.speybooks.com/v1/accounts?type=asset&active=true" \
-H "Authorization: Bearer sk_live_your_api_key"
Query parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
type | string | — | Filter by account type |
active | boolean | — | Filter by active status |
flat | boolean | false | Return flat list instead of hierarchy |
Response (hierarchical)
Accounts include nested children.
{
"success": true,
"data": {
"accounts": [
{
"id": "acc_1000",
"code": "1000",
"name": "Current Assets",
"accountType": "asset",
"parentId": null,
"isActive": true,
"children": [
{
"id": "acc_1100",
"code": "1100",
"name": "Accounts Receivable",
"accountType": "asset",
"parentId": "acc_1000",
"isActive": true,
"children": []
},
{
"id": "acc_1200",
"code": "1200",
"name": "Bank Account",
"accountType": "asset",
"parentId": "acc_1000",
"isActive": true,
"children": []
}
]
}
],
"meta": {
"total": 45
}
}
}
Response (flat)
Use ?flat=true to return a flat list.
{
"success": true,
"data": {
"accounts": [
{
"id": "acc_1000",
"code": "1000",
"name": "Current Assets",
"accountType": "asset",
"parentId": null
},
{
"id": "acc_1100",
"code": "1100",
"name": "Accounts Receivable",
"accountType": "asset",
"parentId": "acc_1000"
}
],
"meta": {
"total": 45
}
}
}
Account type summary
GET /v1/accounts/types
Returns counts grouped by account type.
curl https://api.speybooks.com/v1/accounts/types \
-H "Authorization: Bearer sk_live_your_api_key"
Response
{
"success": true,
"data": {
"types": [
{ "type": "asset", "count": 12, "activeCount": 11 },
{ "type": "liability", "count": 8, "activeCount": 8 },
{ "type": "equity", "count": 3, "activeCount": 3 },
{ "type": "revenue", "count": 5, "activeCount": 5 },
{ "type": "expense", "count": 17, "activeCount": 15 }
]
}
}
Retrieve an account
GET /v1/accounts/:id
Returns the full account object.
curl https://api.speybooks.com/v1/accounts/acc_1200 \
-H "Authorization: Bearer sk_live_your_api_key"
Response
{
"success": true,
"data": {
"id": "acc_1200",
"code": "1200",
"name": "Bank Account",
"accountType": "asset",
"parentId": "acc_1000",
"description": "Main business current account",
"defaultVatRate": null,
"isActive": true,
"isSystem": true,
"isControlAccount": true,
"controlType": "bank",
"createdAt": "2026-01-01T00:00:00Z",
"updatedAt": "2026-01-15T10:30:00Z"
}
}
Get account balance
GET /v1/accounts/:id/balance
Returns debit, credit, and net balances for the account.
curl "https://api.speybooks.com/v1/accounts/acc_1200/balance?from=2026-01-01&to=2026-01-31" \
-H "Authorization: Bearer sk_live_your_api_key"
Query parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
from | string | — | Start date (YYYY-MM-DD) |
to | string | — | End date (YYYY-MM-DD) |
Response
{
"success": true,
"data": {
"account": {
"id": "acc_1200",
"code": "1200",
"name": "Bank Account",
"accountType": "asset"
},
"balance": {
"debit": 5000000,
"credit": 1250000,
"net": 3750000
},
"period": {
"from": "2026-01-01",
"to": "2026-01-31"
},
"transactionCount": 42
}
}
Balance interpretation
| Account type | Normal net |
|---|---|
| Asset / Expense | Positive (debits exceed credits) |
| Liability / Equity / Revenue | Negative (credits exceed debits) |
Create an account
POST /v1/accounts
curl -X POST https://api.speybooks.com/v1/accounts \
-H "Authorization: Bearer sk_live_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"code": "5150",
"name": "Cloud Hosting",
"accountType": "expense",
"parentId": "acc_5100",
"description": "AWS, GCP, and other cloud services",
"defaultVatRate": 20
}'
Parameters
| Field | Type | Required | Description |
|---|---|---|---|
code | string | Yes | Unique account code (max 20 chars) |
name | string | Yes | Account name (max 200 chars) |
accountType | string | Yes | asset, liability, equity, revenue, expense |
parentId | string | No | Parent account ID |
description | string | No | Account description (max 500 chars) |
defaultVatRate | integer | No | Default VAT rate (0–100) |
isControlAccount | boolean | No | Control account flag |
controlType | string | No | Control type if applicable |
Response
{
"success": true,
"data": {
"id": "acc_5150",
"code": "5150",
"name": "Cloud Hosting",
"accountType": "expense",
"parentId": "acc_5100",
"description": "AWS, GCP, and other cloud services",
"defaultVatRate": 20,
"isActive": true,
"isSystem": false,
"isControlAccount": false,
"controlType": null,
"createdAt": "2026-01-31T10:00:00Z",
"updatedAt": "2026-01-31T10:00:00Z"
}
}
Error: Duplicate code
{
"success": false,
"error": {
"code": "conflict",
"message": "Account code already exists"
}
}
Update an account
PUT /v1/accounts/:id
curl -X PUT https://api.speybooks.com/v1/accounts/acc_5150 \
-H "Authorization: Bearer sk_live_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"name": "Cloud Infrastructure",
"description": "AWS, GCP, Azure, and other cloud services",
"defaultVatRate": 20
}'
Update rules
| Account type | Allowed changes |
|---|---|
| System accounts | Only isActive |
| User accounts | name, description, defaultVatRate |
Response
{
"success": true,
"data": {
"updated": true
}
}
Error: Cannot modify system account
{
"success": false,
"error": {
"code": "unprocessable_entity",
"message": "Cannot modify system account"
}
}
Delete an account
DELETE /v1/accounts/:id
curl -X DELETE https://api.speybooks.com/v1/accounts/acc_5150 \
-H "Authorization: Bearer sk_live_your_api_key"
Deletion rules
| Condition | Result |
|---|---|
| Account has transactions | Deactivated, not deleted |
| Account has child accounts | Cannot be deleted |
| System account | Cannot be deleted |
Response (deleted)
{
"success": true,
"data": {
"deleted": true
}
}
Response (deactivated)
{
"success": true,
"data": {
"deactivated": true,
"message": "Account deactivated (has transactions)"
}
}
Error: Cannot delete system account
{
"success": false,
"error": {
"code": "unprocessable_entity",
"message": "Cannot delete system account"
}
}
Error: Has child accounts
{
"success": false,
"error": {
"code": "unprocessable_entity",
"message": "Cannot delete account with child accounts"
}
}
Standard UK account codes
SpeyBooks provisions a UK-standard chart of accounts on registration.
| Code range | Type | Description |
|---|---|---|
| 1000–1999 | Asset | Current and fixed assets |
| 2000–2999 | Liability | Current and long-term liabilities |
| 3000–3999 | Equity | Capital and reserves |
| 4000–4999 | Revenue | Sales and other income |
| 5000–5999 | Expense | Operating expenses |
Common accounts
| Code | Name | Type |
|---|---|---|
| 1100 | Accounts Receivable | Asset |
| 1200 | Bank Account | Asset |
| 2100 | Accounts Payable | Liability |
| 2200 | VAT Output | Liability |
| 2201 | VAT Input | Liability |
| 3000 | Share Capital | Equity |
| 3100 | Retained Earnings | Equity |
| 4000 | Sales | Revenue |
| 5000 | Cost of Sales | Expense |
| 5100 | Office Expenses | Expense |
Key invariants
- Account codes are unique within an organisation
- System accounts are protected from modification
- Accounts with transactions are never removed (only deactivated)
- Balances are derived from transactions, not stored
- The chart is structural, not transactional
Error codes
| Code | HTTP | Description |
|---|---|---|
validation_error | 400 | Invalid account type or missing required field |
invalid_id | 400 | Malformed account ID (expected acc_*) |
not_found | 404 | Account does not exist |
conflict | 409 | Account code already exists |
unprocessable_entity | 422 | Cannot modify/delete system account |
unprocessable_entity | 422 | Cannot delete account with transactions |
unprocessable_entity | 422 | Cannot delete account with child accounts |
Amount format
All balance amounts are returned in minor units (pence for GBP):
3750000 = £37,500.00
Divide by 100 for display.