Saltar al contenido principal

Documentación de la Bulk Template Message API — v2

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 bulkOperationId, 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/v2/bulk-operation/send.js
Formato de la respuesta

Cada endpoint de este documento es una custom function. El cuerpo de la respuesta HTTP contiene los campos propios de la función (_id, title, pathString…) y la respuesta real del endpoint en result. Los ejemplos de respuesta de este documento muestran el contenido de result:

{
"_id": "function_id",
"title": "Show",
"pathString": "/bulk-message-api-app/api/v2/bulk-operation/show.js",
"result": {
"bulkOperation": { "_id": "abc123xyz789", "status": "running" }
}
}

Migrar desde v1​

v2 funciona en paralelo con v1, así que puede migrar a su propio ritmo. Los endpoints de v1 (/api/bulk-message/…, /api/bulk-message-records/…) se retirarán; las nuevas integraciones deben usar v2.

  1. Cambie las rutas de los endpoints a v2: …/api/bulk-message/… pasa a ser …/api/v2/bulk-operation/…, y …/api/bulk-message-records/… pasa a ser …/api/v2/bulk-operation-items/…. El cuerpo de la solicitud de send no cambia; ahora una sola solicitud admite hasta 100.000 destinatarios en lugar de 5.000.
  2. Envíe bulkOperationId en lugar de bulkMessageId en las solicitudes.
  3. Sustituya stats.js por show.js.
  4. Lea las respuestas con los nuevos nombres de campo de la tabla siguiente.

Los endpoints de v2 solo conocen las operaciones masivas creadas con el send de v2. Para seguir un mensaje masivo creado con v1 antes del cambio, siga usando los endpoints de v1 para él.

Endpoints​

v1v2Qué cambia en la respuesta
bulk-message/send.jsv2/bulk-operation/send.js{ bulkMessageId } pasa a ser { bulkOperationId }
bulk-message/stats.jsv2/bulk-operation/show.js{ bulkMessage, stats } pasa a ser { bulkOperation }
bulk-message/message-stats.jsv2/bulk-operation/message-stats.jsLos contadores están en la raíz en lugar de en messageStats
bulk-message/stop.jsv2/bulk-operation/stop.jsNada
bulk-message-records/list.jsv2/bulk-operation-items/list.jsbulkMessageRecords pasa a ser bulkOperationItems
bulk-message-records/list-with-messages.jsv2/bulk-operation-items/list-with-messages.jsIgual que list, y cada elemento incluye además session

Nombres de campo​

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 (mensaje masivo)bulkOperation (operación masiva)
bulkMessageRecord (registro)bulkOperationItem (elemento)
bulkMessageId en las solicitudes, en la respuesta de send y en los registrosbulkOperationId
username / userId / sessionId del registro tal como se enviaronpayload.username / payload.userId / payload.sessionId
referenceId del registropayload.referenceId
payload del registro (el payload de plantilla del destinatario)payload.payload
userId, sessionId, messageId del registro tras el envíoresult.userId, result.sessionId, result.messageId
estado de registro successsucceeded
errorMessage en los registros fallidoserror.message, junto a error.code y error.retryable
—position (el índice del destinatario en recipients)
filtro {"status": "success"}{"status": "succeeded"}
filtro {"referenceId": "…"}{"payload.referenceId": "…"}
errores de send schema-error, invalidRequestzod-schema-error, con la ruta del campo no válido en el mensaje

Funciones principales​

  • Envíe mensajes de plantilla masivos a 1–100.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 100.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/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" }
]
}'
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 bulkOperationId, que se puede usar para seguir el proceso de envío:

{
"bulkOperationId": "abc123xyz789"
}

Respuestas de error​

EstadoDescripción
recipients field is requiredNo se envió el campo recipients
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
zod-schema-errorUn campo del cuerpo de la solicitud no superó la validación del esquema (falta un campo obligatorio, tipo incorrecto, valor no admitido, más de un identificador en un destinatario o falta payload). El mensaje indica el campo, p. ej., recipients.0.referenceId: referenceId must be unique

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


Show: estado y estadísticas de la operación masiva​

Obtiene la operación masiva con su estado actual y los contadores de envío de sus elementos, en la clave bulkOperation.

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

Parámetros de la solicitud​

ParámetroTipoObligatorioDescripción
bulkOperationIdstringSíID de la operación masiva que se quiere seguir (devuelto 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"
}'

Respuesta​

{
"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​

Los campos están dentro de bulkOperation.

CampoTipoDescripción
statusstringEstado de la operación masiva: preparing, scheduled, pending, running, stopping, stopped, completed, failed
progress.totalnumberNúmero total de elementos
progress.pendingnumberElementos que siguen esperando en la cola
progress.succeedednumberElementos procesados correctamente para su envío
progress.failednumberElementos que han tenido un error de envío
progress.cancellednumberElementos cancelados por stop
progress.unknownnumberElementos cuyo resultado no se pudo determinar
result.outcomestringResultado final una vez terminada la operación masiva: success, partial, all-failed, cancelled, unknown
result.hasErrorsbooleantrue si al menos un elemento falló
scheduleAtstringHora de envío programada (solo en operaciones masivas programadas)
startedAt, completedAtstringCuándo empezó y terminó el envío
nota

progress.succeeded 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í.

Show frente a Message Stats
  • Endpoint show: muestra el estado de envío de los elementos (pending, succeeded, failed, cancelled, unknown)
  • Endpoint message-stats: muestra el estado real del mensaje (pending, sending, sent, delivered, read, error, etc.)
  • Un elemento puede estar en succeeded 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 elementos de envío con un ID de su propio sistema con fines de seguimiento (p. ej., número de pedido, ID de ticket). Se devuelve en cada elemento como payload.referenceId.

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

Importante
  • No es obligatorio
  • No se puede duplicar dentro de la misma operación masiva
  • Se puede reutilizar en distintas operaciones masivas

Message Stats: estado de los mensajes de WhatsApp​

Obtiene las estadísticas de estado de los mensajes de una operación masiva. A diferencia del endpoint show, este muestra el message.status real de los mensajes enviados en lugar del estado de los elementos.

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/v2/bulk-operation/message-stats.js

Parámetros de la solicitud​

ParámetroTipoObligatorioDescripción
bulkOperationIdstringSíID de la operación masiva que se quiere 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"
}'

Respuesta​

{
"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​

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-messagenumberElementos sin mensaje (aún en cola, fallidos o cancelados)
totalnumberNúmero total de elementos
Consejos de uso
  • Un valor alto de no-message mientras la operación masiva está en running 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., {"position": 1})

Estructura de pagination​

Si no se envía pagination, se devuelve la primera página con hasta 50 elementos. Si se envía, currentPage es obligatorio.

CampoTipoPor defectoDescripción
currentPagenumber—Número de página que se quiere obtener (obligatorio cuando se envía pagination)
pageItemsnumber50Número de elementos por página (máximo: 50)

Estructura de filtering​

El filtrado se realiza con el formato de consulta de MongoDB sobre los campos de los elementos, con los nombres de campo exactamente como aparecen en la respuesta (p. ej., status, payload.referenceId, result.messageId). En el endpoint list-with-messages también puede filtrar por campos del mensaje (p. ej., 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
}
}
}
}

Estructura de sorting​

La ordenación se realiza con el formato de ordenación de MongoDB. 1 significa ascendente y -1 descendente. position es el orden del destinatario en el array recipients de la solicitud (empezando por 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
}
}
}

Ejemplo de uso combinado​

{
"bulkOperationId": "abc123xyz789",
"options": {
"pagination": {
"currentPage": 2,
"pageItems": 50
},
"filtering": {
"message.status": "delivered"
},
"sorting": {
"position": 1
}
}
}

Este ejemplo lista la segunda página de mensajes entregados, en el orden de los destinatarios.

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

Items: detalles y listado de elementos​

Lista todos los elementos de envío de una operación masiva. Cada elemento corresponde a una entrada del array recipients.

List: lista de elementos​

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

Parámetros de la solicitud​

ParámetroTipoObligatorioDescripción
bulkOperationIdstringSíID de la operación masiva que se quiere listar
optionsobjectNoOpciones de paginación, filtrado y ordenación. Consulte los detalles en Estructura de options.

Solicitud: uso básico​

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

Solicitud: filtrar por un estado concreto​

{
"bulkOperationId": "abc123xyz789",
"options": {
"pagination": {
"currentPage": 1,
"pageItems": 50
},
"filtering": {
"status": "failed"
}
}
}

Lista solo los elementos de envío fallidos, con el motivo en error.

Respuesta​

{
"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 con detalles de los mensajes​

Tiene las mismas características que el endpoint list (paginación, filtrado, ordenación). La diferencia: cada elemento incluye además los objetos message y session relacionados, cuando existen. 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/v2/bulk-operation-items/list-with-messages.js

Solicitud: uso básico​

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

Solicitud: filtrar por estado del mensaje​

{
"bulkOperationId": "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​

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

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

Respuesta​

{
"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 del elemento​

CampoTipoDescripción
_idstringID del elemento
bulkOperationIdstringID de la operación masiva a la que pertenece este elemento
positionnumberOrden del destinatario en el array recipients de la solicitud, empezando por 0
payloadobjectEl destinatario exactamente como se envió en la solicitud (username / userId / sessionId, referenceId, payload, isMerge)
statusstringEstado del elemento: pending, succeeded, failed, cancelled, unknown
errorobjectSolo en elementos failed: code, message y retryable
result.userIdstringID del usuario destinatario
result.sessionIdstringID de la sesión de conversación
result.messageIdstringID del mensaje enviado (no aparece si no se envió ningún mensaje)
completedAtstringCuándo se procesó el elemento
messageobjectDetalles del mensaje (solo en list-with-messages)
sessionobjectDetalles de la conversación (solo en list-with-messages)

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

Característicalistlist-with-messages
PaginaciónSíSí
FiltradoSí (solo campos del elemento)Sí (campos del elemento y del mensaje)
Message / SessionNoSí (si existen)
RendimientoRápidoMedio (realiza un JOIN)
Filtro message.statusNo disponibleDisponible
Escenarios de uso
  • list: lista rápidamente todos los elementos, filtra por referenceId, comprueba el estado de los elementos
  • list-with-messages: consulta el estado de los mensajes de WhatsApp (delivered, read), inspecciona los payloads de los mensajes
  • Ejemplos de filtrado:
    • {"status": "failed"}: elementos de envío fallidos
    • {"payload.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)
    • {"message": {"$exists": false}}: elementos sin mensaje (solo list-with-messages)
    • {"status": {"$in": ["succeeded", "pending"]}}: elementos 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 elementos 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 elementos sin result.messageId no tienen objeto message

Stop: cancelar el envío​

Detiene el envío en curso de una operación masiva. Todos los elementos pending pasan al estado cancelled y la operación masiva pasa a stopped. Los elementos ya procesados como succeeded o failed no se ven afectados. Una operación masiva programada también se puede detener antes de su hora scheduleAt.

POST https://app.monochat.ai/api/:slug/custom-functions/bulk-message-api-app/api/v2/bulk-operation/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
bulkOperationIdstringSíID de la operación masiva que se quiere detener
{
"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"
}'

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 las operaciones masivas creadas mediante esta API
  • Tras detener un envío, puede usar el endpoint show para verificar el número de elementos cancelados (bulkOperation.progress.cancelled)
  • Si no se encuentra la operación masiva, la API devuelve el error: Bulk operation not found.