Перейти к основному содержимому

Документация 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.jsbulkMessageRecords становится 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": "…"}
ошибки send schema-error, invalidRequestzod-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Необязательный идентификатор для сопоставления с записями внешней системы (CRM, заказ, заявка и т. д.), до 256 символов. Если указан, должен быть уникальным в рамках одной рассылки.
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"Компонент заголовка шаблона. Текстовая переменная или URL медиафайла (изображение, видео, документ)Да—
"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/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 каждого получателя полностью независим
  • URL медиафайла заголовка должен быть общедоступным
  • Если в нагрузке получателя не указан type, наследуется defaultPayload.type

4. Переменная URL-кнопки​

Используйте компонент BUTTONS, если в шаблоне есть кнопка с динамическим суффиксом URL. Например, номер отслеживания, добавляемый к базовому URL 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 (например, для 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, но сообщение при этом ещё может быть не доставлено или не прочитано

Reference ID​

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​

Если pagination не передан, возвращается первая страница, содержащая до 50 элементов. Если он передан, currentPage обязателен.

ПолеТипПо умолчаниюОписание
currentPagenumber—Номер запрашиваемой страницы (обязателен, если передан pagination)
pageItemsnumber50Количество элементов на странице (максимум: 50)

Структура Filtering​

Фильтрация выполняется в формате запросов 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
}
}
}
}

Структура Sorting​

Сортировка выполняется в формате сортировки 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"} — конкретный reference ID
    • {"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.