My App

Core Concepts

Key domain concepts for understanding the BizCARE Books e-invoicing API

Before integrating with the BizCARE Books e-Invoicing API, familiarize yourself with the core domain concepts that shape how e-invoicing works in Malaysia.

Company

A Company represents your business entity registered for e-invoicing with LHDN (Lembaga Hasil Dalam Negeri). Each user account has one company.

A company record stores:

  • TIN (Tax Identification Number) -- Your LHDN-issued tax ID (e.g., C20948240010)
  • Registration number -- Your SSM business registration number or personal identification number
  • Registration type -- One of BRN (Business Registration Number), NRIC (National ID), PASSPORT, or ARMY
  • LHDN credentials -- A clientId and clientSecret pair obtained from the MyInvois portal, used to authenticate document submissions with LHDN
  • Business details -- MSIC code, business activity description, SST registration number, address, and contact information

Your company must be fully set up before you can submit any invoices. Use GET /api/v1/companies and check the isCompanyReady flag to verify readiness.

The clientSecret is encrypted at rest using AES-256-GCM. Never share your LHDN credentials with third parties.

Invoice Types

BizCARE supports four invoice types, each serving a different purpose:

TypeDescriptionSubmittable
INVOICEStandard e-invoice issued by the supplier to the buyerYes
SELF_BILLED_INVOICEInvoice issued by the buyer on behalf of the supplierYes
PENDING_FINALIZE_INVOICEDraft invoice, not yet finalizedNo
PENDING_FINALIZE_SELF_BILLED_INVOICEDraft self-billed invoice, not yet finalizedNo

Draft types (PENDING_FINALIZE_*) are working documents that cannot be submitted to LHDN. Change the type to INVOICE or SELF_BILLED_INVOICE when the invoice is ready for submission.

Adjustment Notes

Adjustment notes are corrections applied to a Valid invoice. They must always reference a parent invoice.

TypePurpose
CREDIT_NOTEReduces the amount owed (e.g., partial return, discount applied after invoicing)
DEBIT_NOTEIncreases the amount owed (e.g., undercharged amount, additional charges)
REFUND_NOTERecords a full or partial refund against the original invoice

Each adjustment note has its own sequential code (separate from invoice codes) and contains line items describing the adjustment. To create an adjustment note, use POST /api/v1/invoices/:id/adjustment-note where :id is the parent invoice.

Consolidated Invoices

Consolidated invoices aggregate multiple transactions into a single LHDN submission. They are commonly used for:

  • Daily POS (Point of Sale) sales summaries
  • Batch processing of low-value transactions (under RM 10,000)
  • Transactions where buyer details are not available
TypeDescription
CONSOLIDATED_INVOICEAggregated standard invoice
CONSOLIDATED_SELF_BILLED_INVOICEAggregated self-billed invoice

Consolidation runs monthly on the server (see Monthly consolidation). Invoice responses carry isTotalExceedOrEqual10k so you can see which side of the RM 10,000 line an invoice falls on.

Document Lifecycle

Every invoice and adjustment note follows a defined lifecycle:

Draft --> Ready --> Submitted --> Valid / Invalid
                                    |        |
                                Cancelled  Resubmit
  1. Draft -- The document is created but not yet complete. The isReady flag is false.
  2. Ready -- All required fields are populated. The isReady flag is true. The document can now be submitted.
  3. Submitted -- The document has been sent to LHDN and is awaiting validation. LHDN typically validates within seconds to minutes.
  4. Valid -- LHDN has accepted the document. It is now a legally binding e-invoice. Valid documents can be cancelled by providing a cancellation reason.
  5. Invalid -- LHDN has rejected the document. The rejection reasons are available in the submitted document's failReason and failDetails fields. You can fix the issues and resubmit.

You can skip the two-step create-then-submit flow by passing submitImmediately: true when creating an invoice. This creates the invoice and submits it to LHDN in a single request.

Buyer and Supplier

Every invoice contains two party objects representing the transaction participants:

  • Supplier -- The party issuing the invoice. This is typically your company. The supplier object includes additional fields like msic (MSIC code), businessActivityDescription, and optionally bankAccount and exporterCertifiedNumber.
  • Buyer -- The party receiving the goods or services. Your customer.

Both parties require:

FieldDescription
nameLegal name of the business or individual
tinTax Identification Number
registrationTypeOne of BRN, NRIC, PASSPORT, ARMY
registrationNumberThe corresponding registration number
contactNumberPhone number
partyTypeOne of the values in Party types
addressObject with addressLine0, cityName, state (a state code), country, and optional postalZone
emailEmail address (optional)

When your company is set up, BizCARE can auto-populate the supplier (or buyer, for self-billed invoices) from your company profile.

Party types

partyTypeUse for
LOCAL_INDIVIDUALA person in Malaysia
LOCAL_EXEMPTED_ENTITYAn exempted entity in Malaysia
LOCAL_BUSINESS_AGENT_DEALER_DISTRIBUTORA business, agent, dealer or distributor in Malaysia
FOREIGNER_BUSINESSA business outside Malaysia
FOREIGNER_INDIVIDUALA person outside Malaysia

Malaysian state codes

address.state takes one of these LHDN codes:

CodeState
01Johor
02Kedah
03Kelantan
04Melaka
05Negeri Sembilan
06Pahang
07Pulau Pinang
08Perak
09Perlis
10Selangor
11Terengganu
12Sabah
13Sarawak
14Wilayah Persekutuan Kuala Lumpur
15Wilayah Persekutuan Labuan
16Wilayah Persekutuan Putrajaya
17Not Applicable

Issue dates

invoiceDateTime.date (invoices) and adjustmentNoteIssueDate (adjustment notes) must be today or up to 3 days back on the Malaysian calendar. A future date is always refused. An older date fails with 400 VALIDATION_ERROR ("Issue date must be today or within the last 3 days, and cannot be in the future."). The examples in these docs use <today, YYYY-MM-DD> for this reason. Replace it with a real date in that window.

invoiceDateTime.time with a zone marker (14:30:00Z) is that exact instant. Without a marker (14:30:00) it is read as Malaysian time.

Line Items

Line items represent individual goods or services on an invoice. Each line item contains:

FieldDescription
idA unique identifier for the line item within the invoice
descriptionDescription of the good or service
unit.countQuantity
unit.priceUnit price in MYR (or the invoice currency)
unit.codeUnit of measure code (optional, e.g., "EA" for each)
taxDetailsArray of tax entries, each with taxType and taxRate
classificationsProduct classification codes (optional)
allowanceChargesLine-level discounts or surcharges (optional)
taxExemptionTax exemption details if applicable (optional)

Tax Details

Each line item must specify at least one tax detail entry:

{
  "taxType": "01",
  "taxRate": {
    "percentage": 10
  }
}

The taxRate object supports either percentage (e.g., 10 for 10%) or ratePerUnit (a fixed amount per unit), depending on the tax type.

Tax Types

Malaysia's e-invoicing system uses the following tax type codes:

CodeDescription
01Sales Tax
02Service Tax
03Tourism Tax
04High-Value Goods Tax
05Sales Tax on Low Value Goods
06Not Applicable
ETax Exempt

Most businesses use tax type 01 (Sales Tax) or 02 (Service Tax). Use 06 for zero-rated or out-of-scope items, and E for items that are specifically exempt from tax.

LHDN Document Statuses

After submission to LHDN, each document is tracked with one of four statuses:

StatusDescription
SubmittedThe document has been sent to LHDN and is pending validation
ValidLHDN has accepted the document as a valid e-invoice
InvalidLHDN has rejected the document -- check failReason and failDetails for specifics
CancelledThe document was previously valid but has been cancelled by the issuer with a stated reason

BizCARE automatically polls LHDN for status updates after submission (every 60 seconds while LHDN reports "in progress", then a half-hourly sweep for anything still Submitted after 10 minutes), and pushes changes to your webhooks. You can check the current status at any time: the latestSubmission object on GET /api/v1/invoices/:id carries it, and GET /api/v1/invoices/:id/submitted-documents gives the full history. POST /api/v1/submitted-documents/sync-status forces an immediate re-check.

When a document is marked Invalid, the failDetails field contains the LHDN validation errors in a structured format, allowing you to identify and fix the issue before resubmitting.

On this page