Global Unify API v3 — Integration Guide
Submit and manage invoices across supported countries with a single, unified endpoint.
Version: v3 · Protocol: REST / JSON · Countries: SA · MY · BE · AE · SG · DE
Overview
The Unify API is a global, unified endpoint that consolidates invoice management functionalities across supported countries. It encompasses validation for Business-to-Business (B2B), Business-to-Consumer (B2C), and Business-to-Government (B2G) transactions.
Key Features:
- Single Endpoint — Submit invoices and manage documents across all supported countries with one consistent URL
- Multi-Transaction Support — Handles validation for B2B, B2C, and B2G transactions
- Validation & Submission — Comprehensive validation and government submission workflow
- XML Response Support — Responses can be returned as XML files in addition to JSON format
After successfully onboarding, simply use the Unify API key to submit invoices. The system will handle validation, document transformation, and government submission based on the specified country and invoice type.
Endpoint
POST /api/v3/unifyEvery request uses this same URL. The action field in the request body controls what the API does.
| Action | Description |
|---|---|
"submit" | Submit one or more invoices for processing and government submission. Supports single and bulk (up to 10 invoices per request). |
"list" | Retrieve document details for a previously submitted invoice. Currently supported for Malaysia (MY) only. |
Authentication
All requests must include your API key as a Bearer token in the Authorization header.
Authorization: Bearer <YOUR_API_KEY>
Content-Type: application/jsonKeep your API key secure. Never expose it in frontend code, public repositories, or logs. Use environment variables to store it server-side.
API key must match the environment. Your production key is required for
"env": "production"or"prod". For other environments like"sandbox"and"simulation", you can use your mock key. Mismatches will return an auth error.
Environments
Every request includes an env field that tells the API which environment to use. This must match the environment your API key was issued for.
env value | Use for |
|---|---|
sandbox | Development and testing. Requests are not submitted to any government system. |
simulation | End-to-end testing that mimics production behaviour without real submission. |
production or prod | Live submissions to government tax authorities. |
Start with sandbox or simulation. Always build and test your integration using
sandboxorsimulationenvironments first. These environments may behave differently depending on the country and regulatory requirements. Switch toproductiononly when you're ready to submit real invoices.
The "Purpose" Workflow
The integration requires a specific two-stage process to ensure your document data correctly translates to regulatory standards.
Step 1: MAPPING (Setup & Template Creation)
Set the Purpose to "MAPPING" to push your raw data to the Complyance platform. This stage is used for initial field discovery and visualization.
- In Code: Submit your payload with
"purpose": "MAPPING" - In Portal: Locate the uploaded payload, complete the field mapping, and save it as a successful Template.
- Final Step: Register and bind your unique
sourceNameandsourceVersionto this template on the portal.
Step 2: INVOICING (Production Submission)
After your template is successfully bound to your source identifiers, change the Purpose to "INVOICING".
- Action: The system now recognizes your
sourceName/sourceVersionand applies the saved template logic to transform, validate, and officially submit the document to the tax authority. - Requirement: You must use the exact same Source identifiers registered during the Mapping phase.
Payload Structure (Country Label & Tooltip Mapping)
Use the following mapping structure as a payload reference for country-specific field labels and tooltips. For a complete and detailed field mapping reference, refer to the Field Mapping Payload Reference page.
Integration Engine & Field Mapping Workflow
Before submitting invoices through the Unify API, you must complete the field mapping process through the Integration Engine portal. This ensures your payload data correctly aligns with regulatory requirements for your target countries.
Complete Mapping Process
-
Access the Integration Engine Portal
- Navigate to your Dev Portal or Integration Engine dashboard
- Create a new integration or select an existing one
-
Upload Your Payload
- Upload a sample JSON payload file representing your invoice data structure
- The platform will analyze your payload and identify all available fields
-
Map Your Fields
- Map each field from your source payload to the corresponding Complyance standard field
- Configure field transformations if needed (formatting, calculations, etc.)
- Validate that all mandatory fields for your target country are mapped
-
Test & Validate
- Submit a test payload with
"purpose": "MAPPING"through the Unify API - Verify the transformed data in the portal
- Review any validation warnings or errors
- Submit a test payload with
-
Save & Bind Your Template
- Save your completed field mapping as a template
- Register your integration with unique
sourceNameandsourceVersionidentifiers - Bind this template to your integration
Using Mapped Templates with Unify API
Once your mapping is complete and bound to your integration, you can submit invoices through the Unify API:
- Initial Submissions — Use
"purpose": "MAPPING"if testing new payload structures - Production Submissions — Switch to
"purpose": "INVOICING"to use the bound template - Critical Requirement — Always use the exact same
sourceNameandsourceVersionthat you registered in the Integration Engine
The Unify API will automatically apply your saved field mappings and validation rules, transforming your raw payload data into regulatory-compliant documents for submission to government authorities.
LogicalDocType
LogicalDocType is the recommended way to drive document behavior across different transaction types (B2B/B2C variants, export/self-billed/third-party, etc.). The same LogicalDocType values apply across all supported countries, ensuring consistency in your integration regardless of the target regulatory environment.
Common Document Types:
- B2B Invoices:
TAX_INVOICE,TAX_INVOICE_CREDIT_NOTE,TAX_INVOICE_DEBIT_NOTE - B2C Invoices (Simplified):
SIMPLIFIED_TAX_INVOICE,SIMPLIFIED_TAX_INVOICE_CREDIT_NOTE - Special Types:
EXPORT_INVOICE,SELF_BILLED_INVOICE,THIRD_PARTY_INVOICE,DEEMED_SUPPLY,MARGIN_SCHEME,CONTINUOUS_SUPPLY
Use the appropriate LogicalDocType value in the logicalDocumentType field of your request to ensure the correct document classification and validation rules are applied by the system.
Submit Invoices
Use action: "submit" to send invoices for processing. You can submit a single invoice or up to 10 invoices in one request (bulk).
Request Structure
{
"action": "submit",
"purpose": "invoicing",
"env": "sandbox",
"defaults": {
"country": "MY",
"logicalDocumentType": "TAX_INVOICE",
"source": {
"name": "your-system-name",
"version": "1.0"
},
"destinations": [
{ "type": "TAX_AUTHORITY" }
]
},
"invoices": [
{
"payload": {
"invoice_data": {
"document_number": "INV-2026-0001",
"invoice_date": "2026-02-23"
}
}
}
],
"options": {
"continueOnError": true,
"submitToGovernment": true
}
}Field Reference
| Field | Required | Description |
|---|---|---|
action | ✅ Required | Must be "submit" |
purpose | ✅ Required | Must be "invoicing" |
env | ✅ Required | One of: sandbox, simulation, production, prod |
defaults.country | ✅ Required | ISO country code. Supported: SA, MY, BE, AE, SG, DE |
defaults.logicalDocumentType | ✅ Required | Document type, validated per country (e.g. TAX_INVOICE) |
defaults.source.name | ✅ Required | Name of your system or integration |
defaults.source.version | ✅ Required | Version of your system |
defaults.destinations | ⬜ Optional | Array of destination objects. Tax authority submission is mandatory by default. Use this field when the document needs to be routed to additional networks such as PEPPOL in parallel with the tax authority submission. |
invoices | ✅ Required | Array of invoice objects. Min 1, max 10. |
invoices[].payload | ✅ Required | Invoice data object. Must not be empty. |
options.continueOnError | ⬜ Optional | In bulk mode: true = process remaining invoices if one fails. false = abort on first error. |
options.submitToGovernment | ⬜ Optional | Defaults to true when purpose is "invoicing". |
Important Notes
payload goes directly inside each invoice object — do not wrap it in an extra object.
// ✅ Correct
"invoices": [
{ "payload": { "invoice_data": { ... } } }
]
// ❌ Wrong
"invoices": [
{ "invoice": { "payload": { "invoice_data": { ... } } } }
]Do not include metaConfig — the fields defaults.metaConfig and invoices[].metaConfig are system-managed and will be rejected if present in your request.
List Documents (Malaysia)
Use action: "list" to retrieve the full document details for a previously submitted invoice. This action is currently supported for Malaysia (MY) only.
You need two identifiers to look up a document — both are returned in the submit response:
| Identifier | Where to find it |
|---|---|
uuid | Returned by the tax authority after successful submission |
documentId | Returned by the API in the submit response (results[].documentId) |
Request Structure
{
"action": "list",
"env": "sandbox",
"filters": {
"country": "MY",
"uuid": "4Q2H2R3YSSYZTX5TRWZF2M2K10",
"documentId": "01DXXXXXXXXXXXXXXXXXXXXXXX"
},
"page": 1,
"limit": 20,
"sort": "createdAt:desc"
}The document details are returned inside data.results[0].documentDetails in the response.
Validation Rules
General
| Rule | Detail |
|---|---|
env | Must be one of: sandbox, simulation, production/prod |
| Supported countries | SA, MY, BE, AE, SG, DE |
| API key / env mismatch | Returns AUTH_INVALID_API_KEY |
Submit Action
| Rule | Detail |
|---|---|
| Invoice count | Min 1, max 10 invoices per request |
logicalDocumentType | Must be a valid type for the specified country |
invoices[].payload | Must be a non-empty object |
submitToGovernment | Cannot be false when purpose is "invoicing" |
List Action
| Rule | Detail |
|---|---|
filters.country | Must be "MY" (only Malaysia is supported) |
filters.uuid | Required |
filters.documentId | Required |
filters.tinNumber | Optional — resolved automatically, do not send |
Response Format
All API responses share a consistent envelope structure, whether the request succeeded or failed.
Submit — Success Response
{
"status": "success",
"code": "OK",
"message": "Processed",
"requestId": "01J...",
"timestamp": "2026-02-26T10:00:00.000Z",
"data": {
"summary": {
"total": 2,
"success": 2,
"failed": 0
},
"results": [
{
"index": 0,
"externalId": "invoice-1",
"status": "success",
"country": "SA",
"inputLogicalDocumentType": "TAX_INVOICE",
"resolvedDocumentType": "tax_invoice",
"derivedFlags": {
"isExport": false,
"isSelfBilled": false,
"isThirdParty": false,
"isNominalSupply": false,
"isSummary": false,
"isB2B": true,
"isPrepayment": false,
"isAdjusted": false,
"isReceipt": false,
"isB2G": false,
"isPartial": false,
"isPartialConstruction": false,
"isPartialFinalConst": false,
"isFinalConstruction": false
},
"payloadId": "01KJCVMXZ2V23SC1HP5GHY8484",
"documentId": "01D...",
"validation": {
"success": true,
"errors": []
},
"submission": {
"success": true,
"errors": [],
"governmentResponse": {
"statusCode": 200,
"body": {
"clearanceStatus": "CLEARED",
"invoiceHash": "..."
}
},
"submittedAt": "2026-02-26T10:00:00.000Z"
},
"errors": []
}
]
},
"errors": []
}Save the
documentId. This is your reference for looking up document details later using thelistaction. Persist it in your system alongside your invoice record.
submission.governmentResponse (Important)
submission.governmentResponsecontains the actual country adapter/government response payload.- The shape varies by country and adapter implementation/version.
- Parse this object as country-specific data; do not enforce one global schema for all countries.
- Large internal keys like
originalDocument/updatedDocumentmay be omitted to keep response size manageable.
Example (Malaysia style):
{
"submissionUid": "5XE7HPZYDZAVJB8XDZEEC8HK10",
"acceptedDocuments": [
{
"uuid": "GVHDKMWYEYKMDMVHDZEEC8HK10",
"invoiceCodeNumber": "INV-2026-0001"
}
],
"rejectedDocuments": []
}List — Success Response
{
"status": "success",
"data": {
"summary": {
"total": 1,
"returned": 1,
"page": 1,
"limit": 20
},
"results": [
{
"index": 0,
"documentId": "01DXXXXXXXXXXXXXXXXXXXXXXX",
"uuid": "4Q2H2R3YSSYZTX5TRWZF2M2K10",
"country": "MY",
"environment": "sandbox",
"documentDetails": {}
}
]
}
}Error Response
{
"status": "error",
"code": "VALIDATION_ERROR",
"message": "Request validation failed",
"requestId": "01J...",
"timestamp": "2026-02-26T10:00:00.000Z",
"data": null,
"errors": [
{
"code": "REQ_INVALID_INPUT",
"message": "documentId is required for list action",
"path": ["filters", "documentId"]
}
]
}The errors array tells you exactly which field failed and why. Use the path field to pinpoint the issue in your request body.
Quick Start Checklist
- Get your API key — Start with a sandbox key so you can test safely without submitting real invoices.
- Send a test submit request — Use the single-invoice example with
"env": "sandbox". Verify you get a"status": "success"response. - Save the
documentId— Store thedocumentIdfrom the submit response in your system — you'll need it to retrieve document details. - Test the list action (Malaysia) — Use the
uuidanddocumentIdto call the list endpoint and verify document details are returned. - Switch to production — Replace your sandbox API key with your production key and update
"env"to"production". You're live!
Examples & Code Samples
See Examples for detailed cURL examples and code samples for single submit, bulk submit, and list operations.