Build a MyInvois E-Invoice (UBL JSON)
Skill: Convert invoice data into an LHDN MyInvois UBL 2.1 JSON e-invoice
Region: Malaysia
Category: E-Invoicing — MyInvois (LHDN / Inland Revenue Board of Malaysia)
Does: Takes invoice data and produces a MyInvois e-invoice as a UBL 2.1 document in JSON — the LHDN UBL-in-JSON structure (Invoice array, _D/_A/_B namespace keys, _-wrapped values) submitted to the MyInvois API for validation, mapping supplier/buyer identification, line items, classification and tax to the IRBM data model.
Standard: LHDN e-Invoice (MyInvois) — UBL 2.1 in JSON, e-Invoice version 1.1; submitted to the MyInvois System API and returned with a validated Unique Identifier Number (UUID) and QR validation link.
The artifact is a UBL JSON document submitted to the MyInvois API (or via a Peppol PINT MY route); LHDN validates it, assigns a UUID, and returns a QR validation link to embed on the visual invoice. A submitted invoice can be cancelled by the supplier (or rejected by the buyer) only within 72 hours of validation; after that a credit/debit note is required. The document must carry a digital signature (
UBL Extensionswithds:Signature) except where exempt. Tax type codes, classification codes, MSIC codes and mandatory-rollout dates change; validate against the current LHDN SDK before submitting.
When this applies
- A Malaysian business issues an e-invoice for a B2B, B2G, or B2C transaction under the LHDN MyInvois mandate (phased rollout by annual turnover from 2024 onward; smaller taxpayers phased in through 2025–2026).
- Use type 01 (Invoice) for an ordinary sale, 02 (Credit Note) / 03 (Debit Note) for adjustments, 04 (Refund Note) for refunds, and the 11–14 self-billed variants when the buyer issues on the supplier's behalf.
- For B2C sales where the buyer does not need an e-invoice, the supplier issues a normalised receipt and submits a consolidated e-invoice (aggregating receipts) within 7 days after month-end.
- Excluded: transactions outside the mandate scope and persons not yet in their rollout phase (still issue normal invoices/receipts).
Conversion procedure
- Read the source. Accept the invoice as CSV/JSON/PDF text or pasted fields. Parse line items, parties, and totals directly; OCR/
pdftotexta scanned invoice first. - Identify both parties. Capture the supplier and buyer TIN plus a second ID — BRN (business registration), NRIC (individual), PASSPORT, or ARMY — and the supplier SST registration number and MSIC business code. For B2C consolidation, use the general public buyer TIN
EI00000000010. - Set the document type and currency. Pick the
InvoiceTypeCode(01–14), issue date/time in UTC, and the document currency (MYRby default; add a currency exchange rate if foreign). - Build each line. For every
InvoiceLine: quantity, unit price, line extension amount, the item classification code, description, and the tax sub-total (tax type + rate + amount). - Compute taxes and totals. Sum line extension amounts; compute tax per
TaxSubtotal; buildLegalMonetaryTotal(tax-exclusive, tax-inclusive, payable). - Wrap in UBL JSON. Emit the
Invoicearray with the_D/_A/_Bnamespace keys, value objects under_, and identifiers withschemeID/schemeAgencyID. Attach theUBLExtensionsdigital signature. - Validate. Run the checklist; the API returns a UUID + QR link on success.
Source → MyInvois (UBL JSON) field map
| From the source | → Target path (UBL JSON) |
|---|---|
| Invoice number | Invoice[0].ID[0]._ |
| Invoice type (01–14) | InvoiceTypeCode[0]._ (+ listVersionID = 1.1) |
| Issue date (UTC) | IssueDate[0]._ (yyyy-mm-dd) |
| Issue time (UTC) | IssueTime[0]._ (hh:mm:ssZ) |
| Document currency | DocumentCurrencyCode[0]._ |
| Supplier TIN | AccountingSupplierParty…PartyIdentification with schemeID="TIN" |
| Supplier BRN | …PartyIdentification with schemeID="BRN" |
| Supplier SST number | …PartyIdentification with schemeID="SST" |
| Supplier MSIC code | AccountingSupplierParty…PartyLegalEntity… / IndustryClassificationCode |
| Supplier name / address | …Party.PartyLegalEntity[0].RegistrationName, PostalAddress |
| Buyer TIN + ID | AccountingCustomerParty…PartyIdentification (TIN + BRN/NRIC/PASSPORT) |
| Line item description | InvoiceLine[i].Item[0].Description[0]._ |
| Item classification code | Item[0].CommodityClassification[0].ItemClassificationCode |
| Quantity / unit | InvoiceLine[i].InvoicedQuantity[0] |
| Unit price | InvoiceLine[i].Price[0].PriceAmount |
| Line amount | InvoiceLine[i].LineExtensionAmount |
| Line tax type + rate + amount | InvoiceLine[i].TaxTotal[0].TaxSubtotal[0] |
| Total excluding tax | LegalMonetaryTotal[0].TaxExclusiveAmount |
| Total including tax | LegalMonetaryTotal[0].TaxInclusiveAmount |
| Amount payable | LegalMonetaryTotal[0].PayableAmount |
| Total tax | TaxTotal[0].TaxAmount |
Document structure
{ "_D": ".../Invoice-2", "_A": ".../CommonAggregateComponents-2",
"_B": ".../CommonBasicComponents-2",
"Invoice": [ {
"ID", "IssueDate", "IssueTime",
"InvoiceTypeCode" (01–14, + listVersionID 1.1),
"DocumentCurrencyCode",
"UBLExtensions" (digital signature — ds:Signature),
"AccountingSupplierParty" (TIN + BRN/SST + MSIC + name/address),
"AccountingCustomerParty" (TIN + BRN/NRIC/PASSPORT + name/address),
"InvoiceLine": [ {
"ID", "InvoicedQuantity", "LineExtensionAmount",
"TaxTotal" → "TaxSubtotal" (TaxableAmount, TaxAmount, TaxCategory),
"Item" (Description, CommodityClassification → ItemClassificationCode),
"Price" (PriceAmount)
} ],
"TaxTotal" (TaxAmount + TaxSubtotal per tax type),
"LegalMonetaryTotal" (TaxExclusiveAmount, TaxInclusiveAmount, PayableAmount)
} ]
}
Every leaf value is an array of objects; the scalar sits under "_", and identifiers add schemeID/schemeAgencyID siblings. Mandatory blocks: ID, dates, type code, both parties (each with TIN), at least one line, TaxTotal, and LegalMonetaryTotal.
Code tables
InvoiceTypeCode (e-Invoice type)
| Code | Meaning |
|---|---|
01 |
Invoice |
02 |
Credit Note |
03 |
Debit Note |
04 |
Refund Note |
11 |
Self-billed Invoice |
12 |
Self-billed Credit Note |
13 |
Self-billed Debit Note |
14 |
Self-billed Refund Note |
Tax type (TaxCategory.ID)
| Code | Meaning |
|---|---|
01 |
Sales Tax |
02 |
Service Tax |
03 |
Tourism Tax |
04 |
High-Value Goods Tax |
05 |
Sales Tax on Low Value Goods |
06 |
Not Applicable |
E |
Tax exemption (with exemption reason) |
Party identification schemeID
| Scheme | Meaning |
|---|---|
TIN |
Tax Identification Number (mandatory both parties) |
BRN |
Business Registration Number |
NRIC |
National Registration Identity Card (individuals) |
PASSPORT |
Passport number (foreign individuals) |
SST |
Sales & Service Tax registration number |
The general-public buyer TIN for consolidated B2C e-invoices is EI00000000010.
Calculation rules
- Line extension amount = quantity × unit price, rounded to 2 decimals.
- Line tax amount = taxable amount × tax rate (e.g. Service Tax 8%, Sales Tax 10%), rounded to 2 decimals; tax type
06/Ecarry a 0 tax amount. TaxTotal.TaxAmount= Σ of lineTaxSubtotaltax amounts.TaxExclusiveAmount= Σ line extension amounts.TaxInclusiveAmount= TaxExclusiveAmount + total tax.PayableAmount= TaxInclusiveAmount − any prepaid amount − rounding adjustment.- Amounts use a dot decimal, 2 decimals, with
currencyIDon each monetary value. Always recompute totals from the lines; never blindly copy a printed total — flag any mismatch with the source.
Worked example (end-to-end)
Supplier ABC Trading Sdn. Bhd., TIN C12345678901, BRN 201901234567, SST A01-2345-67891012, MSIC 46900, in Kuala Lumpur. Buyer XYZ Retail Sdn. Bhd., TIN C98765432109, BRN 202001234568. Invoice INV-2026-0001, issued 2026-06-13 08:00:00Z, currency MYR. One line: consulting service, qty 1, unit price RM 1,000.00, Service Tax (type 02) at 8% → RM 80.00. Totals: tax-exclusive 1,000.00, tax 80.00, tax-inclusive/payable 1,080.00.
{
"_D": "urn:oasis:names:specification:ubl:schema:xsd:Invoice-2",
"_A": "urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2",
"_B": "urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2",
"Invoice": [
{
"ID": [{ "_": "INV-2026-0001" }],
"IssueDate": [{ "_": "2026-06-13" }],
"IssueTime": [{ "_": "08:00:00Z" }],
"InvoiceTypeCode": [{ "_": "01", "listVersionID": "1.1" }],
"DocumentCurrencyCode": [{ "_": "MYR" }],
"AccountingSupplierParty": [
{
"Party": [
{
"IndustryClassificationCode": [{ "_": "46900", "name": "Wholesale trade" }],
"PartyIdentification": [
{ "ID": [{ "_": "C12345678901", "schemeID": "TIN" }] },
{ "ID": [{ "_": "201901234567", "schemeID": "BRN" }] },
{ "ID": [{ "_": "A01-2345-67891012", "schemeID": "SST" }] }
],
"PartyLegalEntity": [{ "RegistrationName": [{ "_": "ABC Trading Sdn. Bhd." }] }],
"PostalAddress": [
{
"CityName": [{ "_": "Kuala Lumpur" }],
"PostalZone": [{ "_": "50480" }],
"CountrySubentityCode": [{ "_": "14" }],
"Country": [{ "IdentificationCode": [{ "_": "MYS", "schemeID": "ISO3166-1" }] }]
}
]
}
]
}
],
"AccountingCustomerParty": [
{
"Party": [
{
"PartyIdentification": [
{ "ID": [{ "_": "C98765432109", "schemeID": "TIN" }] },
{ "ID": [{ "_": "202001234568", "schemeID": "BRN" }] }
],
"PartyLegalEntity": [{ "RegistrationName": [{ "_": "XYZ Retail Sdn. Bhd." }] }],
"PostalAddress": [
{
"CityName": [{ "_": "Petaling Jaya" }],
"PostalZone": [{ "_": "47800" }],
"CountrySubentityCode": [{ "_": "10" }],
"Country": [{ "IdentificationCode": [{ "_": "MYS", "schemeID": "ISO3166-1" }] }]
}
]
}
]
}
],
"InvoiceLine": [
{
"ID": [{ "_": "1" }],
"InvoicedQuantity": [{ "_": 1, "unitCode": "C62" }],
"LineExtensionAmount": [{ "_": 1000.0, "currencyID": "MYR" }],
"TaxTotal": [
{
"TaxAmount": [{ "_": 80.0, "currencyID": "MYR" }],
"TaxSubtotal": [
{
"TaxableAmount": [{ "_": 1000.0, "currencyID": "MYR" }],
"TaxAmount": [{ "_": 80.0, "currencyID": "MYR" }],
"TaxCategory": [
{
"ID": [{ "_": "02" }],
"Percent": [{ "_": 8.0 }],
"TaxScheme": [{ "ID": [{ "_": "OTH", "schemeID": "UN/ECE 5153", "schemeAgencyID": "6" }] }]
}
]
}
]
}
],
"Item": [
{
"Description": [{ "_": "Consulting service" }],
"CommodityClassification": [
{ "ItemClassificationCode": [{ "_": "022", "listID": "CLASS" }] }
]
}
],
"Price": [{ "PriceAmount": [{ "_": 1000.0, "currencyID": "MYR" }] }]
}
],
"TaxTotal": [
{
"TaxAmount": [{ "_": 80.0, "currencyID": "MYR" }],
"TaxSubtotal": [
{
"TaxableAmount": [{ "_": 1000.0, "currencyID": "MYR" }],
"TaxAmount": [{ "_": 80.0, "currencyID": "MYR" }],
"TaxCategory": [
{
"ID": [{ "_": "02" }],
"Percent": [{ "_": 8.0 }],
"TaxScheme": [{ "ID": [{ "_": "OTH", "schemeID": "UN/ECE 5153", "schemeAgencyID": "6" }] }]
}
]
}
]
}
],
"LegalMonetaryTotal": [
{
"TaxExclusiveAmount": [{ "_": 1000.0, "currencyID": "MYR" }],
"TaxInclusiveAmount": [{ "_": 1080.0, "currencyID": "MYR" }],
"PayableAmount": [{ "_": 1080.0, "currencyID": "MYR" }]
}
]
}
]
}
Normalisations shown: type 01 with listVersionID 1.1; date/time in UTC (2026-06-13, 08:00:00Z); Service Tax recomputed 8% × 1000.00 = 80.00; TaxInclusiveAmount/PayableAmount recomputed 1000.00 + 80.00 = 1080.00; both parties carry a TIN identification. After this passes the MyInvois API it returns a UUID and a QR validation link to print on the visual invoice. (The UBLExtensions digital signature block is omitted here for brevity and must be added before submission.)
Validation checklist
- All required fields extracted; AI asked about anything missing or ambiguous (no invented TINs, BRNs, or amounts)
- UBL JSON shape correct:
_D/_A/_Bnamespace keys, every value an array of{ "_": … }objects, identifiers carryschemeID -
InvoiceTypeCodeis a valid 01–14 code withlistVersionID1.1; issue date/time in UTC - Supplier and buyer each carry a TIN, plus the correct second ID (BRN/NRIC/PASSPORT); supplier SST + MSIC present
- Consolidated B2C invoices use buyer TIN
EI00000000010and aggregate within 7 days of month-end - Each line has a classification code; tax type code valid (01/02/06/E…) with the correct rate
-
TaxTotal.TaxAmount= Σ line tax;TaxInclusiveAmount= TaxExclusiveAmount + total tax;PayableAmountcorrect - Monetary values carry
currencyID; amounts recomputed from lines (mismatches flagged) -
UBLExtensionsdigital signature attached (unless exempt) - JSON strictly valid and validated against the current LHDN MyInvois SDK before submission; cancellation/rejection only within 72 hours
Last updated: 2026-06-13 — verify the current LHDN MyInvois SDK (UBL JSON structure, type/tax/classification code lists, MSIC codes, mandatory rollout dates, and the 72-hour cancellation window) before use.