Appearance
Complete Flow Example
Here's a complete working example that you can copy and run. This script creates a buyer, creates an invoice, validates it, submits to LHDN, and retrieves the QR code.
Before Running
Replace your-api-token-here with your actual API token from the InvoisX dashboard.
javascript
/**
* InvoisX Complete Flow Example
*
* Run with: node complete-flow.js
*/
const fs = require('fs');
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);
const json = await response.json();
if (!response.ok) {
throw new Error(json.message || 'API request failed');
}
return json;
}
async function main() {
console.log('=== InvoisX Complete Flow ===\n');
// Step 1: Create Buyer
console.log('Step 1: Creating buyer...');
const buyer = await api('POST', '/buyers', {
name: 'Example Trading Pte Ltd',
tin: 'EI00000000020',
id_type: 'PASSPORT',
id_value: 'A12345678',
address: {
line1: '123 Orchard Road',
city: 'Singapore',
state: '17',
postCode: '238867',
countryCode: 'SGP',
},
contact: {
phone: '+6591234567',
email: 'billing@example.sg',
},
});
const buyerId = buyer.data.id;
console.log(`Created buyer: ${buyerId}\n`);
// Step 2: Create Invoice
console.log('Step 2: Creating invoice...');
const invoice = await api('POST', '/invoices', {
buyerId: buyerId,
invoiceSerialNumber: `INV-${Date.now()}`,
currencyCode: 'MYR',
autoCalculate: true,
invoiceLines: [
{
classifications: ['001'],
productDescription: 'Consulting Services',
quantity: 10,
unitCode: 'H87',
unitPrice: 500.00,
invoiceLineTaxes: [
{ taxType: '01', taxRate: 8 },
],
},
],
});
const invoiceId = invoice.data.id;
const payable = invoice.data.payableAmount;
console.log(`Created invoice: ${invoiceId} (RM ${payable})\n`);
// Step 3: Validate
console.log('Step 3: Validating invoice...');
const validation = await api('POST', `/documents/${invoiceId}/validate`);
console.log(`Validation: ${validation.data.status}\n`);
// Step 4: Submit to LHDN
console.log('Step 4: Submitting to LHDN...');
const submission = await api('POST', `/documents/${invoiceId}/submit`);
const documentUuid = submission.data.document_uuid;
console.log(`Submitted! LHDN UUID: ${documentUuid}\n`);
// Step 5: Check Status
console.log('Step 5: Checking LHDN status...');
let status = 'Submitted';
let attempts = 0;
while (status === 'Submitted' && attempts < 10) {
await new Promise(resolve => setTimeout(resolve, 2000));
attempts++;
const statusCheck = await api('GET', `/documents/${invoiceId}/status`);
status = statusCheck.data.status;
console.log(`Attempt ${attempts}: ${status}`);
}
console.log();
// Step 6: Get QR Code
if (status === 'Valid') {
console.log('Step 6: Getting QR code...');
const qr = await api('GET', `/documents/${invoiceId}/qr`);
console.log(`Verification URL: ${qr.data.verification_url}`);
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');
}
console.log('\n=== Complete! ===');
}
main().catch(console.error);python
"""
InvoisX Complete Flow Example
Run with: python complete_flow.py
"""
import requests
import time
import base64
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)
if not response.ok:
raise Exception(response.json().get('message', 'API request failed'))
return response.json()
def main():
print('=== InvoisX Complete Flow ===\n')
# Step 1: Create Buyer
print('Step 1: Creating buyer...')
buyer = api('POST', '/buyers', {
'name': 'Example Trading Pte Ltd',
'tin': 'EI00000000020',
'id_type': 'PASSPORT',
'id_value': 'A12345678',
'address': {
'line1': '123 Orchard Road',
'city': 'Singapore',
'state': '17',
'postCode': '238867',
'countryCode': 'SGP',
},
'contact': {
'phone': '+6591234567',
'email': 'billing@example.sg',
},
})
buyer_id = buyer['data']['id']
print(f'Created buyer: {buyer_id}\n')
# Step 2: Create Invoice
print('Step 2: Creating invoice...')
invoice = api('POST', '/invoices', {
'buyerId': buyer_id,
'invoiceSerialNumber': f'INV-{int(time.time())}',
'currencyCode': 'MYR',
'autoCalculate': True,
'invoiceLines': [
{
'classifications': ['001'],
'productDescription': 'Consulting Services',
'quantity': 10,
'unitCode': 'H87',
'unitPrice': 500.00,
'invoiceLineTaxes': [
{'taxType': '01', 'taxRate': 8},
],
},
],
})
invoice_id = invoice['data']['id']
payable = invoice['data']['payableAmount']
print(f'Created invoice: {invoice_id} (RM {payable})\n')
# Step 3: Validate
print('Step 3: Validating invoice...')
validation = api('POST', f'/documents/{invoice_id}/validate')
print(f"Validation: {validation['data']['status']}\n")
# Step 4: Submit to LHDN
print('Step 4: Submitting to LHDN...')
submission = api('POST', f'/documents/{invoice_id}/submit')
document_uuid = submission['data']['document_uuid']
print(f'Submitted! LHDN UUID: {document_uuid}\n')
# Step 5: Check Status
print('Step 5: Checking LHDN status...')
status = 'Submitted'
attempts = 0
while status == 'Submitted' and attempts < 10:
time.sleep(2)
attempts += 1
status_check = api('GET', f'/documents/{invoice_id}/status')
status = status_check['data']['status']
print(f'Attempt {attempts}: {status}')
print()
# Step 6: Get QR Code
if status == 'Valid':
print('Step 6: Getting QR code...')
qr = api('GET', f'/documents/{invoice_id}/qr')
print(f"Verification URL: {qr['data']['verification_url']}")
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')
print('\n=== Complete! ===')
if __name__ == '__main__':
main()php
<?php
/**
* InvoisX Complete Flow Example (Laravel)
*
* Add to a route or run with: php artisan tinker < complete_flow.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);
echo "=== InvoisX Complete Flow ===\n\n";
// Step 1: Create Buyer
echo "Step 1: Creating buyer...\n";
$response = $api->post('/buyers', [
'name' => 'Example Trading Pte Ltd',
'tin' => 'EI00000000020',
'id_type' => 'PASSPORT',
'id_value' => 'A12345678',
'address' => [
'line1' => '123 Orchard Road',
'city' => 'Singapore',
'state' => '17',
'postCode' => '238867',
'countryCode' => 'SGP',
],
'contact' => [
'phone' => '+6591234567',
'email' => 'billing@example.sg',
],
]);
if ($response->failed()) {
throw new Exception("Failed to create buyer: " . $response->body());
}
$buyerId = $response->json('data.id');
echo "Created buyer: $buyerId\n\n";
// Step 2: Create Invoice
echo "Step 2: Creating invoice...\n";
$response = $api->post('/invoices', [
'buyerId' => $buyerId,
'invoiceSerialNumber' => 'INV-' . time(),
'currencyCode' => 'MYR',
'autoCalculate' => true,
'invoiceLines' => [
[
'classifications' => ['001'],
'productDescription' => 'Consulting Services',
'quantity' => 10,
'unitCode' => 'H87',
'unitPrice' => 500.00,
'invoiceLineTaxes' => [
['taxType' => '01', 'taxRate' => 8],
],
],
],
]);
if ($response->failed()) {
throw new Exception("Failed to create invoice: " . $response->body());
}
$invoiceId = $response->json('data.id');
$payable = $response->json('data.payableAmount');
echo "Created invoice: $invoiceId (RM $payable)\n\n";
// Step 3: Validate
echo "Step 3: Validating invoice...\n";
$response = $api->post("/documents/$invoiceId/validate");
$status = $response->json('data.status');
echo "Validation: $status\n\n";
// Step 4: Submit to LHDN
echo "Step 4: Submitting to LHDN...\n";
$response = $api->post("/documents/$invoiceId/submit");
$documentUuid = $response->json('data.document_uuid');
echo "Submitted! LHDN UUID: $documentUuid\n\n";
// Step 5: Check Status
echo "Step 5: Checking LHDN status...\n";
$status = 'Submitted';
$attempts = 0;
while ($status === 'Submitted' && $attempts < 10) {
sleep(2);
$attempts++;
$response = $api->get("/documents/$invoiceId/status");
$status = $response->json('data.status');
echo "Attempt $attempts: $status\n";
}
echo "\n";
// Step 6: Get QR Code
if ($status === 'Valid') {
echo "Step 6: Getting QR code...\n";
$response = $api->get("/documents/$invoiceId/qr");
echo "Verification URL: " . $response->json('data.verification_url') . "\n";
$qrData = str_replace('data:image/png;base64,', '', $response->json('data.qr_code'));
file_put_contents('invoice-qr.png', base64_decode($qrData));
echo "QR code saved to: invoice-qr.png\n";
}
echo "\n=== Complete! ===\n";php
<?php
/**
* InvoisX Complete Flow Example (Guzzle)
*
* Run with: php complete_flow.php
*/
require_once 'vendor/autoload.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',
],
]);
function api($client, $method, $endpoint, $data = null) {
$options = [];
if ($data) {
$options['json'] = $data;
}
$response = $client->request($method, $endpoint, $options);
return json_decode($response->getBody(), true);
}
echo "=== InvoisX Complete Flow ===\n\n";
// Step 1: Create Buyer
echo "Step 1: Creating buyer...\n";
$buyer = api($client, 'POST', '/buyers', [
'name' => 'Example Trading Pte Ltd',
'tin' => 'EI00000000020',
'id_type' => 'PASSPORT',
'id_value' => 'A12345678',
'address' => [
'line1' => '123 Orchard Road',
'city' => 'Singapore',
'state' => '17',
'postCode' => '238867',
'countryCode' => 'SGP',
],
'contact' => [
'phone' => '+6591234567',
'email' => 'billing@example.sg',
],
]);
$buyerId = $buyer['data']['id'];
echo "Created buyer: $buyerId\n\n";
// Step 2: Create Invoice
echo "Step 2: Creating invoice...\n";
$invoice = api($client, 'POST', '/invoices', [
'buyerId' => $buyerId,
'invoiceSerialNumber' => 'INV-' . time(),
'currencyCode' => 'MYR',
'autoCalculate' => true,
'invoiceLines' => [
[
'classifications' => ['001'],
'productDescription' => 'Consulting Services',
'quantity' => 10,
'unitCode' => 'H87',
'unitPrice' => 500.00,
'invoiceLineTaxes' => [
['taxType' => '01', 'taxRate' => 8],
],
],
],
]);
$invoiceId = $invoice['data']['id'];
$payable = $invoice['data']['payableAmount'];
echo "Created invoice: $invoiceId (RM $payable)\n\n";
// Step 3: Validate
echo "Step 3: Validating invoice...\n";
$validation = api($client, 'POST', "/documents/$invoiceId/validate");
echo "Validation: {$validation['data']['status']}\n\n";
// Step 4: Submit to LHDN
echo "Step 4: Submitting to LHDN...\n";
$submission = api($client, 'POST', "/documents/$invoiceId/submit");
$documentUuid = $submission['data']['document_uuid'];
echo "Submitted! LHDN UUID: $documentUuid\n\n";
// Step 5: Check Status
echo "Step 5: Checking LHDN status...\n";
$status = 'Submitted';
$attempts = 0;
while ($status === 'Submitted' && $attempts < 10) {
sleep(2);
$attempts++;
$statusCheck = api($client, 'GET', "/documents/$invoiceId/status");
$status = $statusCheck['data']['status'];
echo "Attempt $attempts: $status\n";
}
echo "\n";
// Step 6: Get QR Code
if ($status === 'Valid') {
echo "Step 6: Getting QR code...\n";
$qr = api($client, 'GET', "/documents/$invoiceId/qr");
echo "Verification URL: {$qr['data']['verification_url']}\n";
$qrData = str_replace('data:image/png;base64,', '', $qr['data']['qr_code']);
file_put_contents('invoice-qr.png', base64_decode($qrData));
echo "QR code saved to: invoice-qr.png\n";
}
echo "\n=== Complete! ===\n";java
/**
* InvoisX Complete Flow Example
*
* Compile and run with:
* javac -cp gson.jar CompleteFlow.java
* java -cp .:gson.jar CompleteFlow
*/
import java.net.http.*;
import java.net.URI;
import java.nio.file.*;
import java.util.Base64;
import com.google.gson.*;
public class CompleteFlow {
private static final String API_URL = "https://invoisx.com/api/v1";
private static final String API_TOKEN = "your-api-token-here";
private static final HttpClient client = HttpClient.newHttpClient();
private static final Gson gson = new Gson();
public static void main(String[] args) throws Exception {
System.out.println("=== InvoisX Complete Flow ===\n");
// Step 1: Create Buyer
System.out.println("Step 1: Creating buyer...");
String buyerJson = """
{
"name": "Example Trading Pte Ltd",
"tin": "EI00000000020",
"id_type": "PASSPORT",
"id_value": "A12345678",
"address": {
"line1": "123 Orchard Road",
"city": "Singapore",
"state": "17",
"postCode": "238867",
"countryCode": "SGP"
},
"contact": {
"phone": "+6591234567",
"email": "billing@example.sg"
}
}
""";
JsonObject buyer = post("/buyers", buyerJson);
String buyerId = buyer.getAsJsonObject("data").get("id").getAsString();
System.out.println("Created buyer: " + buyerId + "\n");
// Step 2: Create Invoice
System.out.println("Step 2: Creating invoice...");
String invoiceJson = String.format("""
{
"buyerId": "%s",
"invoiceSerialNumber": "INV-%d",
"currencyCode": "MYR",
"autoCalculate": true,
"invoiceLines": [{
"classifications": ["001"],
"productDescription": "Consulting Services",
"quantity": 10,
"unitCode": "H87",
"unitPrice": 500.00,
"invoiceLineTaxes": [{"taxType": "01", "taxRate": 8}]
}]
}
""", buyerId, System.currentTimeMillis());
JsonObject invoice = post("/invoices", invoiceJson);
String invoiceId = invoice.getAsJsonObject("data").get("id").getAsString();
String payable = invoice.getAsJsonObject("data").get("payableAmount").getAsString();
System.out.println("Created invoice: " + invoiceId + " (RM " + payable + ")\n");
// Step 3: Validate
System.out.println("Step 3: Validating invoice...");
JsonObject validation = post("/documents/" + invoiceId + "/validate", null);
System.out.println("Validation: " + validation.getAsJsonObject("data").get("status") + "\n");
// Step 4: Submit to LHDN
System.out.println("Step 4: Submitting to LHDN...");
JsonObject submission = post("/documents/" + invoiceId + "/submit", null);
String documentUuid = submission.getAsJsonObject("data").get("document_uuid").getAsString();
System.out.println("Submitted! LHDN UUID: " + documentUuid + "\n");
// Step 5: Check Status
System.out.println("Step 5: Checking LHDN status...");
String status = "Submitted";
int attempts = 0;
while (status.equals("Submitted") && attempts < 10) {
Thread.sleep(2000);
attempts++;
JsonObject statusCheck = get("/documents/" + invoiceId + "/status");
status = statusCheck.getAsJsonObject("data").get("status").getAsString();
System.out.println("Attempt " + attempts + ": " + status);
}
System.out.println();
// Step 6: Get QR Code
if (status.equals("Valid")) {
System.out.println("Step 6: Getting QR code...");
JsonObject qr = get("/documents/" + invoiceId + "/qr");
System.out.println("Verification URL: " +
qr.getAsJsonObject("data").get("verification_url").getAsString());
String qrData = qr.getAsJsonObject("data").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");
}
System.out.println("\n=== Complete! ===");
}
private static JsonObject post(String endpoint, String body) throws Exception {
var builder = HttpRequest.newBuilder()
.uri(URI.create(API_URL + endpoint))
.header("Authorization", "Bearer " + API_TOKEN)
.header("Accept", "application/json")
.header("Content-Type", "application/json");
if (body != null) {
builder.POST(HttpRequest.BodyPublishers.ofString(body));
} else {
builder.POST(HttpRequest.BodyPublishers.noBody());
}
var response = client.send(builder.build(), HttpResponse.BodyHandlers.ofString());
return JsonParser.parseString(response.body()).getAsJsonObject();
}
private static JsonObject get(String endpoint) throws Exception {
var request = HttpRequest.newBuilder()
.uri(URI.create(API_URL + endpoint))
.header("Authorization", "Bearer " + API_TOKEN)
.header("Accept", "application/json")
.GET()
.build();
var response = client.send(request, HttpResponse.BodyHandlers.ofString());
return JsonParser.parseString(response.body()).getAsJsonObject();
}
}csharp
/**
* InvoisX Complete Flow Example
*
* Run with: dotnet run
*/
using System.Net.Http.Json;
using System.Text.Json;
const string API_URL = "https://invoisx.com/api/v1";
const string API_TOKEN = "your-api-token-here";
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", $"Bearer {API_TOKEN}");
client.DefaultRequestHeaders.Add("Accept", "application/json");
Console.WriteLine("=== InvoisX Complete Flow ===\n");
// Step 1: Create Buyer
Console.WriteLine("Step 1: Creating buyer...");
var buyerData = new {
name = "Example Trading Pte Ltd",
tin = "EI00000000020",
id_type = "PASSPORT",
id_value = "A12345678",
address = new {
line1 = "123 Orchard Road",
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 buyer = await response.Content.ReadFromJsonAsync<JsonElement>();
var buyerId = buyer.GetProperty("data").GetProperty("id").GetString();
Console.WriteLine($"Created buyer: {buyerId}\n");
// Step 2: Create Invoice
Console.WriteLine("Step 2: Creating invoice...");
var invoiceData = new {
buyerId = buyerId,
invoiceSerialNumber = $"INV-{DateTimeOffset.UtcNow.ToUnixTimeSeconds()}",
currencyCode = "MYR",
autoCalculate = true,
invoiceLines = new[] {
new {
classifications = new[] { "001" },
productDescription = "Consulting Services",
quantity = 10,
unitCode = "H87",
unitPrice = 500.00,
invoiceLineTaxes = new[] {
new { taxType = "01", taxRate = 8 }
}
}
}
};
response = await client.PostAsJsonAsync($"{API_URL}/invoices", invoiceData);
var invoice = await response.Content.ReadFromJsonAsync<JsonElement>();
var invoiceId = invoice.GetProperty("data").GetProperty("id").GetString();
var payable = invoice.GetProperty("data").GetProperty("payableAmount").GetString();
Console.WriteLine($"Created invoice: {invoiceId} (RM {payable})\n");
// Step 3: Validate
Console.WriteLine("Step 3: Validating invoice...");
response = await client.PostAsync($"{API_URL}/documents/{invoiceId}/validate", null);
var validation = await response.Content.ReadFromJsonAsync<JsonElement>();
Console.WriteLine($"Validation: {validation.GetProperty("data").GetProperty("status")}\n");
// Step 4: Submit to LHDN
Console.WriteLine("Step 4: Submitting to LHDN...");
response = await client.PostAsync($"{API_URL}/documents/{invoiceId}/submit", null);
var submission = await response.Content.ReadFromJsonAsync<JsonElement>();
var documentUuid = submission.GetProperty("data").GetProperty("document_uuid").GetString();
Console.WriteLine($"Submitted! LHDN UUID: {documentUuid}\n");
// Step 5: Check Status
Console.WriteLine("Step 5: Checking LHDN status...");
var status = "Submitted";
var attempts = 0;
while (status == "Submitted" && attempts < 10)
{
await Task.Delay(2000);
attempts++;
response = await client.GetAsync($"{API_URL}/documents/{invoiceId}/status");
var statusCheck = await response.Content.ReadFromJsonAsync<JsonElement>();
status = statusCheck.GetProperty("data").GetProperty("status").GetString() ?? "Unknown";
Console.WriteLine($"Attempt {attempts}: {status}");
}
Console.WriteLine();
// Step 6: Get QR Code
if (status == "Valid")
{
Console.WriteLine("Step 6: Getting QR code...");
response = await client.GetAsync($"{API_URL}/documents/{invoiceId}/qr");
var qr = await response.Content.ReadFromJsonAsync<JsonElement>();
Console.WriteLine($"Verification URL: {qr.GetProperty("data").GetProperty("verification_url")}");
var qrData = qr.GetProperty("data").GetProperty("qr_code").GetString()!
.Replace("data:image/png;base64,", "");
await File.WriteAllBytesAsync("invoice-qr.png", Convert.FromBase64String(qrData));
Console.WriteLine("QR code saved to: invoice-qr.png");
}
Console.WriteLine("\n=== Complete! ===");Expected Output
=== InvoisX Complete Flow ===
Step 1: Creating buyer...
Created buyer: 9e1a2b3c-4d5e-6f7a-8b9c-0d1e2f3a4b5c
Step 2: Creating invoice...
Created invoice: a1b2c3d4-e5f6-7890-abcd-ef1234567890 (RM 5400.00)
Step 3: Validating invoice...
Validation: ready
Step 4: Submitting to LHDN...
Submitted! LHDN UUID: QZSABHBPPZH51WM6G06KSSBK10
Step 5: Checking LHDN status...
Attempt 1: Submitted
Attempt 2: Valid
Step 6: Getting QR code...
Verification URL: https://myinvois.hasil.gov.my/...
QR code saved to: invoice-qr.png
=== Complete! ===Next Steps
- Buyer Guide - Learn more about buyer management
- Invoice Guide - Advanced invoice features
- Document Types - Credit notes, debit notes, and more
