اربط كلكس مع أنظمتك
أنشئ واقرأ فواتير متوافقة مع هيئة الزكاة والضريبة والجمارك من نظام ERP أو نقاط البيع أو برنامج المحاسبة لديك عبر مفتاح API. تضيف عملاءك وأصنافك وجهاز الهيئة مرة واحدة في تطبيق كلكس، وواجهة API تقرؤها ولا تنشئها.
افتح مرجع APIالحصول على الوصول
احصل على مفتاح في أربع خطوات
باقة تشمل الوصول إلى API
الوصول إلى API مشمول في باقة الأعمال. المنشآت على الباقة المجانية أو الاحترافية ترى دعوة للترقية بدلاً من نموذج المفتاح.
مشرف في المنشأة
المشرفون فقط يمكنهم إصدار المفاتيح وعرضها وإلغاؤها. اطلب من مشرف منشأتك، أو دعه يصدر المفتاح لك.
أنشئ المفتاح
في تطبيق كلكس افتح الإعدادات ← مفاتيح API ← إنشاء مفتاح. سمِّه باسم النظام الذي سيستخدمه واختر مستوى الوصول.
انسخه مرة واحدة
يُعرض المفتاح الكامل مرة واحدة فقط. نحتفظ بالتجزئة فقط ولا يمكننا عرضه مجدداً — احفظه في مدير الأسرار لديك، لا في الشيفرة أبداً.
كلكس مدرجة في دليل مزوّدي الحلول لدى هيئة الزكاة والضريبة والجمارك كمزوّد مؤهّل للمرحلة الثانية (الربط والتكامل) — وهو مسار الاعتماد والإبلاغ نفسه الذي يستخدمه تكاملك.
المصادقة
أرسل المفتاح كرمز Bearer مع كل طلب: Authorization: Bearer clix_…. لا يوجد تدفق OAuth ولا ترويسة للمنشأة — المفتاح مرتبط بالمنشأة التي أصدرته.
أول طلب لك
اعرض فاتورة واحدة للتأكد من أن المفتاح يعمل:
curl -H 'Authorization: Bearer clix_…' https://<server>/api/invoices/?page_size=1
استبدل <server> بعنوان الأساس المذكور تحت Servers أعلى مرجع API. يتضمن الإصدار مسبقاً، مثل …/v1.
الأخطاء
كل خطأ يأتي بصيغة JSON مع message؛ وتضيف أخطاء التحقق details باسم الحقل.
- 400 — الفاتورة خالفت قاعدة عمل (تاريخ، أو رمز، أو صنف مفقود)، أو أُنشئت فاتورة بالبيانات نفسها خلال الدقائق الخمس الأخيرة.
- 401 — المفتاح مفقود أو خاطئ أو مُلغى.
- 403 — مستوى وصول المفتاح لا يسمح بهذه النقطة، أو الباقة لا تشمل الوصول إلى API.
- 404 — uuid غير معروف لفاتورة أو عميل أو صنف، أو مسار خارج واجهة التكامل.
- 422 — الجسم لا يطابق المخطط: نوع خاطئ أو حقل مطلوب مفقود، مع قائمة لكل حقل.
- 429 — طلبات كثيرة جداً؛ انتظر عدد الثواني في ترويسة
Retry-Afterثم أعد المحاولة.
مستويات الوصول
- ViewInvoice — قراءة الفواتير والعملاء والأصناف. لا يمكنه إنشاء أي شيء.
- CreateInvoice — إنشاء الفواتير وقراءتها؛ الخيار المعتاد لتكاملات ERP ونقاط البيع.
- Accountant — الفواتير مع إشعارات الدائن والمدين والمدفوعات وتقارير ضريبة القيمة المضافة.
الحدود
مفاتيح API متاحة في باقة الأعمال. عدد الطلبات محدود لكل دقيقة؛ وعند تجاوزه يردّ API بـ 429 مع ترويسة Retry-After.
إلغاء مفتاح
الإعدادات ← مفاتيح API ← إلغاء. تتوقف الطلبات بذلك المفتاح خلال دقيقة. ألغِ المفتاح فوراً إذا ظهر في سجل أو تذكرة أو مستودع شيفرة، وأصدر مفتاحاً جديداً.
شرح عملي
أنشئ أول فاتورة لك
- ٠١
جهّز مرة واحدة في كلكس
أضف عملاءك وأصنافك وفعّل جهاز هيئة الزكاة والضريبة والجمارك واحداً على الأقل من تطبيق كلكس. واجهة API تقرؤها فقط ولا تنشئها.
- ٠٢
اقرأ معرّفي الجهاز والبائع
GET /api/devices/ وخذ device_id و seller_id من الجهاز الذي توقّع به. كلاهما يُرسل مع كل فاتورة.
- ٠٣
ابحث عن العميل والصنف
GET /api/buyers/ و GET /api/items/ يعيدان كتالوجك مع uuid لكل صف. طابق بالاسم أو الرقم الضريبي أو رمز الصنف واحتفظ بالمعرّفات.
- ٠٤
حمّل الرموز المرجعية
GET /api/invoices/vat-categories/ و /payment-means-types/ يسردان الرموز التي تقبلها الهيئة. خزّنها مؤقتاً؛ فهي نادراً ما تتغير.
- ٠٥
معاينة
POST /api/invoices/preview/ بالحمولة أدناه. 201 يعيد الإجماليات المحسوبة؛ و400 يعيد أخطاء التحقق. لا يُحفظ شيء.
- ٠٦
إنشاء
POST /api/invoices/ بالحمولة نفسها. 202 مقبول يعيد location؛ تُوقّع الفاتورة وتُرسل إلى الهيئة في الخلفية. فاتورة بالبيانات نفسها خلال خمس دقائق تُرفض بـ 400. إذا انتهت مهلة طلبك قبل وصول 202، لا تُعِد الإرسال مباشرة: اعرض الفواتير الأخيرة عبر GET /api/invoices/ وابحث عن ملاحظتك أولاً.
- ٠٧
تابع الموقع (location)
نفّذ GET على location كل ثانيتين تقريباً حتى يصبح zatca_response_status إحدى القيم CLEARED أو REPORTED أو REJECTED — عادةً خلال ثوانٍ. يُخزَّن ملف PDF بعد الاعتماد بلحظات: انتظر حتى يُملأ invoice_pdf_url أيضاً. يصل ref_num و qr_code مع الحالة.
- ٠٨
احصل على ملف PDF
GET /api/invoices/{uuid}/pdf-a3/ يعيد ملف PDF/A-3 مع XML المضمّن، جاهزاً للإرسال إلى عميلك. يردّ بـ 404 حتى يُملأ invoice_pdf_url، والفاتورة المرفوضة لا ملف PDF لها.
حمولة الفاتورة
جسم واحد يصلح للمعاينة preview والإنشاء create. type_code 388 فاتورة ضريبية قياسية، وtransaction_code 0100000 بيع قياسي بين منشأتين، وpayment_means_type_code 10 دفع نقدي؛ وبقية الرموز من الخطوة 4. تشير البنود إلى أصناف كتالوجك عبر uuid وتُسعّرها كلكس من الكتالوج.
المصفوفات الفارغة جزء من العقد — أرسلها كما هي. تحمل الخصومات والدفعات المقدمة والإشارات إلى فواتير سابقة عند الحاجة.
{
"device": "<device_id from GET /api/devices/>",
"seller": "<seller_id from the same device>",
"buyer": "<buyer uuid from GET /api/buyers/>",
"issue_date": "2026-09-10",
"issue_time": "12:00:00",
"type_code": 388,
"transaction_code": "0100000",
"currency": "SAR",
"supply_date": "2026-09-10",
"supply_end_date": "2026-09-10",
"payment_means_type_code": "10",
"notes": [{ "language_id": "en", "note": "Order 1042" }],
"lines": [{ "item_id": "<item uuid from GET /api/items/>", "quantity": 2 }],
"form_lines": [],
"prepaid_invoices": [],
"document_level_allowances": [],
"original_invoice_reference": [],
"exchange_rate": 1,
"add_prepaid_amount": false
}القيم بين الأقواس الزاوية تأتي من الخطوتين 2 و3؛ والتواريخ أمثلة.
أمثلة برمجية
التسلسل كاملاً في الشيفرة
الخطوات من 2 إلى 8 من البداية إلى النهاية: البحث عن المعرّفات، والمعاينة، والإنشاء، وانتظار رد الهيئة، ثم تنزيل ملف PDF. يحتاج مثال Python إلى حزمة requests؛ ويعمل مثال Node.js على Node 18 أو أحدث دون اعتماديات. كلاهما يقرأ عنوان الأساس والمفتاح من متغيرات البيئة.
# pip install requests
import os
import time
import requests
BASE = os.environ["CLIX_BASE_URL"] # the "Servers" URL at the top of the API reference, ends in /v1
api = requests.Session()
api.headers["Authorization"] = f"Bearer {os.environ['CLIX_API_KEY']}"
# 1. The device you sign with, and its seller id
device = api.get(f"{BASE}/api/devices/", params={"page_size": 1}).json()["devices"][0]
# 2. The client and the item, prepared once in the Clix app
buyers = api.get(f"{BASE}/api/buyers/", params={"page_size": 100}).json()["buyers"]
items = api.get(f"{BASE}/api/items/", params={"page_size": 100}).json()["items"]
buyer = next(b for b in buyers if b["buyer_name"] == "Acme Trading")
item = next(i for i in items if i["item_name"] == "Consulting hour")
today = time.strftime("%Y-%m-%d")
invoice = {
"device": device["device_id"],
"seller": device["seller_id"],
"buyer": buyer["uuid"],
"issue_date": today,
"issue_time": time.strftime("%H:%M:%S"),
"type_code": 388, # standard tax invoice
"transaction_code": "0100000", # standard B2B
"currency": "SAR",
"supply_date": today,
"supply_end_date": today,
"notes": [{"language_id": "en", "note": "Order 1042"}],
"lines": [{"item_id": item["uuid"], "quantity": 2}],
"form_lines": [],
"prepaid_invoices": [],
"document_level_allowances": [],
"exchange_rate": 1,
"original_invoice_reference": [],
"payment_means_type_code": "10", # cash
"add_prepaid_amount": False,
}
# 3. Preview: totals and validation errors, nothing stored
preview = api.post(f"{BASE}/api/invoices/preview/", json=invoice)
preview.raise_for_status()
print("payable:", preview.json()["invoice"]["invoice_payable_amount"])
# 4. Create: 202 Accepted - signed and sent to ZATCA in the background.
# A 400 here means an invoice with the same data was created in the last
# five minutes; do not retry blindly.
created = api.post(f"{BASE}/api/invoices/", json=invoice)
created.raise_for_status()
location = created.json()["location"] # "/api/invoices/<uuid>/"
# 5. Poll until ZATCA has answered AND the PDF is stored (usually a few
# seconds). The status turns CLEARED first; invoice_pdf_url follows shortly
# after, and /pdf-a3/ answers 404 until it does.
FINAL = ("CLEARED", "REPORTED", "REJECTED")
for _ in range(30):
result = api.get(f"{BASE}{location}").json()
status = result.get("zatca_response_status")
if status == "REJECTED" or (status in FINAL and result.get("invoice_pdf_url")):
break
time.sleep(2)
else:
# Still pending after a minute: the invoice exists, keep polling the location later.
raise SystemExit(f"ZATCA has not answered yet for {location}")
print(status, result["ref_num"])
if status == "REJECTED":
# Review why in the Clix app (Invoices -> Rejected), fix the data, and create a new invoice.
raise SystemExit(f"rejected: {result.get('zatca_response_code')}")
# 6. The PDF/A-3 with the embedded XML, for your customer
pdf = api.get(f"{BASE}{location}pdf-a3/")
pdf.raise_for_status()
with open(f"{result['ref_num']}.pdf", "wb") as f:
f.write(pdf.content)استبدل اسمي العميل والصنف بأسمائك. الأمثلة غير مترجمة: واجهة API وأسماء حقولها والتعليقات بالإنجليزية.
الهندسة
كيف نبني كلكس
ما يقف خلف واجهة كلكس البرمجية ومحرك الفوترة.
تصميم بطبقات
تسير الطلبات في اتجاه واحد: الواجهة، ثم الخدمات، ثم النطاق، ثم التخزين. قواعد الهيئة موجودة في طبقة النطاق.
واجهة برمجية متوقعة
موارد بطرق HTTP ورموز حالة قياسية، ومرجع OpenAPI، واستجابة 202 Accepted مع الاستعلام الدوري عند الإرسال إلى الهيئة، وأخطاء موثقة منها 429 مع Retry-After.
مراجعة من شخصين
كل تغيير يحتاج موافقة مهندس ثانٍ ويخضع لمراجعة آلية للشيفرة.
اختبارات مع كل تغيير
تعمل الاختبارات الآلية مع كل طلب دمج.
المرجع والمساعدة
مرجع API
واجهة التكامل: الفواتير، ورموز هيئة الزكاة والضريبة والجمارك المرجعية، والعملاء، والأصناف، وحصتك المتبقية — مع مخططات الطلب والاستجابة. الصق مفتاحك في Authorize لتجربة الطلبات مباشرة.
افتح المرجعجاهز للبناء؟
احصل على الوصول إلى API في باقة الأعمال
فواتير غير محدودة، وطلبات API غير محدودة، ومهندسون يساعدونك في ربط نظام ERP لديك.