Passa al contenuto principale

Documentazione dell’API Bulk Template Message — v2

Questa API permette di inviare messaggi template a più destinatari contemporaneamente tramite il canale WhatsApp.

L’invio dei messaggi viene elaborato in modo asincrono; la richiesta API restituisce subito un bulkOperationId, mentre i messaggi vengono messi in coda ed elaborati in background.

POST https://app.monochat.ai/api/:slug/custom-functions/bulk-message-api-app/api/v2/bulk-operation/send.js
Formato della risposta

Ogni endpoint di questo documento è una custom function. Il corpo della risposta HTTP contiene i campi propri della funzione (_id, title, pathString…) e la risposta effettiva dell’endpoint in result. Gli esempi di risposta di questo documento mostrano il contenuto di result:

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

Migrazione dalla v1​

La v2 funziona in parallelo alla v1, quindi è possibile migrare con i propri tempi. Gli endpoint v1 (/api/bulk-message/…, /api/bulk-message-records/…) verranno dismessi; le nuove integrazioni devono usare la v2.

  1. Passare i percorsi degli endpoint alla v2: …/api/bulk-message/… diventa …/api/v2/bulk-operation/… e …/api/bulk-message-records/… diventa …/api/v2/bulk-operation-items/…. Il corpo della richiesta send non cambia; una singola richiesta ora accetta fino a 100.000 destinatari invece di 5.000.
  2. Inviare bulkOperationId invece di bulkMessageId nelle richieste.
  3. Sostituire stats.js con show.js.
  4. Leggere le risposte con i nuovi nomi dei campi indicati nella tabella seguente.

Gli endpoint v2 conoscono solo le operazioni in blocco create con il send della v2. Per seguire un messaggio in blocco creato con la v1 prima del passaggio, continuare a usare gli endpoint v1.

Endpoint​

v1v2Cosa cambia nella risposta
bulk-message/send.jsv2/bulk-operation/send.js{ bulkMessageId } diventa { bulkOperationId }
bulk-message/stats.jsv2/bulk-operation/show.js{ bulkMessage, stats } diventa { bulkOperation }
bulk-message/message-stats.jsv2/bulk-operation/message-stats.jsI contatori sono al livello principale invece che sotto messageStats
bulk-message/stop.jsv2/bulk-operation/stop.jsNiente
bulk-message-records/list.jsv2/bulk-operation-items/list.jsbulkMessageRecords diventa bulkOperationItems
bulk-message-records/list-with-messages.jsv2/bulk-operation-items/list-with-messages.jsCome list, e ogni elemento contiene anche session

Nomi dei campi​

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 (messaggio in blocco)bulkOperation (operazione in blocco)
bulkMessageRecord (record)bulkOperationItem (elemento)
bulkMessageId nelle richieste, nella risposta di send e nei recordbulkOperationId
username / userId / sessionId del record così come inviatipayload.username / payload.userId / payload.sessionId
referenceId del recordpayload.referenceId
payload del record (il payload del template del destinatario)payload.payload
userId, sessionId, messageId del record dopo l’invioresult.userId, result.sessionId, result.messageId
stato del record successsucceeded
errorMessage sui record non riuscitierror.message, accanto a error.code e error.retryable
—position (l’indice del destinatario in recipients)
filtro {"status": "success"}{"status": "succeeded"}
filtro {"referenceId": "…"}{"payload.referenceId": "…"}
errori di send schema-error, invalidRequestzod-schema-error, con il percorso del campo non valido nel messaggio

Funzionalità principali​

  • Invio di messaggi template in blocco a 1–100.000 destinatari in una singola richiesta
  • Variabili personalizzate per ogni destinatario (HEADER, BODY, BUTTONS, CAROUSEL)
  • defaultPayload condiviso da tutti i destinatari, con unione del payload specifico di ciascun destinatario (isMerge)
  • Invio programmato (scheduleAt)
  • Indicazione dei destinatari tramite username (numero di telefono), userId o sessionId
  • Invio di più messaggi allo stesso utente all’interno di una singola richiesta in blocco
  • referenceId facoltativo per collegare i record a sistemi esterni
  • Assegnazione automatica delle conversazioni a un utente o a un gruppo di lavoro dopo l’invio (action)
avvertenza

Questa API può inviare solo template approvati da Meta.

Il nome del template e il codice lingua devono corrispondere esattamente al template registrato in Meta Business Manager.

Parametri della richiesta​

Parametri di primo livello​

ParametroTipoObbligatorioDescrizione
channelUsernamestringSìNumero del canale WhatsApp usato per inviare il messaggio (ad es. "908506669933")
connectorBrandstringSìMarca del connettore del canale. Valore attualmente supportato: "whatsapp"
titlestringNoTitolo della campagna. Usato per la visualizzazione nella dashboard. Predefinito: "-"
scheduleAtstring (ISO 8601)NoData e ora di invio programmato (ad es. "2026-06-10T10:00:00.000Z"). Se omesso, i messaggi vengono inviati subito.
defaultPayloadobjectCondizionale*Payload predefinito del template applicato a tutti i destinatari. Obbligatorio se un destinatario non fornisce un proprio payload.
recipientsarraySìElenco dei destinatari. Minimo 1, massimo 100.000 destinatari.
actionobjectNoAzione applicata alla conversazione dopo l’invio. assign-to-user o assign-to-workgroup.

*Se ogni destinatario fornisce un proprio payload, defaultPayload è facoltativo.

Struttura del destinatario​

Per ogni destinatario deve essere indicato esattamente uno tra username, userId e sessionId. Non si possono usare più identificativi insieme e ometterli tutti provoca un errore.

Per inviare più messaggi allo stesso utente all’interno di una singola richiesta in blocco, aggiungere lo stesso identificativo più volte all’elenco dei destinatari.

CampoTipoDescrizione
usernamestringNumero di telefono del destinatario (ad es. "905554443322"). Se l’utente non esiste nel sistema, viene creato automaticamente.
userIdstringID di un utente esistente nel sistema.
sessionIdstringID di una sessione di conversazione esistente nel sistema.
referenceIdstringID di riferimento facoltativo (massimo 256 caratteri) per il collegamento con i record di sistemi esterni (CRM, ordine, ticket e così via). Se indicato, deve essere univoco all’interno dell’invio in blocco.
payloadobjectPayload del template specifico del destinatario (facoltativo). Se isMerge: true, viene unito a defaultPayload.
isMergebooleanSostituisce il comportamento di unione per questo destinatario (facoltativo). Se omesso, viene usato defaultPayload.isMerge.

Struttura dell’azione​

CampoTipoDescrizione
action.keystring"assign-to-user" assegna la conversazione a un operatore specifico; "assign-to-workgroup" la assegna a un gruppo di lavoro.
action.valuestringID dell’utente o del gruppo di lavoro di destinazione.

Struttura del payload del template​

defaultPayload e il payload specifico del destinatario hanno la stessa struttura. Per i messaggi template deve essere indicato type: "template".

{
"type": "template",
"template": {
"templateName": "order_confirmation",
"languageCode": "tr-TR",
"variables": []
},
"isMerge": true
}
CampoTipoObbligatorioDescrizione
typestringSìTipo di payload. Per i messaggi template: "template"
template.templateNamestringSì*Nome del template registrato in Meta. Facoltativo nei payload dei destinatari quando si usa isMerge: true (viene ereditato dal payload predefinito).
template.languageCodestringNoCodice lingua del template (ad es. "tr", "en", "tr-TR", "en-US"). Deve corrispondere esattamente alla lingua registrata in Meta.
template.variablesarrayNoElenco delle variabili applicate ai componenti del template. Dettagli più avanti.
isMergebooleanNotrue: il payload del destinatario viene unito in profondità a defaultPayload. false oppure omesso: il payload del destinatario sostituisce completamente defaultPayload.
Comportamento di isMerge
  • Se defaultPayload.isMerge: true e il destinatario fornisce un proprio payload, viene applicata un’unione in profondità.
  • Con l’unione in profondità, il destinatario può fornire solo variables; templateName e languageCode vengono ereditati dal payload predefinito.
  • Il campo isMerge del destinatario sostituisce defaultPayload.isMerge.
  • Se un destinatario non fornisce un payload, viene sempre usato defaultPayload.

Struttura delle variabili​

Ogni elemento dell’array variables corrisponde a un componente del template. Un tipo di componente (type) può comparire una sola volta nell’array.

typeDescrizioneparameterscards
"HEADER"Componente di intestazione del template. Variabile di testo o URL multimediale (immagine, video, documento)Sì—
"BODY"Variabili di testo del corpo del templateSì—
"BUTTONS"Variabili del suffisso URL dinamico per i pulsantiSì—
"CAROUSEL"Componenti delle schede per i template a carosello—Sì

Formati dei parametri​

Il campo parameters può essere indicato in tre formati diversi:

// 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" }
Quale formato devo usare?
  • Se il tuo template Meta usa segnaposto come {{1}}, {{2}}, usa il formato array oppure il formato oggetto con chiavi numeriche.
  • Se il tuo template usa segnaposto con nome come {{firstName}} o {{orderTotal}}, usa il formato oggetto con chiavi nominali.
  • Con gli array l’ordine conta: il primo elemento corrisponde a {{1}}, il secondo a {{2}} e così via.

Componente HEADER​

Usa il componente HEADER quando l’intestazione del template contiene un contenuto multimediale (immagine, video, documento) o testo dinamico.

// Media header (image URL)
{
"type": "HEADER",
"parameters": ["https://example.com/product-image.jpg"]
}

// Text header variable
{
"type": "HEADER",
"parameters": ["Special Campaign"]
}

Componente BODY​

Serve per le variabili di testo dinamiche nel corpo del 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​

Serve per i pulsanti con suffissi URL dinamici. Se il template contiene più pulsanti URL, vengono indicizzati in sequenza solo i pulsanti con variabili (i pulsanti senza variabili o i pulsanti FLOW vengono ignorati).

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

Per i template a carosello, le variabili dei componenti sono definite separatamente per ogni scheda.

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

La lunghezza dell’array cards deve corrispondere esattamente al numero di schede definite nel template.

Esempi​

1. Template semplice — nessuna variabile, stesso contenuto per tutti i destinatari​

È il modo più semplice per inviare a più destinatari un template statico senza variabili.

{
"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" }
]
}'
suggerimento
  • I destinatari indicati tramite username vengono creati automaticamente se non esistono già nel sistema
  • Tutti i destinatari usano lo stesso defaultPayload; non servono dati specifici per destinatario
  • Quando isMerge non è indicato, ogni destinatario usa direttamente defaultPayload

2. Template con variabili del corpo condivise​

Lo stesso template viene inviato a tutti i destinatari con valori di variabile identici. Il template contiene segnaposto come {{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" }]
}
suggerimento
  • In questo esempio, il corpo del template potrebbe contenere un testo come: "Approfitta di uno sconto del {{1}} nella nostra campagna! Offerta valida fino al {{2}}."
  • parameters[0] sostituisce {{1}}, mentre parameters[1] sostituisce {{2}}

3. Template personalizzato — variabili per destinatario con isMerge​

Per ogni destinatario si usano valori di variabile diversi. Impostando isMerge: true in defaultPayload, i destinatari devono fornire solo variables; templateName e languageCode vengono ereditati dal payload predefinito.

In questo esempio, il template include sia un’intestazione multimediale sia variabili personalizzate nel corpo.

{
"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"]
}
]
}
}
}
]
}
suggerimento
  • Grazie a isMerge: true, templateName non deve essere ripetuto nel payload di ogni destinatario
  • L’array variables di ogni destinatario è del tutto indipendente
  • L’URL del contenuto multimediale dell’intestazione deve essere accessibile pubblicamente
  • Se type è omesso nel payload del destinatario, viene ereditato defaultPayload.type

4. Variabile di un pulsante URL​

Usa il componente BUTTONS quando il template contiene un pulsante con un suffisso URL dinamico. Ad esempio, un numero di tracciamento aggiunto all’URL di 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"]
}
]
}
}
}
]
}
suggerimento
  • I parametri di BUTTONS vengono associati in base all’ordine dei pulsanti che contengono variabili
  • I pulsanti FLOW e i pulsanti senza variabili vengono ignorati; l’indicizzazione riguarda solo i pulsanti URL dinamici
  • Se l’URL del pulsante del template è https://example.com/track/{{1}}, parameters[0] sostituisce {{1}}

5. Invio programmato​

Programma l’invio di un messaggio a una data e un’ora future. scheduleAt deve essere indicato come timestamp 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" }
}
]
}
}
}
]
}
suggerimento
  • scheduleAt deve essere indicato nel fuso orario UTC (ad es., per le 10:00 ora della Turchia, usa 07:00:00.000Z)
  • Questo esempio usa il formato con parametri nominali; il template deve contenere segnaposto come {{name}} e {{discountRate}}
  • Con action, le conversazioni create dall’invio del messaggio vengono assegnate automaticamente al gruppo di lavoro indicato

Risposta​

Una richiesta riuscita restituisce un bulkOperationId, utilizzabile per seguire il processo di invio:

{
"bulkOperationId": "abc123xyz789"
}

Risposte di errore​

StatoDescrizione
recipients field is requiredIl campo recipients non è stato inviato
Channel not foundNon è stato trovato alcun canale verificato corrispondente a channelUsername e connectorBrand
Channel is not verifiedIl canale corrispondente esiste ma non è ancora stato verificato
zod-schema-errorUn campo del corpo della richiesta non ha superato la validazione dello schema (campo obbligatorio mancante, tipo errato, valore non supportato, più di un identificatore su un destinatario o payload mancante). Il messaggio indica il campo, ad es. recipients.0.referenceId: referenceId must be unique

Il bulkOperationId restituito può essere usato con gli endpoint seguenti per consultare le statistiche di invio e interrompere il processo di invio.


Show — stato e statistiche dell’operazione in blocco​

Recupera l’operazione in blocco con il suo stato attuale e i contatori di invio dei suoi elementi, sotto la chiave bulkOperation.

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

Parametri della richiesta​

ParametroTipoObbligatorioDescrizione
bulkOperationIdstringSìID dell’operazione in blocco da seguire (restituito da 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"
}'

Risposta​

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

Campi di show​

I campi si trovano sotto bulkOperation.

CampoTipoDescrizione
statusstringStato dell’operazione in blocco: preparing, scheduled, pending, running, stopping, stopped, completed, failed
progress.totalnumberNumero totale di elementi
progress.pendingnumberElementi ancora in attesa nella coda
progress.succeedednumberElementi elaborati con successo per l’invio
progress.failednumberElementi che hanno incontrato un errore di invio
progress.cancellednumberElementi annullati da stop
progress.unknownnumberElementi il cui risultato non è stato possibile determinare
result.outcomestringEsito finale al termine dell’operazione in blocco: success, partial, all-failed, cancelled, unknown
result.hasErrorsbooleantrue se almeno un elemento non è riuscito
scheduleAtstringOrario di invio programmato (solo per le operazioni in blocco programmate)
startedAt, completedAtstringQuando l’invio è iniziato e terminato
nota

progress.succeeded indica che il messaggio è stato consegnato con successo dal sistema. Non garantisce che Meta abbia recapitato il messaggio al destinatario. Gli aggiornamenti di stato successivi generati da Meta (come delivered, read o failed) non incidono su questo contatore e non vengono riportati qui.

Show e Message Stats a confronto
  • Endpoint show: mostra lo stato di invio degli elementi (pending, succeeded, failed, cancelled, unknown)
  • Endpoint message-stats: mostra lo stato effettivo del messaggio (pending, sending, sent, delivered, read, error e così via)
  • Un elemento può essere succeeded anche se il messaggio non è ancora stato recapitato o letto

ID di riferimento​

Il referenceId è un campo facoltativo che consente di associare gli elementi di invio a un ID del proprio sistema a fini di tracciamento (ad es. numero d’ordine, ID del ticket). Viene restituito su ogni elemento come payload.referenceId.

Se indicato, deve essere univoco all’interno dell’invio in blocco (massimo 256 caratteri).

Importante
  • Non è obbligatorio
  • Non può essere duplicato all’interno della stessa operazione in blocco
  • Può essere riutilizzato in operazioni in blocco diverse

Message Stats — stato dei messaggi WhatsApp​

Recupera le statistiche sullo stato dei messaggi di un’operazione in blocco. A differenza dell’endpoint show, mostra il message.status effettivo dei messaggi inviati invece dello stato degli elementi.

Stati possibili del messaggio: 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

Parametri della richiesta​

ParametroTipoObbligatorioDescrizione
bulkOperationIdstringSìID dell’operazione in blocco da consultare
{
"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"
}'

Risposta​

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

Campi di Message Stats​

CampoTipoDescrizione
pendingnumberMessaggi non ancora inviati
sendingnumberMessaggi in corso di invio
sentnumberMessaggi consegnati a WhatsApp, non ancora recapitati
deliverednumberMessaggi recapitati al telefono del destinatario
readnumberMessaggi letti dal destinatario
deletednumberMessaggi eliminati
warningnumberMessaggi con avvisi
errornumberMessaggi con errori
unknownnumberMessaggi con stato sconosciuto
not-sendednumberMessaggi che non è stato possibile inviare
no-messagenumberElementi senza messaggio (ancora in coda, non riusciti o annullati)
totalnumberNumero totale di elementi
Suggerimenti d’uso
  • Un valore alto di no-message mentre l’operazione in blocco è running indica che l’invio è ancora in corso
  • Il valore di delivered indica i messaggi recapitati con successo
  • Il valore di read può servire a misurare il coinvolgimento della campagna
  • Puoi interrogare periodicamente questo endpoint per un monitoraggio in tempo reale

Struttura di options — paginazione, filtri e ordinamento​

Il parametro options usato negli endpoint list e list-with-messages offre una struttura standard per paginazione, filtri e ordinamento.

Campi di options​

CampoTipoObbligatorioDescrizione
paginationobjectNoImpostazioni di paginazione
filteringobjectNoCriteri di filtro
sortingobjectNoImpostazioni di ordinamento (ad es. {"position": 1})

Struttura della paginazione​

Se pagination non viene inviato, viene restituita la prima pagina con un massimo di 50 elementi. Se viene inviato, currentPage è obbligatorio.

CampoTipoPredefinitoDescrizione
currentPagenumber—Numero della pagina da recuperare (obbligatorio quando si invia pagination)
pageItemsnumber50Numero di elementi per pagina (massimo: 50)

Struttura dei filtri​

Il filtro si basa sul formato di query di MongoDB applicato ai campi degli elementi, con i nomi dei campi esattamente come compaiono nella risposta (ad es. status, payload.referenceId, result.messageId). Nell’endpoint list-with-messages si può filtrare anche per campi del messaggio (ad es. 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
}
}
}
}

Struttura dell’ordinamento​

L’ordinamento si basa sul formato di ordinamento di MongoDB. 1 indica ordine crescente, -1 ordine decrescente. position è l’ordine del destinatario nell’array recipients della richiesta (a partire da 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
}
}
}

Esempio di uso combinato​

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

Questo esempio elenca la seconda pagina dei messaggi recapitati, nell’ordine dei destinatari.

Suggerimenti pratici
  • Combina filtering e pagination per query mirate
  • La risposta include options.pagination.totalCount e options.pagination.totalPages per la navigazione
  • Il filtro message.status funziona solo nell’endpoint list-with-messages

Items — dettagli ed elenco degli elementi​

Elenca tutti gli elementi di invio di un’operazione in blocco. Ogni elemento corrisponde a una voce dell’array recipients.

List — elenco degli elementi​

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

Parametri della richiesta​

ParametroTipoObbligatorioDescrizione
bulkOperationIdstringSìID dell’operazione in blocco da elencare
optionsobjectNoOpzioni di paginazione, filtro e ordinamento. Per i dettagli vedi Struttura di options.

Richiesta — uso di base​

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

Richiesta — filtro per stato specifico​

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

Elenca solo gli elementi di invio non riusciti, con il motivo in error.

Risposta​

{
"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 — elenco con dettagli dei messaggi​

Ha le stesse funzionalità dell’endpoint list (paginazione, filtri, ordinamento). La differenza: ogni elemento contiene anche gli oggetti message e session corrispondenti, quando esistono. Così è possibile vedere lo stato del messaggio (delivered, read, error e così via) e il payload in un’unica query.

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

Richiesta — uso di base​

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

Richiesta — filtro per stato del messaggio​

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

Questo esempio recupera solo i messaggi con stato "delivered".

Richiesta — elenco dei messaggi non riusciti​

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

Serve a esaminare i messaggi che hanno incontrato errori di invio.

Risposta​

{
"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": {}
}
}

Campi dell’elemento​

CampoTipoDescrizione
_idstringID dell’elemento
bulkOperationIdstringID dell’operazione in blocco a cui appartiene l’elemento
positionnumberOrdine del destinatario nell’array recipients della richiesta, a partire da 0
payloadobjectIl destinatario esattamente come è stato inviato nella richiesta (username / userId / sessionId, referenceId, payload, isMerge)
statusstringStato dell’elemento: pending, succeeded, failed, cancelled, unknown
errorobjectSolo sugli elementi failed: code, message e retryable
result.userIdstringID utente del destinatario
result.sessionIdstringID della sessione di conversazione
result.messageIdstringID del messaggio inviato (assente se non è stato inviato alcun messaggio)
completedAtstringQuando l’elemento è stato elaborato
messageobjectDettagli del messaggio (solo in list-with-messages)
sessionobjectDettagli della conversazione (solo in list-with-messages)

Confronto tra List e List-With-Messages​

Caratteristicalistlist-with-messages
PaginazioneSìSì
FiltriSì (solo campi dell’elemento)Sì (campi dell’elemento e del messaggio)
Message / SessionNoSì (se esistono)
PrestazioniVeloceMedie (esegue un JOIN)
Filtro message.statusNon disponibileDisponibile
Scenari d’uso
  • list: elenca rapidamente tutti gli elementi, filtra per referenceId, controlla lo stato degli elementi
  • list-with-messages: consulta lo stato dei messaggi WhatsApp (delivered, read), esamina i payload dei messaggi
  • Esempi di filtro:
    • {"status": "failed"} — elementi di invio non riusciti
    • {"payload.referenceId": "ORDER-123"} — un ID di riferimento specifico
    • {"message.status": "delivered"} — messaggi recapitati (solo list-with-messages)
    • {"message.status": "read"} — messaggi letti (solo list-with-messages)
    • {"message.status": "error"} — messaggi con errori (solo list-with-messages)
    • {"message.status": {"$in": ["delivered", "read"]}} — messaggi recapitati o letti (solo list-with-messages)
    • {"message.status": {"$nin": ["error", "not-sended"]}} — messaggi esclusi quelli con errori e non inviati (solo list-with-messages)
    • {"message": {"$exists": false}} — elementi senza messaggio (solo list-with-messages)
    • {"status": {"$in": ["succeeded", "pending"]}} — elementi riusciti o in sospeso
Note su prestazioni e uso
  • L’endpoint list è più veloce; preferiscilo per i controlli generali sullo stato
  • Usa list-with-messages quando servono i dettagli dei messaggi
  • Il numero massimo di elementi per pagina (pageItems) è 50; se non specificato, il valore predefinito è 50
  • Il filtro message.status funziona solo in list-with-messages
  • Gli elementi senza result.messageId non hanno l’oggetto message

Stop — annullare l’invio​

Interrompe l’invio in corso di un’operazione in blocco. Tutti gli elementi pending passano allo stato cancelled e l’operazione in blocco diventa stopped. Gli elementi già elaborati come succeeded o failed non vengono modificati. Un’operazione in blocco programmata può essere interrotta anche prima del suo orario scheduleAt.

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

Questa azione non può essere annullata. Un invio interrotto non può essere ripreso.

Parametri della richiesta​

ParametroTipoObbligatorioDescrizione
bulkOperationIdstringSìID dell’operazione in blocco da interrompere
{
"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"
}'

Risposta​

Per una richiesta riuscita, il corpo della risposta è vuoto. Uno stato HTTP 200 indica che l’operazione si è conclusa con successo.

{}
suggerimento
  • Si possono interrompere solo le operazioni in blocco create tramite questa API
  • Dopo aver interrotto un invio, è possibile usare l’endpoint show per verificare il numero di elementi annullati (bulkOperation.progress.cancelled)
  • Se l’operazione in blocco non viene trovata, l’API restituisce l’errore: Bulk operation not found.