Import Malaysia E-Invoice

View as Markdown
# Import Malaysia E-Invoice (JSON) into a Queue Import a Malaysia e-invoice document into a Staple **Queue** in **JSON** format. Staple will create a document (`docId`) and submit it to LHDN MyInvois asynchronously. This endpoint supports **all MyInvois document types**, including **self-billed** types. * * * ## Endpoint **POST** `/v2/einvoice/malaysia/queue/{queueId}` * * * ## Request Headers | Attribute | Type | Option | Description | | --- | --- | --- | --- | | x-api-key | String | Required | A unique string | | Authorization | String | Required | Bearer token | **Content-Type:** `application/json` **Accept:** `application/json` * * * ## Path Parameter | Attribute | Type | Option | Description | | --- | --- | --- | --- | | queueId | String | Required | Target queue ID | * * * ## Supported Document Types (`docType`) `docType` determines the business scenario. Allowed values: | docType | Description | | --- | --- | | `invoice` | Commercial document issued by Supplier to Buyer. | | `credit_note` | Issued by Supplier to reduce the value of a previously issued e-Invoice (no money returned to Buyer). | | `debit_note` | Issued by Supplier to indicate additional charges on a previously issued e-Invoice. | | `refund_note` | Issued by Supplier to confirm refund of Buyer’s payment (money returned to Buyer). | | `self_billed_invoice` | Issued by Buyer (instead of Supplier) in allowed self-billing scenarios. | | `self_billed_credit_note` | Issued by Buyer to reduce value of a previously issued self-billed e-Invoice. | | `self_billed_debit_note` | Issued by Buyer to indicate additional charges on a previously issued self-billed e-Invoice. | | `self_billed_refund_note` | Issued by Buyer to confirm refund payment (money returned from Supplier to Buyer). | * * * ## Request Payload (JSON) A single endpoint supports all `docType` values above. ### Top-level Fields | Field | Type | Required | Description | | --- | --- | --- | --- | | docType | String | ✅ | One of the supported document types listed above. | | docNumber | String | ✅ | Document number (Invoice No / Credit Note No / etc.). Used for tracking and de-duplication. | | issueDate | String (YYYY-MM-DD) | ✅ | Issue date. | | issueTime | String (HH:mm:ssZ) | ✅ | Issue time. Example: `09:44:25Z`. | | currency | String | ✅ | ISO 4217 currency code (e.g. `MYR`). | | fxRate | Number | Optional | Foreign exchange rate. Use `1.0` for MYR documents when no conversion is needed. | | supplier | Object | ✅ | Supplier / issuer party. | | buyer | Object | ✅ | Buyer party. | | lines | Array | ✅ | Line items (min 1). | | totals | Object | ✅ | Totals (must reconcile with lines). | | reference | Object | Optional | Required for adjustment documents (see **Reference Rules**). | | reason | String | Optional | Recommended for adjustment documents (credit/debit/refund) and audit trail. | * * * ## Sample Payload (Invoice) > Paste this into Postman Body. ```json { "docType": "invoice", "docNumber": "INV-2026-0001", "issueDate": "2026-03-23", "issueTime": "09:44:25Z", "currency": "MYR", "fxRate": 1.0, "supplier": { "name": "Seller Sdn Bhd", "tin": "IG59605712010", "registrationType": "PASSPORT", "registrationNo": "RA2052854", "msicCode": "85494", "address": { "line1": "1 Jalan Example", "city": "Kuala Lumpur", "stateCode": "14", "postcode": "50000", "country": "MYS" }, "contact": { "telephone": "+60123456789" } }, "buyer": { "name": "Buyer Sdn Bhd", "tin": "C59584904000", "registrationType": "BRN", "registrationNo": "202401040495", "address": { "line1": "2 Jalan Example", "city": "Kuala Lumpur", "stateCode": "14", "postcode": "50000", "country": "MYS" }, "contact": { "telephone": "+60165537256" } }, "lines": [ { "lineNo": 1, "description": "Consulting service", "quantity": 1, "unitPrice": 100, "amount": 100, "amountExclTax": 100, "classifications": [ { "code": "003" } ] }, { "lineNo": 2, "description": "Non-taxable item", "quantity": 1, "uom": "EA", "unitPrice": 50, "amount": 50, "amountExclTax": 50, "classifications": [ { "code": "003" } ], "taxes": [ { "type": "NOT_APPLICABLE", "rate": 0, "amount": 0 } ] } ], "totals": { "totalExclTax": 150, "totalInclTax": 168, "taxTotal": 18, "payableAmount": 168 } } ``` * * * ## Reference Rules (VERY IMPORTANT) Some document types must reference an earlier document. ### Supplier-issued adjustments (reference original `invoice`) When `docType` is one of: - `credit_note` - `debit_note` - `refund_note` `reference.originalInvoiceCodeNumber` is **required** and must point to the original **invoice** `docNumber` / code number used by your integration. ### Buyer-issued (self-billed) adjustments (reference original `self_billed_invoice`) When `docType` is one of: - `self_billed_credit_note` - `self_billed_debit_note` - `self_billed_refund_note` `reference.originalInvoiceCodeNumber` is **required** and must point to the original **self\_billed\_invoice** `docNumber` / code number used by your integration. ### Reference Object | Field | Type | Required | Description | | --- | --- | --- | --- | | reference.originalInvoiceCodeNumber | String | ✅ (when applicable) | The original invoice/self-billed invoice code number being adjusted. | Example: ```json "reference": { "originalInvoiceCodeNumber": "INV-2026-0001" } ``` * * * ## Party Objects (`supplier`, `buyer`) | Field | Type | Required | Description | | --- | --- | --- | --- | | name | String | ✅ | Legal/trade name. | | tin | String | ✅ | Supplier TIN is required. Buyer TIN may be required depending on scenario. | | registrationType | String | ✅ | Registration identifier type, e.g. `BRN`, `PASSPORT`. | | registrationNo | String | ✅ | Registration number / identity number. | | msicCode | String | Conditional | Business classification code. Commonly provided on supplier. | | address | Object | ✅ | Address object. | | contact | Object | ✅ | Contact object. | **Address Object (recommended fields):** `line1`, `city`, `stateCode`, `postcode`, `country` **Contact Object (recommended fields):** `telephone` > Self-billed documents: Buyer is the issuer in business terms, but this API keeps `supplier` and `buyer` fields consistent. Staple validates and maps parties according to `docType`. * * * ## Line Items (`lines[]`) | Field | Type | Required | Description | | --- | --- | --- | --- | | lineNo | Integer | ✅ | Line sequence number (starting from 1). | | description | String | ✅ | Item/service description. | | quantity | Number | ✅ | Quantity. | | uom | String | Optional | Unit of measure (e.g. `EA`). | | unitPrice | Number | ✅ | Unit price (non-negative). | | amount | Number | Optional | Gross line amount before or alongside tax calculation, depending on integration flow. | | amountExclTax | Number | ✅ | Line amount excluding tax. Recommended to use negative amounts for `credit_note` and `refund_note`. | | classifications | Array | ✅ | Example: `[{"code": "003"}]` | | taxes | Array | ✅ | Line-level taxes array (see **Tax** section). | * * * ## Totals (`totals`) | Field | Type | Required | Description | | --- | --- | --- | --- | | totalExclTax | Number | ✅ | Sum of `lines[].amountExclTax`. | | totalInclTax | Number | ✅ | Final total including tax. | | taxTotal | Number | ✅ | Total tax amount across all lines. | | payableAmount | Number | ✅ | Final payable amount. Usually matches `totalInclTax`. | * * * ## Tax Tax is represented at **line-level** under `lines[].taxes`. ### Tax Object (`taxes[]`) | Field | Type | Required | Description | | --- | --- | --- | --- | | type | String | ✅ | Tax category (see allowed values). | | rate | Number | ✅ | Tax rate in percentage (e.g. `8.0`). | | amount | Number | ✅ | Tax amount for the line. May be negative for credit/refund documents. | ### Allowed Values for `taxes[].type` | Type | Meaning | | --- | --- | | `SALES_TAX` | Sales Tax | | `SERVICE_TAX` | Service Tax | | `TOURISM_TAX` | Tourism Tax | | `HIGH_VALUE_GOODS_TAX` | High-Value Goods Tax | | `LOW_VALUE_GOODS_TAX` | Sales Tax on Low Value Goods | | `NOT_APPLICABLE` | No tax applies | | `EXEMPT` | Tax exempt | > Do not use ambiguous values like `SST`. Choose `SALES_TAX` or `SERVICE_TAX` explicitly. * * * ## Amount Conventions (Recommended) To keep adjustments unambiguous: - `credit_note`: use **negative** amounts for `lines[].amountExclTax`, `lines[].taxes[].amount`, and totals. - `refund_note`: use **negative** amounts when reducing original invoice value and confirming money returned to Buyer. - `debit_note`: use **positive** amounts (additional charges). Staple will validate totals consistency. * * * ## Response (Success) > The response confirms the document was queued in Staple. Use `docId` and `trackingUrl` to check ongoing status. ### Example ```json { "requestId": "c86fdc72-51d7-4572-9e67-d11101bc3e29", "queueId": 4520, "docId": 242069, "docType": "invoice", "docNumber": "INV-2026-0001", "message": "Document queued for processing. Use docId to track submission status.", "trackingUrl": "/v2/einvoice/malaysia/status/242069", "myInvois": { "submissionId": "9EJDZFB2WJ967NZ5AXSXNMMK10", "uuid": "7ZPFV97R3VPY3HWGAXSXNMMK10" } } ``` ### Response Field Notes - `requestId`: Request trace ID. - `queueId`: Queue used for import. - `docId`: Staple document ID created in the queue. - `docType`: Imported document type. - `docNumber`: Imported document number. - `message`: Human-readable processing message. - `trackingUrl`: Internal status endpoint for this document. - `myInvois.submissionId`: MyInvois submission batch ID. - `myInvois.uuid`: MyInvois document UUID. > `myInvois` is present only when Staple already has MyInvois submission details available at response time. > If processing later fails, or MyInvois details are not ready yet, the response may still return `docId` **without** `myInvois`. > In that case, check the actual processing result via: > **GET** `/v2/einvoice/malaysia/status/{docId}` * * * ## Error / Status Handling This endpoint is **asynchronous**. A successful import request can still return a normal queued response first, while the actual Malaysia e-invoice processing succeeds or fails later. ### Important behavior - Do **not** assume failures will come back as HTTP errors from the import endpoint. - If processing fails after the document is queued, the response may simply **not include** `myInvois`. - When `myInvois` is missing, use `docId` to call the status endpoint and inspect the real outcome. ### Example follow-up check **GET** `/v2/einvoice/malaysia/status/242069` Use this endpoint to check whether the document was submitted, validated, rejected, or failed during later processing. ### Practical rule - Import response has `docId` + `myInvois` → MyInvois submission details are already available. - Import response has `docId` but **no** `myInvois` → do **not** treat it as HTTP failure; call `/v2/einvoice/malaysia/status/{docId}`.

Authentication

x-api-keystring
API key issued by Staple.
AuthorizationBearer
JWT obtained from the login endpoint.

Request

This endpoint expects an object.
docTypestringOptional
docNumberstringOptional
issueDatestringOptional
issueTimestringOptional
currencystringOptional
fxRateintegerOptional
supplierobjectOptional
buyerobjectOptional
lineslist of objectsOptional
taxTotalslist of objectsOptional
totalsobjectOptional

Response

OK