First chart of accounts¶
This walks through setting up a chart of accounts on a fresh SAE Books instance, posting an opening balances journal, and confirming the result in the trial balance.
You'll need:
- A running SAE Books instance (quickstart)
- A bearer token for your tenant (auth)
1. Decide the structure¶
The chart is hierarchical, keyed by code. The top-level shape is
fixed (the account types — ASSET, LIABILITY, EQUITY, INCOME,
OTHER_INCOME, EXPENSE, COST_OF_SALES, OTHER_EXPENSE); below
that, codes and grouping are yours.
A common Australian SME structure:
| Code | Name | Type |
|---|---|---|
| 1100 | Cash at bank | ASSET |
| 1200 | Trade debtors | ASSET |
| 1500 | Inventory | ASSET |
| 1700 | Plant & equipment | ASSET |
| 2100 | Trade creditors | LIABILITY |
| 2300 | GST payable | LIABILITY |
| 3100 | Owner equity | EQUITY |
| 4000 | Sales | INCOME |
| 5000 | Cost of goods sold | COST_OF_SALES |
| 6000 | Operating expenses | EXPENSE |
| 6100 | Wages & salaries | EXPENSE |
You don't have to commit upfront — you can add accounts later. But the codes are sticky in the sense that reports order on them, so pick a numbering scheme you'll be happy with in a year.
2. Seed the chart¶
There is no bulk-create endpoint. Post accounts one at a time to
POST /api/v1/accounts. The account_type values are uppercase enum
strings; tax_code_default sets the default tax code for a line
posted to that account (use the tax code string, e.g. "GST"):
curl -X POST "$SAEBOOKS_API_BASE/accounts" \
-H "Authorization: Bearer $JWT" \
-H "Content-Type: application/json" \
-d '{"code":"1100","name":"Cash at bank","account_type":"ASSET"}'
curl -X POST "$SAEBOOKS_API_BASE/accounts" \
-H "Authorization: Bearer $JWT" \
-H "Content-Type: application/json" \
-d '{"code":"1200","name":"Trade debtors","account_type":"ASSET"}'
curl -X POST "$SAEBOOKS_API_BASE/accounts" \
-H "Authorization: Bearer $JWT" \
-H "Content-Type: application/json" \
-d '{"code":"2100","name":"Trade creditors","account_type":"LIABILITY"}'
curl -X POST "$SAEBOOKS_API_BASE/accounts" \
-H "Authorization: Bearer $JWT" \
-H "Content-Type: application/json" \
-d '{"code":"2300","name":"GST payable","account_type":"LIABILITY","tax_code_default":"GST"}'
curl -X POST "$SAEBOOKS_API_BASE/accounts" \
-H "Authorization: Bearer $JWT" \
-H "Content-Type: application/json" \
-d '{"code":"3100","name":"Owner equity","account_type":"EQUITY"}'
curl -X POST "$SAEBOOKS_API_BASE/accounts" \
-H "Authorization: Bearer $JWT" \
-H "Content-Type: application/json" \
-d '{"code":"4000","name":"Sales","account_type":"INCOME","tax_code_default":"GST"}'
curl -X POST "$SAEBOOKS_API_BASE/accounts" \
-H "Authorization: Bearer $JWT" \
-H "Content-Type: application/json" \
-d '{"code":"6000","name":"Operating expenses","account_type":"EXPENSE","tax_code_default":"GST"}'
Each call returns the created account with its UUID. Save the UUIDs you need for the next step.
Valid account_type values: ASSET, LIABILITY, EQUITY, INCOME,
OTHER_INCOME, EXPENSE, COST_OF_SALES, OTHER_EXPENSE.
3. Post opening balances¶
Opening balances are a single journal that brings the trial balance up from zero to your "as at" position on day one. It must balance.
The journal entries endpoint is /api/v1/journal_entries. Lines
reference accounts by UUID (account_id), not by code. The
payload fields are entry_date, narration, and reference:
curl -X POST "$SAEBOOKS_API_BASE/journal_entries" \
-H "Authorization: Bearer $JWT" \
-H "Content-Type: application/json" \
-d '{
"entry_date": "2026-07-01",
"narration": "Opening balances",
"lines": [
{"account_id":"<uuid-of-1100>","debit":"15000.00","credit":"0"},
{"account_id":"<uuid-of-1200>","debit":"4200.00","credit":"0"},
{"account_id":"<uuid-of-2100>","debit":"0","credit":"3100.00"},
{"account_id":"<uuid-of-3100>","debit":"0","credit":"16100.00"}
]
}'
This creates a DRAFT entry. To post it, call:
curl -X POST "$SAEBOOKS_API_BASE/journal_entries/<entry-id>/post" \
-H "Authorization: Bearer $JWT" \
-H "If-Match: 1" \
-H "X-Idempotency-Key: $(uuidgen)"
The server validates SUM(debits) = SUM(credits) at both the schema
level and on post; an unbalanced journal returns 422.
4. Verify¶
curl "$SAEBOOKS_API_BASE/reports/trial_balance?as_of_date=2026-07-01" \
-H "Authorization: Bearer $JWT"
You should see your four touched accounts at their opening balances, and every other account at zero.
What you've built¶
- A chart of accounts you'll add to as the business grows
- An immutable opening-balances journal that anchors every report
- A trial balance that balances at zero — the precondition for every P&L, balance sheet, and BAS run from here on
Next¶
- Connect a bank feed — start ingesting real transactions
- Accounting module — the deeper model behind journals and lines