ثلاث لوحات كود متجاورة تعرض نفس كود إرسال رسالة WhatsApp Cloud API في Node.js وPython وPHP على خلفية طرفية داكنة
الأقسام: أساسيات API · رسالة نصية · قالب مع متغيرات · صورة ومستند · أزرار تفاعلية · موقع · إرسال مجمّع مع تحديد المعدل · معالجة الأخطاء والمحاولة المتكررة · أغلفة فئات كاملة (Node / Python / PHP)

أساسيات API: نقطة الوصول الوحيدة التي يمر عبرها كل شيء

كل رسالة WhatsApp صادرة — بغض النظر عن النوع — تمر عبر نقطة وصول HTTP POST واحدة. نوع الرسالة ومحتواها في جسم JSON. هذا كل شيء. لا WebSockets، ولا streaming، ولا long-polling.

ثلاث قيم تحتاجها قبل تشغيل أي كود:

  • Phone Number ID — معرّف رقمي لرقم WhatsApp Business الخاص بك (يبدو مثل 123456789012345). مختلف عن رقم هاتفك الفعلي.
  • Access Token — رمز System User دائم بصلاحية whatsapp_business_messaging. لا تستخدم أبداً رمز مستخدم مؤقت في الإنتاج.
  • رقم هاتف المستلم — بصيغة E.164: رمز الدولة + الرقم، بدون مسافات أو شُرَط أو علامة + في قيمة JSON (مثلاً 15550001234 لرقم أمريكي، أو مع + مقبول أيضاً: +15550001234).

إرسال ناجح يُعيد HTTP 200 مع جسم مثل:

أنواع الرسائل: الجلسة مقابل القالب

قبل اختيار نوع الرسالة، تحتاج أن تعرف ما إذا كنت داخل نافذة الخدمة. نافذة الجلسة (24 ساعة بعد أن يراسلك العميل، أو 72 ساعة بعد نقرة إعلان Click-to-WhatsApp) تحدد أنواع الرسائل المجانية وغير المقيدة.

text
نص عادي. مدعوم بتنسيق WhatsApp شبيه بالـ markdown. حتى 4,096 حرفاً.
مجاني داخل النافذة
template
صيغة معتمدة مسبقاً بخانات متغيرات. مطلوب لبدء الاتصال خارج النافذة.
يتطلب موافقة
image
JPEG أو PNG. حد أقصى 5 ميجابايت. URL أو media ID. تعليق اختياري.
مجاني داخل النافذة
document
PDF أو DOCX أو XLSX. حد أقصى 100 ميجابايت. URL أو media ID. اسم الملف ظاهر.
مجاني داخل النافذة
video
MP4 أو 3GPP. حد أقصى 16 ميجابايت. URL أو media ID. تعليق اختياري.
مجاني داخل النافذة
interactive
ردود أزرار (حد أقصى 3) أو رسائل قوائم (حد أقصى 10 عناصر). العميل ينقر للرد.
مجاني داخل النافذة
location
أرسل خط العرض/الطول مع اسم وعنوان اختياريين. يُعرض على خريطة في WhatsApp.
مجاني داخل النافذة
audio
MP3 أو AAC. حد أقصى 16 ميجابايت. URL أو media ID. لا يدعم التعليقات.
مجاني داخل النافذة

إرسال رسالة نصية

أبسط إرسال. يعمل داخل نافذة الخدمة لـ 24 ساعة دون أي رسوم من Meta (ضمن حصة 1,000 محادثة خدمة مجانية/شهر). خارج النافذة، استخدم قالباً بدلاً من ذلك.

Node.js (native fetch)
sendText.js
async function sendText(to, message) { const url = `https://graph.facebook.com/v21.0/${process.env.WA_PHONE_ID}/messages`; const res = await fetch(url, { method: 'POST', headers: { 'Authorization': `Bearer ${process.env.WA_TOKEN}`, 'Content-Type': 'application/json', }, body: JSON.stringify({ messaging_product: 'whatsapp', recipient_type: 'individual', to, type: 'text', text: { body: message, preview_url: false }, }), }); if (!res.ok) throw new Error(`WhatsApp error: ${await res.text()}`); return (await res.json()).messages[0].id; // wamid — خزّنه لتتبع الحالة } // الاستخدام const messageId = await sendText('+15550001234', 'Hello from WhatsApp Cloud API! 👋');
Python (requests)
send_text.py
import os, requests def send_text(to: str, message: str) -> str: url = f"https://graph.facebook.com/v21.0/{os.environ['WA_PHONE_ID']}/messages" res = requests.post(url, headers={ "Authorization": f"Bearer {os.environ['WA_TOKEN']}", "Content-Type": "application/json", }, json={ "messaging_product": "whatsapp", "recipient_type": "individual", "to": to, "type": "text", "text": { "body": message, "preview_url": False }, } ) res.raise_for_status() return res.json()["messages"][0]["id"] # الاستخدام message_id = send_text("+15550001234", "Hello from WhatsApp Cloud API! 👋")
PHP (cURL)
send_text.php
function sendText(string $to, string $message): string { $url = "https://graph.facebook.com/v21.0/" . getenv('WA_PHONE_ID') . "/messages"; $body = [ 'messaging_product' => 'whatsapp', 'recipient_type' => 'individual', 'to' => $to, 'type' => 'text', 'text' => ['body' => $message, 'preview_url' => false], ]; $ch = curl_init($url); curl_setopt_array($ch, [ CURLOPT_POST => true, CURLOPT_POSTFIELDS => json_encode($body), CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => [ 'Authorization: Bearer ' . getenv('WA_TOKEN'), 'Content-Type: application/json', ], ]); $response = json_decode(curl_exec($ch), true); $status = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); if ($status !== 200) { throw new RuntimeException('WhatsApp error: ' . json_encode($response)); } return $response['messages'][0]['id']; // خزّنه لتتبع الحالة } // الاستخدام $messageId = sendText('+15550001234', 'Hello from WhatsApp Cloud API! 👋');

إرسال رسالة قالب مع متغيرات

القوالب مطلوبة للرسالة الأولى في محادثة جديدة، أو أي رسالة تُرسَل خارج نافذة الخدمة لـ 24 ساعة. تُعرَّف القوالب في WhatsApp Manager، وتعتمدها Meta، ويمكن أن تتضمن خانات متغيرات {{1}} {{2}}. استدعاء API الخاص بك يملأ هذه المتغيرات وقت الإرسال.

توقيت اعتماد القالب: قوالب المرافق البسيطة (تأكيدات الطلبات، تحديثات الشحن) عادةً تُعتمد خلال 1–24 ساعة. قوالب التسويق تستغرق 1–5 أيام عمل. يمكنك التحقق من حالة الاعتماد عبر اشتراك webhook message_template_status_update أو في WhatsApp Manager. القوالب ذات الحالة المرفوضة لا يمكن إرسالها — إرسال قالب غير APPROVED يُعيد خطأ 400.
Node.js
sendTemplate.js
async function sendTemplate(to, templateName, languageCode, variables = []) { const url = `https://graph.facebook.com/v21.0/${process.env.WA_PHONE_ID}/messages`; const body = { messaging_product: 'whatsapp', to, type: 'template', template: { name: templateName, language: { code: languageCode }, // مثلاً 'en', 'pt_BR', 'de' components: variables.length ? [{ type: 'body', parameters: variables.map(v => ({ type: 'text', text: v })), }] : [], }, }; const res = await fetch(url, { method: 'POST', headers: { 'Authorization': `Bearer ${process.env.WA_TOKEN}`, 'Content-Type': 'application/json', }, body: JSON.stringify(body), }); if (!res.ok) throw new Error(`Template send failed: ${await res.text()}`); return (await res.json()).messages[0].id; } // مثال: قالب "order_confirmation" مع نص الجسم {{1}}="order #1234" {{2}}="2h" await sendTemplate( '+15550001234', 'order_confirmation', 'en', ['order #1234', '2 hours'] );
Python
send_template.py
def send_template(to: str, template_name: str, language_code: str, variables: list = []) -> str: url = f"https://graph.facebook.com/v21.0/{os.environ['WA_PHONE_ID']}/messages" components = [] if variables: components.append({ "type": "body", "parameters": [{ "type": "text", "text": v } for v in variables], }) res = requests.post(url, headers={ "Authorization": f"Bearer {os.environ['WA_TOKEN']}", "Content-Type": "application/json", }, json={ "messaging_product": "whatsapp", "to": to, "type": "template", "template": { "name": template_name, "language": { "code": language_code }, "components": components, }, } ) res.raise_for_status() return res.json()["messages"][0]["id"] # الاستخدام send_template("+15550001234", "order_confirmation", "en", ["order #1234", "2 hours"])
PHP
send_template.php
function sendTemplate(string $to, string $templateName, string $langCode, array $variables = []): string { $url = "https://graph.facebook.com/v21.0/" . getenv('WA_PHONE_ID') . "/messages"; $components = []; if (!empty($variables)) { $components[] = [ 'type' => 'body', 'parameters' => array_map( fn($v) => ['type' => 'text', 'text' => $v], $variables ), ]; } $body = [ 'messaging_product' => 'whatsapp', 'to' => $to, 'type' => 'template', 'template' => [ 'name' => $templateName, 'language' => ['code' => $langCode], 'components' => $components, ], ]; $ch = curl_init($url); curl_setopt_array($ch, [ CURLOPT_POST => true, CURLOPT_POSTFIELDS => json_encode($body), CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => [ 'Authorization: Bearer ' . getenv('WA_TOKEN'), 'Content-Type: application/json', ], ]); $res = json_decode(curl_exec($ch), true); $status = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); if ($status !== 200) throw new RuntimeException(json_encode($res)); return $res['messages'][0]['id']; }

إرسال صورة أو مستند

رسائل الوسائط تشير إلى ملف إما عبر URL (يجب أن يكون الملف متاحاً علناً عبر HTTPS) أو عبر Media ID (يُحصل عليه بعد رفع الملف إلى نقطة وسائط Meta). الـ URL أبسط لمعظم حالات الاستخدام — يجلبه Cloud API ويحفظه في الذاكرة المؤقتة. الـ Media IDs أفضل للأصول التي تُعاد استخدامها كثيراً مثل صور المنتجات أو ملفات PDF ذات العلامة التجارية.

Node.js
sendMedia.js
// إرسال صورة عبر URL عام async function sendImage(to, imageUrl, caption = '') { return sendMedia(to, 'image', { link: imageUrl, caption }); } // إرسال مستند عبر URL عام async function sendDocument(to, docUrl, filename, caption = '') { return sendMedia(to, 'document', { link: docUrl, filename, caption }); } // مرسل وسائط عام — يعمل للصور والفيديو والصوت والمستندات async function sendMedia(to, type, mediaObj) { const res = await fetch( `https://graph.facebook.com/v21.0/${process.env.WA_PHONE_ID}/messages`, { method: 'POST', headers: { 'Authorization': `Bearer ${process.env.WA_TOKEN}`, 'Content-Type': 'application/json', }, body: JSON.stringify({ messaging_product: 'whatsapp', to, type, [type]: mediaObj, // { link, caption } أو { id, caption } }), } ); if (!res.ok) throw new Error(`Media send failed: ${await res.text()}`); return (await res.json()).messages[0].id; } // الاستخدام await sendImage('+15550001234', 'https://yourdomain.com/promo.jpg', 'Check out our new product! 🚀'); await sendDocument('+15550001234', 'https://yourdomain.com/invoice.pdf', 'invoice-2026.pdf');
Python
send_media.py
def send_media(to: str, media_type: str, media_obj: dict) -> str: url = f"https://graph.facebook.com/v21.0/{os.environ['WA_PHONE_ID']}/messages" res = requests.post(url, headers={ "Authorization": f"Bearer {os.environ['WA_TOKEN']}", "Content-Type": "application/json", }, json={ "messaging_product": "whatsapp", "to": to, "type": media_type, media_type: media_obj, # مثلاً {"link": url, "caption": "..."} } ) res.raise_for_status() return res.json()["messages"][0]["id"] def send_image(to: str, url: str, caption: str = "") -> str: return send_media(to, "image", { "link": url, "caption": caption }) def send_document(to: str, url: str, filename: str, caption: str = "") -> str: return send_media(to, "document", { "link": url, "filename": filename, "caption": caption })
PHP
send_media.php
function sendMedia(string $to, string $type, array $mediaObj): string { $url = "https://graph.facebook.com/v21.0/" . getenv('WA_PHONE_ID') . "/messages"; $body = [ 'messaging_product' => 'whatsapp', 'to' => $to, 'type' => $type, $type => $mediaObj, // ['link' => url, 'caption' => '...'] ]; $ch = curl_init($url); curl_setopt_array($ch, [ CURLOPT_POST => true, CURLOPT_POSTFIELDS => json_encode($body), CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => [ 'Authorization: Bearer ' . getenv('WA_TOKEN'), 'Content-Type: application/json', ], ]); $res = json_decode(curl_exec($ch), true); $status = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); if ($status !== 200) throw new RuntimeException(json_encode($res)); return $res['messages'][0]['id']; } // الاستخدام sendMedia('+15550001234', 'image', ['link' => 'https://yourdomain.com/img.jpg', 'caption' => 'New product!']); sendMedia('+15550001234', 'document', ['link' => 'https://yourdomain.com/invoice.pdf', 'filename' => 'invoice.pdf']);

إرسال رسالة تفاعلية بأزرار

رسائل الأزرار التفاعلية تتيح للعملاء الرد بنقرة بدلاً من الكتابة. الحد الأقصى 3 أزرار لكل رسالة. عناوين الأزرار محدودة بـ 20 حرفاً. عندما ينقر العميل زراً، يستقبل webhook الخاص بك رسالة من نوع interactive بقيمة id الزر في msg.interactive.button_reply.id.

Node.js
sendButtons.js
async function sendButtons(to, bodyText, buttons) { // buttons: [{ id: 'btn_yes', label: 'Yes' }, { id: 'btn_no', label: 'No' }] const res = await fetch( `https://graph.facebook.com/v21.0/${process.env.WA_PHONE_ID}/messages`, { method: 'POST', headers: { 'Authorization': `Bearer ${process.env.WA_TOKEN}`, 'Content-Type': 'application/json', }, body: JSON.stringify({ messaging_product: 'whatsapp', to, type: 'interactive', interactive: { type: 'button', body: { text: bodyText }, action: { buttons: buttons.map(b => ({ type: 'reply', reply: { id: b.id, title: b.label.slice(0, 20) }, // حد 20 حرفاً })), }, }, }), } ); if (!res.ok) throw new Error(`Button send failed: ${await res.text()}`); return (await res.json()).messages[0].id; } // الاستخدام await sendButtons( '+15550001234', 'Would you like a callback from our team?', [ { id: 'yes_callback', label: 'Yes, call me!' }, { id: 'no_thanks', label: 'No thanks' }, ] );
Python
send_buttons.py
def send_buttons(to: str, body_text: str, buttons: list) -> str: # buttons: [{"id": "btn_yes", "label": "Yes"}, ...] حد أقصى 3 أزرار url = f"https://graph.facebook.com/v21.0/{os.environ['WA_PHONE_ID']}/messages" res = requests.post(url, headers={ "Authorization": f"Bearer {os.environ['WA_TOKEN']}", "Content-Type": "application/json", }, json={ "messaging_product": "whatsapp", "to": to, "type": "interactive", "interactive": { "type": "button", "body": { "text": body_text }, "action": { "buttons": [ { "type": "reply", "reply": { "id": b["id"], "title": b["label"][:20] }} for b in buttons ] }, }, } ) res.raise_for_status() return res.json()["messages"][0]["id"]
PHP
send_buttons.php
function sendButtons(string $to, string $bodyText, array $buttons): string { $url = "https://graph.facebook.com/v21.0/" . getenv('WA_PHONE_ID') . "/messages"; $btns = array_map(fn($b) => [ 'type' => 'reply', 'reply' => ['id' => $b['id'], 'title' => mb_substr($b['label'], 0, 20)], ], $buttons); $body = [ 'messaging_product' => 'whatsapp', 'to' => $to, 'type' => 'interactive', 'interactive' => [ 'type' => 'button', 'body' => ['text' => $bodyText], 'action' => ['buttons' => $btns], ], ]; $ch = curl_init($url); curl_setopt_array($ch, [ CURLOPT_POST => true, CURLOPT_POSTFIELDS => json_encode($body), CURLOPT_RETURNTRANSFER => true, CURLOPT_HTTPHEADER => [ 'Authorization: Bearer ' . getenv('WA_TOKEN'), 'Content-Type: application/json', ], ]); $res = json_decode(curl_exec($ch), true); $status = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); if ($status !== 200) throw new RuntimeException(json_encode($res)); return $res['messages'][0]['id']; }

إرسال موقع

رسائل الموقع تُعرض كدبوس خريطة في WhatsApp مع اسم وعنوان اختياريين تحته. يمكن للعملاء النقر لفتحه في تطبيق الخرائط لديهم. لا حاجة لـ URL أو media ID — فقط الإحداثيات.

الإرسال المجمّع: حدود المعدل والنمط الصحيح

تسمح WhatsApp Cloud API بـ 80 رسالة في الثانية لكل رقم هاتف افتراضياً. بهذا المعدل، يستغرق إرسال 10,000 رسالة حوالي دقيقتين. دون تحديد للمعدل، تستنفد حلقة ساذجة الحد على الفور تقريباً وتبدأ في الحصول على أخطاء 429 في منتصف الحملة. النمط الصحيح: أضف تأخيراً ثابتاً بين الإرسالات ونفّذ تراجعاً أسياً على 429.

Node.js — مرسل مجمّع مع تحديد المعدل
bulkSend.js
const DELAY_MS = 20; // 20 مللي ثانية بين الإرسالات = 50 رسالة/ث — آمن تحت حد 80 رسالة/ث const MAX_RETRIES = 4; async function sleep(ms) { return new Promise(r => setTimeout(r, ms)); } async function sendWithRetry(to, message, attempt = 0) { try { return await sendText(to, message); } catch (err) { const is429 = err.message.includes('429'); if (!is429 || attempt >= MAX_RETRIES) throw err; const waitMs = Math.min(1000 * 2 ** attempt + Math.random() * 500, 60000); console.warn(`Rate limited — waiting ${Math.round(waitMs)}ms (attempt ${attempt + 1})`); await sleep(waitMs); return sendWithRetry(to, message, attempt + 1); } } async function bulkSend(contacts, messageBody) { const results = { sent: 0, failed: [] }; for (const { phone, name } of contacts) { try { const personalised = messageBody.replace('{{name}}', name); await sendWithRetry(phone, personalised); results.sent++; } catch (err) { results.failed.push({ phone, error: err.message }); } await sleep(DELAY_MS); // تباعد لتحديد المعدل } console.log(`Sent: ${results.sent}, Failed: ${results.failed.length}`); return results; } // الاستخدام await bulkSend( [{ phone: '+15550001234', name: 'Alice' }, { phone: '+15550005678', name: 'Bob' }], 'Hi {{name}}, your order is ready! 🎉' );

معالجة الأخطاء: ماذا يعني كل رمز حالة

HTTP Statusالسبب الشائعالحل
200 OKقبلت Meta الرسالة — لم تُسلَّم بعدخزّن wamid المُعاد واستمع إلى webhooks حالة التسليم
400 Bad RequestJSON غير صالح، حقل مطلوب مفقود، قالب غير معتمد، عدم تطابق عدد متغيرات القالبتحقق من جسم استجابة الخطأ — تعيد Meta error.message مفصّلاً يشرح الحقل أو القيد بالضبط
401 Unauthorizedرمز وصول غير صالح أو منتهي؛ ترويسة Authorization مفقودةأعد توليد رمز System User دائم. لا تستخدم أبداً رموز مستخدم مؤقتة في الإنتاج — تنتهي بعد 60 يوماً
404 Not FoundPhone Number ID خاطئ في الـ URL؛ الرقم غير مسجّل على Cloud APIتحقق من Phone Number ID في Meta Developer Dashboard ← WhatsApp ← Phone Numbers. تأكد أن الرقم مسجّل وموثّق.
429 Too Many Requestsتجاوز حد 80 رسالة/ث، أو حد معدل استدعاء APIنفّذ تراجعاً أسياً مع jitter. أضف تأخير 15–20 مللي ثانية بين الإرسالات في العمليات المجمّعة. لا تعد المحاولة فوراً.
460 (Meta داخلي)رقم المستلم غير مسجّل على WhatsAppرقم الهاتف ليس مستخدم WhatsApp. أزله من قائمتك. هذا ليس رقماً قابلاً للتسليم.
131026الرسالة غير قابلة للتسليم — قيود على حساب WhatsApp للمستلمقد يكون المستلم قد حظر رقمك أو حسابه مقيّد. سجّل وتجاوز.
500 / 503عطل في بنية Meta أو خطأ مؤقتأعد المحاولة بتراجع أسي. تحقق من metastatus.com للأحداث النشطة. لا تعد المحاولة أكثر من 3 مرات.

فئة عميل WhatsApp كاملة (Node.js)

الدوال أعلاه مُجمّعة في فئة قابلة لإعادة الاستخدام مع منطق إعادة محاولة مدمج، ومعالجة أخطاء متّسقة، وتكوين قائم على البيئة:

Node.js
WhatsAppClient.js
class WhatsAppClient { constructor({ phoneId = process.env.WA_PHONE_ID, token = process.env.WA_TOKEN, version = 'v21.0', } = {}) { this.baseUrl = `https://graph.facebook.com/${version}/${phoneId}/messages`; this.headers = { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json', }; } async #send(payload) { const res = await fetch(this.baseUrl, { method: 'POST', headers: this.headers, body: JSON.stringify({ messaging_product: 'whatsapp', ...payload }), }); if (!res.ok) { const err = await res.json(); throw Object.assign(new Error(err?.error?.message ?? 'WhatsApp API error'), { code: err?.error?.code, status: res.status, }); } return (await res.json()).messages[0].id; } text(to, body) { return this.#send({ to, type: 'text', text: { body } }); } image(to, link, caption = '') { return this.#send({ to, type: 'image', image: { link, caption } }); } document(to, link, filename, caption = '') { return this.#send({ to, type: 'document', document: { link, filename, caption } }); } location(to, lat, lng, name = '', address = '') { return this.#send({ to, type: 'location', location: { latitude: lat, longitude: lng, name, address } }); } buttons(to, bodyText, buttons) { return this.#send({ to, type: 'interactive', interactive: { type: 'button', body: { text: bodyText }, action: { buttons: buttons.map(b => ({ type: 'reply', reply: { id: b.id, title: b.label.slice(0, 20) } })) }, }}); } template(to, name, lang, variables = []) { return this.#send({ to, type: 'template', template: { name, language: { code: lang }, components: variables.length ? [{ type: 'body', parameters: variables.map(v => ({ type: 'text', text: v })) }] : [], }}); } } // الاستخدام const wa = new WhatsAppClient(); await wa.text('+15550001234', 'Hello! 👋'); await wa.template('+15550001234', 'order_shipped', 'en', ['#1234']); await wa.buttons('+15550001234', 'Rate your experience:', [{ id: 'great', label: 'Great! 🌟' }, { id: 'poor', label: 'Could be better' }]); module.exports = WhatsAppClient;

النصف الآخر: استقبال الردود مع SocialHook

إرسال الرسائل ليس سوى نصف الصورة. عندما يرد عميلك، تطلق WhatsApp Cloud API webhook إلى خادمك — لكنك تحتاج نقطة وصول HTTPS قابلة للوصول علناً لاستقباله، بالإضافة إلى التحقق من توقيع HMAC-SHA256، واستخراج الحمولة المتداخلة، ومعالجة إعادة المحاولة.

SocialHook يتولى طبقة الوارد بأكملها. اربط رقم WhatsApp الخاص بك بـ SocialHook، الصق رابط خادمك كوجهة، وتصل كل ردود العملاء كأحداث JSON مطبّعة — متحقق منها، مستخرجة من غلاف Meta المتداخل، ومُعاد توجيهها إلى نقطتك في أقل من 50 مللي ثانية. نفس التنسيق المسطّح يعمل لـ Facebook Messenger وInstagram DMs أيضاً.

الإعداد الكامل: يستخدم خادمك WhatsAppClient أعلاه للصادر، يسلّم SocialHook الأحداث الواردة إلى معالج webhook الخاص بك. اتجاهان، 50 دولاراً شهرياً ثابتة. انظر دليل webhook الوارد الكامل أو ابدأ بـ البدء السريع في 5 دقائق.

أسئلة شائعة

كيف أرسل رسالة WhatsApp باستخدام Cloud API؟
POST إلى https://graph.facebook.com/v21.0/{PHONE_NUMBER_ID}/messages مع ترويسة Authorization: Bearer {ACCESS_TOKEN} وجسم JSON بـ messaging_product: "whatsapp"، to: "+E.164_number"، type: "text"، وtext: { body: "message" }. الكود الكامل لـ Node.js وPython وPHP في قسم الرسالة النصية أعلاه.
ما هو WhatsApp Phone Number ID وأين أجده؟
Phone Number ID هو معرّف رقمي لرقم WhatsApp Business المحدد لديك على Cloud API — مختلف عن رقم الهاتف الفعلي. أوجده في Meta Developer Dashboard ← WhatsApp ← Phone Numbers. يبدو كرقم من 15–16 رقماً. استخدمه في الـ URL: graph.facebook.com/v21.0/{PHONE_NUMBER_ID}/messages. لكل رقم هاتف معرّف واحد لا يتغير أبداً.
ما الفرق بين رسالة الجلسة ورسالة القالب؟
رسالة الجلسة (نص، صورة، أزرار، موقع، مستند) لا يمكن إرسالها إلا داخل نافذة الخدمة لـ 24 ساعة التي تفتح عندما يراسلك العميل أولاً. هذه مجانية ضمن الحصة الشهرية. رسالة القالب هي صيغة معتمدة من Meta مطلوبة لبدء محادثات جديدة أو الإرسال خارج نافذة الخدمة. يجب أن تُعتمد القوالب (1–24 ساعة للمرافق، حتى 5 أيام للتسويق) قبل أن تتمكن من إرسالها.
ماذا يحدث عندما أحصل على 429 من WhatsApp Cloud API؟
لقد بلغت حد المعدل (80 رسالة/ث افتراضياً). نفّذ تراجعاً أسياً: انتظر 1000 * 2^attempt + random(500) مللي ثانية قبل إعادة المحاولة، بحد أقصى 60 ثانية. أضف jitter (المكون العشوائي) لمنع المحاولات المتزامنة من عدة عمّال. للحملات المجمّعة، أضف تأخير ثابت 15–20 مللي ثانية بين الإرسالات للبقاء بأمان تحت الحد بدلاً من بلوغه وإعادة المحاولة.
كيف أرسل قالب WhatsApp مع متغيرات في Python؟
اضبط "type": "template" وضمّن مصفوفة components مع مكون body يحتوي على parameters — كائن واحد لكل متغير في قالبك. كل معامل هو {"type": "text", "text": "variable_value"}. تتطابق تسلسلياً مع {{1}}، {{2}}، {{3}} في قالبك. كود Python الكامل في قسم رسالة القالب أعلاه.
كيف أستقبل ردود رسائل WhatsApp من العملاء؟
تصل ردود العملاء عبر webhook — تطلق Meta طلب HTTP POST إلى نقطتك المسجّلة عند حدوث أي حدث رسالة. تحتاج URL HTTPS قابلاً للوصول علناً، والتحقق من توقيع HMAC-SHA256، وتحليل حمولة متداخلة. SocialHook يتولى كل هذا تلقائياً ويسلّم JSON نظيفاً إلى نقطتك في أقل من 50 مللي ثانية. انظر الإعداد الكامل في دليل webhook الوارد.

يمكنك الإرسال. الآن
استقبل الردود أيضاً.

كود الصادر لديك جاهز. اربط SocialHook للوارد — تصل كل ردود العملاء كـ JSON نظيف إلى نقطة webhook لديك. لا قوالب نمطية لـ HMAC، ولا تحليل حمولة متداخلة، ولا بنية إعادة محاولة لبنائها.

لا حاجة لبطاقة ائتمان · 50 دولاراً شهرياً بعد التجربة · إلغاء في أي وقت