Odoo ZATCA Phase 2 Guide: CSID Onboarding, Clearance, POS and Testing
Odoo ZATCA Phase 2 setup for Odoo 19 and 20: CSID onboarding, clearance vs reporting, POS receipts, multi-branch journals and a full testing checklist.
Phase 2 is the integration phase of ZATCA e-invoicing, and Odoo ships the connector itself. Our Odoo integration services team uses this guide to set up Odoo ZATCA Phase 2 for Saudi companies, from CSID onboarding to the first cleared invoice.
This is the technical deep dive for finance managers, IT leads and implementers. If you first need to know whether your company is in scope and by when, read our ZATCA Wave 25 scope test and plan to February 2027.
What does ZATCA Phase 2 require from Odoo?
ZATCA Phase 2 requires Odoo to generate signed UBL 2.1 XML invoices, connect to the Fatoora platform through APIs, and either clear or report every invoice and note. Phase 1 only asked for a compliant invoice with a QR code.
ZATCA's e-invoicing page dates Phase 1 to 4 December 2021 and Phase 2 to 1 January 2023, rolled out in waves. ZATCA's detailed e-invoicing guideline adds rules that shape how you configure Odoo:
- Counter: every invoice carries a counter that can never be reset, so a sales journal cannot start its numbering again.
- Hash chain: each invoice holds the hash of the previous one, and one solution unit may run only one chain at a time.
- Language: everything in the human-readable invoice must be in Arabic, notes included; English alongside is allowed.
- Format: if you send a PDF, it must be PDF/A-3 with the XML embedded.
- No cancelling: a rejected invoice cannot be cancelled; you fix it and submit it as a new document with its own counter and hash.
Which Odoo modules handle ZATCA e-invoicing?
Odoo's Saudi localization splits ZATCA e-invoicing across six modules, and the main two are l10n_sa_edi for invoices and l10n_sa_edi_pos for the till. The Odoo Saudi Arabia localization documentation lists them all, and the Odoo 20 page is the same.
| Module | Technical name | What it does |
|---|---|---|
| Saudi Arabia - Accounting | l10n_sa | Chart of accounts, 15% VAT, zero-rated and exempt taxes, Phase 1 QR |
| Saudi Arabia - Accounting Reports | l10n_sa_reports | VAT and withholding returns |
| Saudi Arabia - E-invoicing | l10n_sa_edi | ZATCA Phase 2 API, clearance and reporting |
| Saudi Arabia - Point of Sale | l10n_sa_pos | Compliance fields and behavior on POS invoices |
| Saudi Arabia - E-invoicing (Simplified) | l10n_sa_edi_pos | Reports POS receipts as simplified invoices |
| Saudi Arabia - Withholding Tax | l10n_sa_withholding_tax | Withholding tax on payments |
The module manifests in Odoo's source code show Odoo S.A. as author and an LGPL-3 license for the e-invoicing modules. They sit in Odoo's main open-source repository, so they are not a paid add-on to your subscription.
Odoo Saudi localization vs third-party ZATCA modules: which should you use?

For most companies on Odoo 19 or 20, the native Saudi localization is the safer choice, and a third-party ZATCA module only makes sense when you are stuck on an old version or need a flow Odoo does not cover. The comparison below is our implementation view.
| Factor | Odoo Saudi localization | Third-party ZATCA module |
|---|---|---|
| Who maintains it | Odoo S.A., inside each release | The module vendor, on its own schedule |
| Version coverage | Odoo 19 and 20, Sandbox, Simulation, Production | Varies; often built for older versions |
| Odoo Online | Works, no custom code needed | Not possible on Odoo Online |
| Upgrades | Migrated by Odoo with your database | Must be ported and retested every upgrade |
| Fixes for ZATCA rule changes | Shipped in Odoo updates | Depend on the vendor's contract |
| Best fit | Most Saudi companies on supported versions | Legacy versions or unusual flows |
The Odoo Online row matters more than it looks. Odoo's documentation says Odoo Online cannot run custom or Odoo Apps Store modules, so the native localization is the only route there.
Third-party modules also add an upgrade bill. If one ZATCA module ties your accounting to an old version, the cost of porting it lands on every future upgrade, which is why we usually upgrade first and configure the native modules after.
How does CSID onboarding work in Odoo?
CSID onboarding links each Odoo sales journal to ZATCA as an E-Invoice Solution Unit, using a one-time password from the Fatoora portal. In the screen you only click Onboard and enter the OTP, but Odoo's source code shows three API calls behind that button.
ZATCA's guideline defines a Cryptographic Stamp Identifier (CSID) as the identifier that links a solution unit to a trusted party that confirms the taxpayer's identity. In Odoo 20 each journal stores two of them: a compliance CSID and a production CSID.
- Request the OTP: generate a six-digit OTP in the Fatoora portal for the right environment. It expires after 60 minutes.
- Compliance CSID: Odoo builds a certificate signing request from your company data and calls ZATCA's compliance API, which returns a compliance certificate and secret.
- Compliance checks: Odoo signs and submits six sample files: standard invoice, credit and debit note, and simplified invoice, credit and debit note.
- Production CSID: with the checks passed, Odoo requests the production certificate that signs your live invoices.
- Renewal: Odoo only lets you renew a production CSID once it has expired, so put the validity date in your compliance calendar.
- Revocation: when a journal stops issuing invoices, revoke its CSID in the Fatoora portal under View List of Solutions and Devices.
Most onboarding failures come from step 2. On the Odoo forum, a ZATCA journal onboarding error traced back to the company record and the certificate fields, such as a VAT number that is not 15 digits or a common name with spaces or Arabic characters.
Clearance vs reporting in Odoo: what happens to each invoice?
Clearance means ZATCA validates and stamps a B2B tax invoice before you share it; reporting means Odoo stamps a B2C simplified invoice itself and sends it to ZATCA within 24 hours. Odoo decides which flow to use from the invoice type and the customer.
| Step | Tax invoice (clearance) | Simplified invoice (reporting) |
|---|---|---|
| Typical use | B2B and B2G sales | B2C sales, or B2B below SAR 1,000 |
| Who stamps it | ZATCA, during clearance | Odoo, with the journal's production CSID |
| When it goes to ZATCA | Before you share it with the buyer | Within 24 hours of issue |
| If ZATCA is down | Retry, then share with records kept | Keep retrying within the 24 hours |
| If rejected | Not legally valid; fix and resubmit | Fix and resubmit as a new document |
In Odoo, you confirm the invoice and click Process now on the blue banner. Odoo's documentation notes that an invoice with a related contact, such as an invoicing address, goes to the clearance API as B2B.
Successful invoices keep their UBL 2.1 XML and PDF in the chatter permanently. In Production they cannot be reset to draft, so a wrong customer address on a cleared invoice is fixed with a credit note that carries a ZATCA reason, not by editing.
How should multi-branch companies set up ZATCA journals in Odoo?
Branches under one VAT number share the parent's VAT, carry their own Commercial Registration Number, and either bill through one central journal or through one onboarded journal per branch. The choice changes how invoices queue and how you report.
Odoo's documentation calls these two models centralized billing and a multi-threaded system with parallel invoice processing. Here is how we weigh them:
- Central journal: one CSID and one hash chain; simple to run, but every branch's invoices queue in one sequence.
- Journal per branch: each journal is onboarded and holds its own counter and chain, so branches submit in parallel and keep separate numbering.
- Branch data: on each branch contact, enter the parent VAT number and the branch CRN in the Identification Scheme field.
- Count first: every sales journal is onboarded separately, so list journals, branches and tills before you request OTPs.
ZATCA allows a different sequence per branch, as long as each invoice is clearly identified and follows a sequence. Our guide on how Odoo Accounting works explains journals and sequences in more depth.
How do you make Odoo POS ZATCA Phase 2 compliant?
Odoo POS becomes ZATCA Phase 2 compliant once l10n_sa_edi_pos is installed, the POS Invoices journal is onboarded, and each order carries a customer before payment. The Phase 2 QR code then prints on the receipt and the PDF.
Odoo's steps run through Point of Sale settings: pick the point of sale, open the default Invoices journal from the Accounting section, and click Onboard on its ZATCA tab with a production OTP. Then enable the Gulf Cooperation Council Format under Bills and Receipts so the receipt prints in Arabic.
Three POS details catch retailers out:
- Shared journals: tills that share one Invoices journal share one CSID and one chain, so decide this before onboarding.
- Offline time: the 24-hour window covers short outages, but if a till cannot report in time, ZATCA expects a failure notification and a second notice once fixed.
- Printers: reprint on every thermal printer and scan the QR with ZATCA's app, because a blurred code fails in front of the customer.
For the wider retail rollout around these steps, see our Odoo POS implementation guide.
What does an Odoo ZATCA Phase 2 testing checklist look like?
A sound Odoo ZATCA Phase 2 test runs every invoice type you really issue through Sandbox and then Simulation, until each one returns 200 with no warnings. Simulation invoices are not legally valid, which is exactly why you test there.
- Sandbox: set the ZATCA API mode to Sandbox, use the test VAT number from Odoo's docs, onboard a sales journal and confirm a few invoices.
- Copy production: duplicate the live database, switch it to Simulation (Pre-Production) and onboard each journal with an OTP from the Fatoora Simulation Portal.
- Standard flows: B2B invoice, credit note and debit note, each with a ZATCA reason where needed.
- POS flows: cash and card receipts, refunds, and an order rung up just after midnight Riyadh time.
- Edge cases: global discount lines with 15% tax, down payments, retention, zero-rated exports and foreign-currency invoices.
- Integrations: invoices created by eCommerce, marketplaces or an API, not only by users.
- Read every response: fix each 400 and 202, then repeat until the chatter shows Action Successful.
- Switch to Production: once Production has submitted an invoice, you cannot switch back to Sandbox or Simulation.
If invoices reach Odoo from outside systems, test those too. Our Odoo Salla integration guide shows how online orders become ZATCA invoices. Before any of this, run the free Odoo health check to spot version and module risks.
Which ZATCA errors do Odoo users hit most?
Most ZATCA errors in Odoo point to master data, such as buyer IDs, VAT numbers and addresses, rather than to the API itself. Odoo writes ZATCA's response code and message into the invoice chatter, which makes them quick to trace.
| Response | Meaning | Usual fix in Odoo |
|---|---|---|
| 200 | Accepted | None |
| 202 | Accepted with warnings | Fix the data now; warnings may become rejections |
| 303 | Clearance switched off | Submit through reporting instead |
| 400 | Rejected, not legally valid | Correct the cause, then click Retry |
| 401 | Unauthorized | Check the certificate and secret; re-onboard if needed |
| 429, 500, 503, 504 | Not received | Resend the invoice |
Two real cases from the Odoo forum show the pattern. A 202 warning, BR-KSA-F-07, came from a tax number entered in the Other ID field instead of the customer's VAT Number field.
A 400 rejection, BR-CUSTOM-VALIDATION-01, happened because seller and buyer had the same VAT number. That is a business flow question, so an internal transfer should not be issued as a tax invoice.
Is Odoo the best accounting software in Saudi Arabia for ZATCA?
Odoo is a strong fit for Saudi companies that want accounting, sales, stock and POS in one database with ZATCA Phase 2 built in, but no system is best for everyone. ZATCA itself lets taxpayers choose any compliant solution.
ZATCA keeps an indicative list of solution providers, and says a taxpayer that meets the requirements is compliant even if its provider is not listed. So the question is fit, not a ZATCA badge.
Odoo wins when one system should run invoicing, POS, inventory and Arabic documents across branches. Larger groups weighing global suites should read our Odoo 20 vs SAP vs Dynamics 365 comparison for Saudi and GCC.
Which industries face the hardest ZATCA Phase 2 cases in Odoo?
Retail, food service, contracting and distribution each hit a different ZATCA edge case, so the test plan should follow your industry, not a generic script. The table shows where we focus.
| Industry | Pain or cost driver | Odoo approach | How iVentureTeam helps |
|---|---|---|---|
| Retail chains | Many tills, Arabic receipts, 24-hour reporting | l10n_sa_edi_pos, GCC receipt format | Onboard each till journal, test reprints |
| Restaurants and cafes | Peak-hour volume, offline periods | POS reporting with retry | Set up a failure-notification routine |
| Contractors | Retention, down payments, progress billing | Retention taxes and advance invoices | Map contracts to compliant invoice flows |
| Distributors | Credit notes, global discounts, many B2B buyers | Clearance with ZATCA reason codes | Clean buyer VAT and address data |
| Multi-branch groups | One VAT, many CRNs, parallel invoicing | Branch records and journals per branch | Design the journal model before onboarding |
| eCommerce sellers | Orders from Salla, Shopify or marketplaces | API-created invoices in Odoo | Test integrated invoices in Simulation |
How iVentureTeam helps with Odoo ZATCA Phase 2 integration

iVentureTeam sets up Odoo ZATCA Phase 2 end to end: data, journals, POS, outside systems and the test cycle. We have delivered 150+ ERP projects across 35+ countries with 40+ Odoo specialists over 13+ years.
- Readiness review: version, modules, company and customer data, journals, branches and tills checked against ZATCA's fields.
- Configuration and onboarding: the native Saudi localization set up, then each journal onboarded through Sandbox, Simulation and Production.
- POS and branches: till journals, GCC receipt format and branch CRNs, tested on your own printers.
- Integrations: eCommerce, marketplace and API invoices tested through Simulation, using our Odoo integration services.
- Budget: our Odoo implementation cost ranges start at US$3,000 to US$9,000 over 4 to 8 weeks for small projects; we confirm scope before we quote.
For the wider country rollout, including Arabic and timelines, see our guide to Odoo ERP implementation in Saudi Arabia.
Odoo ZATCA Phase 2 case study: bilingual Arabic POS receipts
A Middle East retail business needed every POS receipt in both Arabic and English, which is the same receipt layer ZATCA now expects on simplified invoices. This project ran on Odoo 11, before the native Phase 2 modules.
Odoo 11's standard POS receipt printed in one language. Arabic-speaking customers could not read English-only slips, while audit needs favored English line items next to the Arabic.
We rebuilt the POS receipt template so product name, taxable and non-taxable amounts, subtotal and total print in both languages, with right-to-left Arabic rendered correctly. Printing ran through a Raspberry Pi at each station, and delivery took 3 weeks.
The lesson for Phase 2 is the printer test: we checked both scripts on real thermal paper before go-live. Read the bilingual Arabic POS receipts case study.
The bottom line on Odoo ZATCA Phase 2
On Odoo 19 or 20, ZATCA Phase 2 is a configuration and testing project, not a development project, as long as your data and journal model are right. Use the native localization unless you have a clear reason not to.
Clean the company, branch and customer data, decide your journal model, onboard each journal through Simulation, and test every invoice type you really issue. The companies that struggle are the ones that onboard first and fix data later.
Ready to get your Odoo ZATCA Phase 2 integration live?

Get a clear plan for your journals, tills and test cycle from a team that works with the Saudi localization. Plan your Odoo ZATCA Phase 2 rollout with us, call +91-90235-15208, or email business@iventureteam.com.
Frequently Asked Questions
Does Odoo support ZATCA Phase 2?
+
Yes. Odoo's Saudi localization includes l10n_sa_edi for clearance and reporting and l10n_sa_edi_pos for POS receipts. Odoo 19 and 20 support Sandbox, Simulation and Production onboarding.
Is ZATCA Phase 2 available in Odoo Community?
+
The e-invoicing modules are LGPL-3 and sit in Odoo's open-source repository, so Community databases can install them. Test the full flow on your own version first, as reports and support differ by edition.
What is a CSID in ZATCA?
+
A Cryptographic Stamp Identifier links your e-invoicing solution unit to ZATCA. In Odoo, each sales journal gets a compliance CSID, passes six compliance checks, and then receives a production CSID.
Do I need a separate CSID for each branch or POS?
+
You need one per onboarded sales journal. Branches and tills that share a journal share its CSID and hash chain; separate journals each need their own onboarding with a fresh OTP.
What is the difference between clearance and reporting?
+
Clearance applies to B2B tax invoices: ZATCA validates and stamps them before you share them. Reporting applies to B2C simplified invoices: Odoo stamps them and sends them to ZATCA within 24 hours.
Can I edit an invoice after ZATCA clears it?
+
No. In Production, submitted invoices cannot be reset to draft, and their XML and PDF stay attached. Issue a credit or debit note with a ZATCA reason instead.
Does Odoo Online work with ZATCA Phase 2?
+
Yes. The Saudi localization is standard Odoo, so it runs on Odoo Online. Third-party ZATCA modules cannot be installed there, because Odoo Online does not accept custom or App Store modules.
What happens if my POS goes offline?
+
Simplified invoices must reach ZATCA within 24 hours, so Odoo can report them once the connection returns. If you cannot report in time, notify ZATCA through its failure form and again after recovery.
How long does an Odoo ZATCA Phase 2 setup take?
+
For a company already on Odoo 19 or 20 with clean data, configuration and testing often fit our small-project range of 4 to 8 weeks. Old versions, many branches or integrations add time.
Ready to put this into action?
Talk to iVentureTeam about Odoo, AI automation, or custom development — get a free, no-obligation consultation.
Free Odoo tools
All tools- Odoo Health CheckVersion, modules, findings and upgrade cost
- Odoo App SelectorWhich apps you need, by industry
- Odoo Project EstimateIndicative cost and timeline in minutes
- Odoo Implementation Cost CalculatorImplementation cost and timeline, in minutes
- Odoo Migration Cost CalculatorVersion jump or legacy ERP, priced in minutes
Continue reading
Odoo Muqeem Integration: Iqama, Visas, GOSI and KSA Payroll Guide
Odoo Muqeem integration for Saudi HR: iqama renewal, exit re-entry visas, Odoo 20 GOSI API, WPS files for Mudad and KSA payroll setup, step by step.
Odoo Accounting for CFOs in the GCC: VAT, E-Invoicing and Controls
Odoo accounting for CFOs in the GCC: UAE and Saudi VAT, ZATCA and UAE e-invoicing, AED and SAR multi-currency, lock dates and hashed audit controls.
Odoo 20 for Professional Services: Timesheets, Billing and Margins
Odoo for professional services in Odoo 20: timesheets, time and materials billing, employee rates, milestone invoicing and the new project margin reports.
