In the Saudi Arabian business landscape, the QR code on an e-invoice is far more than a simple URL shortcut. It is a strictly encoded, cryptographic data structure mandated by the Zakat, Tax and Customs Authority (ZATCA). Whether you are in Phase 1 (Generation) or Phase 2 (Integration), ensuring your QR code complies with the TLV (Tag-Length-Value) encoding standard is critical to avoiding fines and invoice rejections.
This guide provides a comprehensive breakdown of the technical requirements, the underlying TLV binary structure, and a complete TypeScript/Node.js implementation.
1. What is TLV Encoding?
ZATCA requires QR code data to be formatted using the TLV (Tag-Length-Value) method before being converted into a Base64 string. This ensures that the data is compact, deterministic, and easily readable by the Fatoora simulation and production environments.
The Anatomy of TLV
- Tag: A 1-byte identifier for the data field (e.g., Tag 1 for Seller Name).
- Length: The length (in bytes) of the value field.
- Value: The raw UTF-8 byte representation of the data.
Required Fields for Phase 1 (Simplified & Standard Invoices)
For Phase 1, the QR code must contain the following five tags:
| Tag | Field Name | Description | Example |
|---|---|---|---|
| 1 | Seller Name | Legal entity name as registered with ZATCA | Qeemah Software |
| 2 | VAT Number | 15-digit VAT registration number | 300000000000003 |
| 3 | Timestamp | Invoice issuance timestamp (ISO 8601 UTC/Z) | 2026-10-23T06:00:00Z |
| 4 | Invoice Total | Total invoice amount including VAT | 1150.00 |
| 5 | VAT Total | Total VAT amount charged | 150.00 |
2. Phase 2: Cryptographic Extensions
In Phase 2 (Integration Phase), the QR code for Simplified Tax Invoices (B2C) becomes a cryptographic proof of document integrity.
In addition to Tags 1 through 5, Phase 2 mandates four additional cryptographic tags:
- Tag 6 (Invoice Hash): The SHA-256 hash of the sanitized invoice XML.
- Tag 7 (Digital Signature): An ECDSA digital signature (secp256k1) generated using the private key associated with your Cryptographic Stamp (CSID).
- Tag 8 (Public Key): The ECDSA public key used by ZATCA to verify the signature.
- Tag 9 (Certificate Signature): For simplified invoices, the digital signature of the CSID certificate itself.
3. Step-by-Step Implementation in Node.js / TypeScript
Here is a clean, production-ready utility to generate compliant ZATCA TLV Base64 QR strings:
import { Buffer } from "node:buffer";
interface ZATCAQRData {
sellerName: string;
vatNumber: string;
timestamp: string;
invoiceTotal: string;
vatTotal: string;
invoiceHash?: string;
signature?: string;
publicKey?: string;
certificateSignature?: string;
}
function encodeTLVField(tag: number, value: string | Buffer): Buffer {
const valBuf = Buffer.isBuffer(value) ? value : Buffer.from(value, "utf8");
const tagBuf = Buffer.from([tag]);
const lenBuf = Buffer.from([valBuf.length]);
return Buffer.concat([tagBuf, lenBuf, valBuf]);
}
export function generateZATCAQRCode(data: ZATCAQRData): string {
const buffers: Buffer[] = [
encodeTLVField(1, data.sellerName),
encodeTLVField(2, data.vatNumber),
encodeTLVField(3, data.timestamp),
encodeTLVField(4, data.invoiceTotal),
encodeTLVField(5, data.vatTotal),
];
if (data.invoiceHash) {
buffers.push(encodeTLVField(6, data.invoiceHash));
}
if (data.signature) {
buffers.push(encodeTLVField(7, data.signature));
}
if (data.publicKey) {
buffers.push(encodeTLVField(8, data.publicKey));
}
if (data.certificateSignature) {
buffers.push(encodeTLVField(9, data.certificateSignature));
}
const combined = Buffer.concat(buffers);
return combined.toString("base64");
}
4. Common Validation Pitfalls
When submitting to the Fatoora portal, common rejection errors include:
-
BR-KSA-26/BR-KSA-27: The QR code does not conform to the TLV structure or is missing mandatory tags. -
Timestamp Mismatch: The timestamp in Tag 3 must match the
cbc:IssueDateandcbc:IssueTimeXML elements exactly to the second. - Character Encoding: Seller names with Arabic characters must be encoded strictly in UTF-8 to ensure byte-length calculations match the TLV length header.
Conclusion & Resources
Building compliant e-invoicing pipelines requires strict adherence to cryptographic standards and binary data structures.
If you are developing or managing business infrastructure in Saudi Arabia, Qeemah provides a modern, fully compliant cloud ERP and accounting platform with native ZATCA Phase 2 clearance and automated cryptographic stamping.
Original article published on Qeemah Cloud Accounting.
Top comments (0)