Skip to content

Chart of Accounts

The chart of accounts is the account structure the rest of the ERP hangs off. Ledgers reference it directly; cashbooks reference it through a GL code. Create these records first.

Base path: https://api-etl.akaun.com/core2/tnt/dm/erp/chart-of-acc

Authentication covers credentials, Data API the envelope and query parameters, and ERP Core API the shared errors and filters.

The fast path:

  1. To see what you would get, POST /etl-ep/default-gl-codes: it returns the default financial report sections and writes nothing.
  2. Setting up a tenant from nothing, POST /etl-ep/create-with-glcode with name, code and txn_type (create with default GL codes). Its codes are six-digit numbers with camel-case names, so if your chart uses other codes, decide first whether you will rename them or build the chart yourself. Plain POST /etl-ep makes an account with nothing to post to until GL codes are added, and cashbooks need a GL code to reference.
  3. To update, PUT /etl-ep the whole container with guid, revision and status. Permission is checked against the specific account.

Permissions

The access key’s owner needs one of these for each operation:

OperationPermissions (any one)
CreateTNT_LOG_CHART_OF_ACC_OWNER, TNT_LOG_CHART_OF_ACC_ADMIN, TNT_API_CHART_OF_ACC_CREATE
ReadTNT_LOG_CHART_OF_ACC_OWNER, TNT_LOG_CHART_OF_ACC_ADMIN, TNT_API_CHART_OF_ACC_READ
UpdateTNT_LOG_CHART_OF_ACC_OWNER, TNT_LOG_CHART_OF_ACC_ADMIN, TNT_API_CHART_OF_ACC_UPDATE
DeleteTNT_LOG_CHART_OF_ACC_OWNER, TNT_LOG_CHART_OF_ACC_ADMIN, TNT_API_CHART_OF_ACC_DELETE

A tenant owner or admin passes all of these regardless.


Endpoints

OperationIntegration path (/etl-ep)Back-office path
CreatePOST /etl-epPOST /
UpdatePUT /etl-epPUT /
DeleteDELETE /etl-ep/{guid}DELETE /{guid}
List allGET /etl-epGET /
Get oneGET /etl-ep/{guid}GET /{guid}
QueryGET /etl-ep/queryGET /query

Two further endpoints help you build a chart of accounts from scratch:

OperationIntegration path (/etl-ep)Back-office path
Create with default GL codesPOST /etl-ep/create-with-glcodePOST /create-with-glcode
Default GL code templatePOST /etl-ep/default-gl-codesPOST /default-gl-codes

create-with-glcode creates the account and its default GL code set in one call. default-gl-codes returns the default financial report sections without writing anything, so you can inspect the template first.

Setting up a tenant from nothing? Use create-with-glcode rather than plain POST /etl-ep. An account created without GL codes has nothing to post to until GL codes are added, and cashbooks need a GL code to reference.

The ChartOfAccContainer

{
  "bl_fi_mst_chart_of_acc": { },
  "financialReportSections": [ ]
}

bl_fi_mst_chart_of_acc

FieldTypeOn createDescription
guidUUIDOptionalGenerated if omitted. Required on update. If you supply it on create, it must not already exist.
namestringRequiredAccount name.
codestringRequiredAccount code.
txn_typestringRequiredTransaction type this account is used for.
descrstringOptionalDescription.
statusstringOptionalDefaults to ACTIVE.
revisionUUIDOptionalGenerated if omitted. Send the value you read back when updating.
vrsnstringServer-assignedVersion marker.
created_datedatetimeServer-assigned
updated_datedatetimeServer-assigned
created_by_subject_guidUUIDServer-assignedSet from the access key’s owner.
updated_by_subject_guidUUIDServer-assignedSet from the access key’s owner.

Create fails with CHARTSOFACC_OBJECT_NAME_IS_NULL_OR_EMPTY, ..._CODE_IS_NULL_OR_EMPTY or ..._TXNTYPE_IS_NULL_OR_EMPTY when a required field is missing.

financialReportSections

Optional. Each section groups GL categories for financial reporting:

FieldTypeDescription
accNostringAccount number for the section.
codestringSection code.
namestringSection name.
glCategoriesarrayGL categories in the section, each with code, name, guid, level_value, group_guid, status, descr, category_group.

Send [] if you are not using report sections.


Create an account

POST /core2/tnt/dm/erp/chart-of-acc/etl-ep

curl -X POST "https://api-etl.akaun.com/core2/tnt/dm/erp/chart-of-acc/etl-ep" \
  -H "AccessId: YOUR_ACCESS_ID" \
  -H "AccessKey: YOUR_ACCESS_KEY" \
  -H "tenantCode: YOUR_TENANT_CODE" \
  -H "Content-Type: application/json" \
  -d '{
    "bl_fi_mst_chart_of_acc": {
      "name": "Main Chart of Accounts",
      "code": "COA-MAIN-01",
      "txn_type": "GENERAL",
      "descr": "Primary chart of accounts",
      "status": "ACTIVE"
    },
    "financialReportSections": []
  }'

Response

{
  "code": "OK_RESPONSE",
  "data": {
    "bl_fi_mst_chart_of_acc": {
      "guid": "8d1e4b77-2c60-4f19-93a5-6e0b2d8c4a71",
      "name": "Main Chart of Accounts",
      "code": "COA-MAIN-01",
      "txn_type": "GENERAL",
      "descr": "Primary chart of accounts",
      "status": "ACTIVE",
      "revision": "5e9c3a81-7d42-4b06-9f18-2a7b4c6e8d50",
      "created_date": "2026-09-14T09:30:00+08:00"
    },
    "financialReportSections": []
  },
  "message": ""
}

Keep the returned guid: ledgers reference it as chart_of_acc_hdr_guid.


Create an account with its default GL codes

POST /core2/tnt/dm/erp/chart-of-acc/etl-ep/create-with-glcode

Takes the same ChartOfAccContainer as plain create, and additionally generates the default GL code set for the account. This is normally what you want when setting up a tenant. See the note under Endpoints.

curl -X POST "https://api-etl.akaun.com/core2/tnt/dm/erp/chart-of-acc/etl-ep/create-with-glcode" \
  -H "AccessId: YOUR_ACCESS_ID" \
  -H "AccessKey: YOUR_ACCESS_KEY" \
  -H "tenantCode: YOUR_TENANT_CODE" \
  -H "Content-Type: application/json" \
  -d '{
    "bl_fi_mst_chart_of_acc": {
      "name": "Main Chart of Accounts",
      "code": "COA-MAIN-01",
      "txn_type": "GENERAL",
      "status": "ACTIVE"
    },
    "financialReportSections": []
  }'

The response is the created ChartOfAccContainer. Sent with [], it comes back with financialReportSections filled with the stock set (the one default-gl-codes shows). Shortened to one section:

{
  "code": "OK_RESPONSE",
  "data": {
    "bl_fi_mst_chart_of_acc": {
      "guid": "8d1e4b77-2c60-4f19-93a5-6e0b2d8c4a71",
      "name": "Main Chart of Accounts",
      "code": "COA-MAIN-01",
      "status": "ACTIVE"
    },
    "financialReportSections": [
      { "accNo": "110000", "code": "CurrentAssets", "name": "CurrentAssets", "glCategories": [ ] }
    ]
  },
  "message": ""
}

The GL codes are written separately. Read them back through the GL code endpoints rather than expecting them in this response body.

Requires the same create permission as POST /etl-ep.


Inspect the default GL code template

POST /core2/tnt/dm/erp/chart-of-acc/etl-ep/default-gl-codes

Returns the default financial report sections without writing anything, so you can see what create-with-glcode would generate. The body is an optional raw JSON string used to steer the template; send none to get the stock set.

curl -X POST "https://api-etl.akaun.com/core2/tnt/dm/erp/chart-of-acc/etl-ep/default-gl-codes" \
  -H "AccessId: YOUR_ACCESS_ID" \
  -H "AccessKey: YOUR_ACCESS_KEY" \
  -H "tenantCode: YOUR_TENANT_CODE"

Response: an array of FinancialReportSection, eighteen of them in the stock set at the time of writing (CurrentAssets, FixedAssets, CurrentLiabilities, SalesRevenue, CostOfGoodsSold, GeneralExpenses and the rest). Each section holds its GL categories, and each category the GL codes create-with-glcode would write. Shortened to one section:

{
  "code": "OK_RESPONSE",
  "message": "",
  "data": [
    {
      "accNo": "110000",
      "code": "CurrentAssets",
      "name": "CurrentAssets",
      "glCategories": [
        {
          "accNo": "110100",
          "code": "Cash",
          "name": "Cash",
          "glCodes": [
            { "accNo": "110101", "code": "cashDraws", "name": "Cash Drawers" },
            { "accNo": "110102", "code": "cashOnHand", "name": "Cash On Hand" }
          ]
        },
        {
          "accNo": "110300",
          "code": "Inventory",
          "name": "Inventory",
          "glCodes": [
            { "accNo": "110301", "code": "inventory", "name": "Inventory" }
          ]
        }
      ]
    }
  ]
}

The stock numbering is six digits (110000 for the section, 110100 for a category, 110101 for a code), and the codes are camel-case names such as cashOnHand. If your chart uses other codes, such as mnemonic ones like INV-LAPTOP, decide before you call create-with-glcode whether you will rename these afterwards or build the chart yourself.

This endpoint computes the template in memory and does no permission check beyond authentication.


Update an account

PUT /core2/tnt/dm/erp/chart-of-acc/etl-ep

Send the whole container with guid set. On update, revision and status are both required as well as guid. Permission is checked against the specific account, so TNT_API_CHART_OF_ACC_UPDATE granted on one account does not permit editing another.

curl -X PUT "https://api-etl.akaun.com/core2/tnt/dm/erp/chart-of-acc/etl-ep" \
  -H "AccessId: YOUR_ACCESS_ID" \
  -H "AccessKey: YOUR_ACCESS_KEY" \
  -H "tenantCode: YOUR_TENANT_CODE" \
  -H "Content-Type: application/json" \
  -d '{
    "bl_fi_mst_chart_of_acc": {
      "guid": "8d1e4b77-2c60-4f19-93a5-6e0b2d8c4a71",
      "name": "Main Chart of Accounts (2026)",
      "code": "COA-MAIN-01",
      "txn_type": "GENERAL",
      "status": "ACTIVE",
      "revision": "5e9c3a81-7d42-4b06-9f18-2a7b4c6e8d50"
    }
  }'

The answer is the account as saved, with a new revision:

{
  "code": "OK_RESPONSE",
  "data": {
    "bl_fi_mst_chart_of_acc": {
      "guid": "8d1e4b77-2c60-4f19-93a5-6e0b2d8c4a71",
      "name": "Main Chart of Accounts (2026)",
      "code": "COA-MAIN-01",
      "status": "ACTIVE",
      "revision": "0b7d2e95-6a14-4c83-b5f9-1e8a3c7d4f26"
    },
    "financialReportSections": []
  },
  "message": ""
}

Delete an account

DELETE /core2/tnt/dm/erp/chart-of-acc/etl-ep/{guid}

curl -X DELETE "https://api-etl.akaun.com/core2/tnt/dm/erp/chart-of-acc/etl-ep/8d1e4b77-2c60-4f19-93a5-6e0b2d8c4a71" \
  -H "AccessId: YOUR_ACCESS_ID" \
  -H "AccessKey: YOUR_ACCESS_KEY" \
  -H "tenantCode: YOUR_TENANT_CODE"

Response

{ "code": "OK_RESPONSE", "data": true, "message": "" }

Returns 404 with CLIENT_VALIDATION_GUID_DOES_NOT_EXIST if the account does not exist, and 403 if the key’s owner has no delete permission on it.

Deleting an account that ledgers or GL codes still reference will leave those records pointing at a deleted account. Detach them first.


List all accounts

GET /core2/tnt/dm/erp/chart-of-acc/etl-ep

The answer is the envelope without paging fields, one container per record:

{
  "code": "OK_RESPONSE",
  "message": "",
  "data": [
    {
      "bl_fi_mst_chart_of_acc": { "guid": "8d1e4b77-2c60-4f19-93a5-6e0b2d8c4a71", "code": "COA-MAIN-01", "status": "ACTIVE" },
      "financialReportSections": null
    }
  ]
}

Streams every account, including those the key’s owner may not read, which arrive as their guid and "status": "PERMISSION_DENIED" only (Redacted records). No paging: use /etl-ep/query for that.


Get one account

GET /core2/tnt/dm/erp/chart-of-acc/etl-ep/{guid}

curl "https://api-etl.akaun.com/core2/tnt/dm/erp/chart-of-acc/etl-ep/8d1e4b77-2c60-4f19-93a5-6e0b2d8c4a71" \
  -H "AccessId: YOUR_ACCESS_ID" \
  -H "AccessKey: YOUR_ACCESS_KEY" \
  -H "tenantCode: YOUR_TENANT_CODE"
{
  "code": "OK_RESPONSE",
  "data": {
    "bl_fi_mst_chart_of_acc": {
      "guid": "8d1e4b77-2c60-4f19-93a5-6e0b2d8c4a71",
      "name": "Main Chart of Accounts (2026)",
      "code": "COA-MAIN-01",
      "txn_type": "GENERAL",
      "status": "ACTIVE"
    },
    "financialReportSections": null
  },
  "message": ""
}

The account is looked up before the permission is checked: an unknown guid answers 404 CLIENT_VALIDATION_GUID_DOES_NOT_EXIST, an account you may not read answers 403.


Query accounts

GET /core2/tnt/dm/erp/chart-of-acc/etl-ep/query

In addition to the shared query parameters:

ParameterTypeDescription
txn_typestringFilter by transaction type.
codestringExact code match.
namestringExact name match.
descrstringMatch on description.
hdr_guidsUUID setFetch a specific set of accounts. Repeat the parameter.
curl -G "https://api-etl.akaun.com/core2/tnt/dm/erp/chart-of-acc/etl-ep/query" \
  -H "AccessId: YOUR_ACCESS_ID" \
  -H "AccessKey: YOUR_ACCESS_KEY" \
  -H "tenantCode: YOUR_TENANT_CODE" \
  --data-urlencode "txn_type=GENERAL" \
  --data-urlencode "status=ACTIVE" \
  --data-urlencode "limit=50" \
  --data-urlencode "calcTotalRecords=true"

Response

{
  "totalRecords": 1,
  "offset": 0,
  "limit": 50,
  "code": "OK_RESPONSE",
  "message": null,
  "data": [
    {
      "bl_fi_mst_chart_of_acc": {
        "guid": "8d1e4b77-2c60-4f19-93a5-6e0b2d8c4a71",
        "code": "COA-MAIN-01",
        "name": "Main Chart of Accounts",
        "txn_type": "GENERAL",
        "status": "ACTIVE"
      },
      "financialReportSections": null
    }
  ]
}

The query answers "message": null where most endpoints send ""; test code, never message.


Related

  • Accounting API — the generated inventory of this family’s etl-ep routes, where the eight chart-of-accounts routes are listed with ledgers and cashbooks. It lists paths only; the bodies, requirements and failure modes are here.
  • Ledger — the next thing to create; it references the account you just made
  • Data API — hosts, headers, paging, the response envelope and limits
Last updated on