ERP Core API
The ERP Core APIs cover the master data and financial documents most external integrations need: ledgers, the chart of accounts, cashbooks, suppliers, purchase invoices and payment vouchers.
This reference assumes you have read Integration → Getting Started and have an access key. Authentication covers credentials and their error codes; Data API covers hosts, envelopes, shared query parameters and limits. Everything below is what is specific to these six resources.
Available Sections
- Chart of Accounts: the account structure everything else hangs off. Create these first.
- Ledger: ledgers per company, primary or secondary.
- Cashbook: bank and cash accounts, linked to a GL code.
- Supplier: suppliers and the other business entity types.
- Purchase Invoice:
docTypeinternal-purchase-invoices. - Payment Voucher:
docTypeinternal-payment-vouchers.
Master data must exist before documents can reference it, so the order above is also the order to build in: chart of accounts, then ledgers and cashbooks, then suppliers, then purchase invoices, then the payment vouchers that settle them.
Which endpoint to call
Each resource exposes the same operations more than once, under different path suffixes. The suffix does not decide which credential is accepted: every suffix accepts either an access key or a bearer token. What the suffix decides is which permission set is checked, and which shape of caller the endpoint was designed for.
| Suffix | Designed for | Credentials accepted |
|---|---|---|
/etl-ep | Server-to-server integration. Start here. | Access key, or bearer token |
/backoffice-ep, or no suffix | A signed-in back-office user session | Bearer token, or access key |
/login-entity-ep | A customer or supplier acting on their own records | Bearer token |
The two paths differ only in which credential they try first. /etl-ep endpoints check the access key first and fall back to the bearer token. The plain and /backoffice-ep endpoints read the Authorization header first and, when there is no token at all, fall back to the access key.
/backoffice-ep endpoint, an Authorization header that is present but invalid fails immediately with CLIENT_AUTH_INVALID_TOKEN and your access key is never tried. Omit the header entirely when authenticating with a key.Prefer /etl-ep anyway: it is the endpoint family intended for integrations, it is the one BigLedger’s own data pipelines use, and on some resources it carries a different permission set from /backoffice-ep (cashbook is the clearest example, see its page).
Every request needs tenantCode alongside the credential. Base paths and per-operation paths are on each page.
How this section relates to the generated module references
The module references are generated from the backend’s route table, so they
list every etl-ep route and describe no behaviour. The six pages here are hand-written and verified against
the live API, so they carry the bodies, field meanings, lifecycle and failure modes. Use the generated page to
find out what exists and the page here when you are about to write the call;
the two layers explains why a
route missing from a generated page is not a route your key is refused.
Redacted records
A list or query endpoint returns every row matching your filter, including rows you lack permission to read. Those come back carrying only their guid and status: "PERMISSION_DENIED". Every other field is stripped.
This is not an error and carries no error code. Check status before using a record, so a redacted row is not read as a record with empty fields.
This applies to ledger and chart-of-accounts lists and queries, and to the cashbook list, spelt Permission Denied. The cashbook query instead refuses the whole call.
Choosing a filter
Filter on the named fields documented on each page: code, name, name_like, code_like and the GUID filters. These are the ones applied on these resources.
The general-purpose search_word parameter, and cashbook’s keyword, are not applied here. A request using either returns the unfiltered result set, so use the named fields instead. As a habit, confirm that a new filter changes the result count before relying on it.
Status values
status on these records is one of ACTIVE, INACTIVE, DRAFT, PENDING, PROCESSING, DONE, DISCARDED, ARCHIVED, DELETED, FAILED, TEMP.
PERMISSION_DENIED is a response-only marker, as above. Never send it in a request.
Documents carry a second, independent field, posting_status, DRAFT or FINAL; Finalise queues the ledger posting, it does not wait for it. See Purchase Invoice.
Errors from the ERP layer
Authentication lists the credential failures. Once a request is authenticated, these are what the ERP endpoints return.
| HTTP | Code | Meaning |
|---|---|---|
| 400 | EXCEPTION_INCONSISTENT_DATA | Validation failure. data carries the per-field errors. See below. |
| 403 | CLIENT_AUTH_USER_NOT_AUTHORIZED | Authenticated, but the key’s owner lacks the required permission. |
| 404 | CLIENT_VALIDATION_GUID_DOES_NOT_EXIST | No record with that GUID. |
| 417 | SERVER_GENERAL_UNKNOWN_ERROR | Unhandled server error. |
A missing or unrecognised tenantCode returns a tenant error rather than a credential error, so check that header first when a request fails for no obvious reason.
Validation failures
A rejected write returns 400 with code set to EXCEPTION_INCONSISTENT_DATA and data as an array of per-field errors, not the usual single object:
{
"code": "EXCEPTION_INCONSISTENT_DATA",
"message": null,
"data": [
{
"errorCode": "API_TNT_DM_ERP_FI_MST_LEDGER_HDR_OBJECT_OBJ_TYPE_IS_NULL_OR_EMPTY",
"shortMessage": "The obj_type field in the com.bigledger.core2.dal.table.bl_fi_mst_ledger_hdr object is empty",
"longMessage": "The obj_type field in the com.bigledger.core2.dal.table.bl_fi_mst_ledger_hdr object is empty",
"targetedObject": { }
}
]
}errorCode names the table and column at fault, and targetedObject echoes the record you sent, with any server-filled defaults already applied. Read errorCode rather than parsing the message text.
guid on an update. Without it the request is rejected before the field checks run, so it returns 417 rather than the 400 envelope above. A 417 whose message mentions getGuid() means the guid is missing from the body.Two resources deviate, and both are called out on their own pages: cashbook returns 400 with CLIENT_CASHBOOK_NOT_FOUND where the others return 404, and the document endpoints check permissions against the company and store GUIDs on the payload you send, so a valid key can still be refused.