跳到主要内容

批量模板消息 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. 用 show.js 替换 stats.js。
  4. 按照下表中的新字段名读取响应。

v2 接口只识别通过 v2 send 创建的批量操作。若要跟踪在切换之前用 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(条目)
请求中、send 响应中以及记录上的 bulkMessageIdbulkOperationId
记录上按发送时的 username / userId / sessionIdpayload.username / payload.userId / payload.sessionId
记录的 referenceIdpayload.referenceId
记录的 payload(收件人的模板载荷)payload.payload
发送后记录的 userId、sessionId、messageIdresult.userId、result.sessionId、result.messageId
记录状态 successsucceeded
失败记录上的 errorMessageerror.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,并可通过 isMerge 与各收件人专属的 payload 合并
  • 定时发送(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系统中已有用户的 ID。
sessionIdstring系统中已有会话的 ID。
referenceIdstring可选的引用 ID(最多 256 个字符),用于与外部系统记录(CRM、订单、工单等)对应。如果提供,在同一次批量请求中必须唯一。
payloadobject收件人专属的模板载荷(可选)。如果 isMerge: true,则与 defaultPayload 合并。
isMergeboolean覆盖该收件人的合并行为(可选)。如果省略,则使用 defaultPayload.isMerge。

操作结构​

字段类型说明
action.keystring"assign-to-user" 把会话分配给指定的客服;"assign-to-workgroup" 把会话分配给某个工作组。
action.valuestring目标用户或工作组的 ID。

模板载荷结构​

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 为每位收件人设置变量​

每位收件人使用不同的变量值。在 defaultPayload 中设置 isMerge: true 后,收件人只需提供 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 按钮变量​

当模板包含带动态 URL 后缀的按钮时,请使用 BUTTONS 组件。例如,把运单号追加到基础 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 必须以 ISO 8601 UTC 时间戳的形式提供。

{
"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是要跟踪的批量操作 ID(由 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.hasErrorsboolean如果至少有一个条目失败,则为 true
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,但消息可能尚未送达或被阅读

引用 ID​

referenceId 是一个可选字段,您可以用它把投递条目与您自己系统中的 ID(例如订单号、工单 ID)对应起来,便于追踪。它会以 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是要查询的批量操作 ID
{
"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条目总数
使用提示
  • 批量操作处于 running 时,no-message 数量较高表示投递仍在进行中
  • delivered 数量显示消息成功送达的情况
  • read 数量可用于衡量活动的互动程度
  • 您可以定期轮询该接口,以实时跟踪

Options 结构:分页、筛选和排序​

list 和 list-with-messages 接口中使用的 options 参数,为分页、筛选和排序提供了标准结构。

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是要列出的批量操作 ID
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条目 ID
bulkOperationIdstring该条目所属的批量操作 ID
positionnumber收件人在请求的 recipients 数组中的顺序,从 0 开始
payloadobject与请求中发送时完全一致的收件人信息(username / userId / sessionId、referenceId、payload、isMerge)
statusstring条目状态:pending、succeeded、failed、cancelled、unknown
errorobject仅出现在 failed 条目上:code、message 和 retryable
result.userIdstring收件人的用户 ID
result.sessionIdstring会话 ID
result.messageIdstring已发送消息的 ID(如果未发送消息则不存在)
completedAtstring条目被处理的时间
messageobject消息详情(仅限 list-with-messages)
sessionobject会话详情(仅限 list-with-messages)

List 与 List-With-Messages 对比​

功能listlist-with-messages
分页是是
筛选是(仅条目字段)是(条目 + 消息字段)
Message / Session否是(如果存在)
性能快中等(执行 JOIN)
message.status 筛选不可用可用
使用场景
  • list:快速列出所有条目、按 referenceId 筛选、检查条目状态
  • list-with-messages:查看 WhatsApp 消息状态(delivered、read)、检查消息载荷
  • 筛选示例:
    • {"status": "failed"} — 投递失败的条目
    • {"payload.referenceId": "ORDER-123"} — 特定的引用 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是要停止的批量操作 ID
{
"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.