وثائق المطورين والربط البرمجي

اربط برامجك الخاصة بصندوق وارد SyBox

أرسل رسائل واتساب من رقمك الخاص، واعرض بيانات عملائك بجوار كل محادثة، وافتح الحالات، واستقبل كل حدث على خادمك الخاص، وضع دردشة مباشرة على موقعك الإلكتروني. يعتمد مسار الإرسال صيغة WhatsApp Cloud API، لذلك لا يحتاج الكود المكتوب لـ Meta إلا إلى عنوان أساسي جديد ومفتاح من SyBox.

العنوان الأساسيhttps://api.sybox.io

البدء

البدء السريع

ثلاثة عناصر أساسية لإرسال أول رسالة: العنوان الرئيسي Base URL، مفتاح الجهاز Device Key، ومسار الرسائل.

POST/v26.0/{phone-number-id}/messagesAuthorization: Bearer <DEVICE_KEY>

يتم قبول جزء الإصدار بأي صيغة v<n> مثل (v26.0 أو v1.0) — احتفظ بنفس الصيغة المستخدمة في كودك الحالي. بينما {phone-number-id} هو معرّف رقم واتساب الخاص بك مطابقاً لـ Meta.

يظهر {phone-number-id} بعد id في بطاقة الرقم في الإعدادات › المراسلة › القنوات. يرتبط مفتاح الإرسال برقم واحد، ويرسل منه فقط.

cURL
curl -X POST https://api.sybox.io/v26.0/PHONE_NUMBER_ID/messages \
  -H "Authorization: Bearer YOUR_DEVICE_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "messaging_product": "whatsapp",
    "to": "15551234567",
    "type": "text",
    "text": { "body": "Hello from SyBox" }
  }'

تعرض بطاقة كل مفتاح في الإعدادات › التكاملات › مفاتيح API آخر وقت تم استخدامه فيه — وهي أسرع طريقة لمعرفة ما إذا كانت استدعاءاتك تصل.

البدء

المصادقة والمفاتيح

يحمل كل استدعاء مفتاحاً في الترويسة Authorization على شكل Bearer token. لكل مفتاح وظيفة واحدة: المفتاح المخصص للإرسال لا يمكنه فتح حالة، والمفتاح المخصص لفتح الحالات لا يمكنه الإرسال. احتفظ بكل مفتاح على خادمك — والاستثناء الوحيد هو المفتاح العام للدردشة المباشرة، فهو مصمم لتضعه في صفحاتك.

HTTP
Authorization: Bearer YOUR_KEY
Content-Type: application/json
المفتاحالغرض منه
الإرسال عبر واتسابPOST /v{n}/{phone-number-id}/messages
تسجيل شكوىPOST /v1/case
تشغيل أتمتةPOST /v1/automation
قراءة جهات الاتصال وتحديثهاPOST /v1/contacts/…
استقبال من برنامجPOST /v1/inbound
المفتاح العام · lcpk_<script … data-key="lcpk_…">
مفتاح توقيع المستخدمين المسجلين · lcid_المستخدمون المسجلون: مفتاح التوقيع
مفتاح الخادم (لشاشة الدردشة الخاصة بك) · lcsk_/v1/livechat/*
مفتاح توقيع الردود · lcwh_x-sybox-signature
مفتاح التوقيعX-Hub-Signature-256

البدء

إنشاء واستخراج مفاتيح الأجهزة Device Keys

يتم إنشاء المفاتيح بداخل مساحة عملك وتتحمل التوجيه ذاتياً.

  1. افتح مساحة العمل ← الإعدادات ← مفاتيح API وأنشئ مفتاح جهاز جديد.
  2. كل مفتاح مربوط برقم واحد محدد ويمكن إلغاؤه في أي وقت.
  3. رمز WhatsApp Token الحقيقي لا يغادر سيرفراتنا إطلاقاً — المفتاح يقوم بالنيابة عنه.
  4. البوابة مغلقة افتراضياً؛ وتفعيل وصول API يضمن تشغيلها بأمان.

واجهة WhatsApp API

إرسال أول رسالة

رسالة نصية عادية. جسم الطلب هو نفس هيكل كود Cloud API القياسي — نمرره مباشرة لـ Meta بدون تعديل.

POST/v26.0/{phone-number-id}/messagesAuthorization: Bearer <DEVICE_KEY>
curl -X POST https://api.sybox.io/v26.0/PHONE_NUMBER_ID/messages \
  -H "Authorization: Bearer YOUR_DEVICE_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "messaging_product": "whatsapp",
    "to": "15551234567",
    "type": "text",
    "text": { "body": "Hello from SyBox" }
  }'

الاستجابة

تستقبل نفس الاستجابة الناتجة من Meta مع نفس كود حالة HTTP — لتستمر مكتبات الكود الحالية في قراءته بسلاسة.

200 OK · application/json
{
  "messaging_product": "whatsapp",
  "contacts": [{ "input": "15551234567", "wa_id": "15551234567" }],
  "messages": [{ "id": "wamid.HBgLMTU1NTEyMzQ1NjcVAgARGBI…" }]
}

واجهة WhatsApp API

دعم كامل لجميع أنواع الرسائل

نظراً لتمرير جسم الطلب كما هو، فإن كافة أنواع الرسائل مدعومة — القوالب، الصور، المستندات، والرسائل التفاعلية. إليك مثال لإرسال قالب Template.

{
  "messaging_product": "whatsapp",
  "to": "15551234567",
  "type": "template",
  "template": {
    "name": "order_shipped",
    "language": { "code": "en_US" },
    "components": [{
      "type": "body",
      "parameters": [{ "type": "text", "text": "#10432" }]
    }]
  }
}

لا يصل النص الحر إلى العميل إلا خلال 24 ساعة من آخر رسالة منه. خارج هذه الفترة، أرسل قالباً معتمداً: يقوم SyBox برفض النص الحر حينها بالكود 131047 قبل أن يصل إلى Meta.

واجهة WhatsApp API

قواعد المفاتيح وحدودها

يحمل كل مفتاح إرسال قواعده الخاصة، والتي تحددها عند إنشائه: نص حر أو قوالب أو كلاهما؛ السماح بالوسائط أو منعها؛ القوالب المسموح بها؛ دول المستلمين المسموح بها؛ الساعات التي يمكنه الإرسال فيها؛ وحد يومي. وإذا خالفت عملية إرسال إحدى هذه القواعد، يقوم SyBox برفضها قبل أن تصل إلى Meta.

الحالةمتى
404رد فارغ: بوابة API مغلقة، أو المفتاح لا ينتمي إلى أي مساحة عمل. تحقّق من مفتاح التشغيل أعلى شاشة الإعدادات › التكاملات › مفاتيح API.
401المفتاح غير موجود في الطلب أو غير معروف.
403المفتاح ليس مفتاح إرسال، أو يرسل من رقم غير مربوط به.
403الرسالة تخالف إحدى قواعد المفتاح: النص الحر، أو القوالب، أو الوسائط، أو اسم القالب، أو الدولة، أو الساعات.
403قامت Meta بإيقاف القالب مؤقتاً، أو تقييده بسبب تقييم جودته.
400فترة الـ 24 ساعة مغلقة (الكود 131047): أرسل قالباً بدلاً من ذلك.
400نص الطلب ليس JSON صالحاً، أو رقم واتساب الخاص بالمفتاح لم يعد متصلاً.
409قامت Meta بإيقاف الإرسال من هذا الرقم مؤقتاً.
429تم بلوغ الحد اليومي للمفتاح، أو حد المراسلة في واتساب لهذا الرقم.
502تعذر الوصول إلى Meta. حاول مرة أخرى.

يبدأ العدّ اليومي من جديد عند منتصف الليل بتوقيت UTC، ولا يتم احتساب عملية الإرسال التي تفشل.

واجهة WhatsApp API

معالجة الأخطاء

تأتي الأخطاء من مصدرين، وكلاهما يستخدم صيغة أخطاء Meta، لذلك يقرؤها أي كود حالي مكتوب لـ Cloud API بدون تغيير. الخطأ الصادر من Meta يعود تماماً كما أرسلته Meta، مع كود الحالة الخاص بها. أما الخطأ الصادر من إحدى قواعد SyBox نفسها فتكون قيمة type فيه SyBoxGatewayError، ويوضح message القاعدة التي رفضت الاستدعاء.

{
  "error": {
    "message": "(#131030) Recipient phone number not in allowed list",
    "type": "OAuthException",
    "code": 131030
  }
}

نظامك داخل SyBox

اعرض بيانات نظامك بجانب المحادثة

عند فتح محادثة، يستدعي SyBox نقطةَ الوصول الخاصة بنظامك ويعرض ما تُرجِعه بجانب المحادثة مباشرةً — طلبات العميل ورصيده وتذاكره. نُرسل رقم هاتف العميل، أو بريده الإلكتروني في محادثات البريد.

أضف نقطة الاتصال الخاصة بك في الإعدادات › التكاملات › واجهات الـ ERP. كل استدعاء هو طلب POST يحمل مفتاحك في Authorization، والطلب في حقل واحد هو data يحتوي على نص JSON — حتى يتمكن أي طرف من إضافة حقول لاحقاً بدون أن يتأثر الطرف الآخر. يجب الرد خلال 15 ثانية.

POST YOUR_ERP_URL
Authorization: Bearer YOUR_ERP_KEY
X-Sybox-Action: lookup
X-Sybox-Lang: en
X-Sybox-Theme: light
X-Sybox-Agent: 6f1c…
X-Sybox-Number: 104857600000000
Content-Type: application/json

{ "data": "{\"phone\":\"15551234567\",\"email\":\"customer@example.com\",\"ref\":\"\"}" }

يوضح كل استدعاء أيضاً من الذي يطلب: X-Sybox-Lang (لغة المستخدم — أجب بها)، و X-Sybox-Theme (light أو dark، للرد من نوع html)، و X-Sybox-Agent (معرّف المستخدم)، و X-Sybox-Number (الرقم الذي تجري عليه المحادثة).

نُرسل الهاتف والبريد معاً، وقد يكون أحدهما فارغاً؛ طابِق العميل بأيّهما يُعرّفه في نظامك، وأجِب بـ { renderAs, content }.

renderAs

حدِّد renderAs ليعرف SyBox كيف يعرض بياناتك — واحدة من:

renderAsالوصف
tableصفوف وأعمدة. content هو مصفوفة من كائنات بسيطة (أو { rows: [ … ] })، وتصبح مفاتيحها عناوين الأعمدة.
cards · kpiمربعات صغيرة، مثل الرصيد أو عدد الطلبات. content هو مصفوفة من { label, value } (أو { cards: [ … ] }).
feed · list · threadخط زمني من البطاقات. content هو مصفوفة من { title, text, date, tags, media: [{ type, url, name }] }.
messageسجل واحد يتم عرضه في بطاقة واحدة على شكل رسالة.
htmlكود HTML الخاص بك، كنص في content. فقط للكود الذي تقوم بإنشائه بنفسك.
sectionsعدة أقسام في رد واحد: content هو { sections: [ { title, renderAs, content } ] }.
jsonالخيار الافتراضي عند عدم تحديد renderAs: يقوم SyBox بعرض content الخاص بك بصيغة JSON منسّقة.

أضِف sybox_ref إلى أي صفٍّ في جدول أو بطاقة فيصبح قابلاً للنقر — يستدعيك SyBox مجدَّداً بذلك الـ ref لتُرجِع تفاصيل ذلك السجلّ وحده.

بحث المنتجات (X-Sybox-Action: products)

نفس الرابط يمكنه أيضاً الردّ على عمليات بحث المنتجات. يكتب المستخدم ما يسأل عنه العميل، فيرسله SyBox في الحقل "q"، ويتم عرض ردّك على شكل بطاقات منتجات بجوار المحادثة، مع زر إرسال يضع رابط المنتج في صندوق الكتابة.

POST YOUR_ERP_URL
Authorization: Bearer YOUR_ERP_KEY
X-Sybox-Action: products

# the decoded "data":
{ "q": "wireless keyboard", "phone": "15551234567", "email": "customer@example.com", "ref": "" }
الحقلالوصف
nameمطلوبالحقل الوحيد المطلوب. المنتج الذي لا يحمل سوى اسم يظهر كبطاقة مرتّبة أيضاً.
price · oldPrice · currencyأرقام، لا نصوص منسّقة. أرسل oldPrice فقط عند وجود سعر سابق حقيقي — يتم احتساب نسبة الخصم من الاثنين.
available · stockavailable تكون true/false، و stock عدد اختياري يظهر بجوارها. احذفهما تماماً إن كنت لا تتابع المخزون — الحقل الغائب لا يرسم شيئاً ولا تتم قراءته أبداً على أنه «غير متوفر».
imageرابط صورة https مباشر. أي صورة تفشل في التحميل يتم استبدالها بخلفية محايدة.
linkرابط صفحة المنتج. بدونه تكون البطاقة للعرض فقط — زر الإرسال يظهر فقط عندما يوجد ما يمكن إرساله.
noteسطر حر قصير أسفل السعر — مدة التوصيل، أو نوع، أو شرط.

لا شيء جديد سوى ما بنيته فعلاً: نفس الرابط، نفس المفتاح، ونفس الغلاف { "data": "…" }. انظر إلى X-Sybox-Action لتفرّق بين بحث المنتجات واستعلام العميل، وأجِب بـ content كمصفوفة مباشرة (أو { items: [ … ] }).

نظامك داخل SyBox

إنشاء حالة/تذكرة من نظامك الخارجي

هذا هو المسار الذي تستخدمه برامج الـ ERP والأنظمة المحاسبية. بدلاً من إرسال نص عادي، يطلب برنامجك من SyBox فتح حالة جديدة ومتابعتها.

POST/v1/caseAuthorization: Bearer <CASE_KEY>
curl -X POST https://api.sybox.io/v1/case \
  -H "Authorization: Bearer $SYBOX_CASE_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "customer_unique_id": "CUST-10432",
    "header": "Screen replacement not delivered",
    "description": "Paid on 12 Aug, promised in 3 days, still nothing.",
    "department_id": 5,
    "ext_ref": "TICKET-99817"
  }'

الحقول المطلوب تمريرها

الحقلالوصف
customer_unique_idالمعرّف الخاص بك للعميل — وهو نفس المفتاح الذي تستخدمه مزامنة العملاء. أرسل phone بدلاً منه إذا لم يكن لديك معرّف.
phoneرقم هاتف العميل، إذا لم يكن لديك معرّف.
header · descriptionأحدهما على الأقل مطلوب. الترويسة هي العنوان الذي يظهر للمستخدمين داخل القائمة.
department_idمطلوبintegerمطلوب. القسم الذي قُيدت فيه الحالة: الرقم الظاهر بجواره في الإعدادات › الأقسام (على سبيل المثال #5).
ext_refرقم التذكرة بداخل نظامك. أرسله دائماً؛ فإعادة الطلب بنفس ext_ref تعيد الحالة الموجودة بدلاً من تكرارها.
sectionintegerمن 1 إلى 4: تبويب الحالات الذي تظهر فيه الحالة. القيمة الافتراضية 1.
deadlinestringتاريخ الاستحقاق، YYYY-MM-DD.
notifybooleanالقيمة الافتراضية true: تظهر ملاحظة برقم الحالة في محادثة العميل داخل SyBox. لا يتم إرسال أي شيء إلى العميل. والقيمة false تلغي هذه الملاحظة.
sourcestringاسم البرنامج الذي يظهر على تلك الملاحظة. القيمة الافتراضية ERP.

يحمل الرد رقم الحالة، وهو الرقم الذي يذكره فريقك للعميل. وعند إعادة المحاولة بنفس ext_ref يكون الرد "duplicate": true مع الحالة الموجودة بالفعل، بدون customer_id.

يجب أن يكون العميل موجوداً مسبقاً في SyBox. إذا لم يتم العثور على المعرّف، يقوم SyBox بإجراء مزامنة عملاء واحدة مع نظامك ثم يبحث مرة أخرى؛ وإذا لم يتم العثور عليه بعدها، يكون الرد 404 — ولا يتم أبداً فتح حالة لعميل غير حقيقي.

استخدم مفتاحاً من نوع case. مفاتيح التمرير (الخاصة بالرسائل) سيتم رفضها بكود 403 لمنع استخدام مفاتيح المحادثات بداخل نظام CRM.

نظامك داخل SyBox

إدراج وتمرير رسالة من نظام خارجي

لأي نظام خارج واتساب: تنبيه من نقاط البيع POS، إشعار من جهاز، أو سطر من نظام قديم. تظهر الرسالة بداخل محادثة العميل بوضوح مع اسم البرنامج الصادر منه.

POST/v1/inboundAuthorization: Bearer <INBOUND_KEY>

لم يعد يتم إنشاء مفاتيح من هذا النوع، ويستمر أي مفتاح «استقبال من برنامج» موجود في العمل. للتكامل الجديد، افتح حالة — وسيقوم SyBox بكتابة الملاحظة في المحادثة نيابةً عنك.

cURL
curl -X POST https://api.sybox.io/v1/inbound \
  -H "Authorization: Bearer $SYBOX_INBOUND_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "phone": "15551234567",
    "text": "Order 4821 has left the warehouse.",
    "source": "Warehouse"
  }'
الحقلالوصف
phoneمطلوبstringرقم هاتف العميل، مع رمز الدولة.
textمطلوبstringالرسالة.
sourcestringاسم البرنامج، ويظهر على الرسالة.

الرد هو {"ok": 1, "id": …}، وهو معرّف الملاحظة في المحادثة.

مخصص للرسائل الواردة فقط بحكم تصميمه؛ حيث يقتصر دوره على الكتابة داخل المحادثة دون إرسال أي رسائل للعميل.

نظامك داخل SyBox

جهات الاتصال: القراءة والتحديث

باستخدام مفتاح من نوع «قراءة جهات الاتصال وتحديثها»، يمكن لأي برنامج البحث عن جهة اتصال وقراءتها وتعديل اسمها وبريدها الإلكتروني وحقول جهة الاتصال والتصنيفات الخاصة بها. كل طلب هو POST يحتوي على جسم JSON.

يعمل المفتاح بصفته الشخص الذي أنشأه: فهو لا يعثر إلا على جهات الاتصال المسموح لذلك الشخص برؤيتها، وفقط إذا كان مسموحًا له بفتح قائمة جهات الاتصال ورؤية الأرقام. ولتعديل أي شيء، يجب أن يكون مسموحًا لذلك الشخص بتعديل جهات الاتصال. إذا تم إيقاف حساب منشئ المفتاح، يتوقف المفتاح عن العمل.

POST/v1/contacts/searchAuthorization: Bearer <CONTACTS_KEY>

يبحث عن جهات الاتصال التي يحتوي اسمها أو رقم هاتفها أو بريدها الإلكتروني على q. قيمة limit الافتراضية هي 20، والحد الأقصى هو 50.

POST/v1/contacts/get

يجلب جهة اتصال واحدة بواسطة phone أو بواسطة key (وهو نفس المعرّف contact.key الذي يرسله الويب هوك).

POST/v1/contacts/update

يعدّل فقط ما ترسله: name و email و fields (حقول جهة الاتصال بواسطة المعرّف أو الاسم مع قيمها؛ القيمة الفارغة تمسح الحقل).

POST/v1/contacts/labels

يضيف التصنيفات ويزيلها بواسطة المعرّف أو الاسم: الحقلان add و remove هما قائمتان.

curl -X POST https://api.sybox.io/v1/contacts/update \
  -H "Authorization: Bearer $SYBOX_CONTACTS_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "phone": "201112223344",
    "name": "Sara Ali",
    "fields": { "city": "Alexandria" }
  }'

# Find:   POST /v1/contacts/search  {"q": "sara", "limit": 20}
# Read:   POST /v1/contacts/get     {"phone": "201112223344"}
# Labels: POST /v1/contacts/labels  {"phone": "201112223344", "add": ["VIP"], "remove": [7]}

يرد كل طلب ببيانات جهة الاتصال (في search: قائمة منها): key و name و phone و email و channel و labels و fields.

الأحداث

الويب هوك: الأحداث على خادمك

أضف نقطة الاتصال الخاصة بك في الإعدادات › التكاملات › الويب هوك، واختر الأحداث والأرقام، وسيقوم SyBox بإرسال كل حدث إليها بطلب POST فور حدوثه. يصل حدث واتساب بصيغة الويب هوك الخاصة بـ Meta نفسها، لذلك يعمل الكود المكتوب لـ Meta بدون تغيير.

الحدثالوصف
messageرسالة واردةرسالة من العميل.
statusحالة الرسالةتم الإرسال، أو تم التسليم، أو تمت القراءة، أو فشل الإرسال — لرسالة أرسلتها أنت.
reactionتفاعلقام العميل بالتفاعل مع رسالة.
doneوضع علامة كمكتمل على محادثةتم وضع علامة كمكتمل على محادثة: بواسطة مستخدم، أو بواسطة أتمتة، أو تلقائياً بعد صمت العميل.
labelإضافة تصنيف أو إزالتهتمت إضافة تصنيف إلى محادثة أو إزالته منها.
contactإنشاء جهة اتصال أو تحديثهاتم إنشاء جهة اتصال، أو تغيّر اسمها أو بريدها الإلكتروني أو حقول جهة الاتصال الخاصة بها.
dealإتمام صفقةتم تسجيل صفقة مكتملة في محادثة.
caseفتح حالة CRM أو إغلاقهاتم فتح حالة CRM أو إغلاقها (تم حلها أو لم يتم حلها أو تم إلغاؤها).
الطلب · من SyBox إليك
POST YOUR_WEBHOOK_URL
Content-Type: application/json
X-Hub-Signature-256: sha256=5d1f0c…
x-sybox-signature: sha256=5d1f0c…
x-sybox-event: message
x-sybox-timestamp: 1761400000

{
  "object": "whatsapp_business_account",
  "entry": [{
    "id": "WABA_ID",
    "changes": [{
      "field": "messages",
      "value": {
        "messaging_product": "whatsapp",
        "metadata": { "display_phone_number": "15550001111", "phone_number_id": "PHONE_NUMBER_ID" },
        "contacts": [{ "profile": { "name": "Sara" }, "wa_id": "15551234567" }],
        "messages": [{
          "from": "15551234567",
          "id": "wamid.HBgLMTU1NTEyMzQ1NjcVAgASGBQ…",
          "timestamp": "1761400000",
          "type": "text",
          "text": { "body": "Is my order shipped?" }
        }]
      }
    }]
  }]
}

الوسائط. رابط Meta الأصلي يحتاج إلى رمز وصول من Meta لفتحه، لذلك يقوم SyBox باستبداله برابط موقّع لنسخته الخاصة من الملف، صالح لمدة 24 ساعة. ويمكن للرسالة الصوتية أيضاً أن تتضمن نصها في sybox.transcription، عندما يطلبه الويب هوك.

القنوات الأخرى — ماسنجر، وإنستجرام، وتيليجرام، والدردشة المباشرة — تصل بصيغة SyBox الخاصة، لحدث الرسالة فقط:

JSON
{
  "object": "sybox",
  "event": "message",
  "channel": "telegram",
  "line": "8123456789",
  "workspace": "yourworkspace",
  "contact": { "key": "tg:6423115118", "name": "Sara" },
  "message": {
    "id": "812345",
    "timestamp": 1761400000,
    "type": "image",
    "text": "",
    "caption": "The broken part",
    "media": { "url": "https://api.sybox.io/…", "mime": "image/jpeg" }
  }
}

تصل أحداث المحادثات بتنسيق SyBox الموحّد لجميع القنوات. ويحدد الحقل event ما حدث بالضبط:

الحدث<code>event</code>
وضع علامة كمكتمل على محادثةconversation.done
إضافة تصنيف أو إزالتهlabel.added · label.removed
إنشاء جهة اتصال أو تحديثهاcontact.created · contact.updated
إتمام صفقةdeal.closed
فتح حالة CRM أو إغلاقهاcase.opened · case.closed
حدث تجريبيtest
{
  "object": "sybox",
  "event": "conversation.done",
  "channel": "whatsapp",
  "line": "201001234567",
  "workspace": "yourworkspace",
  "timestamp": 1761400000,
  "contact": {
    "key": "201112223344",
    "name": "Sara",
    "phone": "201112223344",
    "email": "",
    "channel": "whatsapp",
    "labels": [{ "id": 3, "name": "VIP" }],
    "fields": [{ "id": 2, "key": "city", "name": "City", "value": "Cairo" }]
  },
  "data": { "by": "Omar", "note": "Refund sent" }
}

مفتاح التوقيع

الترويسةالوصف
X-Hub-Signature-256sha256= متبوعاً بقيمة HMAC-SHA256 بصيغة hex لجسم الطلب الخام، باستخدام سر التوقيع الخاص بالويب هوك كمفتاح — نفس الترويسة والطريقة المستخدمة لدى Meta.
x-sybox-signatureالقيمة نفسها، حتى تتمكن نقطة الاتصال التي تستقبل أيضاً طلبات Meta نفسها من التمييز بين طلباتنا وطلباتها.
x-sybox-eventما حدث: message أو status أو reaction، أو أحد أحداث المحادثة الموضحة أدناه (conversation.done، label.added…)، أو test.
x-sybox-timestampوقت الإرسال، بالثواني بصيغة Unix.
x-sybox-signature-rsaتوقيع ثانٍ: rsa-sha256= ثم توقيع RSA-SHA256 (PKCS#1 v1.5) بترميز base64 لـ x-sybox-timestamp ثم نقطة ثم النص الخام للطلب.
x-sybox-key-idأيّ من مفاتيحنا قام بإنشاء التوقيع. المفتاح العام موجود على https://api.sybox.io/.well-known/sybox-webhook-key.

تحقق من التوقيع على البايتات الخام قبل تحليلها، وقارن في زمن ثابت:

const crypto = require('crypto');

// express.raw: the signature is over the bytes as sent, so read them before any JSON parser.
app.post('/sybox/webhook', express.raw({ type: 'application/json' }), (req, res) => {
  const sent = Buffer.from(req.get('X-Hub-Signature-256') || '');
  const want = Buffer.from('sha256=' + crypto
    .createHmac('sha256', process.env.SYBOX_WEBHOOK_SECRET)
    .update(req.body)
    .digest('hex'));
  if (sent.length !== want.length || !crypto.timingSafeEqual(sent, want)) return res.sendStatus(401);

  res.sendStatus(200);                       // answer first, then do the work
  const event = JSON.parse(req.body);
  const kind = req.get('x-sybox-event');     // message | status | reaction
});

لا تريد الاحتفاظ بسر مشترك على خادمك؟ تحقّق من x-sybox-signature-rsa بمفتاحنا العام بدلاً من ذلك. وفي الحالتين، ارفض أي طابع زمني مرّ عليه أكثر من خمس دقائق.

أجب بأي كود 2xx خلال 15 ثانية. مع أي رد آخر — خطأ، أو انتهاء المهلة، أو إعادة توجيه — تتم إعادة إرسال الحدث بعد 1 و 2 و 4 و 8 و 16 و 32 دقيقة، ثم يتم إهماله. قد يصل الحدث أكثر من مرة: استخدم معرّف الرسالة لتجاهل التكرار. يجب أن يكون العنوان عاماً ويستخدم https.

الويب هوك الذي يفشل 20 مرات متتالية لأكثر من ساعة يتم إيقافه تلقائياً ويتم إبلاغ مسؤول مساحة العمل. يتم الاحتفاظ بالأحداث المنتظرة لمدة 24 ساعة: أعد تفعيله لإرسالها.

للاختبار، اضغط على «إرسال حدث تجريبي» في بطاقة الويب هوك. وتعرض نافذة «عمليات التسليم» في البطاقة نفسها آخر 50 عملية تسليم مع رد الخادم لديك، ويمكنك من خلالها إعادة إرسال أي عملية.

الدردشة المباشرة

الدردشة المباشرة

ضع دردشة على موقعك الإلكتروني: يكتب الزوار هناك، ويجيب فريقك من SyBox. أضف الموقع في الإعدادات › المراسلة › القنوات، من بطاقة «الدردشة المباشرة»؛ وستعطيك النافذة التي تظهر، «الرمز البرمجي لموقعك»، الرمز البرمجي والمفاتيح الموضحة أدناه. لا يتم عرض المفاتيح السرية الثلاثة إلا مرة واحدة.

المفتاحيبدأ بـالغرض منه
المفتاح العامlcpk_تضعه في صفحاتك. ونشره آمن: فهو يحدد الموقع فقط، ولا تظهر الدردشة إلا على العناوين الموجودة في «عناوين المواقع الإلكترونية».
مفتاح توقيع المستخدمين المسجلينlcid_على خادمك فقط. يقوم بتوقيع كل مستخدم مسجل، حتى لا يتمكن أحد من الكتابة باسم شخص آخر.
مفتاح الخادم (لشاشة الدردشة الخاصة بك)lcsk_على خادمك فقط. مخصص فقط للموقع الذي يبني شاشة دردشة خاصة به بدلاً من الدردشة الجاهزة.
مفتاح توقيع الردودlcwh_على خادمك فقط. يثبت أن الرد الذي وصل إلى خادمك صادر من SyBox.

الدردشة الجاهزة لا تحتاج إلا إلى الرمز البرمجي. مفتاح التوقيع مخصص للموقع الذي يحتوي على حسابات للمستخدمين؛ أما مفتاح الخادم ومفتاح توقيع الردود فمخصصان فقط للموقع الذي لديه شاشة دردشة خاصة به.

عند إيقاف موقع، يتم إخفاء الدردشة فوراً. ويستمر قبول استدعاءات خادمك وتخزينها.

أضف الدردشة إلى موقعك

الصق الرمز البرمجي مرة واحدة في كل صفحة، قبل وسم إغلاق body مباشرة. لا تظهر الدردشة إلا على العناوين الموجودة في «عناوين المواقع الإلكترونية»، ويتم ضبط لونها وموضعها وعنوانها ورسالة الترحيب من SyBox، وليس من الكود.

HTML
<script async src="https://api.sybox.io/lc/w.js" data-key="lcpk_YOUR_PUBLIC_KEY"></script>

WordPress: قم بتنزيل إضافتنا من النافذة نفسها. Shopify: في تطبيق SyBox على Shopify، فعّل «الدردشة المباشرة في هذا المتجر»، ثم فعّل SyBox Live Chat ضمن تضمينات التطبيقات (App embeds) — ويتم التعرف على العميل المسجل بدون أي خطوة إضافية منك.

المستخدمون المسجلون: مفتاح التوقيع

عندما يكون المستخدم مسجلاً الدخول في موقعك، يقوم خادمك بإخبار الدردشة بهويته عن طريق رمز قصير — JWT بخوارزمية HS256 — موقّع بمفتاح التوقيع. بعدها تكون للمستخدم محادثة واحدة باسمه على كل أجهزته، ولا يمكن لأحد فتحها بكتابة معرّف شخص آخر.

  1. بعد تسجيل الدخول، يقوم خادمك ببناء الرمز من الحقول (claims) التالية.
  2. تمرر الصفحة الرمز إلى الدردشة باسم identity، قبل الرمز البرمجي للدردشة.
  3. بعد تسجيل الدخول بدون إعادة تحميل الصفحة، استدعِ SyBoxChat('identify', token) بدلاً من ذلك.
الحقلالوصف
subمطلوبstringمعرّف المستخدم لديك، حتى 120 حرفاً. لا يمكن أن يبدأ بـ v_.
expمطلوبnumberوقت انتهاء الصلاحية، بالثواني بصيغة Unix — لا يتجاوز يوماً واحداً من الآن. عشر دقائق مدة مناسبة: فلا تتم قراءة الرمز إلا عند فتح الدردشة.
namestringالاسم الذي يظهر في المحادثة.
emailstringالبريد الإلكتروني للمستخدم.
phonestringرقم هاتف المستخدم.
picturestringعنوان https لصورة المستخدم، حتى 500 حرف. يحتفظ SyBox بنسخته الخاصة منها، ويقوم بجلبها مجدداً عند تسجيل الدخول التالي إذا تغيّر العنوان.
function b64url(string $s): string { return rtrim(strtr(base64_encode($s), '+/', '-_'), '='); }

$header  = b64url(json_encode(['alg' => 'HS256', 'typ' => 'JWT']));
$payload = b64url(json_encode([
    'sub'   => (string) $user->id,
    'name'  => $user->name,
    'email' => $user->email,
    'exp'   => time() + 600,          // ten minutes
]));
$signature = b64url(hash_hmac('sha256', "$header.$payload", getenv('SYBOX_LC_SIGNING_KEY'), true));
$token = "$header.$payload.$signature";
HTML
<script>
  window.SyBoxChatConfig = { identity: "TOKEN_FROM_YOUR_SERVER", locale: "en" };
</script>
<script async src="https://api.sybox.io/lc/w.js" data-key="lcpk_YOUR_PUBLIC_KEY"></script>

أنشئ الرمز على خادمك فقط. وجود مفتاح التوقيع في صفحة ويب يسمح لأي شخص بالكتابة باسم أي مستخدم من مستخدميك. ولا تضع أبداً معرّف المستخدم وحده في الصفحة بدلاً من الرمز: فهذا يسمح لأي شخص باختيار المحادثة التي يريد قراءتها.

عند تفعيل «المستخدمون المسجلون في موقعي فقط»، لا تظهر الدردشة للزائر الذي ليس لديه رمز.

الزائر الذي تحدث في الدردشة قبل تسجيل الدخول يظهر له سؤال مرة واحدة، في المتصفح نفسه، عمّا إذا كان يريد متابعة تلك المحادثة بحسابه. لا تحتاج إلى فعل أي شيء لذلك.

تحكم في الدردشة من صفحتك

يضيف الرمز البرمجي للدردشة دالة واحدة إلى صفحتك، وهي SyBoxChat:

JavaScript
SyBoxChat('open');                       // open the chat
SyBoxChat('close');                      // close it
SyBoxChat('identify', token);            // after a sign-in without a page reload
SyBoxChat('locale', 'fr');               // the chat's language
SyBoxChat('on', 'message', function (m) {
  // a reply arrived
});
SyBoxChat('on', 'open', function () { /* the chat opened */ });
SyBoxChat('on', 'close', function () { /* the chat closed */ });

// Before the chat's code, every setting is optional:
window.SyBoxChatConfig = {
  identity: 'TOKEN_FROM_YOUR_SERVER',    // a signed-in user (see above)
  name: 'Sara', email: 'sara@example.com', // a visitor without an account: fills the form for them
  locale: 'ar',
  serviceWorker: 'auto'                   // 'auto' | '/your-sw.js' | 'site' | 'off'
};

الإشعارات بعد إغلاق موقعك

أثناء فتح أي صفحة من موقعك، يظهر الرد كإشعار تلقائياً. وللوصول إلى الزائر بعد إغلاق موقعك، تتطلب المتصفحات وجود service worker على نطاقك الخاص: قدّم هذا السطر الواحد كملف /sybox-lc-sw.js في جذر موقعك، بنوع application/javascript.

/sybox-lc-sw.js
try { importScripts('https://api.sybox.io/lc/sw.js'); } catch (e) {}

اختر الوضع في SyBox («الإشعارات عندما يكون الموقع مغلقًا») أو في الصفحة باستخدام serviceWorker: "auto" (الملف أعلاه، وهو الافتراضي)، أو مسار خاص بك، أو "site" (ضع السطر نفسه في بداية الـ service worker الخاص بموقعك)، أو "off".

لا تقوم الدردشة أبدًا باستبدال الـ service worker الموجود على موقعك، ولا يحتوي الملف على معالج fetch، لذلك لا يرى أي طلب من طلبات موقعك. وتقوم إضافة WordPress بتقديم الملف نيابة عنك. لا يعرض Safari على iPhone أي إشعارات لموقع ويب عادي.

شاشة الدردشة الخاصة بك: مفتاح الخادم

الموقع أو التطبيق الذي لديه شاشة دردشة خاصة به يتواصل مع SyBox من خادمه بدلاً من استخدام الدردشة الجاهزة. كل استدعاء يحمل Authorization: Bearer lcsk_…. يحدد خادمك المستخدم بالمعرّف الخاص بك، ويثق به SyBox لأنه يحمل المفتاح.

الاستدعاءالوصف
POST /v1/livechat/messagesيكتب المستخدم لديك رسالة. يجعل client_id إعادة المحاولة آمنة: يتم حفظ المعرّف نفسه مرة واحدة فقط ("duplicate": 1).
POST /v1/livechat/uploadملف، بصيغة multipart form data: file و user_id و client_id. حتى 16 MB: صور، وصوت، وفيديو، و PDF، ونصوص، ومستندات Office.
GET /v1/livechat/messages?user_id=&since=&before=&limit=المحادثة: الرسائل بعد since، و agents_read_id، وهو أحدث رسالة من رسائل المستخدم لديك قرأها أحد أفراد فريقك.
POST /v1/livechat/readقرأ المستخدم لديك الردود حتى up_to.
POST /v1/livechat/editيعدّل المستخدم لديك رسالته، خلال 15 دقيقة.
POST /v1/livechat/deleteيحذف المستخدم لديك رسالته لدى الجميع، خلال 24 ساعة.
POST /v1/livechat/reactتفاعل على أي رسالة؛ وقيمة emoji الفارغة تقوم بإزالته.
POST /v1/livechat/typingالمستخدم لديك يكتب الآن: أرسل on: 1 كل بضع ثوانٍ، و on: 0 عندما يتوقف.
curl -X POST https://api.sybox.io/v1/livechat/messages \
  -H "Authorization: Bearer $SYBOX_LC_SERVER_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "user":    { "id": "u42", "name": "Sara Ali", "email": "sara@example.com", "locale": "ar" },
    "message": { "client_id": "a1b2c3", "text": "Hi, is my order on its way?", "reply_to": "" }
  }'

الرسالة، في السجل وفي الردود:

JSON
{
  "id": 990,
  "guid": "b81d…",
  "dir": "out",                       // "in" = your user wrote it, "out" = your team
  "type": "image",                    // text | image | audio | video | file
  "text": "Here is the tracking page",
  "media": { "url": "https://api.sybox.io/…", "mime": "image/png", "name": "tracking.png", "w": 1080, "h": 720 },
                                       // a voice note or a video also has "secs"
  "status": 3,                         // on your user's messages: 1 received, 3 read by an agent
  "reply_to": "7c9e…",
  "client": "a1b2c3",                  // on your user's messages: the client_id you sent
  "react_us": "",                      // your team's reaction on it
  "react_me": "👍",                    // your user's reaction on it
  "at": "2026-10-25T09:41:07Z",
  "edited": 0
}

عند طلب سجل مستخدم لم يكتب من قبل، يكون الرد 404 unknown_user: اعرض محادثة فارغة.

روابط الوسائط موقّعة وتعمل لمدة ساعة واحدة؛ اطلبها مرة أخرى للحصول على رابط جديد. لا يقوم SyBox أبداً بجلب ملف من عنوان ترسله: قم برفعه. حتى 120 استدعاء في الدقيقة لكل موقع.

الردود على خادمك: مفتاح توقيع الردود

أدخل «عنوان خادمك لتلقي الردود» في إعدادات الموقع. عندما يرد فريقك أو يعدّل أو يحذف أو يقرأ، يقوم SyBox بإرسال الحدث إلى هذا العنوان بطلب POST، موقّعاً بمفتاح توقيع الردود.

الترويسةالوصف
x-sybox-signaturet=TIMESTAMP,v1=SIGNATURE — حيث TIMESTAMP هو الوقت بثواني Unix، و SIGNATURE هو قيمة HMAC-SHA256 بصيغة hex لـ TIMESTAMP.BODY (المحتوى الخام للطلب)، ويتم حسابها بمفتاح توقيع الردود.
x-sybox-eventmessage.created أو message.updated أو message.deleted أو messages.read.
x-sybox-deliveryالقيمة نفسها في كل إعادة محاولة للحدث الواحد: استخدمها لتجاهل التكرار.

يحتوي جسم الطلب على event و line_id و user_id و message — أو message_id في حالة الحذف، و read_id في messages.read: وتكون رسائل المستخدم لديك مقروءة حتى هذا المعرّف.

const crypto = require('crypto');

app.post('/sybox/livechat', express.raw({ type: 'application/json' }), (req, res) => {
  const parts = Object.fromEntries((req.get('x-sybox-signature') || '').split(',').map(p => p.split('=')));
  const t = Number(parts.t);
  if (!t || Math.abs(Date.now() / 1000 - t) > 300) return res.sendStatus(401);   // older than five minutes

  const want = Buffer.from(crypto.createHmac('sha256', process.env.SYBOX_LC_REPLY_KEY)
    .update(t + '.').update(req.body).digest('hex'));
  const sent = Buffer.from(parts.v1 || '');
  if (sent.length !== want.length || !crypto.timingSafeEqual(sent, want)) return res.sendStatus(401);

  res.sendStatus(200);
  const delivery = req.get('x-sybox-delivery');   // seen it already? ignore
  const evt = JSON.parse(req.body);               // { event, line_id, user_id, message | message_id | read_id }
});

تحقق من التوقيع على جسم الطلب الخام، وارفض أي t أقدم من خمس دقائق، وأجب بكود 2xx بسرعة. مع أي رد آخر تتم إعادة المحاولة بعد 10 ثوانٍ، ثم 30 ثانية، ثم دقيقتين، ثم 10 دقائق، ثم 30 دقيقة، ثم يتم إسقاط الحدث. لا يتصل SyBox إلا بالعناوين العامة، ولا يتبع أبداً إعادة التوجيه.

أكواد الأسباب

كل رد من الدردشة المباشرة يكون بصيغة JSON — {"ok": 1, …}، أو {"ok": 0, "error": "CODE"} مع كود بدلاً من جملة:

الكودالحالةالوصف
unauthorized401مفتاح الخادم خاطئ أو تم استبداله.
invalid_json invalid_payload invalid_user_id400الطلب ليس بالصيغة المتوقعة.
empty_message no_file empty_file400لا يوجد نص ولا ملف.
too_long400النص المعدّل يتجاوز 4,096 حرفاً.
not_an_emoji400emoji ليس رمزاً تعبيرياً.
not_found404لا توجد رسالة بهذا المعرّف، أو أنها ليست من رسائل هذا المستخدم.
too_late409انتهى الوقت المسموح للتعديل أو الحذف.
file_type_not_allowed400هذا النوع من الملفات غير مقبول.
file_too_large413حجم الملف أكبر من 16 MB.
blocked403قام فريقك بحظر هذا المستخدم.
unknown_user404لا توجد محادثة لمعرّف المستخدم هذا حتى الآن.
rate_limited429عدد كبير جداً من الاستدعاءات: قلّل السرعة وحاول مرة أخرى.
maintenance503جارٍ تحديث SyBox: حاول مرة أخرى بعد Retry-After ثانية.
server_error500حدث خطأ من جهتنا.

استبدال مفتاح

هل فقدت مفتاحاً، أو تظن أنه تسرّب؟ في بطاقة الموقع، اضغط «مفتاح توقيع جديد» أو «مفتاح خادم جديد» أو «مفتاح توقيع ردود جديد». مفتاح الخادم الجديد يترك المفتاح القديم يعمل لمدة يوم واحد، حتى تتمكن من الانتقال بدون انقطاع؛ أما المفاتيح الأخرى فتتوقف فوراً.