انتقل إلى المحتوى
OmniChannels.ai
القائمة

إرسال رسالة واتساب عبر API: أمثلة cURL وNode وPython وPHP

كيف ترسل رسالة واتساب عبر API: أمثلة عملية بلغات cURL وNode.js وPython وPHP لقوالب الرسائل ورسائل الجلسة، مع تتبع الحالات ومعالجة الأخطاء بوضوح.

آخر تحديث 10 دقائق للقراءة

بقلم OmniChannels.ai Editorial Team · مراجعة BroadNet Messaging Solutions Team

التكامل

الإجابة المختصرة

مع واجهة OmniChannels.ai ترسل كل رسائل واتساب عبر نقطة نهاية واحدة، POST https://api.broadnet.me/whatsapp/message/sendbulk، بصيغة multipart form data مع ترويسة Authorization: Bearer. يحدد الحقل messageType الحمولة: TEMPLATE للقوالب المعتمدة التي تحتاجها لبدء محادثة أو للكتابة خارج نافذة 24 ساعة، وTEXT أو IMAGE أو INTERACTIVE للردود داخلها.

في هذه الصفحة
  1. كيف أرسل رسالة واتساب عبر الـ API؟
  2. قالب أم رسالة جلسة: أيهما أرسل؟
  3. كيف أرسل قالبًا معتمدًا؟
  4. ما حقول الطلب الأهم؟
  5. كيف أرسل قالبًا بزر أو رمز OTP؟
  6. كيف أرد داخل نافذة خدمة العملاء؟
  7. كيف أتتبع التسليم؟
  8. ما الأخطاء التي ينبغي معالجتها؟
  9. مثال تطبيقي: خدمة إشعارات الطلبات
  10. ما الأخطاء الشائعة؟
  11. كيف تساعدك OmniChannels.ai؟

أهم النقاط

  • تمر كل رسائل واتساب عبر POST /whatsapp/message/sendbulk؛ ويحدد messageType (TEMPLATE وTEXT وIMAGE وINTERACTIVE وغيرها) الحقول المطلوبة.
  • الطلب بصيغة multipart/form-data لا JSON، لذا تحتاج Python إلى files= وتحتاج PHP إلى جسم مصفوفة لتجنب الترميز بالعناوين (url-encoding).
  • خارج نافذة خدمة العملاء البالغة 24 ساعة لا يمكن إرسال سوى قالب معتمد؛ وداخلها يمكنك إرسال نص حر ووسائط ورسائل تفاعلية.
  • يضع الاستدعاء الرسائل في الطابور ويعيد batchId فورًا؛ وتصل حالات كل مستلم إلى webhook ومن نقطة نهاية bulk-insights.
  • لا يقبل الـ API مفتاح idempotency، لذا سجّل كل إرسال قبل تنفيذه وافحص الحالة بعد انتهاء المهلة بدل إعادة الإرسال.

هذا الدليل موجّه للمطورين الذين يدمجون إرسال واتساب في تطبيق. يعرض طلبات عاملة بلغات cURL وNode.js وPython وPHP، ويشرح الفرق بين رسائل القوالب ورسائل الجلسة، ويغطي التتبع والأخطاء. وكل نقطة نهاية وحقل مأخوذ من مرجع واتساب API ومواصفة OpenAPI لدينا.

كيف أرسل رسالة واتساب عبر الـ API؟

ترسل طلب POST موثّقًا واحدًا إلى https://api.broadnet.me/whatsapp/message/sendbulk مع حقول النموذج. يختار الحقل messageType نوع الرسالة، وتؤكد الاستجابة أن الرسائل وُضعت في الطابور.

العنصر القيمة
عنوان الأساس https://api.broadnet.me (دون بادئة /v1)
نقطة النهاية POST /whatsapp/message/sendbulk
المصادقة Authorization: Bearer $BROADNET_TOKEN
نوع المحتوى multipart/form-data (يضبطه عميل HTTP لديك تلقائيًا)
الاستجابة ملخص دفعة بصيغة JSON مع batchId

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

قالب أم رسالة جلسة: أيهما أرسل؟

أرسل قالبًا لبدء محادثة أو للكتابة خارج النافذة، ورسالة جلسة حين يكون العميل قد راسلك خلال آخر 24 ساعة. هذه قاعدة Meta وليست قاعدتنا.

رسالة قالب رسالة جلسة
messageType TEMPLATE TEXT وIMAGE وVIDEO وAUDIO وDOCUMENT وINTERACTIVE وغيرها
متى تُسمح في أي وقت بعد اعتماد القالب فقط أثناء فتح نافذة خدمة العملاء
تحتاج اعتمادًا نعم، من Meta لا
الاستخدام المعتاد تحديثات الطلبات وOTP والتذكيرات والحملات ردود الدعم وإجابات الأسئلة

تحتسب Meta رسومًا لكل رسالة مُسلَّمة بحسب الفئة، وقد تغيرت قواعدها لرسائل الخدمة وقوالب تحديثات المعاملات في 1 أكتوبر 2026. يغطي دليل النافذة الآليات، وتغطي صفحة الأسعار والحاسبة التكلفة.

كيف أرسل قالبًا معتمدًا؟

اضبط messageType=TEMPLATE، وسمِّ القالب ورمز لغته، ومرّر قيم المتغيرات. أنشئ batchId=0 لبدء دفعة جديدة.

curl -X POST https://api.broadnet.me/whatsapp/message/sendbulk \
  -H "Authorization: Bearer $BROADNET_TOKEN" \
  -F batchId=0 \
  -F campaignName=order-updates \
  -F destinationNo=971500000000 \
  -F messageType=TEMPLATE \
  -F templateName=order_update \
  -F templateLanguage=en_US \
  -F bodyTemplateVariables=INV-400
// Node.js 18+ (fetch وFormData مدمجان)
const form = new FormData();
form.append("batchId", "0");
form.append("campaignName", "order-updates");
form.append("destinationNo", "971500000000");
form.append("messageType", "TEMPLATE");
form.append("templateName", "order_update");
form.append("templateLanguage", "en_US");
form.append("bodyTemplateVariables", "INV-400");

const res = await fetch("https://api.broadnet.me/whatsapp/message/sendbulk", {
  method: "POST",
  headers: { Authorization: `Bearer ${process.env.BROADNET_TOKEN}` }, // يضبط fetch حد multipart
  body: form,
});
console.log(await res.json());
import os
import requests

fields = {
    "batchId": "0",
    "campaignName": "order-updates",
    "destinationNo": "971500000000",
    "messageType": "TEMPLATE",
    "templateName": "order_update",
    "templateLanguage": "en_US",
    "bodyTemplateVariables": "INV-400",
}

# أرسل كل حقل بوصفه جزء multipart (files=) لا مرمَّزًا بالعناوين (data=).
r = requests.post(
    "https://api.broadnet.me/whatsapp/message/sendbulk",
    headers={"Authorization": f"Bearer {os.environ['BROADNET_TOKEN']}"},
    files={k: (None, v) for k, v in fields.items()},
    timeout=30,
)
print(r.json())
<?php
$ch = curl_init("https://api.broadnet.me/whatsapp/message/sendbulk");
curl_setopt_array($ch, [
    CURLOPT_POST => true,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => ["Authorization: Bearer " . getenv("BROADNET_TOKEN")],
    // المصفوفة (لا النص) تجعل cURL يرسل multipart/form-data.
    CURLOPT_POSTFIELDS => [
        "batchId" => "0",
        "campaignName" => "order-updates",
        "destinationNo" => "971500000000",
        "messageType" => "TEMPLATE",
        "templateName" => "order_update",
        "templateLanguage" => "en_US",
        "bodyTemplateVariables" => "INV-400",
    ],
]);
echo curl_exec($ch);
curl_close($ch);

الوجهة هي رمز الدولة مع الرقم، أرقامًا فقط. يعود الاستدعاء فورًا بملخص دفعة:

{
  "totalFiles": 1,
  "totalSuccess": 1,
  "totalFailed": 0,
  "totalDuplicates": 0,
  "batchId": "2609091405000000001",
  "fileResults": [
    {
      "fileName": "direct",
      "totalRecords": 1,
      "successCount": 1,
      "failedRecipients": [],
      "duplicateRecipients": []
    }
  ],
  "message": "Messages queued for delivery"
}

خزّن batchId بجانب سجلك الخاص. «في الطابور» لا تعني «مُسلَّمة».

ما حقول الطلب الأهم؟

تعتمد الحقول المطلوبة على messageType. هذه هي الشائعة.

الحقل مطلوب الوصف
messageType نعم TEXT أو IMAGE أو VIDEO أو AUDIO أو DOCUMENT أو STICKER أو LOCATION أو CONTACTS أو TEMPLATE أو INTERACTIVE أو REACTION أو FLOW
destinationNo أو destinationFiles أحدهما أرقام مفصولة بفواصل أو فواصل منقوطة أو أسطر جديدة؛ أو ملف TXT أو CSV أو XLSX
batchId لا 0 يبدأ دفعة جديدة
campaignName لا تسميتك للتقارير
allowDuplicate لا false يزيل المستلمين المكررين
templateName وtemplateLanguage لـ TEMPLATE اسم القالب المعتمد ورمز اللغة، مثل en_US أو ar
bodyTemplateVariables بحسب القالب قيمة متغير النص الأساسي؛ وتُمرَّر المعاملات المسماة بصيغة JSON
buttonsTemplateVariable بحسب القالب قيمة الزر الديناميكي: لاحقة الرابط أو رمز القسيمة أو رمز OTP
content لـ TEXT نص الرسالة حتى 4,096 حرفًا، أو تعليق للوسائط
mediaUrl بحسب النوع رابط HTTPS عام للوسائط
interactivePayload لـ INTERACTIVE كائن Meta التفاعلي نص JSON

تستخدم الجدولة scheduled وscheduleTime وgmt، ويخنق delay التسليم. القائمة الكاملة في مرجع واتساب API.

كيف أرسل قالبًا بزر أو رمز OTP؟

أضف قيمة الزر في buttonsTemplateVariable. وفي قالب مصادقة بزر نسخ الرمز، مرّر الرمز في حقلي النص والزر معًا.

curl -X POST https://api.broadnet.me/whatsapp/message/sendbulk \
  -H "Authorization: Bearer $BROADNET_TOKEN" \
  -F batchId=0 \
  -F destinationNo=971500000000 \
  -F messageType=TEMPLATE \
  -F templateName=login_code \
  -F templateLanguage=en_US \
  -F bodyTemplateVariables=482913 \
  -F buttonsTemplateVariable=482913

هنا login_code عنصر نائب لقالب المصادقة المعتمد الخاص بك. ولأزرار متعددة يقبل buttonsTemplateVariable مصفوفة JSON. ولّد الرمز على خادمك، وخزّنه مجزّأً مع انتهاء صلاحية، ولا تسجله أبدًا. ويغطي دليل OTP التسليم بالنقرة الواحدة وبلا نقرات ونسخ الرمز.

كيف أرد داخل نافذة خدمة العملاء؟

استخدم نوع رسالة جلسة. يحتاج الرد النصي العادي إلى messageType=TEXT وcontent.

curl -X POST https://api.broadnet.me/whatsapp/message/sendbulk \
  -H "Authorization: Bearer $BROADNET_TOKEN" \
  -F batchId=0 \
  -F destinationNo=971500000000 \
  -F messageType=TEXT \
  -F campaignName=support \
  -F "content=Your order has shipped. Reply here if you need anything."

لأزرار الرد، أرسل messageType=INTERACTIVE وinteractivePayload يتبع صيغة الرسالة التفاعلية لدى Meta.

curl -X POST https://api.broadnet.me/whatsapp/message/sendbulk \
  -H "Authorization: Bearer $BROADNET_TOKEN" \
  -F batchId=0 \
  -F destinationNo=971500000000 \
  -F messageType=INTERACTIVE \
  -F campaignName=support \
  -F 'interactivePayload={"type":"button","body":{"text":"Confirm your delivery slot?"},"action":{"buttons":[{"type":"reply","reply":{"id":"slot_ok","title":"Confirm"}},{"type":"reply","reply":{"id":"slot_change","title":"Change"}}]}}'

لتعليم رسالة واردة مقروءة، وإظهار مؤشر الكتابة اختياريًا، استدعِ POST /whatsapp/message/read بصيغة JSON:

curl -X POST https://api.broadnet.me/whatsapp/message/read \
  -H "Authorization: Bearer $BROADNET_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "messageId": "wamid.HBgMOTcxNTAwMDAwMDAwFQIAEhgg", "typing": true }'

راجع دليلنا عن الرسائل التفاعلية لإرشادات التصميم.

كيف أتتبع التسليم؟

تُدفع الحالات إلى webhook المضبوط على حسابك ويمكن قراءتها أيضًا لكل دفعة. ينتقل كل مستلم عبر SUBMITTED وSENT وDELIVERED وREAD، أو ينتهي بـ FAILED أو REJECTED مع السبب.

curl "https://api.broadnet.me/whatsapp/message/bulk-insights?batch_Id=2609091405000000001&status=FAILED&page=0&size=50" \
  -H "Authorization: Bearer $BROADNET_TOKEN"

batch_Id مطلوب؛ وstatus وdestination وsearch وpage وsize اختيارية، وpage يبدأ من الصفر. استخدم الاستعلام الدوري شبكة أمان للأحداث الفائتة، وابنِ مستقبِلك كما في دليل webhooks. ويمكن أيضًا إيقاف الدفعات مؤقتًا واستئنافها وإلغاؤها بنقاط نهاية الدفعات في المرجع.

ما الأخطاء التي ينبغي معالجتها؟

اقرأ حالة HTTP أولًا، ثم جسم الخطأ. يطلق الـ API الأخطاء في جسم JSON من خمسة حقول، وقد تأتي إخفاقات واتساب الخاصة من Meta.

الحالة المعنى الإجراء
400 خطأ تحقق، كحقل ناقص خاص بالنوع أو وجهة غير صالحة أصلح الطلب؛ ولا تعد المحاولة دون تغيير
401 / 403 رمز مفقود أو غير صالح، أو عملية غير مسموحة أصلح الرمز أو اطلب منا تفعيل العملية
404 القالب أو المرسل غير موجود تحقق من اسم القالب ولغته
413 الملف المرفوع كبير جدًا قلّل حجم الملف
429 حد المعدل انتظر Retry-After
502 رفضت Meta الاستدعاء؛ ويحمل message رمز خطأ Meta ونصه اقرأه؛ ولا تعد المحاولة إلا إن كان عابرًا
500 و503 و504 مشكلة في الخادم أو المنبع أعد المحاولة بتراجع أسّي وتشويش

يشرح دليل رموز الأخطاء لدينا رموز Meta الشائعة. ولأنه لا يوجد مفتاح idempotency، اتبع خطوات الحماية من التكرار في الأخطاء والحدود: اكتب سجلًا معلقًا أولًا، وخزّن batchId العائد، وبعد انتهاء المهلة افحص الحالة قبل الإرسال مجددًا.

مثال تطبيقي: خدمة إشعارات الطلبات

ترسل «سوق رفيق» (اسم افتراضي)، وهي متجر تجزئة في الإمارات، قالب order_update عند شحن الطلب.

  1. تكتب خدمة الطلبات صفًا بالمفتاح order-8842-shipped وحالته pending.
  2. تستدعي sendbulk مع القالب ورقم الطلب في bodyTemplateVariables.
  3. عند 200 تخزّن batchId وتعلّم الصف accepted.
  4. يحدّث معالج webhook الصف إلى DELIVERED أو READ، أو FAILED مع السبب.
  5. إذا ردّ العميل، تستخدم أداة الدعم رسالة جلسة TEXT داخل النافذة.
  6. تقرأ مهمة ليلية bulk-insights لدفعات الأمس وتطابق أي حالات مفقودة.

ما الأخطاء الشائعة؟

  • إرسال JSON. نقطة نهاية إرسال واتساب بصيغة multipart؛ ولن ينجح Content-Type: application/json.
  • استخدام data= في Python بدل files=، فيُرمَّز النموذج بالعناوين.
  • نص حر خارج النافذة، وهذا يفشل. استخدم قالبًا.
  • رمز لغة خاطئ، مثل en بدل en_US الخاص بالقالب.
  • اعتبار 200 تسليمًا. إنها تعني الوضع في الطابور.
  • إعادة محاولة عمياء بعد انتهاء المهلة، فقد تراسل العميل مرتين.
  • الرمز في شيفرة العميل. استدعِ الـ API من خلفيتك فقط.
  • الحدود: تختلف تفاصيل الحمولة بحسب القالب. أكّد تخطيط المتغيرات لأول حملة مخصصة مع فريقنا.

كيف تساعدك OmniChannels.ai؟

BroadNet مزوّد حلول أعمال رسمي لدى Meta، ويستخدم الإعداد في واتساب للأعمال API مسار Meta Embedded Signup؛ يجهّز فريقنا التسجيل معك، وتبقى الاعتمادات لدى Meta. واجهة REST موثّقة بمواصفة OpenAPI 3.1 وSDK بلغة TypeScript هو @broadnet/cpaas-sdk، وتُوحَّد حالات التسليم عبر القنوات. ابدأ من وثائق واتساب API أو البدء السريع.

الأسئلة الشائعة

هل أرسل رسائل واتساب بصيغة JSON أم form data؟

form data. تقبل نقطة نهاية إرسال واتساب، POST /whatsapp/message/sendbulk، الصيغة multipart/form-data، وكل حقل جزء في النموذج. أما الإرسال الفردي لـ SMS فيستخدم JSON، وهذا مصدر ارتباك شائع. في Python أرسل الحقول عبر files= لا data=، وفي PHP مرّر مصفوفة بوصفها الجسم ليبني cURL الصيغة multipart.

هل يمكنني إرسال رسالة واتساب دون قالب؟

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

كيف أعرف هل سُلّمت الرسالة؟

يؤكد استدعاء الإرسال فقط أن الرسائل وُضعت في الطابور ويعيد batchId. وتنتقل حالات كل مستلم عبر SUBMITTED وSENT وDELIVERED وREAD، أو تنتهي بـ FAILED أو REJECTED. تُدفع إلى webhook الخاص بك، ويمكنك أيضًا قراءتها لكل دفعة من نقطة نهاية bulk-insights.

هل يمكنني الإرسال إلى مستلمين كثيرين في طلب واحد؟

نعم. يقبل destinationNo عدة أرقام مفصولة بفواصل أو فواصل منقوطة أو أسطر جديدة، ويقبل destinationFiles ملف TXT أو CSV أو XLSX. ولقالب بمتغيرات مختلفة لكل مستلم، ارفع ملفًا مخصصًا بصف لكل مستلم. اضبط allowDuplicate على false لإزالة الأرقام المكررة.

هل يوجد مفتاح idempotency لمنع الإرسال المزدوج؟

لا. لا يقبل الـ API مفتاح idempotency. وإذا انتهت مهلة طلب، لا يمكنك أن تعرف من جانب العميل هل قُبل. سجّل كل إرسال في قاعدة بياناتك قبل الاستدعاء، وخزّن batchId العائد، وافحص الحالة أو قائمة الدفعات قبل أي إعادة محاولة.

هل أحتاج إلى موافقة اشتراك قبل الإرسال؟

نعم. تشترط سياسة Meta أن يكون كل مستلم قد وافق على تلقي رسائل من نشاطك، ويجب اعتماد القوالب قبل استخدامها. لا تتحقق الواجهة من الموافقة نيابةً عنك. التقط الموافقة من المصدر، واحتفظ بالدليل، واكبت من يلغي اشتراكه.

المصادر

  1. سياسة المراسلة التجارية في واتساب
  2. الأسعار على منصة واتساب للأعمال — Meta for Developers
  3. RFC 7578: إرجاع قيم النماذج: multipart/form-data