Skip to main content

Malaysia MyInvois (LHDN) E-Invoicing

The ECOSIRE Malaysia MyInvois module connects Odoo's account.move (invoices, credit notes, debit notes) to the MyInvois Centralised CTC e-invoicing platform operated by LHDN / IRBM (Lembaga Hasil Dalam Negeri Malaysia -- Inland Revenue Board of Malaysia). Malaysia's e-invoicing model is a Direct Government REST API: your ERP builds a digitally-signed UBL 2.1 (MY) document and submits it straight to LHDN. LHDN validates, stamps a UUID + longId + QR URL, archives the document, and notifies the buyer. No mandatory ASP or clearance intermediary sits in the path.

Compatibility: Odoo 17 / 18 / 19 Price: $399 (one-time) License: LGPL-3

Mandatory compliance timeline

Malaysia phased its e-invoice mandate by annual turnover: Phase 1 (August 2024, turnover > MYR 100M), Phase 2 (January 2025, MYR 25M -- MYR 100M), Phase 3 (July 2025 onwards, all remaining taxpayers). Verify current enforcement status and any grace periods against the latest LHDN circulars at hasil.gov.my.

Key Features

  • OAuth 2.0 Client Credentials authentication (taxpayer and intermediary on-behalf-of modes)
  • UBL 2.1 (MY) document builder: Invoice, Credit Note, Debit Note, Refund Note (types 01--04)
  • Self-billed invoice types 11--14 (foreign vendor payments, agent disbursements, imports)
  • Batch document submission -- up to 100 documents per API call
  • Async status polling via ir.cron (polls submission UID until cleared or rejected)
  • Cancel action (issuer, 72-hour window from LHDN validation)
  • Reject action (buyer, 72-hour window from invoice issuance)
  • Consolidated B2C monthly invoice (General Public TIN EI00000000010)
  • TIN / BRN / NRIC / Passport validation against LHDN registry
  • MSIC code and SST registration fields on company record
  • LHDN QR URL renderer -- renders the stamped URL returned by LHDN, never self-generated
  • Submission state machine with full per-call audit log
  • Notification poller that surfaces buyer rejections into the invoice chatter
  • Config-driven API hosts (sandbox preprod vs production) -- no hardcoded URLs or secrets

Prerequisites

  • Odoo 17, 18, or 19 (Community or Enterprise edition)
  • ecosire_einvoice_core (the ECOSIRE e-invoicing engine -- installed automatically as a dependency)
  • An active ECOSIRE license for ecosire_einvoice_my
  • A registered taxpayer TIN issued by LHDN
  • MyInvois Portal access to register your ERP system and obtain sandbox/production credentials
  • A digital certificate from an LHDN-accepted Certificate Authority (required for document signing -- see the Digital Signing note below)

Installation

  1. Download the module ZIP from your ECOSIRE Dashboard
  2. Extract to your Odoo addons directory:
    unzip ecosire-einvoice-my-*.zip -d /opt/odoo/addons/
  3. Restart the Odoo service:
    sudo systemctl restart odoo
  4. Navigate to Apps, click Update Apps List
  5. Search for "ECOSIRE E-Invoicing | Malaysia MyInvois" and click Install
  6. Activate your ECOSIRE license when prompted (see Configuration below)

Configuration

Step 1: Activate your ECOSIRE License

  1. Navigate to Settings > ECOSIRE License
  2. Enter the license key provided after purchase
  3. Click Activate -- the module will verify the key against the ECOSIRE licensing server

Step 2: Register your ERP System in the MyInvois Portal

Before configuring Odoo, you must obtain API credentials from LHDN:

  1. Log in to the MyInvois Portal (preprod: preprod.myinvois.hasil.gov.my; production: myinvois.hasil.gov.my)
  2. Navigate to the ERP System Registration section
  3. Register your Odoo instance to receive a Client ID and Client Secret
  4. For intermediary mode: grant the intermediary's Client ID the required API permissions in the portal and note the taxpayer TIN (and ROB number if applicable) for the on-behalf-of header
Sandbox first

Begin with the LHDN preprod (sandbox) environment. Sandbox credentials are separate from production. Obtain sandbox credentials from the LHDN portal sandbox registration process and verify the full submission flow before switching to production mode.

Step 3: Configure Company Identity (LHDN Mandatory Fields)

  1. Navigate to Settings > Companies > your company
  2. Open the MyInvois tab and fill in:
    • MyInvois TIN (myinvois_tin) -- LHDN-issued Tax Identification Number (11--14 alphanumeric characters)
    • Business Registration No. (BRN) (myinvois_brn) -- SSM-issued Business Registration Number
    • SST Registration No. (myinvois_sst_id) -- Sales & Service Tax number; enter NA if not SST-registered
    • MSIC Code (myinvois_msic_code) -- Malaysia Standard Industrial Classification (5-digit code)
    • Business Activity Description (myinvois_activity_desc) -- free-text description of your main business activity

Step 4: Configure the MyInvois Connection

  1. Navigate to Accounting > MyInvois > Configuration
  2. Set Environment to Sandbox (preprod) while testing, then Production for live submission
  3. The API and token base URLs are pre-filled with the LHDN defaults -- adjust only if LHDN changes its hostnames
  4. Enter your Client ID (client_id) and Client Secret (client_secret) from the portal
  5. Leave Scope as InvoicingAPI (the LHDN default)
  6. For intermediary mode: tick Intermediary Mode and enter the taxpayer TIN (or TIN:ROB) in the On-Behalf-Of field
  7. Click Test Connection -- this exercises the CONFIRMED OAuth 2.0 token endpoint (POST /connect/token) and displays OK (token acquired) on success

Step 5: Verify Sandbox and Enable Live Transmission

The module gates all document endpoints behind a Sandbox Verified flag. These endpoints are implemented from LHDN published documentation and must be confirmed against the LHDN preprod sandbox before enabling production submissions:

  1. Submit test documents in the preprod environment using the Submit to MyInvois action on a test invoice
  2. Confirm the full cycle: submission accepted, UUID returned, status polled to Valid
  3. Once the sandbox handshake succeeds, tick Sandbox Verified in the configuration record
  4. Switch Environment to Production only after the sandbox cycle completes cleanly
Digital signing prerequisite

Document signing (XAdES-ENVELOPED over UBL 2.1 XML) is required by LHDN. This module provides the signing infrastructure but raises a clear error until you supply a valid taxpayer digital certificate from an LHDN-accepted Certificate Authority (MSC Trustgate, Telekom Malaysia / DigiCert, MIMOS). Obtain the certificate through the MyInvois Portal and configure it under Accounting > MyInvois > Configuration before live submission. The exact canonicalization form and certificate authority list should be verified against the current LHDN SDK at sdk.myinvois.hasil.gov.my.

Usage

Submitting an Invoice

  1. Confirm an invoice (account.move) in Odoo as you normally would
  2. Open the validated invoice and click Submit to MyInvois
  3. The module builds the UBL 2.1 (MY) XML, computes the SHA-256 hash, Base64-encodes it, and POSTs to /api/v1.0/documentsubmissions
  4. A myinvois.submission record is created with state Submitted and the LHDN submissionUid
  5. The ir.cron poller checks the submission status (via GET /api/v1.0/documentsubmissions/{submissionUid}) until LHDN returns Valid, Invalid, or Partially Valid
  6. On success the invoice record is updated with the LHDN Document UUID, Long ID, and QR URL

Batch Submission

For high-volume scenarios, multiple confirmed invoices can be batched:

  1. From the invoice list, select the invoices to submit
  2. Use Action > Submit to MyInvois (Batch)
  3. Up to 100 documents are sent per API call; larger selections are automatically split into batches
  4. Monitor progress in Accounting > MyInvois > Submissions

Consolidated B2C Invoice

For B2C transactions below the LHDN threshold (currently reported as MYR 500 per transaction -- verify the current threshold in LHDN circulars):

  1. Navigate to Accounting > MyInvois > Consolidated Invoice
  2. Select the month and the B2C invoices to consolidate
  3. The module generates a single Invoice (type 01) addressed to the General Public TIN EI00000000010
  4. Submit by the 7th day of the following month (LHDN reported deadline)

Cancelling a Document

After LHDN validates a document, the issuer has a 72-hour window to cancel it:

  1. Open the myinvois.submission record for the document
  2. Click Cancel and enter a cancellation reason
  3. The module sends PUT /api/v1.0/documents/state/{uuid}/state with status: cancelled
  4. Cancellation is blocked if the buyer has already accepted or rejected the document

Checking Buyer Rejections

The notification poller (ir.cron) periodically calls GET /api/v1.0/notifications/taxpayer to fetch LHDN system notifications. Buyer rejections are surfaced as chatter messages on the linked invoice, with the rejection reason and timestamp.

Validating a Partner's TIN

Before issuing a B2B invoice, validate the buyer's identity:

  1. Open the partner record and navigate to the MyInvois tab
  2. Click Validate TIN -- the module calls GET /api/v1.0/taxpayer/validate/{idType}/{idValue}
  3. A green indicator confirms the TIN is registered in the LHDN registry
  4. An invalid TIN will cause LHDN to reject the entire submission batch; validate before submitting

API Details

FieldValue
Auth methodOAuth 2.0 Client Credentials Grant
Token endpoint (sandbox)https://preprod-api.myinvois.hasil.gov.my/connect/token
Token endpoint (production)https://api.myinvois.hasil.gov.my/connect/token
Document submissionPOST /api/v1.0/documentsubmissions
Status pollingGET /api/v1.0/documentsubmissions/{submissionUid}
Document detailsGET /api/v1.0/documents/{uuid}/details
Cancel / RejectPUT /api/v1.0/documents/state/{uuid}/state
NotificationsGET /api/v1.0/notifications/taxpayer
TIN validationGET /api/v1.0/taxpayer/validate/{idType}/{idValue}
Batch limit100 documents per submission call
Token lifetime3,600 seconds (auto-refreshed)
Key config fieldsclient_id, client_secret, myinvois_tin, myinvois_brn, myinvois_sst_id, myinvois_msic_code

Troubleshooting

IssueSolution
License not activeGo to Settings > ECOSIRE License and verify the key is activated
Connection test failsCheck Client ID and Client Secret match those in the MyInvois Portal; confirm you are pointing at the correct environment (sandbox vs production)
"Sandbox Verified flag not set" errorComplete a successful sandbox submission cycle first, then tick Sandbox Verified in the configuration record
Document signing errorEnsure a valid digital certificate from an LHDN-accepted CA is configured; verify against sdk.myinvois.hasil.gov.my signing requirements
TIN validation returns 400The buyer TIN is not registered in the LHDN registry or the format is wrong (11--14 alphanumeric); contact the buyer to provide their correct LHDN TIN
Submission returns partial acceptanceSome documents in the batch passed and others failed; review the rejectedDocuments entries in the submission record's audit log for per-document error codes
Status stuck at "In Progress"LHDN async validation can take several minutes for large batches; the cron poller retries automatically -- check the submission audit log for the latest poll result
Cancel rejected with 422The 72-hour cancellation window has closed or the buyer has already accepted the document; issue a Credit Note instead
QR URL empty on invoiceThe document has not yet reached Valid state; the QR URL is only returned after LHDN stamps the document
No MyInvois configuration found for companyCreate a configuration record under Accounting > MyInvois > Configuration for the active company

Support