ZATCA API Client¶
C signatures use the C API. See C and C++ bindings for ownership and build instructions.
The declarations below come from the generated headers. C++ exposes the same types
in namespace fatoora through fatoora/Type.hpp headers.
The HTTP client is the main way to contact ZATCA's official fatoora platform API. Please do read the ZATCA Official API Gateway for more details.
JavaScript uses the async ZatcaClient facade and Rust-owned prepared requests.
See JavaScript / TypeScript for all six
operations, cancellation and response error handling.
ZatcaClient¶
new¶
Create client
ZatcaClient::new(config: Config) -> Result<ZatcaClient, ZatcaError>
ZatcaClient(config: Config)
#include "fatoora.h"
FatooraStatus fatoora_zatca_client_create(const FatooraConfig *config,
FatooraZatcaClient **out,
FatooraError **error);
post_csr_for_ccsid¶
Issue compliance CSID
ZatcaClient::post_csr_for_ccsid(csr: &Csr, otp: &str) -> Result<CsidCredentials<Compliance>, ZatcaError>
ZatcaClient.post_csr_for_ccsid(csr: Csr, otp: str) -> CsidCompliance
#include "fatoora.h"
FatooraStatus fatoora_zatca_client_post_csr_for_ccsid(const FatooraZatcaClient *self,
const FatooraCsr *csr,
const char *otp,
FatooraCsidCompliance **out,
FatooraError **error);
post_ccsid_for_pcsid¶
Issue production CSID
ZatcaClient::post_ccsid_for_pcsid(ccsid: &CsidCredentials<Compliance>) -> Result<CsidCredentials<Production>, ZatcaError>
ZatcaClient.post_ccsid_for_pcsid(ccsid: CsidCompliance) -> CsidProduction
#include "fatoora.h"
FatooraStatus fatoora_zatca_client_post_ccsid_for_pcsid(const FatooraZatcaClient *self,
const FatooraCsidCompliance *credentials,
FatooraCsidProduction **out,
FatooraError **error);
renew_csid¶
Renew production CSID
ZatcaClient::renew_csid(pcsid: &CsidCredentials<Production>, csr: &Csr, otp: &str, accept_language: Option<&str>) -> Result<CsidCredentials<Production>, ZatcaError>
ZatcaClient.renew_csid(pcsid: CsidProduction, csr: Csr, otp: str, accept_language: Optional[str]) -> CsidProduction
#include "fatoora.h"
FatooraStatus fatoora_zatca_client_renew_csid(const FatooraZatcaClient *self,
const FatooraCsidProduction *credentials,
const FatooraCsr *csr,
const char *otp,
const char *accept_language,
FatooraCsidProduction **out,
FatooraError **error);
check_invoice_compliance¶
Check invoice compliance
ZatcaClient::check_invoice_compliance(invoice: &SignedInvoice, credentials: &CsidCredentials<Compliance>) -> Result<ValidationResponse, ZatcaError>
ZatcaClient.check_invoice_compliance(invoice: SignedInvoice, ccsid: CsidCompliance) -> ValidationResponse
#include "fatoora.h"
FatooraStatus fatoora_zatca_client_check_invoice_compliance(const FatooraZatcaClient *self,
const FatooraSignedInvoice *invoice,
const FatooraCsidCompliance *credentials,
FatooraValidationResponse **out,
FatooraError **error);
report_simplified_invoice¶
Report simplified invoice
ZatcaClient::report_simplified_invoice(invoice: &SignedInvoice, credentials: &CsidCredentials<Production>, clearance_status: bool, accept_language: Option<&str>) -> Result<ValidationResponse, ZatcaError>
ZatcaClient.report_simplified_invoice(invoice: SignedInvoice, pcsid: CsidProduction, clearance_status: bool, accept_language: Optional[str]) -> ValidationResponse
#include "fatoora.h"
FatooraStatus fatoora_zatca_client_report_simplified_invoice(const FatooraZatcaClient *self,
const FatooraSignedInvoice *invoice,
const FatooraCsidProduction *credentials,
bool clearance_status,
const char *accept_language,
FatooraValidationResponse **out,
FatooraError **error);
clear_standard_invoice¶
Clear standard invoice
ZatcaClient::clear_standard_invoice(invoice: &SignedInvoice, credentials: &CsidCredentials<Production>, clearance_status: bool, accept_language: Option<&str>) -> Result<ValidationResponse, ZatcaError>
ZatcaClient.clear_standard_invoice(invoice: SignedInvoice, pcsid: CsidProduction, clearance_status: bool, accept_language: Optional[str]) -> ValidationResponse
#include "fatoora.h"
FatooraStatus fatoora_zatca_client_clear_standard_invoice(const FatooraZatcaClient *self,
const FatooraSignedInvoice *invoice,
const FatooraCsidProduction *credentials,
bool clearance_status,
const char *accept_language,
FatooraValidationResponse **out,
FatooraError **error);
CsidCredentials / CsidCompliance / CsidProduction¶
new¶
Create credential handle
CsidCredentials::new(env: EnvironmentType, request_id: Option<String>, token: impl Into<String>, secret: impl Into<String>) -> CsidCredentials<T>
CsidCompliance.new(env: Environment, token: str, secret: str, request_id: Optional[str] = None) -> CsidCompliance
CsidProduction.new(env: Environment, token: str, secret: str, request_id: Optional[str] = None) -> CsidProduction
#include "fatoora.h"
FatooraStatus fatoora_csid_compliance_create(int32_t environment,
const char *request_id,
const char *token,
const char *secret,
FatooraCsidCompliance **out,
FatooraError **error);
FatooraStatus fatoora_csid_production_create(int32_t environment,
const char *request_id,
const char *token,
const char *secret,
FatooraCsidProduction **out,
FatooraError **error);
env¶
Read credential environment
CsidCredentials::env(&self) -> EnvironmentType
CsidCompliance.env() -> Environment
CsidProduction.env() -> Environment
#include "fatoora.h"
FatooraStatus fatoora_csid_compliance_env(const FatooraCsidCompliance *self,
uint8_t *out,
FatooraError **error);
FatooraStatus fatoora_csid_production_env(const FatooraCsidProduction *self,
uint8_t *out,
FatooraError **error);
request_id¶
Read optional request id
CsidCredentials::request_id(&self) -> Option<&str>
CsidCompliance.request_id() -> str
CsidProduction.request_id() -> str
#include "fatoora.h"
FatooraStatus fatoora_csid_compliance_request_id(const FatooraCsidCompliance *self,
char **out,
FatooraError **error);
FatooraStatus fatoora_csid_production_request_id(const FatooraCsidProduction *self,
char **out,
FatooraError **error);
binary_security_token¶
Read token
CsidCredentials::binary_security_token(&self) -> &str
CsidCompliance.binary_security_token() -> str
CsidProduction.binary_security_token() -> str
#include "fatoora.h"
FatooraStatus fatoora_csid_compliance_binary_security_token(const FatooraCsidCompliance *self,
char **out,
FatooraError **error);
FatooraStatus fatoora_csid_production_binary_security_token(const FatooraCsidProduction *self,
char **out,
FatooraError **error);
secret¶
Read credential secret
CsidCredentials::secret(&self) -> &str
CsidCompliance.secret() -> str
CsidProduction.secret() -> str
#include "fatoora.h"
FatooraStatus fatoora_csid_compliance_secret(const FatooraCsidCompliance *self,
char **out,
FatooraError **error);
FatooraStatus fatoora_csid_production_secret(const FatooraCsidProduction *self,
char **out,
FatooraError **error);
Invoice response contract¶
This contract applies to reporting, clearance, and invoice compliance methods.
Ok (or a Python return value) means HTTP 2xx with a decoded validation body.
Non-2xx responses, including 400 and 409, return errors. Successful HTTP status
alone does not establish invoice acceptance.
| Accessor | Rust | Python | C result value |
|---|---|---|---|
http_status() |
Option<u16> |
Optional[int] |
uint16_t output plus bool has_value |
outcome() |
InvoiceOutcome |
InvoiceOutcome |
FatooraInvoiceOutcome: unknown, accepted, rejected |
ensure_accepted() |
Result<(), ZatcaError> |
returns None or raises ApiError |
FATOORA_OK or an error status |
cleared_invoice_base64() |
Option<&str> |
Optional[str] |
copied string; null if absent |
cleared_invoice_xml() |
Result<Option<String>, ZatcaError> |
Optional[str] or ParseError |
copied decoded string or error; null if absent |
C accessor names start with fatoora_validation_response_. Text getters return
owned strings through char **out; optional text returns NULL for absence,
distinct from a present empty string. Release text with fatoora_string_free().
Response children are owned copies and survive destruction of the response.
A present but empty base64 field stays an empty string and fails decoding.
Outcome uses the endpoint actually invoked: REPORTED/NOT_REPORTED for
reporting, CLEARED/NOT_CLEARED for clearance, and PASS or WARNING/ERROR
for compliance. A positive status alongside validation errors is Unknown.
Unknown or missing endpoint status also yields Unknown. Standalone JSON
serialization omits HTTP/operation metadata; deserializing a body yields no HTTP
status and an unknown outcome, even if the JSON includes metadata-like fields.
ensure_accepted() fails for both rejected and unknown outcomes and retains the
response in ZatcaError::NotAccepted.
A compliance pass establishes only the result of that check. Cleared XML decoding preserves the returned text and performs neither XML parsing nor signature verification. Missing cleared XML is independent of the acceptance outcome.
Duplicate submissions and redirects¶
Reporting HTTP 409 can mean that the same invoice hash was already reported; this submission returns an error without asserting that the earlier invoice was rejected. Duplicate clearance HTTP 208 follows the successful-response path and can carry the cleared invoice. See the Fatoora Development Team announcement.
The client does not follow HTTP redirects. A clearance-disabled 303 is exposed as a structured response error; callers decide what to do next. This change does not add automatic reporting of standard invoices. See the ZATCA developer manual.
Credential endpoints keep their existing response rules, including the wrapped HTTP 428 renewal response.
Migration¶
Code that previously handled 400/409 through Ok(ValidationResponse) must now
handle ZatcaError::Response, or ApiError in Python. Invoice HTTP 401 still
classifies as Unauthorized but now uses the status-preserving Response variant.
Other non-2xx invoice responses classify as Api. Successful HTTP responses with
malformed bodies classify as Parse; failed body reads classify as Network and
retain the received status. Rust callers can inspect ZatcaError::http_status()
and HttpResponseError::body() / validation_response().
Response Types¶
Response shapes
ValidationResponseexposesvalidation_results(),reporting_status(),clearance_status(), and QR status fields.ValidationResultsexposesinfo_messages(),warning_messages(),error_messages(), andstatus().ValidationMessageexposes type, code, category, message, and status fields.MessageListnormalizes info messages that may be one, many, or empty.UnauthorizedResponseandServerErrorResponseprovide structured error bodies.
Errors¶
Errors
ZatcaErroris returned for HTTP failures, invalid responses, unauthorized/server errors, and client-state mismatches (environment, invoice type, etc.).
See also: API Client Guide