واجهة WidersApps البرمجية
واجهة REST لبيانات WidersApps — جهات الاتصال والمحادثات والطلبات والحجوزات. JSON دخولاً وخروجاً، بغلاف موحّد واحد، ومؤمّنة بمفتاح Bearer تنشئه بنفسك.
العنوان الأساسي
كل نقطة نهاية تقع تحت مسار أساسي واحد يحمل رقم الإصدار. أرسِل كل الطلبات عبر HTTPS.
https://console.widers.net/api/v1
الموارد
الموارد الأساسية والصلاحية التي تحتاجها كل قدرة. هذه مجموعة مختارة للبدء — والمرجع التفاعلي يسرد كل نقطة نهاية تكشفها الواجهة، بتفاصيل الطلب والاستجابة لكلٍّ منها.
| المورد | ما يمكنك فعله | النطاق |
|---|---|---|
| جهات الاتصال | عرض القائمة · عرض واحد · إنشاء · تعديل · حذف | contacts.view · contacts.manage |
| المنتجات | عرض القائمة · عرض واحد · إنشاء وتحديث الحقول الأساسية (الاسم، السعر، الحالة، المخزون — لمزامنة الكتالوج والمخزون) | commerce.view · commerce.manage |
| الطلبات | عرض القائمة · عرض واحد · إنشاء · تقديم الحالة | commerce.view · commerce.manage |
| الرسائل | عرض القائمة · عرض واحد · إرسال | inbox.access |
| المحادثات | عرض القائمة · عرض واحد · إسناد · تحويل · إغلاق · إعادة فتح · تعليم مقروء · كتم · أرشفة · متابعة · ملاحظة · وسم | inbox.access |
| الحجوزات | CRUD كامل + الأوقات المتاحة | calendar.view · calendar.manage |
| الوسوم | عرض الوسوم؛ وإنشاء/إعادة تسمية/حذف وسومك (وسوم النظام للقراءة فقط) | inbox.access · tags.manage |
| الوسائط | رفع ملف والحصول على رابط لإرفاقه عند إرسال رسالة | inbox.access |
| الردود السريعة | عرض وإنشاء الردود السريعة المحفوظة | quick-replies.manage |
| الحملات | عرض الحملات وإحصاءاتها؛ وإيقاف/استئناف/إلغاء حملة جارية | campaigns.view · campaigns.manage |
حالات تسليم الرسائل وقراءتها وفشلها تصل عبر الويب هوك (message.delivered · message.read · message.failed) لا كنقاط نهاية تُستعلَم. وتغيّرات دورة حياة المحادثة (إنشاء · إسناد · إغلاق · وسم · …) ويب هوك أيضاً — اشترك فيها من الإعدادات ← الويب هوك.
إنشاء مفتاح API
أنشئ مفتاحاً من لوحة التحكّم عبر: الإعدادات ← المطوّرون ← مفاتيح API (للمالك فقط). عند الإنشاء تختار:
- اسماً — لتتعرّف عليه وتُبطله لاحقاً.
- النطاقات — لا يمكنك منح إلا النطاقات التي تملكها أنت.
- مباشر أم اختبار — مفتاح الاختبار (Sandbox) لا يمسّ بيانات حقيقية أبداً.
- تاريخ انتهاء اختياري.
يُعرض المفتاح كاملاً مرّة واحدة عند الإنشاء. انسخه حينها واحفظه بأمان — وإن فقدته فأبطِله وأنشئ غيره.
المصادقة
صادِق كل طلب بمفتاح Bearer في ترويسة Authorization. الصق المفتاح تماماً كما عُرض لك، ببادئته:
Authorization: Bearer wa_live_<id>|<token>
مفتاح الاختبار يحمل البادئة wa_test_ بدلاً من ذلك:
Authorization: Bearer wa_test_<id>|<token>
كل مستخدم ينتمي لشركة واحدة فقط، فالمفتاح يحدّد الحساب الذي يعمل عليه — لا وسيط للمستأجر تمرّره.
النطاقات (Scopes)
النطاقات هي أسماء صلاحيات المنصّة نفسها، فلا يقدر المفتاح على أكثر ممّا يقدر عليه مستخدم اللوحة صاحب الصلاحيات ذاتها. النطاقات المتاحة:
| النطاق | الوصف |
|---|---|
contacts.view |
قراءة جهات الاتصال |
contacts.manage |
إدارة جهات الاتصال |
inbox.access |
الرسائل (قراءة وإرسال) |
tags.manage |
إدارة الوسوم |
quick-replies.manage |
إدارة الردود السريعة |
commerce.view |
قراءة الطلبات والمنتجات |
commerce.manage |
إدارة الطلبات والمنتجات |
campaigns.view |
قراءة الحملات |
campaigns.manage |
التحكم بالحملات (إيقاف مؤقت، استئناف، إلغاء) |
calendar.view |
قراءة الحجوزات |
calendar.manage |
إدارة الحجوزات |
يُصدَر المفتاح بالنطاقات التي تحدّدها بالضبط — بلا تعميم، وبما لا يتجاوز ما تملكه أنت.
غلاف الاستجابة
الاستجابة الناجحة تغلّف البيانات داخل مفتاح data، مع كتلة meta اختيارية (تستخدمها القوائم المصفّحة):
{
"data": { ... },
"meta": { "next_cursor": null, "has_more": false }
}
يُرجِع الفشل كائن خطأ موحّداً واحداً:
{
"error": {
"type": "invalid_request_error",
"code": "not_found",
"message": "The requested resource was not found.",
"param": null,
"request_id": "req_01J..."
}
}
رموز الأخطاء
سلسلة code عقد ثابت مقروء آلياً (مستقلّ عن اللغة، لا يُعاد تسميته) لتفرّع منطقك عليه؛ أمّا الرسالة البشرية message فتُترجَم على حدة. أمّا type فهو عائلة الخطأ العامّة.
| الرمز | النوع | HTTP |
|---|---|---|
bad_request |
invalid_request_error |
400 |
validation_failed |
invalid_request_error |
422 |
unauthenticated |
authentication_error |
401 |
forbidden |
authorization_error |
403 |
not_found |
invalid_request_error |
404 |
method_not_allowed |
invalid_request_error |
405 |
not_acceptable |
invalid_request_error |
406 |
conflict |
idempotency_error |
409 |
idempotency_conflict |
idempotency_error |
409 |
payload_too_large |
invalid_request_error |
413 |
rate_limited |
rate_limit_error |
429 |
server_error |
api_error |
500 |
كل خطأ يردّد request_id (نفس قيمة ترويسة X-Request-Id) — اذكره عند الإبلاغ عن مشكلة.
حدود المعدّل
تسمح الواجهة بـ120 طلباً في الدقيقة لكل مفتاح (الطلبات غير المصادَقة تُحدّ بعنوان IP). كل استجابة تحمل الترويسات القياسية:
X-RateLimit-Limit,X-RateLimit-Remaining,Retry-After- تجاوز الحدّ يُرجِع 429 برمز rate_limited؛ تمهّل حتى Retry-After.
عدم التكرار (Idempotency)
أرسِل ترويسة Idempotency-Key مع أي POST أو PUT أو PATCH أو DELETE ليُطبَّق الطلب المُعاد مرّة واحدة على الأكثر. استخدم UUID جديداً لكل عملية منطقية:
Idempotency-Key: 6f9e0b2c-1a3d-4e5f-8a7b-9c0d1e2f3a4b
- إعادة نفس المفتاح والجسم تُرجِع الاستجابة المخزّنة مع Idempotency-Replayed: true.
- تُحفظ المفاتيح لمدّة 24 ساعة.
- إعادة استخدام مفتاح بجسم مختلف، أو والطلب الأول ما زال جارياً، تُرجِع 409 idempotency_conflict.
التصفّح (Pagination)
القوائم تستخدم تصفّحاً مبهماً قائماً على المؤشّر (keyset). مرّر limit (افتراضياً 25، وأقصاه 100) ومؤشّراً cursor مبهماً:
GET https://console.widers.net/api/v1/contacts?limit=25&cursor=<opaque>
تحمل meta في الاستجابة مؤشّر الصفحة التالية وما إن كانت هناك صفوف أخرى. عندما يكون has_more قيمته false يكون next_cursor فارغاً null:
"meta": { "next_cursor": "eyJ...", "has_more": true }
المؤشّر التالف يُرجِع 422 — لا مسحاً كاملاً صامتاً. عامِل المؤشّر ككتلة مبهمة وأعده كما هو حرفياً.
وضع الاختبار (Sandbox)
وضع الاختبار يحمله المفتاح (مفتاح اختبار)، فلا تقلبه أثناء الطلب. طلب الـSandbox لا يمسّ عملاء أو طلبات أو أموالاً حقيقية — بل يصطنع الاستجابات:
- كل استجابة تُعلن وضعها:
X-Widers-Mode: live/X-Widers-Mode: test - مفتاح وضع الاختبار يتوقّف قبل أي أثر فعلي، فلا يُطلق أي Webhook — كل Webhook يصلك يكون من نشاط حقيقي.
- الخدمات ذات الأثر الجانبي تصطنع نداءاتها الخارجية في وضع الاختبار.
توقيع الـWebhook
كل webhook نرسله إلى نقطتك موقّع بـHMAC مختوم بالوقت في ترويسة X-Widers-Signature، لتتحقّق من الأصالة والحداثة معاً:
X-Widers-Signature: t=1706342400,v1=<hmac_sha256>
- تحقّق مقابل جسم الطلب الخام غير المحلَّل — احسب hmac_sha256(secret, "<t>.<body>").
- ارفض أي طلب تبعد طابعه الزمني أكثر من 300 ثانية عن الآن (دفاعاً عن إعادة التشغيل).
- قارِن بدالّة ثابتة الزمن (hash_equals) تفادياً لهجمات التوقيت.
مُتحقّق جاهز للنسخ (PHP):
<?php
function widers_verify(string $secret, string $rawBody, string $header): bool
{
// header: "t=<unix>,v1=<hex>"
parse_str(strtr($header, ',', '&'), $parts);
$t = (int) ($parts['t'] ?? 0);
$sig = (string) ($parts['v1'] ?? '');
if (abs(time() - $t) > 300) {
return false; // outside the 300s replay window
}
$expected = hash_hmac('sha256', $t . '.' . $rawBody, $secret);
return hash_equals($expected, $sig);
}
طلبك الأول
اسرد جهات اتصالك بطلب واحد مصادَق:
curl https://console.widers.net/api/v1/contacts \
-H "Authorization: Bearer wa_live_<id>|<token>" \
-H "Accept: application/json"
حجوزات التقويم (مصادقة قديمة)
- يصادِق بصلاحيات Sanctum القديمة، لا بالنطاقات أعلاه:
bookings.read/bookings.write - يُرجِع غلاف Laravel الافتراضي، لا شكل data/error:
{"data":[...]} - لا تصفّح بالمؤشّر، ولا وضع اختبار، ولا دعم لعدم التكرار — قائمته غير مصفّحة ومحدودة بسقف صارم.
مستعدّ لاستكشاف كل نقطة نهاية؟ راجِع مرجع الـAPI