Books
46 operations in the Tolvi API, version 1. Paths are relative to https://api.tolvi.co.uk. Every amount is integer pence.
Sign a business up to Tolvi Books
POST/api/v1/books/signup
- Access
- No authentication.
Creates the business and emails a single-use link to the address given. Following it confirms the address, has the person choose a password in the Tolvi Books app and makes them the business’s owner. No token needed.
Request body
Required. application/json: object (BooksSignUp).
A business signing up to Tolvi Books on its own.
| Field | Type | Description |
|---|---|---|
businessNamerequired | string | up to 200 characters; example "Abbey Bakery Ltd" |
entityTyperequired | string (EntityType) | One of: |
emailrequired | string (email) | up to 254 characters |
Responses
202 Accepted, application/json
Body: object (SignUpResult).
| Field | Type | Description |
|---|---|---|
emailrequired | string (email) | Where the link to finish signing up was sent. |
403 Forbidden
Sign-up is closed: people join by invitation (TOLVI_SIGNUP_OPEN is off).
Errors: 400 Bad request, 429 Too many requests, as problem details (application/problem+json).
Get the business’s profile
GET/api/v1/books/business
- Scopes
books:read
Anyone who can read the books, including a linked accountant. Part of the books product: the firm must have it and you must have access to it.
Responses
200 OK, application/json
Body: object (Business).
A business’s profile in Tolvi Books: who it is, its VAT registration and its year end.
| Field | Type | Description |
|---|---|---|
idrequired | string (uuid) | The business’s tenant id (send it as x-business-id to work in its books as its accountant). |
legalNamerequired | string | example "Abbey Bakery Ltd" |
tradingNamerequired | stringnullable | |
entityTyperequired | string (EntityType) | One of: |
companyNumberrequired | stringnullable | example "01234567" |
vatRegisteredrequired | boolean | |
vatNumberrequired | stringnullable | 9 digits (12 for a group branch), without GB. example "123456789" |
vatSchemerequired | string (VatScheme)nullable | One of: |
vatRegisteredFromrequired | string (date)nullable | example "2026-03-31" |
yearEndDayrequired | integernullable | 1 to 31 |
yearEndMonthrequired | integernullable | 1 to 12 |
booksStartDaterequired | string (date)nullable | The first day the books cover. example "2026-03-31" |
baseCurrencyrequired | string (BooksCurrency) | One of: |
custodianFirmIdrequired | string (uuid)nullable | The accountancy practice that set the business up, until an owner claims it. |
createdAtrequired | string (date-time) | |
updatedAtrequired | string (date-time) |
Errors: 400 Bad request, 401 Unauthorised, 403 Forbidden, 429 Too many requests, as problem details (application/problem+json).
Change the business’s details
PATCH/api/v1/books/business
- Scopes
books:write
The business’s owners and admins (books:admin). A practice that set the business up can too, through its link, until the owner joins. Changing VAT details needs a signed-in person. Part of the books product: the firm must have it and you must have access to it.
Request body
Required. application/json: object (UpdateBusiness).
Only the fields sent change. VAT details need a signed-in person.
| Field | Type | Description |
|---|---|---|
legalName | string | up to 200 characters |
tradingName | stringnullable | up to 200 characters |
entityType | string (EntityType) | One of: |
companyNumber | stringnullable | pattern ^[A-Za-z0-9 ]{8,10}$ |
vatRegistered | boolean | |
vatNumber | stringnullable | |
vatScheme | string (VatScheme)nullable | One of: |
vatRegisteredFrom | string (date)nullable | example "2026-03-31" |
yearEndDay | integernullable | 1 to 31 |
yearEndMonth | integernullable | 1 to 12 |
booksStartDate | string (date)nullable | example "2026-03-31" |
Responses
200 OK, application/json
Body: object (Business).
A business’s profile in Tolvi Books: who it is, its VAT registration and its year end.
The fields are as shown above.
Errors: 400 Bad request, 401 Unauthorised, 403 Forbidden, 429 Too many requests, as problem details (application/problem+json).
List the business’s accountants
GET/api/v1/books/accountants
- Scopes
books:read
Every practice link, live or ended. A linked accountant sees only their own firm’s link. Part of the books product: the firm must have it and you must have access to it.
Responses
200 OK, application/json
Body: array of PracticeLink.
An accountancy practice’s access to a business’s books, as either side sees it.
| Field | Type | Description |
|---|---|---|
[].idrequired | string (uuid) | |
[].statusrequired | string (PracticeLinkStatus) | invited_by_business: waiting for the practice to accept. requested_by_firm: waiting for the business to approve. active: the practice can work in the books. ended: never active again. One of: |
[].accessrequired | string (PracticeAccess) | read_only: see the books, export, pull the TB. year_end: also post year-end adjustments. full_bookkeeping: also keep the books. One of: |
[].vatAgentrequired | boolean | The practice may prepare (and, once built, submit) VAT returns. At most one practice at a time. |
[].billedByrequired | string (LinkBilledBy) | Who the business said should pay, on its link. One of: |
[].consentBasisrequired | string (LinkConsentBasis) | One of: |
[].businessIdrequired | string (uuid)nullable | |
[].businessNamerequired | stringnullable | |
[].firmIdrequired | string (uuid)nullable | |
[].firmNamerequired | stringnullable | |
[].invitedEmailrequired | stringnullable | |
[].requestedEmailrequired | stringnullable | |
[].expiresAtrequired | string (date-time)nullable | |
[].createdAtrequired | string (date-time) | |
[].activatedAtrequired | string (date-time)nullable | |
[].endedAtrequired | string (date-time)nullable | |
[].endedBySiderequired | string (LinkSide)nullable | One of: |
Errors: 400 Bad request, 401 Unauthorised, 403 Forbidden, 429 Too many requests, as problem details (application/problem+json).
Invite an accountant
POST/api/v1/books/accountants/invitations
- Scopes
books:admin- Access
- A signed-in Tolvi session only, never an API token.
- Retries
- Send an
Idempotency-Keyto make retries safe.
Emails a single-use link to the accountant, who accepts while signed in to their practice. Signed-in owners and admins only. Part of the books product: the firm must have it and you must have access to it.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
Idempotency-Key | header | string | A unique key (1-255 visible characters) to make retries safe. Replayed for 24 hours. 1 to 255 characters |
Request body
Required. application/json: object (InviteAccountant).
| Field | Type | Description |
|---|---|---|
emailrequired | string (email) | The accountant who will accept, signed in to their practice in Tolvi. up to 254 characters |
accessrequired | string (PracticeAccess) | read_only: see the books, export, pull the TB. year_end: also post year-end adjustments. full_bookkeeping: also keep the books. One of: |
vatAgent | boolean |
Responses
201 Created, application/json
Body: object (PracticeLink).
An accountancy practice’s access to a business’s books, as either side sees it.
| Field | Type | Description |
|---|---|---|
idrequired | string (uuid) | |
statusrequired | string (PracticeLinkStatus) | invited_by_business: waiting for the practice to accept. requested_by_firm: waiting for the business to approve. active: the practice can work in the books. ended: never active again. One of: |
accessrequired | string (PracticeAccess) | read_only: see the books, export, pull the TB. year_end: also post year-end adjustments. full_bookkeeping: also keep the books. One of: |
vatAgentrequired | boolean | The practice may prepare (and, once built, submit) VAT returns. At most one practice at a time. |
billedByrequired | string (LinkBilledBy) | Who the business said should pay, on its link. One of: |
consentBasisrequired | string (LinkConsentBasis) | One of: |
businessIdrequired | string (uuid)nullable | |
businessNamerequired | stringnullable | |
firmIdrequired | string (uuid)nullable | |
firmNamerequired | stringnullable | |
invitedEmailrequired | stringnullable | |
requestedEmailrequired | stringnullable | |
expiresAtrequired | string (date-time)nullable | |
createdAtrequired | string (date-time) | |
activatedAtrequired | string (date-time)nullable | |
endedAtrequired | string (date-time)nullable | |
endedBySiderequired | string (LinkSide)nullable | One of: |
Errors: 400 Bad request, 401 Unauthorised, 403 Forbidden, 409 Conflict, 422 Unprocessable content, 429 Too many requests, as problem details (application/problem+json).
Change an accountant’s access
PATCH/api/v1/books/accountants/{linkId}
- Scopes
books:admin- Access
- A signed-in Tolvi session only, never an API token.
Access level, VAT agent (one practice at a time) and who pays. Part of the books product: the firm must have it and you must have access to it.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
linkIdrequired | path | string (uuid) |
Request body
Required. application/json: object (ChangePracticeLink).
Only the fields sent change.
| Field | Type | Description |
|---|---|---|
access | string (PracticeAccess) | read_only: see the books, export, pull the TB. year_end: also post year-end adjustments. full_bookkeeping: also keep the books. One of: |
vatAgent | boolean | |
billedBy | string (LinkBilledBy) | Who the business said should pay, on its link. One of: |
Responses
200 OK, application/json
Body: object (PracticeLink).
An accountancy practice’s access to a business’s books, as either side sees it.
The fields are as shown above.
Errors: 400 Bad request, 401 Unauthorised, 403 Forbidden, 404 Not found, 429 Too many requests, as problem details (application/problem+json).
End an accountant’s access
POST/api/v1/books/accountants/{linkId}/end
- Scopes
books:admin- Access
- A signed-in Tolvi session only, never an API token.
Takes effect from their next request, in the database itself. Also withdraws an invitation. An ended link is never active again. Allowed even while Tolvi Books is suspended. Part of the books product: the firm must have it and you must have access to it.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
linkIdrequired | path | string (uuid) |
Request body
Optional. application/json: object (EndPracticeLink).
| Field | Type | Description |
|---|---|---|
reason | string | up to 500 characters |
Responses
200 OK, application/json
Body: object (PracticeLink).
An accountancy practice’s access to a business’s books, as either side sees it.
The fields are as shown above.
Errors: 400 Bad request, 401 Unauthorised, 403 Forbidden, 404 Not found, 429 Too many requests, as problem details (application/problem+json).
List practices’ requests for access
GET/api/v1/books/accountants/requests
- Scopes
books:admin- Access
- A signed-in Tolvi session only, never an API token.
Requests sent to your verified email address, waiting for an answer. Part of the books product: the firm must have it and you must have access to it.
Responses
200 OK, application/json
Body: array of PracticeLink.
An accountancy practice’s access to a business’s books, as either side sees it.
The fields are as shown above.
Errors: 400 Bad request, 401 Unauthorised, 403 Forbidden, 429 Too many requests, as problem details (application/problem+json).
Approve a practice’s request
POST/api/v1/books/accountants/requests/{linkId}/approve
- Scopes
books:admin- Access
- A signed-in Tolvi session only, never an API token.
Links the practice to this business with the access you choose. Part of the books product: the firm must have it and you must have access to it.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
linkIdrequired | path | string (uuid) |
Request body
Optional. application/json: object (ApprovePracticeLinkRequest).
| Field | Type | Description |
|---|---|---|
access | string (PracticeAccess) | Defaults to what the practice asked for. One of: |
vatAgent | boolean |
Responses
200 OK, application/json
Body: object (PracticeLink).
An accountancy practice’s access to a business’s books, as either side sees it.
The fields are as shown above.
Errors: 400 Bad request, 401 Unauthorised, 403 Forbidden, 404 Not found, 429 Too many requests, as problem details (application/problem+json).
Decline a practice’s request
POST/api/v1/books/accountants/requests/{linkId}/decline
- Scopes
books:admin- Access
- A signed-in Tolvi session only, never an API token.
Part of the books product: the firm must have it and you must have access to it.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
linkIdrequired | path | string (uuid) |
Responses
200 OK, application/json
Body: object (PracticeLink).
An accountancy practice’s access to a business’s books, as either side sees it.
The fields are as shown above.
Errors: 400 Bad request, 401 Unauthorised, 403 Forbidden, 404 Not found, 429 Too many requests, as problem details (application/problem+json).
List the firm’s links to businesses’ books
GET/api/v1/practice/books/links
- Scopes
client_books:read
Requests, accepted invitations, live and ended links.
Responses
200 OK, application/json
Body: array of PracticeLink.
An accountancy practice’s access to a business’s books, as either side sees it.
The fields are as shown above.
Errors: 400 Bad request, 401 Unauthorised, 403 Forbidden, 429 Too many requests, as problem details (application/problem+json).
Ask a business for access to its books
POST/api/v1/practice/books/requests
- Scopes
client_books:read- Access
- A signed-in Tolvi session only, never an API token.
- Retries
- Send an
Idempotency-Keyto make retries safe.
Emails the owner, who approves or declines in Tolvi Books.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
Idempotency-Key | header | string | A unique key (1-255 visible characters) to make retries safe. Replayed for 24 hours. 1 to 255 characters |
Request body
Required. application/json: object (RequestBooksAccess).
| Field | Type | Description |
|---|---|---|
emailrequired | string (email) | The business owner’s email: they approve in Tolvi Books. up to 254 characters |
accessrequired | string (PracticeAccess) | read_only: see the books, export, pull the TB. year_end: also post year-end adjustments. full_bookkeeping: also keep the books. One of: |
Responses
201 Created, application/json
Body: object (PracticeLink).
An accountancy practice’s access to a business’s books, as either side sees it.
The fields are as shown above.
Errors: 400 Bad request, 401 Unauthorised, 403 Forbidden, 409 Conflict, 422 Unprocessable content, 429 Too many requests, as problem details (application/problem+json).
See what a business’s invitation offers
POST/api/v1/practice/books/link-invitations/preview
- Scopes
client_books:read- Access
- A signed-in Tolvi session only, never an API token.
The token from the email, in the body (never the URL).
Request body
Required. application/json: object (PracticeLinkToken).
The token from the invitation email.
| Field | Type | Description |
|---|---|---|
tokenrequired | string | 20 to 200 characters |
Responses
200 OK, application/json
Body: object (PracticeLinkInvitationPreview).
| Field | Type | Description |
|---|---|---|
businessNamerequired | stringnullable | |
accessrequired | string (PracticeAccess) | read_only: see the books, export, pull the TB. year_end: also post year-end adjustments. full_bookkeeping: also keep the books. One of: |
vatAgentrequired | boolean | |
expiresAtrequired | string (date-time)nullable | |
expiredrequired | boolean |
Errors: 400 Bad request, 401 Unauthorised, 403 Forbidden, 429 Too many requests, as problem details (application/problem+json).
Accept a business’s invitation
POST/api/v1/practice/books/link-invitations/accept
- Scopes
client_books:read- Access
- A signed-in Tolvi session only, never an API token.
The person it was emailed to accepts, signed in to their practice. Single use.
Request body
Required. application/json: object (PracticeLinkToken).
The token from the invitation email.
| Field | Type | Description |
|---|---|---|
tokenrequired | string | 20 to 200 characters |
Responses
200 OK, application/json
Body: object (PracticeLink).
An accountancy practice’s access to a business’s books, as either side sees it.
The fields are as shown above.
Errors: 400 Bad request, 401 Unauthorised, 403 Forbidden, 429 Too many requests, as problem details (application/problem+json).
End the firm’s access to a business’s books
POST/api/v1/practice/books/links/{linkId}/end
- Scopes
client_books:read- Access
- A signed-in Tolvi session only, never an API token.
Also withdraws a request. An ended link is never active again.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
linkIdrequired | path | string (uuid) |
Request body
Optional. application/json: object (EndPracticeLink).
| Field | Type | Description |
|---|---|---|
reason | string | up to 500 characters |
Responses
200 OK, application/json
Body: object (PracticeLink).
An accountancy practice’s access to a business’s books, as either side sees it.
The fields are as shown above.
Errors: 400 Bad request, 401 Unauthorised, 403 Forbidden, 404 Not found, 429 Too many requests, as problem details (application/problem+json).
Set Tolvi Books up for a client
POST/api/v1/practice/books/businesses
- Scopes
client_books:read- Access
- A signed-in Tolvi session only, never an API token.
- Retries
- Send an
Idempotency-Keyto make retries safe.
Creates the business with the firm as its accountant (full bookkeeping) under the firm’s engagement letter. The firm looks after it until the owner joins.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
Idempotency-Key | header | string | A unique key (1-255 visible characters) to make retries safe. Replayed for 24 hours. 1 to 255 characters |
Request body
Required. application/json: object (ProvisionBusiness).
A practice setting Tolvi Books up for a client. The practice looks after it until the owner joins.
| Field | Type | Description |
|---|---|---|
legalNamerequired | string | up to 200 characters |
tradingName | stringnullable | up to 200 characters |
entityTyperequired | string (EntityType) | One of: |
companyNumber | stringnullable | |
yearEndDay | integernullable | 1 to 31 |
yearEndMonth | integernullable | 1 to 12 |
booksStartDate | string (date)nullable | example "2026-03-31" |
billedBy | string (LinkBilledBy) | Who pays for Tolvi Books. Defaults to the practice. One of: |
ownerEmail | string (email) | Invite the owner now (they can also be invited later). |
Responses
201 Created, application/json
Body: object (ProvisionedBusiness).
The business a practice set up, and the practice’s link to it.
| Field | Type | Description |
|---|---|---|
businessrequired | object (Business) | A business’s profile in Tolvi Books: who it is, its VAT registration and its year end. |
business.idrequired | string (uuid) | The business’s tenant id (send it as x-business-id to work in its books as its accountant). |
business.legalNamerequired | string | example "Abbey Bakery Ltd" |
business.tradingNamerequired | stringnullable | |
business.entityTyperequired | string (EntityType) | One of: |
business.companyNumberrequired | stringnullable | example "01234567" |
business.vatRegisteredrequired | boolean | |
business.vatNumberrequired | stringnullable | 9 digits (12 for a group branch), without GB. example "123456789" |
business.vatSchemerequired | string (VatScheme)nullable | One of: |
business.vatRegisteredFromrequired | string (date)nullable | example "2026-03-31" |
business.yearEndDayrequired | integernullable | 1 to 31 |
business.yearEndMonthrequired | integernullable | 1 to 12 |
business.booksStartDaterequired | string (date)nullable | The first day the books cover. example "2026-03-31" |
business.baseCurrencyrequired | string (BooksCurrency) | One of: |
business.custodianFirmIdrequired | string (uuid)nullable | The accountancy practice that set the business up, until an owner claims it. |
business.createdAtrequired | string (date-time) | |
business.updatedAtrequired | string (date-time) | |
linkrequired | object (PracticeLink) | An accountancy practice’s access to a business’s books, as either side sees it. |
link.idrequired | string (uuid) | |
link.statusrequired | string (PracticeLinkStatus) | invited_by_business: waiting for the practice to accept. requested_by_firm: waiting for the business to approve. active: the practice can work in the books. ended: never active again. One of: |
link.accessrequired | string (PracticeAccess) | read_only: see the books, export, pull the TB. year_end: also post year-end adjustments. full_bookkeeping: also keep the books. One of: |
link.vatAgentrequired | boolean | The practice may prepare (and, once built, submit) VAT returns. At most one practice at a time. |
link.billedByrequired | string (LinkBilledBy) | Who the business said should pay, on its link. One of: |
link.consentBasisrequired | string (LinkConsentBasis) | One of: |
link.businessIdrequired | string (uuid)nullable | |
link.businessNamerequired | stringnullable | |
link.firmIdrequired | string (uuid)nullable | |
link.firmNamerequired | stringnullable | |
link.invitedEmailrequired | stringnullable | |
link.requestedEmailrequired | stringnullable | |
link.expiresAtrequired | string (date-time)nullable | |
link.createdAtrequired | string (date-time) | |
link.activatedAtrequired | string (date-time)nullable | |
link.endedAtrequired | string (date-time)nullable | |
link.endedBySiderequired | string (LinkSide)nullable | One of: |
Errors: 400 Bad request, 401 Unauthorised, 403 Forbidden, 409 Conflict, 422 Unprocessable content, 429 Too many requests, as problem details (application/problem+json).
Invite the owner of a business the firm set up
POST/api/v1/practice/books/businesses/{businessId}/owner-invitation
- Scopes
client_books:read- Access
- A signed-in Tolvi session only, never an API token.
Only while the firm still looks after it (before an owner has joined).
Parameters
| Name | In | Type | Description |
|---|---|---|---|
businessIdrequired | path | string (uuid) |
Request body
Required. application/json: object (OwnerInvitation).
| Field | Type | Description |
|---|---|---|
emailrequired | string (email) | up to 254 characters |
Responses
200 OK, application/json
Body: object (OwnerInvitation).
| Field | Type | Description |
|---|---|---|
emailrequired | string (email) | up to 254 characters |
Errors: 400 Bad request, 401 Unauthorised, 403 Forbidden, 404 Not found, 429 Too many requests, as problem details (application/problem+json).
List clients’ books
GET/api/v1/practice/books/clients
- Scopes
client_books:read
Every business whose Tolvi Books the firm reaches (live and ended links), the client it is linked to, and for live links the books at a glance: entries posted, when last posted, receipts to review, VAT registration (bank lines to explain and VAT due appear once those are available).
Responses
200 OK, application/json
Body: object (ClientsBooksList).
| Field | Type | Description |
|---|---|---|
rowsrequired | array of ClientsBooksRow | |
rows[].practiceLinkIdrequired | string (uuid) | |
rows[].businessIdrequired | string (uuid) | |
rows[].businessNamerequired | stringnullable | |
rows[].linkStatusrequired | string (PracticeLinkStatus) | invited_by_business: waiting for the practice to accept. requested_by_firm: waiting for the business to approve. active: the practice can work in the books. ended: never active again. One of: |
rows[].accessrequired | string (PracticeAccess) | read_only: see the books, export, pull the TB. year_end: also post year-end adjustments. full_bookkeeping: also keep the books. One of: |
rows[].consentBasisrequired | string (LinkConsentBasis) | One of: |
rows[].clientIdrequired | string (uuid)nullable | The firm’s client these books are, once linked. |
rows[].clientNamerequired | stringnullable | |
rows[].healthrequired | object (BooksHealth)nullable | Null when the link has ended. |
rows[].health.entriesrequired | integer | Ledger entries posted. at least 0 |
rows[].health.lastPostedAtrequired | string (date-time)nullable | |
rows[].health.lastEntryDaterequired | string (date)nullable | The latest date any entry is dated. example "2026-03-31" |
rows[].health.receiptsToReviewrequired | integer | Receipts read and waiting to be confirmed. at least 0 |
rows[].health.unexplainedBankLinesrequired | integernullable | Bank lines not yet explained. Null until bank feeds are available. at least 0 |
rows[].health.vatRegisteredrequired | boolean | |
rows[].health.vatSchemerequired | stringnullable | example "standard" |
rows[].health.nextVatDuerequired | string (date)nullable | The next VAT return due. Null until MTD VAT returns are available. example "2026-03-31" |
Errors: 400 Bad request, 401 Unauthorised, 403 Forbidden, 429 Too many requests, as problem details (application/problem+json).
Get the chart of accounts
GET/api/v1/books/accounts
- Scopes
books:read
Every account, with its balance now and whether it has been used. Set up from the template for the business’s entity type when the business joined. Part of the books product: the firm must have it and you must have access to it.
Responses
200 OK, application/json
Body: object (BooksChartOfAccounts).
The business’s chart of accounts, and the template version it started from.
| Field | Type | Description |
|---|---|---|
templateIdrequired | string | example "ltd_frs102_1a" |
templateVersionrequired | string | example "2026-11" |
entityTyperequired | string | example "LTD_FRS102_1A" |
accountsrequired | array of BooksAccount | |
accounts[].idrequired | string (uuid) | |
accounts[].coderequired | string | Unique in the business; never changes. example "6110" |
accounts[].namerequired | string | The accountant’s name. example "Light, heat and power" |
accounts[].ownerNamerequired | string | What owners see. example "Gas and electricity" |
accounts[].ownerCategoryrequired | string (BooksOwnerCategory) | One of: |
accounts[].ownerCategoryLabelrequired | string | example "Premises" |
accounts[].hintrequired | stringnullable | One sentence for owners on what goes here. |
accounts[].classrequired | string (BooksAccountClass) | One of: |
accounts[].normalBalancerequired | string (BooksNormalBalance) | One of: |
accounts[].subtyperequired | string | example "overhead" |
accounts[].leadLinerequired | stringnullable | The Working Papers lead schedule line the account maps to. example "M.adm" |
accounts[].sa103required | stringnullable | The SA103 line (sole traders). |
accounts[].systemRolerequired | stringnullable | Set for accounts Tolvi keeps (control accounts, suspense, retained earnings or capital): they can’t be archived or take a manual journal. |
accounts[].defaultVatCodeIdrequired | stringnullable | The VAT code suggested for new lines. example "S20" |
accounts[].fromTemplaterequired | boolean | Created from the chart template when the business signed up. |
accounts[].archivedrequired | boolean | |
accounts[].archivedAtrequired | string (date-time)nullable | |
accounts[].usedrequired | boolean | Posted to at least once: it can then be archived, never deleted. |
accounts[].balancePencerequired | integer | The balance now, in pence (debit positive, credit negative). |
accounts[].createdAtrequired | string (date-time) | |
accounts[].updatedAtrequired | string (date-time) |
Errors: 400 Bad request, 401 Unauthorised, 403 Forbidden, 429 Too many requests, as problem details (application/problem+json).
Add an account
POST/api/v1/books/accounts
- Scopes
books:write- Retries
- Send an
Idempotency-Keyto make retries safe.
The business’s owners and admins (books:admin), or a linked practice whose access lets it post (year-end or full bookkeeping). Give a name and a category: Tolvi picks a free code and copies the mapping from a similar account. Part of the books product: the firm must have it and you must have access to it.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
Idempotency-Key | header | string | A unique key (1-255 visible characters) to make retries safe. Replayed for 24 hours. 1 to 255 characters |
Request body
Required. application/json: object (BooksCreateAccount).
Add an account. Give a name and a category; Tolvi picks a free code and copies the mapping from a similar account unless you say otherwise.
| Field | Type | Description |
|---|---|---|
namerequired | string | up to 120 characters; example "Software subscriptions" |
ownerName | string | What owners see; defaults to the name. up to 120 characters |
ownerCategoryrequired | string (BooksOwnerCategory) | One of: |
class | string (BooksAccountClass) | Needed only where a category spans classes (bank and cash, tax, you and the business). One of: |
code | string | Defaults to the next free code in the category’s range. up to 20 characters |
leadLine | string | Working Papers lead schedule line (accountants). |
sa103 | string | SA103 line (accountants, sole traders). |
subtype | string | |
hint | stringnullable | up to 300 characters |
defaultVatCodeId | stringnullable | example "S20" |
likeAccountId | string (uuid) | Copy the mapping from this account. |
Responses
201 Created, application/json
Body: object (BooksAccount).
An account in the business’s chart of accounts. Owners see ownerName under ownerCategoryLabel; accountants see the code, name and class.
| Field | Type | Description |
|---|---|---|
idrequired | string (uuid) | |
coderequired | string | Unique in the business; never changes. example "6110" |
namerequired | string | The accountant’s name. example "Light, heat and power" |
ownerNamerequired | string | What owners see. example "Gas and electricity" |
ownerCategoryrequired | string (BooksOwnerCategory) | One of: |
ownerCategoryLabelrequired | string | example "Premises" |
hintrequired | stringnullable | One sentence for owners on what goes here. |
classrequired | string (BooksAccountClass) | One of: |
normalBalancerequired | string (BooksNormalBalance) | One of: |
subtyperequired | string | example "overhead" |
leadLinerequired | stringnullable | The Working Papers lead schedule line the account maps to. example "M.adm" |
sa103required | stringnullable | The SA103 line (sole traders). |
systemRolerequired | stringnullable | Set for accounts Tolvi keeps (control accounts, suspense, retained earnings or capital): they can’t be archived or take a manual journal. |
defaultVatCodeIdrequired | stringnullable | The VAT code suggested for new lines. example "S20" |
fromTemplaterequired | boolean | Created from the chart template when the business signed up. |
archivedrequired | boolean | |
archivedAtrequired | string (date-time)nullable | |
usedrequired | boolean | Posted to at least once: it can then be archived, never deleted. |
balancePencerequired | integer | The balance now, in pence (debit positive, credit negative). |
createdAtrequired | string (date-time) | |
updatedAtrequired | string (date-time) |
Errors: 400 Bad request, 401 Unauthorised, 403 Forbidden, 409 Conflict, 422 Unprocessable content, 429 Too many requests, as problem details (application/problem+json).
Rename or recategorise an account
PATCH/api/v1/books/accounts/{accountId}
- Scopes
books:write
The business’s owners and admins (books:admin), or a linked practice whose access lets it post (year-end or full bookkeeping). Codes and classes never change. Part of the books product: the firm must have it and you must have access to it.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
accountIdrequired | path | string (uuid) |
Request body
Required. application/json: object (BooksUpdateAccount).
Rename or recategorise an account. Codes and classes never change.
| Field | Type | Description |
|---|---|---|
name | string | up to 120 characters |
ownerName | string | up to 120 characters |
ownerCategory | string (BooksOwnerCategory) | One of: |
hint | stringnullable | up to 300 characters |
defaultVatCodeId | stringnullable |
Responses
200 OK, application/json
Body: object (BooksAccount).
An account in the business’s chart of accounts. Owners see ownerName under ownerCategoryLabel; accountants see the code, name and class.
The fields are as shown above.
Errors: 400 Bad request, 401 Unauthorised, 403 Forbidden, 404 Not found, 429 Too many requests, as problem details (application/problem+json).
Delete an unused account
DELETE/api/v1/books/accounts/{accountId}
- Scopes
books:write
The business’s owners and admins (books:admin), or a linked practice whose access lets it post (year-end or full bookkeeping). Only an account nothing has ever been posted to; once used, archive it instead (409). Part of the books product: the firm must have it and you must have access to it.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
accountIdrequired | path | string (uuid) |
Responses
204 No content
Errors: 400 Bad request, 401 Unauthorised, 403 Forbidden, 404 Not found, 429 Too many requests, as problem details (application/problem+json).
Archive an account
POST/api/v1/books/accounts/{accountId}/archive
- Scopes
books:write
The business’s owners and admins (books:admin), or a linked practice whose access lets it post (year-end or full bookkeeping). Its history stays; it is no longer offered for new entries. Refused for accounts Tolvi keeps and for accounts with a balance. Part of the books product: the firm must have it and you must have access to it.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
accountIdrequired | path | string (uuid) |
Responses
200 OK, application/json
Body: object (BooksAccount).
An account in the business’s chart of accounts. Owners see ownerName under ownerCategoryLabel; accountants see the code, name and class.
The fields are as shown above.
Errors: 400 Bad request, 401 Unauthorised, 403 Forbidden, 404 Not found, 429 Too many requests, as problem details (application/problem+json).
Restore an archived account
POST/api/v1/books/accounts/{accountId}/restore
- Scopes
books:write
The business’s owners and admins (books:admin), or a linked practice whose access lets it post (year-end or full bookkeeping). Part of the books product: the firm must have it and you must have access to it.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
accountIdrequired | path | string (uuid) |
Responses
200 OK, application/json
Body: object (BooksAccount).
An account in the business’s chart of accounts. Owners see ownerName under ownerCategoryLabel; accountants see the code, name and class.
The fields are as shown above.
Errors: 400 Bad request, 401 Unauthorised, 403 Forbidden, 404 Not found, 429 Too many requests, as problem details (application/problem+json).
Get one account’s ledger
GET/api/v1/books/accounts/{accountId}/ledger
- Scopes
books:read
Postings between two dates with the balance brought forward and a running balance (debit positive). Part of the books product: the firm must have it and you must have access to it.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
accountIdrequired | path | string (uuid) | |
to | query | string (date) | Last day (inclusive). Defaults to today. |
from | query | string (date) | First day (inclusive). Defaults to the start of the financial year containing |
Responses
200 OK, application/json
Body: object (BooksAccountLedger).
One account’s postings between two dates, with the balance brought forward and a running balance.
| Field | Type | Description |
|---|---|---|
accountrequired | object (BooksAccount) | An account in the business’s chart of accounts. Owners see |
account.idrequired | string (uuid) | |
account.coderequired | string | Unique in the business; never changes. example "6110" |
account.namerequired | string | The accountant’s name. example "Light, heat and power" |
account.ownerNamerequired | string | What owners see. example "Gas and electricity" |
account.ownerCategoryrequired | string (BooksOwnerCategory) | One of: |
account.ownerCategoryLabelrequired | string | example "Premises" |
account.hintrequired | stringnullable | One sentence for owners on what goes here. |
account.classrequired | string (BooksAccountClass) | One of: |
account.normalBalancerequired | string (BooksNormalBalance) | One of: |
account.subtyperequired | string | example "overhead" |
account.leadLinerequired | stringnullable | The Working Papers lead schedule line the account maps to. example "M.adm" |
account.sa103required | stringnullable | The SA103 line (sole traders). |
account.systemRolerequired | stringnullable | Set for accounts Tolvi keeps (control accounts, suspense, retained earnings or capital): they can’t be archived or take a manual journal. |
account.defaultVatCodeIdrequired | stringnullable | The VAT code suggested for new lines. example "S20" |
account.fromTemplaterequired | boolean | Created from the chart template when the business signed up. |
account.archivedrequired | boolean | |
account.archivedAtrequired | string (date-time)nullable | |
account.usedrequired | boolean | Posted to at least once: it can then be archived, never deleted. |
account.balancePencerequired | integer | The balance now, in pence (debit positive, credit negative). |
account.createdAtrequired | string (date-time) | |
account.updatedAtrequired | string (date-time) | |
fromrequired | string (date) | example "2026-03-31" |
torequired | string (date) | example "2026-03-31" |
openingPencerequired | integer | Integer pence (GBP). |
closingPencerequired | integer | Integer pence (GBP). |
linesrequired | array of BooksAccountLedgerLine | |
lines[].entryIdrequired | string (uuid) | |
lines[].seqrequired | integer | |
lines[].lineIndexrequired | integer | |
lines[].daterequired | string (date) | example "2026-03-31" |
lines[].kindrequired | string (BooksEntryKind) | One of: |
lines[].descriptionrequired | string | |
lines[].amountPencerequired | integer | Integer pence (GBP). Debit positive, credit negative. |
lines[].runningBalancePencerequired | integer | Integer pence (GBP). |
lines[].viarequired | string (BooksPostedVia) | One of: |
Errors: 400 Bad request, 401 Unauthorised, 403 Forbidden, 404 Not found, 429 Too many requests, as problem details (application/problem+json).
List posted entries
GET/api/v1/books/entries
- Scopes
books:read
Newest first, with their lines. Posted entries never change. Part of the books product: the firm must have it and you must have access to it.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
limit | query | integer | 1 to 100; default 50 |
beforeSeq | query | integer | The page before this entry number (from nextBeforeSeq). at least 1 |
accountId | query | string (uuid) | Only entries with a line on this account. |
kind | query | string | One of: |
to | query | string (date) | Entries dated on or before. |
from | query | string (date) | Entries dated on or after. |
Responses
200 OK, application/json
Body: object (BooksEntryPage).
| Field | Type | Description |
|---|---|---|
itemsrequired | array of BooksEntry | |
items[].idrequired | string (uuid) | |
items[].seqrequired | integer | Numbered from 1 per business, without gaps. |
items[].kindrequired | string (BooksEntryKind) | One of: |
items[].daterequired | string (date) | example "2026-03-31" |
items[].taxPointrequired | string (date)nullable | example "2026-03-31" |
items[].descriptionrequired | string | |
items[].sourcerequired | object (BooksEntrySource)nullable | |
items[].source.typerequired | string | example "journal" |
items[].source.idrequired | string | |
items[].source.keyrequired | stringnullable | |
items[].reversesSeqrequired | integernullable | |
items[].reversedBySeqrequired | integernullable | The entry that reversed this one. |
items[].postedAtrequired | string (date-time) | |
items[].postedByrequired | object (BooksActor) | |
items[].postedBy.kindrequired | string (BooksActorKind) | One of: |
items[].postedBy.idrequired | string | |
items[].postedBy.versionrequired | integernullable | |
items[].viarequired | string (BooksPostedVia) | One of: |
items[].actingFirmIdrequired | string (uuid)nullable | The practice that posted it through its link. |
items[].practiceLinkIdrequired | string (uuid)nullable | |
items[].prevHashrequired | stringnullable | |
items[].hashrequired | string | example "sha256:…" |
items[].journalIdrequired | string (uuid)nullable | The manual journal it posted from. |
items[].linesrequired | array of BooksEntryLine | |
items[].lines[].lineIndexrequired | integer | |
items[].lines[].accountIdrequired | string (uuid) | |
items[].lines[].accountCoderequired | string | |
items[].lines[].accountNamerequired | string | |
items[].lines[].accountOwnerNamerequired | string | |
items[].lines[].amountPencerequired | integer | Integer pence (GBP). Debit positive, credit negative. |
items[].lines[].descriptionrequired | stringnullable | |
items[].lines[].contactIdrequired | string (uuid)nullable | |
items[].lines[].vatrequired | object (BooksLineVat)nullable | VAT on a posted line, worked once at posting and never recomputed. |
items[].lines[].vat.vatCodeIdrequired | string | example "S20" |
items[].lines[].vat.siderequired | string (BooksVatSide)nullable | One of: |
items[].lines[].vat.netPencerequired | integer | Integer pence (GBP). |
items[].lines[].vat.vatPencerequired | integer | Integer pence (GBP). |
items[].lines[].vat.rateVersionrequired | stringnullable | example "S20@2011-01-04" |
items[].lines[].vat.taxPointrequired | string (date)nullable | When it differs from the entry’s. example "2026-03-31" |
items[].lines[].vat.cashBasisDaterequired | string (date)nullable | example "2026-03-31" |
items[].lines[].vat.boxesrequired | array of BooksVatBoxContribution | |
items[].lines[].vat.boxes[].boxrequired | integer | example 1 |
items[].lines[].vat.boxes[].amountPencerequired | integer | Integer pence (GBP). |
items[].lines[].vat.capitalGoodsrequired | booleannullable | |
items[].lines[].vat.frsRelevantGoodsrequired | booleannullable | |
items[].lines[].vat.frsOutsideSchemerequired | booleannullable | |
nextBeforeSeqrequired | integernullable | Pass as beforeSeq for the next (older) page; null on the last page. |
Errors: 400 Bad request, 401 Unauthorised, 403 Forbidden, 429 Too many requests, as problem details (application/problem+json).
Get a posted entry
GET/api/v1/books/entries/{entryId}
- Scopes
books:read
Part of the books product: the firm must have it and you must have access to it.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
entryIdrequired | path | string (uuid) |
Responses
200 OK, application/json
Body: object (BooksEntry).
A posted entry. Posted entries never change: a correction is a reversal and a new entry. hash chains each entry to the one before.
| Field | Type | Description |
|---|---|---|
idrequired | string (uuid) | |
seqrequired | integer | Numbered from 1 per business, without gaps. |
kindrequired | string (BooksEntryKind) | One of: |
daterequired | string (date) | example "2026-03-31" |
taxPointrequired | string (date)nullable | example "2026-03-31" |
descriptionrequired | string | |
sourcerequired | object (BooksEntrySource)nullable | |
source.typerequired | string | example "journal" |
source.idrequired | string | |
source.keyrequired | stringnullable | |
reversesSeqrequired | integernullable | |
reversedBySeqrequired | integernullable | The entry that reversed this one. |
postedAtrequired | string (date-time) | |
postedByrequired | object (BooksActor) | |
postedBy.kindrequired | string (BooksActorKind) | One of: |
postedBy.idrequired | string | |
postedBy.versionrequired | integernullable | |
viarequired | string (BooksPostedVia) | One of: |
actingFirmIdrequired | string (uuid)nullable | The practice that posted it through its link. |
practiceLinkIdrequired | string (uuid)nullable | |
prevHashrequired | stringnullable | |
hashrequired | string | example "sha256:…" |
journalIdrequired | string (uuid)nullable | The manual journal it posted from. |
linesrequired | array of BooksEntryLine | |
lines[].lineIndexrequired | integer | |
lines[].accountIdrequired | string (uuid) | |
lines[].accountCoderequired | string | |
lines[].accountNamerequired | string | |
lines[].accountOwnerNamerequired | string | |
lines[].amountPencerequired | integer | Integer pence (GBP). Debit positive, credit negative. |
lines[].descriptionrequired | stringnullable | |
lines[].contactIdrequired | string (uuid)nullable | |
lines[].vatrequired | object (BooksLineVat)nullable | VAT on a posted line, worked once at posting and never recomputed. |
lines[].vat.vatCodeIdrequired | string | example "S20" |
lines[].vat.siderequired | string (BooksVatSide)nullable | One of: |
lines[].vat.netPencerequired | integer | Integer pence (GBP). |
lines[].vat.vatPencerequired | integer | Integer pence (GBP). |
lines[].vat.rateVersionrequired | stringnullable | example "S20@2011-01-04" |
lines[].vat.taxPointrequired | string (date)nullable | When it differs from the entry’s. example "2026-03-31" |
lines[].vat.cashBasisDaterequired | string (date)nullable | example "2026-03-31" |
lines[].vat.boxesrequired | array of BooksVatBoxContribution | |
lines[].vat.boxes[].boxrequired | integer | example 1 |
lines[].vat.boxes[].amountPencerequired | integer | Integer pence (GBP). |
lines[].vat.capitalGoodsrequired | booleannullable | |
lines[].vat.frsRelevantGoodsrequired | booleannullable | |
lines[].vat.frsOutsideSchemerequired | booleannullable |
Errors: 400 Bad request, 401 Unauthorised, 403 Forbidden, 404 Not found, 429 Too many requests, as problem details (application/problem+json).
Reverse an entry
POST/api/v1/books/entries/{entryId}/reverse
- Scopes
books:write- Retries
- Send an
Idempotency-Keyto make retries safe.
Anyone who can write in the books (books:write), including a linked practice with year-end or full bookkeeping access; a read-only link can’t. For opening balances and adjustments posted without a journal: every line is negated, dated on the original’s date or the first open day after it. Void or amend a journal instead; change a bank line or invoice where it came from (409). Part of the books product: the firm must have it and you must have access to it.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
entryIdrequired | path | string (uuid) | |
Idempotency-Key | header | string | A unique key (1-255 visible characters) to make retries safe. Replayed for 24 hours. 1 to 255 characters |
Request body
Optional. application/json: object (BooksReverseEntry).
Reverse an opening balances entry or an adjustment that isn’t a journal’s (void a journal instead).
| Field | Type | Description |
|---|---|---|
date | string (date) | Defaults to the original’s date, or the first open day after it. example "2026-03-31" |
description | string | up to 500 characters |
Responses
201 Created, application/json
Body: object (BooksEntry).
A posted entry. Posted entries never change: a correction is a reversal and a new entry. hash chains each entry to the one before.
The fields are as shown above.
Errors: 400 Bad request, 401 Unauthorised, 403 Forbidden, 404 Not found, 409 Conflict, 422 Unprocessable content, 429 Too many requests, as problem details (application/problem+json).
List journals
GET/api/v1/books/journals
- Scopes
books:read
Newest first. Drafts carry the problems that stop them being posted. Part of the books product: the firm must have it and you must have access to it.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
status | query | string | One of: |
Responses
200 OK, application/json
Body: array of BooksJournal.
A manual journal. A draft can be edited, discarded or posted; once posted it is changed only by amending it (a reversal and a new entry) or voiding it (a reversal). VAT on lines is posted to the VAT account by Tolvi.
| Field | Type | Description |
|---|---|---|
[].idrequired | string (uuid) | |
[].statusrequired | string (BooksJournalStatus) | One of: |
[].kindrequired | string (BooksJournalKind) | One of: |
[].daterequired | string (date) | example "2026-03-31" |
[].descriptionrequired | string | |
[].referencerequired | stringnullable | |
[].linesrequired | array of BooksJournalLine | |
[].lines[].accountIdrequired | string (uuid) | |
[].lines[].amountPencerequired | integer | Integer pence (GBP). Debit positive, credit negative. With VAT, the net. |
[].lines[].description | stringnullable | up to 200 characters |
[].lines[].vat | object (BooksJournalLineVat)nullable | |
[].lines[].vat.vatCodeIdrequired | string | example "S20" |
[].lines[].vat.side | string (BooksVatSide)nullable | One of: |
[].lines[].vat.netPence | integernullable | Integer pence (GBP). Defaults to the line’s amount. |
[].lines[].vat.vatPence | integernullable | Integer pence (GBP). Worked from the rate when left out. |
[].lines[].vat.taxPoint | string (date)nullable | example "2026-03-31" |
[].lines[].vat.capitalGoods | booleannullable | |
[].lines[].vat.frsRelevantGoods | booleannullable | |
[].lines[].vat.frsOutsideScheme | booleannullable | |
[].lines[].vat.workedVatPence | integernullable | Integer pence (GBP). Read only: the VAT as posting would work it. |
[].debitsPencerequired | integer | Integer pence (GBP). |
[].creditsPencerequired | integer | Integer pence (GBP). Positive: the sum of the credit lines. |
[].vatControlPencerequired | integer | Integer pence (GBP). What Tolvi will post to the VAT account for VAT on the lines (debit positive). |
[].differencePencerequired | integer | Integer pence (GBP). Debits less credits, including the VAT line: nil when it balances. |
[].problemsrequired | array of BooksLedgerProblem | Why it can’t be posted yet (drafts only). |
[].problems[].coderequired | string | example "unbalanced" |
[].problems[].messagerequired | string | |
[].problems[].linerequired | integernullable | Zero-based index of the line it is about. |
[].entryIdrequired | string (uuid)nullable | |
[].entrySeqrequired | integernullable | |
[].voidEntryIdrequired | string (uuid)nullable | |
[].createdByrequired | string (uuid)nullable | |
[].createdAtrequired | string (date-time) | |
[].updatedAtrequired | string (date-time) | |
[].postedAtrequired | string (date-time)nullable | |
[].voidedAtrequired | string (date-time)nullable |
Errors: 400 Bad request, 401 Unauthorised, 403 Forbidden, 429 Too many requests, as problem details (application/problem+json).
Start a journal
POST/api/v1/books/journals
- Scopes
books:write- Retries
- Send an
Idempotency-Keyto make retries safe.
Anyone who can write in the books (books:write), including a linked practice with year-end or full bookkeeping access; a read-only link can’t. A draft touches nothing until it is posted. Part of the books product: the firm must have it and you must have access to it.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
Idempotency-Key | header | string | A unique key (1-255 visible characters) to make retries safe. Replayed for 24 hours. 1 to 255 characters |
Request body
Required. application/json: object (BooksCreateJournal).
| Field | Type | Description |
|---|---|---|
daterequired | string (date) | example "2026-03-31" |
description | string | up to 500 characters |
reference | stringnullable | up to 60 characters |
kind | string (BooksJournalKind) | journal (default) or year_end_adjustment. One of: |
lines | array of BooksJournalLine | |
lines[].accountIdrequired | string (uuid) | |
lines[].amountPencerequired | integer | Integer pence (GBP). Debit positive, credit negative. With VAT, the net. |
lines[].description | stringnullable | up to 200 characters |
lines[].vat | object (BooksJournalLineVat)nullable | |
lines[].vat.vatCodeIdrequired | string | example "S20" |
lines[].vat.side | string (BooksVatSide)nullable | One of: |
lines[].vat.netPence | integernullable | Integer pence (GBP). Defaults to the line’s amount. |
lines[].vat.vatPence | integernullable | Integer pence (GBP). Worked from the rate when left out. |
lines[].vat.taxPoint | string (date)nullable | example "2026-03-31" |
lines[].vat.capitalGoods | booleannullable | |
lines[].vat.frsRelevantGoods | booleannullable | |
lines[].vat.frsOutsideScheme | booleannullable | |
lines[].vat.workedVatPence | integernullable | Integer pence (GBP). Read only: the VAT as posting would work it. |
Responses
201 Created, application/json
Body: object (BooksJournal).
A manual journal. A draft can be edited, discarded or posted; once posted it is changed only by amending it (a reversal and a new entry) or voiding it (a reversal). VAT on lines is posted to the VAT account by Tolvi.
| Field | Type | Description |
|---|---|---|
idrequired | string (uuid) | |
statusrequired | string (BooksJournalStatus) | One of: |
kindrequired | string (BooksJournalKind) | One of: |
daterequired | string (date) | example "2026-03-31" |
descriptionrequired | string | |
referencerequired | stringnullable | |
linesrequired | array of BooksJournalLine | |
lines[].accountIdrequired | string (uuid) | |
lines[].amountPencerequired | integer | Integer pence (GBP). Debit positive, credit negative. With VAT, the net. |
lines[].description | stringnullable | up to 200 characters |
lines[].vat | object (BooksJournalLineVat)nullable | |
lines[].vat.vatCodeIdrequired | string | example "S20" |
lines[].vat.side | string (BooksVatSide)nullable | One of: |
lines[].vat.netPence | integernullable | Integer pence (GBP). Defaults to the line’s amount. |
lines[].vat.vatPence | integernullable | Integer pence (GBP). Worked from the rate when left out. |
lines[].vat.taxPoint | string (date)nullable | example "2026-03-31" |
lines[].vat.capitalGoods | booleannullable | |
lines[].vat.frsRelevantGoods | booleannullable | |
lines[].vat.frsOutsideScheme | booleannullable | |
lines[].vat.workedVatPence | integernullable | Integer pence (GBP). Read only: the VAT as posting would work it. |
debitsPencerequired | integer | Integer pence (GBP). |
creditsPencerequired | integer | Integer pence (GBP). Positive: the sum of the credit lines. |
vatControlPencerequired | integer | Integer pence (GBP). What Tolvi will post to the VAT account for VAT on the lines (debit positive). |
differencePencerequired | integer | Integer pence (GBP). Debits less credits, including the VAT line: nil when it balances. |
problemsrequired | array of BooksLedgerProblem | Why it can’t be posted yet (drafts only). |
problems[].coderequired | string | example "unbalanced" |
problems[].messagerequired | string | |
problems[].linerequired | integernullable | Zero-based index of the line it is about. |
entryIdrequired | string (uuid)nullable | |
entrySeqrequired | integernullable | |
voidEntryIdrequired | string (uuid)nullable | |
createdByrequired | string (uuid)nullable | |
createdAtrequired | string (date-time) | |
updatedAtrequired | string (date-time) | |
postedAtrequired | string (date-time)nullable | |
voidedAtrequired | string (date-time)nullable |
Errors: 400 Bad request, 401 Unauthorised, 403 Forbidden, 409 Conflict, 422 Unprocessable content, 429 Too many requests, as problem details (application/problem+json).
Get a journal
GET/api/v1/books/journals/{journalId}
- Scopes
books:read
Part of the books product: the firm must have it and you must have access to it.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
journalIdrequired | path | string (uuid) |
Responses
200 OK, application/json
Body: object (BooksJournal).
A manual journal. A draft can be edited, discarded or posted; once posted it is changed only by amending it (a reversal and a new entry) or voiding it (a reversal). VAT on lines is posted to the VAT account by Tolvi.
The fields are as shown above.
Errors: 400 Bad request, 401 Unauthorised, 403 Forbidden, 404 Not found, 429 Too many requests, as problem details (application/problem+json).
Change a draft journal
PATCH/api/v1/books/journals/{journalId}
- Scopes
books:write
Anyone who can write in the books (books:write), including a linked practice with year-end or full bookkeeping access; a read-only link can’t. Posted journals are amended instead (409). Part of the books product: the firm must have it and you must have access to it.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
journalIdrequired | path | string (uuid) |
Request body
Required. application/json: object (BooksUpdateJournal).
Change a draft. Only the fields sent change; lines replaces every line.
| Field | Type | Description |
|---|---|---|
date | string (date) | example "2026-03-31" |
description | string | up to 500 characters |
reference | stringnullable | up to 60 characters |
kind | string (BooksJournalKind) | One of: |
lines | array of BooksJournalLine | |
lines[].accountIdrequired | string (uuid) | |
lines[].amountPencerequired | integer | Integer pence (GBP). Debit positive, credit negative. With VAT, the net. |
lines[].description | stringnullable | up to 200 characters |
lines[].vat | object (BooksJournalLineVat)nullable | |
lines[].vat.vatCodeIdrequired | string | example "S20" |
lines[].vat.side | string (BooksVatSide)nullable | One of: |
lines[].vat.netPence | integernullable | Integer pence (GBP). Defaults to the line’s amount. |
lines[].vat.vatPence | integernullable | Integer pence (GBP). Worked from the rate when left out. |
lines[].vat.taxPoint | string (date)nullable | example "2026-03-31" |
lines[].vat.capitalGoods | booleannullable | |
lines[].vat.frsRelevantGoods | booleannullable | |
lines[].vat.frsOutsideScheme | booleannullable | |
lines[].vat.workedVatPence | integernullable | Integer pence (GBP). Read only: the VAT as posting would work it. |
Responses
200 OK, application/json
Body: object (BooksJournal).
A manual journal. A draft can be edited, discarded or posted; once posted it is changed only by amending it (a reversal and a new entry) or voiding it (a reversal). VAT on lines is posted to the VAT account by Tolvi.
The fields are as shown above.
Errors: 400 Bad request, 401 Unauthorised, 403 Forbidden, 404 Not found, 429 Too many requests, as problem details (application/problem+json).
Discard a draft journal
DELETE/api/v1/books/journals/{journalId}
- Scopes
books:write
Anyone who can write in the books (books:write), including a linked practice with year-end or full bookkeeping access; a read-only link can’t. A posted journal is never deleted: void it (409). Part of the books product: the firm must have it and you must have access to it.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
journalIdrequired | path | string (uuid) |
Responses
204 No content
Errors: 400 Bad request, 401 Unauthorised, 403 Forbidden, 404 Not found, 429 Too many requests, as problem details (application/problem+json).
Post a journal
POST/api/v1/books/journals/{journalId}/post
- Scopes
books:write
Anyone who can write in the books (books:write), including a linked practice with year-end or full bookkeeping access; a read-only link can’t. It must balance to the penny, use open accounts and be dated after any lock (422 lists every problem). VAT on lines is worked at the rate in force at the tax point and posted to the VAT account by Tolvi. Part of the books product: the firm must have it and you must have access to it.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
journalIdrequired | path | string (uuid) |
Responses
200 OK, application/json
Body: object (BooksJournal).
A manual journal. A draft can be edited, discarded or posted; once posted it is changed only by amending it (a reversal and a new entry) or voiding it (a reversal). VAT on lines is posted to the VAT account by Tolvi.
The fields are as shown above.
Errors: 400 Bad request, 401 Unauthorised, 403 Forbidden, 404 Not found, 429 Too many requests, as problem details (application/problem+json).
Void a posted journal
POST/api/v1/books/journals/{journalId}/void
- Scopes
books:write
Anyone who can write in the books (books:write), including a linked practice with year-end or full bookkeeping access; a read-only link can’t. Its entry is reversed, dated on the journal’s date or the first open day after it. Part of the books product: the firm must have it and you must have access to it.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
journalIdrequired | path | string (uuid) |
Request body
Optional. application/json: object (BooksVoidJournal).
| Field | Type | Description |
|---|---|---|
date | string (date) | Defaults to the journal’s date, or the first open day after it. example "2026-03-31" |
Responses
200 OK, application/json
Body: object (BooksJournal).
A manual journal. A draft can be edited, discarded or posted; once posted it is changed only by amending it (a reversal and a new entry) or voiding it (a reversal). VAT on lines is posted to the VAT account by Tolvi.
The fields are as shown above.
Errors: 400 Bad request, 401 Unauthorised, 403 Forbidden, 404 Not found, 429 Too many requests, as problem details (application/problem+json).
Amend a posted journal
POST/api/v1/books/journals/{journalId}/amend
- Scopes
books:write
Anyone who can write in the books (books:write), including a linked practice with year-end or full bookkeeping access; a read-only link can’t. Tolvi reverses the posted entry and posts the journal as sent, in one step. Either is dated in the first open period if its own date is locked. Part of the books product: the firm must have it and you must have access to it.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
journalIdrequired | path | string (uuid) |
Request body
Required. application/json: object (BooksAmendJournal).
The journal as it should have been. Tolvi reverses the posted entry and posts this, in one step.
| Field | Type | Description |
|---|---|---|
daterequired | string (date) | example "2026-03-31" |
descriptionrequired | string | up to 500 characters |
reference | stringnullable | up to 60 characters |
linesrequired | array of BooksJournalLine | |
lines[].accountIdrequired | string (uuid) | |
lines[].amountPencerequired | integer | Integer pence (GBP). Debit positive, credit negative. With VAT, the net. |
lines[].description | stringnullable | up to 200 characters |
lines[].vat | object (BooksJournalLineVat)nullable | |
lines[].vat.vatCodeIdrequired | string | example "S20" |
lines[].vat.side | string (BooksVatSide)nullable | One of: |
lines[].vat.netPence | integernullable | Integer pence (GBP). Defaults to the line’s amount. |
lines[].vat.vatPence | integernullable | Integer pence (GBP). Worked from the rate when left out. |
lines[].vat.taxPoint | string (date)nullable | example "2026-03-31" |
lines[].vat.capitalGoods | booleannullable | |
lines[].vat.frsRelevantGoods | booleannullable | |
lines[].vat.frsOutsideScheme | booleannullable | |
lines[].vat.workedVatPence | integernullable | Integer pence (GBP). Read only: the VAT as posting would work it. |
Responses
200 OK, application/json
Body: object (BooksJournal).
A manual journal. A draft can be edited, discarded or posted; once posted it is changed only by amending it (a reversal and a new entry) or voiding it (a reversal). VAT on lines is posted to the VAT account by Tolvi.
The fields are as shown above.
Errors: 400 Bad request, 401 Unauthorised, 403 Forbidden, 404 Not found, 429 Too many requests, as problem details (application/problem+json).
Get the trial balance at a date
GET/api/v1/books/trial-balance
- Scopes
books:read
Derived from posted entries, never stored. Debit positive, credit negative. Part of the books product: the firm must have it and you must have access to it.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
includeZero | query | string | One of: |
throughSeq | query | integer | The ledger as it stood after this entry. at least 0 |
yearStart | query | string (date) | Defaults to the start of the financial year containing asAt, from the business’s year end. |
asAt | query | string (date) | Defaults to today. |
Responses
200 OK, application/json
Body: object (BooksTrialBalance).
The trial balance at a date, derived from posted entries (nothing is stored). Profit and loss before the year start is in retained earnings or the capital account. throughSeq and ledgerHash pin exactly which entries it reflects.
| Field | Type | Description |
|---|---|---|
asAtrequired | string (date) | example "2026-03-31" |
yearStartrequired | string (date) | example "2026-03-31" |
throughSeqrequired | integer | |
ledgerHashrequired | stringnullable | |
rowsrequired | array of BooksTrialBalanceRow | |
rows[].accountIdrequired | string (uuid) | |
rows[].coderequired | string | |
rows[].namerequired | string | |
rows[].ownerNamerequired | string | |
rows[].ownerCategoryrequired | string (BooksOwnerCategory) | One of: |
rows[].ownerCategoryLabelrequired | string | |
rows[].classrequired | string (BooksAccountClass) | One of: |
rows[].normalBalancerequired | string (BooksNormalBalance) | One of: |
rows[].leadLinerequired | stringnullable | |
rows[].balancePencerequired | integer | Integer pence (GBP). Debit positive, credit negative. |
totalDebitsPencerequired | integer | Integer pence (GBP). |
totalCreditsPencerequired | integer | Integer pence (GBP). Positive: the sum of credit balances. |
Errors: 400 Bad request, 401 Unauthorised, 403 Forbidden, 429 Too many requests, as problem details (application/problem+json).
List changes since a ledger point
GET/api/v1/books/ledger/changes
- Scopes
books:read
Postings made after throughSeq that change a balance on or before asAt. Part of the books product: the firm must have it and you must have access to it.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
asAtrequired | query | string (date) | The period end it was taken for. |
throughSeqrequired | query | integer | The ledger point a trial balance was taken at. at least 0 |
Responses
200 OK, application/json
Body: object (BooksLedgerChanges).
Postings made after a ledger point (throughSeq) that change a balance on or before asAt: what explains a difference since a trial balance was taken.
| Field | Type | Description |
|---|---|---|
throughSeqrequired | integer | |
asAtrequired | string (date) | example "2026-03-31" |
headSeqrequired | integer | The latest entry now. |
changesrequired | array of BooksLedgerChange | |
changes[].entryIdrequired | string (uuid) | |
changes[].seqrequired | integer | |
changes[].lineIndexrequired | integer | |
changes[].accountIdrequired | string (uuid) | |
changes[].accountCoderequired | string | |
changes[].daterequired | string (date) | example "2026-03-31" |
changes[].descriptionrequired | string | |
changes[].amountPencerequired | integer | Integer pence (GBP). |
changes[].postedAtrequired | string (date-time) | |
changes[].kindrequired | string (BooksEntryKind) | One of: |
changes[].viarequired | string (BooksPostedVia) | One of: |
Errors: 400 Bad request, 401 Unauthorised, 403 Forbidden, 429 Too many requests, as problem details (application/problem+json).
Check the ledger’s hash chain
GET/api/v1/books/ledger/integrity
- Scopes
books:read
Re-walks every entry from the first: numbered without gaps, each unchanged since it was posted, each balanced. Part of the books product: the firm must have it and you must have access to it.
Responses
200 OK, application/json
Body: object (BooksLedgerIntegrity).
The hash chain re-walked from the first entry: numbering without gaps, each entry unchanged since posting and balanced.
| Field | Type | Description |
|---|---|---|
okrequired | boolean | |
entriesrequired | integer | |
headSeqrequired | integer | |
headHashrequired | stringnullable | |
problemrequired | object (BooksLedgerIntegrityProblem)nullable | |
problem.seqrequired | integer | |
problem.kindrequired | string (BooksIntegrityProblemKind) | One of: |
problem.messagerequired | string |
Errors: 400 Bad request, 401 Unauthorised, 403 Forbidden, 429 Too many requests, as problem details (application/problem+json).
Get the period locks
GET/api/v1/books/locks
- Scopes
books:read
The locks in force, their history and the first open date. Part of the books product: the firm must have it and you must have access to it.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
date | query | string (date) | A date to check: dateProblem says why it can’t take an entry. Defaults to today. |
Responses
200 OK, application/json
Body: object (BooksLocks).
The locks in force. owner: the business closed its books to a date (it or its practice can move it). accountant: the practice locked them after year-end sign-off (only it can reopen them). vatFiled: set by Tolvi when HMRC accepts a VAT return; never lifted.
| Field | Type | Description |
|---|---|---|
ownerrequired | object (BooksLockState)nullable | |
owner.throughrequired | string (date) | Nothing new may be dated on or before this day. example "2026-03-31" |
owner.atrequired | string (date-time) | |
owner.byKindrequired | string (BooksLockBy) | One of: |
owner.byNamerequired | stringnullable | The practice’s name, for an accountant’s lock. |
owner.linkIdrequired | string (uuid)nullable | |
owner.referencerequired | stringnullable | |
accountantrequired | object (BooksLockState)nullable | |
accountant.throughrequired | string (date) | Nothing new may be dated on or before this day. example "2026-03-31" |
accountant.atrequired | string (date-time) | |
accountant.byKindrequired | string (BooksLockBy) | One of: |
accountant.byNamerequired | stringnullable | The practice’s name, for an accountant’s lock. |
accountant.linkIdrequired | string (uuid)nullable | |
accountant.referencerequired | stringnullable | |
vatFiledrequired | object (BooksLockState)nullable | |
vatFiled.throughrequired | string (date) | Nothing new may be dated on or before this day. example "2026-03-31" |
vatFiled.atrequired | string (date-time) | |
vatFiled.byKindrequired | string (BooksLockBy) | One of: |
vatFiled.byNamerequired | stringnullable | The practice’s name, for an accountant’s lock. |
vatFiled.linkIdrequired | string (uuid)nullable | |
vatFiled.referencerequired | stringnullable | |
firstOpenDaterequired | string (date) | example "2026-03-31" |
daterequired | string (date) | example "2026-03-31" |
dateProblemrequired | stringnullable | |
eventsrequired | array of BooksLockEvent | |
events[].idrequired | string (uuid) | |
events[].kindrequired | string (BooksLockKind) | One of: |
events[].actionrequired | string (BooksLockAction) | One of: |
events[].throughrequired | string (date)nullable | example "2026-03-31" |
events[].atrequired | string (date-time) | |
events[].byKindrequired | string (BooksLockBy) | One of: |
events[].byNamerequired | stringnullable | |
events[].byUserIdrequired | string (uuid)nullable | |
events[].linkIdrequired | string (uuid)nullable | |
events[].reasonrequired | stringnullable | |
events[].referencerequired | stringnullable |
Errors: 400 Bad request, 401 Unauthorised, 403 Forbidden, 429 Too many requests, as problem details (application/problem+json).
Lock or unlock the books
POST/api/v1/books/locks
- Scopes
books:write- Access
- A signed-in Tolvi session only, never an API token.
Needs a signed-in person (never a token or connected app). The owner lock: the business’s owners and admins, or a linked practice that can post. The accountant’s year-end lock: only a linked practice, and only the practice that set it can reopen the year, with a reason. The VAT lock is set by Tolvi when HMRC accepts a return and can’t be changed here. Part of the books product: the firm must have it and you must have access to it.
Request body
Required. application/json: object (BooksChangeLock).
Lock the books through a date, or move a lock back (with through) or lift it (no through).
| Field | Type | Description |
|---|---|---|
kindrequired | string (BooksPersonLockKind) | owner: the business’s own lock. accountant: the practice’s year-end lock (practices only). One of: |
actionrequired | string (BooksLockAction) | One of: |
through | string (date)nullable | example "2026-03-31" |
reason | string | Needed to reopen a year the accountant locked. up to 500 characters |
reference | string | e.g. the engagement behind a year-end lock. up to 100 characters |
Responses
200 OK, application/json
Body: object (BooksLocks).
The locks in force. owner: the business closed its books to a date (it or its practice can move it). accountant: the practice locked them after year-end sign-off (only it can reopen them). vatFiled: set by Tolvi when HMRC accepts a VAT return; never lifted.
The fields are as shown above.
Errors: 400 Bad request, 401 Unauthorised, 403 Forbidden, 429 Too many requests, as problem details (application/problem+json).
Get the opening balances in force
GET/api/v1/books/opening-balances
- Scopes
books:read
The opening entry in force, if any, the suggested start date, and the accounts each plain-English question posts to. Part of the books product: the firm must have it and you must have access to it.
Responses
200 OK, application/json
Body: object (BooksOpeningStatus).
Whether the books have a start, and what the opening balances screen needs.
| Field | Type | Description |
|---|---|---|
suggestedStartDaterequired | string (date) | The first day of this financial year. example "2026-03-31" |
standingrequired | object (BooksOpeningStanding)nullable | The opening entry in force. |
standing.entryIdrequired | string (uuid) | |
standing.seqrequired | integer | |
standing.entryDaterequired | string (date) | example "2026-03-31" |
standing.startDaterequired | string (date) | The first day the books cover. example "2026-03-31" |
standing.fromWorkingPapersrequired | boolean | Posted from a final trial balance in Working Papers. |
standing.postedAtrequired | string (date-time) | |
standing.linesrequired | array of BooksOpeningEntryLine | |
standing.lines[].accountIdrequired | string (uuid) | |
standing.lines[].accountCoderequired | string | |
standing.lines[].accountNamerequired | string | |
standing.lines[].ownerNamerequired | string | |
standing.lines[].normalBalancerequired | string (BooksNormalBalance) | One of: |
standing.lines[].amountPencerequired | integer | Integer pence (GBP). Debit positive, credit negative. |
standing.lines[].contactNamerequired | stringnullable | The customer or supplier, on a control account line split by unpaid invoice or bill. |
standing.suspensePencerequired | integer | Integer pence (GBP). |
standing.unpaidInvoicesrequired | array of BooksOpeningStandingInvoice | |
standing.unpaidInvoices[].idrequired | string (uuid) | |
standing.unpaidInvoices[].numberrequired | string | |
standing.unpaidInvoices[].customerNamerequired | string | |
standing.unpaidInvoices[].amountPencerequired | integer | Integer pence (GBP). |
standing.unpaidInvoices[].outstandingPencerequired | integer | Integer pence (GBP). |
standing.unpaidBillsrequired | array of BooksOpeningStandingBill | |
standing.unpaidBills[].idrequired | string (uuid) | |
standing.unpaidBills[].referencerequired | string | |
standing.unpaidBills[].supplierNamerequired | string | |
standing.unpaidBills[].amountPencerequired | integer | Integer pence (GBP). |
standing.unpaidBills[].outstandingPencerequired | integer | Integer pence (GBP). |
guidedrequired | object (BooksOpeningGuidedAccounts) | The accounts each plain-English question posts to. |
guided.bankrequired | array of BooksOpeningAccountRef | |
guided.bank[].coderequired | string | |
guided.bank[].namerequired | string | |
guided.bank[].ownerNamerequired | string | |
guided.debtorsrequired | object (BooksOpeningAccountRef)nullable | |
guided.debtors.coderequired | string | |
guided.debtors.namerequired | string | |
guided.debtors.ownerNamerequired | string | |
guided.creditorsrequired | object (BooksOpeningAccountRef)nullable | |
guided.creditors.coderequired | string | |
guided.creditors.namerequired | string | |
guided.creditors.ownerNamerequired | string | |
guided.vatrequired | object (BooksOpeningAccountRef)nullable | |
guided.vat.coderequired | string | |
guided.vat.namerequired | string | |
guided.vat.ownerNamerequired | string | |
guided.loanrequired | object (BooksOpeningAccountRef)nullable | |
guided.loan.coderequired | string | |
guided.loan.namerequired | string | |
guided.loan.ownerNamerequired | string | |
guided.worthrequired | object (BooksOpeningAccountRef)nullable | Where the difference goes when it is what the business was worth. |
guided.worth.coderequired | string | |
guided.worth.namerequired | string | |
guided.worth.ownerNamerequired | string | |
vatRegisteredrequired | boolean | |
vatSchemerequired | stringnullable | |
canSetUprequired | boolean | This person can post and reverse opening balances. |
Errors: 400 Bad request, 401 Unauthorised, 403 Forbidden, 429 Too many requests, as problem details (application/problem+json).
Post opening balances
POST/api/v1/books/opening-balances
- Scopes
books:write- Retries
- Send an
Idempotency-Keyto make retries safe.
The business’s owners and admins (books:admin), or a linked practice whose access lets it post (year-end or full bookkeeping). One entry dated the day before the books start. Every balance must have an account (422 lists any that don’t); a difference goes to suspense. Refused while earlier opening balances stand (409). Part of the books product: the firm must have it and you must have access to it.
Parameters
| Name | In | Type | Description |
|---|---|---|---|
Idempotency-Key | header | string | A unique key (1-255 visible characters) to make retries safe. Replayed for 24 hours. 1 to 255 characters |
Request body
Required. application/json: object (BooksOpeningBalancesInput).
Opening balances from a trial balance (as accounts, or the CSV text of an export), at the date the books start.
| Field | Type | Description |
|---|---|---|
conversionDaterequired | string (date) | The first day the books cover; the entry is dated the day before. example "2026-03-31" |
accounts | array of object | |
accounts[].coderequired | string | |
accounts[].name | string | |
accounts[].balancePencerequired | integer | Integer pence (GBP). Debit positive, credit negative. |
accounts[].leadLine | stringnullable | |
csv | string | A trial balance export as CSV text (code, name, debit, credit or balance). |
mapping | object | Source code to an account code in these books. |
differenceTo | string (BooksOpeningDifferenceTo) | suspense (the default): a difference is an error for the accountant to clear. equity: it is what the business was worth (capital or reserves). One of: |
unpaidInvoices | array of BooksOpeningUnpaidInvoiceInput | Invoices issued before the books start and not yet paid. They are part of the debtors balance and can be paid and chased like any other. |
unpaidInvoices[].customerId | string (uuid) | |
unpaidInvoices[].customerName | string | up to 200 characters |
unpaidInvoices[].numberrequired | string | The number it was issued with, outside Tolvi’s own series. up to 60 characters |
unpaidInvoices[].issueDaterequired | string (date) | example "2026-03-31" |
unpaidInvoices[].dueDate | string (date) | Defaults to the business’s usual payment terms. example "2026-03-31" |
unpaidInvoices[].amountPencerequired | integer | Integer pence (GBP). What is still owed, including any VAT. |
unpaidBills | array of BooksOpeningUnpaidBillInput | Bills dated before the books start and not yet paid. They are part of the creditors balance and can be paid and matched like any other, with no VAT breakdown. |
unpaidBills[].supplierId | string (uuid) | |
unpaidBills[].supplierName | string | up to 200 characters |
unpaidBills[].referencerequired | string | The supplier’s own invoice number. up to 60 characters |
unpaidBills[].billDaterequired | string (date) | example "2026-03-31" |
unpaidBills[].dueDate | string (date) | Defaults to the supplier’s payment terms, or 30 days. example "2026-03-31" |
unpaidBills[].amountPencerequired | integer | Integer pence (GBP). What is still owed, including any VAT. |
Responses
201 Created, application/json
Body: object (BooksOpeningBalancesPosted).
| Field | Type | Description |
|---|---|---|
entryrequired | object (BooksEntry) | A posted entry. Posted entries never change: a correction is a reversal and a new entry. |
entry.idrequired | string (uuid) | |
entry.seqrequired | integer | Numbered from 1 per business, without gaps. |
entry.kindrequired | string (BooksEntryKind) | One of: |
entry.daterequired | string (date) | example "2026-03-31" |
entry.taxPointrequired | string (date)nullable | example "2026-03-31" |
entry.descriptionrequired | string | |
entry.sourcerequired | object (BooksEntrySource)nullable | |
entry.source.typerequired | string | example "journal" |
entry.source.idrequired | string | |
entry.source.keyrequired | stringnullable | |
entry.reversesSeqrequired | integernullable | |
entry.reversedBySeqrequired | integernullable | The entry that reversed this one. |
entry.postedAtrequired | string (date-time) | |
entry.postedByrequired | object (BooksActor) | |
entry.postedBy.kindrequired | string (BooksActorKind) | One of: |
entry.postedBy.idrequired | string | |
entry.postedBy.versionrequired | integernullable | |
entry.viarequired | string (BooksPostedVia) | One of: |
entry.actingFirmIdrequired | string (uuid)nullable | The practice that posted it through its link. |
entry.practiceLinkIdrequired | string (uuid)nullable | |
entry.prevHashrequired | stringnullable | |
entry.hashrequired | string | example "sha256:…" |
entry.journalIdrequired | string (uuid)nullable | The manual journal it posted from. |
entry.linesrequired | array of BooksEntryLine | |
entry.lines[].lineIndexrequired | integer | |
entry.lines[].accountIdrequired | string (uuid) | |
entry.lines[].accountCoderequired | string | |
entry.lines[].accountNamerequired | string | |
entry.lines[].accountOwnerNamerequired | string | |
entry.lines[].amountPencerequired | integer | Integer pence (GBP). Debit positive, credit negative. |
entry.lines[].descriptionrequired | stringnullable | |
entry.lines[].contactIdrequired | string (uuid)nullable | |
entry.lines[].vatrequired | object (BooksLineVat)nullable | VAT on a posted line, worked once at posting and never recomputed. |
entry.lines[].vat.vatCodeIdrequired | string | example "S20" |
entry.lines[].vat.siderequired | string (BooksVatSide)nullable | One of: |
entry.lines[].vat.netPencerequired | integer | Integer pence (GBP). |
entry.lines[].vat.vatPencerequired | integer | Integer pence (GBP). |
entry.lines[].vat.rateVersionrequired | stringnullable | example "S20@2011-01-04" |
entry.lines[].vat.taxPointrequired | string (date)nullable | When it differs from the entry’s. example "2026-03-31" |
entry.lines[].vat.cashBasisDaterequired | string (date)nullable | example "2026-03-31" |
entry.lines[].vat.boxesrequired | array of BooksVatBoxContribution | |
entry.lines[].vat.boxes[].boxrequired | integer | example 1 |
entry.lines[].vat.boxes[].amountPencerequired | integer | Integer pence (GBP). |
entry.lines[].vat.capitalGoodsrequired | booleannullable | |
entry.lines[].vat.frsRelevantGoodsrequired | booleannullable | |
entry.lines[].vat.frsOutsideSchemerequired | booleannullable | |
suspensePencerequired | integer | Integer pence (GBP). |
warningsrequired | array of string |
Errors: 400 Bad request, 401 Unauthorised, 403 Forbidden, 409 Conflict, 422 Unprocessable content, 429 Too many requests, as problem details (application/problem+json).
Preview opening balances
POST/api/v1/books/opening-balances/preview
- Scopes
books:write
The business’s owners and admins (books:admin), or a linked practice whose access lets it post (year-end or full bookkeeping). Where each balance would go and the entry that would be posted. Nothing is saved. Part of the books product: the firm must have it and you must have access to it.
Request body
Required. application/json: object (BooksOpeningBalancesInput).
Opening balances from a trial balance (as accounts, or the CSV text of an export), at the date the books start.
The fields are as shown above.
Responses
200 OK, application/json
Body: object (BooksOpeningBalancesPreview).
Where each balance would go, the entry that would be posted, and anything that must be mapped first.
| Field | Type | Description |
|---|---|---|
conversionDaterequired | string (date) | example "2026-03-31" |
entryDaterequired | string (date) | example "2026-03-31" |
planrequired | array of BooksOpeningPlanLine | |
plan[].sourceCoderequired | string | |
plan[].sourceNamerequired | string | |
plan[].balancePencerequired | integer | Integer pence (GBP). |
plan[].targetCoderequired | string | |
plan[].targetNamerequired | string | |
plan[].viarequired | string (BooksOpeningPlanVia) | One of: |
unmappedrequired | array of BooksOpeningUnmapped | |
unmapped[].coderequired | string | |
unmapped[].namerequired | string | |
unmapped[].balancePencerequired | integer | Integer pence (GBP). |
unmapped[].leadLinerequired | stringnullable | |
linesrequired | array of BooksOpeningEntryLine | |
lines[].accountIdrequired | string (uuid) | |
lines[].accountCoderequired | string | |
lines[].accountNamerequired | string | |
lines[].ownerNamerequired | string | |
lines[].normalBalancerequired | string (BooksNormalBalance) | One of: |
lines[].amountPencerequired | integer | Integer pence (GBP). Debit positive, credit negative. |
lines[].contactNamerequired | stringnullable | The customer or supplier, on a control account line split by unpaid invoice or bill. |
suspensePencerequired | integer | Integer pence (GBP). What went to suspense to make it balance (debit positive). |
equityPencerequired | integer | Integer pence (GBP). What went to capital or reserves to make it balance (debit positive). |
warningsrequired | array of string | |
problemsrequired | array of string | What stops it being posted, in words. |
unpaidInvoicesrequired | array of BooksOpeningUnpaidInvoice | |
unpaidInvoices[].customerNamerequired | string | |
unpaidInvoices[].newCustomerrequired | boolean | The customer will be added. |
unpaidInvoices[].numberrequired | string | |
unpaidInvoices[].issueDaterequired | string (date) | example "2026-03-31" |
unpaidInvoices[].dueDaterequired | string (date) | example "2026-03-31" |
unpaidInvoices[].amountPencerequired | integer | Integer pence (GBP). |
unpaidBillsrequired | array of BooksOpeningUnpaidBill | |
unpaidBills[].supplierNamerequired | string | |
unpaidBills[].newSupplierrequired | boolean | The supplier will be added. |
unpaidBills[].referencerequired | string | |
unpaidBills[].billDaterequired | string (date) | example "2026-03-31" |
unpaidBills[].dueDaterequired | string (date) | example "2026-03-31" |
unpaidBills[].amountPencerequired | integer | Integer pence (GBP). |
alreadyPostedrequired | boolean |
Errors: 400 Bad request, 401 Unauthorised, 403 Forbidden, 429 Too many requests, as problem details (application/problem+json).
Get the getting-started checklist
GET/api/v1/books/getting-started
- Scopes
books:read
Six steps for a new business, each ticked from real data: business details, a bank, starting balances, how invoices look, VAT and an accountant. Part of the books product: the firm must have it and you must have access to it.
Responses
200 OK, application/json
Body: object (BooksGettingStarted).
The new business checklist, worked out from the business’s own data on every read.
| Field | Type | Description |
|---|---|---|
stepsrequired | array of BooksGettingStartedStep | |
steps[].keyrequired | string (BooksGettingStartedKey) | One of: |
steps[].labelrequired | string | |
steps[].donerequired | boolean | |
steps[].detailrequired | stringnullable | How it was done, when that needs saying. |
doneCountrequired | integer | |
completerequired | boolean | Every step is done. |
hiddenrequired | boolean | The owner hid the list from Home. |
notVatRegisteredrequired | boolean | The business said it isn’t registered for VAT. |
noOpeningBalancesrequired | boolean | The business said it has nothing to bring forward. |
Errors: 400 Bad request, 401 Unauthorised, 403 Forbidden, 429 Too many requests, as problem details (application/problem+json).
Answer or hide the getting-started checklist
PUT/api/v1/books/getting-started
- Scopes
books:write
Hide the list or bring it back, and the two answers only a person can give: not registered for VAT, and nothing to bring forward. The business’s owners and admins, or a practice with a link that can post. Part of the books product: the firm must have it and you must have access to it.
Request body
Required. application/json: object (BooksUpdateGettingStarted).
Answers only a person can give. The ticks themselves come from the books.
| Field | Type | Description |
|---|---|---|
hidden | boolean | Hide the list from Home, or bring it back. |
notVatRegistered | boolean | The business isn’t registered for VAT, so that step is done. |
noOpeningBalances | boolean | A brand-new business with nothing to bring forward, so the starting balances step is done. |
Responses
200 OK, application/json
Body: object (BooksGettingStarted).
The new business checklist, worked out from the business’s own data on every read.
The fields are as shown above.
Errors: 400 Bad request, 401 Unauthorised, 403 Forbidden, 429 Too many requests, as problem details (application/problem+json).