Codes and constants¶
Every value below is read from the backend's own enumerations on 2026-09-28, not from memory. Where the API refuses anything outside a list, the list here is the complete one.
Invoice body¶
type_code, what document this is¶
| Value | Document | When |
|---|---|---|
388 |
Tax invoice | A sale. The value for POST /api/invoices/. |
381 |
Credit note | Reduces an issued invoice. Created through POST /api/invoices/{invoice_id}/notes/, never through the invoices endpoint. |
383 |
Debit note | Increases an issued invoice. Same notes endpoint. |
386 |
Advance payment invoice | Money received before supply. Referenced later from the sale through prepaid_invoices. |
An integer, not a string.
transaction_code, standard or simplified, and which special case¶
A seven-character string. ZATCA calls it the invoice type "name". The first two characters say who the buyer is; the last five are flags.
0 1 0 0 0 0 0
└┬┘ │ │ │ │ └─ self-billed
│ │ │ │ └─── summary
│ │ │ └───── export
│ │ └─────── nominal
│ └───────── third party
└───────────── 01 standard (business buyer, clearance)
02 simplified (consumer, reporting)
Accepted at creation, the complete list:
| Value | Meaning |
|---|---|
0100000 |
Standard tax invoice to a business. Cleared by ZATCA before it is valid. |
0200000 |
Simplified tax invoice to a consumer. Reported to ZATCA within 24 hours. |
0100100 |
Standard export invoice to a non-resident buyer. Zero-rated lines with an export reason. |
Anything else, including export on a simplified invoice, third party, nominal, summary and self-billed, is refused with 400 Invalid transaction_code. The device must allow the type: see invoice_type under Devices below.
payment_means_type_code, how the buyer pays¶
A string. Subset of UN/CEFACT code list 4461. Each carries an English and an Arabic label that print on the invoice.
| Value | Meaning | Arabic |
|---|---|---|
"10" |
In cash | نقدا |
"20" |
Cheque | شيك |
"23" |
Bank cheque, issued by a bank | شيك بنكي |
"25" |
Certified cheque | شيك مصدق |
"26" |
Local cheque | شيك محلي |
"30" |
Credit transfer | تحويل الائتمان |
"31" |
Debit transfer | تحويل الخصم |
"46" |
Interbank debit transfer | تحويل خصم بين البنوك |
"48" |
Bank card | بطاقة بنكية |
"49" |
Direct debit | الخصم المباشر |
"54" |
Credit card | بطاقة ائتمان |
"55" |
Debit card | بطاقة الخصم |
"30" credit transfer requires payment_terms in the body, or the create is refused with Payment terms are required for credit payment. The other codes need nothing more. GET /api/invoices/payment-means-types/ returns the same list.
currency and exchange_rate¶
currency is an ISO 4217 code; SAR for a domestic sale. exchange_rate is required, a number, 1 for SAR. For an export invoice in another currency send that currency and its rate to SAR; VAT is always reported to ZATCA in SAR.
issue_date and issue_time, set by the server¶
YYYY-MM-DD and HH:MM:SS, in Riyadh time, and written by Clix, not by you. The server stamps both from its own clock at the moment it accepts the invoice and discards whatever you send. The worked example shows it: the request carried 10:00:00 and the invoice came back 13:27:38.
Send both keys anyway on backend release 0.108.7, which demands them. The release after it makes them optional, so they can be dropped once your environment is past 0.108.7.
supply_date and supply_end_date¶
YYYY-MM-DD, in Riyadh time, and yours to set. supply_date is when the goods or service were delivered; for a single delivery set supply_end_date to the same day.
notes[]¶
Free text printed on the invoice. language_id is en or ar; note is the text. Optional; send [] for none.
is_sample_invoice¶
false for every real invoice. true marks the sample invoices Clix itself sends to ZATCA during device onboarding to obtain the production certificate. Your integration never sets it.
add_prepaid_amount and prepaid_invoices[]¶
false and [] unless the sale was paid in advance through a 386 advance payment invoice. Then set true and list the advance invoices being applied; Clix deducts their amount from what is payable.
reason_id and original_invoice_reference[]¶
Used by credit and debit notes only. reason_id is the uuid of an adjustment reason the organisation configured under Setup → Reasons; each reason belongs to one document type, credit or debit. original_invoice_reference names the invoice being corrected. On a tax invoice send null and [].
form_lines[] and lines¶
form_lines is the list of lines you write; lines stays [], Clix fills it. Per line:
| Field | Type | Values |
|---|---|---|
item_name |
string | free text; printed |
item_net_price |
decimal as a string | unit price before VAT, "100" or "100.00" |
invoiced_quantity |
number | 1 or 2.5 |
invoiced_quantity_unit_of_measure |
string | one of the unit codes below |
vat_category_code |
S, Z, E, O |
see the table below |
vat_rate |
number | must match the category |
vat_exemption_reason_code |
string | required for Z and E; "" otherwise |
vat_exemption_reason_text |
string | required for O, your own wording; "" otherwise |
invoice_line_id |
uuid | notes only, the original line being corrected |
vat_category_code and the vat_rate it allows¶
| Code | Category | Accepted vat_rate |
Needs |
|---|---|---|---|
S |
Standard rated | 15.0 or 5.0 |
nothing |
Z |
Zero rated | 0.0 |
a VATEX-SA-… reason code |
E |
Exempt from VAT | 0.0 |
a VATEX-SA-… reason code |
O |
Not subject to VAT | 0.0 |
vat_exemption_reason_text, free text |
A rate outside the list for its category is refused. The sixteen VATEX-SA-… reason codes and the category each belongs to come from GET /api/invoices/vat-exemption-reasons/; the human list is on Reference data.
invoiced_quantity_unit_of_measure¶
UN/ECE Recommendation 20 codes, the complete accepted list:
| Code | Unit | Code | Unit | Code | Unit |
|---|---|---|---|---|---|
PCE |
piece | PCS |
pieces | PKT |
packet |
CTN |
carton | BOX |
box | PALLET |
pallet |
KGM |
kilogram | GRM |
gram | MGM |
milligram |
MC |
microgram | GRN |
grain | TNE |
tonne |
DTN |
tonne, metric | TON |
ton, US | STN |
short ton |
LTN |
long ton | STI |
stone | LBR |
pound |
ONZ |
ounce | LTR |
litre | K6 |
kilolitre |
GLL |
gallon | BL |
barrel | MTQ |
cubic metre |
FTQ |
cubic foot | H19 |
hundred cubic foot | CDL |
cord |
MTK |
square metre | FTK |
square foot | INK |
square inch |
ACR |
acre | MTR |
metre | CMT |
centimetre |
INH |
inch | FOT |
foot | YRD |
yard |
KWH |
kilowatt-hour | JOU |
joule | D10 |
calorie |
GET /api/invoices/units-of-measure/ returns the same codes with Arabic labels. Services usually use PCE.
Devices¶
invoice_type and business_type, what a device may issue¶
invoice_type |
business_type |
May issue | transaction_code allowed |
|---|---|---|---|
1000 |
B2B |
standard only | 0100000, 0100100 |
0100 |
B2C |
simplified only | 0200000 |
1100 |
BOTH |
either | all three |
Chosen when the device is connected in the app: Businesses, Consumers or Both. An invoice whose transaction_code the device does not allow is refused.
device_status, where the device is in ZATCA onboarding¶
In order. Only the last successful state can issue invoices.
| Value | Meaning | In the app |
|---|---|---|
csr_pending, csr_generated |
signing request being made | Setup in Progress |
ccsid_pending, ccsid_generated |
compliance certificate being issued | Setup in Progress |
ccsid_failed |
compliance certificate refused, usually a bad or used Fatoora code | Action Required |
sample_invoices_pending, sample_invoices_generated |
Clix submitting the sample invoices ZATCA requires | Setup in Progress |
sample_invoices_failed |
a sample was rejected | Action Required |
ZATCA_Submission_Pending |
waiting on ZATCA | Pending Activation |
ZATCA_Submission_Failed |
ZATCA refused | Action Required |
pcsid_pending |
production certificate being issued | Pending Activation |
pcsid_generated |
production certificate held; the device can issue | Active |
pcsid_failed |
production certificate refused | Action Required |
ccsid_status and pcsid_status read ISSUED once each certificate exists; the *CertificateData objects carry not_valid_after and days_until_expiry.
Invoice responses¶
zatca_response_status¶
| Value | Meaning | Final? |
|---|---|---|
CLEARED |
standard invoice accepted and stamped by ZATCA | yes |
REPORTED |
simplified invoice accepted by ZATCA | yes |
NOT_CLEARED |
standard invoice rejected; reasons in zatca_response_data.validationResults.errorMessages[] |
no, fix and resubmit |
NOT_REPORTED |
simplified invoice rejected; same place | no, fix and resubmit |
Absent or null while ZATCA has not answered. zatca_response_code is ZATCA's HTTP status, 200 on acceptance, 400 on rejection.
payment_status¶
Set by payments you record, never by ZATCA.
| Value | Meaning |
|---|---|
Pending |
nothing received |
Partially Paid |
some payments recorded, balance remains |
Paid |
payments equal the total |
Overdue |
balance remains and the due date has passed |
Cancelled |
credited in full |
API keys¶
Access level, the role a key carries¶
| In the app | Value | A key with it can |
|---|---|---|
| View only | ViewInvoice |
read invoices, clients, items, devices, usage |
| Create and view invoices | CreateInvoice |
the above, plus create invoices, notes, clients and items |
| Accountant | Accountant |
the same as CreateInvoice on this surface |
Admin cannot be given to a key. Optional scopes[] narrow a key below its role and never widen it: invoice.create, invoice.get, and the other permission names shown in Swagger.
Related¶
- Quickstart, where these values appear in a body
- Worked example, the same body on the wire
- Reference data, the endpoints that return these lists with Arabic labels
- Invoice types, the same ideas for a non-developer