Skip to content

Your First Invoice

Submit your first e-invoice to LHDN in 6 simple steps. This guide provides code examples in multiple programming languages.

Prerequisites

  • InvoisX API token (create one)
  • LHDN credentials configured (preprod for testing)

Setup

First, set up your API client:

javascript
const API_URL = 'https://invoisx.com/api/v1';
const API_TOKEN = 'your-api-token-here';

async function api(method, endpoint, data = null) {
  const options = {
    method,
    headers: {
      'Authorization': `Bearer ${API_TOKEN}`,
      'Accept': 'application/json',
      'Content-Type': 'application/json',
    },
  };

  if (data) {
    options.body = JSON.stringify(data);
  }

  const response = await fetch(`${API_URL}${endpoint}`, options);
  return response.json();
}
python
import requests

API_URL = 'https://invoisx.com/api/v1'
API_TOKEN = 'your-api-token-here'

headers = {
    'Authorization': f'Bearer {API_TOKEN}',
    'Accept': 'application/json',
    'Content-Type': 'application/json',
}

def api(method, endpoint, data=None):
    url = f'{API_URL}{endpoint}'
    response = requests.request(method, url, headers=headers, json=data)
    return response.json()
php
use Illuminate\Support\Facades\Http;

$apiUrl = 'https://invoisx.com/api/v1';
$apiToken = 'your-api-token-here';

$api = Http::withToken($apiToken)
    ->accept('application/json')
    ->contentType('application/json')
    ->baseUrl($apiUrl);
php
use GuzzleHttp\Client;

$apiUrl = 'https://invoisx.com/api/v1/';  // Trailing slash required for Guzzle
$apiToken = 'your-api-token-here';

$client = new Client([
    'base_uri' => $apiUrl,
    'headers' => [
        'Authorization' => 'Bearer ' . $apiToken,
        'Accept' => 'application/json',
        'Content-Type' => 'application/json',
    ],
]);
java
import java.net.http.*;
import java.net.URI;

String API_URL = "https://invoisx.com/api/v1";
String API_TOKEN = "your-api-token-here";

HttpClient client = HttpClient.newHttpClient();

HttpRequest.Builder requestBuilder(String endpoint) {
    return HttpRequest.newBuilder()
        .uri(URI.create(API_URL + endpoint))
        .header("Authorization", "Bearer " + API_TOKEN)
        .header("Accept", "application/json")
        .header("Content-Type", "application/json");
}
csharp
using System.Net.Http;
using System.Net.Http.Json;

const string API_URL = "https://invoisx.com/api/v1";
const string API_TOKEN = "your-api-token-here";

var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", $"Bearer {API_TOKEN}");
client.DefaultRequestHeaders.Add("Accept", "application/json");

Step 1: Create a Buyer

Create a buyer (your customer) with their business details.

Testing Note

LHDN validates Malaysian TINs in both sandbox and production. For testing, we use a foreign buyer (Singapore) which bypasses TIN validation.

javascript
const buyerData = {
  name: 'Example Trading Pte Ltd',
  tin: 'EI00000000020',
  id_type: 'PASSPORT',
  id_value: 'A12345678',
  address: {
    line1: '123 Orchard Road',
    line2: '#10-01 Plaza Tower',
    city: 'Singapore',
    state: '17',           // Use '17' for non-Malaysian addresses
    postCode: '238867',
    countryCode: 'SGP',
  },
  contact: {
    phone: '+6591234567',
    email: 'billing@example.sg',
  },
};

const buyer = await api('POST', '/buyers', buyerData);
const buyerId = buyer.data.id;

console.log(`Created Buyer: ${buyer.data.name}`);
console.log(`Buyer ID: ${buyerId}`);
python
buyer_data = {
    'name': 'Example Trading Pte Ltd',
    'tin': 'EI00000000020',
    'id_type': 'PASSPORT',
    'id_value': 'A12345678',
    'address': {
        'line1': '123 Orchard Road',
        'line2': '#10-01 Plaza Tower',
        'city': 'Singapore',
        'state': '17',           # Use '17' for non-Malaysian addresses
        'postCode': '238867',
        'countryCode': 'SGP',
    },
    'contact': {
        'phone': '+6591234567',
        'email': 'billing@example.sg',
    },
}

buyer = api('POST', '/buyers', buyer_data)
buyer_id = buyer['data']['id']

print(f"Created Buyer: {buyer['data']['name']}")
print(f"Buyer ID: {buyer_id}")
php
$buyerData = [
    'name' => 'Example Trading Pte Ltd',
    'tin' => 'EI00000000020',
    'id_type' => 'PASSPORT',
    'id_value' => 'A12345678',
    'address' => [
        'line1' => '123 Orchard Road',
        'line2' => '#10-01 Plaza Tower',
        'city' => 'Singapore',
        'state' => '17',           // Use '17' for non-Malaysian addresses
        'postCode' => '238867',
        'countryCode' => 'SGP',
    ],
    'contact' => [
        'phone' => '+6591234567',
        'email' => 'billing@example.sg',
    ],
];

$response = $api->post('/buyers', $buyerData);
$buyer = $response->json('data');
$buyerId = $buyer['id'];

echo "Created Buyer: {$buyer['name']}\n";
echo "Buyer ID: $buyerId\n";
php
$buyerData = [
    'name' => 'Example Trading Pte Ltd',
    'tin' => 'EI00000000020',
    'id_type' => 'PASSPORT',
    'id_value' => 'A12345678',
    'address' => [
        'line1' => '123 Orchard Road',
        'line2' => '#10-01 Plaza Tower',
        'city' => 'Singapore',
        'state' => '17',
        'postCode' => '238867',
        'countryCode' => 'SGP',
    ],
    'contact' => [
        'phone' => '+6591234567',
        'email' => 'billing@example.sg',
    ],
];

$response = $client->post('buyers', ['json' => $buyerData]);
$buyer = json_decode($response->getBody(), true)['data'];
$buyerId = $buyer['id'];

echo "Created Buyer: {$buyer['name']}\n";
echo "Buyer ID: $buyerId\n";
java
String buyerJson = """
{
    "name": "Example Trading Pte Ltd",
    "tin": "EI00000000020",
    "id_type": "PASSPORT",
    "id_value": "A12345678",
    "address": {
        "line1": "123 Orchard Road",
        "line2": "#10-01 Plaza Tower",
        "city": "Singapore",
        "state": "17",
        "postCode": "238867",
        "countryCode": "SGP"
    },
    "contact": {
        "phone": "+6591234567",
        "email": "billing@example.sg"
    }
}
""";

HttpRequest request = requestBuilder("/buyers")
    .POST(HttpRequest.BodyPublishers.ofString(buyerJson))
    .build();

HttpResponse<String> response = client.send(request,
    HttpResponse.BodyHandlers.ofString());

// Parse response to get buyerId
JsonObject buyer = JsonParser.parseString(response.body())
    .getAsJsonObject().getAsJsonObject("data");
String buyerId = buyer.get("id").getAsString();

System.out.println("Created Buyer: " + buyer.get("name").getAsString());
System.out.println("Buyer ID: " + buyerId);
csharp
var buyerData = new {
    name = "Example Trading Pte Ltd",
    tin = "EI00000000020",
    id_type = "PASSPORT",
    id_value = "A12345678",
    address = new {
        line1 = "123 Orchard Road",
        line2 = "#10-01 Plaza Tower",
        city = "Singapore",
        state = "17",
        postCode = "238867",
        countryCode = "SGP"
    },
    contact = new {
        phone = "+6591234567",
        email = "billing@example.sg"
    }
};

var response = await client.PostAsJsonAsync($"{API_URL}/buyers", buyerData);
var result = await response.Content.ReadFromJsonAsync<JsonElement>();
var buyerId = result.GetProperty("data").GetProperty("id").GetString();

Console.WriteLine($"Created Buyer: {result.GetProperty("data").GetProperty("name")}");
Console.WriteLine($"Buyer ID: {buyerId}");

Response

json
{
  "success": true,
  "data": {
    "id": "9e1a2b3c-4d5e-6f7a-8b9c-0d1e2f3a4b5c",
    "name": "Example Trading Pte Ltd",
    "tin": "EI00000000020",
    "id_type": "PASSPORT",
    "id_value": "A12345678",
    "is_ready": true,
    "address": {
      "line1": "123 Orchard Road",
      "line2": "#10-01 Plaza Tower",
      "city": "Singapore",
      "state": "17",
      "postCode": "238867",
      "countryCode": "SGP"
    },
    "contact": {
      "phone": "+6591234567",
      "email": "billing@example.sg"
    }
  }
}

Save the UUID!

You'll need the id (UUID) for the next step.


Step 2: Create an Invoice

Create an invoice with line items. Use autoCalculate: true to let the system calculate all totals.

javascript
const invoiceData = {
  buyerId: buyerId,  // UUID from Step 1
  invoiceSerialNumber: 'INV-2024-001',
  currencyCode: 'MYR',
  autoCalculate: true,
  invoiceLines: [
    {
      classifications: ['001'],
      productDescription: 'Web Development Services',
      quantity: 1,
      unitCode: 'H87',
      unitPrice: 5000.00,
      invoiceLineTaxes: [
        { taxType: '01', taxRate: 8 },
      ],
    },
    {
      classifications: ['001'],
      productDescription: 'Monthly Hosting',
      quantity: 12,
      unitCode: 'MON',
      unitPrice: 150.00,
      discountRate: 10,
      invoiceLineTaxes: [
        { taxType: '01', taxRate: 8 },
      ],
    },
  ],
};

const invoice = await api('POST', '/invoices', invoiceData);
const invoiceId = invoice.data.id;

console.log(`Created Invoice: ${invoice.data.invoiceSerialNumber}`);
console.log(`Invoice ID: ${invoiceId}`);
console.log(`Total Payable: RM ${invoice.data.payableAmount}`);
python
invoice_data = {
    'buyerId': buyer_id,  # UUID from Step 1
    'invoiceSerialNumber': 'INV-2024-001',
    'currencyCode': 'MYR',
    'autoCalculate': True,
    'invoiceLines': [
        {
            'classifications': ['001'],
            'productDescription': 'Web Development Services',
            'quantity': 1,
            'unitCode': 'H87',
            'unitPrice': 5000.00,
            'invoiceLineTaxes': [
                {'taxType': '01', 'taxRate': 8},
            ],
        },
        {
            'classifications': ['001'],
            'productDescription': 'Monthly Hosting',
            'quantity': 12,
            'unitCode': 'MON',
            'unitPrice': 150.00,
            'discountRate': 10,
            'invoiceLineTaxes': [
                {'taxType': '01', 'taxRate': 8},
            ],
        },
    ],
}

invoice = api('POST', '/invoices', invoice_data)
invoice_id = invoice['data']['id']

print(f"Created Invoice: {invoice['data']['invoiceSerialNumber']}")
print(f"Invoice ID: {invoice_id}")
print(f"Total Payable: RM {invoice['data']['payableAmount']}")
php
$invoiceData = [
    'buyerId' => $buyerId,  // UUID from Step 1
    'invoiceSerialNumber' => 'INV-2024-001',
    'currencyCode' => 'MYR',
    'autoCalculate' => true,
    'invoiceLines' => [
        [
            'classifications' => ['001'],
            'productDescription' => 'Web Development Services',
            'quantity' => 1,
            'unitCode' => 'H87',
            'unitPrice' => 5000.00,
            'invoiceLineTaxes' => [
                ['taxType' => '01', 'taxRate' => 8],
            ],
        ],
        [
            'classifications' => ['001'],
            'productDescription' => 'Monthly Hosting',
            'quantity' => 12,
            'unitCode' => 'MON',
            'unitPrice' => 150.00,
            'discountRate' => 10,
            'invoiceLineTaxes' => [
                ['taxType' => '01', 'taxRate' => 8],
            ],
        ],
    ],
];

$response = $api->post('/invoices', $invoiceData);
$invoice = $response->json('data');
$invoiceId = $invoice['id'];

echo "Created Invoice: {$invoice['invoiceSerialNumber']}\n";
echo "Invoice ID: $invoiceId\n";
echo "Total Payable: RM {$invoice['payableAmount']}\n";
php
$invoiceData = [
    'buyerId' => $buyerId,
    'invoiceSerialNumber' => 'INV-2024-001',
    'currencyCode' => 'MYR',
    'autoCalculate' => true,
    'invoiceLines' => [
        [
            'classifications' => ['001'],
            'productDescription' => 'Web Development Services',
            'quantity' => 1,
            'unitCode' => 'H87',
            'unitPrice' => 5000.00,
            'invoiceLineTaxes' => [
                ['taxType' => '01', 'taxRate' => 8],
            ],
        ],
        [
            'classifications' => ['001'],
            'productDescription' => 'Monthly Hosting',
            'quantity' => 12,
            'unitCode' => 'MON',
            'unitPrice' => 150.00,
            'discountRate' => 10,
            'invoiceLineTaxes' => [
                ['taxType' => '01', 'taxRate' => 8],
            ],
        ],
    ],
];

$response = $client->post('invoices', ['json' => $invoiceData]);
$invoice = json_decode($response->getBody(), true)['data'];
$invoiceId = $invoice['id'];

echo "Created Invoice: {$invoice['invoiceSerialNumber']}\n";
echo "Invoice ID: $invoiceId\n";
echo "Total Payable: RM {$invoice['payableAmount']}\n";
java
String invoiceJson = String.format("""
{
    "buyerId": "%s",
    "invoiceSerialNumber": "INV-2024-001",
    "currencyCode": "MYR",
    "autoCalculate": true,
    "invoiceLines": [
        {
            "classifications": ["001"],
            "productDescription": "Web Development Services",
            "quantity": 1,
            "unitCode": "H87",
            "unitPrice": 5000.00,
            "invoiceLineTaxes": [
                {"taxType": "01", "taxRate": 8}
            ]
        },
        {
            "classifications": ["001"],
            "productDescription": "Monthly Hosting",
            "quantity": 12,
            "unitCode": "MON",
            "unitPrice": 150.00,
            "discountRate": 10,
            "invoiceLineTaxes": [
                {"taxType": "01", "taxRate": 8}
            ]
        }
    ]
}
""", buyerId);

HttpRequest request = requestBuilder("/invoices")
    .POST(HttpRequest.BodyPublishers.ofString(invoiceJson))
    .build();

HttpResponse<String> response = client.send(request,
    HttpResponse.BodyHandlers.ofString());

JsonObject invoice = JsonParser.parseString(response.body())
    .getAsJsonObject().getAsJsonObject("data");
String invoiceId = invoice.get("id").getAsString();

System.out.println("Created Invoice: " + invoice.get("invoiceSerialNumber"));
System.out.println("Invoice ID: " + invoiceId);
System.out.println("Total Payable: RM " + invoice.get("payableAmount"));
csharp
var invoiceData = new {
    buyerId = buyerId,  // UUID from Step 1
    invoiceSerialNumber = "INV-2024-001",
    currencyCode = "MYR",
    autoCalculate = true,
    invoiceLines = new[] {
        new {
            classifications = new[] { "001" },
            productDescription = "Web Development Services",
            quantity = 1,
            unitCode = "H87",
            unitPrice = 5000.00,
            invoiceLineTaxes = new[] {
                new { taxType = "01", taxRate = 8 }
            }
        },
        new {
            classifications = new[] { "001" },
            productDescription = "Monthly Hosting",
            quantity = 12,
            unitCode = "MON",
            unitPrice = 150.00,
            discountRate = 10,
            invoiceLineTaxes = new[] {
                new { taxType = "01", taxRate = 8 }
            }
        }
    }
};

var response = await client.PostAsJsonAsync($"{API_URL}/invoices", invoiceData);
var result = await response.Content.ReadFromJsonAsync<JsonElement>();
var invoiceId = result.GetProperty("data").GetProperty("id").GetString();

Console.WriteLine($"Created Invoice: {result.GetProperty("data").GetProperty("invoiceSerialNumber")}");
Console.WriteLine($"Invoice ID: {invoiceId}");
Console.WriteLine($"Total Payable: RM {result.GetProperty("data").GetProperty("payableAmount")}");

Response

json
{
  "success": true,
  "data": {
    "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "type": "invoice",
    "invoiceSerialNumber": "INV-2024-001",
    "status": "draft",
    "currencyCode": "MYR",
    "totalNetAmount": "6620.00",
    "totalTaxAmount": "529.60",
    "payableAmount": "7149.60",
    "buyer": {
      "id": "9e1a2b3c-4d5e-6f7a-8b9c-0d1e2f3a4b5c",
      "name": "Example Trading Pte Ltd",
      "tin": "EI00000000020"
    }
  }
}

Step 3: Validate the Invoice

Before submitting to LHDN, validate the invoice to check for any errors.

javascript
const validation = await api('POST', `/documents/${invoiceId}/validate`);

if (validation.data.validation_passed) {
  console.log(`Validation passed! Status: ${validation.data.status}`);
} else {
  console.log('Validation failed:', validation.errors);
}
python
validation = api('POST', f'/documents/{invoice_id}/validate')

if validation['data'].get('validation_passed'):
    print(f"Validation passed! Status: {validation['data']['status']}")
else:
    print('Validation failed:', validation.get('errors'))
php
$response = $api->post("/documents/$invoiceId/validate");
$result = $response->json('data');

if ($result['validation_passed'] ?? false) {
    echo "Validation passed! Status: {$result['status']}\n";
} else {
    echo "Validation failed.\n";
    print_r($response->json('errors'));
}
php
$response = $client->post("documents/$invoiceId/validate");
$result = json_decode($response->getBody(), true)['data'];

if ($result['validation_passed'] ?? false) {
    echo "Validation passed! Status: {$result['status']}\n";
} else {
    echo "Validation failed.\n";
}
java
HttpRequest request = requestBuilder("/documents/" + invoiceId + "/validate")
    .POST(HttpRequest.BodyPublishers.noBody())
    .build();

HttpResponse<String> response = client.send(request,
    HttpResponse.BodyHandlers.ofString());

JsonObject result = JsonParser.parseString(response.body())
    .getAsJsonObject().getAsJsonObject("data");

if (result.get("validation_passed").getAsBoolean()) {
    System.out.println("Validation passed! Status: " + result.get("status"));
} else {
    System.out.println("Validation failed.");
}
csharp
var response = await client.PostAsync($"{API_URL}/documents/{invoiceId}/validate", null);
var result = await response.Content.ReadFromJsonAsync<JsonElement>();

if (result.GetProperty("data").GetProperty("validation_passed").GetBoolean()) {
    Console.WriteLine($"Validation passed! Status: {result.GetProperty("data").GetProperty("status")}");
} else {
    Console.WriteLine("Validation failed.");
}

Response

json
{
  "success": true,
  "data": {
    "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "status": "ready",
    "validation_passed": true,
    "message": "Document validated successfully and marked as ready for submission"
  }
}

Step 4: Submit to LHDN

Submit the validated invoice to LHDN's MyInvois system.

javascript
const submission = await api('POST', `/documents/${invoiceId}/submit`);

console.log(`Status: ${submission.data.status}`);
console.log(`LHDN Document UUID: ${submission.data.document_uuid}`);
python
submission = api('POST', f'/documents/{invoice_id}/submit')

print(f"Status: {submission['data']['status']}")
print(f"LHDN Document UUID: {submission['data']['document_uuid']}")
php
$response = $api->post("/documents/$invoiceId/submit");
$result = $response->json('data');

echo "Status: {$result['status']}\n";
echo "LHDN Document UUID: {$result['document_uuid']}\n";
php
$response = $client->post("documents/$invoiceId/submit");
$result = json_decode($response->getBody(), true)['data'];

echo "Status: {$result['status']}\n";
echo "LHDN Document UUID: {$result['document_uuid']}\n";
java
HttpRequest request = requestBuilder("/documents/" + invoiceId + "/submit")
    .POST(HttpRequest.BodyPublishers.noBody())
    .build();

HttpResponse<String> response = client.send(request,
    HttpResponse.BodyHandlers.ofString());

JsonObject result = JsonParser.parseString(response.body())
    .getAsJsonObject().getAsJsonObject("data");

System.out.println("Status: " + result.get("status"));
System.out.println("LHDN Document UUID: " + result.get("document_uuid"));
csharp
var response = await client.PostAsync($"{API_URL}/documents/{invoiceId}/submit", null);
var result = await response.Content.ReadFromJsonAsync<JsonElement>();

Console.WriteLine($"Status: {result.GetProperty("data").GetProperty("status")}");
Console.WriteLine($"LHDN Document UUID: {result.GetProperty("data").GetProperty("document_uuid")}");

Response

json
{
  "success": true,
  "data": {
    "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "status": "Submitted",
    "document_uuid": "QZSABHBPPZH51WM6G06KSSBK10",
    "invoice_code_number": "INV-2024-001",
    "message": "Document submitted successfully to LHDN"
  }
}

Save the document_uuid

This is LHDN's unique identifier for your invoice. You'll need it for verification.


Step 5: Check Status

After submission, LHDN validates the document. Check the status to confirm acceptance.

javascript
// Wait a few seconds for LHDN processing
await new Promise(resolve => setTimeout(resolve, 3000));

const status = await api('GET', `/documents/${invoiceId}/status`);

console.log(`Status: ${status.data.status}`);
console.log(`Validated At: ${status.data.validated_at || 'Pending'}`);
python
import time

# Wait a few seconds for LHDN processing
time.sleep(3)

status = api('GET', f'/documents/{invoice_id}/status')

print(f"Status: {status['data']['status']}")
print(f"Validated At: {status['data'].get('validated_at', 'Pending')}")
php
// Wait a few seconds for LHDN processing
sleep(3);

$response = $api->get("/documents/$invoiceId/status");
$result = $response->json('data');

echo "Status: {$result['status']}\n";
echo "Validated At: " . ($result['validated_at'] ?? 'Pending') . "\n";
php
sleep(3);

$response = $client->get("documents/$invoiceId/status");
$result = json_decode($response->getBody(), true)['data'];

echo "Status: {$result['status']}\n";
echo "Validated At: " . ($result['validated_at'] ?? 'Pending') . "\n";
java
Thread.sleep(3000);

HttpRequest request = requestBuilder("/documents/" + invoiceId + "/status")
    .GET()
    .build();

HttpResponse<String> response = client.send(request,
    HttpResponse.BodyHandlers.ofString());

JsonObject result = JsonParser.parseString(response.body())
    .getAsJsonObject().getAsJsonObject("data");

System.out.println("Status: " + result.get("status"));
csharp
await Task.Delay(3000);

var response = await client.GetAsync($"{API_URL}/documents/{invoiceId}/status");
var result = await response.Content.ReadFromJsonAsync<JsonElement>();

Console.WriteLine($"Status: {result.GetProperty("data").GetProperty("status")}");

Status Values

StatusMeaning
SubmittedSent to LHDN, awaiting validation
ValidAccepted by LHDN
InvalidRejected by LHDN (check errors for details)

Step 6: Get the QR Code

Once the invoice is Valid, retrieve the QR code for customer verification.

javascript
const qr = await api('GET', `/documents/${invoiceId}/qr`);

console.log(`Verification URL: ${qr.data.verification_url}`);

// Save QR code to file (base64 data URI)
const qrData = qr.data.qr_code.replace('data:image/png;base64,', '');
fs.writeFileSync('invoice-qr.png', Buffer.from(qrData, 'base64'));
console.log('QR code saved to: invoice-qr.png');
python
import base64

qr = api('GET', f'/documents/{invoice_id}/qr')

print(f"Verification URL: {qr['data']['verification_url']}")

# Save QR code to file
qr_data = qr['data']['qr_code'].replace('data:image/png;base64,', '')
with open('invoice-qr.png', 'wb') as f:
    f.write(base64.b64decode(qr_data))
print('QR code saved to: invoice-qr.png')
php
$response = $api->get("/documents/$invoiceId/qr");
$result = $response->json('data');

echo "Verification URL: {$result['verification_url']}\n";

// Save QR code to file
$qrData = str_replace('data:image/png;base64,', '', $result['qr_code']);
file_put_contents('invoice-qr.png', base64_decode($qrData));
echo "QR code saved to: invoice-qr.png\n";
php
$response = $client->get("documents/$invoiceId/qr");
$result = json_decode($response->getBody(), true)['data'];

echo "Verification URL: {$result['verification_url']}\n";

$qrData = str_replace('data:image/png;base64,', '', $result['qr_code']);
file_put_contents('invoice-qr.png', base64_decode($qrData));
echo "QR code saved to: invoice-qr.png\n";
java
HttpRequest request = requestBuilder("/documents/" + invoiceId + "/qr")
    .GET()
    .build();

HttpResponse<String> response = client.send(request,
    HttpResponse.BodyHandlers.ofString());

JsonObject result = JsonParser.parseString(response.body())
    .getAsJsonObject().getAsJsonObject("data");

System.out.println("Verification URL: " + result.get("verification_url"));

// Save QR code to file
String qrData = result.get("qr_code").getAsString()
    .replace("data:image/png;base64,", "");
Files.write(Path.of("invoice-qr.png"),
    Base64.getDecoder().decode(qrData));
System.out.println("QR code saved to: invoice-qr.png");
csharp
var response = await client.GetAsync($"{API_URL}/documents/{invoiceId}/qr");
var result = await response.Content.ReadFromJsonAsync<JsonElement>();

Console.WriteLine($"Verification URL: {result.GetProperty("data").GetProperty("verification_url")}");

// Save QR code to file
var qrData = result.GetProperty("data").GetProperty("qr_code").GetString()
    .Replace("data:image/png;base64,", "");
File.WriteAllBytes("invoice-qr.png", Convert.FromBase64String(qrData));
Console.WriteLine("QR code saved to: invoice-qr.png");

Response

json
{
  "success": true,
  "data": {
    "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
    "qr_code": "data:image/png;base64,iVBORw0KGgo...",
    "verification_url": "https://myinvois.hasil.gov.my/..."
  }
}

Next Steps

Congratulations! You've submitted your first e-invoice to LHDN.

InvoisX - Malaysia's Leading e-Invoice Platform