مرجع للمطورين

توثيق زرار Zoho المخصص

مرجع تقني لبناء سكريبت Deluge مخصص يرسل بيانات الفاتورة أو الإيصال إلى TaxBridge بالصيغة التي تحددها أنت.

الإصدار: v1·آخر تحديث: 2026-07-28

رابط أساسي

https://taxbridge-backend.biinnovate.com/api

كل المسارات في هذه الصفحة نسبية لهذا الرابط.

معظم العملاء لا يحتاجون قراءة هذه الصفحة — سكريبتات Payload Mode الجاهزة متوفرة في TaxBridge → الإعدادات → الإرسال، مع التوكن الخاص بك جاهزًا للنسخ. هذه الصفحة لمن يبني تكاملًا مخصصًا بنفسه.

1المصادقة

كل طلب يتطلب عنصرين معًا:

الحقلالنوعمطلوبالوصف
X-TaxBridge-Tokenهيدرنعمكود سري 64 حرفًا، خاص بشركتك — يُنسخ من الإعدادات
organization_idحقل في الجسمنعمرقم مؤسسة Zoho — يجب أن يطابق الحساب المربوط بشركتك

توكن مفقود أو غير صحيح يُرجع 401 — وعدم تطابق organization_id يُرجع 401 كمان، بنفس الرسالة بالظبط. الاختلاف بينهم مقصود إنه مايبانش: لو رجّعنا كود مختلف، الكود نفسه كان هيبقى دليل إن التوكن صحيح. لا يوجد طبقة مصادقة أخرى (لا JWT ولا صفحة API keys).

لا تُضمّن التوكن كنص صريح داخل سكريبت Deluge. استخدم Zoho Connection باسم "taxbridge" (يُدرج الهيدر تلقائيًا) — نفس الأسلوب المستخدم في كل السكريبتات الجاهزة من TaxBridge.

حدود معدل الطلبات (rate limit) تُطبَّق لكل توكن، وليس لكل IP — نظرًا لأن خوادم Zoho تشارك نفس عناوين الـ IP بين شركات متعددة.

2وضع Payload (موصى به)

النموذج الأساسي: سكريبت الـ Deluge الخاص بك يبني ويرسل العقد كاملًا — أنت من يحدد المستلم وتاريخ الإصدار والبنود، بدلًا من إرسال رقم الفاتورة وترك TaxBridge يستعلم من Zoho مرة أخرى. هذا يوفر نداءات API على حسابك وحساب Zoho، ويتيح لك تشكيل بياناتك كما تريد. يتحقق TaxBridge من العقد ويحوّله مباشرة إلى نفس الصيغة التي يستهلكها محرّك بناء المستند الضريبي — دون إعادة تفسير.

الـ Endpointموديول Zoho
POST /zoho/invoice-payload[-bulk]الفواتير
POST /zoho/creditnote-payload[-bulk]إشعارات الدائن
POST /zoho/debitnote-payload[-bulk]الفواتير (type = debit_note)

الحقول المشتركة

الحقلالنوعمطلوبالوصف
contract_versionintegerنعمثابت = 1
organization_idstringنعمرقم مؤسسة Zoho
zoho_invoice_idstringنعممعرّف Zoho — للإشعارات: zoho_creditnote_id
invoice_numberstringنعمرقم المستند — للإشعارات: creditnote_number
issue_datestringنعمYYYY-MM-DD — لا يكون مستقبليًا ولا أقدم من 7 أيام
currency_codestringنعمEGP, USD, ...
exchange_ratenumberإذا لم تكن العملة EGPسعر الصرف مقابل الجنيه
receiver.idstringلا9 أرقام = رقم ضريبي، 14 = رقم قومي، فارغ = مجهول
receiver.namestringنعماسم المستلِم — إجباري للفواتير والإشعارات (اختياري للإيصالات فقط). خُذه من كارت العميل، لا من النسخة المخزّنة على المستند
receiver.addressobjectلاgovernate, regionCity, street, postalCode (الرقم البريدي)؛ buildingNumber اختياري — لو مبعتّهوش تاكس بريدج بيحط placeholder
customer_idstringلامعرّف العميل في Zoho — للتدقيق فقط. TaxBridge لا يستعلم من Zoho إطلاقًا: الرقم الضريبي/القومي والعنوان يجب أن يصلا في receiver
lines[]arrayنعمdescription, quantity, unit_price (الثلاثة إجبارية، والكمية والسعر أكبر من صفر) + discount, discount_rate, unit_type, eta_item_code (اختيارية). 200 بند كحد أقصى
lines[].discountnumberلاقيمة الخصم على البند بالعملة (مش نسبة). لو أغفلته يُرفع البند بسعره قبل الخصم. ولا ترسل خصمًا يساوي قيمة البند بالضبط — بند صافيه صفر يُرفع حاليًا بسعره الكامل
lines[].discount_ratenumberلو فيه discount⚠️ نسبة الخصم المئوية. لو بعتّ discount من غيره، القيمة نفسها تُرفع كنسبة — خصم 50 جنيه يُرفع كـ "خصم 50%". ابعت الاتنين دائمًا
lines[].unit_typestringلاكود وحدة القياس لدى الضرائب. الافتراضي EA (قطعة) — لو بتبيع بالوزن أو الحجم ابعت الكود الصحيح
lines[].eta_item_codestringلاكود GS1/EGS للصنف. لو أغفلته يُستخدم الكود المسجَّل للصنف في TaxBridge (مطابقة بالاسم)، ثم كود الشركة الافتراضي
extra_discountnumberلاخصم على مستوى المستند كله. افتراضي 0 — القوالب الجاهزة لا ترسله
po_referencestringلارقم أمر الشراء (Order Number) — يترفع كـ purchaseOrderReference
resubmitbooleanلاtrue = إعادة رفع متعمَّدة لمستند سبق إلغاؤه لدى الضرائب. بدونه يُرد resubmit_required بدل الرفع. في الإرسال الجماعي يوضع مرة واحدة في جذر الطلب، لا داخل كل مستند
triggered_bystringلاللتدقيق فقط — انظر أدناه
{
  "contract_version": 1,
  "organization_id": "20012345678",
  "zoho_invoice_id": "123456",
  "invoice_number": "INV-001",
  "issue_date": "2026-07-19",
  "currency_code": "EGP",
  "exchange_rate": 1,
  "receiver": {
    "name": "شركة العميل",
    "id": "123456789",
    "address": { "governate": "Cairo", "regionCity": "Nasr City",
                 "street": "١٢ شارع الطيران", "postalCode": "11765" }
  },
  "customer_id": "3616396000000392101",
  "lines": [
    { "description": "خدمة", "quantity": 2, "unit_price": 250,
      "discount": 50, "discount_rate": 10,
      "eta_item_code": "EG-XXXXXXXXX-001", "unit_type": "EA" }
  ],
  "extra_discount": 0,
  "po_reference": "PO-2026-01",
  "triggered_by": "user@company.com"
}

إشعارات المدين تتطلب إضافيًا referenced_invoice_number (الفاتورة الأصلية — يجب أن تكون مقبولة على الضرائب مسبقًا). إشعارات الدائن تقبله اختياريًا — يمكن إرسال إشعار دائن مستقل بدون فاتورة مرجعية (ETA تعتبره optional لنوع "C"). إشعارات المدين وحدها تقبل أيضًا reason اختياريًا.

لا ترسل بيانات المُصدِر (اسم شركتك، رقمها الضريبي...) في الـ payload — تُرفض فورًا بخطأ 422. بيانات المُصدِر تُؤخذ فقط من إعدادات شركتك في TaxBridge، لمنع انتحال شخصية شركة أخرى.

ما الذي يوقف المستند قبل رفعه

المستند المرفوع للضرائب لا يمكن تصحيحه — يحتاج إلغاءً أو إشعار خصم. لذلك تُرفض هذه الحالات قبل الرفع، لا بعده:

الحقلالنوعمطلوبالوصف
نص متكسّركل الحساباتيرفضوجود "؟؟" أو حرف الاستبدال في اسم أو عنوان المستلِم — النص يُرفع للضرائب حرفيًا
رقم مستلِم غير صالحكل الحساباتيرفضreceiver.id ليس 9 أرقام ولا 14
رقم مستلِم فارغاختياري لكل حسابيرفض إذا فُعِّلالافتراضي مسموح (بيع تجزئة حقيقي). فعّله لو كل عملائك شركات مسجّلة — يمنع رفع شركة كمستهلك مجهول
عملة غير الجنيه بلا سعر صرفكل الحساباتيرفضcurrency_code ≠ EGP بدون exchange_rate موجب
تاريخ خارج النطاقكل الحساباتيرفضissue_date مستقبلي أو أقدم من 7 أيام
بند بكمية أو سعر صفركل الحساباتيرفضأي بند بـ quantity ≤ 0 أو unit_price ≤ 0
حقل غير معروفكل الحساباتيرفضأي مفتاح خارج الجدول أعلاه — خطأ إملائي في السكريبت يُرفض بدل أن يُتجاهل بصمت
أكثر من 200 بندكل الحساباتيرفضالحد الأقصى 200 بند في المستند الواحد
القوالب الجاهزة تتحقق من هذه الحالات في السكريبت نفسه أيضًا — وتوقف المستند قبل إرساله وتخبرك برقمه وبالقيمة المرفوضة ومصدرها (بياناتك أم فشل نداء Zoho). في الإرسال الجماعي يظهر ذلك مجمّعًا في رسالة الزرار، والتفاصيل الكاملة في سجل تنفيذ الدالة داخل Zoho.

3الإيصالات الإلكترونية

نظام منفصل تمامًا عن الفواتير — بلا توقيع رقمي (الضرائب أجّلت التحقق من التوقيع للإيصالات). العقد مشابه لكن أبسط:

الـ Endpointالسلوك
POST /zoho/receipt-payloadإرسال فوري، يُرجع نتيجة الضرائب الفعلية
POST /zoho/receipt-payload-bulkتسجيل الإيصالات وإرسالها تدريجيًا في الخلفية
الحقلالنوعمطلوبالوصف
zoho_receipt_idstringنعممعرّف Zoho
receipt_numberstringنعمرقم الإيصال
buyer.id / buyer.namestringلاقد تكون فارغة — بيع نقدي مجهول الهوية صالح
payment_methodstringنعمقيمة Zoho الخام لطريقة الدفع
lines[]arrayنعمdescription, quantity, unit_price
{
  "contract_version": 1,
  "organization_id": "20012345678",
  "zoho_receipt_id": "789012",
  "receipt_number": "RC-001",
  "issue_date": "2026-07-19",
  "currency_code": "EGP",
  "buyer": { "id": "", "name": "" },
  "payment_method": "cash",
  "lines": [
    { "description": "قهوة", "quantity": 2, "unit_price": 25 }
  ]
}

4الردود والأخطاء

مستند مرفوض يُرجع ردًا عاديًا (وليس خطأ HTTP) لكي تستمر الدفعة — كل رسالة رفض تأتي ثنائية اللغة:

{
  "zoho_id": "12345",
  "status": "validation_error",
  "reasons": [
    "الحقل 'receiver' مطلوب / Field 'receiver' is required"
  ]
}

كل قيم status

عالِج القيم دي كلها — القيمة اللي مش في القائمة دي لا يُرجعها الـ API. الأربعة الأولى فقط تعني «وصل للضرائب».

القيمةالمعنى
queued✅ نجاح — في طريقه إلى الضرائب
queued_receipt✅ إيصال سُجّل وسيُرسل في الخلفية (الإرسال الجماعي للإيصالات)
requeued_after_cancel✅ نجاح — إعادة رفع بعد إلغاء مؤكَّد لدى الضرائب
requeued_while_cancel_pending✅ نجاح — إعادة رفع وطلب الإلغاء لا يزال معلَّقًا (متاح للحسابات المفعَّل لها ذلك فقط)
validation_error⛔ بيانات ناقصة أو غير صحيحة — التفاصيل في reasons
subscription_or_quota_blocked⛔ الاشتراك منتهٍ أو تم بلوغ الحد الشهري
plan_upgrade_required⛔ إشعارات الدائن/المدين تتطلب باقة مدفوعة
limit_reached⛔ الحد اليومي لباقة التجربة
skipped⛔ الفاتورة المرجعية لم تُقبل على الضرائب بعد
data_refreshedℹ️ المستند مرفوع بالفعل أو قيد الرفع — حُدِّثت بياناته محليًا ولم يُرفع مرة أخرى
cancel_pendingℹ️ طلب إلغاء بانتظار رد المستلم — المستند لا يزال صالحًا لدى الضرائب
resubmit_requiredℹ️ ألغته الضرائب — استخدم زر «إعادة الإرسال» (resubmit) لرفعه من جديد
lockedℹ️ إيصال آخر لنفس الشركة قيد الإرسال — أعد المحاولة بعد لحظات (الإيصالات فقط)

5حدود الاستخدام

كل رد — سواء نجح أو رُفض — يحمل جزء usage يوضح استهلاكك الحالي:

"usage": {
  "plan": "starter",
  "daily_used": 2,            "daily_limit": 20,
  "receipt_daily_used": 0,    "receipt_daily_limit": 20,
  "monthly_used": 4,          "monthly_limit": null,
  "receipt_monthly_used": 1,  "receipt_monthly_limit": null
}

الحد اليومي هو القيد الوحيد المطبَّق. الفواتير والإيصالات لكل منهما عدّاد يومي مستقل بنفس رقم الباقة (تجربة 5 · Starter 20 · Professional 100 · Enterprise 500) — فالإيصالات لا تستهلك رصيد الفواتير. يُحسب بالمستندات الفعلية لا بضغطات الزر، فيمكنك استخدام أي عدد من ضغطات الإرسال الجماعي. إشعارات الدائن والمدين لا تُحتسب على أي عدّاد. الحدود الشهرية لم تعد مطبَّقة (monthly_limit = null) وتُرسل للعلم فقط.

6الإرسال الجماعي

كل الـ endpoints الجماعية تقبل حتى 50 مستندًا في الطلب الواحد. عند بناء تكامل مخصص بأكثر من 50 مستندًا، قسّمها إلى دفعات بنفسك — تمامًا كما تفعل سكريبتات TaxBridge الجاهزة (تقسّم أي عدد تلقائيًا إلى دفعات من 50 وتُجمّع نتيجة واحدة).

{ "total": 42, "queued": 40, "results": [ /* one entry per document */ ] }
زوهو بيطلب اسم دالة (Custom Function) مختلف لكل زرار. أدِّ كل زرار (مفرد/جماعي، وكل نوع مستند) اسمًا مميزًا — مثلاً TaxBridge_Invoice_Single و TaxBridge_Invoice_Bulk. تكرار الاسم بيطلّع رسالة زوهو "A Custom Function with the same name already exists" — وده قيد من زوهو مش خطأ من تاكس بريدج.

عندك سؤال أو محتاج مساعدة في التكامل؟

تواصل عبر واتساب