Skip to main content

Trial balance

6 operations in the Tolvi API, version 1. Paths are relative to https://api.tolvi.co.uk. Every amount is integer pence.

Preview a trial balance import

POST/api/v1/engagements/{id}/tb/preview

Scopes
engagements:write and engagements:read

Nothing is stored. Shows the header row and columns read (layout; send columns to choose them yourself), whether it balances, new and removed codes, the journals a re-import would remove and the sign-offs it would put out of date. Part of the working_papers product: the firm must have it and you must have access to it.

Parameters

Parameters for POST /api/v1/engagements/{id}/tb/preview
NameInTypeDescription
idrequiredpathstring (uuid)

Engagement id.

Request body

Required. application/json: object (TbImport).

A CSV export (format: csv, content), one worksheet of a workbook (format: sheet, sheet) or structured accounts (format: json, accounts).

Request body for POST /api/v1/engagements/{id}/tb/preview
FieldTypeDescription
formatrequiredstring (TbImportFormat)

One of: csv, sheet, json

contentstring

up to 2000000 characters

sheetobject (TbSheet)

One worksheet read from a workbook (.xlsx/.xls) by the caller, e.g. SheetJS sheet_to_json(ws, { header: 1, raw: true }). Dates as YYYY-MM-DD strings.

sheet.​namestring

Worksheet name, used as the source label when there is no file name.

up to 100 characters

sheet.​firstRowinteger

Spreadsheet row number of rows[0], for messages. Default 1.

at least 1

sheet.​rowsrequiredarray of array of one of: string, number, boolean, null

The worksheet’s cells, row by row.

up to 20000 items

accountsarray of TbAccountInput

up to 20000 items

accounts[].​coderequiredstring

up to 50 characters

accounts[].​namerequiredstring

up to 200 characters

accounts[].​cyPencerequiredinteger

Integer pence (GBP).

accounts[].​pyPenceinteger

Integer pence (GBP).

accounts[].​typestring (AccountType)

One of: asset, liability, equity, revenue, expense

asAtstring (date)

Overrides any date in the file.

example "2026-03-31"

sourceLabelstring

File name, shown in the version list.

up to 200 characters

providerstring (TbProvider)

One of: xero, quickbooks, sage, freeagent, tolvi_books

confirmJournalRemovalboolean

Required when the import removes journals (see the preview).

reopenFileboolean

Required to import into a file signed off at every stage (the preview’s importLock says so): the import reopens the file for re-approval, as POST …/workflow/reopen, in the same transaction. Only a reviewer or above (review:write) can reopen; 409 without it, 403 for anyone else.

columnsobject (TbColumns)

csv and sheet only: read these columns instead of detecting them. The preview’s layout shows what was detected.

columns.​headerRowrequiredintegernullable

1 to 1000000

columns.​codeinteger

0 to 49

columns.​nameinteger

0 to 49

columns.​typeinteger

Account type (asset, liability…), when the file has one.

0 to 49

columns.​debitinteger

0 to 49

columns.​creditinteger

0 to 49

columns.​balanceinteger

0 to 49

columns.​pyDebitinteger

0 to 49

columns.​pyCreditinteger

0 to 49

columns.​pyBalanceinteger

0 to 49

Responses

200 OK, application/json

Body: object (TbImportPreview).

What an import would do. Nothing is stored.

200 OK response for POST /api/v1/engagements/{id}/tb/preview
FieldTypeDescription
accountCountrequiredinteger
addedCodesrequiredarray of string
removedCodesrequiredarray of string
changedCountrequiredinteger

Accounts whose balances differ from the current version.

cyTotalPencerequiredinteger

Integer pence (GBP).

balancedrequiredboolean
hashrequiredstring
sameAsCurrentrequiredboolean

Identical to the current version (an import would be refused).

journalsToRemoverequiredarray of JournalRef

Journals whose accounts are not in the new TB: confirm before they are removed.

journalsToRemove[].​idrequiredstring (uuid)
journalsToRemove[].​refrequiredstring
journalsToRemove[].​statusrequiredstring (JournalStatus)

One of: draft, posted

unmappedCountrequiredinteger

Accounts nothing could map.

debitTotalPencerequiredinteger

Current year debit balances added up, in integer pence.

creditTotalPencerequiredinteger

Current year credit balances added up, in integer pence (negative).

accountsrequiredarray of TbPreviewAccount

The accounts as read, in file order.

accounts[].​coderequiredstring
accounts[].​namerequiredstring
accounts[].​cyPencerequiredinteger

Current year balance in integer pence: debits positive, credits negative.

accounts[].​pyPencerequiredinteger

Prior year balance in integer pence: debits positive, credits negative.

accounts[].​lineIdrequiredstring (LeadLineId)nullable

The mapping already held for this code, else the one found automatically; null when it needs mapping.

One of: C.cost, C.dep, D.stk, E.td, E.pre, F.bank, G.tc, G.acc, H.vat, I.paye, J.dla, J.loanst, J.loan, K.cap, K.res, K.div, L.sales, L.intrec, M.cos, M.adm, M.dis, M.dep, M.int, M.disp, T.chg, T.liab, T.dtc, P.dt, J.cap, J.draw

warningsrequiredarray of TbWarning
warnings[].​coderequiredstring
warnings[].​messagerequiredstring
layoutrequiredobject (TbColumns)nullable

The header row and columns read (detected, or as given in columns). Null for structured accounts.

layout.​headerRowrequiredintegernullable

1 to 1000000

layout.​codeinteger

0 to 49

layout.​nameinteger

0 to 49

layout.​typeinteger

Account type (asset, liability…), when the file has one.

0 to 49

layout.​debitinteger

0 to 49

layout.​creditinteger

0 to 49

layout.​balanceinteger

0 to 49

layout.​pyDebitinteger

0 to 49

layout.​pyCreditinteger

0 to 49

layout.​pyBalanceinteger

0 to 49

staleSignOffsrequiredarray of TbStaleSignOff

Sections whose current sign-offs this import would put out of date.

staleSignOffs[].​sectionCoderequiredstring
staleSignOffs[].​sectionNamerequiredstring
staleSignOffs[].​stagesrequiredarray of string

The stages whose sign-off would go out of date, e.g. "Preparer", "Reviewer".

importLockobject (TbImportLock)nullable

Set when the file is signed off at every stage: the import is refused unless it reopens the file.

importLock.​coderequiredstring (TbImportLockCode)

One of: file_signed_off, reopen_not_permitted

importLock.​reasonrequiredstring

In plain words, for the import screen.

importLock.​canReopenrequiredboolean

The caller can import anyway by reopening the file (send reopenFile: true). False for a preparer: a reviewer or above reopens it first.

Errors: 400 Bad request, 401 Unauthorised, 403 Forbidden, 404 Not found, 429 Too many requests, as problem details (application/problem+json).

List trial balance versions, newest first

GET/api/v1/engagements/{id}/tb/versions

Scopes
engagements:read

Part of the working_papers product: the firm must have it and you must have access to it.

Parameters

Parameters for GET /api/v1/engagements/{id}/tb/versions
NameInTypeDescription
idrequiredpathstring (uuid)

Engagement id.

Responses

200 OK, application/json

Body: array of TbVersion.

200 OK response for GET /api/v1/engagements/{id}/tb/versions
FieldTypeDescription
[].​idrequiredstring (uuid)
[].​versionrequiredinteger

at least 1

[].​sourceKindrequiredstring (TbSourceKind)

One of: csv, excel, api, manual

[].​sourceLabelrequiredstringnullable
[].​providerrequiredstringnullable
[].​asAtrequiredstring (date)nullable

example "2026-03-31"

[].​booksThroughSeqrequiredintegernullable

Pulled from Tolvi Books: the ledger point it was read at (the last entry included), so the same trial balance can be recomputed and later entries found exactly. Null for any other source.

[].​hashrequiredstring

Content hash (sha256): the same balances give the same hash.

[].​accountCountrequiredinteger

at least 0

[].​cyTotalPencerequiredinteger

Integer pence (GBP).

Net of current year balances (nil when balanced).

[].​pyTotalPencerequiredinteger

Integer pence (GBP).

[].​balancedrequiredboolean
[].​removedJournalRefsrequiredarray of string
[].​createdByrequiredstring (uuid)nullable
[].​createdAtrequiredstring (date-time)

Errors: 400 Bad request, 401 Unauthorised, 403 Forbidden, 404 Not found, 429 Too many requests, as problem details (application/problem+json).

Import a trial balance (CSV or JSON)

POST/api/v1/engagements/{id}/tb/versions

Scopes
engagements:write and engagements:read
Retries
Send an Idempotency-Key to make retries safe.

Adds an immutable version in pence. If journals would be removed, send confirmJournalRemoval: true after showing the preview (409 otherwise). A file signed off at every stage takes a new trial balance only with reopenFile: true, which reopens it for re-approval in the same transaction: 409 without it, 403 for anyone who cannot reopen a file (a reviewer or above does). The preview’s importLock and GET …/mappings say so first. Part of the working_papers product: the firm must have it and you must have access to it.

Parameters

Parameters for POST /api/v1/engagements/{id}/tb/versions
NameInTypeDescription
idrequiredpathstring (uuid)

Engagement id.

Idempotency-Keyheaderstring

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 (TbImport).

A CSV export (format: csv, content), one worksheet of a workbook (format: sheet, sheet) or structured accounts (format: json, accounts).

The fields are as shown above.

Responses

201 Created, application/json

Body: object (TbImportResult).

201 Created response for POST /api/v1/engagements/{id}/tb/versions
FieldTypeDescription
versionrequiredobject (TbVersion)
version.​idrequiredstring (uuid)
version.​versionrequiredinteger

at least 1

version.​sourceKindrequiredstring (TbSourceKind)

One of: csv, excel, api, manual

version.​sourceLabelrequiredstringnullable
version.​providerrequiredstringnullable
version.​asAtrequiredstring (date)nullable

example "2026-03-31"

version.​booksThroughSeqrequiredintegernullable

Pulled from Tolvi Books: the ledger point it was read at (the last entry included), so the same trial balance can be recomputed and later entries found exactly. Null for any other source.

version.​hashrequiredstring

Content hash (sha256): the same balances give the same hash.

version.​accountCountrequiredinteger

at least 0

version.​cyTotalPencerequiredinteger

Integer pence (GBP).

Net of current year balances (nil when balanced).

version.​pyTotalPencerequiredinteger

Integer pence (GBP).

version.​balancedrequiredboolean
version.​removedJournalRefsrequiredarray of string
version.​createdByrequiredstring (uuid)nullable
version.​createdAtrequiredstring (date-time)
removedJournalRefsrequiredarray of string
warningsrequiredarray of TbWarning
warnings[].​coderequiredstring
warnings[].​messagerequiredstring
unmappedCountrequiredinteger

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).

Get the final trial balance

GET/api/v1/engagements/{id}/tb

Scopes
engagements:read

Current version + posted journals, derived on every request and never stored. Part of the working_papers product: the firm must have it and you must have access to it.

Parameters

Parameters for GET /api/v1/engagements/{id}/tb
NameInTypeDescription
idrequiredpathstring (uuid)

Engagement id.

Responses

200 OK, application/json

Body: object (FinalTrialBalance).

Draft TB + posted journals, derived on every request (never stored).

200 OK response for GET /api/v1/engagements/{id}/tb
FieldTypeDescription
versionrequiredobject (TbVersion)nullable
version.​idrequiredstring (uuid)
version.​versionrequiredinteger

at least 1

version.​sourceKindrequiredstring (TbSourceKind)

One of: csv, excel, api, manual

version.​sourceLabelrequiredstringnullable
version.​providerrequiredstringnullable
version.​asAtrequiredstring (date)nullable

example "2026-03-31"

version.​booksThroughSeqrequiredintegernullable

Pulled from Tolvi Books: the ledger point it was read at (the last entry included), so the same trial balance can be recomputed and later entries found exactly. Null for any other source.

version.​hashrequiredstring

Content hash (sha256): the same balances give the same hash.

version.​accountCountrequiredinteger

at least 0

version.​cyTotalPencerequiredinteger

Integer pence (GBP).

Net of current year balances (nil when balanced).

version.​pyTotalPencerequiredinteger

Integer pence (GBP).

version.​balancedrequiredboolean
version.​removedJournalRefsrequiredarray of string
version.​createdByrequiredstring (uuid)nullable
version.​createdAtrequiredstring (date-time)
accountsrequiredarray of FinalTbAccount
accounts[].​coderequiredstring
accounts[].​namerequiredstring
accounts[].​journalOnlyboolean

Added in Tolvi for journals (journal-only): in no TB version, so draft and prior year are nil and the final balance is journals only.

accounts[].​chartOnlyboolean

An account on the client’s chart of accounts with no balance in this TB, used here by C or a journal: shown under the client’s own code, with nil draft and prior year, so it matches their books once they post it.

accounts[].​lineIdrequiredstring (LeadLineId)nullable

One of: C.cost, C.dep, D.stk, E.td, E.pre, F.bank, G.tc, G.acc, H.vat, I.paye, J.dla, J.loanst, J.loan, K.cap, K.res, K.div, L.sales, L.intrec, M.cos, M.adm, M.dis, M.dep, M.int, M.disp, T.chg, T.liab, T.dtc, P.dt, J.cap, J.draw

accounts[].​lineLabelrequiredstringnullable
accounts[].​sectionCoderequiredstringnullable
accounts[].​pyPencerequiredinteger

Integer pence (GBP).

accounts[].​draftPencerequiredinteger

Integer pence (GBP).

accounts[].​adjustmentsPencerequiredinteger

Integer pence (GBP).

accounts[].​draftJournalsPencerequiredinteger

Integer pence (GBP).

accounts[].​finalPencerequiredinteger

Integer pence (GBP).

accounts[].​needsExplanationrequiredboolean

Final against prior year moved by at least both of the year-end file’s review thresholds: the same test as a lead schedule line. T’s accounts are explained by the tax computation, so never.

draftTotalPencerequiredinteger

Integer pence (GBP).

finalTotalPencerequiredinteger

Integer pence (GBP).

pyTotalPencerequiredinteger

Integer pence (GBP).

balancedrequiredboolean

Errors: 400 Bad request, 401 Unauthorised, 403 Forbidden, 404 Not found, 429 Too many requests, as problem details (application/problem+json).

Get account mappings

GET/api/v1/engagements/{id}/mappings

Scopes
engagements:read

Each account’s lead schedule line and why (client memory, firm rule or built-in). Part of the working_papers product: the firm must have it and you must have access to it.

Parameters

Parameters for GET /api/v1/engagements/{id}/mappings
NameInTypeDescription
idrequiredpathstring (uuid)

Engagement id.

Responses

200 OK, application/json

Body: object (Mappings).

200 OK response for GET /api/v1/engagements/{id}/mappings
FieldTypeDescription
accountsrequiredarray of AccountMapping
accounts[].​coderequiredstring
accounts[].​namerequiredstring
accounts[].​lineIdrequiredstring (LeadLineId)nullable

One of: C.cost, C.dep, D.stk, E.td, E.pre, F.bank, G.tc, G.acc, H.vat, I.paye, J.dla, J.loanst, J.loan, K.cap, K.res, K.div, L.sales, L.intrec, M.cos, M.adm, M.dis, M.dep, M.int, M.disp, T.chg, T.liab, T.dtc, P.dt, J.cap, J.draw

accounts[].​sourcerequiredstring (MappingSource)nullable

chart: an account on the client’s chart of accounts with no balance in this TB, put on the line its use in C implies or the mapping order suggested. books: the account’s lead schedule line in the client’s Tolvi Books.

One of: client, firm, books, builtin, manual, chart

accounts[].​explanationrequiredstring
accounts[].​allowedrequiredboolean

The line can be used for this entity type.

linesrequiredarray of MappingLine
lines[].​idrequiredstring (LeadLineId)

One of: C.cost, C.dep, D.stk, E.td, E.pre, F.bank, G.tc, G.acc, H.vat, I.paye, J.dla, J.loanst, J.loan, K.cap, K.res, K.div, L.sales, L.intrec, M.cos, M.adm, M.dis, M.dep, M.int, M.disp, T.chg, T.liab, T.dtc, P.dt, J.cap, J.draw

lines[].​labelrequiredstring
lines[].​sectionCoderequiredstring
lines[].​allowedrequiredboolean
unmappedCountrequiredinteger
lockedReasonstringnullable

Why the caller cannot change mappings now (B reviewed): ask the reviewer to reopen it.

importLockobject (TbImportLock)nullable

Set when a new trial balance cannot simply be imported: the file is signed off at every stage. B’s import panel says so before anyone starts.

importLock.​coderequiredstring (TbImportLockCode)

One of: file_signed_off, reopen_not_permitted

importLock.​reasonrequiredstring

In plain words, for the import screen.

importLock.​canReopenrequiredboolean

The caller can import anyway by reopening the file (send reopenFile: true). False for a preparer: a reviewer or above reopens it first.

Errors: 400 Bad request, 401 Unauthorised, 403 Forbidden, 404 Not found, 429 Too many requests, as problem details (application/problem+json).

Set account mappings

PUT/api/v1/engagements/{id}/mappings

Scopes
engagements:write and engagements:read

Remembered for the client’s future engagements unless remember is false. Once B’s review sign-off is current, only a reviewer or above can change mappings (403 with the reason, as for T and C); lockedReason on GET says so first. Part of the working_papers product: the firm must have it and you must have access to it.

Parameters

Parameters for PUT /api/v1/engagements/{id}/mappings
NameInTypeDescription
idrequiredpathstring (uuid)

Engagement id.

Request body

Required. application/json: object (SetMappings).

Request body for PUT /api/v1/engagements/{id}/mappings
FieldTypeDescription
mappingsrequiredarray of MappingChange

1 to 5000 items

mappings[].​coderequiredstring
mappings[].​lineIdrequiredstring (LeadLineId)nullable

Null to unmap.

One of: C.cost, C.dep, D.stk, E.td, E.pre, F.bank, G.tc, G.acc, H.vat, I.paye, J.dla, J.loanst, J.loan, K.cap, K.res, K.div, L.sales, L.intrec, M.cos, M.adm, M.dis, M.dep, M.int, M.disp, T.chg, T.liab, T.dtc, P.dt, J.cap, J.draw

rememberboolean

Remember for this client’s future engagements (client memory). Default true.

Responses

200 OK, application/json

Body: object (Mappings).

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).