Skip to main content

Engagements

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

Start an engagement for a client

POST/api/v1/engagements

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

Creates the entity-aware section index and checklists (firm template, else built-in, plus the client’s own steps). Billable (engagement.started); AI tokens come from the plan’s monthly allowance, not from each start. 402 when billing blocks starting; 409 when the period overlaps one of the client’s existing engagements.

Needs the Preparer role or above. 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
NameInTypeDescription
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 (CreateEngagement).

Start an engagement for a client. The entity type defaults to the client’s.

Request body for POST /api/v1/engagements
FieldTypeDescription
clientIdrequiredstring (uuid)
entityTypestring (EntityType)

One of: LTD_FRS102_1A, LTD_FRS105_MICRO, LLP, SOLE_TRADER, INDIVIDUAL, PARTNERSHIP, TRUST, ESTATE, CHARITY_UNINCORPORATED, CHARITY_TRUST, CIO, SCIO, CHARITABLE_COMPANY

periodStartrequiredstring (date)

example "2026-03-31"

periodEndrequiredstring (date)

example "2026-03-31"

isFirstPeriodboolean

First period after incorporation (21-month Companies House deadline).

workflowTemplateIdstring

Workflow template id (a preset id until firm templates exist). Default by entity type.

preparerIdstring (uuid)nullable

Leave out to make the caller the preparer (when they are staff); null for nobody yet.

reviewerIdstring (uuid)
managerIdstring (uuid)
partnerIdstring (uuid)
riskstring (RiskLevel)

One of: standard, high

bringForwardobject (RollForwardOptions)

What to bring forward from the client’s previous engagement when it starts. Each part defaults to true. Set every part false to leave it as a deliberate step in the new file (POST /engagements/{id}/roll-forward).

bringForward.​priorYearFiguresboolean

Last year’s final TB (draft + posted journals) as this year’s comparatives, kept when this year’s TB is imported.

bringForward.​mappingsboolean

Last year’s account mappings (codes not yet mapped here).

bringForward.​fixedAssetsboolean

The fixed asset register: closing cost and depreciation as opening balances, disposed assets left out.

bringForward.​taxBroughtForwardboolean

Main and special rate pool WDVs and trading losses carried forward.

bringForward.​notesboolean

Last year’s variance notes, as hints on the lead schedules (never as this year’s explanations).

Responses

201 Created, application/json

Body: object (EngagementOverview).

201 Created response for POST /api/v1/engagements
FieldTypeDescription
idrequiredstring (uuid)
clientIdrequiredstring (uuid)
clientNamerequiredstring
entityTyperequiredstring (EntityType)

One of: LTD_FRS102_1A, LTD_FRS105_MICRO, LLP, SOLE_TRADER, INDIVIDUAL, PARTNERSHIP, TRUST, ESTATE, CHARITY_UNINCORPORATED, CHARITY_TRUST, CIO, SCIO, CHARITABLE_COMPANY

periodStartrequiredstring (date)

example "2026-03-31"

periodEndrequiredstring (date)

example "2026-03-31"

isFirstPeriodrequiredboolean
dueDaterequiredstring (date)

example "2026-03-31"

riskrequiredstring (RiskLevel)

One of: standard, high

teamrequiredobject (EngagementTeam)
team.​preparerIdrequiredstring (uuid)nullable
team.​reviewerIdrequiredstring (uuid)nullable
team.​managerIdrequiredstring (uuid)nullable
team.​partnerIdrequiredstring (uuid)nullable
thresholdsrequiredobject (Thresholds)

Movements at or above both thresholds need an explanation.

thresholds.​absolutePencerequiredinteger

Integer pence (GBP).

thresholds.​percentrequiredinteger

at least 0

workflowrequiredobject (EngagementWorkflow)
workflow.​templateIdrequiredstring
workflow.​templateNamerequiredstring
workflow.​statusrequiredstring (EngagementStatus)

One of: not_started, in_progress, submitted, returned, complete

workflow.​workflowStatusrequiredstring (WorkflowStatus)

One of: in_progress, submitted, returned, reopened, approved

workflow.​currentStageIdrequiredstring
workflow.​currentStageNamerequiredstring
workflow.​currentStageIndexrequiredinteger

at least 0

workflow.​stagesrequiredarray of WorkflowStage
workflow.​stages[].​idrequiredstring
workflow.​stages[].​namerequiredstring
workflow.​stages[].​staterequiredstring (TimelineStepState)

One of: done, now, todo

workflow.​stages[].​signedByrequiredstring (uuid)nullable
workflow.​stages[].​signedAtrequiredstring (date-time)nullable
workflow.​stages[].​assigneeIdrequiredstring (uuid)nullable

Who the engagement team assigns to this stage (preparer, reviewer, manager or partner), or null when nobody is.

workflow.​stages[].​sentBackByrequiredstring (uuid)nullable

While the workflow is returned: who sent it back from this stage.

workflow.​stages[].​sentBackAtrequiredstring (date-time)nullable

While the workflow is returned: when it was sent back from this stage.

workflow.​roundrequiredinteger

Amendment round (each return or reopen starts a new one).

at least 1

workflow.​returnCountrequiredinteger

at least 0

workflow.​reopenCountrequiredinteger

at least 0

workflow.​changedAfterApprovalrequiredboolean
workflow.​returnTargetsrequiredarray of string

Stages a return can go back to.

workflow.​actionsrequiredobject (EngagementActions)

The engagement-level actions, checked for the caller.

workflow.​actions.​submitrequiredobject (GuardResult)

Whether the caller can take an action now, and every reason not.

workflow.​actions.​submit.​allowedrequiredboolean
workflow.​actions.​submit.​reasonsrequiredarray of string
workflow.​actions.​submit.​codesrequiredarray of string

Machine-readable reason codes from @tolvi/workflow.

workflow.​actions.​approverequiredobject (GuardResult)

Whether the caller can take an action now, and every reason not.

workflow.​actions.​approve.​allowedrequiredboolean
workflow.​actions.​approve.​reasonsrequiredarray of string
workflow.​actions.​approve.​codesrequiredarray of string

Machine-readable reason codes from @tolvi/workflow.

workflow.​actions.​returnrequiredobject (GuardResult)

Whether the caller can take an action now, and every reason not.

workflow.​actions.​return.​allowedrequiredboolean
workflow.​actions.​return.​reasonsrequiredarray of string
workflow.​actions.​return.​codesrequiredarray of string

Machine-readable reason codes from @tolvi/workflow.

workflow.​actions.​reopenrequiredobject (GuardResult)

Whether the caller can take an action now, and every reason not.

workflow.​actions.​reopen.​allowedrequiredboolean
workflow.​actions.​reopen.​reasonsrequiredarray of string
workflow.​actions.​reopen.​codesrequiredarray of string

Machine-readable reason codes from @tolvi/workflow.

trialBalancerequiredobject (TbVersion)nullable
trialBalance.​idrequiredstring (uuid)
trialBalance.​versionrequiredinteger

at least 1

trialBalance.​sourceKindrequiredstring (TbSourceKind)

One of: csv, excel, api, manual

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

example "2026-03-31"

trialBalance.​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.

trialBalance.​hashrequiredstring

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

trialBalance.​accountCountrequiredinteger

at least 0

trialBalance.​cyTotalPencerequiredinteger

Integer pence (GBP).

Net of current year balances (nil when balanced).

trialBalance.​pyTotalPencerequiredinteger

Integer pence (GBP).

trialBalance.​balancedrequiredboolean
trialBalance.​removedJournalRefsrequiredarray of string
trialBalance.​createdByrequiredstring (uuid)nullable
trialBalance.​createdAtrequiredstring (date-time)
sectionsrequiredarray of SectionSummary
sections[].​coderequiredstring

example "C"

sections[].​namerequiredstring
sections[].​kindrequiredstring (SectionKind)

One of: plan, tb, lead, jnl, fs

sections[].​statusrequiredstring (SectionStatus)

One of: todo, progress, prepared, reviewed, changed

sections[].​issueCountrequiredinteger

at least 0

sections[].​openReviewPointsrequiredinteger

at least 0

sections[].​signOffsrequiredarray of SignOff
sections[].​signOffs[].​stageIdrequiredstring
sections[].​signOffs[].​stageNamerequiredstring
sections[].​signOffs[].​signAsrequiredstring (SignOffRole)

Who signs at this stage, for labels such as "Sign as reviewer".

One of: preparer, reviewer, manager, partner

sections[].​signOffs[].​userIdrequiredstring (uuid)nullable
sections[].​signOffs[].​atrequiredstring (date-time)nullable
sections[].​signOffs[].​currentrequiredboolean

Signed against the content as it is now.

sections[].​currentStageIdrequiredstringnullable

Stage the section is at.

openReviewPointsrequiredinteger

at least 0

unmappedAccountsrequiredinteger

Trial balance accounts not mapped to a lead schedule line (nil accounts are not counted). Figures from the final TB are incomplete while this is above 0.

at least 0

journalOnlyAccountsinteger

Accounts Tolvi added for journals (journal-only: the tax and disposal accounts). B lists them with the TB’s own accounts, so B shows trialBalance.accountCount plus these.

at least 0

finalTbAccountsinteger

Every account on the final TB (B): the TB version’s accounts, Tolvi’s journal-only accounts and accounts only in last year’s TB.

at least 0

nextSteprequiredobject (NextStep)

The first outstanding item and the one action that deals with it.

nextStep.​messagerequiredstring
nextStep.​actionrequiredstring (NextStepAction)

One of: import, map, journal, explain, reconcile, post_tax, post_deferred_tax, open_tax, fixed_assets, post_fixed_assets, checklist, sign, resign, answer_review_point, check_review_point, raise_review_point, open_section, submit, approve, reopen, wait, none, generate_file, start_next_year

nextStep.​labelrequiredstringnullable

Button label, e.g. "Post tax journal".

nextStep.​targetrequiredstringnullable

Section code, journal id, account code or review point id the action is about.

nextStep.​donerequiredboolean

Nothing left for anyone to do here.

nextStep.​morerequiredinteger

Further outstanding items after this one.

at least 0

Errors: 400 Bad request, 401 Unauthorised, 403 Forbidden, 409 Conflict, 422 Unprocessable content, 429 Too many requests, as problem details (application/problem+json).

Cancel an engagement

POST/api/v1/engagements/{id}/cancel

Scopes
engagements:write and engagements:read
Role
Manager or above

Only while nothing is signed off. Within 14 days of starting it is credited (not billed). The file stays readable; it leaves the Work queue.

Needs the Manager role or above. 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}/cancel
NameInTypeDescription
idrequiredpathstring (uuid)

Engagement id.

Responses

200 OK, application/json

Body: object (CancelResult).

200 OK response for POST /api/v1/engagements/{id}/cancel
FieldTypeDescription
cancelledrequiredboolean
creditedrequiredboolean

Cancelled within 14 days with no sign-offs: a billing credit was written.

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

Get an engagement overview

GET/api/v1/engagements/{id}

Scopes
engagements:read

Sections and statuses, workflow (with the actions checked for you), trial balance and your next step. 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}
NameInTypeDescription
idrequiredpathstring (uuid)

Engagement id.

Responses

200 OK, application/json

Body: object (EngagementOverview).

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 engagement’s sections and their statuses

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

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}/sections
NameInTypeDescription
idrequiredpathstring (uuid)

Engagement id.

Responses

200 OK, application/json

Body: array of SectionSummary.

200 OK response for GET /api/v1/engagements/{id}/sections
FieldTypeDescription
[].​coderequiredstring

example "C"

[].​namerequiredstring
[].​kindrequiredstring (SectionKind)

One of: plan, tb, lead, jnl, fs

[].​statusrequiredstring (SectionStatus)

One of: todo, progress, prepared, reviewed, changed

[].​issueCountrequiredinteger

at least 0

[].​openReviewPointsrequiredinteger

at least 0

[].​signOffsrequiredarray of SignOff
[].​signOffs[].​stageIdrequiredstring
[].​signOffs[].​stageNamerequiredstring
[].​signOffs[].​signAsrequiredstring (SignOffRole)

Who signs at this stage, for labels such as "Sign as reviewer".

One of: preparer, reviewer, manager, partner

[].​signOffs[].​userIdrequiredstring (uuid)nullable
[].​signOffs[].​atrequiredstring (date-time)nullable
[].​signOffs[].​currentrequiredboolean

Signed against the content as it is now.

[].​currentStageIdrequiredstringnullable

Stage the section is at.

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

Get a section: checklist, issues, sign-off, review points, evidence and next step

GET/api/v1/engagements/{id}/sections/{code}

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}/sections/{code}
NameInTypeDescription
idrequiredpathstring (uuid)

Engagement id.

coderequiredpathstring

Section code (W/P ref), e.g. C.

One of: A, B, C, D, E, F, G, H, I, J, K, L, M, T, X, Z

Responses

200 OK, application/json

Body: object (SectionDetail).

200 OK response for GET /api/v1/engagements/{id}/sections/{code}
FieldTypeDescription
coderequiredstring

example "C"

namerequiredstring
kindrequiredstring (SectionKind)

One of: plan, tb, lead, jnl, fs

statusrequiredstring (SectionStatus)

One of: todo, progress, prepared, reviewed, changed

issueCountrequiredinteger

at least 0

openReviewPointsrequiredinteger

at least 0

signOffsrequiredarray of SignOff
signOffs[].​stageIdrequiredstring
signOffs[].​stageNamerequiredstring
signOffs[].​signAsrequiredstring (SignOffRole)

Who signs at this stage, for labels such as "Sign as reviewer".

One of: preparer, reviewer, manager, partner

signOffs[].​userIdrequiredstring (uuid)nullable
signOffs[].​atrequiredstring (date-time)nullable
signOffs[].​currentrequiredboolean

Signed against the content as it is now.

currentStageIdrequiredstringnullable

Stage the section is at.

checklistrequiredarray of ChecklistItem
checklist[].​idrequiredstring (uuid)
checklist[].​positionrequiredinteger
checklist[].​textrequiredstring
checklist[].​originrequiredstring (ChecklistOrigin)

One of: builtin, firm, client

checklist[].​statusrequiredstring (ChecklistStatus)

"" is not yet done.

One of: , done, na

checklist[].​autorequiredboolean

Ticked by Tolvi from the data (a person’s own tick always wins).

checklist[].​noterequiredstring
checklist[].​doneByrequiredstring (uuid)nullable
checklist[].​doneAtrequiredstring (date-time)nullable
checklist[].​evidencerequiredarray of Evidence
checklist[].​evidence[].​idrequiredstring (uuid)
checklist[].​evidence[].​sectionCoderequiredstringnullable
checklist[].​evidence[].​checklistItemIdrequiredstring (uuid)nullable
checklist[].​evidence[].​reviewPointIdrequiredstring (uuid)nullable
checklist[].​evidence[].​reviewPointMessageIdrequiredstring (uuid)nullable
checklist[].​evidence[].​fileNamerequiredstring
checklist[].​evidence[].​contentTyperequiredstring
checklist[].​evidence[].​sizeBytesrequiredinteger

at least 0

checklist[].​evidence[].​statusrequiredstring (EvidenceStatus)

pending_upload until POST …/evidence/{evidenceId}/confirm checks the stored file; then pending_scan (malware scan) and available. Only available files can be downloaded or read by Tolvi AI. rejected: the file failed the checks or the scan found malware (see rejectedReason); it can never be downloaded.

One of: pending_upload, pending_scan, available, rejected

checklist[].​evidence[].​rejectedReasonrequiredstringnullable

Why a rejected file was rejected, e.g. "malware detected"; null otherwise.

checklist[].​evidence[].​uploadedByrequiredstring (uuid)nullable
checklist[].​evidence[].​createdAtrequiredstring (date-time)
issuesrequiredarray of Issue
issues[].​messagerequiredstring
issues[].​actionrequiredstring (IssueAction)

One of: import, map, journal, explain, reconcile, post_tax, post_deferred_tax, open_tax, fixed_assets, post_fixed_assets, checklist

issues[].​labelrequiredstring
issues[].​targetrequiredstringnullable
signOffrequiredobject (SectionSignOffPanel)
signOff.​stagesrequiredarray of SignOff

Every stage that applies to sections, with its live sign-off.

signOff.​stages[].​stageIdrequiredstring
signOff.​stages[].​stageNamerequiredstring
signOff.​stages[].​signAsrequiredstring (SignOffRole)

Who signs at this stage, for labels such as "Sign as reviewer".

One of: preparer, reviewer, manager, partner

signOff.​stages[].​userIdrequiredstring (uuid)nullable
signOff.​stages[].​atrequiredstring (date-time)nullable
signOff.​stages[].​currentrequiredboolean

Signed against the content as it is now.

signOff.​currentStageIdrequiredstring
signOff.​signrequiredobject (GuardResult)

Can the caller sign at the current stage now?

signOff.​sign.​allowedrequiredboolean
signOff.​sign.​reasonsrequiredarray of string
signOff.​sign.​codesrequiredarray of string

Machine-readable reason codes from @tolvi/workflow.

signOff.​ownSignOffStageIdrequiredstringnullable

Stage of the caller’s own live sign-off, which they can remove.

signOff.​signStageIdstringnullable

The stage signing now would record the caller’s sign-off at. Usually currentStageId; the first stage when the caller re-signs their own out-of-date preparer sign-off (the section is reopened first). Null when there is nothing to sign.

signOff.​unsignobject (GuardResult)

Can the caller remove their own sign-off now? Refused while the file is signed off at every stage.

signOff.​unsign.​allowedrequiredboolean
signOff.​unsign.​reasonsrequiredarray of string
signOff.​unsign.​codesrequiredarray of string

Machine-readable reason codes from @tolvi/workflow.

signOff.​unsignRemovesarray of SignOff

Removing the caller’s own sign-off removes these later sign-offs too (other people’s).

signOff.​unsignRemoves[].​stageIdrequiredstring
signOff.​unsignRemoves[].​stageNamerequiredstring
signOff.​unsignRemoves[].​signAsrequiredstring (SignOffRole)

Who signs at this stage, for labels such as "Sign as reviewer".

One of: preparer, reviewer, manager, partner

signOff.​unsignRemoves[].​userIdrequiredstring (uuid)nullable
signOff.​unsignRemoves[].​atrequiredstring (date-time)nullable
signOff.​unsignRemoves[].​currentrequiredboolean

Signed against the content as it is now.

signOff.​fingerprintrequiredstring

Content fingerprint now.

nextSteprequiredobject (NextStep)

The first outstanding item and the one action that deals with it.

nextStep.​messagerequiredstring
nextStep.​actionrequiredstring (NextStepAction)

One of: import, map, journal, explain, reconcile, post_tax, post_deferred_tax, open_tax, fixed_assets, post_fixed_assets, checklist, sign, resign, answer_review_point, check_review_point, raise_review_point, open_section, submit, approve, reopen, wait, none, generate_file, start_next_year

nextStep.​labelrequiredstringnullable

Button label, e.g. "Post tax journal".

nextStep.​targetrequiredstringnullable

Section code, journal id, account code or review point id the action is about.

nextStep.​donerequiredboolean

Nothing left for anyone to do here.

nextStep.​morerequiredinteger

Further outstanding items after this one.

at least 0

reviewPointsrequiredarray of ReviewPoint
reviewPoints[].​idrequiredstring (uuid)
reviewPoints[].​sectionCoderequiredstringnullable

Null for a point on the engagement as a whole.

reviewPoints[].​categoryrequiredstring (ReviewPointCategory)

One of: query, error, presentation, missing_evidence

reviewPoints[].​statusrequiredstring (ReviewPointStatus)

One of: open, answered, cleared, reopened

reviewPoints[].​raisedAtStageIdrequiredstring
reviewPoints[].​raisedInRoundrequiredinteger

at least 1

reviewPoints[].​raisedByrequiredstring (uuid)nullable
reviewPoints[].​raisedAtrequiredstring (date-time)
reviewPoints[].​clearedByrequiredstring (uuid)nullable
reviewPoints[].​clearedAtrequiredstring (date-time)nullable
reviewPoints[].​sourceMeetingIdstring (uuid)nullable

The meeting whose next step this point came from (Create follow-ups in Tolvi Meetings), if any.

reviewPoints[].​messagesrequiredarray of ReviewPointMessage
reviewPoints[].​messages[].​idrequiredstring (uuid)
reviewPoints[].​messages[].​kindrequiredstring (ReviewPointMessageKind)

One of: raise, comment, answer, clear, reopen

reviewPoints[].​messages[].​authorIdrequiredstring (uuid)nullable
reviewPoints[].​messages[].​bodyrequiredstring
reviewPoints[].​messages[].​mentionsrequiredarray of string (uuid)
reviewPoints[].​messages[].​atrequiredstring (date-time)
reviewPoints[].​messages[].​evidencerequiredarray of Evidence
reviewPoints[].​messages[].​evidence[].​idrequiredstring (uuid)
reviewPoints[].​messages[].​evidence[].​sectionCoderequiredstringnullable
reviewPoints[].​messages[].​evidence[].​checklistItemIdrequiredstring (uuid)nullable
reviewPoints[].​messages[].​evidence[].​reviewPointIdrequiredstring (uuid)nullable
reviewPoints[].​messages[].​evidence[].​reviewPointMessageIdrequiredstring (uuid)nullable
reviewPoints[].​messages[].​evidence[].​fileNamerequiredstring
reviewPoints[].​messages[].​evidence[].​contentTyperequiredstring
reviewPoints[].​messages[].​evidence[].​sizeBytesrequiredinteger

at least 0

reviewPoints[].​messages[].​evidence[].​statusrequiredstring (EvidenceStatus)

pending_upload until POST …/evidence/{evidenceId}/confirm checks the stored file; then pending_scan (malware scan) and available. Only available files can be downloaded or read by Tolvi AI. rejected: the file failed the checks or the scan found malware (see rejectedReason); it can never be downloaded.

One of: pending_upload, pending_scan, available, rejected

reviewPoints[].​messages[].​evidence[].​rejectedReasonrequiredstringnullable

Why a rejected file was rejected, e.g. "malware detected"; null otherwise.

reviewPoints[].​messages[].​evidence[].​uploadedByrequiredstring (uuid)nullable
reviewPoints[].​messages[].​evidence[].​createdAtrequiredstring (date-time)
evidencerequiredarray of Evidence
evidence[].​idrequiredstring (uuid)
evidence[].​sectionCoderequiredstringnullable
evidence[].​checklistItemIdrequiredstring (uuid)nullable
evidence[].​reviewPointIdrequiredstring (uuid)nullable
evidence[].​reviewPointMessageIdrequiredstring (uuid)nullable
evidence[].​fileNamerequiredstring
evidence[].​contentTyperequiredstring
evidence[].​sizeBytesrequiredinteger

at least 0

evidence[].​statusrequiredstring (EvidenceStatus)

pending_upload until POST …/evidence/{evidenceId}/confirm checks the stored file; then pending_scan (malware scan) and available. Only available files can be downloaded or read by Tolvi AI. rejected: the file failed the checks or the scan found malware (see rejectedReason); it can never be downloaded.

One of: pending_upload, pending_scan, available, rejected

evidence[].​rejectedReasonrequiredstringnullable

Why a rejected file was rejected, e.g. "malware detected"; null otherwise.

evidence[].​uploadedByrequiredstring (uuid)nullable
evidence[].​createdAtrequiredstring (date-time)

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

Get a lead schedule

GET/api/v1/engagements/{id}/sections/{code}/lead-schedule

Scopes
engagements:read

Accounts by line with prior year, draft, journals and final balances, movements, variance notes and tickmarks. 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}/sections/{code}/lead-schedule
NameInTypeDescription
idrequiredpathstring (uuid)

Engagement id.

coderequiredpathstring

Section code (W/P ref), e.g. C.

One of: A, B, C, D, E, F, G, H, I, J, K, L, M, T, X, Z

Responses

200 OK, application/json

Body: object (LeadSchedule).

200 OK response for GET /api/v1/engagements/{id}/sections/{code}/lead-schedule
FieldTypeDescription
sectionCoderequiredstring
sectionNamerequiredstring
thresholdsrequiredobject (Thresholds)

Movements at or above both thresholds need an explanation.

thresholds.​absolutePencerequiredinteger

Integer pence (GBP).

thresholds.​percentrequiredinteger

at least 0

linesrequiredarray of LeadLine
lines[].​lineIdrequiredstring (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[].​statementrequiredstring (Statement)

One of: BS, PL, EQ

lines[].​accountsrequiredarray of LeadAccount
lines[].​accounts[].​coderequiredstring
lines[].​accounts[].​namerequiredstring
lines[].​accounts[].​pyPencerequiredinteger

Integer pence (GBP).

lines[].​accounts[].​draftPencerequiredinteger

Integer pence (GBP).

Per the imported (draft) TB.

lines[].​accounts[].​adjustmentsPencerequiredinteger

Integer pence (GBP).

Posted journals.

lines[].​accounts[].​draftJournalsPencerequiredinteger

Integer pence (GBP).

Draft journals, not in the final figure.

lines[].​accounts[].​finalPencerequiredinteger

Integer pence (GBP).

lines[].​accounts[].​movementPencerequiredinteger

Integer pence (GBP).

lines[].​accounts[].​movementPctrequirednumbernullable

Movement as a percentage of last year, 1 dp; null when last year was nil.

lines[].​accounts[].​needsExplanationrequiredboolean
lines[].​accounts[].​noterequiredobject (VarianceNote)nullable
lines[].​accounts[].​note.​bodyrequiredstring
lines[].​accounts[].​note.​authorIdrequiredstring (uuid)nullable
lines[].​accounts[].​note.​updatedAtrequiredstring (date-time)
lines[].​accounts[].​note.​editablerequiredboolean

The caller wrote it, so can change it.

lines[].​accounts[].​lastYearNoterequiredstringnullable

Last year’s explanation, brought forward as a hint: it never counts as this year’s.

lines[].​accounts[].​tickmarkrequiredobject (TickmarkEntry)nullable
lines[].​accounts[].​tickmark.​markrequiredstring (Tickmark)

One of: ✓, ‹, ^, ✗

lines[].​accounts[].​tickmark.​labelrequiredstring
lines[].​accounts[].​tickmark.​authorIdrequiredstring (uuid)nullable
lines[].​accounts[].​tickmark.​updatedAtrequiredstring (date-time)
lines[].​accounts[].​tickmark.​editablerequiredboolean
lines[].​totalsrequiredobject (LeadTotals)
lines[].​totals.​pyPencerequiredinteger

Integer pence (GBP).

lines[].​totals.​draftPencerequiredinteger

Integer pence (GBP).

lines[].​totals.​adjustmentsPencerequiredinteger

Integer pence (GBP).

lines[].​totals.​finalPencerequiredinteger

Integer pence (GBP).

totalsrequiredobject (LeadTotals)
totals.​pyPencerequiredinteger

Integer pence (GBP).

totals.​draftPencerequiredinteger

Integer pence (GBP).

totals.​adjustmentsPencerequiredinteger

Integer pence (GBP).

totals.​finalPencerequiredinteger

Integer pence (GBP).

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

List a section’s reconciliations (F bank, H VAT, I payroll)

GET/api/v1/engagements/{id}/sections/{code}/reconciliations

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}/sections/{code}/reconciliations
NameInTypeDescription
idrequiredpathstring (uuid)

Engagement id.

coderequiredpathstring

Section code (W/P ref), e.g. C.

One of: A, B, C, D, E, F, G, H, I, J, K, L, M, T, X, Z

Responses

200 OK, application/json

Body: array of Reconciliation.

200 OK response for GET /api/v1/engagements/{id}/sections/{code}/reconciliations
FieldTypeDescription
[].​coderequiredstring
[].​namerequiredstring
[].​sectionCoderequiredstring
[].​kindrequiredstring (ReconciliationKind)

What the account is reconciled to: bank statement, VAT return, P32, pension schedule, CIS300, DLA or current account schedule, lender statement.

One of: bank, vat, paye, pension, cis, dla, loan

[].​titlerequiredstring
[].​sourceLabelrequiredstring
[].​sourcePencerequiredintegernullable

Integer pence (GBP).

Per the source document, in its own sign (e.g. VAT payable is positive).

[].​itemsrequiredarray of RecItem
[].​items[].​descriptionrequiredstring

up to 200 characters

[].​items[].​amountPencerequiredinteger

Integer pence (GBP).

[].​noterequiredstring
[].​tbPencerequiredinteger

Integer pence (GBP).

Final TB balance in the source document’s sign.

[].​expectedPencerequiredintegernullable

Integer pence (GBP).

[].​differencePencerequiredintegernullable

Integer pence (GBP).

[].​agreesrequiredboolean
[].​okrequiredboolean

Agrees, or the difference is explained in the note.

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

Get your next step on the engagement and each section

GET/api/v1/engagements/{id}/next-steps

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}/next-steps
NameInTypeDescription
idrequiredpathstring (uuid)

Engagement id.

Responses

200 OK, application/json

Body: object (NextSteps).

The engagement’s next step and each section’s, for the caller.

200 OK response for GET /api/v1/engagements/{id}/next-steps
FieldTypeDescription
engagementrequiredobject (NextStep)

The first outstanding item and the one action that deals with it.

engagement.​messagerequiredstring
engagement.​actionrequiredstring (NextStepAction)

One of: import, map, journal, explain, reconcile, post_tax, post_deferred_tax, open_tax, fixed_assets, post_fixed_assets, checklist, sign, resign, answer_review_point, check_review_point, raise_review_point, open_section, submit, approve, reopen, wait, none, generate_file, start_next_year

engagement.​labelrequiredstringnullable

Button label, e.g. "Post tax journal".

engagement.​targetrequiredstringnullable

Section code, journal id, account code or review point id the action is about.

engagement.​donerequiredboolean

Nothing left for anyone to do here.

engagement.​morerequiredinteger

Further outstanding items after this one.

at least 0

sectionsrequiredarray of SectionNextStep
sections[].​coderequiredstring
sections[].​namerequiredstring
sections[].​statusrequiredstring (SectionStatus)

One of: todo, progress, prepared, reviewed, changed

sections[].​nextSteprequiredobject (NextStep)

The first outstanding item and the one action that deals with it.

sections[].​nextStep.​messagerequiredstring
sections[].​nextStep.​actionrequiredstring (NextStepAction)

One of: import, map, journal, explain, reconcile, post_tax, post_deferred_tax, open_tax, fixed_assets, post_fixed_assets, checklist, sign, resign, answer_review_point, check_review_point, raise_review_point, open_section, submit, approve, reopen, wait, none, generate_file, start_next_year

sections[].​nextStep.​labelrequiredstringnullable

Button label, e.g. "Post tax journal".

sections[].​nextStep.​targetrequiredstringnullable

Section code, journal id, account code or review point id the action is about.

sections[].​nextStep.​donerequiredboolean

Nothing left for anyone to do here.

sections[].​nextStep.​morerequiredinteger

Further outstanding items after this one.

at least 0

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

Write or change a variance note

PUT/api/v1/engagements/{id}/accounts/{code}/note

Scopes
engagements:write and engagements:read

Only the note’s author can change it. 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}/accounts/{code}/note
NameInTypeDescription
idrequiredpathstring (uuid)

Engagement id.

coderequiredpathstring

Account code.

Request body

Required. application/json: object (SetVarianceNote).

Request body for PUT /api/v1/engagements/{id}/accounts/{code}/note
FieldTypeDescription
bodyrequiredstring

1 to 4000 characters

Responses

200 OK, application/json

Body: object (LeadSchedule).

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

Remove your variance note

DELETE/api/v1/engagements/{id}/accounts/{code}/note

Scopes
engagements:write and engagements:read

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

Parameters

Parameters for DELETE /api/v1/engagements/{id}/accounts/{code}/note
NameInTypeDescription
idrequiredpathstring (uuid)

Engagement id.

coderequiredpathstring

Account code.

Responses

200 OK, application/json

Body: object (LeadSchedule).

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 a tickmark

PUT/api/v1/engagements/{id}/accounts/{code}/tickmark

Scopes
engagements:write and engagements:read

Only the tickmark’s author can change it. 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}/accounts/{code}/tickmark
NameInTypeDescription
idrequiredpathstring (uuid)

Engagement id.

coderequiredpathstring

Account code.

Request body

Required. application/json: object (SetTickmark).

Request body for PUT /api/v1/engagements/{id}/accounts/{code}/tickmark
FieldTypeDescription
markrequiredstring (Tickmark)

One of: ✓, ‹, ^, ✗

Responses

200 OK, application/json

Body: object (LeadSchedule).

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

Remove your tickmark

DELETE/api/v1/engagements/{id}/accounts/{code}/tickmark

Scopes
engagements:write and engagements:read

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

Parameters

Parameters for DELETE /api/v1/engagements/{id}/accounts/{code}/tickmark
NameInTypeDescription
idrequiredpathstring (uuid)

Engagement id.

coderequiredpathstring

Account code.

Responses

200 OK, application/json

Body: object (LeadSchedule).

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 a reconciliation: source balance, reconciling items and note

PUT/api/v1/engagements/{id}/reconciliations/{code}

Scopes
engagements:write and engagements:read

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}/reconciliations/{code}
NameInTypeDescription
idrequiredpathstring (uuid)

Engagement id.

coderequiredpathstring

Account code of a bank, VAT or payroll control account.

Request body

Required. application/json: object (SetReconciliation).

Request body for PUT /api/v1/engagements/{id}/reconciliations/{code}
FieldTypeDescription
sourcePencerequiredintegernullable

Integer pence (GBP).

itemsrequiredarray of RecItem

up to 200 items

items[].​descriptionrequiredstring

up to 200 characters

items[].​amountPencerequiredinteger

Integer pence (GBP).

notestring

up to 4000 characters

Responses

200 OK, application/json

Body: object (Reconciliation).

200 OK response for PUT /api/v1/engagements/{id}/reconciliations/{code}
FieldTypeDescription
coderequiredstring
namerequiredstring
sectionCoderequiredstring
kindrequiredstring (ReconciliationKind)

What the account is reconciled to: bank statement, VAT return, P32, pension schedule, CIS300, DLA or current account schedule, lender statement.

One of: bank, vat, paye, pension, cis, dla, loan

titlerequiredstring
sourceLabelrequiredstring
sourcePencerequiredintegernullable

Integer pence (GBP).

Per the source document, in its own sign (e.g. VAT payable is positive).

itemsrequiredarray of RecItem
items[].​descriptionrequiredstring

up to 200 characters

items[].​amountPencerequiredinteger

Integer pence (GBP).

noterequiredstring
tbPencerequiredinteger

Integer pence (GBP).

Final TB balance in the source document’s sign.

expectedPencerequiredintegernullable

Integer pence (GBP).

differencePencerequiredintegernullable

Integer pence (GBP).

agreesrequiredboolean
okrequiredboolean

Agrees, or the difference is explained in the note.

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

Mark a checklist step done or N/A, or add a note

PATCH/api/v1/engagements/{id}/checklist/{itemId}

Scopes
engagements:write and engagements:read

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

Parameters

Parameters for PATCH /api/v1/engagements/{id}/checklist/{itemId}
NameInTypeDescription
idrequiredpathstring (uuid)

Engagement id.

itemIdrequiredpathstring (uuid)

Request body

Required. application/json: object (UpdateChecklistItem).

Request body for PATCH /api/v1/engagements/{id}/checklist/{itemId}
FieldTypeDescription
statusstring (ChecklistStatus)

"" is not yet done.

One of: , done, na

notestring

up to 4000 characters

Responses

200 OK, application/json

Body: object (SectionDetail).

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

Attach evidence

POST/api/v1/engagements/{id}/evidence

Scopes
engagements:write and engagements:read

Records the file and returns a short-lived presigned URL to PUT it to storage. 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}/evidence
NameInTypeDescription
idrequiredpathstring (uuid)

Engagement id.

Request body

Required. application/json: object (CreateEvidence).

Give a section (optionally a checklist step) or a review point. Accepted files: PDF (.pdf); images (.png, .jpg/.jpeg, .heic/.heif, .webp); Excel (.xlsx, .xls); Word (.docx, .doc); .csv; .txt; email (.eml, .msg). The extension decides the type: contentType must agree with it (or be application/octet-stream when unknown), and the upload headers returned carry the type to PUT with. The stored bytes are checked against the type when the upload is confirmed.

Request body for POST /api/v1/engagements/{id}/evidence
FieldTypeDescription
sectionCodestring
checklistItemIdstring (uuid)
reviewPointIdstring (uuid)
fileNamerequiredstring

1 to 200 characters

contentTyperequiredstring

up to 100 characters; example "application/pdf"

sizeBytesrequiredinteger

1 to 104857600

Responses

201 Created, application/json

Body: object (EvidenceUpload).

201 Created response for POST /api/v1/engagements/{id}/evidence
FieldTypeDescription
evidencerequiredobject (Evidence)
evidence.​idrequiredstring (uuid)
evidence.​sectionCoderequiredstringnullable
evidence.​checklistItemIdrequiredstring (uuid)nullable
evidence.​reviewPointIdrequiredstring (uuid)nullable
evidence.​reviewPointMessageIdrequiredstring (uuid)nullable
evidence.​fileNamerequiredstring
evidence.​contentTyperequiredstring
evidence.​sizeBytesrequiredinteger

at least 0

evidence.​statusrequiredstring (EvidenceStatus)

pending_upload until POST …/evidence/{evidenceId}/confirm checks the stored file; then pending_scan (malware scan) and available. Only available files can be downloaded or read by Tolvi AI. rejected: the file failed the checks or the scan found malware (see rejectedReason); it can never be downloaded.

One of: pending_upload, pending_scan, available, rejected

evidence.​rejectedReasonrequiredstringnullable

Why a rejected file was rejected, e.g. "malware detected"; null otherwise.

evidence.​uploadedByrequiredstring (uuid)nullable
evidence.​createdAtrequiredstring (date-time)
uploadrequiredobject (PresignedUpload)
upload.​urlrequiredstring (uri)
upload.​methodrequiredstring (PresignedMethod)

One of: PUT, GET

upload.​headersrequiredobject

Headers to send with the request.

upload.​expiresAtrequiredstring (date-time)

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

Confirm an evidence upload

POST/api/v1/engagements/{id}/evidence/{evidenceId}/confirm

Scopes
engagements:write and engagements:read

Call after the presigned PUT. Checks the stored file’s size, type and contents against what was declared, records its checksum (ETag) and starts the malware scan. Only confirmed, scanned files can be downloaded or read by Tolvi AI. 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}/evidence/{evidenceId}/confirm
NameInTypeDescription
idrequiredpathstring (uuid)

Engagement id.

evidenceIdrequiredpathstring (uuid)

Responses

200 OK, application/json

Body: object (Evidence).

200 OK response for POST /api/v1/engagements/{id}/evidence/{evidenceId}/confirm
FieldTypeDescription
idrequiredstring (uuid)
sectionCoderequiredstringnullable
checklistItemIdrequiredstring (uuid)nullable
reviewPointIdrequiredstring (uuid)nullable
reviewPointMessageIdrequiredstring (uuid)nullable
fileNamerequiredstring
contentTyperequiredstring
sizeBytesrequiredinteger

at least 0

statusrequiredstring (EvidenceStatus)

pending_upload until POST …/evidence/{evidenceId}/confirm checks the stored file; then pending_scan (malware scan) and available. Only available files can be downloaded or read by Tolvi AI. rejected: the file failed the checks or the scan found malware (see rejectedReason); it can never be downloaded.

One of: pending_upload, pending_scan, available, rejected

rejectedReasonrequiredstringnullable

Why a rejected file was rejected, e.g. "malware detected"; null otherwise.

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

Get an evidence file’s status

GET/api/v1/engagements/{id}/evidence/{evidenceId}

Scopes
engagements:read

For following an upload through the malware scan: pending_upload, pending_scan, available, or rejected with the reason. 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}/evidence/{evidenceId}
NameInTypeDescription
idrequiredpathstring (uuid)

Engagement id.

evidenceIdrequiredpathstring (uuid)

Responses

200 OK, application/json

Body: object (Evidence).

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

Remove evidence you attached

DELETE/api/v1/engagements/{id}/evidence/{evidenceId}

Scopes
engagements:write and engagements:read

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

Parameters

Parameters for DELETE /api/v1/engagements/{id}/evidence/{evidenceId}
NameInTypeDescription
idrequiredpathstring (uuid)

Engagement id.

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

Presign an evidence upload again

POST/api/v1/engagements/{id}/evidence/{evidenceId}/upload

Scopes
engagements:write and engagements:read

A fresh presigned PUT for a file that is still pending_upload (the first PUT failed or its link expired), for the same size and type. Only the person who attached it; 409 once the file has been uploaded. 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}/evidence/{evidenceId}/upload
NameInTypeDescription
idrequiredpathstring (uuid)

Engagement id.

evidenceIdrequiredpathstring (uuid)

Responses

200 OK, application/json

Body: object (EvidenceUpload).

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 a short-lived download URL for evidence

GET/api/v1/engagements/{id}/evidence/{evidenceId}/download

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}/evidence/{evidenceId}/download
NameInTypeDescription
idrequiredpathstring (uuid)

Engagement id.

evidenceIdrequiredpathstring (uuid)

Responses

200 OK, application/json

Body: object (PresignedUpload).

200 OK response for GET /api/v1/engagements/{id}/evidence/{evidenceId}/download
FieldTypeDescription
urlrequiredstring (uri)
methodrequiredstring (PresignedMethod)

One of: PUT, GET

headersrequiredobject

Headers to send with the request.

expiresAtrequiredstring (date-time)

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

Get what was brought forward from the prior year

GET/api/v1/engagements/{id}/roll-forward

Scopes
engagements:read

The year-end roll forward: the source engagement, what was brought forward (final TB as comparatives, mappings, fixed asset register, pools and losses, variance notes as hints), whether the prior year changed since (content fingerprint) and whether it can be rolled again. 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}/roll-forward
NameInTypeDescription
idrequiredpathstring (uuid)

Engagement id.

Responses

200 OK, application/json

Body: object (RollForward).

The year-end roll forward: what was brought forward from the prior year, and whether the prior year changed since.

200 OK response for GET /api/v1/engagements/{id}/roll-forward
FieldTypeDescription
rolledForwardrequiredboolean
sourcerequiredobject (RollForwardSource)nullable

The engagement brought forward from.

source.​engagementIdrequiredstring (uuid)nullable

Null once that engagement was deleted.

source.​periodStartrequiredstring (date)

example "2026-03-31"

source.​periodEndrequiredstring (date)

example "2026-03-31"

source.​statusrequiredstring (EngagementStatus)nullable

One of: not_started, in_progress, submitted, returned, complete

rolledAtrequiredstring (date-time)nullable
rolledByrequiredstring (uuid)nullable
optionsrequiredobject (RollForwardParts)

What was brought forward.

options.​priorYearFiguresrequiredboolean
options.​mappingsrequiredboolean
options.​fixedAssetsrequiredboolean
options.​taxBroughtForwardrequiredboolean
options.​notesrequiredboolean
summaryrequiredobject (RollForwardSummary)

What was brought forward; null for a part that was not.

summary.​priorYearFiguresrequiredobject (RolledPriorYearFigures)nullable
summary.​priorYearFigures.​accountsrequiredinteger

at least 0

summary.​priorYearFigures.​profitPencerequiredinteger

Integer pence (GBP).

Last year’s profit after tax per its final TB (a loss negative).

summary.​mappingsrequiredintegernullable

Mappings added.

summary.​notesrequiredintegernullable

Variance notes brought forward as hints.

summary.​fixedAssetsrequiredobject (RolledFixedAssets)nullable
summary.​fixedAssets.​classesrequiredinteger

at least 0

summary.​fixedAssets.​assetsrequiredinteger

at least 0

summary.​fixedAssets.​costPencerequiredinteger

Integer pence (GBP).

summary.​fixedAssets.​depreciationPencerequiredinteger

Integer pence (GBP).

summary.​fixedAssets.​nbvPencerequiredinteger

Integer pence (GBP).

summary.​taxrequiredobject (RolledTax)nullable
summary.​tax.​mainPoolPencerequiredinteger

Integer pence (GBP).

summary.​tax.​specialRatePoolPencerequiredinteger

Integer pence (GBP).

summary.​tax.​lossesPre2017Pencerequiredinteger

Integer pence (GBP).

summary.​tax.​lossesPost2017Pencerequiredinteger

Integer pence (GBP).

summary.​tax.​deferredTaxPencerequiredintegernullable

Integer pence (GBP).

Last year’s deferred tax provision per its computation (liability positive); null when it did not apply.

summary.​tax.​selfAssessmentrequiredobject (RolledSelfAssessment)nullable

Null for a company.

summary.​tax.​selfAssessment.​lossesPencerequiredinteger

Integer pence (GBP).

Trading losses carried forward (ITA 2007 s83).

summary.​tax.​selfAssessment.​overlapReliefPencerequiredinteger

Integer pence (GBP).

Overlap relief not yet used (nil after 2023/24, FA 2022 Sch 1).

summary.​tax.​selfAssessment.​transitionProfitPencerequiredinteger

Integer pence (GBP).

Transition profit still being spread.

summary.​tax.​selfAssessment.​partnersrequiredinteger

at least 0

summary.​warningsrequiredarray of string
priorChangedrequiredboolean

The prior year changed after it was brought forward (its content fingerprint differs): re-roll to take the change.

changedPartsrequiredarray of RollForwardPart

The parts that changed.

One of: priorYearFigures, mappings, fixedAssets, taxBroughtForward, notes

changesrequiredarray of string
availablerequiredobject (RollForwardSource)nullable

The engagement a (re-)roll would bring forward from now.

available.​engagementIdrequiredstring (uuid)nullable

Null once that engagement was deleted.

available.​periodStartrequiredstring (date)

example "2026-03-31"

available.​periodEndrequiredstring (date)

example "2026-03-31"

available.​statusrequiredstring (EngagementStatus)nullable

One of: not_started, in_progress, submitted, returned, complete

rerollrequiredobject (GuardResult)

Re-roll from prior year: only while the file is Not started or Preparing.

reroll.​allowedrequiredboolean
reroll.​reasonsrequiredarray of string
reroll.​codesrequiredarray of string

Machine-readable reason codes from @tolvi/workflow.

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

Re-roll from prior year

POST/api/v1/engagements/{id}/roll-forward

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

Brings forward again from the client’s previous engagement, replacing what an earlier roll forward brought (this year’s additions and disposals are kept). Only while the file is Not started or Preparing (409 otherwise); 422 when there is no earlier engagement. Never copies sign-offs, review points or evidence; sign-offs on changed sections go stale.

Needs the Preparer role or above. 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}/roll-forward
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

Optional. application/json: object (RollForwardOptions).

What to bring forward from the prior year. Each defaults to true.

Request body for POST /api/v1/engagements/{id}/roll-forward
FieldTypeDescription
priorYearFiguresboolean

Last year’s final TB (draft + posted journals) as this year’s comparatives, kept when this year’s TB is imported.

mappingsboolean

Last year’s account mappings (codes not yet mapped here).

fixedAssetsboolean

The fixed asset register: closing cost and depreciation as opening balances, disposed assets left out.

taxBroughtForwardboolean

Main and special rate pool WDVs and trading losses carried forward.

notesboolean

Last year’s variance notes, as hints on the lead schedules (never as this year’s explanations).

Responses

200 OK, application/json

Body: object (RollForward).

The year-end roll forward: what was brought forward from the prior year, and whether the prior year changed since.

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

Get where the trial balance would be pulled from

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

Scopes
engagements:read

The source a pull for this engagement reads, without reading it: an engagement keeps the source it is on (its Work queue software); a new one reads the client’s Tolvi Books when linked, else its OAuth connection. Switch an engagement’s source on the client’s Connection tab (PUT /clients/{clientId}/books-link/engagements). 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/pull
NameInTypeDescription
idrequiredpathstring (uuid)

Engagement id.

Responses

200 OK, application/json

Body: object (TbPullSource).

Which source a pull for this engagement reads: the client’s only source, or, when it has both an OAuth connection and a Tolvi Books link, the one a person chose. Until someone chooses, needsChoice is true and choices lists both: Tolvi asks rather than guessing.

200 OK response for GET /api/v1/engagements/{id}/tb/pull
FieldTypeDescription
engagementIdrequiredstring (uuid)
sourcerequiredstring (BooksSource)nullable

Null when the client has no connection and no Tolvi Books link.

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

labelrequiredstringnullable

example "Tolvi Books"

organisationNamerequiredstringnullable
availablerequiredboolean

A pull can be made now.

reasonrequiredstringnullable

Why not, in words, when it can’t.

needsChoicerequiredboolean

The client has both sources and nobody has chosen which its engagements use.

choicesrequiredarray of TbPullSourceChoice

The two to choose from when needsChoice; empty otherwise.

choices[].​userequiredstring (BooksSourcePick)

What to send as use to PUT /clients/{clientId}/books-link/source.

One of: tolvi_books, connection

choices[].​sourcerequiredstring (BooksSource)

Null when the client has no connection and no Tolvi Books link.

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

choices[].​labelrequiredstring

example "Tolvi Books"

choices[].​organisationNamerequiredstringnullable

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

Pull the trial balance from the bookkeeping software

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

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

Pulls again and adds a new immutable trial balance version, exactly as a CSV import would (mappings remembered, journals on missing accounts removed only with confirmJournalRemoval). Send the preview’s hash as expectedHash to refuse (409) if the books changed in between. 409 also when the connection needs reconnecting. 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/pull
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 (TbPullRequest).

Request body for POST /api/v1/engagements/{id}/tb/pull
FieldTypeDescription
expectedHashstring

The hash from the preview. If the books have changed since, nothing is imported (409) and you preview again.

confirmJournalRemovalboolean

Confirm removing the journals the preview listed.

reopenFileboolean

Required to pull into a file signed off at every stage: the import reopens it for re-approval (reviewer or above). See TbImport.reopenFile.

Responses

201 Created, application/json

Body: object (TbImportResult).

201 Created response for POST /api/v1/engagements/{id}/tb/pull
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).

Preview pulling the trial balance from the bookkeeping software

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

Scopes
engagements:write and engagements:read

Reads the TB at the period end (and at the prior period end for the prior year column) from the client’s connection, or from the client’s Tolvi Books through the firm’s practice link (both columns at one ledger point, already mapped by the books’ lead lines). Nothing is stored. Same shape as the CSV import preview, plus where it came from. 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/pull/preview
NameInTypeDescription
idrequiredpathstring (uuid)

Engagement id.

Responses

200 OK, application/json

Body: object (TbPullPreview).

200 OK response for POST /api/v1/engagements/{id}/tb/pull/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.

providerrequiredstring (BooksSource)

Where the trial balance was read: an OAuth provider, or tolvi_books (the client’s Tolvi Books, through the firm’s practice link).

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

sourceLabelrequiredstring

example "Tolvi Books"

organisationNamerequiredstring

The organisation (OAuth) or business (Tolvi Books) read.

booksThroughSeqrequiredintegernullable

Tolvi Books: the ledger point read (the last entry included). Null for other sources.

asAtrequiredstring (date)

The period end: the current year column.

example "2026-03-31"

priorAsAtrequiredstring (date)nullable

The prior period end: the prior year column (null for a first period).

example "2026-03-31"

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

Preview sending an engagement’s journals to the client’s Tolvi Books

POST/api/v1/engagements/{id}/books/post-back/preview

Scopes
review:write
Access
A signed-in Tolvi session only, never an API token.

For an engagement approved at every stage whose trial balance came from the client’s Tolvi Books: the year-end adjustments the books would get (and any earlier post-back reversed because its journal changed), the books’ trial balance at the period end before and after, which must equal the final trial balance to the penny, and the year-end lock it would set. problems says what stands in the way. Nothing is posted. Session only; reviewers and above. 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}/books/post-back/preview
NameInTypeDescription
idrequiredpathstring (uuid)

Engagement id.

Responses

200 OK, application/json

Body: object (PostBackPreview).

What sending an approved engagement’s posted journals to the client’s Tolvi Books would do: the entries, the books’ trial balance at the period end before and after (which must equal the final trial balance to the penny), and the year-end lock it sets. Nothing is posted.

200 OK response for POST /api/v1/engagements/{id}/books/post-back/preview
FieldTypeDescription
engagementIdrequiredstring (uuid)
businessIdrequiredstring (uuid)
businessNamerequiredstringnullable
periodEndrequiredstring (date)

example "2026-03-31"

readyrequiredboolean

Nothing stands in the way: post-back can go ahead.

problemsrequiredarray of string

What stands in the way, in words.

entriesrequiredarray of PostBackEntry
entries[].​actionrequiredstring (PostBackAction)

reverse: undoes an earlier post-back of a journal that has changed or gone.

One of: post, reverse

entries[].​journalRefrequiredstringnullable

example "J4"

entries[].​daterequiredstring (date)

example "2026-03-31"

entries[].​descriptionrequiredstring
entries[].​dateProblemrequiredstringnullable

Why the books would refuse this date (a lock), or null.

entries[].​linesrequiredarray of PostBackLine
entries[].​lines[].​accountCoderequiredstring
entries[].​lines[].​accountNamerequiredstringnullable
entries[].​lines[].​amountPencerequiredinteger

Debit positive, in pence.

unchangedrequiredinteger

Journals the books already hold exactly, from an earlier post-back.

at least 0

missingAccountsrequiredarray of PostBackMissingAccount

Accounts the journals use that the books don’t have (add them in the client’s chart first; nothing is created silently).

missingAccounts[].​coderequiredstring
missingAccounts[].​namerequiredstring
balancesrequiredarray of PostBackBalance
balances[].​coderequiredstring
balances[].​namerequiredstring
balances[].​booksBeforePencerequiredinteger

Integer pence (GBP).

The books at the period end now, debit positive.

balances[].​booksAfterPencerequiredinteger

Integer pence (GBP).

The books at the period end after post-back.

balances[].​finalPencerequiredinteger

Integer pence (GBP).

The engagement’s final balance (draft TB plus posted journals).

balances[].​differencePencerequiredinteger

booksAfterPence less finalPence: nil on every account before post-back can go ahead.

agreesrequiredboolean

After post-back the books agree to the final trial balance on every account.

lockedThroughrequiredstring (date)nullable

The year-end (accountant) lock in force now.

example "2026-03-31"

lockThroughrequiredstring (date)

Post-back locks the books to this date (the period end), unless already locked to it or later.

example "2026-03-31"

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

Send an engagement’s journals to the client’s Tolvi Books and lock the year

POST/api/v1/engagements/{id}/books/post-back

Scopes
review:write
Access
A signed-in Tolvi session only, never an API token.
Retries
Send an Idempotency-Key to make retries safe.

Posts the preview’s entries to the client’s books as year-end adjustments, through the firm’s practice link (year-end or full bookkeeping access), and locks the books to the period end, in one transaction. 409 with the reasons when the preview isn’t ready (not approved, the TB didn’t come from these books, missing accounts, the books wouldn’t agree, a lock). Safe to repeat: journals the books already hold are not posted again. Never creates a trial balance version. Session only; reviewers and above; not available through the MCP server. 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}/books/post-back
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

Responses

201 Created, application/json

Body: object (PostBackResult).

201 Created response for POST /api/v1/engagements/{id}/books/post-back
FieldTypeDescription
engagementIdrequiredstring (uuid)
postedrequiredinteger

at least 0

reversedrequiredinteger

at least 0

unchangedrequiredinteger

at least 0

entrySeqsrequiredarray of number

The ledger entries made, in order.

lockedThroughrequiredstring (date)

example "2026-03-31"

lockedNowrequiredboolean

This call set the lock (false when it was already in place).

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