Skip to content

Clix as your e-invoicing middleware

Your system already knows what it sold and to whom. ZATCA's Phase 2 asks for much more than that: a UBL 2.1 XML document, a cryptographic stamp from a registered unit, a QR code, a hash chain linking every invoice to the one before, and a live exchange with ZATCA before a business invoice is valid. Clix does all of that behind one REST call.

Clix is listed as a Phase Two solution in ZATCA's E-Invoicing Solution Providers Directory. See Clix and ZATCA compliance.

The picture

Your systems send invoice data as JSON with an API key. Inside Clix: 1 validate and calculate, 2 build the UBL 2.1 XML, 3 stamp and sign with your ZATCA certificate and add the QR code, 4 send to ZATCA. Standard invoices go to ZATCA clearance, simplified ones to reporting. ZATCA's answer comes back; Clix keeps the status, messages, signed XML and PDF in the Kingdom, and your system polls for them. Your systems send invoice data as JSON with an API key. Inside Clix: 1 validate and calculate, 2 build the UBL 2.1 XML, 3 stamp and sign with your ZATCA certificate and add the QR code, 4 send to ZATCA. Standard invoices go to ZATCA clearance, simplified ones to reporting. ZATCA's answer comes back; Clix keeps the status, messages, signed XML and PDF in the Kingdom, and your system polls for them.

Your system sends the commercial facts in JSON. Clix returns the legal facts: the ZATCA status, ZATCA's messages, and the PDF with the signed XML inside.

What you would otherwise build

Each row is a ZATCA Phase 2 requirement that your own systems would have to meet if they talked to ZATCA directly.

ZATCA requirement Built into each of your systems With Clix
Register every invoicing unit with ZATCA and hold its certificate (CSID), renewing it before expiry One onboarding and one certificate per system, with the private key kept safe Done once per ZATCA connection in the Clix app
Produce the e-invoice as UBL 2.1 XML to ZATCA's standard An XML builder that follows every ZATCA rule You send JSON
Stamp, sign and add the QR code Cryptography code and key handling Clix signs with the connection's certificate
Chain every invoice to the one before (UUID, counter, previous hash) Strict sequencing, even across retries and restarts Clix keeps the chain
Clear standard invoices before they are valid; report simplified ones within 24 hours Two ZATCA APIs, their responses and error codes One create call; you poll one status
Keep working when ZATCA is slow or down A queue and retry logic Clix queues and retries
Give the buyer a PDF with the XML inside A PDF generator that embeds the XML GET …/pdf-a3/
Keep records for at least six years, in the Kingdom Storage and retention Clix stores them in Jeddah
Follow new versions of ZATCA's standards Change and retest every system Changed once, in Clix

Several systems, one Clix organisation

A business often invoices from more than one place: an ERP for contracts, tills in each branch, a web store. Each connects to the same Clix organisation with its own API key, and each invoice names the ZATCA connection it is issued from.

An ERP, two branch tills and a web store each connect with their own API key to one Clix organisation with one VAT number. The organisation issues through a business-level ZATCA connection and two branch connections, which send to ZATCA for clearance and reporting. An ERP, two branch tills and a web store each connect with their own API key to one Clix organisation with one VAT number. The organisation issues through a business-level ZATCA connection and two branch connections, which send to ZATCA for clearance and reporting.

  • One key per system. Revoke one without stopping the others. See Authentication.
  • One or more ZATCA connections. A connection can be business-level or tied to a branch, whose address then appears on its invoices. Each invoice sends its connection's device id.
  • One record. All invoices land in one organisation, so the VAT report, payments and reconciliation see everything.

Ways to issue invoices

Way Best for
The REST API Systems that already hold the sale: ERP, point of sale, e-commerce, billing
The Clix web app Teams that invoice by hand, and for checking, correcting and sharing what the API issued

Both write to the same organisation. Clix does not import sales invoices from files, and offers no ready-made ERP plug-ins; connect through the API.

Who does what

Task Your system Clix ZATCA
Decide what was sold, to whom, at what price ✓
Keep clients (and, optionally, items) in Clix ✓ via the API stores them
Check the invoice against ZATCA's business rules ✓ on preview and on create checks again
Work out line totals, VAT, rounding ✓
Number the invoice, chain it to the previous one (UUID, counter, hash) ✓ verifies
Build the UBL 2.1 XML ✓
Hold the ZATCA certificate and stamp the invoice ✓ per ZATCA connection issues the certificate
Clear standard invoices before they are valid ✓ sends ✓ clears
Report simplified invoices within 24 hours ✓ sends straight away ✓ receives
Produce the invoice PDF with the XML embedded ✓
Keep the record for the retention period, in the Kingdom ✓
Store Clix's invoice id, issue date and status ✓
Correct an issued invoice ✓ asks for a credit or debit note ✓ issues it clears or receives it

A standard invoice, end to end

A business-to-business invoice is not valid until ZATCA clears it. Your system does not wait on ZATCA directly: it gets 202 Accepted at once and polls.

sequenceDiagram
    participant ERP as Your ERP
    participant C as Clix API
    participant Z as ZATCA
    ERP->>C: POST /api/invoices/preview/
    C-->>ERP: 201 totals, or 400 with the first broken rule
    ERP->>C: POST /api/invoices/
    C-->>ERP: 202 Accepted + location
    C->>Z: signed XML for clearance
    Z-->>C: Cleared, Cleared with warnings, or Rejected
    loop every 1–2 seconds
        ERP->>C: GET location
        C-->>ERP: zatca_response_status
    end
    ERP->>C: GET …/pdf-a3/
    C-->>ERP: PDF with the cleared XML embedded

Steps, payloads and responses: Quickstart. A full recorded run: Worked example.

A simplified invoice

A business-to-consumer invoice is valid when issued; ZATCA is told afterwards. Clix reports it straight after creation, well inside ZATCA's 24 hours.

sequenceDiagram
    participant POS as Your point of sale
    participant C as Clix API
    participant Z as ZATCA
    POS->>C: POST /api/invoices/ (transaction_code 0200000)
    C-->>POS: 202 Accepted + location
    C->>Z: signed XML for reporting
    Z-->>C: Reported, or Not reported
    POS->>C: GET location
    C-->>POS: REPORTED
    POS->>C: GET …/pdf-a3/
    C-->>POS: PDF with QR code

A till must reach Clix to issue

Clix is the unit ZATCA registered, so an invoice exists only once Clix creates it. A point of sale that cannot reach Clix cannot issue a valid invoice until it reconnects. See Why you cannot choose the issue date.

The life of an invoice

Preview stores nothing. Create returns 202 Accepted, and the invoice ends in one of four states: CLEARED or REPORTED, final and not editable; accepted with warnings, final, and you fix the cause for next time; NOT_CLEARED or NOT_REPORTED, rejected and never valid, so fix the data and create a new invoice; or no response, which you send again with PATCH …/clearance-reporting/ to reach CLEARED or REPORTED. A cleared or reported invoice is changed only by a credit note 381 (buyer owes less) or a debit note 383 (buyer owes more). Preview stores nothing. Create returns 202 Accepted, and the invoice ends in one of four states: CLEARED or REPORTED, final and not editable; accepted with warnings, final, and you fix the cause for next time; NOT_CLEARED or NOT_REPORTED, rejected and never valid, so fix the data and create a new invoice; or no response, which you send again with PATCH …/clearance-reporting/ to reach CLEARED or REPORTED. A cleared or reported invoice is changed only by a credit note 381 (buyer owes less) or a debit note 383 (buyer owes more).

  • A cleared or reported invoice is final. Corrections are credit or debit notes: POST /api/invoices/ with type_code 381 or 383, original_invoice_reference and reason_id. See Codes → reason_id.
  • A rejected invoice is never resubmitted. Create a corrected one.
  • Status values and where ZATCA's messages are: Codes → zatca_response_status.

Handling every answer

What to do for each answer from Clix. 202: store location and poll the status. 202 with '…submission to ZATCA failed': PATCH …/clearance-reporting/ and do not create again. 400: read message, fix the payload and preview again. 400 'same data': a duplicate within 5 minutes; poll for the first and do not resend. 401 or 403: key, plan or permission, see Authentication. 429: wait Retry-After, then retry. Timeout or network error: look the invoice up before any retry. What to do for each answer from Clix. 202: store location and poll the status. 202 with '…submission to ZATCA failed': PATCH …/clearance-reporting/ and do not create again. 400: read message, fix the payload and preview again. 400 'same data': a duplicate within 5 minutes; poll for the first and do not resend. 401 or 403: key, plan or permission, see Authentication. 429: wait Retry-After, then retry. Timeout or network error: look the invoice up before any retry.

The full list, with bodies: Errors. Rate limits and the monthly allowance: Usage.

Going live

Seven steps to go live: Business plan with API access; a ZATCA connection that is Active; create an API key, one per system; load codes for VAT, units and reasons; create clients and store their uuid; preview every scenario; go live: create, poll, store. Seven steps to go live: Business plan with API access; a ZATCA connection that is Active; create an API key, one per system; load codes for VAT, units and reasons; create clients and store their uuid; preview every scenario; go live: create, poll, store.

  1. API access comes with the Business plan. See Plans.
  2. A ZATCA connection must be Active (device_status pcsid_generated). See Connect to ZATCA.
  3. One API key per system that calls Clix, so you can revoke one without stopping the others. See Authentication.
  4. Codes: VAT categories, exemption reasons, units, payment means. See Reference data.
  5. Clients: create each buyer once with POST /api/onboarding/organizations/clients/ and keep the uuid. The invoice refers to the buyer by uuid. See The buyer is an ID.
  6. Lines: send them in full with form_lines, or bill catalogue items with lines. See Two ways to send lines.
  7. Preview each scenario you will send: standard, simplified, export, credit note, debit note, foreign currency.
  8. In production, store Clix's invoice uuid, issue_date, issue_time and final status against your own record.

Try it