Skip to content

ZATCA API Client

Using the fatoora-core API client for compliance, reporting, and clearance APIs.

Example

use fatoora_core::api::{CsidCredentials, Production, ZatcaClient};
use fatoora_core::config::{Config, EnvironmentType};
use fatoora_core::invoice::xml::parse::parse_signed_invoice_xml;

#[tokio::main]
pub async fn main() {
    // read and parse the signed XML invoice
    let signed_xml_path = std::path::Path::new(env!("CARGO_MANIFEST_DIR"))
        .join("tests/fixtures/invoices/sample-simplified-invoice.xml");
    let xml = std::fs::read_to_string(&signed_xml_path).unwrap();
    let signed = parse_signed_invoice_xml(&xml).unwrap();

    // initialize the API client and credentials
    let config = Config::new(EnvironmentType::NonProduction);
    let client = ZatcaClient::new(config).unwrap();

    // you can get the sandbox credentials from the ZATCA developer portal:
    // at https://sandbox.zatca.gov.sa/IntegrationSandbox/reporting-api
    let pcsid = CsidCredentials::<Production>::new(
        EnvironmentType::NonProduction,
        None,
        EXAMPLE_BST,
        EXAMPLE_SECRET,
    );

    let response = client
        .report_simplified_invoice(&signed, &pcsid, false, Some("en"))
        .await
        .unwrap();

    assert_eq!(response.reporting_status(), Some("REPORTED"));
}
from fatoora.api import CsidProduction, ZatcaClient
from fatoora.config import Config, Environment
from fatoora.invoice import parse_signed_invoice_xml

# signed_xml_path = "path/to/signed_invoice.xml"
signed = parse_signed_invoice_xml(signed_xml_path.read_text(encoding="utf-8"))

config = Config(Environment.NON_PRODUCTION)
client = ZatcaClient(config)

pcsid = CsidProduction.new(
    Environment.NON_PRODUCTION,
    EXAMPLE_BST,
    EXAMPLE_SECRET,
    None,
)

response = client.report_simplified_invoice(signed, pcsid, False, "en")

assert response.reporting_status() == "REPORTED"
#include "fatoora.h"

#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#ifndef FATOORA_DOC_SIGNED_XML
#define FATOORA_DOC_SIGNED_XML "path/to/signed_invoice.xml"
#endif

static char *read_file(const char *path);

int main(void) {
  // parse the signed XML invoice into a struct
  const char *signed_xml_path = FATOORA_DOC_SIGNED_XML;
  char *xml_cstr = read_file(signed_xml_path);
  struct FfiResult_FfiSignedInvoice signed_invoice =
      fatoora_parse_signed_invoice_xml(xml_cstr);

  struct FfiConfig *config = fatoora_config_new(FfiEnvironment_NonProduction);
  struct FfiResult_FfiZatcaClient client = fatoora_zatca_client_new(config);

  struct FfiResult_FfiCsidProduction pcsid = fatoora_csid_production_new(
      FfiEnvironment_NonProduction, NULL, EXAMPLE_BST, EXAMPLE_SECRET);

  // response handle provides getters for results
  FfiResult_FfiValidationResponse resp =
      fatoora_zatca_report_simplified_invoice(
          &client.value, &signed_invoice.value, &pcsid.value, true, "en");

  FfiResult_FfiString reporting_status =
      fatoora_validation_response_reporting_status(&resp.value);

  assert(!strcmp(reporting_status.value.ptr, "REPORTED"));

  // don't forget to free all the resources you allocated!
  free(xml_cstr);
  fatoora_signed_invoice_free(&signed_invoice.value);
  fatoora_csid_production_free(&pcsid.value);
  fatoora_validation_response_free(&resp.value);
  fatoora_zatca_client_free(&client.value);
  fatoora_config_free(config);

  return 0;
}

Notes

  • Config and credentials must target the same environment (non-production, simulation, or production).
  • Reporting and clearance APIs require production credentials; compliance checks use compliance credentials.
  • All endpoints return structured validation responses; in FFI/bindings these are opaque handles with getter functions (no JSON payloads).

See also: API Client Reference