ZATCA Guide
Comply with ZATCA e-Invoicing using B2Brouter API
The ZATCA e-Invoicing Resolution (Zakat, Tax and Customs Authority) mandates that businesses operating in Saudi Arabia must generate and submit electronic invoices in UBL XML format. B2Brouter's REST API allows your business to be fully compliant with ZATCA, handling XML generation, hash chaining, and clearance on your behalf.
What is ZATCA e-Invoicing?
ZATCA e-Invoicing (Fatoorah) requires:
- Generating invoices in UBL 2.1 XML format, with Saudi-specific extensions.
- Computing a SHA-256 hash chain linking each invoice to the previous one.
- Submitting each invoice to the ZATCA Clearance API for validation and digital signing.
- Embedding the QR code returned by ZATCA in the issued invoice.
With B2Brouter you can offload all of this. You issue invoices or create tax reports via REST calls, and B2Brouter handles chaining, clearance, and QR code generation.
Account (Company) Requirements
ZATCA invoices are issued by Saudi Arabian companies. The account must have country: "sa". The following fields are required for SA accounts:
| API param | Description | Notes |
|---|---|---|
name | Company legal name | Required |
country | Must be "sa" | Required |
address | Street name | Required |
address2 | Building number | Required — 4-digit integer |
city | City | Required |
postalcode | Postal code | Required |
province | District | Required |
tin_value | VAT registration number (15 digits) | Required |
tin_scheme | Must be 9760 (SA VAT) | Required |
Note: The fields
address2andprovincecorrespond to the Saudi address concepts of building number and district respectively. Useaddress2andprovinceas the API param names — the API will return errors referencing these names.
Contact Requirements
Contacts (buyers) for ZATCA invoices must also have correct address data. The following fields apply when country is "sa":
| API param | Description | Notes |
|---|---|---|
name | Buyer legal name | Required |
country | ISO-2 country code | Required |
address | Street name | Required for SA contacts with ZATCA enabled |
address2 | Building number | Required for SA contacts with ZATCA enabled |
city | City | Required for SA contacts with ZATCA enabled |
postalcode | Postal code | Required for SA contacts with ZATCA enabled |
province | District | Required for SA contacts with ZATCA enabled |
tin_value | VAT registration number | Required for B2B invoices |
tin_scheme | 9760 for SA VAT; see Buyer ID types for foreign buyers | Required |
Invoice Requirements
ZATCA invoices use SAR (Saudi Riyal) as currency. Taxes must use name: "VAT" and category: "S" for the standard 15% rate.
Minimal invoice example:
curl --request POST \
--url https://api-staging.b2brouter.net/accounts/{ACCOUNT_ID}/invoices \
--header 'X-B2B-API-Key: {YOUR_API_KEY}' \
--header 'Content-Type: application/json' \
--data '{
"send_after_import": true,
"invoice": {
"date": "2025-01-15",
"number": "INV-001",
"currency": "SAR",
"payment_method": 1,
"contact": {
"name": "Buyer Company Ltd",
"address": "King Fahd Road",
"address2": "1234",
"city": "Riyadh",
"postalcode": "12345",
"province": "Riyadh",
"country": "sa",
"tin_value": "310175397400003",
"tin_scheme": 9760,
"language": "en",
"currency": "SAR"
},
"invoice_lines_attributes": [
{
"quantity": 1.0,
"description": "Professional services",
"price": 100.0,
"taxes_attributes": [
{
"name": "VAT",
"percent": 15.0,
"category": "S"
}
]
}
]
}
}'Tax Categories and Exemption Codes
ZATCA defines four VAT categories. For categories E (Exempt) and Z (Zero rated), a valid exemption reason code (comment on the tax line) is required — the invoice will be rejected without it.
| Category | Description | Rate | Exemption code required? |
|---|---|---|---|
S | Standard rate | 15% | No |
E | Exempt from VAT | 0% | Yes — VATEX-SA-29, VATEX-SA-29-7, or VATEX-SA-30 |
Z | Zero rated | 0% | Yes — see table below |
O | Out of scope | 0% | No |
The exemption code is set in the comment field of the tax line:
{
"name": "VAT",
"percent": 0.0,
"category": "Z",
"comment": "VATEX-SA-32"
}Valid VATEX-SA-* Codes
Category E — Exempt from VAT
| Code | Description |
|---|---|
VATEX-SA-29 | Financial services mentioned in Article 29 of the VAT Regulations |
VATEX-SA-29-7 | Life insurance services mentioned in Article 29 of the VAT Regulations |
VATEX-SA-30 | Real estate transactions mentioned in Article 30 of the VAT Regulations |
Category Z — Zero rated
| Code | Description |
|---|---|
VATEX-SA-32 | Export of goods |
VATEX-SA-33 | Export of services |
VATEX-SA-34-1 | The international transport of Goods |
VATEX-SA-34-2 | International transport of passengers |
VATEX-SA-34-3 | Services directly connected and incidental to a Supply of international passenger transport |
VATEX-SA-34-4 | Supply of a qualifying means of transport |
VATEX-SA-34-5 | Any services relating to Goods or passenger transportation (Article 25 of the VAT Regulations) |
VATEX-SA-35 | Medicines and medical equipment |
VATEX-SA-36 | Qualifying metals |
VATEX-SA-EDU | Private education to citizen |
VATEX-SA-HEA | Private healthcare to citizen |
VATEX-SA-MLTRY | Supply of qualified military goods |
VATEX-SA-DIPLOMAT | Qualified Supplies to Diplomatic Missions |
VATEX-SA-DUTYFREE | Qualified Supply of Goods in Duty Free area |
VATEX-SA-32(bis) | Supply under Customs Suspension Arrangement |
VATEX-SA-ROYALDECREE | Supply on which the Government bears the VAT |
Category O — Out of scope
| Code | Description |
|---|---|
VATEX-SA-OOS | Services outside scope of tax / Not subject to VAT (free text per case) |
Buyer ID Types
For foreign buyers (non-SA), use tin_scheme to specify the identifier type:
tin_scheme | Description |
|---|---|
9760 | Saudi VAT registration number |
0002 | EU VAT number |
0003 | Passport number |
0004 | Official ID (country of residence) |
0005 | Certificate of residence |
0006 | Other document |
0007 | Not registered |
Tax Report Lifecycle
After creating or sending an invoice, ZATCA clearance is asynchronous. The tax_report will be in processing state initially.
Monitor progress via:
- Webhook (recommended): Subscribe to the tax report state change webhook. Final states are
registered,error,registered_with_errors. - Polling: Call the get tax report endpoint until the state is final.
Field Mapping: Invoice API → ZATCA XML
| Invoice API field | ZATCA XML element |
|---|---|
number | cbc:ID |
date | cbc:IssueDate |
company.tin_value | Supplier cbc:CompanyID |
company.address2 | Supplier cbc:BuildingNumber |
company.province | Supplier cbc:District |
contact.tin_value | Customer cbc:CompanyID |
contact.address2 | Customer cbc:BuildingNumber |
contact.province | Customer cbc:District |
tax.percent | cbc:Percent |
tax.category | cbc:ID in cac:TaxCategory |
tax.comment | cbc:TaxExemptionReasonCode |
invoice.total | cbc:TaxInclusiveAmount |
invoice.subtotal | cbc:TaxExclusiveAmount |
Updated about 3 hours ago