ZATCA e-invoicing phase 2: what we learned integrating POS and inventory systems with Fatoora
No feature is requested by a Saudi merchant before “is the system connected to ZATCA?”. Phase 2 of e-invoicing (integration) turned the invoice from a printed slip into a digitally signed XML document reported to the Zak…

No feature is requested by a Saudi merchant before “is the system connected to ZATCA?”. Phase 2 of e-invoicing (integration) turned the invoice from a printed slip into a digitally signed XML document reported to the Zakat, Tax and Customs Authority. We integrated TtaKkaa POS for restaurants, Sanmoris for single stores and AutoParts System for spare parts — these are the lessons you will not find in the official guide.
The basics in a minute
- Two invoice types: tax invoices (B2B) need clearance before delivery to the customer; simplified invoices (B2C) are issued immediately and then reported within 24 hours.
- UBL 2.1 XML + digital signature + previous-invoice hash (a chain) + counter + a QR code with defined fields.
- Setup: a digital certificate per device/branch via CSR and an OTP from the Fatoora portal.
Lesson 1: the invoice is an immutable entity
The biggest architectural change: after issuance an invoice is never edited. Mistakes are corrected with a credit/debit note linked to the original. In TtaKkaa the cashier used to edit the order after printing; we redesigned the path: the order is editable until issuance, then issuance is a final event that generates, signs and stores the XML.
Lesson 2: the chain never breaks — even when the internet does
Every invoice carries the previous invoice’s hash and a sequential counter per device. The restaurant loses connectivity at the lunch peak; simplified invoices are issued locally with signature and chain, and reported when the connection returns within the window. The local queue with ordered retries was the most important part of the whole integration.
If your system can issue two invoices with the same sequence number under any circumstance, you are not compliant yet.
Lesson 3: the sandbox is not quite production
We tested everything on the compliance environment, then details differed in production: date formats, Arabic characters in item names, and line-level versus invoice-level discounts. We caught most with a golden test set: 40 real invoices covering the cases (discount, return, zero-rated, foreign currency) run before every deploy.
Lesson 4: inventory and invoice are one event
In AutoParts, stock was deducted when the draft was created, so numbers drifted when drafts were cancelled. New rule: stock deduction and tax issuance in one database transaction; both or nothing.
Lesson 5: a compliance panel for the merchant, not just the accountant
One screen: today’s invoices, what was reported, what is pending, what was rejected and why (in human language). When the merchant sees “3 invoices pending report — will retry automatically” they relax, and do not call support.
What this means for any new system
- Design the invoice as a final entity from day one.
- The local queue and retries are not “enhancements”.
- A golden test set of real invoices.
- Payroll, purchasing and inventory follow the invoice, not the other way round.
Tax compliance is not a marketing feature; it is what makes the system sellable in Saudi Arabia at all. Built right, it becomes a source of trust: every riyal has an invoice, and every invoice has a trail.


