الشرح والتوثيق

كل ما تحتاجه لاستقبال وإرسال رسائل واتساب مع Kobry.

البداية السريعة

Kobry يربط الرقم الذي تستخدمه على تطبيق واتساب للأعمال بالـ Cloud API (تسميها Meta باسم Coexistence). تستمر في المحادثة من هاتفك، وتستقبل الأتمتة كل رسالة عبر Webhook وترد عبر REST API بسيط.

  1. أنشئ حسابك واختر باقة (فودافون كاش داخل مصر، أو فيزا/ماستركارد من أي دولة).
  2. افتح الأرقام المربوطة ← ربط رقم وأكمل خطوات Meta بالرقم الموجود على تطبيق واتساب للأعمال.
  3. ضع رابط الـ Webhook (مثل Webhook node في n8n) واضغط إرسال حدث تجريبي.
  4. أنشئ مفتاح API من مفاتيح الـ API وأرسل أول رسالة.

يجب أن يكون تطبيق واتساب للأعمال إصدار 2.24.17 أو أحدث. احتفظ بالتطبيق على هاتفك — ستستمر في استخدامه كالمعتاد.

استقبال الرسائل (Webhooks)

كل حدث ترسله Meta لرقمك — الرسائل الجديدة، حالات التوصيل والقراءة، الرسائل التي ترسلها من التطبيق (smb_message_echoes)، تحديثات القوالب — يصلك على رابطك كطلب HTTPS POST. المحتوى هو JSON الأصلي من Meta بدون أي تغيير، لذلك تنطبق عليه توثيقات Meta كما هي.

مثال: رسالة نصية جديدة
{
  "object": "whatsapp_business_account",
  "entry": [{
    "id": "102290129340398",
    "changes": [{
      "field": "messages",
      "value": {
        "messaging_product": "whatsapp",
        "metadata": { "display_phone_number": "201000000000", "phone_number_id": "106540352242922" },
        "contacts": [{ "profile": { "name": "Mona" }, "wa_id": "201012345678" }],
        "messages": [{
          "from": "201012345678",
          "id": "wamid.HBgM...",
          "timestamp": "1700000000",
          "type": "text",
          "text": { "body": "Is the blue hoodie available?" }
        }]
      }
    }]
  }]
}
  • رد بأي حالة 2xx خلال 5 ثوانٍ. نفّذ الأعمال البطيئة بعد الرد.
  • إذا كان السيرفر متوقفًا أو بطيئًا، نعيد إرسال الحدث لمدة تصل إلى 24 ساعة (بعد 10 ثوانٍ، ثم دقيقة، 5، 15، 30 دقيقة، ثم كل ساعة تقريبًا). يظهر كـ جاري إعادة المحاولة في سجل الـ Webhooks حتى يتم توصيله. بسبب إعادة المحاولة قد يصلك نفس الحدث مرتين نادرًا — استخدم id الرسالة لتجاهل المكرر.
  • يجب أن يكون الرابط HTTPS على المنفذ 443، وبدون تحويل (redirect)، ويشير إلى عنوان عام.
  • لا نخزّن محتوى الرسائل أبدًا — إلا الحدث اللي سيرفرك لسه ما استقبلهوش: بنحتفظ بيه مشفّرًا وإحنا بنعيد المحاولة، ويتمسح أول ما يوصل، ولا يزيد عن 24 ساعة. نحتفظ فقط بالبيانات الوصفية (نوع الحدث، النتيجة، التوقيت) لمدة 7 أيام في سجل الـ Webhooks.

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

كل طلب نرسله يحمل الهيدر X-Kobry-Signature: sha256=<hex> — وهو HMAC-SHA256 لـ محتوى الطلب الخام باستخدام الـ Signing secret الخاص بالرقم (الأرقام المربوطة ← Signing secret). تحقق منه حتى لا يستطيع أحد إرسال أحداث مزيفة إلى رابطك.

Node.js (Express)
const crypto = require('crypto');

app.post('/whatsapp', express.raw({ type: 'application/json' }), (req, res) => {
  const expected = 'sha256=' + crypto
    .createHmac('sha256', process.env.KOBRY_SECRET)
    .update(req.body) // raw bytes, not re-serialized JSON
    .digest('hex');
  const received = req.get('X-Kobry-Signature') || '';
  const ok = expected.length === received.length &&
    crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(received));
  if (!ok) return res.sendStatus(401);

  res.sendStatus(200); // answer fast…
  handle(JSON.parse(req.body)); // …then do the work
});
Python
import hmac, hashlib

def is_valid(raw_body: bytes, header: str, secret: str) -> bool:
    expected = "sha256=" + hmac.new(secret.encode(), raw_body, hashlib.sha256).hexdigest()
    return hmac.compare_digest(expected, header or "")

إرسال الرسائل

أرسل عبر POST https://kobry.app/v1/messages مع مفتاح الـ API في هيدر Authorization. المحتوى هو كائن الرسالة كما تعرّفه Meta (فيعمل كل نوع رسالة تدعمه Meta)، ويمكنك إضافة connection_id إذا كان لديك أكثر من رقم.

رسالة نصية (فقط خلال 24 ساعة من آخر رسالة من العميل)
curl -X POST https://kobry.app/v1/messages \
  -H "Authorization: Bearer kob_live_…" \
  -H "Content-Type: application/json" \
  -d '{
    "to": "201012345678",
    "type": "text",
    "text": { "body": "Yes, size L is in stock ✅" }
  }'
رسالة قالب (لبدء محادثة)
curl -X POST https://kobry.app/v1/messages \
  -H "Authorization: Bearer kob_live_…" \
  -H "Content-Type: application/json" \
  -d '{
    "to": "201012345678",
    "type": "template",
    "template": {
      "name": "order_ready",
      "language": { "code": "ar" },
      "components": [{
        "type": "body",
        "parameters": [{ "type": "text", "text": "Mona" }, { "type": "text", "text": "A-1001" }]
      }]
    }
  }'
الرد
{
  "messaging_product": "whatsapp",
  "contacts": [{ "input": "201012345678", "wa_id": "201012345678" }],
  "messages": [{ "id": "wamid.HBgM..." }]
}

يسمح واتساب بالرسائل الحرة فقط خلال 24 ساعة من آخر رسالة من العميل. بعد ذلك أرسل قالبًا مقبولًا.

GET /v1/connections يعرض أرقامك ومعرّفاتها. ويمكن قصر المفتاح على رقم واحد عند إنشائه.

القوالب

أنشئ القوالب وأدرها من لوحة التحكم (القوالب) أو عبر الـ API. تراجع Meta كل قالب جديد، عادةً خلال دقائق.

الطلبماذا يفعل
GET /v1/templatesعرض القوالب مع حالتها (APPROVED أو PENDING أو REJECTED…).
POST /v1/templatesإنشاء قالب — بنفس محتوى Meta (name و language و category و components).
DELETE /v1/templates/{name}حذف قالب بالاسم.

أضف ?connection_id=… (أو "connection_id" داخل المحتوى) إذا كان لديك أكثر من رقم.

دليل n8n

استقبل رسائل واتساب في n8n ورد عليها — بدون كود للأساسيات.

  1. Webhook node — اختر HTTP Method POST ومسارًا، و Respond: Immediately. انسخ Production URL.
  2. في Kobry: الأرقام المربوطة ← الصق الرابط ← حفظ الرابط ← إرسال حدث تجريبي. فعّل الـ workflow أولًا، أو استخدم Test URL أثناء التجربة.
  3. اقرأ الرسالة: النص في {{ $json.body.entry[0].changes[0].value.messages[0].text.body }} والمرسل في …messages[0].from.
  4. IF node — أكمل فقط عند وجود messages (تحديثات الحالة تصل على نفس الـ Webhook).
  5. HTTP Request node للرد — Method POST والرابط https://kobry.app/v1/messages، و Authentication ← Generic Credential ← Header Auth (Name Authorization و Value Bearer kob_live_…)، والمحتوى JSON كما في «إرسال الرسائل».

للتحقق من التوقيع داخل n8n، فعّل Raw Body من خيارات الـ Webhook node وأضف Code node قبل باقي الخطوات:

Code node في n8n — التحقق من التوقيع
const crypto = require('crypto');
const item = $input.first();
const raw = Buffer.from(item.binary.data.data, 'base64');
const expected = 'sha256=' + crypto
  .createHmac('sha256', 'PASTE_YOUR_SIGNING_SECRET')
  .update(raw)
  .digest('hex');
const received = item.json.headers['x-kobry-signature'] || '';
if (expected !== received) throw new Error('Invalid signature');
return [{ json: JSON.parse(raw.toString('utf8')) }];

في n8n المستضاف ذاتيًا يجب ضبط المتغير NODE_FUNCTION_ALLOW_BUILTIN=crypto حتى يعمل require('crypto').

الأخطاء والحدود

كل الأخطاء بنفس الشكل: { "error": { "code": "…", "message": "…" } }.

الحالةcodeالمعنى
400meta_rejectedرفضت Meta الطلب — الرسالة توضح السبب.
401unauthorizedمفتاح API ناقص أو خاطئ أو ملغى.
402plan_requiredلا توجد باقة مفعّلة.
403forbidden_connectionهذا المفتاح مقصور على رقم آخر.
404connection_not_foundهذا الرقم غير موجود في مساحة العمل.
409connection_not_readyالرقم متوقف أو لم يُربط بعد.
413payload_too_largeالمحتوى أكبر من 64 كيلوبايت.
422invalid_request / connection_requiredصحّح المحتوى، أو أضف connection_id.
429rate_limitedأكثر من 600 طلب في الدقيقة لهذا المفتاح — راجع Retry-After.
502meta_unavailableمشكلة لدى Meta. حاول بعد قليل.

معلومات مهمة (Coexistence)

  • محادثات المجموعات لا تتم مزامنتها مع الـ API.
  • بعد الربط تتوقف في التطبيق: الرسائل المختفية، والعرض لمرة واحدة، والموقع المباشر، وقوائم البث.
  • أرقام الـ Coexistence ترسل حتى حوالي 20 رسالة في الثانية.
  • افتح تطبيق واتساب للأعمال بانتظام (مرة كل أسبوعين على الأقل) — قد تفصل Meta الأرقام غير النشطة.
  • رسوم Meta على الرسائل تدفعها مباشرة إلى Meta. لا نضيف أي زيادة.