Ledgers (Chart of Accounts)
Ledgers represent accounts in the chart of accounts. Every financial transaction flows through ledger accounts via journal entries.
Account Types
| Type | Description | Normal Balance |
|---|---|---|
asset |
Cash, bank accounts, receivables, equipment | Debit |
liability |
Payables, loans, credit cards | Credit |
equity |
Owner's equity, retained earnings | Credit |
revenue |
Sales, service income | Credit |
expense |
Rent, payroll, utilities, supplies | Debit |
List Ledgers
curl "https://api.ondayzero.com/api/v1/ledgers?type=expense&status=active" \
-H "Authorization: Bearer dz_your_token_here" \
-H "x-business-id: YOUR_BUSINESS_ID"Filter Parameters
| Parameter | Type | Description |
|---|---|---|
name |
string | Partial name match |
type |
string | asset, liability, equity, revenue, expense |
status |
string | active, inactive |
id |
string | Comma-separated ledger UUIDs |
include_balances |
boolean | Fill each ledger's balance (cents, oriented on its normal side) from the books. Off by default, when balance is null |
as_of_date |
date | Balance date (YYYY-MM-DD) for include_balances; defaults to today |
Plus the standard pagination parameters. GET /api/v1/ledgers/{ledger_id} returns one ledger.
Each ledger carries id, name, type, sub_type, debit_credit, sort_code, account_number, status, currency, parent_id, report_cash_flow, cash_flow_section, cfs_class, depreciation_tag, editable, financial_account_type, is_required, system_key (set on system ledgers such as accounts_receivable), and account_mask (last four digits of a linked bank or card account).
Create a Ledger
There are two creation modes — templated (a standard financial account, auto-configured) and custom (you specify the accounting properties):
Templated
curl -X POST "https://api.ondayzero.com/api/v1/ledgers" \
-H "Authorization: Bearer dz_your_token_here" \
-H "x-business-id: YOUR_BUSINESS_ID" \
-H "Content-Type: application/json" \
-d '{
"name": "Operating Checking",
"financial_account_type": "bank_account"
}'financial_account_type is one of bank_account, credit_card, payments, payroll, loan, prepaid_card, accounts_receivable, accounts_payable.
Custom
curl -X POST "https://api.ondayzero.com/api/v1/ledgers" \
-H "Authorization: Bearer dz_your_token_here" \
-H "x-business-id: YOUR_BUSINESS_ID" \
-H "Content-Type: application/json" \
-d '{
"name": "Prepaid Insurance",
"type": "asset",
"sub_type": "current_assets",
"debit_credit": "debit",
"sort_code": 1400,
"report_cash_flow": true,
"account_number": "1400",
"description": "Insurance premiums paid in advance",
"parent_id": "PARENT_LEDGER_UUID"
}'Response data is the new ledger (abbreviated):
{
"success": true,
"data": {
"id": "019ab37c-d4a2-7b38-85f0-6b2a3c8e9f1a",
"name": "Prepaid Insurance",
"type": "asset",
"sub_type": "current_assets",
"debit_credit": "debit",
"sort_code": "1400",
"account_number": "1400",
"status": "active",
"currency": "USD",
"editable": true,
"balance": null
}
}Custom mode requires name, type, sub_type, debit_credit, sort_code (an integer) and report_cash_flow. Optional extras: currency (USD, CAD, AUD, EUR, GBP), editable (default true; whether journal entries can be posted manually), status (active by default), account_number (chart-of-accounts code), parent_id (nest under a parent account), cash_flow_section (operating, investing, financing, excluded), cfs_class (indirect-method cash flow class such as cash, ar, inventory, ppe, ap, lt_debt, retained_earnings, revenue, cogs, opex; derived from the type when omitted), and depreciation_tag (depreciable / amortizable — lets fixed assets be capitalized from this account's transactions).
Update a Ledger
curl -X PUT "https://api.ondayzero.com/api/v1/ledgers/{ledger_id}" \
-H "Authorization: Bearer dz_your_token_here" \
-H "x-business-id: YOUR_BUSINESS_ID" \
-H "Content-Type: application/json" \
-d '{
"name": "Prepaid Insurance (Current)",
"description": "Short-term insurance prepayments"
}'Updates accept the same fields as create except currency (all optional), including type to reclassify an account and status to archive it. An inactive ledger can only have its status changed. Renaming to a name an active ledger already holds returns 409, and a system ledger's name, type and debit_credit cannot be changed (400). An empty body returns the ledger unchanged.
Merge Ledgers
Consolidate multiple accounts into one. All journal entry lines, transactions, budgets, reconciliations, and bank rules are reassigned. Source accounts are archived.
curl -X POST "https://api.ondayzero.com/api/v1/ledgers/merge" \
-H "Authorization: Bearer dz_your_token_here" \
-H "x-business-id: YOUR_BUSINESS_ID" \
-H "Content-Type: application/json" \
-d '{
"source_ledger_ids": ["LEDGER_UUID_1", "LEDGER_UUID_2"],
"target_ledger_id": "TARGET_LEDGER_UUID",
"new_name": "Consolidated Office Expenses"
}'Source and target must be the same kind of account (same type, sub_type and debit_credit), the target must be active and cannot also be a source, and bank-linked ledgers cannot be merged. System ledgers can only merge into another system ledger and additionally require "confirmation": "MERGE". You cannot rename a system target during a merge. The response is {"message": "...", "merged_ledger": {...}}. Merges are irreversible.
Bulk Update and AI Helpers
POST /api/v1/ledgers/bulk-updateapplies many updates in one call ({"updates": [{"id": "...", "status": "inactive"}, …]}) and returns{"updated": N}. Each update is applied likePUT; a row that fails is skipped and not counted, so compareupdatedwith what you sent.POST /api/v1/ledgers/suggest-cleanup(no body) returns AI suggestions, each with atype(merge,cleanup,reclassifyorunused),affected_ledger_idsand, for merges,suggested_target_ledger_idto pass to/ledgers/merge. It is rate limited (10 requests per 5 minutes per user) and counts against the monthly AI quota.POST /api/v1/ledgers/suggest-cash-flow(no body, deterministic) returnssuggested_cfs_classandsuggested_cash_flow_sectionfor each active account next to its current values.POST /api/v1/ledgers/apply-coaupserts a whole chart of accounts from{"ledgers": [{"name", "type", "sub_type", "sort_code", ...}]}.sort_codeis a digits-only string and must be unique in the template; optional per row:debit_credit,report_cash_flow,editable,description,financial_account_type. Rows are matched to existing ledgers by sort code: new codes are created, matches updated, and custom ledgers missing from the template are set inactive. System, required and bank-linked ledgers are skipped. A bad row is reported infailedand does not stop the rest; the response hascreated,updated,skipped,deactivated,failedandtotal.
Delete a Ledger
curl -X DELETE "https://api.ondayzero.com/api/v1/ledgers/{ledger_id}" \
-H "Authorization: Bearer dz_your_token_here" \
-H "x-business-id: YOUR_BUSINESS_ID"Deletion returns
400for protected accounts (system accounts such as AR and AP, required accounts, and bank-linked ledgers) and409 Conflictif the ledger still has journal entry lines — move or delete those first, merge the ledger into another, or mark itinactiveinstead.
To remove a ledger and everything posted to it, preview the blast radius with GET /api/v1/ledgers/{ledger_id}/cascade-preview, then DELETE /api/v1/ledgers/{ledger_id}/cascade. The preview returns counts of journal entries, line entries, transactions, bill payments, reconciliations and more. The delete returns 202 with a workflow_id (or 200 if the ledger is already gone); poll GET /api/v1/ledgers/deletion-status/{workflow_id} for completed, status, success and deleted_count. This is destructive and cannot be undone.
Errors
| Status | code |
Cause |
|---|---|---|
400 |
VALIDATION_066 |
Custom create without sort_code (the other required custom fields have their own VALIDATION_* codes) |
400 |
VALIDATION_130 / VALIDATION_216 |
Renaming or changing accounting properties of a system ledger |
400 |
VALIDATION_131 |
Deleting, or merging away, a system, required or bank-linked ledger |
400 |
VALIDATION_217 |
Updating anything but status on an inactive ledger |
404 |
NOT_FOUND_014 |
Ledger not found in this business |
409 |
CONFLICT_015 |
Another active ledger already has this name (create, rename, reactivate) |
409 |
CONFLICT_013 |
Deleting a ledger that still has journal entry lines |