REST API Accounts - edmozley/freeitsm GitHub Wiki
๐ REST API: Chart of accounts
The usage guide for accounts in the REST API โ the chart itself, and the sync a finance system calls. Mirrors the interactive documentation at System โ API โ Documentation. User guide: Chart of accounts. New in 5.1.0.
[!NOTE] New to the API? The basics table on REST API: Tickets covers base URL, authentication, the response envelope, error codes, rate limits and PATCH semantics - identical across all modules.
Accounts work exactly like cost centres - company-scoped, codes as text, one sync call to stay in step - with one more field, kind.
| ๐ข Company-scoped | Every account is one company's. Lists are filtered to the key's companies; one outside them is a 404 on every by-id route. Writes land in company_id (checked against the key) or the key's default company. |
| ๐ค Codes are text | "2.0.3.0.4" and "0010" stay as sent. Unique per company, ignoring case. Send codes as JSON strings. |
| ๐ท๏ธ Kind | expense, fixed_asset, payroll or income. Words the import understands ("Capex", "Salaries", "Revenue") are accepted too and stored as the key. |
| ๐ One call keeps you in step | POST /accounts/sync takes the whole chart, matched on code. All or nothing. |
๐ Quick start
B="https://your-server/api/v1"; K="Authorization: Bearer fitsm_โฆ"
# Active fixed-asset accounts
curl -s -H "$K" "$B/accounts?kind=fixed_asset&active=true" | jq '.data[] | {code, name}'
# Nightly sync from finance - try it first with dry_run
curl -s -H "$K" -H "Content-Type: application/json" -X POST "$B/accounts/sync" -d '{
"dry_run": true,
"accounts": [
{"code": "2.0.3.0", "name": "IT running costs", "kind": "expense"},
{"code": "2.0.3.0.4", "name": "Software Licences", "parent_code": "2.0.3.0"},
{"code": "2.1.0.3.2", "name": "Computer Equipment", "kind": "fixed_asset"},
{"code": "1.3.0.0.1", "name": "Employee Payroll", "kind": "payroll"}
]}'
Endpoints
| Method | Path | Permission | What |
|---|---|---|---|
| GET | /accounts |
accounts.read | List / search |
| POST | /accounts |
accounts.create | Add one |
| GET | /accounts/{id} |
accounts.read | One account |
| PATCH | /accounts/{id} |
accounts.update | Change fields |
| DELETE | /accounts/{id} |
accounts.delete | Delete (refused with 409 while it has children - make it inactive instead) |
| POST | /accounts/sync |
accounts.update and create | Bring the whole chart in step |
List filters
company_id, code (exact), kind (expense / fixed_asset / payroll / income; anything else is a 400), q (code, name or description), active=true|false, parent_id (0 = top level), sort (code default, name, kind, updated_at, id; prefix - for descending), page / per_page.
An account
{
"id": 12, "code": "2.0.3.0.4", "name": "Software Licences", "kind": "expense", "description": null,
"parent": { "id": 11, "code": "2.0.3.0", "name": "IT running costs" },
"is_active": true,
"company": { "id": 1, "name": "Default" },
"child_count": 0,
"created_at": "2026-11-12T19:02:00Z", "updated_at": "2026-11-12T19:02:00Z"
}
Writes take code, name, kind (required on create), description, parent_id or parent_code (same company; never itself or anything below it), is_active, and on create company_id. kind can be changed but not emptied.
The sync
Body: accounts (array, at most 10,000 โ split bigger charts by company), each with code and any of name, kind, description, parent_code, is_active; optional company_id, dry_run, deactivate_missing.
- Matched on code, ignoring case. Only the keys you send are changed.
- A new code needs a
nameand akind- or aparent_code, whose kind it then takes (the nearest ancestor with one, in this call or already there). parent_codemay name another row in the same call, or an existing account. A blank one means top level.deactivate_missing: truemakes inactive every account of that company not in the list. Nothing is ever deleted.- All or nothing. Any problem and nothing is written: 422
invalid_rowswith every problem inerror.details.errors(line= 1-based position inaccounts). dry_run: truereturns what would happen and writes nothing.
Response: company_id, applied, dry_run, counts (create, update, unchanged, deactivate) and changes - one entry per row that changed, with its line, code, name, kind, action and the fields that changed.
Related: REST API ยท Chart of accounts ยท REST API: Cost centres