Appearance
QR Codes & PDFs
Retrieve verification QR codes and PDF documents for LHDN-validated invoices.
Setup
Before using the examples below, set up your HTTP client:
javascript
const API_URL = 'https://invoisx.com/api/v1';
const API_TOKEN = 'your-api-token';
async function api(method, endpoint, data = null) {
const response = await fetch(`${API_URL}${endpoint}`, {
method,
headers: {
'Authorization': `Bearer ${API_TOKEN}`,
'Accept': 'application/json',
'Content-Type': 'application/json',
},
body: data ? JSON.stringify(data) : null,
});
return response.json();
}python
import requests
API_URL = 'https://invoisx.com/api/v1'
API_TOKEN = 'your-api-token'
def api(method, endpoint, data=None):
response = requests.request(
method,
f'{API_URL}{endpoint}',
headers={
'Authorization': f'Bearer {API_TOKEN}',
'Accept': 'application/json',
},
json=data
)
return response.json()php
use Illuminate\Support\Facades\Http;
$api = Http::withToken('your-api-token')
->accept('application/json')
->baseUrl('https://invoisx.com/api/v1');php
use GuzzleHttp\Client;
$client = new Client([
'base_uri' => 'https://invoisx.com/api/v1/',
'headers' => [
'Authorization' => 'Bearer your-api-token',
'Accept' => 'application/json',
'Content-Type' => 'application/json',
],
]);java
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
HttpClient client = HttpClient.newHttpClient();
String API_URL = "https://invoisx.com/api/v1";
String API_TOKEN = "your-api-token";csharp
using System.Net.Http;
using System.Net.Http.Json;
using System.Text.Json;
var client = new HttpClient {
BaseAddress = new Uri("https://invoisx.com/api/v1")
};
client.DefaultRequestHeaders.Add("Authorization", "Bearer your-api-token");
client.DefaultRequestHeaders.Add("Accept", "application/json");Overview
Once a document is Valid, you can:
- Generate a QR code for customer verification
- Retrieve a PDF version of the document
Both link to LHDN's official verification portal.
Getting the QR Code
JSON Response (Default)
Returns base64-encoded QR code and verification URL:
javascript
const qr = await api('GET', `/documents/${documentId}/qr`);
console.log(`Verification URL: ${qr.data.verification_url}`);
// Save QR code to file
const qrData = qr.data.qr_code.replace('data:image/png;base64,', '');
fs.writeFileSync('invoice-qr.png', Buffer.from(qrData, 'base64'));python
import base64
qr = api('GET', f'/documents/{document_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))php
$response = $api->get("/documents/$documentId/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));php
$response = $client->get("documents/$documentId/qr");
$result = json_decode($response->getBody(), true)['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));java
var request = HttpRequest.newBuilder()
.uri(URI.create(API_URL + "/documents/" + documentId + "/qr"))
.header("Authorization", "Bearer " + API_TOKEN)
.GET()
.build();
var response = client.send(request, HttpResponse.BodyHandlers.ofString());
// Parse JSON to get verification_url and qr_code
// Decode base64 qr_code and save to file
System.out.println("Response: " + response.body());csharp
var response = await client.GetAsync($"/documents/{documentId}/qr");
var json = await response.Content.ReadFromJsonAsync<JsonElement>();
var data = json.GetProperty("data");
Console.WriteLine($"Verification URL: {data.GetProperty("verification_url").GetString()}");
// Save QR code to file
var qrCode = data.GetProperty("qr_code").GetString();
var qrData = qrCode.Replace("data:image/png;base64,", "");
await File.WriteAllBytesAsync("invoice-qr.png", Convert.FromBase64String(qrData));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/..."
}
}Direct Image Response
Get the QR code as a ready-to-use image file:
javascript
// Get as PNG
const response = await fetch(`${API_URL}/documents/${documentId}/qr`, {
headers: {
'Authorization': `Bearer ${API_TOKEN}`,
'Accept': 'image/png' // Request image directly
}
});
const buffer = await response.arrayBuffer();
fs.writeFileSync('invoice-qr.png', Buffer.from(buffer));python
# Get as PNG
response = requests.get(
f'{API_URL}/documents/{document_id}/qr',
headers={
'Authorization': f'Bearer {API_TOKEN}',
'Accept': 'image/png' # Request image directly
}
)
with open('invoice-qr.png', 'wb') as f:
f.write(response.content)php
// Get as PNG
$response = Http::withToken($apiToken)
->accept('image/png') // Request image directly
->get("$apiUrl/documents/$documentId/qr");
file_put_contents('invoice-qr.png', $response->body());php
// Get as PNG
$response = $client->get("documents/$documentId/qr", [
'headers' => ['Accept' => 'image/png'] // Request image directly
]);
file_put_contents('invoice-qr.png', $response->getBody()->getContents());java
// Get as PNG
var request = HttpRequest.newBuilder()
.uri(URI.create(API_URL + "/documents/" + documentId + "/qr"))
.header("Authorization", "Bearer " + API_TOKEN)
.header("Accept", "image/png") // Request image directly
.GET()
.build();
var response = client.send(request, HttpResponse.BodyHandlers.ofByteArray());
Files.write(Path.of("invoice-qr.png"), response.body());csharp
// Get as PNG
using var request = new HttpRequestMessage(HttpMethod.Get, $"/documents/{documentId}/qr");
request.Headers.Accept.Clear();
request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("image/png"));
var response = await client.SendAsync(request);
var bytes = await response.Content.ReadAsByteArrayAsync();
await File.WriteAllBytesAsync("invoice-qr.png", bytes);Supported Image Formats
| Accept Header | Format |
|---|---|
image/png | PNG image |
image/jpeg | JPEG image |
application/json | JSON with base64 (default) |
Getting the PDF
Retrieve a PDF version of the document:
javascript
const response = await fetch(`${API_URL}/documents/${documentId}/pdf`, {
headers: {
'Authorization': `Bearer ${API_TOKEN}`,
'Accept': 'application/pdf'
}
});
const buffer = await response.arrayBuffer();
fs.writeFileSync('invoice.pdf', Buffer.from(buffer));
console.log('PDF saved to: invoice.pdf');python
response = requests.get(
f'{API_URL}/documents/{document_id}/pdf',
headers={
'Authorization': f'Bearer {API_TOKEN}',
'Accept': 'application/pdf'
}
)
with open('invoice.pdf', 'wb') as f:
f.write(response.content)
print('PDF saved to: invoice.pdf')php
$response = Http::withToken($apiToken)
->accept('application/pdf')
->get("$apiUrl/documents/$documentId/pdf");
if ($response->successful()) {
file_put_contents('invoice.pdf', $response->body());
echo "PDF saved to: invoice.pdf\n";
}php
$response = $client->get("documents/$documentId/pdf", [
'headers' => ['Accept' => 'application/pdf']
]);
file_put_contents('invoice.pdf', $response->getBody()->getContents());
echo "PDF saved to: invoice.pdf\n";java
var request = HttpRequest.newBuilder()
.uri(URI.create(API_URL + "/documents/" + documentId + "/pdf"))
.header("Authorization", "Bearer " + API_TOKEN)
.header("Accept", "application/pdf")
.GET()
.build();
var response = client.send(request, HttpResponse.BodyHandlers.ofByteArray());
Files.write(Path.of("invoice.pdf"), response.body());
System.out.println("PDF saved to: invoice.pdf");csharp
using var request = new HttpRequestMessage(HttpMethod.Get, $"/documents/{documentId}/pdf");
request.Headers.Accept.Clear();
request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/pdf"));
var response = await client.SendAsync(request);
var bytes = await response.Content.ReadAsByteArrayAsync();
await File.WriteAllBytesAsync("invoice.pdf", bytes);
Console.WriteLine("PDF saved to: invoice.pdf");Using QR Codes in Your Application
HTML Embed (Base64)
html
<img src="{{ qr_code }}" alt="LHDN Verification QR Code" />With Verification Link
html
<div class="verification">
<img src="{{ qr_code }}" alt="Scan to verify" />
<p>Scan to verify on LHDN MyInvois</p>
<a href="{{ verification_url }}">Or click here to verify</a>
</div>Print-Ready Invoice
html
<div class="invoice-footer">
<div class="qr-section">
<img src="{{ qr_code }}" width="100" height="100" />
<small>Scan to verify this e-invoice on LHDN MyInvois</small>
</div>
<div class="lhdn-info">
<p>Document UUID: {{ document_uuid }}</p>
<p>Validated: {{ validated_at }}</p>
</div>
</div>Error Handling
Document Not Valid
QR codes are only available for Valid documents:
json
{
"success": false,
"message": "QR code is only available for validated documents",
"error_code": "DOCUMENT_NOT_VALID"
}Solution: Wait for document to be validated by LHDN.
Checking Before Request
javascript
// Check status first
const status = await api('GET', `/documents/${documentId}/status`);
if (status.data.status === 'Valid') {
const qr = await api('GET', `/documents/${documentId}/qr`);
// Use QR code
} else {
console.log(`Document status: ${status.data.status}`);
}python
# Check status first
status = api('GET', f'/documents/{document_id}/status')
if status['data']['status'] == 'Valid':
qr = api('GET', f'/documents/{document_id}/qr')
# Use QR code
else:
print(f"Document status: {status['data']['status']}")php
// Check status first
$status = $api->get("/documents/$documentId/status")->json('data');
if ($status['status'] === 'Valid') {
$qr = $api->get("/documents/$documentId/qr")->json('data');
// Use QR code
} else {
echo "Document status: {$status['status']}\n";
}php
// Check status first
$response = $client->get("documents/$documentId/status");
$status = json_decode($response->getBody(), true)['data'];
if ($status['status'] === 'Valid') {
$response = $client->get("documents/$documentId/qr");
$qr = json_decode($response->getBody(), true)['data'];
// Use QR code
} else {
echo "Document status: {$status['status']}\n";
}java
// Check status first
var statusRequest = HttpRequest.newBuilder()
.uri(URI.create(API_URL + "/documents/" + documentId + "/status"))
.header("Authorization", "Bearer " + API_TOKEN)
.GET()
.build();
var statusResponse = client.send(statusRequest, HttpResponse.BodyHandlers.ofString());
// Parse JSON to check status
// If Valid, get QR code
var qrRequest = HttpRequest.newBuilder()
.uri(URI.create(API_URL + "/documents/" + documentId + "/qr"))
.header("Authorization", "Bearer " + API_TOKEN)
.GET()
.build();
var qrResponse = client.send(qrRequest, HttpResponse.BodyHandlers.ofString());
// Use QR codecsharp
// Check status first
var statusResponse = await client.GetAsync($"/documents/{documentId}/status");
var statusJson = await statusResponse.Content.ReadFromJsonAsync<JsonElement>();
var status = statusJson.GetProperty("data").GetProperty("status").GetString();
if (status == "Valid") {
var qrResponse = await client.GetAsync($"/documents/{documentId}/qr");
var qrJson = await qrResponse.Content.ReadFromJsonAsync<JsonElement>();
var qrData = qrJson.GetProperty("data");
// Use QR code
} else {
Console.WriteLine($"Document status: {status}");
}Complete Example
javascript
async function getInvoiceWithQR(documentId) {
// 1. Check status
const status = await api('GET', `/documents/${documentId}/status`);
if (status.data.status !== 'Valid') {
throw new Error(`Document not valid: ${status.data.status}`);
}
// 2. Get document details
const doc = await api('GET', `/invoices/${documentId}`);
// 3. Get QR code
const qr = await api('GET', `/documents/${documentId}/qr`);
return {
invoice: doc.data,
qr_code: qr.data.qr_code,
verification_url: qr.data.verification_url,
document_uuid: status.data.document_uuid,
validated_at: status.data.validated_at
};
}
const result = await getInvoiceWithQR(documentId);
console.log('Invoice:', result.invoice.invoiceSerialNumber);
console.log('Verification URL:', result.verification_url);python
def get_invoice_with_qr(document_id):
# 1. Check status
status = api('GET', f'/documents/{document_id}/status')
if status['data']['status'] != 'Valid':
raise Exception(f"Document not valid: {status['data']['status']}")
# 2. Get document details
doc = api('GET', f'/invoices/{document_id}')
# 3. Get QR code
qr = api('GET', f'/documents/{document_id}/qr')
return {
'invoice': doc['data'],
'qr_code': qr['data']['qr_code'],
'verification_url': qr['data']['verification_url'],
'document_uuid': status['data']['document_uuid'],
'validated_at': status['data']['validated_at']
}
result = get_invoice_with_qr(document_id)
print(f"Invoice: {result['invoice']['invoiceSerialNumber']}")
print(f"Verification URL: {result['verification_url']}")php
function getInvoiceWithQR($api, $documentId) {
// 1. Check status
$status = $api->get("/documents/$documentId/status")->json('data');
if ($status['status'] !== 'Valid') {
throw new Exception("Document not valid: {$status['status']}");
}
// 2. Get document details
$doc = $api->get("/invoices/$documentId")->json('data');
// 3. Get QR code
$qr = $api->get("/documents/$documentId/qr")->json('data');
return [
'invoice' => $doc,
'qr_code' => $qr['qr_code'],
'verification_url' => $qr['verification_url'],
'document_uuid' => $status['document_uuid'],
'validated_at' => $status['validated_at']
];
}
$result = getInvoiceWithQR($api, $documentId);
echo "Invoice: {$result['invoice']['invoiceSerialNumber']}\n";
echo "Verification URL: {$result['verification_url']}\n";php
function getInvoiceWithQR($client, $documentId) {
// 1. Check status
$response = $client->get("documents/$documentId/status");
$status = json_decode($response->getBody(), true)['data'];
if ($status['status'] !== 'Valid') {
throw new Exception("Document not valid: {$status['status']}");
}
// 2. Get document details
$response = $client->get("invoices/$documentId");
$doc = json_decode($response->getBody(), true)['data'];
// 3. Get QR code
$response = $client->get("documents/$documentId/qr");
$qr = json_decode($response->getBody(), true)['data'];
return [
'invoice' => $doc,
'qr_code' => $qr['qr_code'],
'verification_url' => $qr['verification_url'],
'document_uuid' => $status['document_uuid'],
'validated_at' => $status['validated_at']
];
}
$result = getInvoiceWithQR($client, $documentId);
echo "Invoice: {$result['invoice']['invoiceSerialNumber']}\n";
echo "Verification URL: {$result['verification_url']}\n";java
public Map<String, Object> getInvoiceWithQR(String documentId) throws Exception {
// 1. Check status
var statusRequest = HttpRequest.newBuilder()
.uri(URI.create(API_URL + "/documents/" + documentId + "/status"))
.header("Authorization", "Bearer " + API_TOKEN)
.GET()
.build();
var statusResponse = client.send(statusRequest, HttpResponse.BodyHandlers.ofString());
// Parse status from JSON
// 2. Get document details
var docRequest = HttpRequest.newBuilder()
.uri(URI.create(API_URL + "/invoices/" + documentId))
.header("Authorization", "Bearer " + API_TOKEN)
.GET()
.build();
var docResponse = client.send(docRequest, HttpResponse.BodyHandlers.ofString());
// 3. Get QR code
var qrRequest = HttpRequest.newBuilder()
.uri(URI.create(API_URL + "/documents/" + documentId + "/qr"))
.header("Authorization", "Bearer " + API_TOKEN)
.GET()
.build();
var qrResponse = client.send(qrRequest, HttpResponse.BodyHandlers.ofString());
// Return combined result
return Map.of(
"invoice", parseInvoice(docResponse.body()),
"qr_code", parseQrCode(qrResponse.body()),
"verification_url", parseVerificationUrl(qrResponse.body())
);
}
var result = getInvoiceWithQR(documentId);
System.out.println("Invoice: " + result.get("invoice"));
System.out.println("Verification URL: " + result.get("verification_url"));csharp
async Task<Dictionary<string, object>> GetInvoiceWithQR(string documentId) {
// 1. Check status
var statusResponse = await client.GetAsync($"/documents/{documentId}/status");
var statusJson = await statusResponse.Content.ReadFromJsonAsync<JsonElement>();
var status = statusJson.GetProperty("data");
if (status.GetProperty("status").GetString() != "Valid") {
throw new Exception($"Document not valid: {status.GetProperty("status").GetString()}");
}
// 2. Get document details
var docResponse = await client.GetAsync($"/invoices/{documentId}");
var docJson = await docResponse.Content.ReadFromJsonAsync<JsonElement>();
var doc = docJson.GetProperty("data");
// 3. Get QR code
var qrResponse = await client.GetAsync($"/documents/{documentId}/qr");
var qrJson = await qrResponse.Content.ReadFromJsonAsync<JsonElement>();
var qr = qrJson.GetProperty("data");
return new Dictionary<string, object> {
["invoice"] = doc,
["qr_code"] = qr.GetProperty("qr_code").GetString(),
["verification_url"] = qr.GetProperty("verification_url").GetString(),
["document_uuid"] = status.GetProperty("document_uuid").GetString(),
["validated_at"] = status.GetProperty("validated_at").GetString()
};
}
var result = await GetInvoiceWithQR(documentId);
Console.WriteLine($"Invoice: {((JsonElement)result["invoice"]).GetProperty("invoiceSerialNumber").GetString()}");
Console.WriteLine($"Verification URL: {result["verification_url"]}");Next Steps
- API Reference - Complete API documentation
- Error Codes - Error handling reference
