Skip to content
mqqzPublic

About

Open-source toolkit for everything you'd need for ZATCA (Zakat, Tax and Customs Authority of Saudi Arabia) Phase 1 and 2 compliant e-invoicing

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

4 stars

Watchers

0 watching

Forks

Latest commit

Β 

History

377 Commits

Folders and files

πŸ‡ΈπŸ‡¦ fatoority 🧾
fatoority-logo

🌐 Homepage Β β€’Β  ⚑ Features Β β€’Β  πŸ“₯ Installation Β β€’Β  πŸ’‘ Examples Β β€’Β  πŸ—‚οΈ Documentation

fatoority is an unofficial open-source toolkit for developers building e-invoicing integrations in Saudi Arabia. Sign invoice XML, validate it locally, generate QR payloads, and connect to ZATCA APIs for Phase 1 and Phase 2 workflows.

With bindings and support for many programming languages:

  • πŸ¦€ Rust fatoora-core Crates.io Version

  • 🐍 Python PyPi Version

  • πŸ‡―β€ŒπŸ‡Έβ€Œ JavaScript / TypeScript NPM Version

  • 🟣 C# / .NET NuGet Version

  • β˜• Kotlin / Java / Android Maven Central Version

  • πŸŒ€ C/C++ (through the C FFI see releases)

  • πŸ”Œ Also, a Command Line Interface (CLI) Tool fatoora-cli Crates.io Version

Disclaimer: fatoority is not affiliated, associated, authorized, endorsed by, or in any way officially connected with ZATCA (Zakat, Tax and Customs Authority), or any of its subsidiaries or its affiliates. The official ZATCA website can be found at https://zatca.gov.sa.

πŸ—‚οΈ Documentation

Checkout the homepage, also the Rust API at docs.rs may prove useful.

⚑ Features

Tools for your ZATCA integration:

πŸš€ But we do it faster and better e.g. ~190x faster invoice hashing than ZATCA's SDK (see bench/)

βš™οΈ Rigorously tested with fuzzing and ~97% coverage

See the benchmarks for measured performance and methodology, and SDK compatibility notes for the scope of comparison with the official SDK. Local validation does not establish certificate issuer trust or ZATCA gateway acceptance.

πŸ“₯ Installation

Rust
cargo add fatoora-core
Python
pip install fatoority
JavaScript / TypeScript
npm install fatoority
C# / .NET 8
dotnet add package Fatoority
Kotlin / Java / Android

Install a published release from Maven Central.

Gradle (build.gradle.kts):

repositories { mavenCentral() }
dependencies {
    implementation("com.fatoority:fatoority:0.4.3")
}

Maven (pom.xml):

<dependency>
  <groupId>com.fatoority</groupId>
  <artifactId>fatoority</artifactId>
  <version>0.4.3</version>
</dependency>

For Android, use com.fatoority:fatoority-android:0.4.3 instead of the desktop artifact. Java/Kotlin imports remain com.fatoora.

C/C++

Download the fatoora-ffi-* archive for your platform from releases and extract it. The shared library is at the archive root. The C API header is include/fatoora.h, with its adapter in src/fatoora.c and generated headers in include/generated; C++ headers are in include/diplomat-cpp and expose types in namespace fatoora.

For example, on Linux, compile your application from the extracted directory:

cc -std=c11 -Iinclude app.c src/fatoora.c -L. -lfatoora_ffi -Wl,-rpath,'$ORIGIN' -o app
c++ -std=c++17 -Iinclude/diplomat-cpp app.cpp -L. -lfatoora_ffi -Wl,-rpath,'$ORIGIN' -o app-cpp

Include fatoora.h in C or fatoora/Config.hpp in C++. Keep the shared library beside these executables. On Windows, link the supplied import library and keep the DLLs from the archive beside your executable.

To build the library from a source checkout:

cargo build -p fatoora-ffi --release --locked

The C API provides one fatoora.h, plain strings, shared errors, and named-field options. Compile bindings/c/fatoora.c once with your application, add bindings/c to your include path, and link fatoora_ffi. Release archives also include the C examples under examples/c.

The library is written to target/release/. The generated headers are checked in under bindings/c/generated and bindings/cpp; raw ABI callers use those include paths and -Ltarget/release when compiling against a source build. Cargo does not regenerate headers. After changing bridge declarations, follow the Diplomat generation workflow.

CLI

The cli tool can also be installed with cargo:

cargo install fatoora-cli

Alternatively, you can grab the precompiled binary for your platform on the repo's releases (fatoora-cli-*). Extract the archive and run fatoora.

πŸ’‘ Examples

CSR Generation

Rust

use fatoora_core::config::EnvironmentType;
use fatoora_core::csr::{CsrProperties, SigningKey};

let props_text = std::fs::read_to_string("csr.properties")?;
let props = CsrProperties::from_properties_str(&props_text)?;
let key = SigningKey::generate();
let csr = props.build(&key, EnvironmentType::NonProduction)?;
let csr_pem = csr.to_pem()?;
let key_pem = key.to_pem()?;

Python

from fatoora.config import Environment
from fatoora.csr import CsrProperties, SigningKey

props = CsrProperties.parse_csr_config_file("csr.properties")
key = SigningKey.generate()
csr = props.build(key, Environment.NON_PRODUCTION)
csr_pem = csr.to_pem_base64()
key_pem = key.to_pem()

JavaScript

import { CsrProperties, SigningKey } from 'fatoority';

const key = SigningKey.generate();
const csr = CsrProperties.fromPropertiesStr(propertiesText).build(key, 0);
const csrPem = csr.toPem();

CLI

fatoora csr --csr-config csr.properties --generated-csr csr.pem --private-key key.pem --pem
Invoice Signing

Rust

use fatoora_core::invoice::sign::InvoiceSigner;

let cert_pem = std::fs::read_to_string("cert.pem")?;
let key_pem = std::fs::read_to_string("key.pem")?;
let signer = InvoiceSigner::from_pem(cert_pem.trim(), key_pem.trim())?;
let xml = std::fs::read_to_string("invoice.xml")?;
let signed_xml = signer.sign_xml(&xml)?;

CLI

fatoora sign --invoice invoice.xml --cert cert.pem --key key.pem --signed-invoice signed.xml
Validation

Rust

use fatoora_core::config::Config;
use fatoora_core::invoice::validation::{
    validate_zatca_invoice_from_str, ZatcaValidationOptions,
};

let config = Config::new(fatoora_core::config::EnvironmentType::NonProduction);
let xml = std::fs::read_to_string("invoice.xml")?;
let options = ZatcaValidationOptions {
    previous_invoice_hash: Some(previous_hash_from_history),
    ..Default::default()
};
let report = validate_zatca_invoice_from_str(&xml, &config, &options)?;
if !report.is_valid() {
    // Inspect stages and findings; missing predecessor context is incomplete.
}

CLI

fatoora validate --invoice invoice.xml --profile zatca --format json \
  --previous-invoice-hash "$PREVIOUS_INVOICE_HASH"

The local profile implements all 257 business-rule assertions from SDK 238-R3.4.8, plus applicable signature, QR and predecessor checks. It preserves warnings and partial reports. Standard invoices skip signature/QR checks under this SDK profile. Local validation does not establish issuer trust or remote acceptance. Existing validate_xml_invoice_from_str and the default CLI profile continue to check XSD only.

QR Generation & Reading

Rust

use fatoora_core::invoice::xml::parse::parse_signed_invoice_xml;

let xml = std::fs::read_to_string("signed.xml")?;
let signed = parse_signed_invoice_xml(&xml)?;
let qr = signed.qr_code();

CLI

fatoora qr --invoice invoice.xml
fatoora qr --invoice signed.xml
fatoora qr --invoice signed.xml --fail-on-signed
fatoora qr-read --invoice signed.xml
Invoice Hash

Rust

use fatoora_core::invoice::xml::parse::parse_finalized_invoice_xml;

let xml = std::fs::read_to_string("invoice.xml")?;
let invoice = parse_finalized_invoice_xml(&xml)?;
let hash = invoice.hash_base64()?;

CLI

fatoora generate-hash --invoice invoice.xml
Invoice Request Payload

Rust

use fatoora_core::invoice::xml::parse::parse_signed_invoice_xml;

let xml = std::fs::read_to_string("signed.xml")?;
let signed = parse_signed_invoice_xml(&xml)?;
let payload = serde_json::json!({
    "invoiceHash": signed.invoice_hash(),
    "uuid": signed.uuid(),
    "invoice": signed.to_xml_base64(),
});

CLI

fatoora invoice-request --invoice signed.xml --api-request request.json

And much more... see the guides in the homepage for more info.

🀝 Contributing

Contributions are always welcome! See CONTRIBUTING.md for more details.

πŸͺ§ Roadmap

  • Increase test coverage to 100% (Inshallah)
  • Expand bindings to other languages (subject to demand)
  • PDF invoice generation

Author πŸ€“

This project began as a personal undertaking, and continues to be developed and maintained by me @mqqz.

While this means development happens alongside other commitments, I do my best to keep the project maintained and responsive to issues. Contributions, feedback, and suggestions are always welcome.

If you or your team are working on fintech or ZATCA integrations and need help building reliable scalable infrastructure, feel free to get in touch.

πŸ”— Relevant Links

License

This project's code is licensed under either the MIT License or the Apache License, Version 2.0, at your option.

Third-party schemas, fixtures, templates, and dependencies retain their applicable upstream licenses and notices. The project license does not relicense those materials.

See third-party notices for attribution, applicable terms, and outstanding permission questions.

About

Open-source toolkit for everything you'd need for ZATCA (Zakat, Tax and Customs Authority of Saudi Arabia) Phase 1 and 2 compliant e-invoicing

Topics

Resources

Code of conduct

Contributing

Security policy

Stars

4 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages