Quick Start

This example demonstrates authentication, a sale-invoice upload, and a status lookup. Replace every placeholder and use approved test data.

1. Request a token

curl --request POST "{token_url}" \
  --header "Content-Type: application/x-www-form-urlencoded" \
  --data-urlencode "grant_type=client_credentials" \
  --data-urlencode "client_id={client_id}" \
  --data-urlencode "client_secret={client_secret}"

Store the returned access_token securely.

2. Check connectivity

curl --request GET "{api_base_url}/version/" \
  --header "Authorization: Bearer {access_token}" \
  --header "Accept: application/json"

3. Submit an invoice

Save a validated AECloud invoice payload as invoice.json, then send the file as the raw JSON body:

curl --request POST "{api_base_url}/sale/invoice_submission" \
  --header "Authorization: Bearer {access_token}" \
  --header "Content-Type: application/json" \
  --header "Accept: application/json" \
  --data-binary "@invoice.json"

Do not send this:

{
  "body_text": "..."
}

The submission handler reads the entire HTTP body as the business document.

4. Check the response

Inspect the body for:

  • overall_status;
  • the initial validation result;
  • sale_id and sale_guid;
  • whether processing is immediate or scheduled;
  • LHDN_submission_uid, when available;
  • LHDN_accepted_uuid, when available; and
  • the recorded submission or document status.

Store sale_guid against the POS or ERP document. A 2xx HTTP response alone is not sufficient because a business-level failure can be described inside the JSON body.

5. Query by sale GUID

curl --request GET "{api_base_url}/sale/invoice_checkstatus/by_guid" \
  --header "Authorization: Bearer {access_token}" \
  --header "Accept: application/json" \
  --header "sale_guid: {sale_guid}"

The sale_guid is an HTTP header for this endpoint, not a path segment or query parameter.

Continue status reconciliation until the document reaches the terminal outcome required by your business process. See Status and reconciliation.