Start here · 1 of 3
Your first invoice
- 1. Create a client.
Zatca("sandbox")works against ZATCA's public test environment. - 2. Get test credentials.
onboard()fetches them from ZATCA's sandbox in a few seconds. There is nothing for you to provide. - 3. Create the invoice.
create_invoice()checks it, computes VAT and totals, and signs it — on your machine. Nothing is sent yet. - 4. Send it.
submit()sends it to ZATCA and returns ZATCA's answer.
from zatca_tools import Zatca
zatca = Zatca("sandbox")
zatca.onboard() # the sandbox's test credentials, straight from ZATCA — a few seconds
invoice = zatca.create_invoice({
"number": "INV-1001",
"type": "simplified",
"items": [
{"name": "Product", "quantity": 2, "unit_price": 100},
],
})
result = zatca.submit(invoice)
if result.success:
print("ZATCA says:", result.status) # REPORTED
invoice.save_xml("INV-1001.xml")
invoice.save_pdf("INV-1001.pdf")
else:
print(result.error.message)
print(result.error.help_url)
ZATCA says: REPORTED
Reading the result
Three questions, three fields. Did it work? result.success. If not, why? result.error.message. How do I fix it? result.error.help_url — a page that explains the error, on the ZATCA Tools error reference or in this documentation.
success is true only when ZATCA itself reported or cleared the invoice. A dropped connection, a refused certificate and a rejection are all success == False, and status says which — see what to do for each.
result.success # True only when ZATCA reported or cleared the invoice
result.status # REPORTED · CLEARED · NOT_REPORTED · NOT_CLEARED · NOT_SENT · UNKNOWN · FAILED
result.error.code # what went wrong: ZATCA's code (BR-KSA-63) or the SDK's own (network_error)
result.error.message # why, in one sentence
result.error.help_url # how to fix it: a page on zatcatools.com, built offline
result.warnings # accepted, but worth fixing — each with its own help_url
Saving the invoice
Keep the XML: it is the e-invoice. The PDF is PDF/A-3 with that XML embedded inside, so the copy a person reads and the copy a system reads travel as one file. Brand it with your logo, colour and footer — printed invoices.
invoice.save_xml("INV-1001.xml") # the signed e-invoice
invoice.save_pdf("INV-1001.pdf") # PDF/A-3, the XML embedded, ready to hand over
# A standard (B2B) invoice is shared once ZATCA has cleared it — print the result:
result.save_pdf("INV-2001.pdf") # carries ZATCA's cleared copy
Next steps
How it works
The SDK is a library inside your process, not a service in between. The first two steps run on your servers; only the last arrow leaves them, and it goes to ZATCA.
ERP, POS, store or SaaS — passes a plain dict.
Reports or clears it, and answers — returned to you as a result.
ZATCA Tools is nowhere on this path: no proxy, no account, no telemetry.
What it does today
Three calls
onboard() once, create_invoice() locally, submit() to ZATCA. The certificate steps, the invoice chain and the choice between reporting and clearance happen inside.
Sandbox in one line
onboard() in the sandbox gets ZATCA's test credentials by itself: a first invoice in under a minute, with nothing to set up.
Clear results
success, status, and an error with a code, a sentence and a help link. Local problems, connection problems and ZATCA's answers are never mixed up.
Signed XML, hash and QR
UBL 2.1 invoices, credit and debit notes, with the XAdES signature, the invoice hash and the QR code ZATCA checks.
Reporting and clearance
Simplified invoices reported, standard ones cleared — with ZATCA's stamped copy returned to you.
Printed invoices
PDF/A-3 with the XML embedded, Arabic and English, your logo and colour. veraPDF passes it as PDF/A-3b.
VAT done right
Standard, zero-rated, exempt and out-of-scope items with their reasons, prices with or without VAT, discounts, rounding the way ZATCA checks it.
Every problem at once
An invoice that cannot be valid is refused before anything is sent, with every field that needs fixing.
Open source, local
MIT licence. Runs in your process; the only network calls go to ZATCA.
Questions developers ask
Is the SDK free?
Yes. It is open source under the MIT licence: free to use, including in commercial products, with no account, no key and no usage limit of ours. ZATCA itself charges nothing for its API.
Do I need a ZATCA Tools account?
No. The SDK talks to ZATCA directly with the certificate ZATCA issues to you. ZATCA Tools is not in the path and never sees your requests.
Does my invoice data pass through your servers?
No. Invoices are built, signed and hashed inside your application and sent from your servers straight to gw-fatoora.zatca.gov.sa. The SDK makes no request to any other host, sends no telemetry and writes no logs. Even the help links on errors are built offline, and carry nothing but the error code.
Do I have to understand CSRs and CSIDs?
No. In the sandbox, zatca.onboard() needs nothing at all. For your own company it needs one thing only you can provide: a one-time password from the Fatoora portal. The key, the CSR, the compliance checks and the certificates are handled inside that call. Connect to ZATCA has the details.
Does it support Phase 2 (integration)?
Yes: onboarding, signed UBL 2.1 invoices, credit and debit notes with the XAdES signature, invoice hash and QR code, reporting of simplified invoices and clearance of standard ones. It has been run end to end against ZATCA's sandbox.
Can it print the invoice?
Yes. save_pdf() writes a PDF/A-3 file with the signed XML embedded in it, in Arabic and English, with your logo, colour and footer. veraPDF, the reference PDF/A checker, passes it as PDF/A-3b.
Can I use it in an ERP or a POS?
Yes — that is what it is for. Each till or server that issues invoices is a unit with its own certificate and its own invoice chain; one client per unit.
Can I use it in production?
The SDK is new (version 0.1). Its arithmetic and XML match the ZATCA Tools platform's, which signs production invoices today, and it passes ZATCA's sandbox end to end. Run it in simulation with your own VAT number before you switch production traffic to it.
How is it different from ZATCA Tools?
The SDK is a library: you build your own integration and keep everything in your infrastructure. ZATCA Tools is the hosted product around the same engine — dashboard, invoice history, Shopify and WooCommerce integrations, a REST API — for teams that would rather not run their own.
How do I report a problem?
Open an issue on GitHub, or write to [email protected], with the SDK version and, if you can, the failing invoice with personal data removed. Security issues privately to [email protected].
Open source
The SDK is published under the MIT licence: use it, change it and ship it in commercial products, keeping the copyright notice. You can read every line that touches your data — and check for yourself that nothing leaves for anywhere but ZATCA.
Issues and pull requests are welcome. Questions: [email protected].
SDK or platform?
| ZATCA Tools SDK | ZATCA Tools platform | |
|---|---|---|
| What it is | A library in your code | A hosted product |
| Where it runs | Your servers | Our servers |
| Account | None | Required |
| Price | Free (MIT) | Subscription |
| Onboarding, signing, reporting, clearance | Yes | Yes |
| Printed invoices (PDF/A-3) | Yes | Yes |
| Storage of invoices and the chain | Yours to build | Included |
| Dashboard, invoice history | — | Included |
| Shopify, WooCommerce, REST API | — | Included |
Building your own integration? The SDK. Would rather not run one? ZATCA Tools.