MyInvoisLHDNE-InvoicingDevelopers

The MyInvois API: What Integrating with LHDN Involves

How the MyInvois API works — credentials and signing, UBL 2.1 documents, submit-then-poll validation, the sandbox, and the limits that shape a build.

F
Finvo Team
18 min read

The MyInvois API is the connection between a business system and LHDN's e-invoicing platform. Instead of a person filling in a form, your software builds an e-invoice, signs it, sends it to LHDN and reads back the validation result — all without anyone opening a browser.

It is worth being clear about what it is not. The API is a transmission mechanism, not a product. It does not keep your books, store your customers or replace your invoicing software. It is the doorway those systems use to reach MyInvois. This page explains what passing through that doorway actually involves: what you need before you can call anything, what a document has to look like, how submission behaves, what the limits are, and whether building it yourself is the right call.

What the MyInvois API is

LHDN documents two groups of endpoints, and the split tells you how the system is organised.

The Platform API handles everything that is not an invoice: logging in, asking which document types and versions the system currently accepts, and reading your notification history. The e-Invoicing API handles documents themselves — validating a TIN, submitting, cancelling, rejecting, and retrieving what you sent or received.

Both are described in the MyInvois SDK, currently SDK 1.0, whose release notes were last updated on 25 September 2026. Some of its changes are scheduled rather than live: the notes of 6 August and 25 September 2026 schedule production changes for 24 October 2026. The SDK changes, so treat any endpoint list — including the ones on this page — as a snapshot rather than a contract.

Who actually needs it

Not everyone connecting to MyInvois needs to build anything. There are really three positions:

  • You do not need the API at all. Low volume, and the MyInvois Portal handles it. The portal is free, needs no digital certificate of your own, and includes a batch upload for more than one invoice at a time.
  • You need API submission, but not your own integration. This is most businesses. Your accounting or ERP software already connects, or a service provider connects for you. You never see an endpoint.
  • You need to build it. Usually because invoice volume is high, because invoices originate in a system nobody sells a connector for, or because the data that becomes an invoice lives somewhere that would be painful to export.

The middle position is a common one: the question "do we need the MyInvois API?" is often really "does our software support it?" Those have very different answers.

How the API differs from the portal

MyInvois PortalAPI
Who does the workA person, on a form or a spreadsheet uploadYour system, automatically
Digital certificateNot needed — the portal signs on your behalfSigning requirements depend on the document version; you or an authorised provider may hold the certificate
VolumeSuitable for lower-volume/manual submissionBetter suited to system-generated and higher-volume submission
Validation resultShown on screenReturned asynchronously, read back by your system
Setup effortUser and taxpayer-profile setupRequires a development/integration project
What breaksA person makes a mistakeCredentials expire, schemas change, jobs fail silently

The last row matters more than it looks. An automated integration fails quietly; a person notices when a form rejects them. Any serious integration needs someone watching it.

The three ways to connect

LHDN's e-Invoice Guideline describes API transmission as happening by one of three routes.

RouteWhat it meansWho holds the build
Direct ERP integrationYour own system talks to MyInvois using your taxpayer credentialsYou
Through a Peppol technology providerAn accredited Peppol access point transmits on your behalf, using the Peppol network for exchange with trading partnersThe provider
Through a non-Peppol technology providerA software vendor or service provider transmits on your behalf without using PeppolThe provider

Peppol is worth one clarification, because it gets confused with validation. Peppol is an international network for exchanging structured documents between trading partners. It does not perform LHDN's tax validation — that still happens in MyInvois. A Peppol provider can do both jobs in one workflow, but they remain two different things.

Where the intermediary fits

Separately from those routes, a taxpayer can appoint an intermediary: a company authorised to act on their behalf inside MyInvois. This is an authorisation model, not a technology one, and it changes who authenticates.

A few things about intermediaries are set by LHDN rather than by your software:

  • Registration as an intermediary is restricted to businesses, companies or organisations. An individual taxpayer cannot register in their own name.
  • The taxpayer grants permissions, and those permissions apply to the intermediary's profile.
  • An intermediary profile cannot be deleted once registered. To end the arrangement you set the "Representation To" date, which deactivates further action while preserving the historical records.

That last point is the one to plan around: an appointment that lapses does not produce an error message in your own system. Submissions simply stop being authorised.

What you need before you can call anything

Client credentials

An ERP system that submits using your own identity has to be registered in your taxpayer profile in the MyInvois Portal, under Representatives. LHDN issues a Client ID and Client Secret for it, and there is no restriction on how many systems you register. You can regenerate the credentials from the same place if they are ever exposed.

Treat them as you would a banking credential. Anyone holding them can submit e-invoices in your name.

Authentication itself is the OAuth 2.0 client credentials flow — a POST to /connect/token on LHDN's identity service, conceptually:

POST /connect/token

grant_type     = client_credentials
client_id      = <your client id>
client_secret  = <your client secret>
scope          = InvoicingAPI

The response carries an access_token, a token_type of Bearer, and an expires_in. Tokens are valid for 60 minutes. LHDN explicitly names requesting a fresh token for every call as an anti-pattern — cache the token for its stated lifetime and reuse it.

An intermediary authenticates the same way, with one addition: an onbehalfof header carrying the TIN of the taxpayer being represented. The same integration therefore serves many clients by varying one header rather than by holding many sets of credentials.

The digital certificate

This is the requirement that most often stalls an integration, because it is procurement rather than code.

For ordinary API submissions, v1.1 includes digital-signature validation and is strongly recommended. The SDK currently permits v1.0 without signature validation until LHDN announces its retirement. SVDP disclosures use their designated versions. Where digital signing is required, the signing certificate must meet LHDN's X.509 certificate requirements. The certificate must come from a Malaysian certification authority — the recognised authorities are listed on the MCMC website — and must be issued at organisation level, not to an individual. Its subject has to carry the organisation name, country, the TIN (as the organisation identifier) and the organisation's business registration number (BRN, as the serial number) linked to that TIN, and it needs Non-Repudiation key usage and the Document Signing extended key usage.

Two practical notes from LHDN's SDK FAQ: both locally installed ("soft") and server-based ("roaming") certificates are acceptable, and an authorised service provider may sign with its own certificate for its customers rather than obtaining one per customer. A group of companies can either procure certificates independently or appoint one subsidiary as the intermediary for the rest.

Start this early. It is the one item on the list that cannot be shortened by working harder.

What a document has to look like

UBL 2.1, as XML or JSON

MyInvois accepts structured documents following the UBL 2.1 schema, in either XML or JSON. The format is declared as part of the submission. A PDF is not an e-invoice as far as MyInvois is concerned — the PDF a buyer eventually sees is produced from the validated document, not submitted as one.

Each document carries a type code — invoices, credit notes, debit notes and refund notes, plus their self-billed equivalents — and each type has versions with their own lifecycle and active date ranges. Your integration should read the current document type versions from the Platform API rather than hard-coding a version that may later be deactivated.

What actually goes in the fields is a separate subject; the 55 mandatory fields covers that, and self-billed e-invoices and consolidated e-invoices cover the two document patterns that behave differently from an ordinary invoice.

The hash and the signature

Each submitted XML or JSON document has a documentHash calculated using SHA-256. This submission hash is separate from the digital signature.

For signed versions, follow the SDK signature creation procedure exactly. It defines the transformed document digest, signature value, certificate digest and signed-properties digest used in the signature structure. This summary is not an implementation algorithm.

This is the part most worth using a library for. Getting canonicalisation subtly wrong produces a document that looks correct and fails validation.

The submission workflow

  1. Step 1

    Authenticate

    Exchange Client ID and Secret for an access token. Cache it — it lasts 60 minutes.
  2. Step 2

    Build

    Construct the UBL 2.1 document in XML or JSON, against the current document type version.
  3. Step 3

    Sign and hash

    Follow the SDK signing procedure where required by the document version, and provide the SHA-256 documentHash for submission.
  4. Step 4

    Submit

    POST the batch. HTTP 202 returns a submission UID, UUIDs for accepted documents and details of any immediately rejected documents.
  5. Step 5

    Poll

    Check the submission status every few seconds until it settles.
  6. Step 6

    Reconcile

    Store the UUID and status against your own invoice record. This is yours to keep.

Why you get a 202 and not a verdict

Submission is asynchronous, and this catches out anyone expecting a normal request-response API.

MyInvois runs a minimal set of checks synchronously and then returns HTTP 202 Accepted. The response carries a submissionUID, an acceptedDocuments list pairing each document's assigned UUID with your own reference number, and a rejectedDocuments list for anything refused outright. A 202 means "received for processing" — it does not mean the invoice is valid.

Full validation happens afterwards. Your system finds out by calling Get Submission with the submission UID. LHDN's guidance is to wait a period appropriate to the size of the batch, then poll at a 3–5 second interval.

Submission status resolves to in progress, valid, partially valid or invalid. Individual documents resolve to Submitted, Valid, Invalid or Cancelled. Partially valid is the case worth designing for deliberately: some documents in your batch passed and some did not, and your system has to handle both in one response.

The current SDK does not document a webhook callback mechanism. Notifications are retrieved through the Platform API instead, but the working pattern for submission status is submit, then poll.

Reading back what you submitted

Several endpoints return documents, and LHDN is unusually direct about which one to use for which job. Using the wrong one is a common cause of throttling.

EndpointUse it forNot for
Get SubmissionChecking whether a submission has finished processing—
Get Document DetailsRetrieving validation errors on a document that came back invalidRoutine status checking
Get DocumentRetrieving the document source and its tax authority metadata—
Get Recent DocumentsTroubleshooting, within the last 31 daysReconciliation against your own records
Search DocumentsAuditing and investigation, with filtersReconciliation against your own records
Validate Taxpayer's TINChecking a buyer's TIN when you set the buyer upCalling before every submission

The recurring theme is that MyInvois is not your system of record. Search windows are capped at 31 days between start and end dates, a search returns at most 10,000 documents, and LHDN states plainly that these endpoints were not designed for reconciling an ERP against MyInvois. Your own database holds the mapping from your invoice to its UUID, status and validation time. Build that in from the start rather than planning to query it back later.

The TIN row is worth acting on too: validate a buyer's TIN when you create or edit the buyer record and cache the outcome, rather than calling it on every invoice. An incorrect TIN can cause validation to fail, so checking it at the right moment is genuinely useful — just not on every submission.

Two kinds of limit

These get conflated, and they are unrelated.

Submission limits are properties of the payload:

LimitValue
Maximum submission size5 MB
Maximum e-invoices per submission100
Maximum size per e-invoice300 KB

A batch has to satisfy all three, so 100 documents averaging more than 50 KB will hit the 5 MB ceiling before the document count.

Request rates are separate, and LHDN publishes them per endpoint as recommendations rather than as a single enforced number:

EndpointRecommended rate, per Client ID
Login (taxpayer or intermediary)12 RPM
Submit Documents100 RPM
Get Submission300 RPM
Get Document Details125 RPM
Search Documents12 RPM, and around one request every 5 seconds per taxpayer
Get Recent Documents12 RPM
Cancel Document12 RPM

Exceeding what the system will tolerate returns HTTP 429 with a Retry-After header. Handle that header rather than retrying immediately — a retry loop that ignores it makes the situation worse. The low login limit is the clearest argument for caching tokens: at 12 requests per minute, a system that authenticates per invoice will throttle itself long before it throttles anything else.

Sandbox and production

These are genuinely separate environments.

  • Production: api.myinvois.hasil.gov.my
  • Sandbox: preprod-api.myinvois.hasil.gov.my

They need different Client IDs and Client Secrets. Production credentials do not work in the sandbox, and the reverse is equally true. Documents submitted to the sandbox are test data — they are not real e-invoices, they carry no legal effect, and nothing migrates between the environments. LHDN's Integration Practices page also states that sandbox data is retained for a maximum of three months and then permanently deleted, and that the sandbox has a lower API rate limit than production.

The portal side has its own preproduction environment for setting up and inspecting sandbox submissions; the portal guide covers getting into it. Build and test there first, and keep the environment choice in configuration rather than in code, so that pointing at production is a deployment decision rather than an edit.

Where integrations go wrong

Common production failures fall into a small number of categories:

  • Token expiry. A 60-minute token, a long-running job, and no refresh — a 401 partway through a batch.
  • Requesting tokens too often. The opposite failure, and it throttles at 12 RPM.
  • Schema and version drift. A document type version is deactivated, or the SDK changes, and documents that worked last quarter stop validating.
  • Invalid TIN or registration number. An invalid TIN or registration number can cause validation to fail, and is avoidable by checking the data when the buyer is created.
  • Wrong codes. Classification codes, unit codes, tax types and currency codes are enumerated values, not free text.
  • Duplicate submission. A retry after a timeout that actually succeeded, producing two validated invoices for one sale. Idempotency on your side, keyed to your own reference number, prevents this.
  • Throttling. Usually caused by polling the wrong endpoint, or by treating Search Documents as a reconciliation tool.
  • Transient failures. Networks and platforms have bad days. Retries need backoff and a dead-letter path, not an infinite loop.

What the specific validation errors mean is a subject of its own — common MyInvois rejection errors covers those. And corrections have a deadline: a validated document can be cancelled within 72 hours of validation with a mandatory reason, after which the correction has to be made through a credit, debit or refund note. The 72-hour cancellation window covers the timing rules, including the case where the buyer, not the supplier, is the one who cancels.

What to prepare

Before a developer starts, have these settled: the taxpayer's TIN and registration details, an ERP system registered in the MyInvois Portal with credentials issued, a signing plan and, where required, an organisation-level certificate held by you or your authorised provider, sandbox access, a decision on whether you are submitting as the taxpayer or as an intermediary, and a clear answer on where the UUID and status will be stored in your own schema.

Before you commission an integration, these are the questions worth asking a software provider:

  1. Do you submit to MyInvois directly, or through a partner or intermediary?
  2. Who holds the credentials and the digital certificate — us, or you?
  3. If we leave, do we keep our credentials and our validated document records?
  4. How do we see that a submission failed, and how quickly?
  5. Do you handle consolidated and self-billed documents, and adjustments to validated ones?
  6. What happens when LHDN changes the schema — who updates it, and at whose cost?
  7. Can we test in the sandbox before going live?

Question 2 decides more than it appears to. If your provider signs with their own certificate, that is normal and permitted — but it means changing provider is a migration, not a switch.

Build it, or buy something that already has it

This is a genuine question with a real answer on both sides.

Building is reasonable when volume is high enough that per-document fees matter, when invoices originate in a system nobody sells a connector for, or when you already run engineering capable of maintaining a compliance integration through schema changes for years.

Buying is reasonable — and is often the practical answer for businesses that need e-invoicing but do not want to maintain the integration themselves. The work does not end at go-live: certificates expire, schemas version, limits change, and the integration needs an owner for as long as the business issues invoices. The portal versus third-party apps sets out that comparison at length, and choosing accounting software covers what to look for more generally.

Finvo is being developed as Malaysian accounting software with a MyInvois submission workflow in the same system as its accounting records. That connection is separate from a public Finvo developer API; public developer access is not yet confirmed as available. Check current access and features during rollout.

Official documentation

Go to the primary sources for anything you are going to implement:

Related guides

Related Articles