Skip to content

Purchase Invoice

Purchase invoices are one of the document types served by BigLedger’s shared financial-document API. The document type is a path segment, and for purchase invoices it is internal-purchase-invoices.

Base path: https://api-etl.akaun.com/core2/tnt/dm/erp/gen-doc Path segment ({docType}): internal-purchase-invoices server_doc_type field value: INTERNAL_PURCHASE_INVOICE

See ERP Core API for authentication, the response envelope, and shared query parameters.

The path segment is not the same string as the server_doc_type field. The URL takes the lower-case, hyphenated, plural form (internal-purchase-invoices); the server_doc_type field inside the document takes the upper-case singular constant (INTERNAL_PURCHASE_INVOICE).

Using the upper-case form in the URL returns 404, which can read as “no such document” rather than “wrong path”. The response body varies by endpoint: query and get-by-guid return an empty body, while create and delete return {"code": "OK_NODATA", ...}. If a request 404s unexpectedly, check the path segment first.

Note also that GET /etl-ep/server-doc-types lists the field values, not the path segments, so it is not the list to copy URLs from. The table below has the mapping for the common types.

Everything on this page applies unchanged to payment vouchers and to every other document type: swap the {docType} segment.

Path segment ({docType})server_doc_type field value
internal-purchase-invoicesINTERNAL_PURCHASE_INVOICE
internal-payment-vouchersINTERNAL_PAYMENT_VOUCHER
internal-reimbursement-payment-vouchersINTERNAL_REIMBURSEMENT_PAYMENT_VOUCHER
internal-purchase-ordersINTERNAL_PURCHASE_ORDER
internal-purchase-returnsINTERNAL_PURCHASE_RETURN
internal-purchase-credit-notesINTERNAL_PURCHASE_CREDIT_NOTE
internal-purchase-debit-notesINTERNAL_PURCHASE_DEBIT_NOTE
internal-purchase-goods-received-notesINTERNAL_PURCHASE_GOODS_RECEIVED_NOTE
internal-receipt-vouchersINTERNAL_RECEIPT_VOUCHER
internal-sales-invoicesINTERNAL_SALES_INVOICE

A handful of older types use underscores rather than hyphens in the path segment, for example internal_purchase_grn_stock_in. If a hyphenated guess returns 404, try the underscore form before assuming the endpoint is missing.


Permissions

OperationPermission
CreateTNT_API_DOC_INTERNAL_PURCHASE_INVOICE_CREATE_TGT_GUID
ReadTNT_API_DOC_INTERNAL_PURCHASE_INVOICE_READ_TGT_GUID
UpdateTNT_API_DOC_INTERNAL_PURCHASE_INVOICE_UPDATE_TGT_GUID
DeleteTNT_API_DOC_INTERNAL_PURCHASE_INVOICE_DELETE_TGT_GUID
Document permissions are target-scoped. The _TGT_GUID suffix means the permission is granted against specific company, branch and store GUIDs, and is checked against the guid_comp, guid_branch, guid_store, guid_store_2 and delivery_branch_guid values on the document you are sending. A key whose owner holds the permission for one company cannot create invoices for another, and that is returned as a 403. If you get one, check the company and store GUIDs on the payload as well as the key’s permissions.

Endpoints

All of these already accept an access key. Substitute internal-purchase-invoices for {docType}.

Core CRUD

OperationPath (relative to the base path)
CreatePOST /{docType}/etl-ep
Create severalPOST /{docType}/etl-ep/multi
UpdatePUT /{docType}/etl-ep
DeleteDELETE /{docType}/etl-ep/{guid}
List allGET /{docType}/etl-ep
Get oneGET /{docType}/etl-ep/{guid}
QueryGET /{docType}/etl-ep/query
Query with a POST bodyPOST /{docType}/etl-ep/query
Query across all doc typesGET /etl-ep/query
List valid document typesGET /etl-ep/server-doc-types

Lifecycle

OperationPath
Set posting statusPUT /{docType}/etl-ep/update-posting-status/{guid}
Clear posting statusPUT /{docType}/set-posting-status-null/etl-ep/{guid}
VoidPUT /{docType}/etl-ep/void/{guid}
DiscardPUT /{docType}/discard/etl-ep/{guid}
PurgeDELETE /{docType}/purge/etl-ep/{guid}
Multi-document operationPOST /etl-ep/multi-doc

Reporting and files

OperationPath
Query snapshotGET /{docType}/etl-ep/query/snapshot
Query snapshot with a POST bodyPOST /{docType}/etl-ep/query/snapshot
Query by transaction typeGET /{docType}/etl-ep/type/query
Print to PDFGET /{docType}/etl-ep/print-jasper-pdf/{guid}
Batch printGET /{docType}/etl-ep/batch-print-jasper-pdf/{guids}
Batch print with a POST bodyPOST /{docType}/etl-ep/batch-print-jasper-pdf
Attach a filePUT /{docType}/etl-ep/add-files/{hdrGuid}
Replace a filePUT /{docType}/etl-ep/replace-file/{extGuid}
Get a fileGET /{docType}/etl-ep/file/{extGuid}
Delete a fileDELETE /{docType}/etl-ep/file/{extGuid}
UnbundleGET /{docType}/bundle/unwrapped/etl-ep/{guid}

Standard ETL endpoints

Higher-throughput variants intended for bulk import:

OperationPath
Create (standard)POST /standard/{docType}/etl-ep
Create, returning only the GUIDPOST /custom-prev/standard/{docType}/etl-ep
Create via JSON import (async)POST /custom/standard/{docType}/etl-ep
Check JSON import statusGET /custom/standard/{docType}/etl-ep/status/{guid}

The GenericDocumentContainer

{
  "bl_fi_generic_doc_hdr": { },
  "bl_fi_generic_doc_line": [ ],
  "bl_fi_generic_doc_ext": [ ],
  "bl_fi_generic_doc_link": [ ],
  "bl_fi_generic_doc_event": [ ],
  "bl_fi_generic_doc_budget_sub_line": [ ]
}

bl_fi_generic_doc_hdr and bl_fi_generic_doc_line are the two you need. The rest may be omitted or sent as [].

bl_fi_generic_doc_hdr: fields you are likely to need

The fields a purchase invoice uses.

FieldTypeOn createDescription
guidUUIDOptionalGenerated if omitted. Required on update.
guid_compUUIDRequiredCompany the invoice belongs to. Also a permission target.
guid_storeUUIDRequiredStore/location. Also a permission target.
guid_branchUUIDOptionalBranch. Also a permission target.
doc_entity_hdr_guidUUIDRequiredThe supplier being invoiced.
server_doc_typestringRequiredINTERNAL_PURCHASE_INVOICE, the upper-case constant. Required on the header: it is not inferred from the {docType} path segment, and omitting it fails with GENERIC_DOC_HDR_INVALID_SERVERDOCTYPE. Lines inherit it from the header.
amount_signumdecimalRequired-1 on a purchase invoice. A purchase invoice is money owed, so the sign is negative. Validated on the header only; sending 1 fails with GENERIC_DOC_INVALID_SIGNUM.
client_doc_typestringRecommendedYour classification of the document. Often the same as server_doc_type, but not always: an invoice raised from a goods-received note carries INTERNAL_PURCHASE_GOODS_RECEIVED_NOTE.
doc_source_typestringRecommendedWhere the document came from. Use INTERNAL for documents you create.
doc_ccystringRecommendedDocument currency, e.g. MYR.
date_txndatetimeRecommendedTransaction date. Defaults to now.
due_datedatetimeOptionalPayment due date.
doc_referencestringOptionalThe supplier’s invoice number.
doc_descstringOptionalShort description.
doc_remarksstringOptionalFree-text remarks.
doc_reference_tax_numstringOptionalTax invoice number.
doc_reference_tax_datedatetimeOptionalTax invoice date.
amount_stddecimalRecommendedGross amount before discount.
amount_discountdecimalOptionalTotal discount.
amount_netdecimalRecommendedNet amount after discount, before tax.
amount_tax_gstdecimalOptionalGST/SST amount.
amount_tax_whtdecimalOptionalWithholding tax amount.
amount_txndecimalRecommendedTotal payable.
amount_open_balancedecimalOptionalOutstanding balance. Maintained by the system as payments settle.
foreign_ccybooleanOptionalSet when the document is in a foreign currency.
base_doc_ccystringOptionalBase currency for a foreign-currency document.
base_doc_xratedecimalOptionalExchange rate to the base currency.
posting_statusstringOptionalDRAFT or FINAL. See the lifecycle section.
statusstringOptionalDefaults to ACTIVE.
revisionUUIDOptionalGenerated if omitted. Send the value you read back when updating.
client_keystringOptionalYour system’s key for this document.
client_sourcestringOptionalYour system’s name.
client_doc_1client_doc_5stringOptionalYour own document references.
client_valuestringOptionalFree-form value for your own use.
property_jsonobjectOptionalArbitrary extra properties.
credit_terms_jsonobjectOptionalCredit terms.
billing_jsonobjectOptionalBilling details.
server_doc_1server_doc_5stringServer-assignedRunning numbers generated by BigLedger. server_doc_1 is the document number you will recognise, and it stays null while the document is DRAFT: numbers are assigned when it is finalized.
code_company, code_branch, code_locationstringServer-maintainedCode equivalents of the company, branch and store GUIDs. Useful for filtering; do not rely on setting them.
arap_pns_amount, arap_stlm_amount, arap_doc_open, arap_bal, arap_contradecimalServer-maintainedAR/AP settlement tracking, updated as payment vouchers settle the invoice.
amount_internal_settlementdecimalServer-maintainedAmount already applied against this invoice.
doc_entity_hdr_json, delivery_entity_jsonobjectServer-maintainedSnapshots of the supplier and delivery entity at the time the document was written.
posting_inventory, posting_journal, posting_bundlestringServer-maintainedWhether each posting step has run.
pin_code, pin_type, pin_hash, pin_algorithmstringServer-assignedGenerated on create when no PIN is supplied. Do not set these.
created_date, updated_datedatetimeServer-assigned
created_by_subject_guid, updated_by_subject_guidUUIDServer-assignedSet from the access key’s owner.

Create fails with GENERIC_DOC_HDR_GUID_COMP_IS_NULL_OR_EMPTY or GENERIC_DOC_HDR_GUID_STORE_IS_NULL_OR_EMPTY when guid_comp or guid_store is missing.

bl_fi_generic_doc_line

FieldTypeOn createDescription
guidUUIDOptionalGenerated if omitted.
generic_doc_hdr_guidUUIDSet for youFilled in from the header.
item_guidUUIDRequiredThe item being purchased.
item_codestringRequiredThe item’s code.
quantity_basedecimalRequiredQuantity in the item’s base unit.
amount_stddecimalRequiredGross line amount before discount.
server_doc_typestringServer-filledInherited from the header.
amount_signumdecimalServer-filledForced to -1. Anything you send is discarded.
quantity_signumdecimalServer-filledForced to 1. Anything you send is discarded.
item_namestringRecommendedItem name as it should appear on the document.
item_descstringOptionalItem description.
item_remarksstringOptionalLine remarks.
uomstringOptionalUnit of measure.
qty_by_uomdecimalOptionalQuantity in that unit.
uom_to_base_ratiodecimalOptionalConversion factor to the base unit.
unit_price_by_uomdecimalOptionalUnit price in that unit.
amount_discountdecimalOptionalLine discount.
amount_netdecimalRecommendedLine net after discount, before tax.
amount_txndecimalRecommendedLine total.
tax_gst_code, tax_gst_type, tax_gst_rate, amount_tax_gststring / decimalOptionalGST/SST on the line.
tax_wht_code, tax_wht_type, tax_wht_rate, amount_tax_whtstring / decimalOptionalWithholding tax on the line.
guid_glcodeUUIDOptionalGL code to post this line to.
guid_comp, guid_branch, guid_storeUUIDOptionalDefault to the header’s values.
doc_ccystringOptionalLine currency. Defaults to the header’s.
statusstringOptionalDefaults to ACTIVE.
revisionUUIDOptionalGenerated if omitted.

Create fails with GENERIC_DOC_LINE_OBJECT_ITEM_GUID_IS_NULL_OR_EMPTY, ..._ITEM_CODE_IS_NULL_OR_EMPTY, ..._QUANTITY_BASE_IS_NULL_OR_EMPTY or ..._AMOUNT_STD_IS_NULL_OR_EMPTY when a required line field is missing.


Document lifecycle

posting_status controls whether the document has hit the ledgers:

ValueMeaning
DRAFTCreated but not posted. Freely editable.
FINALPosted. Journals, tax and AP balances are written.

Create the document as DRAFT, check it, then move it to FINAL. Once final, use void rather than update or delete: voiding writes the reversing entries, while deleting does not.

ActionWhat it does
DiscardMarks the document discarded. Reversible bookkeeping-wise; the record stays.
VoidReverses a finalized document. This is the correct way to cancel a posted invoice.
DeleteRemoves the document. Only appropriate for a draft that was never posted.
PurgePermanently removes the record and its history.

Create a purchase invoice

POST /core2/tnt/dm/erp/gen-doc/internal-purchase-invoices/etl-ep
curl -X POST "https://api-etl.akaun.com/core2/tnt/dm/erp/gen-doc/internal-purchase-invoices/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_generic_doc_hdr": {
      "server_doc_type": "INTERNAL_PURCHASE_INVOICE",
      "guid_comp": "3f2a7c10-9b4e-4d61-8a22-1c5e7f9d0b33",
      "guid_store": "6b8d1f42-7e35-4c09-ad81-1d4e8b2c5a70",
      "doc_entity_hdr_guid": "e7b2d48f-1c93-4a05-8e67-4f9a3b1d5c26",
      "doc_ccy": "MYR",
      "date_txn": "2026-09-14T00:00:00+08:00",
      "due_date": "2026-10-14T00:00:00+08:00",
      "doc_reference": "INV-2026-00187",
      "doc_desc": "Office stationery, September",
      "amount_std": 1000.00,
      "amount_discount": 0.00,
      "amount_net": 1000.00,
      "amount_tax_gst": 60.00,
      "amount_txn": 1060.00,
      "amount_signum": -1,
      "posting_status": "DRAFT",
      "status": "ACTIVE"
    },
    "bl_fi_generic_doc_line": [
      {
        "item_guid": "9c4a7e21-5d83-4b16-8f52-3a6e1c9b7d40",
        "item_code": "STN-A4-80",
        "item_name": "A4 Paper 80gsm, ream",
        "quantity_base": 40,
        "uom": "REAM",
        "qty_by_uom": 40,
        "uom_to_base_ratio": 1,
        "unit_price_by_uom": 25.00,
        "amount_std": 1000.00,
        "amount_discount": 0.00,
        "amount_net": 1000.00,
        "tax_gst_code": "SR",
        "tax_gst_rate": 6,
        "amount_tax_gst": 60.00,
        "amount_txn": 1060.00
      }
    ],
    "bl_fi_generic_doc_ext": [],
    "bl_fi_generic_doc_link": [],
    "bl_fi_generic_doc_event": []
  }'

Response: 200 OK with the created document. server_doc_1 carries the running number BigLedger assigned:

{
  "code": "OK_RESPONSE",
  "data": {
    "bl_fi_generic_doc_hdr": {
      "guid": "4d8b2f61-3a07-4e95-b12c-7f6a9d3e5c84",
      "server_doc_type": "INTERNAL_PURCHASE_INVOICE",
      "server_doc_1": "PI-2026-000042",
      "guid_comp": "3f2a7c10-9b4e-4d61-8a22-1c5e7f9d0b33",
      "doc_entity_hdr_guid": "e7b2d48f-1c93-4a05-8e67-4f9a3b1d5c26",
      "doc_reference": "INV-2026-00187",
      "doc_ccy": "MYR",
      "amount_txn": 1060.00,
      "amount_open_balance": 1060.00,
      "posting_status": "DRAFT",
      "status": "ACTIVE",
      "revision": "1e5c9a37-8b40-4d26-9f73-2a8e6c4b1d95",
      "created_date": "2026-09-14T09:30:00+08:00"
    },
    "bl_fi_generic_doc_line": [ ]
  },
  "message": ""
}

Keep the returned guid: payment vouchers settle against it.

Creating several at once

POST /{docType}/etl-ep/multi takes a JSON array of containers and creates them in one call. Use it for bulk import rather than looping over the single-create endpoint.


Update a purchase invoice

PUT /core2/tnt/dm/erp/gen-doc/internal-purchase-invoices/etl-ep

Send the whole container with guid and revision set. Only update documents still in DRAFT. Void and re-issue a finalized one.


Finalize a purchase invoice

PUT /core2/tnt/dm/erp/gen-doc/internal-purchase-invoices/etl-ep/update-posting-status/{guid}

The body is a small JSON object, not the whole document:

FieldTypeDescription
posting_statusstringDRAFT or FINAL.
validate_serial_signum_zeroboolean stringOptional. "true" to validate serial-number balance on posting. Defaults to false.
curl -X PUT "https://api-etl.akaun.com/core2/tnt/dm/erp/gen-doc/internal-purchase-invoices/etl-ep/update-posting-status/4d8b2f61-3a07-4e95-b12c-7f6a9d3e5c84" \
  -H "AccessId: YOUR_ACCESS_ID" \
  -H "AccessKey: YOUR_ACCESS_KEY" \
  -H "tenantCode: YOUR_TENANT_CODE" \
  -H "Content-Type: application/json" \
  -d '{"posting_status": "FINAL"}'

Void a purchase invoice

PUT /core2/tnt/dm/erp/gen-doc/internal-purchase-invoices/etl-ep/void/{guid}

Takes the same small JSON body as the posting-status endpoint.

curl -X PUT "https://api-etl.akaun.com/core2/tnt/dm/erp/gen-doc/internal-purchase-invoices/etl-ep/void/4d8b2f61-3a07-4e95-b12c-7f6a9d3e5c84" \
  -H "AccessId: YOUR_ACCESS_ID" \
  -H "AccessKey: YOUR_ACCESS_KEY" \
  -H "tenantCode: YOUR_TENANT_CODE" \
  -H "Content-Type: application/json" \
  -d '{}'

Delete, discard and purge

DELETE /core2/tnt/dm/erp/gen-doc/internal-purchase-invoices/etl-ep/{guid}
PUT    /core2/tnt/dm/erp/gen-doc/internal-purchase-invoices/discard/etl-ep/{guid}
DELETE /core2/tnt/dm/erp/gen-doc/internal-purchase-invoices/purge/etl-ep/{guid}

See the lifecycle table above for which one to reach for.


Get one purchase invoice

GET /core2/tnt/dm/erp/gen-doc/internal-purchase-invoices/etl-ep/{guid}

Query purchase invoices

GET /core2/tnt/dm/erp/gen-doc/internal-purchase-invoices/etl-ep/query

The same criteria can be sent as a JSON body to POST /{docType}/etl-ep/query when the filter is too long for a URL.

In addition to the shared query parameters:

ParameterTypeDescription
has_linebooleanInclude line rows in the response. Set this to true or you get headers only.
has_extbooleanInclude extension rows.
has_linkbooleanInclude document links.
has_eventbooleanInclude events.
has_attachmentbooleanInclude attachments.
guid_compUUIDFilter by company.
guid_branchUUIDFilter by branch.
guid_storestring (UUID)Filter by store.
doc_entity_hdr_guidUUIDFilter by supplier.
server_doc_1stringExact BigLedger document number.
client_doc_1stringExact client document number.
client_doc_1_likestringPartial client document number.
client_doc_1sstring setSeveral client document numbers. Repeat the parameter.
client_doc_2stringSecond client reference.
client_doc_typestringClient document type.
client_doc_typesstring setSeveral client document types. Repeat the parameter.
doc_source_typestringDocument source.
doc_descstringMatch on description.
hdr_doc_ccystringFilter by currency.
hdr_posting_statusstringDRAFT or FINAL.
arap_bal_rangestringFilter by outstanding balance range.
hdr_client_key, hdr_client_sourcestringFilter by your system’s identifiers.
code_company, code_branch, code_locationstringFilter by code instead of GUID.
contact_hdr_guid, contact_key_guid, member_guidUUIDContact and member filters.
file_batch_idstringFilter by import batch.
curl -G "https://api-etl.akaun.com/core2/tnt/dm/erp/gen-doc/internal-purchase-invoices/etl-ep/query" \
  -H "AccessId: YOUR_ACCESS_ID" \
  -H "AccessKey: YOUR_ACCESS_KEY" \
  -H "tenantCode: YOUR_TENANT_CODE" \
  --data-urlencode "doc_entity_hdr_guid=e7b2d48f-1c93-4a05-8e67-4f9a3b1d5c26" \
  --data-urlencode "hdr_posting_status=FINAL" \
  --data-urlencode "has_line=true" \
  --data-urlencode "limit=50" \
  --data-urlencode "calcTotalRecords=true"

Print a purchase invoice

GET /core2/tnt/dm/erp/gen-doc/internal-purchase-invoices/etl-ep/print-jasper-pdf/{guid}

Returns a PDF rather than the JSON envelope. GET .../etl-ep/batch-print-jasper-pdf/{guids} takes several GUIDs and returns a ZIP.

Last updated on