الشرح والتوثيق
كل ما تحتاجه لاستقبال وإرسال رسائل واتساب مع Kobry.
البداية السريعة
Kobry يربط الرقم الذي تستخدمه على تطبيق واتساب للأعمال بالـ Cloud API (تسميها Meta باسم Coexistence). تستمر في المحادثة من هاتفك، وتستقبل الأتمتة كل رسالة عبر Webhook وترد عبر REST API بسيط.
- أنشئ حسابك واختر باقة (فودافون كاش داخل مصر، أو فيزا/ماستركارد من أي دولة).
- افتح الأرقام المربوطة ← ربط رقم وأكمل خطوات Meta بالرقم الموجود على تطبيق واتساب للأعمال.
- ضع رابط الـ Webhook (مثل Webhook node في n8n) واضغط إرسال حدث تجريبي.
- أنشئ مفتاح 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). تحقق منه حتى لا يستطيع أحد إرسال أحداث مزيفة إلى رابطك.
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
});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 إذا كان لديك أكثر من رقم.
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 ورد عليها — بدون كود للأساسيات.
- Webhook node — اختر HTTP Method
POSTومسارًا، و Respond: Immediately. انسخ Production URL. - في Kobry: الأرقام المربوطة ← الصق الرابط ← حفظ الرابط ← إرسال حدث تجريبي. فعّل الـ workflow أولًا، أو استخدم Test URL أثناء التجربة.
- اقرأ الرسالة: النص في
{{ $json.body.entry[0].changes[0].value.messages[0].text.body }}والمرسل في…messages[0].from. - IF node — أكمل فقط عند وجود
messages(تحديثات الحالة تصل على نفس الـ Webhook). - HTTP Request node للرد — Method
POSTوالرابطhttps://kobry.app/v1/messages، و Authentication ← Generic Credential ← Header Auth (NameAuthorizationو ValueBearer kob_live_…)، والمحتوى JSON كما في «إرسال الرسائل».
للتحقق من التوقيع داخل n8n، فعّل Raw Body من خيارات الـ Webhook node وأضف Code node قبل باقي الخطوات:
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 | المعنى |
|---|---|---|
| 400 | meta_rejected | رفضت Meta الطلب — الرسالة توضح السبب. |
| 401 | unauthorized | مفتاح API ناقص أو خاطئ أو ملغى. |
| 402 | plan_required | لا توجد باقة مفعّلة. |
| 403 | forbidden_connection | هذا المفتاح مقصور على رقم آخر. |
| 404 | connection_not_found | هذا الرقم غير موجود في مساحة العمل. |
| 409 | connection_not_ready | الرقم متوقف أو لم يُربط بعد. |
| 413 | payload_too_large | المحتوى أكبر من 64 كيلوبايت. |
| 422 | invalid_request / connection_required | صحّح المحتوى، أو أضف connection_id. |
| 429 | rate_limited | أكثر من 600 طلب في الدقيقة لهذا المفتاح — راجع Retry-After. |
| 502 | meta_unavailable | مشكلة لدى Meta. حاول بعد قليل. |
معلومات مهمة (Coexistence)
- محادثات المجموعات لا تتم مزامنتها مع الـ API.
- بعد الربط تتوقف في التطبيق: الرسائل المختفية، والعرض لمرة واحدة، والموقع المباشر، وقوائم البث.
- أرقام الـ Coexistence ترسل حتى حوالي 20 رسالة في الثانية.
- افتح تطبيق واتساب للأعمال بانتظام (مرة كل أسبوعين على الأقل) — قد تفصل Meta الأرقام غير النشطة.
- رسوم Meta على الرسائل تدفعها مباشرة إلى Meta. لا نضيف أي زيادة.