← Blog Guides 7 min read · 29 September 2026

ZATCA e-invoicing in n8n without code: the ZATCA Tools node turns the API into workflow steps

An n8n workflow in which a sale flows into the ZATCA Tools node and comes out as a signed e-invoice with its QR code
You fill in fields. The signing, the hash chain and the conversation with ZATCA happen behind the node.

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.

  1. Create an account at zatcatools.com and connect your establishment with the OTP from the Fatoora portal, or start in trial mode (below).
  2. Open Settings, then API, and copy the key. It starts with ztk_live_.
  3. 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

ResourceOperationWhat it doesSame call in the API
InvoiceCreateBuilds, signs and submits a simplified (B2C) or standard (B2B) tax invoicePOST /v1/invoices
InvoiceGetOne invoice by its UUID, with its ZATCA status and linksGET /v1/invoices/{uuid}
InvoiceGet ManyNewest first, filtered by kind, status or a since dateGET /v1/invoices
InvoiceEmailSends the signed PDF to the buyerPOST /v1/invoices/{uuid}/email
NoteCreateA credit note (reduce) or debit note (increase) against an issued invoicePOST /v1/notes
AccountGetYour establishment and the invoices left on your planGET /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

  1. Trigger: an n8n Form submission, a deal marked won in your CRM, or a new row in Google Sheets.
  2. 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.
  3. 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

  1. Trigger: a refund recorded in your system, or a row marked refunded.
  2. 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.
  3. 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

  1. ZATCA Tools Trigger, event Any Document Issued.
  2. A Slack or WhatsApp node posts the number, total and status.
  3. 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

  1. A Schedule Trigger on the first of each month.
  2. Google Sheets reads your active contracts: client, VAT number, national address, service and monthly amount.
  3. ZATCA Tools, Invoice, Create, Standard, with External ID built from the contract and the month, such as contract-17-2026-10.
  4. 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.

Frequently asked questions

Can I issue ZATCA e-invoices from n8n without writing code? +
Yes. Install the ZATCA Tools community node from the n8n nodes panel by searching for ZATCA, add a ZATCA Tools API credential with the key from Settings, API in your ZATCA Tools account, and use the Invoice resource with the Create operation. The node sends the sale to the ZATCA Tools API, which builds the UBL 2.1 XML, signs it, adds the QR code and clears or reports it with ZATCA, then returns the invoice number, its status and links to the QR code, XML and PDF.
Is the ZATCA Tools n8n node the same thing as the ZATCA Tools API? +
It is a front end to it. Each operation is one API request: Invoice Create is POST /v1/invoices, Note Create is POST /v1/notes, Account Get is GET /v1/account, and the Trigger polls GET /v1/invoices. The node covers the calls a workflow needs. A few API fields, such as a description or a discount on a single line, are not in the node yet, and an HTTP Request node using the same API key reaches them.
Does the ZATCA Tools Trigger need a public webhook URL? +
No. The Trigger polls the API for documents created since the last one it saw, so it works on a self-hosted n8n behind a firewall. On an active workflow its first poll only records where it is and emits nothing, so switching a workflow on does not replay every invoice you have ever issued. A test run in the editor still returns recent documents for mapping fields.
How do I stop an n8n workflow from issuing the same e-invoice twice? +
Set External ID on every Invoice Create and Note Create, using your own id for the sale or refund, such as order-5501. If the same External ID is sent again after a retry, a duplicated run or a re-activated workflow, the API returns the document already issued instead of creating a second one. This matters because an invoice ZATCA has accepted cannot be deleted, only corrected with a credit or debit note.
Can I test the n8n node before connecting my establishment to ZATCA? +
Yes. A new ZATCA Tools account can start in trial mode, which connects to the ZATCA developer sandbox without a VAT number or a Fatoora OTP. The node then issues real signed, reported test documents, numbered with a TRY- prefix so they cannot be mistaken for real invoices. When you connect your establishment with its OTP, the same API key and the same workflow go on to issue real invoices.
Ready to connect your business?

Connecting is free and takes under five minutes.

Start for free