Dokumentasi Bulk Template Message API — v2
API ini memungkinkan Anda mengirim pesan template ke banyak penerima sekaligus melalui saluran WhatsApp.
Pengiriman pesan diproses secara asinkron; permintaan API langsung mengembalikan bulkOperationId, sementara pesan diantrekan dan diproses di latar belakang.
POST https://app.monochat.ai/api/:slug/custom-functions/bulk-message-api-app/api/v2/bulk-operation/send.js
Setiap endpoint dalam dokumen ini adalah custom function. Isi respons HTTP memuat kolom milik function itu sendiri (_id, title, pathString…) dan respons sebenarnya dari endpoint di bawah result. Contoh respons dalam dokumen ini menampilkan isi result:
{
"_id": "function_id",
"title": "Show",
"pathString": "/bulk-message-api-app/api/v2/bulk-operation/show.js",
"result": {
"bulkOperation": { "_id": "abc123xyz789", "status": "running" }
}
}
Migrasi dari v1
v2 berjalan berdampingan dengan v1, sehingga Anda dapat bermigrasi sesuai jadwal Anda sendiri. Endpoint v1 (/api/bulk-message/…, /api/bulk-message-records/…) akan dihentikan; integrasi baru sebaiknya menggunakan v2.
- Pindahkan path endpoint ke v2:
…/api/bulk-message/…menjadi…/api/v2/bulk-operation/…, dan…/api/bulk-message-records/…menjadi…/api/v2/bulk-operation-items/…. Isi permintaansendtidak berubah; satu permintaan kini menerima hingga 100.000 penerima, bukan 5.000. - Kirim
bulkOperationIdalih-alihbulkMessageIddalam permintaan. - Ganti
stats.jsdenganshow.js. - Baca respons dengan nama kolom baru pada tabel di bawah.
Endpoint v2 hanya mengenali operasi massal yang dibuat dengan send v2. Untuk melacak pesan massal yang dibuat dengan v1 sebelum Anda beralih, tetap gunakan endpoint v1 untuk pesan tersebut.
Endpoint
| v1 | v2 | Apa yang berubah dalam respons |
|---|---|---|
bulk-message/send.js | v2/bulk-operation/send.js | { bulkMessageId } menjadi { bulkOperationId } |
bulk-message/stats.js | v2/bulk-operation/show.js | { bulkMessage, stats } menjadi { bulkOperation } |
bulk-message/message-stats.js | v2/bulk-operation/message-stats.js | Penghitung berada di root, bukan di bawah messageStats |
bulk-message/stop.js | v2/bulk-operation/stop.js | Tidak ada |
bulk-message-records/list.js | v2/bulk-operation-items/list.js | bulkMessageRecords menjadi bulkOperationItems |
bulk-message-records/list-with-messages.js | v2/bulk-operation-items/list-with-messages.js | Sama seperti list, dan setiap item juga membawa session |
Nama kolom
| v1 | v2 |
|---|---|
stats.success | bulkOperation.progress.succeeded |
stats.pending, stats.failed, stats.cancelled, stats.total | bulkOperation.progress.pending, .failed, .cancelled, .total |
| — | bulkOperation.progress.unknown, bulkOperation.status, bulkOperation.result.outcome |
bulkMessage (pesan massal) | bulkOperation (operasi massal) |
bulkMessageRecord (catatan) | bulkOperationItem (item) |
bulkMessageId dalam permintaan, dalam respons send, dan pada catatan | bulkOperationId |
username / userId / sessionId catatan sebagaimana dikirim | payload.username / payload.userId / payload.sessionId |
referenceId catatan | payload.referenceId |
payload catatan (payload template penerima) | payload.payload |
userId, sessionId, messageId catatan setelah pengiriman | result.userId, result.sessionId, result.messageId |
status catatan success | succeeded |
errorMessage catatan pada catatan yang gagal | error.message, berdampingan dengan error.code dan error.retryable |
| — | position (indeks penerima dalam recipients) |
filter {"status": "success"} | {"status": "succeeded"} |
filter {"referenceId": "…"} | {"payload.referenceId": "…"} |
error send schema-error, invalidRequest | zod-schema-error, dengan path kolom yang tidak valid di dalam pesan |
Fitur utama
- Kirim pesan template massal ke 1–100.000 penerima dalam satu permintaan
- Variabel yang dipersonalisasi untuk setiap penerima (HEADER, BODY, BUTTONS, CAROUSEL)
defaultPayloadbersama untuk semua penerima dengan penggabunganpayloadkhusus penerima (isMerge)- Pengiriman terjadwal (
scheduleAt) - Tentukan penerima menggunakan
username(nomor telepon),userId, atausessionId - Kirim beberapa pesan ke pengguna yang sama dalam satu permintaan massal
referenceIdopsional untuk melacak catatan dengan sistem eksternal- Tugaskan percakapan secara otomatis ke pengguna atau grup kerja setelah pengiriman (
action)
API ini hanya dapat mengirim template yang telah disetujui Meta.
Nama template dan kode bahasa harus persis sama dengan template yang terdaftar di Meta Business Manager.
Parameter permintaan
Parameter tingkat atas
| Parameter | Tipe | Wajib | Deskripsi |
|---|---|---|---|
channelUsername | string | Ya | Nomor saluran WhatsApp yang digunakan untuk mengirim pesan (misalnya "908506669933") |
connectorBrand | string | Ya | Merek konektor saluran. Nilai yang saat ini didukung: "whatsapp" |
title | string | Tidak | Judul kampanye. Digunakan untuk tampilan di dasbor. Default: "-" |
scheduleAt | string (ISO 8601) | Tidak | Tanggal dan waktu pengiriman terjadwal (misalnya "2026-06-10T10:00:00.000Z"). Jika dihilangkan, pesan dikirim segera. |
defaultPayload | object | Bersyarat* | Payload template default yang berlaku untuk semua penerima. Wajib jika penerima tidak menyediakan payload sendiri. |
recipients | array | Ya | Daftar penerima. Minimum 1, maksimum 100.000 penerima. |
action | object | Tidak | Tindakan yang diterapkan pada percakapan setelah pengiriman. assign-to-user atau assign-to-workgroup. |
*Jika setiap penerima menyediakan payload sendiri, defaultPayload bersifat opsional.
Struktur penerima
Untuk setiap penerima, tepat satu dari username, userId, atau sessionId harus diberikan. Beberapa pengenal tidak dapat digunakan bersamaan, dan jika semuanya dihilangkan akan terjadi error.
Untuk mengirim beberapa pesan ke pengguna yang sama dalam satu permintaan massal, tambahkan pengenal yang sama ke daftar penerima beberapa kali.
| Kolom | Tipe | Deskripsi |
|---|---|---|
username | string | Nomor telepon penerima (misalnya "905554443322"). Jika pengguna belum ada di sistem, pengguna dibuat otomatis. |
userId | string | ID pengguna yang sudah ada di sistem. |
sessionId | string | ID sesi percakapan yang sudah ada di sistem. |
referenceId | string | Reference ID opsional (maks. 256 karakter) untuk mencocokkan dengan catatan sistem eksternal (CRM, pesanan, tiket, dll.). Harus unik di dalam satu operasi massal jika diberikan. |
payload | object | Payload template khusus penerima (opsional). Jika isMerge: true, payload digabungkan dengan defaultPayload. |
isMerge | boolean | Menggantikan perilaku penggabungan untuk penerima ini (opsional). Jika dihilangkan, defaultPayload.isMerge digunakan. |
Struktur action
| Kolom | Tipe | Deskripsi |
|---|---|---|
action.key | string | "assign-to-user" menugaskan percakapan ke agen tertentu; "assign-to-workgroup" menugaskannya ke grup kerja. |
action.value | string | ID pengguna atau grup kerja tujuan. |
Struktur payload template
defaultPayload dan payload khusus penerima memiliki struktur yang sama. Untuk pesan template, type: "template" harus ditentukan.
{
"type": "template",
"template": {
"templateName": "order_confirmation",
"languageCode": "tr-TR",
"variables": []
},
"isMerge": true
}
| Kolom | Tipe | Wajib | Deskripsi |
|---|---|---|---|
type | string | Ya | Tipe payload. Untuk pesan template: "template" |
template.templateName | string | Ya* | Nama template yang terdaftar di Meta. Opsional pada payload penerima saat isMerge: true digunakan (diwarisi dari default). |
template.languageCode | string | Tidak | Kode bahasa template (misalnya "tr", "en", "tr-TR", "en-US"). Harus persis sama dengan bahasa yang terdaftar di Meta. |
template.variables | array | Tidak | Daftar variabel yang diterapkan pada komponen template. Dijelaskan di bawah. |
isMerge | boolean | Tidak | true: payload penerima digabungkan secara mendalam dengan defaultPayload. false atau dihilangkan: payload penerima sepenuhnya menggantikan defaultPayload. |
- Jika
defaultPayload.isMerge: truedan penerima menyediakanpayloadsendiri, penggabungan mendalam (deep merge) diterapkan. - Dengan deep merge, penerima cukup menyediakan
variables;templateNamedanlanguageCodediwarisi dari payload default. - Kolom
isMergepenerima menggantikandefaultPayload.isMerge. - Jika penerima tidak menyediakan
payload,defaultPayloadselalu digunakan.
Struktur variabel
Setiap item dalam array variables sesuai dengan satu komponen template. Satu jenis komponen (type) hanya boleh muncul sekali dalam array.
| type | Deskripsi | parameters | cards |
|---|---|---|---|
"HEADER" | Komponen header template. Variabel teks atau URL media (gambar, video, dokumen) | Ya | — |
"BODY" | Variabel teks body template | Ya | — |
"BUTTONS" | Variabel akhiran URL dinamis untuk tombol | Ya | — |
"CAROUSEL" | Komponen kartu untuk template carousel | — | Ya |
Format parameter
Kolom parameters dapat diberikan dalam tiga format berbeda:
// Format 1: Array (berbasis indeks) — untuk placeholder seperti {{1}}, {{2}}, {{3}}
"parameters": ["value1", "value2", "value3"]
// Format 2: Objek (kunci numerik) — representasi alternatif untuk {{1}}, {{2}}
"parameters": { "1": "value1", "2": "value2" }
// Format 3: Objek (kunci bernama) — untuk placeholder seperti {{name}}, {{amount}}
"parameters": { "name": "John", "amount": "150 USD" }
- Jika template Meta Anda menggunakan placeholder seperti
{{1}},{{2}}, gunakan format array atau format objek dengan kunci numerik. - Jika template Anda menggunakan placeholder bernama seperti
{{firstName}}atau{{orderTotal}}, gunakan format objek dengan kunci bernama. - Saat menggunakan array, urutan berpengaruh: elemen pertama untuk
{{1}}, elemen kedua untuk{{2}}, dan seterusnya.
Komponen HEADER
Gunakan komponen HEADER saat header template berisi media (gambar, video, dokumen) atau teks dinamis.
// Header media (URL gambar)
{
"type": "HEADER",
"parameters": ["https://example.com/product-image.jpg"]
}
// Variabel header teks
{
"type": "HEADER",
"parameters": ["Special Campaign"]
}
Komponen BODY
Digunakan untuk variabel teks dinamis di dalam body template.
// Format array — jika template menggunakan {{1}}, {{2}}, {{3}}
{
"type": "BODY",
"parameters": ["John", "ORD-12345", "150.00 USD"]
}
// Format bernama — jika template menggunakan {{name}}, {{orderAmount}}
{
"type": "BODY",
"parameters": {
"name": "John",
"orderAmount": "150.00 USD"
}
}
Komponen BUTTONS
Digunakan untuk tombol dengan akhiran URL dinamis. Jika template berisi beberapa tombol URL, hanya tombol yang memiliki variabel yang diindeks secara berurutan (tombol tanpa variabel atau tombol FLOW diabaikan).
// Variabel akhiran untuk satu tombol URL
{
"type": "BUTTONS",
"parameters": ["tracking/ORD-12345"]
}
// Variabel akhiran untuk beberapa tombol URL (tombol URL pertama, tombol URL kedua)
{
"type": "BUTTONS",
"parameters": ["tracking/ORD-12345", "cancel/ORD-12345"]
}
Komponen CAROUSEL
Untuk template carousel, variabel komponen ditentukan secara terpisah untuk setiap kartu.
{
"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"]
}
]
}
]
}
Panjang array cards harus persis sama dengan jumlah kartu yang ditentukan di template.
Contoh
1. Template sederhana — tanpa variabel, isi sama untuk semua penerima
Ini cara paling sederhana untuk mengirim template statis tanpa variabel ke banyak penerima.
{
"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" }
]
}'
- Penerima yang ditentukan lewat
usernamedibuat otomatis jika belum ada di sistem - Semua penerima menggunakan
defaultPayloadyang sama; tidak diperlukan data khusus penerima - Jika
isMergetidak ditentukan, setiap penerima langsung menggunakandefaultPayload
2. Template dengan variabel body bersama
Template yang sama dikirim ke semua penerima dengan nilai variabel yang identik. Template berisi placeholder seperti {{1}} dan {{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" }]
}
- Pada contoh ini, body template dapat berisi teks seperti: "Nikmati diskon
{{1}}di kampanye kami! Penawaran berlaku hingga{{2}}." parameters[0]menggantikan{{1}}, sedangkanparameters[1]menggantikan{{2}}
3. Template yang dipersonalisasi — variabel per penerima dengan isMerge
Nilai variabel yang berbeda digunakan untuk setiap penerima. Dengan menetapkan isMerge: true pada defaultPayload, penerima hanya perlu menyediakan variables; templateName dan languageCode diwarisi dari payload default.
Pada contoh ini, template memiliki header media sekaligus variabel body yang dipersonalisasi.
{
"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"]
}
]
}
}
}
]
}
- Berkat
isMerge: true,templateNametidak perlu diulang di setiap payload penerima - Array
variablessetiap penerima sepenuhnya independen - URL media header harus dapat diakses publik
- Jika
typedihilangkan pada payload penerima,defaultPayload.typediwarisi
4. Variabel tombol URL
Gunakan komponen BUTTONS saat template berisi tombol dengan akhiran URL dinamis. Misalnya, nomor pelacakan yang ditambahkan ke URL dasar 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"]
}
]
}
}
}
]
}
- Parameter
BUTTONSdicocokkan menurut urutan tombol yang memiliki variabel - Tombol FLOW dan tombol tanpa variabel diabaikan; pengindeksan hanya berlaku untuk tombol URL dinamis
- Jika URL tombol template adalah
https://example.com/track/{{1}}, makaparameters[0]menggantikan{{1}}
5. Pengiriman terjadwal
Jadwalkan pesan untuk dikirim pada tanggal dan waktu mendatang. scheduleAt harus diberikan sebagai stempel waktu 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" }
}
]
}
}
}
]
}
scheduleAtharus diberikan dalam zona waktu UTC (misalnya, untuk pukul 10.00 waktu Turki, gunakan07:00:00.000Z)- Contoh ini menggunakan format parameter bernama; template harus berisi placeholder seperti
{{name}}dan{{discountRate}} - Dengan
action, percakapan yang dibuat oleh pengiriman pesan otomatis ditugaskan ke grup kerja yang ditentukan
Respons
Permintaan yang berhasil mengembalikan bulkOperationId, yang dapat digunakan untuk melacak proses pengiriman:
{
"bulkOperationId": "abc123xyz789"
}
Respons error
| Status | Deskripsi |
|---|---|
recipients field is required | Kolom recipients tidak dikirim |
Channel not found | Tidak ditemukan saluran terverifikasi yang cocok dengan channelUsername dan connectorBrand |
Channel is not verified | Saluran yang cocok ada tetapi belum terverifikasi |
zod-schema-error | Sebuah kolom di isi permintaan gagal validasi skema (kolom wajib tidak ada, tipe salah, nilai tidak didukung, lebih dari satu pengenal pada satu penerima, atau payload tidak ada). Pesan menyebutkan nama kolomnya, misalnya recipients.0.referenceId: referenceId must be unique |
bulkOperationId yang dikembalikan dapat digunakan dengan endpoint di bawah ini untuk melihat statistik pengiriman dan menghentikan proses pengiriman.
Show — Status dan statistik operasi massal
Mengambil operasi massal beserta status terkininya dan penghitung pengiriman item-itemnya, di bawah kunci bulkOperation.
POST https://app.monochat.ai/api/:slug/custom-functions/bulk-message-api-app/api/v2/bulk-operation/show.js
Parameter permintaan
| Parameter | Tipe | Wajib | Deskripsi |
|---|---|---|---|
bulkOperationId | string | Ya | ID operasi massal yang dilacak (dikembalikan dari 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"
}'
Respons
{
"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"
}
}
Kolom show
Kolom-kolom ini berada di bawah bulkOperation.
| Kolom | Tipe | Deskripsi |
|---|---|---|
status | string | Status operasi massal: preparing, scheduled, pending, running, stopping, stopped, completed, failed |
progress.total | number | Jumlah total item |
progress.pending | number | Item yang masih menunggu dalam antrean |
progress.succeeded | number | Item yang berhasil diproses untuk pengiriman |
progress.failed | number | Item yang mengalami error pengiriman |
progress.cancelled | number | Item yang dibatalkan oleh stop |
progress.unknown | number | Item yang hasilnya tidak dapat ditentukan |
result.outcome | string | Hasil akhir setelah operasi massal selesai: success, partial, all-failed, cancelled, unknown |
result.hasErrors | boolean | true jika setidaknya satu item gagal |
scheduleAt | string | Waktu pengiriman terjadwal (hanya untuk operasi massal terjadwal) |
startedAt, completedAt | string | Kapan pengiriman dimulai dan selesai |
progress.succeeded menunjukkan bahwa pesan berhasil diserahkan oleh sistem. Ini tidak menjamin bahwa Meta menyampaikan pesan ke penerima. Pembaruan status berikutnya dari Meta (seperti delivered, read, atau failed) tidak memengaruhi penghitung ini dan tidak tercermin di sini.
- Endpoint show: Menampilkan status pengiriman item (
pending,succeeded,failed,cancelled,unknown) - Endpoint message-stats: Menampilkan status pesan sebenarnya (
pending,sending,sent,delivered,read,error, dll.) - Sebuah item bisa
succeeded, tetapi pesannya mungkin belum terkirim/terbaca
Reference ID
referenceId adalah kolom opsional yang dapat Anda gunakan untuk mencocokkan item pengiriman dengan ID dari sistem Anda sendiri untuk keperluan pelacakan (misalnya nomor pesanan, ID tiket). Nilai ini dikembalikan pada setiap item sebagai payload.referenceId.
Jika diberikan, nilainya harus unik di dalam satu operasi massal (maksimal 256 karakter).
- Tidak wajib digunakan
- Tidak boleh duplikat dalam operasi massal yang sama
- Dapat dipakai ulang di operasi massal yang berbeda
Message Stats — Status pesan WhatsApp
Mengambil statistik status pesan dari sebuah operasi massal. Berbeda dengan endpoint show, endpoint ini menampilkan message.status sebenarnya dari pesan yang dikirim, bukan status item.
Status pesan yang mungkin: 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
Parameter permintaan
| Parameter | Tipe | Wajib | Deskripsi |
|---|---|---|---|
bulkOperationId | string | Ya | ID operasi massal yang di-query |
{
"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"
}'
Respons
{
"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
}
Kolom message stats
| Kolom | Tipe | Deskripsi |
|---|---|---|
pending | number | Pesan yang belum dikirim |
sending | number | Pesan yang sedang dikirim |
sent | number | Pesan yang sudah diserahkan ke WhatsApp, belum terkirim |
delivered | number | Pesan yang terkirim ke ponsel penerima |
read | number | Pesan yang dibaca penerima |
deleted | number | Pesan yang dihapus |
warning | number | Pesan dengan peringatan |
error | number | Pesan dengan error |
unknown | number | Pesan dengan status tidak diketahui |
not-sended | number | Pesan yang tidak dapat dikirim |
no-message | number | Item tanpa pesan (masih dalam antrean, gagal, atau dibatalkan) |
total | number | Jumlah total item |
- Jumlah
no-messageyang tinggi saat operasi massal berstatusrunningmenunjukkan pengiriman masih berlangsung - Jumlah
deliveredmenunjukkan pesan berhasil terkirim - Jumlah
readdapat digunakan untuk mengukur keterlibatan kampanye - Anda dapat memanggil endpoint ini secara berkala untuk pelacakan real-time
Struktur options — penomoran halaman, pemfilteran, dan pengurutan
Parameter options yang digunakan pada endpoint list dan list-with-messages menyediakan struktur standar untuk penomoran halaman, pemfilteran, dan pengurutan.
Kolom options
| Kolom | Tipe | Wajib | Deskripsi |
|---|---|---|---|
pagination | object | Tidak | Pengaturan penomoran halaman |
filtering | object | Tidak | Kriteria pemfilteran |
sorting | object | Tidak | Pengaturan pengurutan (misalnya {"position": 1}) |
Struktur pagination
Jika pagination tidak dikirim, halaman pertama dikembalikan dengan maksimal 50 item. Jika dikirim, currentPage wajib diisi.
| Kolom | Tipe | Default | Deskripsi |
|---|---|---|---|
currentPage | number | — | Nomor halaman yang diambil (wajib saat pagination dikirim) |
pageItems | number | 50 | Jumlah item per halaman (maksimum: 50) |
Struktur filtering
Pemfilteran menggunakan format query MongoDB pada kolom item, dengan nama kolom persis seperti yang muncul dalam respons (misalnya status, payload.referenceId, result.messageId). Pada endpoint list-with-messages, Anda juga dapat memfilter berdasarkan kolom pesan (misalnya message.status).
// Filter berdasarkan status item
{
"options": {
"filtering": {
"status": "succeeded"
}
}
}
// Filter berdasarkan referenceId
{
"options": {
"filtering": {
"payload.referenceId": "ORDER-12345"
}
}
}
// Filter berdasarkan status pesan (hanya list-with-messages)
{
"options": {
"filtering": {
"message.status": "delivered"
}
}
}
// Filter berdasarkan beberapa status dengan $in (operator MongoDB)
{
"options": {
"filtering": {
"message.status": {
"$in": ["delivered", "read"]
}
}
}
}
// Kecualikan status tertentu dengan $nin (operator MongoDB)
{
"options": {
"filtering": {
"message.status": {
"$nin": ["error", "not-sended"]
}
}
}
}
// Tampilkan item yang tidak memiliki pesan (hanya list-with-messages)
{
"options": {
"filtering": {
"message": {
"$exists": false
}
}
}
}
Struktur sorting
Pengurutan menggunakan format sort MongoDB. 1 berarti menaik, -1 berarti menurun. position adalah urutan penerima dalam array recipients pada permintaan (dimulai dari 0).
// Urutkan sesuai urutan penerima dikirim dalam permintaan
{
"options": {
"sorting": {
"position": 1
}
}
}
// Urutkan berdasarkan beberapa kolom
{
"options": {
"sorting": {
"status": 1,
"position": 1
}
}
}
Contoh penggunaan gabungan
{
"bulkOperationId": "abc123xyz789",
"options": {
"pagination": {
"currentPage": 2,
"pageItems": 50
},
"filtering": {
"message.status": "delivered"
},
"sorting": {
"position": 1
}
}
}
Contoh ini menampilkan halaman kedua dari pesan yang terkirim, sesuai urutan penerima.
- Gabungkan
filteringdanpaginationuntuk query yang terarah - Respons menyertakan
options.pagination.totalCountdanoptions.pagination.totalPagesuntuk navigasi - Filter
message.statushanya berfungsi pada endpointlist-with-messages
Items — Detail dan daftar item
Menampilkan semua item pengiriman dari sebuah operasi massal. Setiap item mewakili satu entri dalam array recipients.
List — Daftar item
POST https://app.monochat.ai/api/:slug/custom-functions/bulk-message-api-app/api/v2/bulk-operation-items/list.js
Parameter permintaan
| Parameter | Tipe | Wajib | Deskripsi |
|---|---|---|---|
bulkOperationId | string | Ya | ID operasi massal yang ditampilkan |
options | object | Tidak | Opsi penomoran halaman, pemfilteran, dan pengurutan. Lihat Struktur options untuk detailnya. |
Permintaan — penggunaan dasar
{
"bulkOperationId": "abc123xyz789",
"options": {
"pagination": {
"currentPage": 1,
"pageItems": 50
}
}
}
Permintaan — filter berdasarkan status tertentu
{
"bulkOperationId": "abc123xyz789",
"options": {
"pagination": {
"currentPage": 1,
"pageItems": 50
},
"filtering": {
"status": "failed"
}
}
}
Hanya menampilkan item pengiriman yang gagal, dengan alasannya di error.
Respons
{
"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 — Daftar dengan detail pesan
Memiliki fitur yang sama dengan endpoint list (penomoran halaman, pemfilteran, pengurutan). Perbedaannya: setiap item juga membawa objek message dan session terkait jika ada. Dengan begitu Anda dapat melihat status pesan (delivered, read, error, dll.) dan payload dalam satu query.
POST https://app.monochat.ai/api/:slug/custom-functions/bulk-message-api-app/api/v2/bulk-operation-items/list-with-messages.js
Permintaan — penggunaan dasar
{
"bulkOperationId": "abc123xyz789",
"options": {
"pagination": {
"currentPage": 1,
"pageItems": 50
}
}
}
Permintaan — filter berdasarkan status pesan
{
"bulkOperationId": "abc123xyz789",
"options": {
"pagination": {
"currentPage": 1,
"pageItems": 50
},
"filtering": {
"message.status": "delivered"
}
}
}
Contoh ini hanya mengambil pesan dengan status "delivered".
Permintaan — daftar pesan yang gagal
{
"bulkOperationId": "abc123xyz789",
"options": {
"pagination": {
"currentPage": 1,
"pageItems": 50
},
"filtering": {
"message.status": "error"
}
}
}
Digunakan untuk meninjau pesan yang mengalami error pengiriman.
Respons
{
"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": {}
}
}
Kolom item
| Kolom | Tipe | Deskripsi |
|---|---|---|
_id | string | ID item |
bulkOperationId | string | ID operasi massal pemilik item ini |
position | number | Urutan penerima dalam array recipients pada permintaan, dimulai dari 0 |
payload | object | Penerima persis seperti yang dikirim dalam permintaan (username / userId / sessionId, referenceId, payload, isMerge) |
status | string | Status item: pending, succeeded, failed, cancelled, unknown |
error | object | Hanya pada item failed: code, message, dan retryable |
result.userId | string | ID pengguna penerima |
result.sessionId | string | ID sesi percakapan |
result.messageId | string | ID pesan terkirim (tidak ada jika tidak ada pesan yang dikirim) |
completedAt | string | Kapan item diproses |
message | object | Detail pesan (hanya di list-with-messages) |
session | object | Detail percakapan (hanya di list-with-messages) |
Perbandingan List dan List-With-Messages
| Fitur | list | list-with-messages |
|---|---|---|
| Penomoran halaman | Ya | Ya |
| Pemfilteran | Ya (hanya kolom item) | Ya (kolom item + pesan) |
| Message / Session | Tidak | Ya (jika ada) |
| Kinerja | Cepat | Sedang (melakukan JOIN) |
| Filter message.status | Tidak tersedia | Tersedia |
- list: Menampilkan semua item dengan cepat, memfilter berdasarkan referenceId, memeriksa status item
- list-with-messages: Melihat status pesan WhatsApp (delivered, read), memeriksa payload pesan
- Contoh pemfilteran:
{"status": "failed"}— Item pengiriman yang gagal{"payload.referenceId": "ORDER-123"}— Reference ID tertentu{"message.status": "delivered"}— Pesan terkirim (hanya list-with-messages){"message.status": "read"}— Pesan terbaca (hanya list-with-messages){"message.status": "error"}— Pesan dengan error (hanya list-with-messages){"message.status": {"$in": ["delivered", "read"]}}— Pesan yang terkirim atau terbaca (hanya list-with-messages){"message.status": {"$nin": ["error", "not-sended"]}}— Pesan tanpa yang error dan tidak terkirim (hanya list-with-messages){"message": {"$exists": false}}— Item tanpa pesan (hanya list-with-messages){"status": {"$in": ["succeeded", "pending"]}}— Item yang berhasil atau tertunda
- Endpoint
listlebih cepat; pilih endpoint ini untuk pemeriksaan status umum - Gunakan
list-with-messagessaat detail pesan dibutuhkan - Jumlah item maksimum per halaman (pageItems) adalah 50; default 50 jika tidak ditentukan
- Filter
message.statushanya berfungsi padalist-with-messages - Item tanpa
result.messageIdtidak memiliki objekmessage
Stop — Batalkan pengiriman
Menghentikan pengiriman operasi massal yang sedang berjalan. Semua item pending dipindahkan ke status cancelled dan operasi massal menjadi stopped. Item yang sudah diproses sebagai succeeded atau failed tidak terpengaruh. Operasi massal terjadwal juga dapat dihentikan sebelum waktu scheduleAt-nya.
POST https://app.monochat.ai/api/:slug/custom-functions/bulk-message-api-app/api/v2/bulk-operation/stop.js
Tindakan ini tidak dapat dibatalkan. Pengiriman yang dihentikan tidak dapat dilanjutkan.
Parameter permintaan
| Parameter | Tipe | Wajib | Deskripsi |
|---|---|---|---|
bulkOperationId | string | Ya | ID operasi massal yang dihentikan |
{
"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"
}'
Respons
Untuk permintaan yang berhasil, isi respons kosong. Status HTTP 200 menunjukkan bahwa operasi selesai dengan berhasil.
{}
- Hanya operasi massal yang dibuat melalui API ini yang dapat dihentikan
- Setelah menghentikan pengiriman, Anda dapat menggunakan endpoint
showuntuk memeriksa jumlah item yang dibatalkan (bulkOperation.progress.cancelled) - Jika operasi massal tidak ditemukan, API mengembalikan error:
Bulk operation not found.