Plenty of businesses that must issue ZATCA e-invoices have no developer. Their sales live in a web form, a CRM, a spreadsheet of contracts or an in-house tool that will never get a ZATCA plugin. n8n connects systems like these, and the ZATCA Tools node is the step that turns a sale into a Phase 2 e-invoice: signed, QR-coded, and cleared or reported with ZATCA. It makes the same calls as our REST API. You fill in fields instead of writing requests.
What the ZATCA Tools node is
It is an open-source community package, n8n-nodes-zatca-tools, at version 1.1.1 under the MIT licence and verified by n8n as a community node. It adds two nodes: ZATCA Tools, which issues invoices, credit notes and debit notes, reads them back and emails them, and ZATCA Tools Trigger, which starts a workflow whenever a document is issued.
The node never builds XML, signs anything or talks to ZATCA itself. Our service does that: the UBL 2.1 document, the XAdES signature with your establishment's certificate, the ICV counter and PIH hash chain, the QR code, and clearance or reporting. Your workflow sends the sale as JSON and gets back the invoice number, its ZATCA status, and links to the QR code, the signed XML and the PDF. What a direct integration involves shows what that saves.
Installing it and adding your API key
Because it is verified, it installs from inside n8n with no npm step: on the canvas press + (or N), search for ZATCA, open More from the community and choose Install. Only the instance owner or an admin can install a community node; after that every member of the instance can use it. If the search shows nothing, an admin may have hidden community nodes, in the Cloud admin panel or through environment variables on a self-hosted instance, so ask them. On a self-hosted instance an owner can also install it by package name, n8n-nodes-zatca-tools, under Settings, Community Nodes.
- Create an account at zatcatools.com and connect your establishment with the OTP from the Fatoora portal, or start in trial mode (below).
- Open Settings, then API, and copy the key. It starts with
ztk_live_. - In n8n, add a ZATCA Tools API credential and paste the key.
n8n tests the credential on save, so a wrong key fails there, not at your first invoice. One credential is one establishment: one certificate, one invoice chain.
Every operation, and the API call behind it
| Resource | Operation | What it does | Same call in the API |
|---|---|---|---|
| Invoice | Create | Builds, signs and submits a simplified (B2C) or standard (B2B) tax invoice | POST /v1/invoices |
| Invoice | Get | One invoice by its UUID, with its ZATCA status and links | GET /v1/invoices/{uuid} |
| Invoice | Get Many | Newest first, filtered by kind, status or a since date | GET /v1/invoices |
| Invoice | Sends the signed PDF to the buyer | POST /v1/invoices/{uuid}/email | |
| Note | Create | A credit note (reduce) or debit note (increase) against an issued invoice | POST /v1/notes |
| Account | Get | Your establishment and the invoices left on your plan | GET /v1/account |
Two fields matter most. External ID is your own id for the sale, such as order-5501. Send it again after a retry or a duplicated run and you get the same invoice back, not a second one. An invoice ZATCA has accepted cannot be deleted, so set it on every Create. Invoice Type decides the path: a standard invoice is cleared by ZATCA before it is issued and carries the buyer's VAT number and national address (the short form, four letters and four digits); a simplified one is issued at once and reported after.
Four workflows, step by step
1. A paid order becomes an invoice and an email
- Trigger: an n8n Form submission, a deal marked won in your CRM, or a new row in Google Sheets.
- ZATCA Tools, Invoice, Create. Map the item name, quantity and unit price into Lines and the order id into External ID, and pick Simplified or Standard; a business buyer's VAT number and national address go under Additional Fields.
- Invoice, Email. Map the UUID from step two into UUID and the buyer's address into Send To.
Fill Buyer Email at creation and the PDF goes out without step three. Either way, save the returned UUID on the order; a refund needs it.
2. A refund becomes a credit note
- Trigger: a refund recorded in your system, or a row marked refunded.
- ZATCA Tools, Note, Create, kind Credit Note. Give the original invoice's UUID, a Reason (mandatory on every note), and either the refunded lines or the Cancel the Whole Invoice toggle.
- Set External ID to the refund's own id, so a retry never credits twice.
Cancelling is a credit note, never a delete. The toggle credits the open balance, worked out on our side, so an earlier partial refund is not credited twice. Charging more is a Debit Note; our guide to credit and debit notes has the rules.
3. Every issued document reaches your team or your Drive
- ZATCA Tools Trigger, event Any Document Issued.
- A Slack or WhatsApp node posts the number, total and status.
- For Google Drive, an HTTP Request node fetches the PDF from the document's link with the same key, and a Google Drive node uploads it.
A copy of this workflow filtered to Rejected is the one worth having: a person hears about every document ZATCA refuses, and the error reference explains the code.
4. Monthly contracts on a schedule
- A Schedule Trigger on the first of each month.
- Google Sheets reads your active contracts: client, VAT number, national address, service and monthly amount.
- ZATCA Tools, Invoice, Create, Standard, with External ID built from the contract and the month, such as
contract-17-2026-10. - Invoice, Email to each client.
ZATCA Tools has no recurring invoices of its own; this is how you get them for maintenance agreements, retainers or rentals. If the schedule fires twice in a month, the External ID returns the invoices already issued instead of billing everyone again.
VAT per line, and prices that include VAT
Since version 1.1.0 each line has its own VAT Treatment: Standard Rate (15%), Zero-Rated, Exempt or Out of Scope. Left on Establishment Default, the line takes your establishment's treatment. A zero-rated or exempt line can name its Exemption Reason from ZATCA's VATEX-SA list, such as VATEX-SA-32 for an export of goods; an out-of-scope line always carries VATEX-SA-OOS. Left empty, the reason comes from the invoice's other lines of the same treatment, else the one your establishment used last, else none, which ZATCA accepts with a warning.
One invoice can mix treatments. A medical equipment supplier can bill a clinic for a qualifying device zero-rated under VATEX-SA-35 and its installation taxed at 15% on the same invoice. Which reason applies is your accountant's call.
Unit prices are net of VAT by default, and the 15% is added. If your source holds what the customer paid, turn on Prices Include VAT under Additional Fields, and each line's VAT is taken out at its own rate.
The Trigger polls, so no public URL is needed
ZATCA Tools Trigger does not use a webhook. On the interval you set, it asks our API for documents created since the last one it saw, so it works on a self-hosted n8n behind a firewall. You choose the event (invoice, credit note, debit note or any document) and a status (accepted, accepted with warnings, rejected or any), and documents arrive oldest first.
On an active workflow, its first poll only records where it is and emits nothing. Otherwise, switching a workflow on would fire it once for every invoice in your history. A test run in the editor still fetches recent documents, so you have fields to map.
Try it in trial mode first
You need neither a VAT number nor a Fatoora OTP to build the workflow. A new account can start in trial mode, connected to ZATCA's own developer sandbox, so the node issues real signed, reported test documents, numbered TRY- so none can pass for a real invoice. Run every branch, a refund and a repeated External ID included. Then connect your establishment with its OTP, and the same API key and the same workflow go on to issue real invoices.
The action node also works as a tool for an n8n AI Agent, as the demo on the n8n page shows. Build that against the sandbox too: what an agent issues in production is real.
What the node does not do
- Accounting. No ledger, no journal entries, no inventory, no payroll, no VAT return.
- Currencies other than SAR. Every document is issued in Saudi riyals.
- Prepayment invoices. ZATCA's type 386, for an advance that later invoices deduct, cannot be issued through the node or the API; agree advances with your accountant.
- Several establishments on one credential. It is one credential each; a platform invoicing for many merchants belongs on the Partner API.
- Every API field. A description or a discount on a single line is in the API but not in the node yet; an HTTP Request node with the same key reaches it.
Where to go next
The n8n page has a recorded demo from installation to an accepted invoice, and the API reference documents every field the node sends. One week free, no payment, from the day you connect, then very competitive plans: 49 SAR a month for Growth and 149 for Business, on a smooth, fast system that signs each invoice and sends it to ZATCA in seconds. Start here, in trial mode if you want to build the workflow first.