Getting Started
@ripwords/myinvois-client is a TypeScript client for Malaysia's MyInvois (LHDN) e-invoicing API: UBL document building, XAdES (JSON profile) digital signing, submission, polling, cancellation/rejection, taxpayer validation and built-in rate limiting.
Scope: Malaysia MyInvois only. Singapore's InvoiceNow / Peppol e-invoicing is a different system and out of scope for this library.
Installation
npm install @ripwords/myinvois-client
# or: bun add / pnpm add / yarn add @ripwords/myinvois-clientNode.js is the supported runtime (the library also runs on Bun). All credentials are per-instance constructor arguments — nothing is read from process.env, so multi-tenant apps can hold one client per organisation.
Creating a client
From a PKCS#12 bundle (recommended — single source of certificate + key):
import { MyInvoisClient } from '@ripwords/myinvois-client'
const client = MyInvoisClient.fromP12(
clientId,
clientSecret,
'sandbox', // or 'production'
'path/to/certificate.p12',
passphrase,
)From PEM strings, with the options factory (preferred for new code — new options are added here without changing call sites):
const client = MyInvoisClient.create({
clientId,
clientSecret,
environment: 'sandbox',
certificatePem,
privateKeyPem,
// optional:
onBehalfOf: 'C1234567890', // intermediary access (TIN or TIN:ROB)
retryOn429: { maxRetries: 2 }, // automatic Retry-After back-off
rateLimitStore: myRedisStore, // shared limiter for multi-process apps
tokenStore: myRedisTokenStore, // shared token cache
debug: false,
})Client credentials come from the MyInvois portal; see the official login documentation for how clientId/clientSecret pairs work. The client logs in lazily on the first API call, caches the token, and refreshes it 60 seconds before expiry with single-flight deduplication.
First submission
const { data, status } = await client.submitDocument([invoice])
if (status === 202) {
const result = await client.getSubmissionStatus(data.submissionUid)
console.log(result.status) // 'Valid' | 'PartiallyValid' | 'Invalid' | ...
}The invoice shape follows the official Invoice v1.1 structure — see Signing & Submission for the full flow and the Document Submission API reference for every method.
Environments
| Environment | Base URL |
|---|---|
sandbox | https://preprod-api.myinvois.hasil.gov.my |
production | https://api.myinvois.hasil.gov.my |
The sandbox (preprod) environment and its setup are described in the official SDK docs.