پرش به مطلب اصلی

مستندات Bulk Template Message API

این API به شما امکان می‌دهد پیام‌های قالب را هم‌زمان از طریق کانال واتس‌اپ برای چند گیرنده ارسال کنید.

ارسال پیام‌ها به‌صورت ناهمگام (asynchronous) پردازش می‌شود؛ درخواست API بلافاصله یک bulkMessageId برمی‌گرداند و پیام‌ها در پس‌زمینه صف‌بندی و پردازش می‌شوند.

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

ویژگی‌های کلیدی​

  • ارسال پیام‌های قالب گروهی به ۱ تا ۵٬۰۰۰ گیرنده در یک درخواست
  • متغیرهای شخصی‌سازی‌شده برای هر گیرنده (HEADER، BODY، BUTTONS، CAROUSEL)
  • defaultPayload مشترک برای همهٔ گیرندگان و ادغام payload اختصاصی هر گیرنده (isMerge)
  • ارسال زمان‌بندی‌شده (scheduleAt)
  • مشخص‌کردن گیرندگان با username (شمارهٔ تلفن)، userId یا sessionId
  • ارسال چند پیام به یک کاربر در یک درخواست گروهی
  • referenceId اختیاری برای پیگیری رکوردها در سیستم‌های بیرونی
  • واگذاری خودکار گفتگوها به یک کاربر یا گروه کاری پس از ارسال (action)
هشدار

این API فقط می‌تواند قالب‌هایی را ارسال کند که توسط Meta تأیید شده‌اند.

نام قالب و کد زبان باید دقیقاً با قالب ثبت‌شده در Meta Business Manager مطابقت داشته باشند.

پارامترهای درخواست​

پارامترهای سطح بالا​

پارامترنوعالزامیتوضیحات
channelUsernamestringبلهشمارهٔ کانال واتس‌اپ که برای ارسال پیام استفاده می‌شود (مثلاً "908506669933")
connectorBrandstringبلهبرند اتصال‌دهندهٔ کانال. مقدار پشتیبانی‌شدهٔ فعلی: "whatsapp"
titlestringخیرعنوان کمپین. برای نمایش در داشبورد استفاده می‌شود. پیش‌فرض: "-"
scheduleAtstring (ISO 8601)خیرتاریخ و زمان ارسال زمان‌بندی‌شده (مثلاً "2026-06-10T10:00:00.000Z"). اگر ذکر نشود، پیام‌ها بلافاصله ارسال می‌شوند.
defaultPayloadobjectمشروط*payload پیش‌فرض قالب که برای همهٔ گیرندگان اعمال می‌شود. اگر گیرنده‌ای payload اختصاصی خودش را نداشته باشد، الزامی است.
recipientsarrayبلهفهرست گیرندگان. حداقل ۱ و حداکثر ۵٬۰۰۰ گیرنده.
actionobjectخیراقدامی که پس از ارسال روی گفتگو اعمال می‌شود. assign-to-user یا assign-to-workgroup.

*اگر همهٔ گیرندگان payload اختصاصی خودشان را داشته باشند، defaultPayload اختیاری است.

ساختار گیرنده​

برای هر گیرنده باید دقیقاً یکی از username، userId یا sessionId داده شود. چند شناسه را نمی‌توان هم‌زمان به کار برد و ندادن هیچ‌کدام به خطا منجر می‌شود.

برای ارسال چند پیام به یک کاربر در یک درخواست گروهی، همان شناسه را چند بار به فهرست گیرندگان اضافه کنید.

فیلدنوعتوضیحات
usernamestringشمارهٔ تلفن گیرنده (مثلاً "905554443322"). اگر کاربر در سیستم وجود نداشته باشد، به‌صورت خودکار ساخته می‌شود.
userIdstringشناسهٔ یک کاربر موجود در سیستم.
sessionIdstringشناسهٔ یک نشست گفتگوی موجود در سیستم.
referenceIdstringشناسهٔ مرجع اختیاری (حداکثر ۲۵۶ نویسه) برای تطبیق با رکوردهای سیستم بیرونی (CRM، سفارش، تیکت و غیره). در صورت ذکر، باید در همان درخواست گروهی یکتا باشد.
payloadobjectpayload قالب اختصاصی گیرنده (اختیاری). اگر isMerge: true باشد، با defaultPayload ادغام می‌شود.
isMergebooleanرفتار ادغام را برای این گیرنده بازنویسی می‌کند (اختیاری). اگر ذکر نشود، defaultPayload.isMerge استفاده می‌شود.

ساختار اقدام​

فیلدنوعتوضیحات
action.keystring"assign-to-user" گفتگو را به یک کارشناس مشخص و "assign-to-workgroup" آن را به یک گروه کاری واگذار می‌کند.
action.valuestringشناسهٔ کاربر یا گروه کاری مقصد.

ساختار Payload قالب​

defaultPayload و payload اختصاصی گیرنده ساختار یکسانی دارند. برای پیام‌های قالب باید type: "template" مشخص شود.

{
"type": "template",
"template": {
"templateName": "order_confirmation",
"languageCode": "tr-TR",
"variables": []
},
"isMerge": true
}
فیلدنوعالزامیتوضیحات
typestringبلهنوع payload. برای پیام‌های قالب: "template"
template.templateNamestringبله*نام قالب ثبت‌شده در Meta. وقتی isMerge: true به کار رود، در payload گیرندگان اختیاری است (از payload پیش‌فرض به ارث می‌رسد).
template.languageCodestringخیرکد زبان قالب (مثلاً "tr"، "en"، "tr-TR"، "en-US"). باید دقیقاً با زبان ثبت‌شده در Meta مطابقت داشته باشد.
template.variablesarrayخیرفهرست متغیرهایی که روی اجزای قالب اعمال می‌شوند. جزئیات در ادامه آمده است.
isMergebooleanخیرtrue: payload گیرنده به‌صورت عمیق با defaultPayload ادغام می‌شود. false یا ذکرنشده: payload گیرنده به‌طور کامل جایگزین defaultPayload می‌شود.
رفتار isMerge
  • اگر defaultPayload.isMerge: true باشد و گیرنده payload اختصاصی خودش را بدهد، ادغام عمیق اعمال می‌شود.
  • در ادغام عمیق، گیرنده می‌تواند فقط variables را بدهد؛ templateName و languageCode از payload پیش‌فرض به ارث می‌رسند.
  • فیلد isMerge گیرنده، defaultPayload.isMerge را بازنویسی می‌کند.
  • اگر گیرنده payload ندهد، همیشه defaultPayload استفاده می‌شود.

ساختار متغیرها​

هر مورد از آرایهٔ variables با یک جزء قالب متناظر است. نوع هر جزء (type) فقط یک بار می‌تواند در آرایه بیاید.

typeتوضیحاتparameterscards
"HEADER"جزء سرایند قالب. متغیر متنی یا نشانی رسانه (تصویر، ویدیو، سند)بله—
"BODY"متغیرهای متنی بدنهٔ قالببله—
"BUTTONS"متغیرهای پسوند URL پویا برای دکمه‌هابله—
"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​

برای دکمه‌هایی با پسوند URL پویا استفاده می‌شود. اگر قالب چند دکمهٔ URL داشته باشد، فقط دکمه‌های دارای متغیر به‌ترتیب نمایه‌گذاری می‌شوند (دکمه‌های بدون متغیر یا دکمه‌های 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/bulk-message/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 از payload پیش‌فرض به ارث می‌رسند.

در این مثال، قالب هم سرایند رسانه‌ای دارد و هم متغیرهای شخصی‌سازی‌شدهٔ بدنه.

{
"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 در payload هر گیرنده تکرار شود
  • آرایهٔ variables هر گیرنده کاملاً مستقل است
  • نشانی رسانهٔ سرایند باید به‌صورت عمومی در دسترس باشد
  • اگر type در payload گیرنده ذکر نشود، defaultPayload.type به ارث می‌رسد

4. متغیر دکمهٔ URL​

وقتی قالب دکمه‌ای با پسوند URL پویا دارد، از جزء 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 و دکمه‌های بدون متغیر نادیده گرفته می‌شوند؛ نمایه‌گذاری فقط برای دکمه‌های URL پویا اعمال می‌شود
  • اگر URL دکمهٔ قالب 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 داده شود (مثلاً برای ساعت ۱۰:۰۰ صبح به وقت ترکیه، از 07:00:00.000Z استفاده کنید)
  • این مثال از قالب پارامتر نام‌دار استفاده می‌کند؛ قالب باید جانشین‌هایی مانند {{name}} و {{discountRate}} داشته باشد
  • با action، گفتگوهایی که در اثر ارسال پیام ایجاد می‌شوند به‌صورت خودکار به گروه کاری مشخص‌شده واگذار می‌شوند

پاسخ​

یک درخواست موفق یک bulkMessageId برمی‌گرداند که می‌توان از آن برای پیگیری روند ارسال استفاده کرد:

{
"bulkMessageId": "abc123xyz789"
}

پاسخ‌های خطا​

وضعیتتوضیحات
Channel not foundکانال تأییدشده‌ای که با channelUsername و connectorBrand مطابقت داشته باشد پیدا نشد
Channel is not verifiedکانال مطابق وجود دارد اما هنوز تأیید نشده است
invalidRequestبرای یک گیرنده چند شناسه داده شده یا payload لازم وجود ندارد
channelNotFoundکانال فعالی که با channelId داده‌شده مطابقت داشته باشد پیدا نشد
schema-errorیکی از فیلدهای بدنهٔ درخواست در اعتبارسنجی طرح‌واره رد شد (فیلد الزامی وجود ندارد، نوع نادرست است یا مقدار پشتیبانی‌نشده است)

bulkMessageId برگشتی را می‌توان با اندپوینت‌های زیر برای پرس‌وجوی آمار ارسال و متوقف‌کردن روند ارسال به کار برد.


Stats — آمار ارسال​

وضعیت فعلی ارسال یک پیام گروهی را دریافت می‌کند. تعداد رکوردهای در انتظار، موفق، ناموفق و لغوشده را برمی‌گرداند.

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

پارامترهای درخواست​

پارامترنوعالزامیتوضیحات
bulkMessageIdstringبلهشناسهٔ پیام گروهی که باید پیگیری شود (از createBulkPerRecipient برگردانده می‌شود)
{
"bulkMessageId": "abc123xyz789"
}
curl --location 'https://app.monochat.ai/api/:slug/custom-functions/bulk-message-api-app/api/bulk-message/stats.js' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer YOUR_JWT_TOKEN' \
--data '{
"bulkMessageId": "abc123xyz789"
}'

پاسخ​

{
"bulkMessage": {
"_id": "abc123xyz789",
"slug": "my-workspace",
"title": "Campaign Title",
"channelUsername": "908506669933",
"connectorBrand": "whatsapp",
"connectorSlug": "whatsapp-cloud",
"payload": {
"recipientCount": 100,
"defaultPayloadType": "template",
"jobId": "job_abc123"
},
"schedule": {
"date": "2026-06-10T07:00:00.000Z",
"type": "later"
},
"createdAt": "2026-06-08T10:00:00.000Z",
"updatedAt": "2026-06-08T10:30:00.000Z"
},
"stats": {
"pending": 45,
"success": 42,
"failed": 3,
"cancelled": 10,
"total": 100
}
}

فیلدهای Stats​

فیلدنوعتوضیحات
stats.pendingnumberتعداد رکوردهایی که هنوز در صف منتظرند
stats.successnumberتعداد رکوردهایی که با موفقیت برای ارسال پردازش شده‌اند
stats.failednumberتعداد رکوردهایی که در ارسال با خطا مواجه شده‌اند
stats.cancellednumberتعداد رکوردهای لغوشده
stats.totalnumberتعداد کل رکوردها (pending + success + failed + cancelled)
یادداشت

stats.success نشان می‌دهد پیام با موفقیت از سوی سیستم تحویل داده شده است. این به معنای تضمین تحویل پیام به گیرنده توسط Meta نیست. به‌روزرسانی‌های وضعیت بعدی که Meta تولید می‌کند (مانند delivered، read یا failed) روی این شمارنده اثری ندارند و در آن منعکس نمی‌شوند.

تفاوت Stats و Message Stats
  • اندپوینت stats: وضعیت کار ارسال را نشان می‌دهد (pending، success، failed، cancelled)
  • اندپوینت message-stats: وضعیت واقعی پیام را نشان می‌دهد (pending، sending، sent، delivered، read، error و غیره)
  • ممکن است یک کار موفق باشد، اما پیام هنوز تحویل داده نشده یا خوانده نشده باشد

شناسهٔ مرجع​

referenceId یک فیلد اختیاری است که می‌توانید برای پیگیری از آن استفاده کنید تا رکوردهای ارسال را با شناسه‌ای از سیستم خودتان (مثلاً شمارهٔ سفارش یا شناسهٔ تیکت) تطبیق دهید.

در صورت ذکر، باید در همان درخواست گروهی یکتا باشد (حداکثر ۲۵۶ نویسه).

مهم
  • استفاده از آن الزامی نیست
  • در یک پیام گروهی نمی‌تواند تکراری باشد
  • می‌توان آن را در پیام‌های گروهی مختلف دوباره استفاده کرد

Message Stats — وضعیت پیام واتس‌اپ​

آمار وضعیت پیام‌های یک پیام گروهی را دریافت می‌کند. برخلاف اندپوینت stats، این اندپوینت به‌جای وضعیت کار، 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/bulk-message/message-stats.js

پارامترهای درخواست​

پارامترنوعالزامیتوضیحات
bulkMessageIdstringبلهشناسهٔ پیام گروهی که باید پرس‌وجو شود
{
"bulkMessageId": "abc123xyz789"
}
curl --location 'https://app.monochat.ai/api/:slug/custom-functions/bulk-message-api-app/api/bulk-message/message-stats.js' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer YOUR_JWT_TOKEN' \
--data '{
"bulkMessageId": "abc123xyz789"
}'

پاسخ​

{
"bulkMessage": {
"_id": "abc123xyz789",
"slug": "my-workspace",
"type": "perRecipient",
"title": "Campaign Title"
},
"messageStats": {
"pending": 5,
"sending": 2,
"sent": 10,
"delivered": 45,
"read": 30,
"deleted": 2,
"warning": 1,
"error": 3,
"unknown": 0,
"not-sended": 2,
"no-message": 10,
"total": 120
}
}

فیلدهای Message Stats​

فیلدنوعتوضیحات
pendingnumberپیام‌هایی که هنوز ارسال نشده‌اند
sendingnumberپیام‌هایی که اکنون در حال ارسال‌اند
sentnumberپیام‌هایی که به واتس‌اپ تحویل داده شده‌اند اما هنوز به مقصد نرسیده‌اند
deliverednumberپیام‌هایی که به گوشی گیرنده رسیده‌اند
readnumberپیام‌هایی که گیرنده خوانده است
deletednumberپیام‌های حذف‌شده
warningnumberپیام‌های دارای هشدار
errornumberپیام‌های دارای خطا
unknownnumberپیام‌های با وضعیت نامشخص
not-sendednumberپیام‌هایی که نتوانستند ارسال شوند
no-messagenumberرکوردهایی که هنوز پیامی ندارند (هنوز در صف‌اند)
totalnumberتعداد کل رکوردها
نکته‌های استفاده
  • بالا بودن تعداد no-message نشان می‌دهد ارسال هنوز در جریان است
  • تعداد delivered تحویل موفق پیام را نشان می‌دهد
  • از تعداد read می‌توان برای سنجش تعامل کمپین استفاده کرد
  • برای پیگیری لحظه‌ای می‌توانید این اندپوینت را به‌صورت دوره‌ای فراخوانی کنید

ساختار Options — صفحه‌بندی، فیلتر و مرتب‌سازی​

پارامتر options که در اندپوینت‌های list و list-with-messages استفاده می‌شود، ساختاری استاندارد برای صفحه‌بندی، فیلتر و مرتب‌سازی فراهم می‌کند.

فیلدهای Options​

فیلدنوعالزامیتوضیحات
paginationobjectخیرتنظیمات صفحه‌بندی
filteringobjectخیرمعیارهای فیلتر
sortingobjectخیرتنظیمات مرتب‌سازی (مثلاً {"createdAt": -1})

ساختار صفحه‌بندی​

فیلدنوعپیش‌فرضتوضیحات
currentPagenumber1شمارهٔ صفحه‌ای که باید دریافت شود
pageItemsnumber50تعداد رکورد در هر صفحه (حداکثر: ۵۰)

ساختار فیلتر​

فیلتر کردن با قالب پرس‌وجوی MongoDB انجام می‌شود. می‌توانید بر اساس فیلدهای رکورد فیلتر کنید. در اندپوینت list-with-messages می‌توانید بر اساس فیلدهای پیام (مثلاً message.status) هم فیلتر کنید.

// Filter by record status
{
"options": {
"filtering": {
"status": "success"
}
}
}

// Filter by referenceId
{
"options": {
"filtering": {
"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"]
}
}
}
}

ساختار مرتب‌سازی​

مرتب‌سازی با قالب sort در MongoDB انجام می‌شود. 1 به معنای صعودی و -1 به معنای نزولی است.

// Sort by creation date descending (newest first)
{
"options": {
"sorting": {
"createdAt": -1
}
}
}

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

نمونهٔ استفادهٔ ترکیبی​

{
"bulkMessageId": "abc123xyz789",
"options": {
"pagination": {
"currentPage": 2,
"pageItems": 50
},
"filtering": {
"message.status": "delivered"
},
"sorting": {
"createdAt": -1
}
}
}

این مثال پیام‌های تحویل‌شده را از جدید به قدیم مرتب می‌کند.

نکته‌های کاربردی
  • برای پرس‌وجوهای هدفمند filtering و pagination را با هم ترکیب کنید
  • پاسخ برای پیمایش شامل options.pagination.totalCount و options.pagination.totalPages است
  • فیلتر message.status فقط در اندپوینت list-with-messages کار می‌کند

Records — جزئیات و فهرست رکوردها​

همهٔ رکوردهای ارسال یک پیام گروهی را فهرست می‌کند. هر رکورد یک پیام ارسال‌شده به یک گیرنده را نشان می‌دهد.

List — فهرست رکوردها​

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

پارامترهای درخواست​

پارامترنوعالزامیتوضیحات
bulkMessageIdstringبلهشناسهٔ پیام گروهی که باید فهرست شود
optionsobjectخیرگزینه‌های صفحه‌بندی، فیلتر و مرتب‌سازی. جزئیات را در ساختار Options ببینید.

درخواست — استفادهٔ پایه​

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

درخواست — فیلتر بر اساس یک وضعیت مشخص​

{
"bulkMessageId": "abc123xyz789",
"options": {
"pagination": {
"currentPage": 1,
"pageItems": 50
},
"filtering": {
"status": "success"
}
}
}

فقط رکوردهای ارسال موفق را فهرست می‌کند (record.status = "success").

پاسخ​

{
"bulkMessageRecords": [
{
"_id": "record_1",
"bulkMessageId": "abc123xyz789",
"slug": "my-workspace",
"userId": "user_123",
"sessionId": "session_456",
"messageId": "msg_789",
"referenceId": "ORDER-12345",
"status": "success",
"createdAt": "2026-06-10T10:00:00.000Z"
}
],
"options": {
"pagination": {
"currentPage": 1,
"pageItems": 50,
"totalCount": 150,
"totalPages": 3
},
"sorting": {},
"filtering": {}
}
}

List With Messages — فهرست همراه با جزئیات پیام​

همان ویژگی‌های اندپوینت list را دارد (صفحه‌بندی، فیلتر، مرتب‌سازی). تنها تفاوت: اگر رکوردی messageId داشته باشد، شیء message مربوط به آن هم برگردانده می‌شود. این کار به شما امکان می‌دهد وضعیت پیام (delivered، read، error و غیره) و payload آن را در یک پرس‌وجو ببینید.

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

درخواست — استفادهٔ پایه​

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

درخواست — فیلتر بر اساس وضعیت پیام​

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

این مثال فقط پیام‌هایی با وضعیت "delivered" را دریافت می‌کند.

درخواست — فهرست پیام‌های ناموفق​

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

برای بررسی پیام‌هایی که در ارسال با خطا مواجه شده‌اند استفاده می‌شود.

پاسخ​

{
"bulkMessageRecords": [
{
"_id": "record_1",
"bulkMessageId": "abc123xyz789",
"userId": "user_123",
"messageId": "msg_789",
"referenceId": "ORDER-12345",
"status": "success",
"message": {
"_id": "msg_789",
"status": "delivered",
"payload": {
"type": "template",
"template": {
"templateName": "order_notification"
}
},
"createdAt": "2026-06-10T10:01:00.000Z",
"deliveredAt": "2026-06-10T10:01:05.000Z"
}
}
],
"options": {
"pagination": {
"currentPage": 1,
"pageItems": 50,
"totalCount": 150,
"totalPages": 3
},
"sorting": {},
"filtering": {}
}
}

فیلدهای Record​

فیلدنوعتوضیحات
_idstringشناسهٔ رکورد
bulkMessageIdstringشناسهٔ پیام گروهی که این رکورد به آن تعلق دارد
userIdstringشناسهٔ کاربر گیرنده
sessionIdstringشناسهٔ نشست گفتگو
messageIdstringشناسهٔ پیام ارسال‌شده (اگر هنوز ارسال نشده باشد null)
referenceIdstringشناسهٔ مرجع اختیاری (در صورت ذکر)
statusstringوضعیت رکورد: pending، success، failed، cancelled
messageobjectجزئیات پیام (فقط در list-with-messages)

مقایسهٔ List و List-With-Messages​

ویژگیlistlist-with-messages
صفحه‌بندیبلهبله
فیلتربله (فقط فیلدهای رکورد)بله (فیلدهای رکورد + پیام)
شیء پیامخیربله (اگر messageId وجود داشته باشد)
کاراییسریعمتوسط (JOIN انجام می‌دهد)
فیلتر message.statusدر دسترس نیستدر دسترس
سناریوهای استفاده
  • list: همهٔ رکوردها را سریع فهرست کنید، بر اساس referenceId فیلتر کنید، وضعیت رکوردها را بررسی کنید
  • list-with-messages: وضعیت پیام‌های واتس‌اپ (delivered، read) را ببینید، payload پیام‌ها را بررسی کنید
  • نمونه‌های فیلتر:
    • {"status": "failed"} — رکوردهای ارسال ناموفق
    • {"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)
    • {"status": {"$in": ["success", "pending"]}} — رکوردهای موفق یا در انتظار
نکته‌های کارایی و استفاده
  • اندپوینت list سریع‌تر است؛ برای بررسی‌های عمومی وضعیت آن را ترجیح دهید
  • وقتی به جزئیات پیام نیاز دارید از list-with-messages استفاده کنید
  • حداکثر رکورد در هر صفحه (pageItems) ۵۰ است؛ اگر ذکر نشود پیش‌فرض ۵۰ است
  • فیلتر message.status فقط در list-with-messages کار می‌کند
  • رکوردهایی که messageId آن‌ها null است، شیء message آن‌ها هم null خواهد بود

Stop — لغو ارسال​

ارسال در حال انجام یک پیام گروهی را متوقف می‌کند. کار صف‌شده لغو می‌شود و همهٔ رکوردهای pending به وضعیت cancelled منتقل می‌شوند. رکوردهایی که قبلاً با وضعیت success یا failed پردازش شده‌اند تحت تأثیر قرار نمی‌گیرند.

POST https://app.monochat.ai/api/:slug/custom-functions/bulk-message-api-app/api/bulk-message/stop.js
هشدار

این اقدام قابل بازگشت نیست. ارسال متوقف‌شده را نمی‌توان از سر گرفت.

پارامترهای درخواست​

پارامترنوعالزامیتوضیحات
bulkMessageIdstringبلهشناسهٔ پیام گروهی که باید متوقف شود
{
"bulkMessageId": "abc123xyz789"
}
curl --location 'https://app.monochat.ai/api/:slug/custom-functions/bulk-message-api-app/api/bulk-message/stop.js' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer YOUR_JWT_TOKEN' \
--data '{
"bulkMessageId": "abc123xyz789"
}'

پاسخ​

برای یک درخواست موفق، بدنهٔ پاسخ خالی است. وضعیت HTTP 200 نشان می‌دهد عملیات با موفقیت انجام شده است.

{}
نکته
  • فقط پیام‌های گروهی که از طریق این API ساخته شده‌اند قابل توقف‌اند
  • پس از توقف ارسال، می‌توانید با اندپوینت stats تعداد رکوردهای لغوشده را بررسی کنید
  • اگر پیام گروهی پیدا نشود، API خطای bulkMessageNotFound را برمی‌گرداند