Aller au contenu principal

Documentation de l’API Bulk Template Message — v2

Cette API vous permet d’envoyer simultanément des messages modèles à plusieurs destinataires via le canal WhatsApp.

L’envoi est traité de manière asynchrone : la requête API renvoie immédiatement un bulkOperationId, tandis que les messages sont mis en file d’attente et traités en arrière-plan.

POST https://app.monochat.ai/api/:slug/custom-functions/bulk-message-api-app/api/v2/bulk-operation/send.js
Format de réponse

Chaque endpoint de ce document est une custom function. Le corps de la réponse HTTP contient les champs propres à la fonction (_id, title, pathString…) et la réponse réelle de l’endpoint sous result. Les exemples de réponse de ce document montrent le contenu de result :

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

Migrer depuis la v1​

La v2 fonctionne en parallèle de la v1 : vous pouvez donc migrer à votre rythme. Les endpoints v1 (/api/bulk-message/…, /api/bulk-message-records/…) seront retirés ; les nouvelles intégrations doivent utiliser la v2.

  1. Passez les chemins des endpoints en v2 : …/api/bulk-message/… devient …/api/v2/bulk-operation/…, et …/api/bulk-message-records/… devient …/api/v2/bulk-operation-items/…. Le corps de la requête send ne change pas ; une seule requête accepte désormais jusqu’à 100 000 destinataires au lieu de 5 000.
  2. Envoyez bulkOperationId au lieu de bulkMessageId dans les requêtes.
  3. Remplacez stats.js par show.js.
  4. Lisez les réponses avec les nouveaux noms de champs du tableau ci-dessous.

Les endpoints v2 ne connaissent que les opérations en masse créées avec le send v2. Pour suivre un message en masse créé avec la v1 avant votre migration, continuez à utiliser les endpoints v1 pour celui-ci.

Endpoints​

v1v2Ce qui change dans la réponse
bulk-message/send.jsv2/bulk-operation/send.js{ bulkMessageId } devient { bulkOperationId }
bulk-message/stats.jsv2/bulk-operation/show.js{ bulkMessage, stats } devient { bulkOperation }
bulk-message/message-stats.jsv2/bulk-operation/message-stats.jsLes compteurs sont à la racine au lieu d’être sous messageStats
bulk-message/stop.jsv2/bulk-operation/stop.jsRien
bulk-message-records/list.jsv2/bulk-operation-items/list.jsbulkMessageRecords devient bulkOperationItems
bulk-message-records/list-with-messages.jsv2/bulk-operation-items/list-with-messages.jsComme pour list, et chaque élément contient aussi session

Noms des champs​

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 (message en masse)bulkOperation (opération en masse)
bulkMessageRecord (enregistrement)bulkOperationItem (élément)
bulkMessageId dans les requêtes, dans la réponse de send et sur les enregistrementsbulkOperationId
username / userId / sessionId de l’enregistrement, tels qu’envoyéspayload.username / payload.userId / payload.sessionId
referenceId de l’enregistrementpayload.referenceId
payload de l’enregistrement (le payload de modèle du destinataire)payload.payload
userId, sessionId, messageId de l’enregistrement après l’envoiresult.userId, result.sessionId, result.messageId
statut d’enregistrement successsucceeded
errorMessage sur les enregistrements en échecerror.message, à côté de error.code et error.retryable
—position (l’index du destinataire dans recipients)
filtre {"status": "success"}{"status": "succeeded"}
filtre {"referenceId": "…"}{"payload.referenceId": "…"}
erreurs de send schema-error, invalidRequestzod-schema-error, avec le chemin du champ invalide dans le message

Principales fonctionnalités​

  • Envoyez des messages modèles en masse à 1 à 100 000 destinataires en une seule requête
  • Variables personnalisées pour chaque destinataire (HEADER, BODY, BUTTONS, CAROUSEL)
  • Un defaultPayload partagé par tous les destinataires, avec fusion du payload propre à chaque destinataire (isMerge)
  • Envoi programmé (scheduleAt)
  • Indiquez les destinataires avec username (numéro de téléphone), userId ou sessionId
  • Envoyez plusieurs messages au même utilisateur dans une seule requête en masse
  • referenceId facultatif pour rapprocher les enregistrements de systèmes externes
  • Attribuez automatiquement les conversations à un utilisateur ou à un groupe de travail après l’envoi (action)
attention

Cette API ne peut envoyer que des modèles approuvés par Meta.

Le nom du modèle et le code de langue doivent correspondre exactement au modèle enregistré dans Meta Business Manager.

Paramètres de la requête​

Paramètres de premier niveau​

ParamètreTypeObligatoireDescription
channelUsernamestringOuiNuméro du canal WhatsApp utilisé pour envoyer le message (par ex. "908506669933")
connectorBrandstringOuiMarque du connecteur de canal. Valeur actuellement prise en charge : "whatsapp"
titlestringNonTitre de la campagne. Utilisé pour l’affichage dans le tableau de bord. Par défaut : "-"
scheduleAtstring (ISO 8601)NonDate et heure d’envoi programmé (par ex. "2026-06-10T10:00:00.000Z"). Si omis, les messages sont envoyés immédiatement.
defaultPayloadobjectConditionnel*Payload de modèle par défaut appliqué à tous les destinataires. Obligatoire si un destinataire ne fournit pas son propre payload.
recipientsarrayOuiListe des destinataires. Minimum 1, maximum 100 000 destinataires.
actionobjectNonAction appliquée à la conversation après l’envoi. assign-to-user ou assign-to-workgroup.

*Si chaque destinataire fournit son propre payload, defaultPayload est facultatif.

Structure d’un destinataire​

Pour chaque destinataire, un seul des champs username, userId ou sessionId doit être fourni. Plusieurs identifiants ne peuvent pas être utilisés ensemble, et les omettre tous provoque une erreur.

Pour envoyer plusieurs messages au même utilisateur dans une seule requête en masse, ajoutez plusieurs fois le même identifiant à la liste des destinataires.

ChampTypeDescription
usernamestringNuméro de téléphone du destinataire (par ex. "905554443322"). Si l’utilisateur n’existe pas dans le système, il est créé automatiquement.
userIdstringIdentifiant d’un utilisateur existant dans le système.
sessionIdstringIdentifiant d’une session de conversation existante dans le système.
referenceIdstringIdentifiant de référence facultatif (256 caractères maximum) pour le rapprochement avec les enregistrements de systèmes externes (CRM, commande, ticket, etc.). Doit être unique dans l’envoi en masse s’il est fourni.
payloadobjectPayload de modèle propre au destinataire (facultatif). Si isMerge: true, il est fusionné avec defaultPayload.
isMergebooleanRemplace le comportement de fusion pour ce destinataire (facultatif). Si omis, defaultPayload.isMerge est utilisé.

Structure de l’action​

ChampTypeDescription
action.keystring"assign-to-user" attribue la conversation à un agent précis ; "assign-to-workgroup" l’attribue à un groupe de travail.
action.valuestringIdentifiant de l’utilisateur ou du groupe de travail cible.

Structure du payload de modèle​

defaultPayload et le payload propre à un destinataire ont la même structure. Pour les messages modèles, type: "template" doit être indiqué.

{
"type": "template",
"template": {
"templateName": "order_confirmation",
"languageCode": "tr-TR",
"variables": []
},
"isMerge": true
}
ChampTypeObligatoireDescription
typestringOuiType de payload. Pour les messages modèles : "template"
template.templateNamestringOui*Nom du modèle enregistré dans Meta. Facultatif dans les payloads de destinataires lorsque isMerge: true est utilisé (hérité du payload par défaut).
template.languageCodestringNonCode de langue du modèle (par ex. "tr", "en", "tr-TR", "en-US"). Doit correspondre exactement à la langue enregistrée dans Meta.
template.variablesarrayNonListe des variables appliquées aux composants du modèle. Détaillée ci-dessous.
isMergebooleanNontrue : le payload du destinataire est fusionné en profondeur avec defaultPayload. false ou omis : le payload du destinataire remplace entièrement defaultPayload.
Comportement de isMerge
  • Si defaultPayload.isMerge: true et que le destinataire fournit son propre payload, une fusion en profondeur est appliquée.
  • Avec la fusion en profondeur, le destinataire peut ne fournir que variables ; templateName et languageCode sont hérités du payload par défaut.
  • Le champ isMerge du destinataire remplace defaultPayload.isMerge.
  • Si un destinataire ne fournit pas de payload, defaultPayload est toujours utilisé.

Structure des variables​

Chaque élément du tableau variables correspond à un composant du modèle. Un type de composant (type) ne peut apparaître qu’une seule fois dans le tableau.

typeDescriptionparameterscards
"HEADER"Composant d’en-tête du modèle. Variable de texte ou URL de média (image, vidéo, document)Oui—
"BODY"Variables de texte du corps du modèleOui—
"BUTTONS"Variables de suffixe d’URL dynamique pour les boutonsOui—
"CAROUSEL"Composants de cartes pour les modèles carrousel—Oui

Formats des paramètres​

Le champ parameters peut être fourni sous trois formats différents :

// 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" }
Quel format utiliser ?
  • Si votre modèle Meta utilise des espaces réservés comme {{1}}, {{2}}, utilisez le format tableau ou le format objet à clés numériques.
  • Si votre modèle utilise des espaces réservés nommés comme {{firstName}} ou {{orderTotal}}, utilisez le format objet à clés nommées.
  • Avec les tableaux, l’ordre compte : le premier élément correspond à {{1}}, le deuxième à {{2}}, et ainsi de suite.

Composant HEADER​

Utilisez le composant HEADER lorsque l’en-tête du modèle contient un média (image, vidéo, document) ou du texte dynamique.

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

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

Composant BODY​

Utilisé pour les variables de texte dynamiques dans le corps du modèle.

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

Composant BUTTONS​

Utilisé pour les boutons avec un suffixe d’URL dynamique. Si le modèle contient plusieurs boutons URL, seuls les boutons qui ont des variables sont indexés séquentiellement (les boutons sans variables ou les boutons FLOW sont ignorés).

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

Pour les modèles carrousel, les variables des composants sont définies séparément pour chaque carte.

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

La longueur du tableau cards doit correspondre exactement au nombre de cartes définies dans le modèle.

Exemples​

1. Modèle simple — sans variables, même contenu pour tous les destinataires​

C’est la façon la plus simple d’envoyer à plusieurs destinataires un modèle statique sans variables.

{
"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" }
]
}'
astuce
  • Les destinataires indiqués via username sont créés automatiquement s’ils n’existent pas déjà dans le système
  • Tous les destinataires utilisent le même defaultPayload ; aucune donnée propre à un destinataire n’est nécessaire
  • Quand isMerge n’est pas indiqué, chaque destinataire utilise directement le defaultPayload

2. Modèle avec variables de corps partagées​

Le même modèle est envoyé à tous les destinataires avec des valeurs de variables identiques. Le modèle contient des espaces réservés tels que {{1}} et {{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" }]
}
astuce
  • Dans cet exemple, le corps du modèle pourrait contenir un texte comme : « Profitez d’une remise de {{1}} pendant notre campagne ! Offre valable jusqu’au {{2}}. »
  • parameters[0] remplace {{1}}, tandis que parameters[1] remplace {{2}}

3. Modèle personnalisé — variables par destinataire avec isMerge​

Des valeurs de variables différentes sont utilisées pour chaque destinataire. En définissant isMerge: true dans le defaultPayload, les destinataires n’ont qu’à fournir variables ; templateName et languageCode sont hérités du payload par défaut.

Dans cet exemple, le modèle comprend à la fois un en-tête média et des variables de corps personnalisées.

{
"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"]
}
]
}
}
}
]
}
astuce
  • Grâce à isMerge: true, templateName n’a pas besoin d’être répété dans chaque payload de destinataire
  • Le tableau variables de chaque destinataire est entièrement indépendant
  • L’URL du média d’en-tête doit être accessible publiquement
  • Si type est omis dans le payload du destinataire, defaultPayload.type est hérité

4. Variable de bouton URL​

Utilisez le composant BUTTONS lorsque le modèle contient un bouton avec un suffixe d’URL dynamique. Par exemple, un numéro de suivi ajouté à l’URL de 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"]
}
]
}
}
}
]
}
astuce
  • Les paramètres BUTTONS sont associés selon l’ordre des boutons qui contiennent des variables
  • Les boutons FLOW et les boutons sans variables sont ignorés ; l’indexation ne s’applique qu’aux boutons URL dynamiques
  • Si l’URL du bouton du modèle est https://example.com/track/{{1}}, alors parameters[0] remplace {{1}}

5. Envoi programmé​

Programmez l’envoi d’un message à une date et une heure futures. scheduleAt doit être fourni sous forme d’horodatage 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" }
}
]
}
}
}
]
}
astuce
  • scheduleAt doit être fourni dans le fuseau horaire UTC (par ex., pour 10 h 00 heure de Turquie, utilisez 07:00:00.000Z)
  • Cet exemple utilise le format de paramètres nommés ; le modèle doit contenir des espaces réservés tels que {{name}} et {{discountRate}}
  • Avec action, les conversations créées par l’envoi du message sont automatiquement attribuées au groupe de travail indiqué

Réponse​

Une requête réussie renvoie un bulkOperationId, qui peut servir à suivre le processus d’envoi :

{
"bulkOperationId": "abc123xyz789"
}

Réponses d’erreur​

StatutDescription
recipients field is requiredLe champ recipients n’a pas été envoyé
Channel not foundAucun canal vérifié correspondant à channelUsername et connectorBrand n’a été trouvé
Channel is not verifiedLe canal correspondant existe mais n’a pas encore été vérifié
zod-schema-errorUn champ du corps de la requête a échoué à la validation du schéma (champ obligatoire manquant, type incorrect, valeur non prise en charge, plusieurs identifiants sur un destinataire ou payload manquant). Le message indique le champ, par ex. recipients.0.referenceId: referenceId must be unique

Le bulkOperationId renvoyé peut être utilisé avec les endpoints ci-dessous pour consulter les statistiques d’envoi et arrêter le processus d’envoi.


Show — statut et statistiques de l’opération en masse​

Récupère l’opération en masse avec son statut actuel et les compteurs d’envoi de ses éléments, sous la clé bulkOperation.

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

Paramètres de la requête​

ParamètreTypeObligatoireDescription
bulkOperationIdstringOuiIdentifiant de l’opération en masse à suivre (renvoyé par 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"
}'

Réponse​

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

Champs de show​

Les champs se trouvent sous bulkOperation.

ChampTypeDescription
statusstringStatut de l’opération en masse : preparing, scheduled, pending, running, stopping, stopped, completed, failed
progress.totalnumberNombre total d’éléments
progress.pendingnumberÉléments encore en attente dans la file
progress.succeedednumberÉléments traités avec succès pour l’envoi
progress.failednumberÉléments ayant rencontré une erreur d’envoi
progress.cancellednumberÉléments annulés par stop
progress.unknownnumberÉléments dont le résultat n’a pas pu être déterminé
result.outcomestringRésultat final une fois l’opération en masse terminée : success, partial, all-failed, cancelled, unknown
result.hasErrorsbooleantrue si au moins un élément a échoué
scheduleAtstringHeure d’envoi programmée (uniquement pour les opérations en masse programmées)
startedAt, completedAtstringDébut et fin de l’envoi
remarque

progress.succeeded indique que le message a été transmis avec succès par le système. Cela ne garantit pas que Meta a remis le message au destinataire. Les mises à jour de statut ultérieures générées par Meta (comme delivered, read ou failed) n’affectent pas ce compteur et n’y sont pas reflétées.

Show et Message Stats
  • Endpoint show : affiche le statut d’envoi des éléments (pending, succeeded, failed, cancelled, unknown)
  • Endpoint message-stats : affiche l’état réel des messages (pending, sending, sent, delivered, read, error, etc.)
  • Un élément peut être succeeded sans que le message soit encore remis ou lu

Identifiant de référence​

Le referenceId est un champ facultatif que vous pouvez utiliser pour rapprocher les éléments d’envoi d’un identifiant de votre propre système à des fins de suivi (par ex. numéro de commande, identifiant de ticket). Il est renvoyé sur chaque élément sous la forme payload.referenceId.

S’il est fourni, il doit être unique dans l’envoi en masse (256 caractères maximum).

Important
  • Non obligatoire
  • Ne peut pas être dupliqué dans une même opération en masse
  • Peut être réutilisé dans différentes opérations en masse

Message Stats — statut des messages WhatsApp​

Récupère les statistiques de statut des messages d’une opération en masse. Contrairement à l’endpoint show, il affiche le message.status réel des messages envoyés au lieu du statut des éléments.

Statuts de message possibles : 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

Paramètres de la requête​

ParamètreTypeObligatoireDescription
bulkOperationIdstringOuiIdentifiant de l’opération en masse à interroger
{
"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"
}'

Réponse​

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

Champs de Message Stats​

ChampTypeDescription
pendingnumberMessages pas encore envoyés
sendingnumberMessages en cours d’envoi
sentnumberMessages transmis à WhatsApp, pas encore remis
deliverednumberMessages remis sur le téléphone du destinataire
readnumberMessages lus par le destinataire
deletednumberMessages supprimés
warningnumberMessages avec avertissements
errornumberMessages en erreur
unknownnumberMessages de statut inconnu
not-sendednumberMessages qui n’ont pas pu être envoyés
no-messagenumberÉléments sans message (encore en file, en échec ou annulés)
totalnumberNombre total d’éléments
Conseils d’utilisation
  • Un nombre élevé de no-message alors que l’opération en masse est running indique que l’envoi est encore en cours
  • Le nombre de delivered indique les messages remis avec succès
  • Le nombre de read peut servir à mesurer l’engagement de la campagne
  • Vous pouvez interroger cet endpoint périodiquement pour un suivi en temps réel

Structure des options — pagination, filtrage et tri​

Le paramètre options utilisé dans les endpoints list et list-with-messages fournit une structure standard pour la pagination, le filtrage et le tri.

Champs des options​

ChampTypeObligatoireDescription
paginationobjectNonParamètres de pagination
filteringobjectNonCritères de filtrage
sortingobjectNonParamètres de tri (par ex. {"position": 1})

Structure de la pagination​

Si pagination n’est pas envoyé, la première page est renvoyée avec jusqu’à 50 éléments. S’il est envoyé, currentPage est obligatoire.

ChampTypePar défautDescription
currentPagenumber—Numéro de la page à récupérer (obligatoire lorsque pagination est envoyé)
pageItemsnumber50Nombre d’éléments par page (maximum : 50)

Structure du filtrage​

Le filtrage utilise le format de requête MongoDB sur les champs des éléments, avec les noms de champs exactement tels qu’ils apparaissent dans la réponse (par ex. status, payload.referenceId, result.messageId). Dans l’endpoint list-with-messages, vous pouvez aussi filtrer sur les champs des messages (par ex. 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
}
}
}
}

Structure du tri​

Le tri utilise le format de tri MongoDB. 1 signifie croissant, -1 décroissant. position est l’ordre du destinataire dans le tableau recipients de la requête (à partir de 0).

// Sort in the order the recipients were sent in the request
{
"options": {
"sorting": {
"position": 1
}
}
}

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

Exemple d’utilisation combinée​

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

Cet exemple liste la deuxième page des messages remis, dans l’ordre des destinataires.

Conseils pratiques
  • Combinez filtering et pagination pour des requêtes ciblées
  • La réponse inclut options.pagination.totalCount et options.pagination.totalPages pour la navigation
  • Le filtre message.status ne fonctionne que dans l’endpoint list-with-messages

Items — détails et liste des éléments​

Liste tous les éléments d’envoi d’une opération en masse. Chaque élément correspond à une entrée du tableau recipients.

List — liste des éléments​

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

Paramètres de la requête​

ParamètreTypeObligatoireDescription
bulkOperationIdstringOuiIdentifiant de l’opération en masse à lister
optionsobjectNonOptions de pagination, de filtrage et de tri. Voir Structure des options pour plus de détails.

Requête — utilisation de base​

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

Requête — filtrer par statut précis​

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

Liste uniquement les éléments d’envoi en échec, avec la raison dans error.

Réponse​

{
"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 — liste avec les détails des messages​

Offre les mêmes fonctionnalités que l’endpoint list (pagination, filtrage, tri). La différence : chaque élément contient aussi les objets message et session associés, lorsqu’ils existent. Cela vous permet de voir le statut du message (delivered, read, error, etc.) et son payload en une seule requête.

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

Requête — utilisation de base​

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

Requête — filtrer par statut de message​

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

Cet exemple ne récupère que les messages au statut « delivered ».

Requête — lister les messages en échec​

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

Sert à examiner les messages qui ont rencontré des erreurs d’envoi.

Réponse​

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

Champs d’un élément​

ChampTypeDescription
_idstringIdentifiant de l’élément
bulkOperationIdstringIdentifiant de l’opération en masse à laquelle appartient l’élément
positionnumberOrdre du destinataire dans le tableau recipients de la requête, à partir de 0
payloadobjectLe destinataire exactement tel qu’envoyé dans la requête (username / userId / sessionId, referenceId, payload, isMerge)
statusstringStatut de l’élément : pending, succeeded, failed, cancelled, unknown
errorobjectUniquement sur les éléments failed : code, message et retryable
result.userIdstringIdentifiant de l’utilisateur destinataire
result.sessionIdstringIdentifiant de la session de conversation
result.messageIdstringIdentifiant du message envoyé (absent si aucun message n’a été envoyé)
completedAtstringDate de traitement de l’élément
messageobjectDétails du message (uniquement dans list-with-messages)
sessionobjectDétails de la conversation (uniquement dans list-with-messages)

Comparaison list et list-with-messages​

Fonctionnalitélistlist-with-messages
PaginationOuiOui
FiltrageOui (champs d’élément uniquement)Oui (champs d’élément et de message)
Message / SessionNonOui (s’ils existent)
PerformanceRapideMoyenne (effectue une jointure)
Filtre message.statusNon disponibleDisponible
Scénarios d’utilisation
  • list : lister rapidement tous les éléments, filtrer par referenceId, vérifier les statuts des éléments
  • list-with-messages : consulter les statuts des messages WhatsApp (delivered, read), inspecter les payloads des messages
  • Exemples de filtrage :
    • {"status": "failed"} — éléments d’envoi en échec
    • {"payload.referenceId": "ORDER-123"} — un identifiant de référence précis
    • {"message.status": "delivered"} — messages remis (list-with-messages uniquement)
    • {"message.status": "read"} — messages lus (list-with-messages uniquement)
    • {"message.status": "error"} — messages en erreur (list-with-messages uniquement)
    • {"message.status": {"$in": ["delivered", "read"]}} — messages remis ou lus (list-with-messages uniquement)
    • {"message.status": {"$nin": ["error", "not-sended"]}} — messages hors erreurs et non-envoyés (list-with-messages uniquement)
    • {"message": {"$exists": false}} — éléments sans message (list-with-messages uniquement)
    • {"status": {"$in": ["succeeded", "pending"]}} — éléments réussis ou en attente
Performance et remarques d’utilisation
  • L’endpoint list est plus rapide ; privilégiez-le pour les vérifications générales de statut
  • Utilisez list-with-messages lorsque les détails des messages sont nécessaires
  • Le nombre maximal d’éléments par page (pageItems) est de 50 ; la valeur par défaut est 50 si elle n’est pas indiquée
  • Le filtre message.status ne fonctionne que dans list-with-messages
  • Les éléments sans result.messageId n’ont pas d’objet message

Stop — annuler l’envoi​

Arrête l’envoi en cours d’une opération en masse. Tous les éléments pending passent au statut cancelled et l’opération en masse passe à stopped. Les éléments déjà traités en succeeded ou failed ne sont pas concernés. Une opération en masse programmée peut aussi être arrêtée avant son heure scheduleAt.

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

Cette action est irréversible. Un envoi arrêté ne peut pas être repris.

Paramètres de la requête​

ParamètreTypeObligatoireDescription
bulkOperationIdstringOuiIdentifiant de l’opération en masse à arrêter
{
"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"
}'

Réponse​

Pour une requête réussie, le corps de la réponse est vide. Un statut HTTP 200 indique que l’opération s’est terminée avec succès.

{}
astuce
  • Seules les opérations en masse créées via cette API peuvent être arrêtées
  • Après l’arrêt d’un envoi, vous pouvez utiliser l’endpoint show pour vérifier le nombre d’éléments annulés (bulkOperation.progress.cancelled)
  • Si l’opération en masse est introuvable, l’API renvoie l’erreur : Bulk operation not found.