Accounting Administration
Build tax, opening-balance, and books-closing workflows
Mental Model
Administrative accounting writes configure tax, establish opening positions, or move the first open accounting date. Their consequences span more data than a normal row edit.
Accounts and Assignments
An account's category and classification determine its reporting position.
Use the category IDs returned by GET /accounts/categories; matching display
names do not establish category identity. A ledger account can move between
categories in the same classification. This updates report grouping without
rewriting its historical journal entries.
When a team moves between regions, category matching ignores surrounding name
whitespace and requires the same classification. Existing clean category names
take precedence over whitespace aliases in the destination.
System assignments determine its operational role, such as accounts
receivable, deferred revenue, accounts payable, payout distribution, opening
balance, or the due-to/from-trust bridge.
Assignments are unique within a team: one assignment cannot be active on two
accounts. Create or update the account with the complete intended
assignments array and handle a duplicate assignment as a configuration
conflict. The payout_bankAccount assignment requires a bank account. The
openingBalance assignment requires an active ledger or bank account whose
classification is asset or liability, or whose category is equity.
An account with type=nonPosting is a reference account. Use it for external
values that formulas or source detail need to retain without affecting the live
general ledger. Do not use a reference account for cash, a system balancing
role, or an opening position that must contribute to reports.
Resources and Lifecycle
Tax rates remain renderable on historical fees and transactions after they
become inactive. Opening balances are separate resources, one per accounting
purpose. booksClosedAt is the first open date; earlier affected journal
dates are closed.
Explicit opening balances carry the position immediately before the first live
GL date and remain active even though their journal date precedes
statementStartAt. Changing statementStartAt reclassifies other unlocked
journals around that boundary while preserving active opening balances.
Reapplying the current date does not reclassify other journals; it only
restores explicit opening balances made inactive solely by the GL boundary.
The first owner statement then includes those listing positions in Balance
start.
Trust Opening Positions
Trust go-live is not one plug amount. Record each known position through its dedicated operation so attribution survives into reconciliation and statements:
| Position | API workflow |
|---|---|
| Listing or owner balance | Listing opening balance |
| Guest or channel amount still owed | Accounts receivable |
| Cash received for future recognition | Advance deposits and deferred revenue |
| Amount owed to owners or manager | Accounts payable by party |
| Tax already collected and still payable | Tax payable |
| Remaining trial-balance account position | Opening trial balance |
The API names the reservation-level advance-deposit resource
advanced-deposits. Each non-zero row must identify a reservation and have
listing context. Use the synced payment/refund candidates response as discovery,
then submit only the position that exists at go-live. The mutation replaces the
purpose-specific opening transaction and returns the selected account.
Do not force trust cash to zero with an unrelated journal. After recording the
known asset and liability positions, inspect Trust Reconciliation. A remaining
surplus or deficit is the difference between recorded trust assets and trust
liabilities. Investigate missing cash, guest advances, owner balances, tax, and
payables before changing the account assigned as openingBalance.
Read Model
Render current tax-rate status and usage, dedicated opening-balance responses,
team booksClosedAt, operation issues, and affected-resource results. Each
opening-balance type has its own operation and schema; use them as-is.
Advanced-deposit updates preserve the submitted opening-balance account and
return that account in the mutation response and subsequent reads.
Concurrent writes to the same existing opening balance are serialized before
its transaction lines are replaced. Ownership relinking uses the same journal
lock order, so concurrent saves do not deadlock; if both succeed, the later
opening-balance write wins. If a competing replacement cannot acquire the lock
in time, the API returns 409 CONFLICT; re-read the current balance before
offering a retry.
The trial-balance classification filter accepts a case-insensitive,
comma-separated list of asset, liability, revenue, and expense.
Unsupported values return HTTP 400 before the report query runs. The JSON and
CSV endpoints use the same filter contract.
Decision Table
Tax and Opening Balances
| Workflow | Client rule |
|---|---|
| Tax-rate removal | Archive only when returned contract supports it |
| Opening trial balance | Use dedicated account and balancing contract |
| A/P, A/R, deferred, deposits, tax | Use each dedicated operation |
| Reference-only source amount | Use type=nonPosting; exclude from live totals |
| Trust surplus or deficit | Reconcile known assets and liabilities; do not post a plug |
| Listing or bank initialization | Keep its own identity and posting rules |
| Clear listing balance | Zero may cross statement period; attachments and books still block |
| Listing balance after historical import | Before stored live activity; normal locks apply |
| Close books | Set boundary; explain first-open-date semantics; confirm |
| Reopen all dates | Send booksClosedAt=null through normal operation |
x-ignore-books-closed-at | Never expose as a normal product control |
Editability
Tax usage and historical journals can prevent deletion. Opening balances and
books closing must respect statement attachments and other locks even when the
x-ignore-books-closed-at header is available for controlled repair workflows.
An existing listing opening balance can be corrected to exactly zero when only
the listing's statement-period boundary locks it. A non-zero edit can cross the
boundary only when every stored statement for the listing is an imported
snapshot ending at or before statementStartAt. Books closing, journal entries
directly attached to a statement, and stored live statements still reject the
write.
Books Closing
A business entity can have several journal dates. Compare the affected posting date, not just its top-level transaction or reservation date.
booksClosedAt is inclusive as the first open date. For example,
booksClosedAt=2026-07-01 locks journal dates through 2026-06-30 while leaving
2026-07-01 open. This differs from a user-facing "closed through" date. Store
and send the first open date exactly.
After a successful books-closing update, the new boundary applies immediately to subsequent writes and previews. Clients do not need to refresh their auth session before validating affected resources.
Closing also coordinates with journal writes already in progress. A write admitted before closing completes first; a write admitted after closing must satisfy the new boundary. A previously fetched editable state does not authorize a later write into the closed period.
Preview and Preflight
Tax-rate and opening-balance mutations expose dry run where the generated
OpenAPI declares the dryRun parameter. The books-closing update
intentionally has neither generic dry run nor a dedicated preview. Explain
the boundary and require confirmation, then apply and handle the normal
response.
Mutation Recipe
- Load current configuration and affected operation response.
- Pick the administrative workflow built for the change.
- Validate its exact generated schema and balancing requirements.
- Dry-run when the operation declares support.
- Explain broad journal or lock consequences.
- Confirm and apply.
- Re-read the team and affected resources.
- Surface any resulting issues or queued recalculation state.
Failure and Recovery
For locked historical input, show the statement or books boundary and keep the
original payload. Do not recommend the x-ignore-books-closed-at header. For
an unbalanced import, repair the opening workflow itself rather than posting
an unrelated transaction to hide the difference. For a concurrent opening-
balance conflict, re-read the dedicated resource and let the user confirm a
new replacement.
Common Recipes
Close a month
Select the first date that should remain open, explain that every earlier affected posting date closes, confirm without dry run, apply, and re-read the team setting.
PUT /team/books-closing
Content-Type: application/json
{
"booksClosedAt": "2026-07-01"
}Import an opening trial balance
Load the current trial-balance response, skip rows where importable=false,
map Operating balances for the remaining rows, dry-run the complete import,
then apply through the dedicated operation. See
Opening Trial Balance for the source
ownership rules.
PUT /general-ledger/opening-trial-balance?dryRun=true
Content-Type: application/json
{
"rows": [
{
"accountId": "22222222-2222-4222-8222-222222222222",
"operatingCentTotal": 250000
},
{
"accountId": "33333333-3333-4333-8333-333333333333",
"operatingCentTotal": -40000
}
]
}Filter the current trial balance
Request one or more supported account classifications as a CSV query value.
GET /reports/trial-balance?classification=asset,liabilityEstablish reservation advance deposits
Read synced candidates, preserve reservation and listing identity, dry-run the replacement, and then apply it. Emptying the reservation array removes the purpose-specific opening transaction.
GET /general-ledger/opening-balances/advanced-deposits/synced-payments-refundsPUT /general-ledger/opening-balances/advanced-deposits?dryRun=true
Content-Type: application/json
{
"accountId": "22222222-2222-4222-8222-222222222222",
"currency": "USD",
"reservations": [
{
"reservationId": "33333333-3333-4333-8333-333333333333",
"listingId": "44444444-4444-4444-8444-444444444444",
"amount": 125000
}
]
}API Reference
- List tax rates — GET /tax-rates
- Create a tax rate — POST /tax-rates
- List accounts — GET /accounts
- Update an account —
PUT /accounts/{id} GET /general-ledger/opening-trial-balance— Read the opening trial balancePUT /general-ledger/opening-trial-balance— Replace itGETandPUT /general-ledger/opening-balances/tax-payableGETandPUT /general-ledger/opening-balances/accounts-payableGETandPUT /general-ledger/opening-balances/accounts-receivable-deferred-revenueGETandPUT /general-ledger/opening-balances/advanced-depositsGET /general-ledger/opening-balances/advanced-deposits/synced-payments-refunds- Update books closing — PUT /team/books-closing
