Documentação da Bulk Template Message API — v2
Esta API permite enviar mensagens de template a vários destinatários simultaneamente pelo canal de WhatsApp.
O envio das mensagens é processado de forma assíncrona; a requisição da API retorna imediatamente um bulkOperationId, enquanto as mensagens são colocadas em fila e processadas em segundo plano.
POST https://app.monochat.ai/api/:slug/custom-functions/bulk-message-api-app/api/v2/bulk-operation/send.js
Todos os endpoints deste documento são custom functions. O corpo da resposta HTTP traz os campos da própria função (_id, title, pathString…) e a resposta real do endpoint em result. Os exemplos de resposta deste documento mostram o conteúdo de result:
{
"_id": "function_id",
"title": "Show",
"pathString": "/bulk-message-api-app/api/v2/bulk-operation/show.js",
"result": {
"bulkOperation": { "_id": "abc123xyz789", "status": "running" }
}
}
Migração da v1
A v2 funciona lado a lado com a v1, então você pode migrar no seu próprio ritmo. Os endpoints da v1 (/api/bulk-message/…, /api/bulk-message-records/…) serão desativados; novas integrações devem usar a v2.
- Mude os caminhos dos endpoints para a v2:
…/api/bulk-message/…passa a ser…/api/v2/bulk-operation/…, e…/api/bulk-message-records/…passa a ser…/api/v2/bulk-operation-items/…. O corpo da requisição desendnão muda; uma única requisição agora aceita até 100.000 destinatários em vez de 5.000. - Envie
bulkOperationIdem vez debulkMessageIdnas requisições. - Substitua
stats.jsporshow.js. - Leia as respostas com os novos nomes de campos da tabela abaixo.
Os endpoints da v2 só reconhecem operações em massa criadas com o send da v2. Para acompanhar uma mensagem em massa criada com a v1 antes da migração, continue usando os endpoints da v1 para ela.
Endpoints
| v1 | v2 | O que muda na resposta |
|---|---|---|
bulk-message/send.js | v2/bulk-operation/send.js | { bulkMessageId } passa a ser { bulkOperationId } |
bulk-message/stats.js | v2/bulk-operation/show.js | { bulkMessage, stats } passa a ser { bulkOperation } |
bulk-message/message-stats.js | v2/bulk-operation/message-stats.js | Os contadores ficam na raiz em vez de em messageStats |
bulk-message/stop.js | v2/bulk-operation/stop.js | Nada |
bulk-message-records/list.js | v2/bulk-operation-items/list.js | bulkMessageRecords passa a ser bulkOperationItems |
bulk-message-records/list-with-messages.js | v2/bulk-operation-items/list-with-messages.js | O mesmo que list, e cada item também traz session |
Nomes dos campos
| v1 | v2 |
|---|---|
stats.success | bulkOperation.progress.succeeded |
stats.pending, stats.failed, stats.cancelled, stats.total | bulkOperation.progress.pending, .failed, .cancelled, .total |
| — | bulkOperation.progress.unknown, bulkOperation.status, bulkOperation.result.outcome |
bulkMessage (mensagem em massa) | bulkOperation (operação em massa) |
bulkMessageRecord (registro) | bulkOperationItem (item) |
bulkMessageId nas requisições, na resposta de send e nos registros | bulkOperationId |
username / userId / sessionId do registro, como enviados | payload.username / payload.userId / payload.sessionId |
referenceId do registro | payload.referenceId |
payload do registro (o payload de template do destinatário) | payload.payload |
userId, sessionId, messageId do registro após o envio | result.userId, result.sessionId, result.messageId |
status de registro success | succeeded |
errorMessage nos registros com falha | error.message, ao lado de error.code e error.retryable |
| — | position (o índice do destinatário em recipients) |
filtro {"status": "success"} | {"status": "succeeded"} |
filtro {"referenceId": "…"} | {"payload.referenceId": "…"} |
erros de send schema-error, invalidRequest | zod-schema-error, com o caminho do campo inválido na mensagem |
Principais recursos
- Envie mensagens de template em massa para 1 a 100.000 destinatários em uma única requisição
- Variáveis personalizadas para cada destinatário (HEADER, BODY, BUTTONS, CAROUSEL)
defaultPayloadcompartilhado por todos os destinatários, com mesclagem dopayloadespecífico de cada destinatário (isMerge)- Envio agendado (
scheduleAt) - Indique os destinatários por
username(número de telefone),userIdousessionId - Envie várias mensagens ao mesmo usuário em uma única requisição em massa
referenceIdopcional para acompanhar registros em sistemas externos- Atribua automaticamente as conversas a um usuário ou grupo de trabalho após o envio (
action)
Esta API só pode enviar templates que tenham sido aprovados pela Meta.
O nome do template e o código de idioma devem corresponder exatamente ao template cadastrado no Meta Business Manager.
Parâmetros da requisição
Parâmetros de nível superior
| Parâmetro | Tipo | Obrigatório | Descrição |
|---|---|---|---|
channelUsername | string | Sim | Número do canal de WhatsApp usado para enviar a mensagem (por exemplo "908506669933") |
connectorBrand | string | Sim | Marca do conector do canal. Valor atualmente aceito: "whatsapp" |
title | string | Não | Título da campanha. Usado para exibição no painel. Padrão: "-" |
scheduleAt | string (ISO 8601) | Não | Data e hora do envio agendado (por exemplo "2026-06-10T10:00:00.000Z"). Se omitido, as mensagens são enviadas imediatamente. |
defaultPayload | object | Condicional* | Payload de template padrão aplicado a todos os destinatários. Obrigatório se um destinatário não informar o próprio payload. |
recipients | array | Sim | Lista de destinatários. Mínimo de 1, máximo de 100.000 destinatários. |
action | object | Não | Ação aplicada à conversa após o envio. assign-to-user ou assign-to-workgroup. |
*Se todos os destinatários informarem o próprio payload, o defaultPayload é opcional.
Estrutura do destinatário
Para cada destinatário, deve ser informado exatamente um entre username, userId ou sessionId. Não é possível usar vários identificadores juntos, e omitir todos resultará em erro.
Para enviar várias mensagens ao mesmo usuário em uma única requisição em massa, adicione o mesmo identificador à lista de destinatários várias vezes.
| Campo | Tipo | Descrição |
|---|---|---|
username | string | Número de telefone do destinatário (por exemplo "905554443322"). Se o usuário não existir no sistema, ele é criado automaticamente. |
userId | string | ID de um usuário existente no sistema. |
sessionId | string | ID de uma sessão de conversa existente no sistema. |
referenceId | string | ID de referência opcional (máximo de 256 caracteres) para correspondência com registros de sistemas externos (CRM, pedido, ticket etc.). Deve ser único dentro do envio em massa, se informado. |
payload | object | Payload de template específico do destinatário (opcional). Se isMerge: true, ele é mesclado com o defaultPayload. |
isMerge | boolean | Substitui o comportamento de mesclagem para este destinatário (opcional). Se omitido, usa-se o defaultPayload.isMerge. |
Estrutura da ação
| Campo | Tipo | Descrição |
|---|---|---|
action.key | string | "assign-to-user" atribui a conversa a um atendente específico; "assign-to-workgroup" atribui a um grupo de trabalho. |
action.value | string | ID do usuário ou do grupo de trabalho de destino. |
Estrutura do payload do template
defaultPayload e o payload específico de cada destinatário têm a mesma estrutura. Para mensagens de template, é preciso informar type: "template".
{
"type": "template",
"template": {
"templateName": "order_confirmation",
"languageCode": "tr-TR",
"variables": []
},
"isMerge": true
}
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
type | string | Sim | Tipo do payload. Para mensagens de template: "template" |
template.templateName | string | Sim* | Nome do template cadastrado na Meta. Opcional nos payloads de destinatário quando se usa isMerge: true (herda do padrão). |
template.languageCode | string | Não | Código de idioma do template (por exemplo "tr", "en", "tr-TR", "en-US"). Deve corresponder exatamente ao idioma cadastrado na Meta. |
template.variables | array | Não | Lista de variáveis aplicadas aos componentes do template. Detalhada abaixo. |
isMerge | boolean | Não | true: o payload do destinatário é mesclado em profundidade com o defaultPayload. false ou omitido: o payload do destinatário substitui completamente o defaultPayload. |
- Se
defaultPayload.isMerge: truee o destinatário informar o própriopayload, é aplicada uma mesclagem em profundidade. - Com a mesclagem em profundidade, o destinatário pode informar apenas
variables;templateNameelanguageCodesão herdados do payload padrão. - O campo
isMergedo destinatário substitui odefaultPayload.isMerge. - Se um destinatário não informar um
payload, odefaultPayloadé sempre usado.
Estrutura das variáveis
Cada item do array variables corresponde a um componente do template. Um tipo de componente (type) pode aparecer apenas uma vez no array.
| type | Descrição | parameters | cards |
|---|---|---|---|
"HEADER" | Componente de cabeçalho do template. Variável de texto ou URL de mídia (imagem, vídeo, documento) | Sim | — |
"BODY" | Variáveis de texto do corpo do template | Sim | — |
"BUTTONS" | Variáveis de sufixo de URL dinâmico para botões | Sim | — |
"CAROUSEL" | Componentes de cartão para templates de carrossel | — | Sim |
Formatos dos parâmetros
O campo parameters pode ser informado em três formatos diferentes:
// 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" }
- Se o seu template da Meta usa marcadores como
{{1}},{{2}}, use o formato de array ou o de objeto com chaves numéricas. - Se o seu template usa marcadores nomeados, como
{{firstName}}ou{{orderTotal}}, use o formato de objeto com chaves nomeadas. - Ao usar arrays, a ordem importa: o primeiro elemento corresponde a
{{1}}, o segundo a{{2}}, e assim por diante.
Componente HEADER
Use o componente HEADER quando o cabeçalho do template contiver mídia (imagem, vídeo, documento) ou texto dinâmico.
// Media header (image URL)
{
"type": "HEADER",
"parameters": ["https://example.com/product-image.jpg"]
}
// Text header variable
{
"type": "HEADER",
"parameters": ["Special Campaign"]
}
Componente BODY
Usado para variáveis de texto dinâmicas dentro do corpo do template.
// 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"
}
}
Componente BUTTONS
Usado para botões com sufixos de URL dinâmicos. Se o template contiver vários botões de URL, apenas os botões com variáveis são indexados em sequência (botões sem variáveis ou botões FLOW são ignorados).
// 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"]
}
Componente CAROUSEL
Em templates de carrossel, as variáveis dos componentes são definidas separadamente para cada cartão.
{
"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"]
}
]
}
]
}
O tamanho do array cards deve corresponder exatamente ao número de cartões definidos no template.
Exemplos
1. Template simples — sem variáveis, mesmo conteúdo para todos os destinatários
Esta é a forma mais simples de enviar um template estático, sem variáveis, a vários destinatários.
{
"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" }
]
}'
- Os destinatários indicados por
usernamesão criados automaticamente se ainda não existirem no sistema - Todos os destinatários usam o mesmo
defaultPayload; nenhum dado específico por destinatário é necessário - Quando
isMergenão é especificado, cada destinatário usa diretamente odefaultPayload
2. Template com variáveis de corpo compartilhadas
O mesmo template é enviado a todos os destinatários com valores de variáveis idênticos. O template contém marcadores como {{1}} e {{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" }]
}
- Neste exemplo, o corpo do template pode conter um texto como: "Aproveite
{{1}}de desconto na nossa campanha! Oferta válida até{{2}}." parameters[0]substitui{{1}}, enquantoparameters[1]substitui{{2}}
3. Template personalizado — variáveis por destinatário com isMerge
Valores de variáveis diferentes são usados para cada destinatário. Ao definir isMerge: true no defaultPayload, os destinatários só precisam informar variables; templateName e languageCode são herdados do payload padrão.
Neste exemplo, o template inclui um cabeçalho de mídia e variáveis de corpo personalizadas.
{
"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"]
}
]
}
}
}
]
}
- Graças a
isMerge: true,templateNamenão precisa ser repetido no payload de cada destinatário - O array
variablesde cada destinatário é totalmente independente - A URL da mídia do cabeçalho deve ser publicamente acessível
- Se
typefor omitido no payload do destinatário,defaultPayload.typeé herdado
4. Variável de botão de URL
Use o componente BUTTONS quando o template contiver um botão com sufixo de URL dinâmico. Por exemplo, um código de rastreamento acrescentado à URL base 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"]
}
]
}
}
}
]
}
- Os parâmetros de
BUTTONSsão associados conforme a ordem dos botões que contêm variáveis - Botões FLOW e botões sem variáveis são ignorados; a indexação se aplica apenas aos botões de URL dinâmica
- Se a URL do botão do template for
https://example.com/track/{{1}}, entãoparameters[0]substitui{{1}}
5. Envio agendado
Agende o envio de uma mensagem para uma data e hora futuras. scheduleAt deve ser informado como um timestamp ISO 8601 em 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" }
}
]
}
}
}
]
}
scheduleAtdeve ser informado no fuso horário UTC (por exemplo, para 10:00 no horário da Turquia, use07:00:00.000Z)- Este exemplo usa o formato de parâmetros nomeados; o template deve conter marcadores como
{{name}}e{{discountRate}} - Com
action, as conversas criadas pelo envio da mensagem são atribuídas automaticamente ao grupo de trabalho especificado
Resposta
Uma requisição bem-sucedida retorna um bulkOperationId, que pode ser usado para acompanhar o processo de envio:
{
"bulkOperationId": "abc123xyz789"
}
Respostas de erro
| Status | Descrição |
|---|---|
recipients field is required | O campo recipients não foi enviado |
Channel not found | Nenhum canal verificado correspondente a channelUsername e connectorBrand foi encontrado |
Channel is not verified | O canal correspondente existe, mas ainda não foi verificado |
zod-schema-error | Um campo do corpo da requisição falhou na validação do esquema (campo obrigatório ausente, tipo incorreto, valor não aceito, mais de um identificador em um destinatário ou payload ausente). A mensagem indica o campo, por exemplo recipients.0.referenceId: referenceId must be unique |
O bulkOperationId retornado pode ser usado com os endpoints abaixo para consultar as estatísticas de envio e interromper o processo de envio.
Show — status e estatísticas da operação em massa
Obtém a operação em massa com o seu status atual e os contadores de envio dos seus itens, na chave bulkOperation.
POST https://app.monochat.ai/api/:slug/custom-functions/bulk-message-api-app/api/v2/bulk-operation/show.js
Parâmetros da requisição
| Parâmetro | Tipo | Obrigatório | Descrição |
|---|---|---|---|
bulkOperationId | string | Sim | ID da operação em massa a acompanhar (retornado por 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"
}'
Resposta
{
"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"
}
}
Campos de show
Os campos ficam em bulkOperation.
| Campo | Tipo | Descrição |
|---|---|---|
status | string | Status da operação em massa: preparing, scheduled, pending, running, stopping, stopped, completed, failed |
progress.total | number | Número total de itens |
progress.pending | number | Itens ainda aguardando na fila |
progress.succeeded | number | Itens processados com sucesso para envio |
progress.failed | number | Itens que tiveram um erro de envio |
progress.cancelled | number | Itens cancelados por stop |
progress.unknown | number | Itens cujo resultado não pôde ser determinado |
result.outcome | string | Resultado final depois que a operação em massa termina: success, partial, all-failed, cancelled, unknown |
result.hasErrors | boolean | true se pelo menos um item falhou |
scheduleAt | string | Horário do envio agendado (somente para operações em massa agendadas) |
startedAt, completedAt | string | Quando o envio começou e terminou |
progress.succeeded indica que a mensagem foi repassada com sucesso pelo sistema. Isso não garante que a Meta entregou a mensagem ao destinatário. As atualizações de status posteriores geradas pela Meta (como delivered, read ou failed) não afetam esse contador e não são refletidas aqui.
- Endpoint show: mostra o status de envio dos itens (
pending,succeeded,failed,cancelled,unknown) - Endpoint message-stats: mostra o status real da mensagem (
pending,sending,sent,delivered,read,erroretc.) - Um item pode estar
succeeded, mas a mensagem ainda pode não ter sido entregue/lida
ID de referência
O referenceId é um campo opcional que você pode usar para associar os itens de envio a um ID do seu próprio sistema para fins de acompanhamento (por exemplo, número do pedido, ID do ticket). Ele é retornado em cada item como payload.referenceId.
Se informado, ele deve ser único dentro do envio em massa (máximo de 256 caracteres).
- Não é obrigatório
- Não pode ser duplicado dentro da mesma operação em massa
- Pode ser reutilizado em operações em massa diferentes
Message Stats — status das mensagens do WhatsApp
Obtém as estatísticas de status das mensagens de uma operação em massa. Diferentemente do endpoint show, este mostra o message.status real das mensagens enviadas, em vez do status do item.
Status possíveis das mensagens: 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
Parâmetros da requisição
| Parâmetro | Tipo | Obrigatório | Descrição |
|---|---|---|---|
bulkOperationId | string | Sim | ID da operação em massa a consultar |
{
"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"
}'
Resposta
{
"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
}
Campos de message stats
| Campo | Tipo | Descrição |
|---|---|---|
pending | number | Mensagens ainda não enviadas |
sending | number | Mensagens sendo enviadas no momento |
sent | number | Mensagens entregues ao WhatsApp, ainda não entregues ao destinatário |
delivered | number | Mensagens entregues ao telefone do destinatário |
read | number | Mensagens lidas pelo destinatário |
deleted | number | Mensagens excluídas |
warning | number | Mensagens com avisos |
error | number | Mensagens com erros |
unknown | number | Mensagens com status desconhecido |
not-sended | number | Mensagens que não puderam ser enviadas |
no-message | number | Itens sem mensagem (ainda na fila, com falha ou cancelados) |
total | number | Total de itens |
- Uma contagem alta de
no-messageenquanto a operação em massa estárunningindica que o envio ainda está em andamento - A contagem de
deliveredmostra as mensagens entregues com sucesso - A contagem de
readpode ser usada para medir o engajamento da campanha - Você pode consultar este endpoint periodicamente para acompanhamento em tempo real
Estrutura de options — paginação, filtragem e ordenação
O parâmetro options usado nos endpoints list e list-with-messages oferece uma estrutura padrão para paginação, filtragem e ordenação.
Campos de options
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
pagination | object | Não | Configurações de paginação |
filtering | object | Não | Critérios de filtragem |
sorting | object | Não | Configurações de ordenação (por exemplo, {"position": 1}) |
Estrutura de paginação
Se pagination não for enviado, é retornada a primeira página com até 50 itens. Se for enviado, currentPage é obrigatório.
| Campo | Tipo | Padrão | Descrição |
|---|---|---|---|
currentPage | number | — | Número da página a obter (obrigatório quando pagination é enviado) |
pageItems | number | 50 | Número de itens por página (máximo: 50) |
Estrutura de filtragem
A filtragem usa o formato de consulta do MongoDB sobre os campos do item, com os nomes de campos exatamente como aparecem na resposta (por exemplo status, payload.referenceId, result.messageId). No endpoint list-with-messages, também é possível filtrar pelos campos da mensagem (por exemplo, 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
}
}
}
}
Estrutura de ordenação
A ordenação usa o formato de ordenação do MongoDB. 1 significa crescente e -1 significa decrescente. position é a ordem do destinatário no array recipients da requisição (a partir de 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
}
}
}
Exemplo de uso combinado
{
"bulkOperationId": "abc123xyz789",
"options": {
"pagination": {
"currentPage": 2,
"pageItems": 50
},
"filtering": {
"message.status": "delivered"
},
"sorting": {
"position": 1
}
}
}
Este exemplo lista a segunda página das mensagens entregues, na ordem dos destinatários.
- Combine
filteringepaginationpara consultas direcionadas - A resposta inclui
options.pagination.totalCounteoptions.pagination.totalPagespara navegação - O filtro
message.statussó funciona no endpointlist-with-messages
Items — detalhes e listagem de itens
Lista todos os itens de envio de uma operação em massa. Cada item representa uma entrada do array recipients.
List — lista de itens
POST https://app.monochat.ai/api/:slug/custom-functions/bulk-message-api-app/api/v2/bulk-operation-items/list.js
Parâmetros da requisição
| Parâmetro | Tipo | Obrigatório | Descrição |
|---|---|---|---|
bulkOperationId | string | Sim | ID da operação em massa a listar |
options | object | Não | Opções de paginação, filtragem e ordenação. Veja Estrutura de options para mais detalhes. |
Requisição — uso básico
{
"bulkOperationId": "abc123xyz789",
"options": {
"pagination": {
"currentPage": 1,
"pageItems": 50
}
}
}
Requisição — filtrar por um status específico
{
"bulkOperationId": "abc123xyz789",
"options": {
"pagination": {
"currentPage": 1,
"pageItems": 50
},
"filtering": {
"status": "failed"
}
}
}
Lista apenas os itens de envio com falha, com o motivo em error.
Resposta
{
"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 — lista com detalhes das mensagens
Tem os mesmos recursos do endpoint list (paginação, filtragem, ordenação). A diferença: cada item também traz os objetos message e session relacionados, quando existem. Isso permite ver o status da mensagem (delivered, read, error etc.) e o payload em uma única consulta.
POST https://app.monochat.ai/api/:slug/custom-functions/bulk-message-api-app/api/v2/bulk-operation-items/list-with-messages.js
Requisição — uso básico
{
"bulkOperationId": "abc123xyz789",
"options": {
"pagination": {
"currentPage": 1,
"pageItems": 50
}
}
}
Requisição — filtrar por status da mensagem
{
"bulkOperationId": "abc123xyz789",
"options": {
"pagination": {
"currentPage": 1,
"pageItems": 50
},
"filtering": {
"message.status": "delivered"
}
}
}
Este exemplo obtém apenas as mensagens com status "delivered".
Requisição — listar mensagens com falha
{
"bulkOperationId": "abc123xyz789",
"options": {
"pagination": {
"currentPage": 1,
"pageItems": 50
},
"filtering": {
"message.status": "error"
}
}
}
Usado para revisar as mensagens que tiveram erros de envio.
Resposta
{
"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": {}
}
}
Campos do item
| Campo | Tipo | Descrição |
|---|---|---|
_id | string | ID do item |
bulkOperationId | string | ID da operação em massa à qual este item pertence |
position | number | Ordem do destinatário no array recipients da requisição, a partir de 0 |
payload | object | O destinatário exatamente como foi enviado na requisição (username / userId / sessionId, referenceId, payload, isMerge) |
status | string | Status do item: pending, succeeded, failed, cancelled, unknown |
error | object | Somente em itens failed: code, message e retryable |
result.userId | string | ID do usuário destinatário |
result.sessionId | string | ID da sessão de conversa |
result.messageId | string | ID da mensagem enviada (ausente se nenhuma mensagem foi enviada) |
completedAt | string | Quando o item foi processado |
message | object | Detalhes da mensagem (somente em list-with-messages) |
session | object | Detalhes da conversa (somente em list-with-messages) |
Comparação entre List e List-With-Messages
| Recurso | list | list-with-messages |
|---|---|---|
| Paginação | Sim | Sim |
| Filtragem | Sim (somente campos do item) | Sim (campos do item e da mensagem) |
| Message / Session | Não | Sim (se existirem) |
| Desempenho | Rápido | Médio (executa JOIN) |
| Filtro message.status | Indisponível | Disponível |
- list: liste rapidamente todos os itens, filtre por referenceId, verifique os status dos itens
- list-with-messages: veja os status das mensagens do WhatsApp (delivered, read), inspecione os payloads das mensagens
- Exemplos de filtragem:
{"status": "failed"}— itens de envio com falha{"payload.referenceId": "ORDER-123"}— um ID de referência específico{"message.status": "delivered"}— mensagens entregues (somente list-with-messages){"message.status": "read"}— mensagens lidas (somente list-with-messages){"message.status": "error"}— mensagens com erros (somente list-with-messages){"message.status": {"$in": ["delivered", "read"]}}— mensagens entregues ou lidas (somente list-with-messages){"message.status": {"$nin": ["error", "not-sended"]}}— mensagens, exceto as com erro e as não enviadas (somente list-with-messages){"message": {"$exists": false}}— itens sem mensagem (somente list-with-messages){"status": {"$in": ["succeeded", "pending"]}}— itens bem-sucedidos ou pendentes
- O endpoint
listé mais rápido; prefira-o para verificações gerais de status - Use
list-with-messagesquando os detalhes da mensagem forem necessários - O máximo de itens por página (pageItems) é 50; o padrão é 50 se não for especificado
- O filtro
message.statussó funciona emlist-with-messages - Itens sem
result.messageIdnão têm objetomessage
Stop — cancelar o envio
Interrompe o envio em andamento de uma operação em massa. Todos os itens pending passam para o status cancelled e a operação em massa fica stopped. Os itens que já foram processados como succeeded ou failed não são afetados. Uma operação em massa agendada também pode ser interrompida antes do horário de scheduleAt.
POST https://app.monochat.ai/api/:slug/custom-functions/bulk-message-api-app/api/v2/bulk-operation/stop.js
Esta ação não pode ser desfeita. Um envio interrompido não pode ser retomado.
Parâmetros da requisição
| Parâmetro | Tipo | Obrigatório | Descrição |
|---|---|---|---|
bulkOperationId | string | Sim | ID da operação em massa a interromper |
{
"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"
}'
Resposta
Em uma requisição bem-sucedida, o corpo da resposta fica vazio. Um status HTTP 200 indica que a operação foi concluída com sucesso.
{}
- Somente as operações em massa criadas por esta API podem ser interrompidas
- Depois de interromper um envio, você pode usar o endpoint
showpara verificar o número de itens cancelados (bulkOperation.progress.cancelled) - Se a operação em massa não for encontrada, a API retorna o erro:
Bulk operation not found.