Skip to content
Z
← Back to blog

Published · 31 August 2026 · 8 min read

ZATCA Fatoorah Onboarding: Step-by-Step for SMEs (2026)

A practical step-by-step walkthrough of the Fatoorah onboarding flow for Saudi SMEs: VAT account, device registration, CSR generation, Compliance CSID, Production CSID, and the sandbox-to-production cutover.

ZATCA Fatoorah onboarding step-by-step guide cover showing 4-step flow: register, generate CSR, get CSID, integrate

If you have decided to integrate with ZATCA Fatoorah directly (rather than going through a SaaS provider), this page is the playbook. It walks the actual onboarding flow as documented in the ZATCA technical specifications, with the gotchas our team has hit in production. For the high-level picture of what Phase 2 is and why, see our complete Phase 2 guide.

Estimated effort: 8 to 20 hours of focused developer time, depending on your ERP and how much of this is already automated. You do not need to be a ZATCA expert to complete onboarding — you do need a developer who can generate a CSR, run an HTTPS client, and read error messages.

Before you start: the four prerequisites

You cannot onboard until you have each of these:

  1. An active VAT registration on the ZATCA portal. If you are VAT-registered you already have this; login at login.gazt.gov.sa with your TIN and password. If you are not VAT-registered, you cannot use Fatoorah and Phase 2 does not yet apply to you.
  2. A Fatoorah portal account, distinct from the VAT portal. Register at fatoorah.zatca.gov.sa using your VAT number. The first time you log in, ZATCA walks you through a TOTP setup — save the recovery codes in your password manager.
  3. A development environment that can sign OpenSSL CSRs. You will generate a private key + CSR, keep the private key safe, and upload the CSR. The private key never leaves your infrastructure.
  4. A staging / sandbox ERP or POS instance. You will integrate first against the Fatoorah sandbox (https://sandbox-fatoorah.zatca.gov.sa), prove the flow works, then cut over to production. Don’t integrate against production on day one.

Step 1: Generate your CSR (Certificate Signing Request)

The CSR contains your public key and your VAT identifying information. The matching private key signs every invoice you will ever issue, so it is the single most important secret in the whole Phase 2 setup. Generate it once, store it in a hardware security module (HSM) or encrypted key vault, and never rotate it unless forced.

The most common approach uses OpenSSL. From your dev machine, with a Linux or macOS terminal:

# 1. Generate a 2048-bit RSA private key (keep this secret!)\nopenssl genrsa -out private.key 2048\n\n# 2. Create a config file for the CSR\ncat > csr.conf << EOF\n[req]\ndistinguished_name = dn\nreq_extensions = v3_req\nprompt = no\n[dn]\nC=SA\nOU=Your-Business-Name-In-English\nO=Your-Business-Name\nCN=Your-VAT-Number-15-Digits\n[v3_req]\nsubjectAltName = DNS:fatoorah.zatca.gov.sa\nEOF\n\n# 3. Generate the CSR\nopenssl req -new -key private.key -out request.csr -config csr.conf\n\n# 4. Base64 the CSR — you will paste this into the Fatoorah portal\ncat request.csr | base64 | tr -d "\n"

ZATCA also accepts ECDSA P-256 keys (smaller, faster), but RSA-2048 is the default and what most ERPs support out of the box. Whatever you choose, pin the algorithm in your dev documentation — the spec changes over time.

Step 2: Upload the CSR to Fatoorah and get a Compliance CSID

Log in to Fatoorah. The menu path is: Onboarding → Compliance CSID → Request Compliance CSID. Paste the base64 CSR. ZATCA signs it and returns a Compliance CSID, which is a JSON Web Token (JWT) you use for sandbox calls only.

The Compliance CSID is non-production. It only works against the sandbox endpoint. You have 90 days from issuance to use it. After 90 days you must request a new Compliance CSID. This is by design — it forces you to integrate, not just collect certificates.

Step 3: Integrate against the sandbox

Sandbox endpoint: https://sandbox-fatoorah.zatca.gov.sa. The integration flow is exactly production, but with a relaxed rate limit and a sandbox database that resets daily. Before you write any code, install a sandbox testing tool — ZATCA publishes a Swagger UI and a Postman collection at the Fatoorah portal.

Minimum viable sandbox integration looks like this:

  1. Build a UBL 2.1 XML invoice (the schema is in our XML structure guide).
  2. Sign the canonicalized XML with your private key using the ECDSA or RSA algorithm ZATCA expects.
  3. Compute the SHA-256 hash of the previous invoice in your series (the chain hash — explained in our cryptography guide).
  4. POST to /e-invoicing/clearance/single (B2B) or /e-invoicing/reporting/single (B2C).
  5. Capture the clearance hash + counter from the response. Stamp the PDF with that hash.

Test 5-10 edge cases in the sandbox: invoice with a single line item, invoice with 20 line items, refund (credit note), B2B vs B2C routing, foreign currency line items (USD allowed but the VAT must be SAR), and the "previous invoice hash is missing" failure mode.

Step 4: Get a Production CSID

Once your sandbox integration is stable for 30+ days and you have processed at least 100 test invoices without errors, go back to the Fatoorah portal: Onboarding → Production CSID → Request Production CSID. The portal will let you upload the same CSR (or a fresh one if you have rotated). ZATCA verifies your VAT status and that you are in an active Phase 2 wave, then issues a Production CSID.

The Production CSID is the JWT your production ERP / POS / service uses to sign live invoices. It has a 1-year validity, after which you must rotate. ZATCA will email you 30 days before expiry. Most teams set a calendar reminder for the renewal.

Step 5: Cut over to production

Cutover is the riskiest moment in onboarding. The pattern that works:

  1. Deploy your code to production but point it at the sandbox endpoint. Process a real invoice from a real sale. Verify the PDF carries the sandbox clearance hash.
  2. Flip the endpoint constant to production. Process another real invoice. Verify the production hash appears in the PDF.
  3. Run both endpoints in parallel for 7 days. Daily reconciliation job: compare the production hashes against your internal ledger. Any drift is a bug.
  4. After 7 clean days, disable the sandbox codepath.

Document the cutover in your change-management log. Keep the previous Phase 1 PDFs for at least 90 days after cutover — auditors may ask for a side-by-side comparison.

Operations: counters, retries, and the 24-hour rule

Three things bite people in production:

Counters must be monotonic per device. ZATCA expects your invoice counter (the PIH / UUID field) to be strictly increasing per device. If your ERP loses a number — say, invoice #47 is voided and you skip to #48 — the next call fails. Solution: use a UUID, not an integer. UUIDs are guaranteed unique and ZATCA accepts them.

Retry with exponential backoff. Fatoorah can return 503 / 504 in the first 90 days of a new wave when load is high. Your client must retry with exponential backoff (start at 1s, double, cap at 60s) and idempotency — if the original POST succeeded but you did not get the response, retrying the same invoice hash must not double-bill.

The 24-hour reporting rule (B2C). B2C invoices are reported, not cleared. You have 24 hours from issuance to report them to Fatoorah. If you miss the window, ZATCA flags the invoice as "delayed" and you get a notice. The fix is to either batch-report nightly or report in real time — your call.

When to involve a solution provider instead

Direct integration is the right call if (a) you have a dev team, (b) you issue more than ~5,000 invoices per month (the SaaS subscription starts to amortize below that), and (c) you have at least one full-time person who can maintain the integration long-term. If any of those is false, the cost-of-ownership math favors a ZATCA-accredited SaaS. The approved solution provider list has 30+ vendors in 2026. Pick one that supports your ERP natively (Odoo, ERPNext, Microsoft Dynamics, SAP, Oracle) before you pick one that does not. For the full cost analysis across the three integration paths and the per-wave deadlines, see our waves and deadlines guide.

Frequently asked questions

How long does ZATCA take to issue the CSID?
Compliance CSID: instant after CSR upload. Production CSID: 1-5 business days, sometimes faster. The 1-5 days is a review queue, not a cryptographic operation.

What happens if my private key is compromised?
You must rotate immediately. The old CSID must be revoked through the Fatoorah portal, and any invoices signed with the old key after the compromise are inadmissible in tax disputes. This is a "shame and blame" event; treat key management with the seriousness it deserves.

Can I use the same CSID across multiple systems (ERP + POS + ecommerce)?
One CSID per device. For a multi-channel business, register each system as a separate device. The CSID is bound to the Common Name (CN) in the CSR, which you can set per system.

Do I still need Phase 1 if I have Phase 2?
Yes. Phase 2 is additive. The TLV QR code on the PDF, the bilingual format, the 5-year retention — all still apply. Our free Phase 1 generator remains useful for the customer-facing PDF even when the underlying record is a Phase 2 clearance.

What about the old "Phase 1 only" generators that vendors sold for SAR 5,000?
They are still legal. They are just no longer sufficient for businesses in a Phase 2 wave. If you bought one, you do not need to throw it away — keep it for backfilling or for sub-threshold subsidiaries.

See all →
See all guides →

References

Primary sources used in this guide:

Get the next Saudi finance guide

One short email per month with a new Saudi finance guide, calculator update, or ZATCA tip. No spam, unsubscribe anytime.

I agree to receive marketing emails from this site. You can unsubscribe at any time.

Create your ZATCA tax invoice with QR

Add your 15-digit VAT number, totals, and download a Phase 1 compliant PDF — free, online, no signup.

Open the generator