مولَّد من مستند OpenAPI المنشور (الإصدار 1.4.0). https://fatoora.tw.sa/api/v1
/invoices
List invoices
الصلاحية المطلوبة
invoices:read
Tax invoices only, newest first.
المعاملات
| الحقل | النوع | الوصف |
|---|---|---|
limit
|
integer · query | Page size. |
cursor
|
string · query | meta.pagination.next_cursor of the previous page. |
status
|
array<string> · query | One or more statuses (status[]=paid&status[]=partial, or comma-separated). overdue is worked out from the due date. |
zatca_status
|
array<string: pending, not_submitted, cleared, reported, rejected, retrying, unknown> · query | One or more ZATCA statuses. |
customer_id
|
integer · query | |
issue_date_from
|
string (date) · query | |
issue_date_to
|
string (date) · query | |
updated_since
|
string (date-time) · query | |
external_reference
|
string · query | |
number
|
string · query |
الردود
- 200 A page of invoices.
-
default
An error.
error.codesays which.
/invoices
Create an invoice, as a draft or issued at once
الصلاحية المطلوبة
invoices:draft
Issues the invoice unless issue is false; issuing also needs the
invoices:issue scope. Counts against the plan's monthly invoice
allowance.
Sending your own external_reference (an order number) makes the call
safe to retry: a repeat answers 200 with replayed: true and the
invoice already made. A key without invoices:read is told only the
invoice's id, number and status.
Paid already, through your own payment gateway or till? Send
payment and the payment is recorded in the same call, so the
invoice arrives paid (or partial). It needs the payments:write
scope and an issued invoice; amount defaults to the whole total.
If the payment is refused, nothing is created.
المعاملات
| الحقل | النوع | الوصف |
|---|---|---|
Idempotency-Key
|
string · header | 8 to 255 visible ASCII characters, unique per operation you mean to perform. |
محتوى الطلب application/json
| الحقل | النوع | الوصف |
|---|---|---|
issue_date
مطلوب
|
string (date) | |
due_date
|
string | null (date) | |
issue
|
boolean | null | false creates a draft. |
currency
|
string | null | Defaults to SAR. |
exchange_rate
|
number | null | SAR per unit of currency; required for a foreign currency. |
locale
|
string | null: ar, en, null | |
notes
|
string | null | |
terms
|
string | null | |
external_reference
|
string | null | Your own id for the sale. |
source_system
|
string | null | |
document_discount_type
|
string | null: amount, percent, null | |
document_discount_value
|
number | null | |
payment
|
object | null | Paid already: recorded with the invoice, which then arrives paid (or partial). Needs payments:write; not with issue: false. |
payment.amount
|
number | null | Defaults to the invoice total. |
payment.method
|
string | null | cash (default), bank_transfer, mada, visa_mastercard, apple_pay, stc_pay, cheque, other, or a code the company added. |
payment.reference
|
string | null | Your gateway transaction id, for example. |
payment.paid_on
|
string | null (date) | Defaults to today; never later than today. |
payment.notes
|
string | null | |
payment.account_id
|
integer | null | The company cash or bank account the money went into. |
customer
|
object | null | An existing customer by id, or a new one by its details. |
customer.id
|
integer | null | |
customer.name
|
string | null | |
customer.vat_number
|
string | null | |
customer.type
|
string | null: individual, business, null | Defaults to business with a VAT number, individual without. A Saudi business gets a standard invoice even without a VAT number. |
customer.cr_number
|
string | null | Commercial registration; 10 digits for a Saudi buyer. |
customer.email
|
string | null | |
customer.phone
|
string | null | |
customer.address_line1
|
string | null | |
customer.address_line2
|
string | null | |
customer.building_number
|
string | null | National address building number; 4 digits for a Saudi buyer. |
customer.additional_number
|
string | null | National address additional number; 4 digits for a Saudi buyer. |
customer.district
|
string | null | |
customer.city
|
string | null | |
customer.country
|
string | null | |
customer.postal_code
|
string | null | |
items
مطلوب
|
array<object> | |
items[].description
مطلوب
|
string | |
items[].quantity
مطلوب
|
number | |
items[].unit_price
مطلوب
|
number | |
items[].unit
|
string | null | |
items[].discount
|
number | null | |
items[].vat_rate
|
number | null | |
items[].tax_rate_id
|
integer | null | |
items[].product_id
|
integer | null | |
items[].vat_exemption_code
|
string | null | |
items[].vat_exemption_reason
|
string | null |
الردود
- 201 The invoice was created.
-
200
A repeat of an
external_referencealready invoiced. -
default
An error.
error.codesays which.
curl -X POST https://fatoora.tw.sa/api/v1/invoices \
-H "Authorization: Bearer wbk_test_xxxxxxxxxxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-H "Accept: application/json" \
-d '{
"issue": false,
"issue_date": "2026-11-03",
"customer": {
"name": "Example Trading Co.",
"vat_number": "300000000000003",
"address_line1": "King Fahd Rd",
"city": "Riyadh",
"postal_code": "12345",
"country": "SA"
},
"items": [
{ "description": "Consulting", "quantity": 2, "unit_price": 500, "vat_rate": 15 }
]
}'
<?php
$response = $client->post('invoices', [
'json' => [
'issue' => false, // a draft: no legal number, nothing sent to ZATCA
'issue_date' => '2026-11-03',
'customer' => [
'name' => 'Example Trading Co.',
'vat_number' => '300000000000003',
'address_line1' => 'King Fahd Rd',
'city' => 'Riyadh',
'postal_code' => '12345',
'country' => 'SA',
],
'items' => [
['description' => 'Consulting', 'quantity' => 2, 'unit_price' => 500, 'vat_rate' => 15],
],
],
'http_errors' => false,
]);
$body = json_decode((string) $response->getBody(), true);
if ($body['ok']) {
echo $body['data']['invoice']['number']; // DRAFT-… until it is issued
} else {
echo $body['error']['code'];
}
const res = await fetch("https://fatoora.tw.sa/api/v1/invoices", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.WONDERFATOORA_API_KEY}`,
"Content-Type": "application/json",
Accept: "application/json",
},
body: JSON.stringify({
issue: false, // a draft: no legal number, nothing sent to ZATCA
issue_date: "2026-11-03",
customer: {
name: "Example Trading Co.",
vat_number: "300000000000003",
address_line1: "King Fahd Rd",
city: "Riyadh",
postal_code: "12345",
country: "SA",
},
items: [{ description: "Consulting", quantity: 2, unit_price: 500, vat_rate: 15 }],
}),
});
const body = await res.json();
if (!body.ok) throw new Error(`${body.error.code}: ${body.error.message}`);
console.log(body.data.invoice.id, body.data.invoice.number);
res = requests.post(
"https://fatoora.tw.sa/api/v1/invoices",
headers={
"Authorization": f"Bearer {os.environ['WONDERFATOORA_API_KEY']}",
"Accept": "application/json",
},
json={
"issue": False, # a draft: no legal number, nothing sent to ZATCA
"issue_date": "2026-11-03",
"customer": {
"name": "Example Trading Co.",
"vat_number": "300000000000003",
"address_line1": "King Fahd Rd",
"city": "Riyadh",
"postal_code": "12345",
"country": "SA",
},
"items": [
{"description": "Consulting", "quantity": 2, "unit_price": 500, "vat_rate": 15}
],
},
timeout=30,
)
body = res.json()
print(res.status_code, body["data"]["invoice"]["number"] if body["ok"] else body["error"])
/invoices/{invoice}
Get an invoice
الصلاحية المطلوبة
invoices:read
المعاملات
| الحقل | النوع | الوصف |
|---|---|---|
invoice
مطلوب
|
integer · path |
الردود
- 200 The invoice.
-
default
An error.
error.codesays which.
curl https://fatoora.tw.sa/api/v1/invoices/1024 \
-H "Authorization: Bearer wbk_test_xxxxxxxxxxxxxxxxxxxxxxxx" \
-H "Accept: application/json"
<?php
$response = $client->get('invoices/1024', ['http_errors' => false]);
$invoice = json_decode((string) $response->getBody(), true)['data']['invoice'] ?? null;
if ($invoice && $invoice['zatca']['deliverable']) {
// Safe to hand to the buyer: send $invoice['public_url'].
}
const res = await fetch("https://fatoora.tw.sa/api/v1/invoices/1024", {
headers: {
Authorization: `Bearer ${process.env.WONDERFATOORA_API_KEY}`,
Accept: "application/json",
},
});
const { ok, data, error } = await res.json();
if (ok && data.invoice.zatca.deliverable) {
// Safe to hand to the buyer: data.invoice.public_url
}
res = requests.get(
"https://fatoora.tw.sa/api/v1/invoices/1024",
headers={"Authorization": f"Bearer {os.environ['WONDERFATOORA_API_KEY']}",
"Accept": "application/json"},
timeout=30,
)
invoice = res.json().get("data", {}).get("invoice")
if invoice and invoice["zatca"]["deliverable"]:
print(invoice["public_url"])
/invoices/{invoice}/status
Where an invoice stands
الصلاحية المطلوبة
invoices:read
Its status, payments and ZATCA status, without its lines. Made for polling.
المعاملات
| الحقل | النوع | الوصف |
|---|---|---|
invoice
مطلوب
|
integer · path |
الردود
- 200 The status.
-
default
An error.
error.codesays which.
/invoices/{invoice}/validate
Check whether a draft can be issued
الصلاحية المطلوبة
invoices:draft
Runs every check issuing runs, and changes nothing.
المعاملات
| الحقل | النوع | الوصف |
|---|---|---|
invoice
مطلوب
|
integer · path |
الردود
- 200 Whether it can be issued, and what is missing.
-
default
An error.
error.codesays which.
/invoices/{invoice}/issue
Issue a draft
الصلاحية المطلوبة
invoices:issue
Gives the draft its tax-invoice number and QR and, for a company linked
to ZATCA, submits it. Irreversible: an issued invoice is corrected with
a credit or debit note. An invoice already issued answers 200 with
already_issued: true.
المعاملات
| الحقل | النوع | الوصف |
|---|---|---|
invoice
مطلوب
|
integer · path | |
Idempotency-Key
|
string · header | 8 to 255 visible ASCII characters, unique per operation you mean to perform. |
الردود
- 200 The issued invoice.
-
default
An error.
error.codesays which.
/invoices/{invoice}/pdf
Download the invoice PDF
الصلاحية المطلوبة
invoices:download
A standard invoice ZATCA has not cleared yet prints without a QR and is marked as not yet valid.
المعاملات
| الحقل | النوع | الوصف |
|---|---|---|
invoice
مطلوب
|
integer · path |
الردود
- 200 The PDF.
-
default
An error.
error.codesays which.
/invoices/{invoice}/xml
Download the legal XML
الصلاحية المطلوبة
invoices:download
The document ZATCA holds: the cleared XML of a standard invoice, the
signed XML of a simplified one. document_not_available (409) until
there is one; xml_not_applicable (404) for a company not linked to
ZATCA.
المعاملات
| الحقل | النوع | الوصف |
|---|---|---|
invoice
مطلوب
|
integer · path |
الردود
- 200 The XML.
-
default
An error.
error.codesays which.
/invoices/{invoice}/payments
Customer payments of an invoice
الصلاحية المطلوبة
invoices:read
المعاملات
| الحقل | النوع | الوصف |
|---|---|---|
invoice
مطلوب
|
integer · path |
الردود
- 200 The payments, oldest first, and the invoice balance.
-
default
An error.
error.codesays which.
/invoices/{invoice}/payments
Record a customer payment on an issued invoice
الصلاحية المطلوبة
payments:write
For money received after the invoice was made (a bank transfer, a
late confirmation from your gateway). Never more than the balance
still owed (payment_exceeds_balance), never on a draft, cancelled
or refunded invoice (invoice_not_payable). Paid before the invoice
was made? Send payment with POST /invoices instead.
المعاملات
| الحقل | النوع | الوصف |
|---|---|---|
invoice
مطلوب
|
integer · path | |
Idempotency-Key
|
string · header | 8 to 255 visible ASCII characters, unique per operation you mean to perform. |
محتوى الطلب application/json
| الحقل | النوع | الوصف |
|---|---|---|
amount
مطلوب
|
number | In the invoice currency; at most the balance. |
method
|
string | null | cash (default), bank_transfer, mada, visa_mastercard, apple_pay, stc_pay, cheque, other, or a code the company added. |
reference
|
string | null | |
paid_on
|
string | null (date) | Defaults to today; never later than today. |
notes
|
string | null | |
account_id
|
integer | null | The company cash or bank account the money went into. |
الردود
- 201 The payment and the invoice new balance.
-
default
An error.
error.codesays which.
العودة إلى مرجع الواجهة البرمجية
جاهز للبدء؟
الوصول إلى الواجهة البرمجية ضمن باقات: الأعمال والمؤسسات. أنشئ مفتاحًا من الإعدادات ← مفاتيح API وأرسل أول طلب خلال دقائق.