Saltar al contenido principal

Documentación de la Bulk Template Message API

Esta API le permite enviar mensajes de plantilla a varios destinatarios de forma simultánea a través del canal de WhatsApp.

El envío de los mensajes se procesa de forma asíncrona; la solicitud a la API devuelve de inmediato un bulkMessageId, mientras los mensajes se ponen en cola y se procesan en segundo plano.

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

Funciones principales​

  • Envíe mensajes de plantilla masivos a 1–5.000 destinatarios en una sola solicitud
  • Variables personalizadas para cada destinatario (HEADER, BODY, BUTTONS, CAROUSEL)
  • defaultPayload compartido para todos los destinatarios, con combinación del payload específico de cada destinatario (isMerge)
  • Envío programado (scheduleAt)
  • Indique los destinatarios mediante username (número de teléfono), userId o sessionId
  • Envíe varios mensajes al mismo usuario en una sola solicitud masiva
  • referenceId opcional para el seguimiento de registros con sistemas externos
  • Asigne automáticamente las conversaciones a un usuario o a un grupo de trabajo tras el envío (action)
aviso

Esta API solo puede enviar plantillas que hayan sido aprobadas por Meta.

El nombre de la plantilla y el código de idioma deben coincidir exactamente con la plantilla registrada en Meta Business Manager.

Parámetros de la solicitud​

Parámetros de nivel superior​

ParámetroTipoObligatorioDescripción
channelUsernamestringSíNúmero del canal de WhatsApp utilizado para enviar el mensaje (p. ej. "908506669933")
connectorBrandstringSíMarca del conector del canal. Valor admitido actualmente: "whatsapp"
titlestringNoTítulo de la campaña. Se usa para mostrarla en el panel. Por defecto: "-"
scheduleAtstring (ISO 8601)NoFecha y hora de envío programado (p. ej. "2026-06-10T10:00:00.000Z"). Si se omite, los mensajes se envían de inmediato.
defaultPayloadobjectCondicional*Payload de plantilla por defecto que se aplica a todos los destinatarios. Obligatorio si un destinatario no aporta su propio payload.
recipientsarraySíLista de destinatarios. Mínimo 1, máximo 5.000 destinatarios.
actionobjectNoAcción que se aplica a la conversación tras el envío. assign-to-user o assign-to-workgroup.

*Si todos los destinatarios aportan su propio payload, defaultPayload es opcional.

Estructura del destinatario​

Para cada destinatario se debe indicar exactamente uno de username, userId o sessionId. No se pueden usar varios identificadores a la vez, y omitirlos todos provoca un error.

Para enviar varios mensajes al mismo usuario en una sola solicitud masiva, añada el mismo identificador varias veces a la lista de destinatarios.

CampoTipoDescripción
usernamestringNúmero de teléfono del destinatario (p. ej. "905554443322"). Si el usuario no existe en el sistema, se crea automáticamente.
userIdstringID de un usuario existente en el sistema.
sessionIdstringID de una sesión de conversación existente en el sistema.
referenceIdstringID de referencia opcional (máx. 256 caracteres) para hacerlo coincidir con registros de sistemas externos (CRM, pedido, ticket, etc.). Debe ser único dentro del envío masivo, si se indica.
payloadobjectPayload de plantilla específico del destinatario (opcional). Si isMerge: true, se combina con defaultPayload.
isMergebooleanSustituye el comportamiento de combinación para este destinatario (opcional). Si se omite, se usa defaultPayload.isMerge.

Estructura de la acción​

CampoTipoDescripción
action.keystring"assign-to-user" asigna la conversación a un agente concreto; "assign-to-workgroup" la asigna a un grupo de trabajo.
action.valuestringID del usuario o del grupo de trabajo de destino.

Estructura del payload de plantilla​

defaultPayload y el payload específico de cada destinatario comparten la misma estructura. Para los mensajes de plantilla, debe indicarse type: "template".

{
"type": "template",
"template": {
"templateName": "order_confirmation",
"languageCode": "tr-TR",
"variables": []
},
"isMerge": true
}
CampoTipoObligatorioDescripción
typestringSíTipo de payload. Para mensajes de plantilla: "template"
template.templateNamestringSí*Nombre de la plantilla registrada en Meta. Es opcional en los payloads de destinatario cuando se usa isMerge: true (se hereda del payload por defecto).
template.languageCodestringNoCódigo de idioma de la plantilla (p. ej. "tr", "en", "tr-TR", "en-US"). Debe coincidir exactamente con el idioma registrado en Meta.
template.variablesarrayNoLista de variables aplicadas a los componentes de la plantilla. Se detalla más abajo.
isMergebooleanNotrue: el payload del destinatario se combina en profundidad con defaultPayload. false u omitido: el payload del destinatario sustituye por completo a defaultPayload.
Comportamiento de isMerge
  • Si defaultPayload.isMerge: true y el destinatario aporta su propio payload, se aplica una combinación en profundidad.
  • Con la combinación en profundidad, el destinatario puede aportar solo variables; templateName y languageCode se heredan del payload por defecto.
  • El campo isMerge del destinatario sustituye a defaultPayload.isMerge.
  • Si un destinatario no aporta un payload, siempre se usa defaultPayload.

Estructura de las variables​

Cada elemento del array variables corresponde a un componente de la plantilla. Un tipo de componente (type) solo puede aparecer una vez en el array.

typeDescripciónparameterscards
"HEADER"Componente de encabezado de la plantilla. Variable de texto o URL multimedia (imagen, vídeo, documento)Sí—
"BODY"Variables de texto del cuerpo de la plantillaSí—
"BUTTONS"Variables de sufijo de URL dinámico para los botonesSí—
"CAROUSEL"Componentes de tarjeta para plantillas de carrusel—Sí

Formatos de parámetros​

El campo parameters puede indicarse en tres formatos distintos:

// 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" }
¿Qué formato debo usar?
  • Si su plantilla de Meta usa marcadores como {{1}}, {{2}}, utilice el formato de array o el de objeto con claves numéricas.
  • Si su plantilla usa marcadores con nombre como {{firstName}} o {{orderTotal}}, utilice el formato de objeto con claves con nombre.
  • Al usar arrays, el orden importa: el primer elemento corresponde a {{1}}, el segundo a {{2}}, y así sucesivamente.

Componente HEADER​

Use el componente HEADER cuando el encabezado de la plantilla contenga contenido multimedia (imagen, vídeo, documento) o 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​

Se usa para las variables de texto dinámico dentro del cuerpo de la plantilla.

// 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​

Se usa para botones con sufijos de URL dinámicos. Si la plantilla contiene varios botones de URL, solo se indexan de forma secuencial los botones con variables (los botones sin variables o los botones FLOW se ignoran).

// 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"]
}

En las plantillas de carrusel, las variables de los componentes se definen por separado para cada tarjeta.

{
"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"]
}
]
}
]
}
aviso

La longitud del array cards debe coincidir exactamente con el número de tarjetas definidas en la plantilla.

Ejemplos​

1. Plantilla simple: sin variables, mismo contenido para todos los destinatarios​

Esta es la forma más sencilla de enviar una plantilla estática sin variables a varios destinatarios.

{
"channelUsername": "908506669933",
"connectorBrand": "whatsapp",
"title": "General Announcement",
"defaultPayload": {
"type": "template",
"template": {
"templateName": "hello_world",
"languageCode": "tr-TR"
}
},
"recipients": [{ "username": "905554443301" }, { "username": "905554443302" }, { "username": "905554443303" }]
}
curl --location 'https://app.monochat.ai/api/:slug/custom-functions/bulk-message-api-app/api/bulk-message/send.js' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer YOUR_JWT_TOKEN' \
--data '{
"channelUsername": "908506669933",
"connectorBrand": "whatsapp",
"title": "General Announcement",
"defaultPayload": {
"type": "template",
"template": {
"templateName": "hello_world",
"languageCode": "tr-TR"
}
},
"recipients": [
{ "username": "905554443301" },
{ "username": "905554443302" },
{ "username": "905554443303" }
]
}'
consejo
  • Los destinatarios indicados mediante username se crean automáticamente si aún no existen en el sistema
  • Todos los destinatarios usan el mismo defaultPayload; no se necesitan datos específicos de cada destinatario
  • Cuando no se especifica isMerge, cada destinatario usa directamente el defaultPayload

2. Plantilla con variables de cuerpo compartidas​

La misma plantilla se envía a todos los destinatarios con valores de variables idénticos. La plantilla contiene marcadores como {{1}} y {{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" }]
}
consejo
  • En este ejemplo, el cuerpo de la plantilla podría contener un texto como: "¡Disfrute de un descuento de {{1}} en nuestra campaña! Oferta válida hasta el {{2}}."
  • parameters[0] sustituye a {{1}}, mientras que parameters[1] sustituye a {{2}}

3. Plantilla personalizada: variables por destinatario con isMerge​

Se usan valores de variables diferentes para cada destinatario. Al establecer isMerge: true en el defaultPayload, los destinatarios solo necesitan aportar variables; templateName y languageCode se heredan del payload por defecto.

En este ejemplo, la plantilla incluye tanto un encabezado multimedia como variables de cuerpo 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"]
}
]
}
}
}
]
}
consejo
  • Gracias a isMerge: true, no es necesario repetir templateName en el payload de cada destinatario
  • El array variables de cada destinatario es completamente independiente
  • La URL del contenido multimedia del encabezado debe ser de acceso público
  • Si se omite type en el payload del destinatario, se hereda defaultPayload.type

4. Variable de botón de URL​

Use el componente BUTTONS cuando la plantilla contenga un botón con un sufijo de URL dinámico. Por ejemplo, un número de seguimiento que se añade a la 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"]
}
]
}
}
}
]
}
consejo
  • Los parámetros de BUTTONS se asignan según el orden de los botones que contienen variables
  • Los botones FLOW y los botones sin variables se ignoran; la indexación solo se aplica a los botones de URL dinámicos
  • Si la URL del botón de la plantilla es https://example.com/track/{{1}}, entonces parameters[0] sustituye a {{1}}

5. Envío programado​

Programe un mensaje para enviarlo en una fecha y hora futuras. scheduleAt debe indicarse como una marca de tiempo 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" }
}
]
}
}
}
]
}
consejo
  • scheduleAt debe indicarse en la zona horaria UTC (p. ej., para las 10:00 hora de Turquía, use 07:00:00.000Z)
  • Este ejemplo usa el formato de parámetros con nombre; la plantilla debe contener marcadores como {{name}} y {{discountRate}}
  • Con action, las conversaciones creadas por el envío del mensaje se asignan automáticamente al grupo de trabajo indicado

Respuesta​

Una solicitud correcta devuelve un bulkMessageId, que se puede usar para seguir el proceso de envío:

{
"bulkMessageId": "abc123xyz789"
}

Respuestas de error​

EstadoDescripción
Channel not foundNo se encontró ningún canal verificado que coincida con channelUsername y connectorBrand
Channel is not verifiedEl canal encontrado existe, pero aún no ha sido verificado
invalidRequestSe indicaron varios identificadores para un destinatario o falta un payload obligatorio
channelNotFoundNo se encontró ningún canal activo que coincida con el channelId indicado
schema-errorUn campo del cuerpo de la solicitud no superó la validación del esquema (falta un campo obligatorio, tipo incorrecto o valor no admitido)

El bulkMessageId devuelto se puede usar con los endpoints siguientes para consultar las estadísticas de envío y detener el proceso de envío.


Stats: estadísticas de envío​

Obtiene el estado de envío actual de un mensaje masivo. Devuelve el número de registros pendientes, correctos, fallidos y cancelados.

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

Parámetros de la solicitud​

ParámetroTipoObligatorioDescripción
bulkMessageIdstringSíID del mensaje masivo que se quiere seguir (devuelto por createBulkPerRecipient)
{
"bulkMessageId": "abc123xyz789"
}
curl --location 'https://app.monochat.ai/api/:slug/custom-functions/bulk-message-api-app/api/bulk-message/stats.js' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer YOUR_JWT_TOKEN' \
--data '{
"bulkMessageId": "abc123xyz789"
}'

Respuesta​

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

Campos de stats​

CampoTipoDescripción
stats.pendingnumberNúmero de registros que siguen esperando en la cola
stats.successnumberNúmero de registros procesados correctamente para su envío
stats.failednumberNúmero de registros que han tenido un error de envío
stats.cancellednumberNúmero de registros cancelados
stats.totalnumberNúmero total de registros (pending + success + failed + cancelled)
nota

stats.success indica que el sistema entregó correctamente el mensaje para su envío. No garantiza que Meta haya entregado el mensaje al destinatario. Las actualizaciones de estado posteriores generadas por Meta (como delivered, read o failed) no afectan a este contador y no se reflejan aquí.

Stats frente a Message Stats
  • Endpoint stats: muestra el estado del trabajo de envío (pending, success, failed, cancelled)
  • Endpoint message-stats: muestra el estado real del mensaje (pending, sending, sent, delivered, read, error, etc.)
  • Un trabajo puede ser correcto y, aun así, el mensaje puede no haberse entregado ni leído todavía

ID de referencia​

referenceId es un campo opcional que puede usar para hacer coincidir los registros de envío con un ID de su propio sistema con fines de seguimiento (p. ej., número de pedido, ID de ticket).

Si se indica, debe ser único dentro del envío masivo (máx. 256 caracteres).

Importante
  • No es obligatorio
  • No se puede duplicar dentro del mismo mensaje masivo
  • Se puede reutilizar en distintos mensajes masivos

Message Stats: estado de los mensajes de WhatsApp​

Obtiene las estadísticas de estado de los mensajes de un mensaje masivo. A diferencia del endpoint stats, este muestra el message.status real de cada registro en lugar del estado del trabajo.

Estados posibles del mensaje: pending, sending, sent, delivered, read, deleted, warning, error, unknown, not-sended

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

Parámetros de la solicitud​

ParámetroTipoObligatorioDescripción
bulkMessageIdstringSíID del mensaje masivo que se quiere consultar
{
"bulkMessageId": "abc123xyz789"
}
curl --location 'https://app.monochat.ai/api/:slug/custom-functions/bulk-message-api-app/api/bulk-message/message-stats.js' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer YOUR_JWT_TOKEN' \
--data '{
"bulkMessageId": "abc123xyz789"
}'

Respuesta​

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

Campos de Message Stats​

CampoTipoDescripción
pendingnumberMensajes aún no enviados
sendingnumberMensajes que se están enviando en este momento
sentnumberMensajes entregados a WhatsApp, aún sin confirmar su entrega
deliverednumberMensajes entregados en el teléfono del destinatario
readnumberMensajes leídos por el destinatario
deletednumberMensajes eliminados
warningnumberMensajes con advertencias
errornumberMensajes con errores
unknownnumberMensajes con estado desconocido
not-sendednumberMensajes que no se pudieron enviar
no-messagenumberRegistros sin mensaje todavía (aún en cola)
totalnumberNúmero total de registros
Consejos de uso
  • Un valor alto de no-message indica que el envío sigue en curso
  • El valor de delivered muestra los mensajes entregados correctamente
  • El valor de read se puede usar para medir la interacción con la campaña
  • Puede consultar este endpoint periódicamente para un seguimiento en tiempo real

Estructura de options: paginación, filtrado y ordenación​

El parámetro options usado en los endpoints list y list-with-messages ofrece una estructura estándar para la paginación, el filtrado y la ordenación.

Campos de options​

CampoTipoObligatorioDescripción
paginationobjectNoAjustes de paginación
filteringobjectNoCriterios de filtrado
sortingobjectNoAjustes de ordenación (p. ej., {"createdAt": -1})

Estructura de pagination​

CampoTipoPor defectoDescripción
currentPagenumber1Número de página que se quiere obtener
pageItemsnumber50Número de registros por página (máximo: 50)

Estructura de filtering​

El filtrado se realiza con el formato de consulta de MongoDB. Puede filtrar por campos del registro. En el endpoint list-with-messages también puede filtrar por campos del mensaje (p. ej., message.status).

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

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

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

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

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

Estructura de sorting​

La ordenación se realiza con el formato de ordenación de MongoDB. 1 significa ascendente y -1 descendente.

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

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

Ejemplo de uso combinado​

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

Este ejemplo ordena los mensajes entregados del más reciente al más antiguo.

Consejos prácticos
  • Combine filtering y pagination para consultas específicas
  • La respuesta incluye options.pagination.totalCount y options.pagination.totalPages para la navegación
  • El filtro message.status solo funciona en el endpoint list-with-messages

Records: detalles y listado de registros​

Lista todos los registros de envío de un mensaje masivo. Cada registro representa un único mensaje enviado a un destinatario.

List: lista de registros​

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

Parámetros de la solicitud​

ParámetroTipoObligatorioDescripción
bulkMessageIdstringSíID del mensaje masivo que se quiere listar
optionsobjectNoOpciones de paginación, filtrado y ordenación. Consulte los detalles en Estructura de options.

Solicitud: uso básico​

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

Solicitud: filtrar por un estado concreto​

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

Lista solo los registros de envío correctos (record.status = "success").

Respuesta​

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

List With Messages: lista con detalles de los mensajes​

Tiene las mismas características que el endpoint list (paginación, filtrado, ordenación). La única diferencia: si un registro tiene un messageId, también se devuelve el objeto message relacionado. Esto le permite ver el estado del mensaje (delivered, read, error, etc.) y su payload en una sola consulta.

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

Solicitud: uso básico​

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

Solicitud: filtrar por estado del mensaje​

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

Este ejemplo obtiene solo los mensajes con estado "delivered".

Solicitud: listar los mensajes fallidos​

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

Sirve para revisar los mensajes que tuvieron errores de envío.

Respuesta​

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

Campos del registro​

CampoTipoDescripción
_idstringID del registro
bulkMessageIdstringID del mensaje masivo al que pertenece este registro
userIdstringID del usuario destinatario
sessionIdstringID de la sesión de conversación
messageIdstringID del mensaje enviado (null si aún no se ha enviado)
referenceIdstringID de referencia opcional (si se indicó)
statusstringEstado del registro: pending, success, failed, cancelled
messageobjectDetalles del mensaje (solo en list-with-messages)

Comparación entre List y List-With-Messages​

Característicalistlist-with-messages
PaginaciónSíSí
FiltradoSí (solo campos del registro)Sí (campos del registro y del mensaje)
Objeto messageNoSí (si existe messageId)
RendimientoRápidoMedio (realiza un JOIN)
Filtro message.statusNo disponibleDisponible
Escenarios de uso
  • list: lista rápidamente todos los registros, filtra por referenceId, comprueba el estado de los registros
  • list-with-messages: consulta el estado de los mensajes de WhatsApp (delivered, read), inspecciona los payloads de los mensajes
  • Ejemplos de filtrado:
    • {"status": "failed"}: registros de envío fallidos
    • {"referenceId": "ORDER-123"}: un ID de referencia concreto
    • {"message.status": "delivered"}: mensajes entregados (solo list-with-messages)
    • {"message.status": "read"}: mensajes leídos (solo list-with-messages)
    • {"message.status": "error"}: mensajes con errores (solo list-with-messages)
    • {"message.status": {"$in": ["delivered", "read"]}}: mensajes que están entregados o leídos (solo list-with-messages)
    • {"message.status": {"$nin": ["error", "not-sended"]}}: mensajes sin incluir errores ni no enviados (solo list-with-messages)
    • {"status": {"$in": ["success", "pending"]}}: registros correctos o pendientes
Rendimiento y notas de uso
  • El endpoint list es más rápido; prefiéralo para las comprobaciones generales de estado
  • Use list-with-messages cuando necesite los detalles de los mensajes
  • El máximo de registros por página (pageItems) es 50; si no se especifica, el valor por defecto es 50
  • El filtro message.status solo funciona en list-with-messages
  • Los registros con messageId nulo tendrán objetos message nulos

Stop: cancelar el envío​

Detiene el envío de un mensaje masivo en curso. El trabajo en cola se cancela y todos los registros pending pasan al estado cancelled. Los registros que ya se han procesado como success o failed no se ven afectados.

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

Esta acción no se puede deshacer. Un envío detenido no se puede reanudar.

Parámetros de la solicitud​

ParámetroTipoObligatorioDescripción
bulkMessageIdstringSíID del mensaje masivo que se quiere detener
{
"bulkMessageId": "abc123xyz789"
}
curl --location 'https://app.monochat.ai/api/:slug/custom-functions/bulk-message-api-app/api/bulk-message/stop.js' \
--header 'Content-Type: application/json' \
--header 'Authorization: Bearer YOUR_JWT_TOKEN' \
--data '{
"bulkMessageId": "abc123xyz789"
}'

Respuesta​

Si la solicitud es correcta, el cuerpo de la respuesta está vacío. Un estado HTTP 200 indica que la operación se completó correctamente.

{}
consejo
  • Solo se pueden detener los mensajes masivos creados mediante esta API
  • Tras detener un envío, puede usar el endpoint stats para verificar el número de registros cancelados
  • Si no se encuentra el mensaje masivo, la API devuelve el error: bulkMessageNotFound