Accounts and tax types
Synchronize the Chart of Accounts
/a/Account_updateData
Synchronize the tenant’s complete Chart of Accounts to a CRM2 Finance-page snapshot.
When to use this endpoint
Use Account_updateData only when saving the complete CRM2 Chart of Accounts. It is not a partial update endpoint: rows absent from accounts are permanently deleted.
Authentication and permissions
The request must authenticate with signed API-key fields or a logged-in CRM session. The handler calls the normal login guard but performs no additional Finance-page, client-admin, role, create, edit, or delete permission check.
All reads and writes use the authenticated tenant. CRM1 and CRM2 decide whether to show finance controls, but these handlers do not repeat those client-side checks.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
accounts | Nonempty native array of objects | Yes | Authoritative complete account list. Do not JSON-encode the outer array. |
accounts[].accountID | Integer-compatible | Yes | Existing positive ID to retain/update, or 0 for a new row. IDs absent from the complete list are deleted first. |
accounts[].nominalCode | String | Yes for create/update | Trimmed account code, maximum 10 characters. Blank new rows are skipped; blank existing rows keep their name/code but still have category links replaced. |
accounts[].accountName | String | No | Name and display name, maximum 128 characters. Omission becomes an empty string on a normal existing-row update. |
accounts[].defaultAccount | Integer-compatible | No | Exact value 1 makes this row the default and clears other default markers. Other values do not clear an existing marker on a retained row. |
accounts[].taxType | JSON array | No | Complete linked category-ID list. Missing or invalid JSON is treated as an empty list, clearing links for an existing account. |
Example request
$result = FM_api('Account_updateData', [
'accounts' => [
[
'accountID' => 331042,
'nominalCode' => '4000',
'accountName' => 'Sales',
'defaultAccount' => 0,
'taxType' => json_encode([271006]),
],
],
]);
Example response
{"ok":1}
Errors and unusual responses
| Response | Condition |
|---|---|
{"error":"not logged in"} | No authenticated tenant context is available. Invalid signed credentials can be rejected by the dispatcher before the handler runs. |
{"error":"missing or invalid parameter: accounts"} | The outer value is absent, not a native array, empty, or contains a non-object/non-array element. |
{"error":"parameter too long: accountName. max length 128 characters"} | Any row’s account name exceeds the mapped limit. Validation happens before deletion starts. |
{"error":"parameter too long: nominalCode. max length 10 characters"} | Any row’s nominal code exceeds 10 characters. Validation happens before deletion starts. |
{"error":"account does not exist: 123"} | A submitted positive account ID does not exist. The response includes that ID and no snapshot writes have started. |
Legacy application errors may be returned with HTTP 200. Check the decoded response for error, not only the HTTP status.
Behaviour and edge cases
- Existing IDs are collected with integer conversion for the deletion pass. Each retained row is then updated from its submitted values.
- Account IDs are integer-normalized before validation or SQL use. A submitted positive ID must exist before the snapshot can proceed.
- New rows use
accountID=0and a nonempty code. The endpoint can create duplicate codes because it performs no uniqueness check. - For every retained existing row, category links are deleted and rebuilt even when
taxTypewas omitted or invalid. - The endpoint always returns
{"ok":1}after its loops and provides no insert/update/delete counts or per-row warnings.
Side effects
- Permanently deletes omitted account rows, their category links, and matching stock nominal values; app-sync delete rows use the legacy key
nominal_code. - Creates or updates account rows, default markers, category links, and
last_editedtimestamps. - Migrates matching
stock.nominal_codevalues when a retained account’s nonempty code changes. Other records that contain the code are not rewritten.
See it in Fieldmotion
CRM1
CRM1 does not call this snapshot route; it uses the focused Account_new, Account_set*, and Account_delete endpoints.
CRM2
Open Settings → Finance. CRM2 loads the three finance tables and saves them as complete snapshots; filter browser developer tools for the exact function name. The Save button serializes every nonblank account row and calls this endpoint before saving Tax Types and Tax Groups.
Related endpoints
Accounts_listsupplies the starting account snapshot.AccountCategory_updateDatais the following destructive Tax Types save.AccountCategoryGroup_updateDatacompletes CRM2’s finance snapshot chain.