كيف تعمل
الهيئة تُصدر الشهادات لكل مكلَّف على حدة — لا وجود لشهادة مشتركة يُوقَّع بها عن الجميع. لذلك كل تاجر تنشئه عبر هذه الواجهة هو منشأة مستقلة كاملة: رقمه الضريبي، شهادته، سلسلة فواتيره (ICV/PIH)، وأرشيفه. ما توفره الواجهة هو أنك تنشئ هذه المنشآت وتديرها من نظامك بدل أن يسجّل كل تاجر بنفسه.
| الخطوة | من يقوم بها | كيف |
|---|---|---|
| 1 · إنشاء منشأة التاجر | نظامك | POST /merchants |
| 2 · الربط مع بوابة فاتورة | نظامك — والتاجر يجلب الرمز | POST /merchants/{id}/connect |
| 3 · إصدار الفواتير | نظامك | POST /api/v1/invoices + X-Merchant-Id |
الاشتراكات: اتفاقك معنا يحدد عدد اشتراكات التجار المدفوعة. كل تاجر نشط يستهلك اشتراكًا،
وإيقاف اشتراك تاجرٍ غادَرَ يُعيده لرصيدك. حين يُستهلك الرصيد ترجع الواجهة
402 seat_limit_reached
— تواصل معنا لزيادتها.
حقيقة رمز فاتورة — اقرأها قبل أن تكتب سطرًا
القيد على مصدر الرمز فقط — أما إدخاله فيحدث داخل شاشتك أنت:
اعرض لتاجرك «أدخل رمز التحقق من بوابة فاتورة»، ومرّر ما يكتبه إلى
POST /merchants/{id}/connect
وتابع التقدم من
GET /merchants/{id}/status
— الشهادة وفحوص التوافق الستة خلال دقيقتين تقريبًا، وتاجرك لم يغادر نظامك.
والقاعدة نفسها تنطبق على كل جهاز فرع لاحقًا: رمز جديد لكل جهاز
(إلحاق حل فوترة جديد ← عدد الأجهزة) — تفاصيلها في
فروع التاجر وأجهزته.
لا تريد بناء الشاشة؟
onboarding_url
يبقى بديلًا جاهزًا: رابط موقَّع يفتح صفحتنا على الخطوة نفسها.
الاستيثاق
مفتاح الشريك يبدأ بـztkp_live_
وتستلمه منا عند توقيع الاتفاق — يظهر مرة واحدة، فخزّنه في متغير بيئة.
وهو للأنظمة فقط: بوابة الشركاء تفتح ببريدك المسجّل ورمز تحقق، فلا يحتاج مفتاحك أن يمر بحافظة أحد.
وهو مفتاحك الوحيد: يدير حساباتك هنا، ويُصدر فواتير كل تجّارك على واجهة الفواتير —
التاجر المقصود تسمّيه في كل نداء بترويسة
X-Merchant-Id.
سرّ واحد في خزنتك، وتدوير واحد تديره.
curl https://zatcatools.com/api/partner/account \
-H "Authorization: Bearer ztkp_live_..."
الأخطاء
| HTTP | code | المعنى |
|---|---|---|
| 401 | unauthenticated | مفتاح الشريك مفقود أو غير صحيح — أو أرسلت مفتاح تاجر بالخطأ |
| 402 | seat_limit_reached | كل اشتراكاتك المدفوعة مشغولة — حرّر اشتراكًا أو تواصل لزيادتها |
| 403 | partner_suspended | حساب الشراكة موقوف — تواصل معنا |
| 404 | not_found | لا تاجر بهذا المعرّف ضمن شراكتك |
| 409 | email_taken / vat_taken | البريد له حساب قائم، أو الرقم الضريبي مسجّل لمنشأة أخرى |
| 422 | validation_failed | بيانات ناقصة أو غير صالحة — الرسالة توضح السبب |
| 429 | too_many_requests | تجاوزت حد الطلبات (120/دقيقة) |
حسابك واشتراكاتك
GET /api/partner/account
{
"partner": {
"name": "Smart POS Co.",
"status": "active",
"seats": { "limit": 50, "used": 34, "remaining": 16 }
}
}
إنشاء تاجر
POST /api/partner/merchants
يستهلك اشتراكًا وينشئ منشأة كاملة بفوترة بلا حدّ.
name
وemail
إلزاميان؛ vat_number
إلزامي أيضًا — هو هوية المنشأة لدى الهيئة، ونظامك يعرفه عن عميله دائمًا. السجل التجاري اختياري.
وللعنوان أرسل short_address
— العنوان الوطني المختصر (4 أحرف و4 أرقام، مثل RRRD2929):
نحلّ منه العنوان التفصيلي كاملًا تلقائيًا كما في التسجيل العادي، وإن تعذّر الحلّ يكمل التاجر بياناته
في خطوة الـOnboarding — لا شيء يتعطل.
البريد يجب أن يكون جديدًا عندنا: بريد له حساب قائم يُرفض بـ409 ولا يُتبنّى —
معرفتك ببريد تاجر ليست بابًا إلى حساب يملكه.
curl -X POST https://zatcatools.com/api/partner/merchants \
-H "Authorization: Bearer ztkp_live_..." \
-H "Content-Type: application/json" \
-d '{
"name": "مطعم الذواقة — فرع المروج",
"email": "[email protected]",
"vat_number": "310000000000003",
"cr_number": "1010203040",
"short_address": "RRRD2929"
}'
HTTP/1.1 201 Created
{
"merchant": { "id": 34, "name": "…", "status": "awaiting_onboarding", "seat": "active" },
"onboarding_url": "https://…", // موقَّع، صالح 72 ساعة
"seats": { "limit": 50, "used": 35, "remaining": 15 }
}
لا مفتاح لكل تاجر — خزّن merchant.id
مقابل عميلك في نظامك: هو ما يذهب في ترويسة
X-Merchant-Id
مع مفتاح شراكتك في كل نداء فوترة.
ربط التاجر — من داخل شاشتك
POST /api/partner/merchants/{id}/connect · GET /api/partner/merchants/{id}/status
قبل النداء تأكد أن بيانات المنشأة مكتملة —
name و
vat_number و
cr_number و
short_address
— أكملها بـPATCH /merchants/{id} إن نقصت.
النقص يُرفض قبل صرف الرمز: رمز فاتورة يُستخدم مرة واحدة، وحرقه على نقص حقل هو أسوأ نسخ هذا الخطأ.
# The merchant typed the six digits into YOUR screen:
curl -X POST https://zatcatools.com/api/partner/merchants/34/connect \
-H "Authorization: Bearer ztkp_live_…" \
-H "Content-Type: application/json" \
-d '{ "otp": "123456" }'
HTTP/1.1 202 Accepted
{ "status": "connecting", "poll": "…/merchants/34/status" }
# Poll every couple of seconds while your checklist spins:
GET /api/partner/merchants/34/status
{
"connected": false, "connecting": true, "stalled": false,
"compliance_passed": 4, // of the 6 checks
"error": null
}
# …until:
{ "connected": true, "compliance_passed": 6, "certificate_expires_at": "2029-08-31" }
error
يهمك منه اثنان: otp_invalid
— الرمز خاطئ أو منتهٍ، اطلب من تاجرك رمزًا جديدًا؛ و
stalled: true
— توقف العدّ، أعد المحاولة برمز جديد. وبعد الربط تُقفل حقول الهوية (الاسم والرقم الضريبي والسجل):
الشهادة الصادرة تحملها، وتغييرها يجعل الوثائق تخالف شهادتها.
قائمة التجار وتفاصيلهم
GET /api/partner/merchants · GET /api/partner/merchants/{id}
الحقل الذي تبني عليه شاشتك هو status:
| awaiting_onboarding | أُنشئ ولم يُكمل الربط — اعرض له رابط الإكمال |
| connected | مرتبط بالهيئة — فواتيره تصدر الآن |
| failed | آخر محاولة ربط فشلت — اطلب رابطًا جديدًا وأعد توجيهه |
| trial | يجرّب على بيئة الهيئة التجريبية |
| released | حرّرتَ اشتراكه — بياناته محفوظة ولا فوترة جديدة |
Onboarding Link
POST /api/partner/merchants/{id}/onboarding-link
يسكّ رابطًا موقَّعًا جديدًا صالحًا 72 ساعة — الرابط يوقّع التاجر داخل حسابه فعامله كسرّ: اعرضه داخل شاشة التاجر نفسه فقط، ولا تضعه في بريد جماعي أو رسالة قابلة لإعادة التوجيه. انتهت صلاحيته؟ اطلب غيره — بلا حدّ.
إصدار الفواتير
من هنا وصاعدًا تستخدم واجهة الفواتير v1 بمفتاح شراكتك نفسه + ترويسة تسمّي التاجر — إصدار، إشعارات دائن ومدين، XML وPDF وQR. مثال بيع من نقطة بيعك:
curl -X POST https://zatcatools.com/api/v1/invoices \
-H "Authorization: Bearer ztkp_live_…" \
-H "X-Merchant-Id: 34" # التاجر صاحب هذا البيع \
-H "Content-Type: application/json" \
-d '{
"type": "simplified",
"branch_id": 3, // البيع من فرع؟ سمِّ الفرع وجهازه معًا —
"device_id": 7, // القاعدة نفسها للضريبية والمبسطة سواء
"lines": [
{ "name": "وجبة غداء", "quantity": 2, "unit_price": 45.00 },
{ "name": "دواء", "quantity": 1, "unit_price": 120.00,
"tax_category": "Z", "tax_reason_code": "VATEX-SA-35" }
]
}'
البنود تقبل tax_category
(S افتراضيًا ·
Z صفرية ·
E معفاة ·
O خارج النطاق) —
والفئات غير الخاضعة تتطلب tax_reason_code
من قائمة الهيئة، والفاتورة الواحدة تجمع فئات مختلفة بلا مشكلة.
والبيع من فرع يسمّي branch_id
وdevice_id معًا — للضريبية والمبسطة سواء؛
التفاصيل في فروع التاجر وأجهزته أدناه.
فروع التاجر وأجهزته
تاجرك له أكثر من نقطة بيع؟ كل الفروع تحت رقمه الضريبي، لكن كل فرع يُصدر عبر جهازه الخاص (EGS unit) — نموذج الهيئة نفسه: التاجر يولّد من بوابة فاتورة رمز OTP لكل جهاز (إلحاق حل فوترة جديد ← عدد الأجهزة)، أنت تجمعه في شاشتك وتمرره لنا، وكل جهاز يخرج بشهادته وسلسلة فواتيره المستقلة. ربط المنشأة الأساسي (أعلاه) هو جهاز المقر الرئيسي؛ ما يلي للفروع. نفس مفتاحك + ترويسة التاجر:
# 1. الفرع
curl -X POST https://zatcatools.com/api/v1/branches \
-H "Authorization: Bearer ztkp_live_…" -H "X-Merchant-Id: 34" \
-d '{ "name": "فرع النخيل مول", "cr_number": "1010999888", "short_address": "RESB3139" }'
# → 201 { "branch": { "id": 3, … } }
# 2. جهاز الفرع — otp جمعته من شاشة تاجرك
curl -X POST https://zatcatools.com/api/v1/branches/3/devices \
-H "Authorization: Bearer ztkp_live_…" -H "X-Merchant-Id: 34" \
-d '{ "otp": "482913", "name": "كاشير 1" }'
# → 202 { "device": { "id": 7, "status": "pending", … } }
# 3. تتبّع حتى connected (عادة أقل من دقيقة)
curl https://zatcatools.com/api/v1/devices/7 \
-H "Authorization: Bearer ztkp_live_…" -H "X-Merchant-Id: 34"
# → { "device": { "status": "connected", "usable": true, … } }
# 4. بيع من الفرع — الفاتورة تسمّي فرعها وجهازها معًا
curl -X POST https://zatcatools.com/api/v1/invoices \
-H "Authorization: Bearer ztkp_live_…" -H "X-Merchant-Id: 34" \
-d '{ "type": "simplified", "branch_id": 3, "device_id": 7,
"lines": [{ "name": "وجبة", "quantity": 1, "unit_price": 45 }] }'
الفرع الواحد يتحمّل عدة أجهزة — كرر الخطوة 2 برمز OTP جديد لكل جهاز، وكلٌّ بسلسلته
المستقلة فتُصدر نقاط البيع بالتوازي.
فاتورة الفرع تسمّي جهازها: خزّن device_id
عند كل نقطة بيع ومرّره مع branch_id على كل فاتورة —
أحدهما بلا الآخر يُرفض
(device_required /
branch_required)،
وجهاز غير متصل يُرفض بـ device_not_usable.
الإشعارات تتبع فرع فاتورتها الأصل تلقائيًا وجهازها عليها اختياري.
فشل التفعيل بـ otp_invalid؟
الرمز خُطئ أو انتهت ساعته أو استُهلك — اطلب من تاجرك رمزًا جديدًا وأعد التفعيل على نفس الجهاز:
POST /v1/devices/{id}/connect.
القائمة الكاملة للفروع وأجهزتها دائمًا على
GET /v1/account.
إيقاف اشتراك وإعادته
POST /api/partner/merchants/{id}/release · POST /api/partner/merchants/{id}/reinstate
تاجر غادر نظامك؟ أوقف اشتراكه ليخدم غيره. الإيقاف لا يحذف شيئًا أبدًا — الهيئة تُلزم بأرشيف ست سنوات، وسلسلة الفواتير لا تنقطع: المنشأة ووثائقها ودخول صاحبها كلها تبقى، وقراءة أرشيفه عبر الـ API تبقى أيضًا (كل نداءات GET تعمل للموقوف — تصدير وتدقيق بلا انقطاع)؛ الذي يتوقف هو الفوترة الجديدة وكل فعل يُنشئ شيئًا. عاد التاجر؟ reinstate يعيد تفعيله على اشتراك شاغر ويستأنف سلسلته من حيث توقفت.
حدود الاستخدام
واجهة الشركاء: 120 طلبًا في الدقيقة. واجهة الفواتير: 60 طلبًا في الدقيقة على مفتاحك — يكفي مئات نقاط البيع في الاستخدام الواقعي؛ ولو بلغت حجمًا يتجاوزه فراسلنا ونرفعه لك.