إنتقل إلى المحتوى الرئيسي

توثيق Bulk Template Message API — v2

تتيح لكم واجهة API هذه إرسال رسائل القوالب إلى عدة مستلمين في وقت واحد عبر قناة WhatsApp.

تُعالَج الرسائل بشكل غير متزامن؛ يعيد طلب API فوراً bulkOperationId، بينما تُوضع الرسائل في قائمة الانتظار وتُعالَج في الخلفية.

POST https://app.monochat.ai/api/:slug/custom-functions/bulk-message-api-app/api/v2/bulk-operation/send.js
صيغة الاستجابة

كل نقطة نهاية في هذا المستند هي دالة مخصّصة (custom function). يحمل جسم استجابة HTTP حقول الدالة نفسها (_id وtitle وpathString…)، أما الاستجابة الفعلية لنقطة النهاية فتوجد تحت result. تعرض أمثلة الاستجابات في هذا المستند محتوى result:

{
"_id": "function_id",
"title": "Show",
"pathString": "/bulk-message-api-app/api/v2/bulk-operation/show.js",
"result": {
"bulkOperation": { "_id": "abc123xyz789", "status": "running" }
}
}

الانتقال من v1​

يعمل v2 جنباً إلى جنب مع v1، لذا يمكنكم الانتقال وفق جدولكم الزمني. سيتم إيقاف نقاط نهاية v1 (/api/bulk-message/… و/api/bulk-message-records/…)؛ ويجب أن تستخدم عمليات التكامل الجديدة v2.

  1. انقلوا مسارات نقاط النهاية إلى v2: يصبح …/api/bulk-message/… هو …/api/v2/bulk-operation/…، ويصبح …/api/bulk-message-records/… هو …/api/v2/bulk-operation-items/…. لا يتغيّر جسم طلب send؛ إذ يقبل الطلب الواحد الآن ما يصل إلى 100,000 مستلم بدلاً من 5,000.
  2. أرسلوا bulkOperationId بدلاً من bulkMessageId في الطلبات.
  3. استبدلوا stats.js بـ show.js.
  4. اقرأوا الاستجابات بأسماء الحقول الجديدة الواردة في الجدول أدناه.

لا تعرف نقاط نهاية v2 إلا العمليات الجماعية التي أُنشئت باستخدام send في v2. ولتتبّع رسالة جماعية أُنشئت باستخدام v1 قبل انتقالكم، واصلوا استخدام نقاط نهاية v1 لها.

نقاط النهاية​

v1v2ما الذي يتغيّر في الاستجابة
bulk-message/send.jsv2/bulk-operation/send.jsيصبح { bulkMessageId } هو { bulkOperationId }
bulk-message/stats.jsv2/bulk-operation/show.jsيصبح { bulkMessage, stats } هو { bulkOperation }
bulk-message/message-stats.jsv2/bulk-operation/message-stats.jsتوجد العدّادات في الجذر بدلاً من messageStats
bulk-message/stop.jsv2/bulk-operation/stop.jsلا شيء
bulk-message-records/list.jsv2/bulk-operation-items/list.jsيصبح bulkMessageRecords هو bulkOperationItems
bulk-message-records/list-with-messages.jsv2/bulk-operation-items/list-with-messages.jsمثل list، ويحمل كل عنصر أيضاً session

أسماء الحقول​

v1v2
stats.successbulkOperation.progress.succeeded
stats.pending وstats.failed وstats.cancelled وstats.totalbulkOperation.progress.pending و.failed و.cancelled و.total
—bulkOperation.progress.unknown وbulkOperation.status وbulkOperation.result.outcome
bulkMessage (رسالة جماعية)bulkOperation (عملية جماعية)
bulkMessageRecord (سجل)bulkOperationItem (عنصر)
bulkMessageId في الطلبات وفي استجابة send وفي السجلاتbulkOperationId
username / userId / sessionId في السجل كما أُرسلتpayload.username / payload.userId / payload.sessionId
referenceId في السجلpayload.referenceId
payload في السجل (حمولة القالب الخاصة بالمستلم)payload.payload
userId وsessionId وmessageId في السجل بعد الإرسالresult.userId وresult.sessionId وresult.messageId
حالة السجل successsucceeded
errorMessage في السجلات الفاشلةerror.message، إلى جانب error.code وerror.retryable
—position (موضع المستلم في recipients)
المرشِّح {"status": "success"}{"status": "succeeded"}
المرشِّح {"referenceId": "…"}{"payload.referenceId": "…"}
أخطاء schema-error وinvalidRequest في sendzod-schema-error، مع مسار الحقل غير الصالح في الرسالة

الميزات الرئيسية​

  • إرسال رسائل قوالب جماعية إلى 1–100,000 مستلم في طلب واحد
  • متغيرات مخصّصة لكل مستلم (HEADER وBODY وBUTTONS وCAROUSEL)
  • defaultPayload مشترك لجميع المستلمين مع دمج payload الخاص بكل مستلم (isMerge)
  • إرسال مجدول (scheduleAt)
  • تحديد المستلمين بواسطة username (رقم الهاتف) أو userId أو sessionId
  • إرسال عدة رسائل إلى المستخدم نفسه ضمن طلب جماعي واحد
  • referenceId اختياري لتتبّع السجلات مع الأنظمة الخارجية
  • إسناد المحادثات تلقائياً إلى مستخدم أو مجموعة عمل بعد الإرسال (action)
تحذير

لا تستطيع واجهة API هذه إرسال إلا القوالب المعتمدة من Meta.

يجب أن يطابق اسم القالب ورمز اللغة تماماً القالب المسجَّل في Meta Business Manager.

معاملات الطلب​

المعاملات ذات المستوى الأعلى​

المعاملالنوعمطلوبالوصف
channelUsernamestringنعمرقم قناة WhatsApp المستخدم لإرسال الرسالة (مثل "908506669933")
connectorBrandstringنعمالعلامة التجارية لموصّل القناة. القيمة المدعومة حالياً: "whatsapp"
titlestringلاعنوان الحملة. يُستخدم للعرض في لوحة التحكم. القيمة الافتراضية: "-"
scheduleAtstring (ISO 8601)لاتاريخ ووقت الإرسال المجدول (مثل "2026-06-10T10:00:00.000Z"). إذا حُذف، تُرسل الرسائل فوراً.
defaultPayloadobjectمشروط*حمولة القالب الافتراضية المطبقة على جميع المستلمين. مطلوبة إذا لم يقدّم أحد المستلمين payload خاصاً به.
recipientsarrayنعمقائمة المستلمين. الحد الأدنى 1 والحد الأقصى 100,000 مستلم.
actionobjectلاإجراء يُطبَّق على المحادثة بعد الإرسال. assign-to-user أو assign-to-workgroup.

*إذا قدّم كل مستلم payload خاصاً به، فإن defaultPayload اختياري.

بنية المستلم​

يجب تقديم واحد فقط من username أو userId أو sessionId لكل مستلم. لا يمكن استخدام عدة معرّفات معاً، وسيؤدي حذفها جميعاً إلى خطأ.

لإرسال عدة رسائل إلى المستخدم نفسه ضمن طلب جماعي واحد، أضيفوا المعرّف نفسه إلى قائمة المستلمين عدة مرات.

الحقلالنوعالوصف
usernamestringرقم هاتف المستلم (مثل "905554443322"). إذا لم يكن المستخدم موجوداً في النظام، يُنشأ تلقائياً.
userIdstringمعرّف مستخدم موجود في النظام.
sessionIdstringمعرّف جلسة محادثة موجودة في النظام.
referenceIdstringمعرّف مرجعي اختياري (بحد أقصى 256 حرفاً) للمطابقة مع سجلات الأنظمة الخارجية (CRM أو الطلبات أو التذاكر وغيرها). يجب أن يكون فريداً ضمن الطلب الجماعي إن وُجد.
payloadobjectحمولة القالب الخاصة بالمستلم (اختيارية). إذا كان isMerge: true، فتُدمج مع defaultPayload.
isMergebooleanيتجاوز سلوك الدمج لهذا المستلم (اختياري). إذا حُذف، يُستخدم defaultPayload.isMerge.

بنية الإجراء​

الحقلالنوعالوصف
action.keystring"assign-to-user" يُسند المحادثة إلى موظف محدد؛ و"assign-to-workgroup" يُسندها إلى مجموعة عمل.
action.valuestringمعرّف المستخدم أو مجموعة العمل المستهدفة.

بنية حمولة القالب​

يشترك defaultPayload وpayload الخاص بالمستلم في البنية نفسها. في رسائل القوالب يجب تحديد type: "template".

{
"type": "template",
"template": {
"templateName": "order_confirmation",
"languageCode": "tr-TR",
"variables": []
},
"isMerge": true
}
الحقلالنوعمطلوبالوصف
typestringنعمنوع الحمولة. لرسائل القوالب: "template"
template.templateNamestringنعم*اسم القالب المسجَّل في Meta. اختياري في حمولات المستلمين عند استخدام isMerge: true (يُورَّث من الافتراضي).
template.languageCodestringلارمز لغة القالب (مثل "tr" أو "en" أو "tr-TR" أو "en-US"). يجب أن يطابق تماماً اللغة المسجَّلة في Meta.
template.variablesarrayلاقائمة المتغيرات المطبقة على مكوّنات القالب. مفصَّلة أدناه.
isMergebooleanلاtrue: تُدمج حمولة المستلم دمجاً عميقاً مع defaultPayload. false أو محذوف: تحل حمولة المستلم محل defaultPayload بالكامل.
سلوك isMerge
  • إذا كان defaultPayload.isMerge: true وقدّم المستلم payload خاصاً به، يُطبَّق دمج عميق.
  • مع الدمج العميق، يكفي أن يقدّم المستلم variables فقط؛ ويُورَّث templateName وlanguageCode من الحمولة الافتراضية.
  • يتجاوز حقل isMerge الخاص بالمستلم قيمة defaultPayload.isMerge.
  • إذا لم يقدّم المستلم payload، تُستخدم defaultPayload دائماً.

بنية المتغيرات​

يقابل كل عنصر في المصفوفة variables مكوّناً من مكوّنات القالب. لا يجوز أن يظهر نوع المكوّن (type) إلا مرة واحدة في المصفوفة.

typeالوصفparameterscards
"HEADER"مكوّن رأس القالب. متغير نصي أو رابط وسائط (صورة أو فيديو أو مستند)نعم—
"BODY"متغيرات النص الأساسي للقالبنعم—
"BUTTONS"متغيرات لاحقة الرابط الديناميكية للأزرارنعم—
"CAROUSEL"مكوّنات الشرائح لقوالب العرض الدوّار—نعم

صيغ المعاملات​

يمكن تقديم الحقل parameters بثلاث صيغ مختلفة:

// Format 1: Array (index-based) — for placeholders like {{1}}, {{2}}, {{3}}
"parameters": ["value1", "value2", "value3"]

// Format 2: Object (numeric keys) — alternative representation for {{1}}, {{2}}
"parameters": { "1": "value1", "2": "value2" }

// Format 3: Object (named keys) — for placeholders like {{name}}, {{amount}}
"parameters": { "name": "John", "amount": "150 USD" }
أي صيغة أستخدم؟
  • إذا كان قالب Meta لديكم يستخدم عناصر نائبة مثل {{1}} و{{2}}، فاستخدموا صيغة المصفوفة أو صيغة الكائن بمفاتيح رقمية.
  • إذا كان قالبكم يستخدم عناصر نائبة مسمّاة مثل {{firstName}} أو {{orderTotal}}، فاستخدموا صيغة الكائن بمفاتيح مسمّاة.
  • عند استخدام المصفوفات، الترتيب مهم: العنصر الأول يقابل {{1}} والثاني {{2}} وهكذا.

مكوّن HEADER​

استخدموا المكوّن HEADER عندما يحتوي رأس القالب على وسائط (صورة أو فيديو أو مستند) أو نص ديناميكي.

// Media header (image URL)
{
"type": "HEADER",
"parameters": ["https://example.com/product-image.jpg"]
}

// Text header variable
{
"type": "HEADER",
"parameters": ["Special Campaign"]
}

مكوّن BODY​

يُستخدم للمتغيرات النصية الديناميكية داخل النص الأساسي للقالب.

// Array format — when the template uses {{1}}, {{2}}, {{3}}
{
"type": "BODY",
"parameters": ["John", "ORD-12345", "150.00 USD"]
}

// Named format — when the template uses {{name}}, {{orderAmount}}
{
"type": "BODY",
"parameters": {
"name": "John",
"orderAmount": "150.00 USD"
}
}

مكوّن BUTTONS​

يُستخدم للأزرار ذات لاحقة الرابط الديناميكية. إذا احتوى القالب على عدة أزرار روابط، فلا تُفهرَس بالتسلسل إلا الأزرار التي فيها متغيرات (تُتجاهل الأزرار التي بلا متغيرات وأزرار FLOW).

// Single URL button suffix variable
{
"type": "BUTTONS",
"parameters": ["tracking/ORD-12345"]
}

// Multiple URL button suffix variables (first URL button, second URL button)
{
"type": "BUTTONS",
"parameters": ["tracking/ORD-12345", "cancel/ORD-12345"]
}

في قوالب العرض الدوّار، تُحدَّد متغيرات المكوّنات بشكل منفصل لكل شريحة.

{
"type": "CAROUSEL",
"cards": [
{
"components": [
{
"type": "HEADER",
"parameters": ["https://example.com/card1.jpg"]
},
{
"type": "BODY",
"parameters": ["Product A", "99.00 USD"]
}
]
},
{
"components": [
{
"type": "HEADER",
"parameters": ["https://example.com/card2.jpg"]
},
{
"type": "BODY",
"parameters": ["Product B", "149.00 USD"]
}
]
}
]
}
تحذير

يجب أن يطابق طول المصفوفة cards تماماً عدد الشرائح المعرَّفة في القالب.

أمثلة​

1. قالب بسيط — بلا متغيرات ومحتوى واحد لجميع المستلمين​

هذه أبسط طريقة لإرسال قالب ثابت بلا متغيرات إلى عدة مستلمين.

{
"channelUsername": "908506669933",
"connectorBrand": "whatsapp",
"title": "General Announcement",
"defaultPayload": {
"type": "template",
"template": {
"templateName": "hello_world",
"languageCode": "tr-TR"
}
},
"recipients": [{ "username": "905554443301" }, { "username": "905554443302" }, { "username": "905554443303" }]
}
curl --location 'https://app.monochat.ai/api/:slug/custom-functions/bulk-message-api-app/api/v2/bulk-operation/send.js' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer YOUR_JWT_TOKEN' \
--data '{
"channelUsername": "908506669933",
"connectorBrand": "whatsapp",
"title": "General Announcement",
"defaultPayload": {
"type": "template",
"template": {
"templateName": "hello_world",
"languageCode": "tr-TR"
}
},
"recipients": [
{ "username": "905554443301" },
{ "username": "905554443302" },
{ "username": "905554443303" }
]
}'
تلميح
  • يُنشأ المستلمون المحددون بواسطة username تلقائياً إذا لم يكونوا موجودين في النظام
  • يستخدم جميع المستلمين defaultPayload نفسه؛ ولا حاجة إلى بيانات خاصة بكل مستلم
  • عند عدم تحديد isMerge، يستخدم كل مستلم defaultPayload مباشرة

2. قالب بمتغيرات نص أساسي مشتركة​

يُرسل القالب نفسه إلى جميع المستلمين بقيم المتغيرات نفسها. يحتوي القالب على عناصر نائبة مثل {{1}} و{{2}}.

{
"channelUsername": "908506669933",
"connectorBrand": "whatsapp",
"title": "Summer Campaign",
"defaultPayload": {
"type": "template",
"template": {
"templateName": "promo_notification",
"languageCode": "tr-TR",
"variables": [
{
"type": "BODY",
"parameters": ["30%", "July 31, 2026"]
}
]
}
},
"recipients": [{ "username": "905554443301" }, { "username": "905554443302" }]
}
تلميح
  • في هذا المثال، قد يحتوي نص القالب الأساسي على محتوى مثل: "استمتعوا بخصم {{1}} في حملتنا! العرض ساري حتى {{2}}."
  • يحل parameters[0] محل {{1}}، بينما يحل parameters[1] محل {{2}}

3. قالب مخصّص — متغيرات لكل مستلم مع isMerge​

تُستخدم قيم متغيرات مختلفة لكل مستلم. بضبط isMerge: true في defaultPayload، يكفي أن يقدّم المستلمون variables فقط؛ ويُورَّث templateName وlanguageCode من الحمولة الافتراضية.

في هذا المثال، يتضمن القالب رأس وسائط ومتغيرات نص أساسي مخصّصة.

{
"channelUsername": "908506669933",
"connectorBrand": "whatsapp",
"title": "Personal Order Notification",
"defaultPayload": {
"type": "template",
"template": {
"templateName": "order_confirmation",
"languageCode": "tr-TR"
},
"isMerge": true
},
"recipients": [
{
"username": "905554443301",
"payload": {
"template": {
"variables": [
{
"type": "HEADER",
"parameters": ["https://s3.example.com/product-a.jpg"]
},
{
"type": "BODY",
"parameters": ["Ahmet", "ORD-001", "150.00 TRY"]
}
]
}
}
},
{
"username": "905554443302",
"payload": {
"template": {
"variables": [
{
"type": "HEADER",
"parameters": ["https://s3.example.com/product-b.jpg"]
},
{
"type": "BODY",
"parameters": ["Fatma", "ORD-002", "289.00 TRY"]
}
]
}
}
}
]
}
تلميح
  • بفضل isMerge: true، لا حاجة إلى تكرار templateName في حمولة كل مستلم
  • مصفوفة variables الخاصة بكل مستلم مستقلة تماماً
  • يجب أن يكون رابط وسائط الرأس متاحاً للعموم
  • إذا حُذف type في حمولة المستلم، يُورَّث defaultPayload.type

4. متغير زر رابط​

استخدموا المكوّن BUTTONS عندما يحتوي القالب على زر بلاحقة رابط ديناميكية. مثلاً رقم تتبّع يُلحَق بالرابط الأساسي https://example.com/track/.

{
"channelUsername": "908506669933",
"connectorBrand": "whatsapp",
"title": "Shipment Tracking Notification",
"defaultPayload": {
"type": "template",
"template": {
"templateName": "shipment_tracking",
"languageCode": "tr-TR"
},
"isMerge": true
},
"recipients": [
{
"username": "905554443301",
"payload": {
"template": {
"variables": [
{
"type": "BODY",
"parameters": ["Ahmet", "TK-98765"]
},
{
"type": "BUTTONS",
"parameters": ["TK-98765"]
}
]
}
}
},
{
"username": "905554443302",
"payload": {
"template": {
"variables": [
{
"type": "BODY",
"parameters": ["Recep", "TK-12345"]
},
{
"type": "BUTTONS",
"parameters": ["TK-12345"]
}
]
}
}
}
]
}
تلميح
  • تُطابَق معاملات BUTTONS بحسب ترتيب الأزرار التي تحتوي على متغيرات
  • تُتجاهل أزرار FLOW والأزرار التي بلا متغيرات؛ ولا تنطبق الفهرسة إلا على أزرار الروابط الديناميكية
  • إذا كان رابط زر القالب https://example.com/track/{{1}}، فإن parameters[0] يحل محل {{1}}

5. إرسال مجدول​

جدولوا إرسال رسالة في تاريخ ووقت مستقبليين. يجب تقديم scheduleAt بصيغة طابع زمني UTC وفق ISO 8601.

{
"channelUsername": "908506669933",
"connectorBrand": "whatsapp",
"title": "Morning Campaign Message",
"scheduleAt": "2026-06-10T07:00:00.000Z",
"defaultPayload": {
"type": "template",
"template": {
"templateName": "morning_campaign",
"languageCode": "en-US"
},
"isMerge": true
},
"action": {
"key": "assign-to-workgroup",
"value": "WORKGROUP_ID"
},
"recipients": [
{
"username": "905554443301",
"payload": {
"template": {
"variables": [
{
"type": "BODY",
"parameters": { "name": "Ahmet", "discountRate": "25" }
}
]
}
}
},
{
"username": "905554443302",
"payload": {
"template": {
"variables": [
{
"type": "BODY",
"parameters": { "name": "Zeynep", "discountRate": "40" }
}
]
}
}
}
]
}
تلميح
  • يجب تقديم scheduleAt بالمنطقة الزمنية UTC (مثلاً للساعة 10:00 صباحاً بتوقيت تركيا، استخدموا 07:00:00.000Z)
  • يستخدم هذا المثال صيغة المعاملات المسمّاة؛ ويجب أن يحتوي القالب على عناصر نائبة مثل {{name}} و{{discountRate}}
  • مع action، تُسند المحادثات التي أنشأها إرسال الرسائل تلقائياً إلى مجموعة العمل المحددة

الاستجابة​

يعيد الطلب الناجح bulkOperationId يمكن استخدامه لتتبّع عملية الإرسال:

{
"bulkOperationId": "abc123xyz789"
}

استجابات الأخطاء​

الحالةالوصف
recipients field is requiredلم يُرسَل الحقل recipients
Channel not foundلم يُعثر على قناة موثَّقة تطابق channelUsername وconnectorBrand
Channel is not verifiedالقناة المطابقة موجودة لكنها لم تُوثَّق بعد
zod-schema-errorفشل حقل في جسم الطلب في التحقق من المخطط (حقل مطلوب مفقود، أو نوع غير صحيح، أو قيمة غير مدعومة، أو أكثر من معرّف واحد لمستلم، أو payload مفقودة). تذكر الرسالة اسم الحقل، مثل recipients.0.referenceId: referenceId must be unique

يمكن استخدام bulkOperationId المُعاد مع نقاط النهاية أدناه للاستعلام عن إحصاءات الإرسال وإيقافه.


Show — حالة العملية الجماعية وإحصاءاتها​

يجلب العملية الجماعية مع حالتها الراهنة وعدّادات الإرسال الخاصة بعناصرها، تحت المفتاح bulkOperation.

POST https://app.monochat.ai/api/:slug/custom-functions/bulk-message-api-app/api/v2/bulk-operation/show.js

معاملات الطلب​

المعاملالنوعمطلوبالوصف
bulkOperationIdstringنعممعرّف العملية الجماعية المراد تتبّعها (يُعاد من send)
{
"bulkOperationId": "abc123xyz789"
}
curl --location 'https://app.monochat.ai/api/:slug/custom-functions/bulk-message-api-app/api/v2/bulk-operation/show.js' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer YOUR_JWT_TOKEN' \
--data '{
"bulkOperationId": "abc123xyz789"
}'

الاستجابة​

{
"bulkOperation": {
"_id": "abc123xyz789",
"type": "send-bulk-message",
"slug": "my-workspace",
"userId": "agent_user_id",
"payload": {
"title": "Campaign Title",
"channelUsername": "908506669933",
"connectorBrand": "whatsapp",
"connectorSlug": "om2WabVegaCloud",
"defaultLanguageCode": "tr-TR",
"sentUser": { "firstname": "John", "lastname": "Doe" },
"defaultPayload": {
"type": "template",
"template": { "templateName": "order_confirmation", "languageCode": "tr-TR" },
"isMerge": true
},
"source": { "type": "recipients", "bulkOperationInputGroupId": "group_id" }
},
"status": "running",
"result": { "outcome": "unknown", "hasErrors": false },
"progress": {
"total": 100,
"pending": 45,
"succeeded": 42,
"failed": 3,
"cancelled": 10,
"unknown": 0
},
"scheduleAt": "2026-06-10T07:00:00.000Z",
"createdAt": "2026-06-08T10:00:00.000Z",
"updatedAt": "2026-06-10T07:00:30.000Z",
"startedAt": "2026-06-10T07:00:05.000Z"
}
}

حقول Show​

توجد الحقول تحت bulkOperation.

الحقلالنوعالوصف
statusstringحالة العملية الجماعية: preparing أو scheduled أو pending أو running أو stopping أو stopped أو completed أو failed
progress.totalnumberإجمالي عدد العناصر
progress.pendingnumberالعناصر التي لا تزال تنتظر في القائمة
progress.succeedednumberالعناصر التي عُولجت بنجاح للإرسال
progress.failednumberالعناصر التي واجهت خطأ في الإرسال
progress.cancellednumberالعناصر التي أُلغيت بواسطة stop
progress.unknownnumberالعناصر التي تعذّر تحديد نتيجتها
result.outcomestringالنتيجة النهائية بعد انتهاء العملية الجماعية: success أو partial أو all-failed أو cancelled أو unknown
result.hasErrorsbooleantrue إذا فشل عنصر واحد على الأقل
scheduleAtstringوقت الإرسال المجدول (للعمليات الجماعية المجدولة فقط)
startedAt وcompletedAtstringوقت بدء الإرسال وانتهائه
ملاحظة

يشير progress.succeeded إلى أن النظام سلّم الرسالة بنجاح. وهو لا يضمن أن Meta سلّمت الرسالة إلى المستلم. أما تحديثات الحالة اللاحقة الصادرة عن Meta (مثل delivered أو read أو failed) فلا تؤثر في هذا العداد ولا تنعكس هنا.

Show مقابل Message Stats
  • نقطة النهاية show: تعرض حالة إرسال العناصر (pending وsucceeded وfailed وcancelled وunknown)
  • نقطة النهاية message-stats: تعرض حالة الرسالة الفعلية (pending وsending وsent وdelivered وread وerror وغيرها)
  • قد يكون العنصر succeeded بينما لا تكون الرسالة قد سُلّمت أو قُرئت بعد

المعرّف المرجعي​

referenceId حقل اختياري يمكنكم استخدامه لمطابقة عناصر الإرسال بمعرّف من نظامكم الخاص لأغراض التتبّع (مثل رقم الطلب أو معرّف التذكرة). ويُعاد في كل عنصر بوصفه payload.referenceId.

إذا قُدّم، يجب أن يكون فريداً ضمن الطلب الجماعي (بحد أقصى 256 حرفاً).

مهم
  • استخدامه غير مطلوب
  • لا يمكن تكراره ضمن العملية الجماعية نفسها
  • يمكن إعادة استخدامه عبر عمليات جماعية مختلفة

Message Stats — حالة رسائل WhatsApp​

يجلب إحصاءات حالة الرسائل لعملية جماعية. وعلى عكس نقطة النهاية show، تعرض هذه النقطة message.status الفعلي للرسائل المُرسَلة بدلاً من حالة العنصر.

حالات الرسائل الممكنة: pending وsending وsent وdelivered وread وdeleted وwarning وerror وunknown وnot-sended

POST https://app.monochat.ai/api/:slug/custom-functions/bulk-message-api-app/api/v2/bulk-operation/message-stats.js

معاملات الطلب​

المعاملالنوعمطلوبالوصف
bulkOperationIdstringنعممعرّف العملية الجماعية المراد الاستعلام عنها
{
"bulkOperationId": "abc123xyz789"
}
curl --location 'https://app.monochat.ai/api/:slug/custom-functions/bulk-message-api-app/api/v2/bulk-operation/message-stats.js' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer YOUR_JWT_TOKEN' \
--data '{
"bulkOperationId": "abc123xyz789"
}'

الاستجابة​

{
"pending": 5,
"sending": 2,
"sent": 10,
"delivered": 45,
"read": 30,
"deleted": 2,
"warning": 1,
"error": 3,
"unknown": 0,
"not-sended": 2,
"no-message": 20,
"total": 120
}

حقول Message Stats​

الحقلالنوعالوصف
pendingnumberرسائل لم تُرسل بعد
sendingnumberرسائل قيد الإرسال حالياً
sentnumberرسائل سُلّمت إلى WhatsApp ولم تصل بعد
deliverednumberرسائل وصلت إلى هاتف المستلم
readnumberرسائل قرأها المستلم
deletednumberرسائل محذوفة
warningnumberرسائل بها تحذيرات
errornumberرسائل بها أخطاء
unknownnumberرسائل بحالة غير معروفة
not-sendednumberرسائل تعذّر إرسالها
no-messagenumberعناصر بلا رسالة (لا تزال في القائمة، أو فشلت، أو أُلغيت)
totalnumberإجمالي عدد العناصر
نصائح الاستخدام
  • يشير ارتفاع عدد no-message أثناء كون العملية الجماعية في حالة running إلى أن الإرسال لا يزال جارياً
  • يبيّن عدد delivered نجاح وصول الرسائل
  • يمكن استخدام عدد read لقياس تفاعل الحملة
  • يمكنكم استعلام نقطة النهاية هذه دورياً للتتبّع الفوري

بنية Options — التقسيم إلى صفحات والتصفية والفرز​

يوفّر المعامل options المستخدم في نقطتي النهاية list وlist-with-messages بنية قياسية للتقسيم إلى صفحات والتصفية والفرز.

حقول Options​

الحقلالنوعمطلوبالوصف
paginationobjectلاإعدادات التقسيم إلى صفحات
filteringobjectلامعايير التصفية
sortingobjectلاإعدادات الفرز (مثل {"position": 1})

بنية التقسيم إلى صفحات​

إذا لم يُرسَل pagination، تُعاد الصفحة الأولى بما يصل إلى 50 عنصراً. وإذا أُرسل، يكون currentPage مطلوباً.

الحقلالنوعالافتراضيالوصف
currentPagenumber—رقم الصفحة المراد جلبها (مطلوب عند إرسال pagination)
pageItemsnumber50عدد العناصر في الصفحة (الحد الأقصى: 50)

بنية التصفية​

تتم التصفية بصيغة استعلام MongoDB على حقول العنصر، باستخدام أسماء الحقول كما تظهر في الاستجابة تماماً (مثل status وpayload.referenceId وresult.messageId). وفي نقطة النهاية list-with-messages يمكنكم أيضاً التصفية بحسب حقول الرسالة (مثل message.status).

// Filter by item status
{
"options": {
"filtering": {
"status": "succeeded"
}
}
}

// Filter by referenceId
{
"options": {
"filtering": {
"payload.referenceId": "ORDER-12345"
}
}
}

// Filter by message status (only list-with-messages)
{
"options": {
"filtering": {
"message.status": "delivered"
}
}
}

// Filter by multiple statuses using $in (MongoDB operator)
{
"options": {
"filtering": {
"message.status": {
"$in": ["delivered", "read"]
}
}
}
}

// Exclude specific statuses using $nin (MongoDB operator)
{
"options": {
"filtering": {
"message.status": {
"$nin": ["error", "not-sended"]
}
}
}
}

// List items that have no message (only list-with-messages)
{
"options": {
"filtering": {
"message": {
"$exists": false
}
}
}
}

بنية الفرز​

يتم الفرز بصيغة فرز MongoDB. تعني 1 تصاعدياً و-1 تنازلياً. وposition هو ترتيب المستلم في المصفوفة recipients في الطلب (بدءاً من 0).

// Sort in the order the recipients were sent in the request
{
"options": {
"sorting": {
"position": 1
}
}
}

// Sort by multiple fields
{
"options": {
"sorting": {
"status": 1,
"position": 1
}
}
}

مثال على الاستخدام المركّب​

{
"bulkOperationId": "abc123xyz789",
"options": {
"pagination": {
"currentPage": 2,
"pageItems": 50
},
"filtering": {
"message.status": "delivered"
},
"sorting": {
"position": 1
}
}
}

يعرض هذا المثال الصفحة الثانية من الرسائل المُسلَّمة بترتيب المستلمين.

نصائح عملية
  • ادمجوا filtering مع pagination للاستعلامات المستهدفة
  • تتضمن الاستجابة options.pagination.totalCount وoptions.pagination.totalPages للتنقّل
  • لا يعمل مرشِّح message.status إلا في نقطة النهاية list-with-messages

Items — تفاصيل العناصر وعرضها​

يعرض جميع عناصر الإرسال لعملية جماعية. يمثل كل عنصر إدخالاً واحداً من المصفوفة recipients.

List — قائمة العناصر​

POST https://app.monochat.ai/api/:slug/custom-functions/bulk-message-api-app/api/v2/bulk-operation-items/list.js

معاملات الطلب​

المعاملالنوعمطلوبالوصف
bulkOperationIdstringنعممعرّف العملية الجماعية المراد عرضها
optionsobjectلاخيارات التقسيم إلى صفحات والتصفية والفرز. راجعوا بنية Options للتفاصيل.

الطلب — الاستخدام الأساسي​

{
"bulkOperationId": "abc123xyz789",
"options": {
"pagination": {
"currentPage": 1,
"pageItems": 50
}
}
}

الطلب — التصفية بحسب حالة محددة​

{
"bulkOperationId": "abc123xyz789",
"options": {
"pagination": {
"currentPage": 1,
"pageItems": 50
},
"filtering": {
"status": "failed"
}
}
}

يعرض عناصر الإرسال الفاشلة فقط، مع السبب في error.

الاستجابة​

{
"bulkOperationItems": [
{
"_id": "item_1",
"bulkOperationId": "abc123xyz789",
"bulkOperationBatchId": "batch_1",
"slug": "my-workspace",
"position": 0,
"payload": {
"username": "905554443301",
"referenceId": "ORDER-12345",
"payload": {
"template": {
"variables": [{ "type": "BODY", "parameters": ["Ahmet", "ORD-001"] }]
}
}
},
"status": "succeeded",
"attempt": 1,
"result": {
"userId": "user_123",
"sessionId": "session_456",
"messageId": "msg_789"
},
"createdAt": "2026-06-10T10:00:00.000Z",
"updatedAt": "2026-06-10T10:00:01.000Z",
"completedAt": "2026-06-10T10:00:01.000Z"
},
{
"_id": "item_2",
"bulkOperationId": "abc123xyz789",
"bulkOperationBatchId": "batch_1",
"slug": "my-workspace",
"position": 1,
"payload": { "username": "905554443302", "referenceId": "ORDER-12346" },
"status": "failed",
"attempt": 1,
"error": { "code": "error", "message": "Variable missing", "retryable": false },
"result": { "userId": "user_124", "sessionId": "session_457" },
"createdAt": "2026-06-10T10:00:00.000Z",
"updatedAt": "2026-06-10T10:00:01.000Z",
"completedAt": "2026-06-10T10:00:01.000Z"
}
],
"options": {
"pagination": {
"currentPage": 1,
"pageItems": 50,
"totalCount": 150,
"totalPages": 3
},
"sorting": {},
"filtering": {},
"searching": {}
}
}

List With Messages — قائمة مع تفاصيل الرسائل​

له ميزات نقطة النهاية list نفسها (التقسيم إلى صفحات والتصفية والفرز). والفرق: يحمل كل عنصر أيضاً كائنَي message وsession المرتبطين به عند وجودهما. وهذا يتيح لكم رؤية حالة الرسالة (delivered أو read أو error وغيرها) وحمولتها في استعلام واحد.

POST https://app.monochat.ai/api/:slug/custom-functions/bulk-message-api-app/api/v2/bulk-operation-items/list-with-messages.js

الطلب — الاستخدام الأساسي​

{
"bulkOperationId": "abc123xyz789",
"options": {
"pagination": {
"currentPage": 1,
"pageItems": 50
}
}
}

الطلب — التصفية بحسب حالة الرسالة​

{
"bulkOperationId": "abc123xyz789",
"options": {
"pagination": {
"currentPage": 1,
"pageItems": 50
},
"filtering": {
"message.status": "delivered"
}
}
}

يجلب هذا المثال الرسائل ذات الحالة "delivered" فقط.

الطلب — عرض الرسائل الفاشلة​

{
"bulkOperationId": "abc123xyz789",
"options": {
"pagination": {
"currentPage": 1,
"pageItems": 50
},
"filtering": {
"message.status": "error"
}
}
}

يُستخدم لمراجعة الرسائل التي واجهت أخطاء في الإرسال.

الاستجابة​

{
"bulkOperationItems": [
{
"_id": "item_1",
"bulkOperationId": "abc123xyz789",
"position": 0,
"payload": { "username": "905554443301", "referenceId": "ORDER-12345" },
"status": "succeeded",
"result": {
"userId": "user_123",
"sessionId": "session_456",
"messageId": "msg_789"
},
"message": {
"_id": "msg_789",
"type": "template",
"status": "delivered",
"payload": {
"template": {
"name": "order_notification"
}
},
"createdAt": "2026-06-10T10:01:00.000Z"
},
"session": {
"_id": "session_456",
"status": "opened"
}
}
],
"options": {
"pagination": {
"currentPage": 1,
"pageItems": 50,
"totalCount": 150,
"totalPages": 3
},
"sorting": {},
"filtering": {},
"searching": {}
}
}

حقول العنصر​

الحقلالنوعالوصف
_idstringمعرّف العنصر
bulkOperationIdstringمعرّف العملية الجماعية التي ينتمي إليها هذا العنصر
positionnumberترتيب المستلم في المصفوفة recipients في الطلب، بدءاً من 0
payloadobjectالمستلم كما أُرسل في الطلب تماماً (username / userId / sessionId وreferenceId وpayload وisMerge)
statusstringحالة العنصر: pending أو succeeded أو failed أو cancelled أو unknown
errorobjectفي العناصر failed فقط: code وmessage وretryable
result.userIdstringمعرّف مستخدم المستلم
result.sessionIdstringمعرّف جلسة المحادثة
result.messageIdstringمعرّف الرسالة المُرسَلة (غير موجود إذا لم تُرسَل رسالة)
completedAtstringوقت معالجة العنصر
messageobjectتفاصيل الرسالة (في list-with-messages فقط)
sessionobjectتفاصيل المحادثة (في list-with-messages فقط)

مقارنة List وList-With-Messages​

الميزةlistlist-with-messages
التقسيم إلى صفحاتنعمنعم
التصفيةنعم (حقول العنصر فقط)نعم (حقول العنصر والرسالة)
الرسالة / الجلسةلانعم (إن وُجدتا)
الأداءسريعمتوسط (ينفّذ JOIN)
مرشِّح message.statusغير متاحمتاح
سيناريوهات الاستخدام
  • list: عرض كل العناصر بسرعة، والتصفية بحسب referenceId، والتحقق من حالات العناصر
  • list-with-messages: الاطلاع على حالات رسائل WhatsApp (delivered وread)، وفحص حمولات الرسائل
  • أمثلة على التصفية:
    • {"status": "failed"} — عناصر الإرسال الفاشلة
    • {"payload.referenceId": "ORDER-123"} — معرّف مرجعي محدد
    • {"message.status": "delivered"} — الرسائل المُسلَّمة (list-with-messages فقط)
    • {"message.status": "read"} — الرسائل المقروءة (list-with-messages فقط)
    • {"message.status": "error"} — الرسائل التي بها أخطاء (list-with-messages فقط)
    • {"message.status": {"$in": ["delivered", "read"]}} — الرسائل المُسلَّمة أو المقروءة (list-with-messages فقط)
    • {"message.status": {"$nin": ["error", "not-sended"]}} — الرسائل باستثناء الأخطاء وغير المُرسَلة (list-with-messages فقط)
    • {"message": {"$exists": false}} — العناصر التي لا رسالة لها (list-with-messages فقط)
    • {"status": {"$in": ["succeeded", "pending"]}} — العناصر الناجحة أو المعلّقة
ملاحظات الأداء والاستخدام
  • نقطة النهاية list أسرع؛ فضّلوها لفحوص الحالة العامة
  • استخدموا list-with-messages عندما تحتاجون إلى تفاصيل الرسائل
  • الحد الأقصى للعناصر في الصفحة (pageItems) هو 50؛ وتكون القيمة الافتراضية 50 إذا لم تُحدَّد
  • لا يعمل مرشِّح message.status إلا في list-with-messages
  • العناصر التي ليس لها result.messageId لا تحتوي على كائن message

Stop — إلغاء الإرسال​

يوقف إرسال عملية جماعية جارية. تُنقل جميع العناصر pending إلى الحالة cancelled وتصبح العملية الجماعية stopped. أما العناصر التي عُولجت بالفعل بحالة succeeded أو failed فلا تتأثر. ويمكن أيضاً إيقاف عملية جماعية مجدولة قبل حلول وقت scheduleAt الخاص بها.

POST https://app.monochat.ai/api/:slug/custom-functions/bulk-message-api-app/api/v2/bulk-operation/stop.js
تحذير

لا يمكن التراجع عن هذا الإجراء. ولا يمكن استئناف إرسال تم إيقافه.

معاملات الطلب​

المعاملالنوعمطلوبالوصف
bulkOperationIdstringنعممعرّف العملية الجماعية المراد إيقافها
{
"bulkOperationId": "abc123xyz789"
}
curl --location 'https://app.monochat.ai/api/:slug/custom-functions/bulk-message-api-app/api/v2/bulk-operation/stop.js' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer YOUR_JWT_TOKEN' \
--data '{
"bulkOperationId": "abc123xyz789"
}'

الاستجابة​

عند نجاح الطلب يكون جسم الاستجابة فارغاً. وتشير حالة HTTP 200 إلى أن العملية اكتملت بنجاح.

{}
تلميح
  • لا يمكن إيقاف إلا العمليات الجماعية التي أُنشئت عبر واجهة API هذه
  • بعد إيقاف الإرسال، يمكنكم استخدام نقطة النهاية show للتحقق من عدد العناصر الملغاة (bulkOperation.progress.cancelled)
  • إذا تعذّر العثور على العملية الجماعية، تعيد API الخطأ: Bulk operation not found.