How Kiravy thinks about Chart of Accounts
Why your SQL Account codes stay identical in Kiravy.
This page explains a design decision that confuses people coming from "one CoA template fits all" products: Kiravy keeps every client's chart of accounts exactly as their source system defines it.
That sounds boring. The implications matter.
The decision
Every Kiravy client has its own private chart of accounts (coa_accounts). When SQL Account (or Xero, or QuickBooks) syncs in, the codes land identically:
| In SQL Account | In Kiravy |
|---|---|
500-200 Office Rent | 500-200 Office Rent |
310-001 Maybank Current Account | 310-001 Maybank Current Account |
100-000 Sales | 100-000 Sales |
No remapping. No "Kiravy's standard chart". No AI translation. The string 500-200 stays a 500-200.
Why
1. Your existing chart carries over unchanged
The accountant has already maintained a CoA in SQL Account for years — sometimes a hundred codes, sometimes three hundred. When you migrate into Kiravy that chart comes across as-is; Kiravy isn't here to redo that work. (Kiravy's own ledger is the system of record from then on — SQL Account is the migration source, not a system Kiravy keeps in step with.)
If Kiravy used its own codes, the migration would need a mapping table: SQL: 500-200 → Kiravy: rent_expense. Who would author that mapping? Not us — every client's CoA is different. Not the user — that's another job they didn't ask for. And a renamed code would silently break the mapping.
Letting codes pass through unchanged costs zero maintenance.
2. Migration stays one-to-one
When you check a freshly migrated client against the old SQL Account books, you search 500-200 in both and see the same number. No mental translation. If something disagrees, it's a real disagreement — not a mapping bug.
3. Each client uses their own accountant's codes
Different industries use different conventions. A restaurant client's CoA looks nothing like a software services client's. Forcing both into one Kiravy template would be wrong for at least one of them.
What's NOT in coa_accounts.code
Just the string. No semantics. 500-200 doesn't mean anything to Kiravy — it's a label the accountant chose.
What Kiravy does understand is a coarser classification one level above: account_type.
account_type — the part Kiravy understands
Every CoA row has both code (free-text label) and account_type (one of 7 buckets):
account_type | Used for |
|---|---|
revenue | Sales, services income |
cogs | Direct cost of producing what you sell |
expense | Operating expenses (rent, salaries, utilities) |
asset | Bank accounts, AR, inventory, fixed assets |
liability | AP, loans, tax payable, accrued expenses |
equity | Capital, retained earnings, drawings |
tax | SST control accounts |
The account_type is what Kiravy uses for reporting (e.g. P&L groups everything by revenue / cogs / expense).
The mapping from SQL Account ACCTYPE to Kiravy account_type happens at sync time, as a small lookup table:
SQL Account ACCTYPE → Kiravy account_type
─────────────────────────────────────────
SL, SR → revenue
CO, PR → cogs
EP, EX → expense
CA, FA, AR → asset
CL, LL → liability
AP, CP, EQ → equity
TX → tax
This is the only thing in the CoA pipeline that's translation, not pass-through. And it's a fixed table — no ambiguity, no AI.
So how do you do cross-client analysis?
You're a firm with 30 clients. Each has their own 500-200 (or 4000, or 60100) for rent. How do you ask "how much rent do my clients pay on average?"
Today: not easily. You'd need to write SQL joining on account_type='expense' and filter by name heuristics like name ILIKE '%rent%' — ugly, imprecise.
Phase 2 will add an optional semantic_category column to coa_accounts. AI suggests a standardised label (rent_expense, utilities, professional_fees) for each account; the firm can override. That layer enables cross-client benchmarking without touching the code or account_type columns — so reconciliation stays correct.
This is a future addition, not something to wait for. For now, single-client reports work great; cross-client is a phase 2 feature.
Adding accounts manually
Most CoA codes come from SQL Account sync, but you can add manual codes too — useful for accounts that exist in Kiravy but not (yet) in SQL Account (e.g. tracking AI/automation costs separately).
Client → Settings → Chart of Accounts → Add account:
- Code — free text, must be unique per client (and unique across active rows)
- Name — human label
- Type — pick from the 7 enum values above
If a migration import later brings in a row with the same code, it'll be upserted (merged) — no duplicate.
System / control accounts
Beyond your own revenue and expense codes, Kiravy's ledger needs a handful of control accounts to record double-entry bookkeeping — the places invoices, bills, payments, and tax land. Kiravy creates these for every client automatically, so you don't have to set them up:
| Account | Code |
|---|---|
| Accounts receivable | 200-000 |
| Accounts payable | 300-000 |
| Bank / cash | 100-000 |
| SST output (charged on sales) | 310-000 |
| SST input (paid on purchases) | 210-000 |
| Opening-balance equity | 490-000 |
You normally never touch these by hand — they're posted to behind the scenes when you raise an invoice, enter a bill, mark something paid, or set opening balances. See How Kiravy's general ledger works for what each one is for.
Deactivating vs deleting
Codes in coa_accounts are immutable — code can't change, neither can client_id or workspace_id. Why: existing transactions reference the code by name; renaming would silently break history.
To stop using a code: deactivate it (is_active = false). It stays in the table for historical lookups but no new transactions can reference it (the validation trigger blocks inserts).
To "rename": deactivate the old code, create a new one. Both stay in history.
TL;DR
codeis source-of-truth, never modified, never translatedaccount_typeis Kiravy's coarse classification, mapped from source at syncsemantic_category(Phase 2) will be the AI layer for cross-client analysis- Codes are immutable once created; deactivate to stop using them
See also
- General ledger — how the system/control accounts are used
- Transactions — how transactions reference codes