Nama jenis event menggunakan format dot-namespaced (resource.action), konvensi yang sama dengan yang digunakan Stripe, GitHub, dan Meta. Setiap body JSON event membawa field event dengan string yang persis sama.
Matriks dukungan
Tidak semua channel dapat mengirimkan semua event β sebagian besar karena platform yang mendasarinya (WhatsApp, Telegram, Instagram, Messenger) memang tidak menyediakannya. Pemilih event di dashboard akan menampilkan abu-abu untuk apa pun yang tidak didukung oleh channel yang Anda pilih, sehingga Anda tidak bisa salah berlangganan sesuatu yang tidak akan pernah terpicu.
| Event | WA Official | WA Unofficial | Telegram | Webchat | ||
|---|---|---|---|---|---|---|
message.received | β | β | β | β | β | β |
message.sent | β | β | β | β | β | β |
message.status.sent | β | β | β | β | β | β |
message.status.delivered | β | β | β | β | β | β |
message.status.read | β | β | β | β | β | β |
message.status.failed | β | β | β | β | β | β |
message.reaction.added | β | β | β | β | β | β |
message.reaction.removed | β | β | β | β | β | β |
conversation.assigned | β | β | β | β | β | β |
conversation.resolved | β | β | β | β | β | β |
template.status_updated | β | β | β | β | β | β |
call.status_updated | β | β | β | β | β | β |
Referensi event
| Event | Kapan terpicu |
|---|---|
message.received | Terpicu saat kontak mengirim pesan masuk baru pada channel mana pun. |
message.sent | Terpicu saat Chatmo mengirim pesan keluar β mencakup agen manusia yang mengetik di dashboard, balasan AI agent, otomasi Workflow, dan pesan yang dikirim melalui Send Message API. Periksa field sender.type pada payload untuk membedakannya. |
message.status.sent / .delivered / .read / .failed | Siklus status pengiriman khusus WhatsApp untuk pesan keluar, sesuai dengan level ACK yang dilaporkan WhatsApp sendiri. Telegram, Instagram, dan Messenger tidak menyediakan API delivery-receipt, sehingga event ini tidak pernah terpicu untuk channel tersebut. |
message.reaction.added / .removed | Terpicu saat kontak atau agen bereaksi pada pesan dengan emoji, atau menghapus reaksi yang sebelumnya ditambahkan. |
conversation.assigned | Terpicu saat sebuah percakapan di-assign ke agen atau tim β baik dilakukan secara manual dari dashboard maupun otomatis oleh aturan auto-assignment. |
conversation.resolved | Terpicu saat sebuah percakapan ditandai resolved, terlepas dari siapa atau apa yang me-resolve-nya (agen manusia, handoff AI, atau Workflow). |
template.status_updated | Khusus WhatsApp Official. Terpicu saat status review Meta terhadap salah satu template pesan Anda berubah (approved, rejected, paused, dsb). |
call.status_updated | Khusus WhatsApp Official. Terpicu saat status WhatsApp Business Calling berubah (ringing, in progress, missed, completed, dan seterusnya). |
Bentuk JSON persis dari setiap event, per channel, ada di bawah.
Envelope payload
Setiap request webhook menggunakan envelope yang sama:
Code
event sesuai persis dengan salah satu jenis event. Bentuk data tergantung pada event β identik di semua channel kecuali beberapa field yang dicatat di bawah. raw_payload bersifat opsional dan hanya muncul jika Anda mengaktifkannya β lihat penjelasan di bawah.
Raw provider payload
Setiap webhook endpoint punya toggle Include raw provider payload (nonaktif secara default, ada di form Add/Edit Webhook). Saat diaktifkan, setiap delivery pada endpoint itu akan menyertakan field raw_payload β sejajar dengan data, bukan bersarang di dalamnya β berisi payload yang benar-benar diterima Chatmo dari channel untuk event tersebut, hampir apa adanya.
Gunakan data untuk kebutuhan yang sudah dicakupnya, yaitu hampir semuanya: teks, file pesan media (data.media.url, tersimpan di Chatmo), lokasi, kontak yang dibagikan, template dan balasan tombol semuanya punya block normalized sendiri di setiap channel. Aktifkan raw_payload hanya jika Anda butuh field khusus provider yang tidak ada di data. Lihat Raw payload tiap channel di bawah.
:::warning Ini bentuk dari channel, bukan dari Chatmo
raw_payload mencerminkan item webhook asli dari WhatsApp / Telegram / Meta untuk event tersebut, lengkap dengan nama field aslinya. Ini tidak dinormalisasi, tidak diversi oleh Chatmo, dan bisa berubah kapan saja provider mengubah API mereka β Chatmo tidak menjamin bentuknya seperti pada data. Aktifkan ini hanya jika Anda siap menanganinya, dan perlakukan sebagai kode integrasi khusus-channel, bukan kontrak yang stabil.
:::
raw_payload hanya pernah ada untuk event yang benar-benar diterima Chatmo dari sebuah channel. Event yang berasal dari Chatmo sendiri tidak pernah menyertakannya, terlepas dari toggle-nya:
Tidak pernah ada raw_payload | Alasan |
|---|---|
message.sent | Chatmo yang mengirim pesan ini, jadi tidak ada payload provider masuk yang bisa dilampirkan. Satu-satunya pengecualian adalah pesan yang diketik di HP yang terhubung (sent_via: "device", khusus WhatsApp), yang membawa echo yang diterima Chatmo. |
conversation.assigned | Assignment adalah aksi internal Chatmo. |
conversation.resolved | Resolve adalah aksi internal Chatmo. |
| Event apa pun pada channel Webchat | Webchat adalah protokol milik Chatmo sendiri, bukan provider pihak ketiga β tidak ada body webhook eksternal yang bisa dicerminkan. |
Event lainnya (message.received, message.reaction.added/.removed, message.status.*, template.status_updated, call.status_updated) akan menyertakannya, di setiap channel yang memang mendukung event tersebut β lihat matriks dukungan.
:::tip Coba dengan Test
Tombol Test juga mengirim raw_payload yang realistis per channel (kalau toggle-nya aktif), dibangun dari bentuk yang sama seperti di halaman ini β cara yang bagus untuk melihat nama field sebenarnya sebelum menulis kode apa pun. Lihat Pengujian & Log Pengiriman.
:::
message.received
Code
message.received dan message.sent memakai bentuk data yang persis sama di semua channel. Partner cukup menangani keduanya dengan satu parser.
Field
| Field | Selalu ada | Keterangan |
|---|---|---|
message_id | β | ID pesan di Chatmo (UUID). Gunakan untuk de-duplikasi delivery. |
conversation_id | β | ID percakapan di Chatmo (UUID). |
external_message_id | β | ID pesan dari channel itu sendiri (wamid... di WhatsApp Official, TLGM... di Telegram, dan seterusnya). |
type | β | TEXT, IMAGE, VIDEO, AUDIO, DOCUMENT, STICKER, LOCATION, CONTACT, TEMPLATE, CALL_REQUEST atau CALL_ENDED. |
content | β | Teks pesan, caption pesan media, atau ringkasan singkat yang mudah dibaca. String kosong jika tidak ada. Lihat Jenis konten. |
timestamp | β | Waktu pesan dikirim, dalam UTC (RFC 3339). created_at pada envelope adalah waktu webhook dikirim. |
sender | β | Siapa yang menulis pesan. type bernilai CONTACT untuk message.received, beserta id/name kontak. |
contact | β | Pelanggan di percakapan ini: id, name, dan phone jika kontak punya nomor (selalu ada di channel WhatsApp; kontak Instagram, Facebook dan Telegram tidak punya). |
media | β | File dari pesan media. Lihat media. |
location | β | Lokasi yang dibagikan. Lihat location. |
contacts | β | Kartu kontak yang dibagikan. Lihat contacts. |
template | β | Pesan template. Lihat template. |
button_reply | β | Tombol atau baris list yang diklik kontak. Lihat button_reply. |
reply_to | β | Pesan yang dikutip (di-reply) oleh pesan ini. Lihat reply_to. |
referral | β | Iklan Click-to-WhatsApp / Instagram yang memulai chat. Lihat referral. |
call | β | Ringkasan panggilan untuk CALL_REQUEST / CALL_ENDED. Lihat call. |
Field bertanda "β" tidak dikirim sama sekali (bukan null) jika tidak relevan, jadi periksa dulu keberadaan key-nya sebelum membacanya. Field opsional baru bisa ditambahkan seiring waktu; abaikan key yang tidak Anda kenali.
Jenis konten
type mencerminkan apa yang sebenarnya dikirim. Baca content untuk teksnya, lalu block sesuai tipenya:
type | content | Block yang dibaca |
|---|---|---|
TEXT | Isi teks pesan. | button_reply jika berasal dari klik tombol. |
IMAGE / VIDEO / AUDIO / DOCUMENT / STICKER | Caption, atau string kosong. | media |
LOCATION | "π <nama tempat>", atau "π Shared Location" jika pin dikirim tanpa nama. | location |
CONTACT | "π€ <nama kontak>" ("π€ <nama> and N more" untuk beberapa kontak sekaligus). | contacts |
TEMPLATE | Teks template (header teks, lalu body). | template |
CALL_REQUEST / CALL_ENDED | Ringkasan singkat panggilan, bisa kosong. | call |
LOCATION dan CONTACT datang dari WhatsApp Official, WhatsApp Unofficial dan Telegram. Facebook dan Instagram (Messenger Platform) tidak punya pesan location atau contact-share, jadi di dua channel itu kontak bisa mengirim TEXT, IMAGE, VIDEO, AUDIO, DOCUMENT atau STICKER. TEMPLATE masuk datang dari WhatsApp Unofficial, saat akun WhatsApp Business lain mengirim pesan template atau interaktif ke nomor Anda.
Block khusus per tipe
media
Ada untuk IMAGE, VIDEO, AUDIO, DOCUMENT dan STICKER. Chatmo mengunduh setiap file masuk dari channel dan menyimpan salinannya di storage Chatmo sendiri, jadi media.url adalah link langsung https://files.chatmo.io/... di semua channel. Anda tidak butuh access token provider, bot token, atau panggilan Graph API untuk mengambilnya, dan link-nya tidak kedaluwarsa seperti link CDN provider.
Code
| Field | Keterangan |
|---|---|
url | Link unduhan langsung ke file di storage Chatmo. |
id | ID file di Chatmo. Kirim sebagai media.file_id ke Send Message API untuk mengirim ulang file yang sama tanpa upload ulang. |
file_name | Nama file asli, jika channel menyediakannya (selalu ada untuk DOCUMENT). |
mime_type | Contoh: image/jpeg, video/mp4, audio/ogg, application/pdf. |
file_size | Ukuran dalam byte. |
thumbnail_url | Gambar preview kecil, jika Chatmo membuatnya. |
caption | Sama dengan content. Hanya ada jika pengirim menambahkan caption. |
Hanya url yang dijamin ada. Field lainnya diisi jika diketahui. Pada kasus langka Chatmo gagal menyalin file dari channel (error provider saat itu), id tidak ada dan url berisi link asli provider (Facebook / Instagram, berumur pendek) atau seluruh block media tidak dikirim. Referensi asli dari provider tetap ada di raw_payload jika Anda mengaktifkannya.
location
Ada untuk LOCATION.
Code
latitude dan longitude selalu diisi. name dan address berasal dari channel untuk tempat yang punya nama; jika tidak ada, Chatmo mencarinya dari koordinat (best effort). static_map_url adalah gambar preview peta.
contacts
Ada untuk CONTACT. Selalu berupa array, walaupun hanya satu kontak.
Code
vcard hanya disertakan jika channel mengirim teks vCard mentah (WhatsApp Unofficial).
template
Ada untuk pesan TEMPLATE (dan pesan interaktif WhatsApp Unofficial seperti pesan tombol atau list). Teks body ada di content; bagian template lainnya ada di sini:
Code
| Field | Keterangan |
|---|---|
type | Khusus pesan masuk (WhatsApp Unofficial): template, buttons, list atau interactive. |
name / language / category | Identitas template. Ada di message.sent untuk template yang Anda kirim dari Chatmo (WhatsApp Official). |
id | ID template di Chatmo, pada message.sent. |
components | Bagian-bagian template dalam format component WhatsApp (HEADER, FOOTER, BUTTONS, ...). Teks BODY ada di content. |
header_media_url | Gambar/video/dokumen header, tersimpan di storage Chatmo. |
variables | Nilai yang mengisi placeholder template, pada message.sent. |
button_reply
Ada saat kontak mengklik tombol quick-reply, tombol interaktif, atau baris list (WhatsApp Official dan Unofficial). type bernilai TEXT dan content berisi label tombolnya.
Code
type bernilai quick_reply (tombol template), button_reply (tombol interaktif) atau list_reply (baris list, yang juga membawa description). payload adalah ID yang Anda pasang di tombol tersebut.
reply_to
Ada saat kontak membalas (mengutip) pesan sebelumnya.
Code
message_id diisi jika pesan yang dikutip dikenali Chatmo; external_message_id adalah ID pesan tersebut di channel.
referral
Ada di pesan pertama dari chat yang dimulai dari iklan Click-to-WhatsApp atau iklan / post Instagram.
Code
call
Ada untuk CALL_REQUEST dan CALL_ENDED (WhatsApp Official calling): snapshot panggilan, misalnya call_id, direction, status dan duration_seconds. Lihat call.status_updated untuk status panggilan secara live.
Raw payload tiap channel
Semua yang di atas sudah ada di data pada setiap channel, jadi sebagian besar integrasi tidak butuh raw_payload. Aktifkan hanya jika Anda butuh field khusus provider yang tidak ada di data. Untuk media, raw payload berisi referensi file milik provider sendiri, yang cara pakainya berbeda per channel:
| Channel | Field raw | Cara mengambil file dari provider |
|---|---|---|
| WhatsApp Official | message.image.id (atau .video.id / .document.id / ...), media ID yang opaque. Meta sedang meluncurkan field message.image.url secara bertahap per-WABA (mulai 2025-11-12) yang berupa link unduhan langsung dengan autentikasi access token, tapi bisa saja belum ada di pesan tertentu. | Kalau url ada, ambil langsung (dengan access token Anda). Kalau tidak ada, panggil Graph API Meta GET /{media-id} dengan access token Anda sendiri untuk meresolusi id menjadi URL unduhan berumur pendek. Lebih mudah: pakai data.media.url. |
| WhatsApp Unofficial | data.media_url | Sudah berupa URL langsung yang di-hosting (file yang sama dengan data.media.url). |
| Telegram | message.photo[].file_id (atau .video.file_id / .document.file_id), file ID yang opaque. | Panggil getFile Bot API dengan bot token Anda untuk meresolusinya menjadi path unduhan. Lebih mudah: pakai data.media.url. |
| Facebook / Instagram | message.attachments[].payload.url | Link CDN Meta berumur pendek. Pakai data.media.url untuk link yang tidak kedaluwarsa. |
Di bawah ini satu contoh raw_payload per channel: pesan TEXT (kasus paling sederhana) dan pesan IMAGE (untuk menunjukkan referensi media-nya). Jenis konten lain (VIDEO, DOCUMENT, LOCATION, CONTACT) mengikuti bentuk objek yang sama dengan field bersarang yang berbeda; tabel referensi di bawah tiap channel mencantumkan nama field-nya.
WhatsApp Official
Dibungkus dalam envelope webhook lengkap milik Meta β object β entry β changes β value β persis seperti referensi webhook resmi Meta, dipersempit hanya untuk satu pesan yang memicu delivery ini (entry/changes masing-masing hanya punya satu elemen).
Raw payload β TEXT
Code
Raw payload β IMAGE
Code
url bagian dari peluncuran bertahap Meta (lihat tabel di atas) β bisa saja tidak ada di webhook Anda meskipun untuk pesan IMAGE. Selalu siapkan fallback ke id kalau tidak ada.
| Tipe | Field raw |
|---|---|
| VIDEO | ...value.messages[0].video.id, .mime_type, .caption, .url (peluncuran bertahap) |
| DOCUMENT | ...value.messages[0].document.id, .mime_type, .filename, .caption, .url (peluncuran bertahap) |
| LOCATION | ...value.messages[0].location.latitude, .longitude, .name, .address |
| CONTACT | ...value.messages[0].contacts[].name.formatted_name, .phones[].phone / .wa_id |
:::tip Chatmo merekonstruksi ini, bukan meneruskan byte asli dari Meta
Meta mengelompokkan beberapa pesan/status dalam satu panggilan webhook (value.messages bisa berisi lebih dari satu elemen). Chatmo sudah memecah satu batch menjadi satu delivery per pesan sebelum sampai ke endpoint Anda, jadi raw_payload membangun ulang struktur object/entry/changes/value yang sama seperti yang didokumentasikan Meta, hanya untuk satu pesan tersebut β akurat field demi field, tapi bukan salinan byte-per-byte dari apa yang benar-benar dikirim Meta (field metadata yang disertakan Meta tapi tidak disimpan Chatmo akan kosong, bukan dikarang).
:::
WhatsApp Unofficial
Raw payload β TEXT
Code
Raw payload β IMAGE
Code
| Tipe | Field raw |
|---|---|
| VIDEO | data.media_url, .mimetype, .seconds, .caption |
| DOCUMENT | data.media_url, .mimetype, .filename, .page_count, .caption |
| LOCATION | data.latitude, .longitude, .location_name, .location_address |
| CONTACT | data.vcard (teks vCard mentah β nama/telepon ada di dalamnya) |
Telegram
Raw payload β TEXT
Code
Raw payload β IMAGE
Code
| Tipe | Field raw |
|---|---|
| VIDEO | message.video.file_id, .duration, .caption |
| DOCUMENT | message.document.file_id, .file_name, .caption |
| LOCATION | message.location.latitude, .longitude (atau message.venue untuk tempat bernama) |
| CONTACT | message.contact.phone_number, .first_name, .last_name |
Facebook Messenger
Dibungkus dalam bentuk resmi Messenger Platform milik Meta β object: "page" β entry[] β messaging[] β lihat referensi webhook Messenger Meta. entry/messaging masing-masing hanya punya satu elemen, alasan yang sama seperti WhatsApp Official di atas.
Raw payload β TEXT
Code
Raw payload β IMAGE
Code
| Tipe | Field raw |
|---|---|
| VIDEO / AUDIO / DOCUMENT | ...messaging[0].message.attachments[0].type (video / audio / file), .payload.url |
Tidak ada tipe pesan LOCATION atau CONTACT β Messenger Platform tidak mengirimkannya sebagai pesan masuk.
Kontrak Messenger Platform yang sama dengan Facebook, nama field identik β tapi perhatikan body level teratas berupa JSON array, bukan objek biasa, sesuai referensi webhook Instagram Meta:
Raw payload β TEXT
Code
Raw payload β IMAGE
Code
| Tipe | Field raw |
|---|---|
| VIDEO / AUDIO / DOCUMENT | [0].entry[0].messaging[0].message.attachments[0].type, .payload.url |
Tidak ada tipe pesan LOCATION atau CONTACT, sama seperti Facebook.
message.sent
Code
Bentuk data sama dengan message.received: field yang sama dan block khusus per tipe yang sama (media, location, template, reply_to, ...). Template yang Anda kirim dari Chatmo membawa block template lengkap (name, language, category, components, variables). Perbedaannya:
| Field | Keterangan |
|---|---|
sender.type | AGENT (agen manusia, Workflow, Send Message API, atau aplikasi WhatsApp Business di HP yang terhubung) atau AI_AGENT. id/name adalah agen atau AI agent jika diketahui. |
status | Status pengiriman saat pesan dikirim: sent, delivered (Webchat), atau failed jika ditolak channel. Perubahan berikutnya dikirim sebagai event message.status.* (khusus WhatsApp). |
contact | Pelanggan penerima pesan. |
sent_via | Hanya untuk pengiriman otomatis atau eksternal: workflow, api (Send Message API) atau device (diketik langsung di HP lewat aplikasi WhatsApp / WhatsApp Business). Tidak ada untuk balasan dari dashboard dan AI agent. |
sent_via_api | true untuk pengiriman lewat Send Message API. Dipertahankan untuk integrasi lama; sebaiknya pakai sent_via. |
message.sent hanya membawa raw_payload untuk sent_via: "device" (echo yang diterima Chatmo dari WhatsApp). Pengiriman lainnya dilakukan oleh Chatmo sendiri, jadi tidak ada payload provider. Catatan internal (pesan private) tidak pernah memicu message.sent.
message.status.delivered / .read / .sent / .failed
Code
status mengikuti akhiran nama event (sent, delivered, read, failed). Hanya untuk WhatsApp Official dan WhatsApp Unofficial.
Raw payload β WhatsApp Official
Envelope object/entry/changes/value yang sama seperti message.received, dengan value.statuses menggantikan value.messages (webhook status masuk di bawah change "field": "messages" yang sama, sesuai model Meta):
Code
Raw payload β WhatsApp Unofficial
Code
message.reaction.added / .removed
Code
emoji berupa string kosong pada message.reaction.removed. reactor.type adalah CONTACT, AGENT, atau AI_AGENT. raw_payload hanya ada jika yang bereaksi adalah kontak β reaksi dari agen tidak punya payload provider masuk yang bisa dilampirkan, alasan yang sama seperti message.sent.
Raw payload β WhatsApp Official
Meta mengirim reaksi sebagai entri messages[] dengan type: "reaction" β envelope yang sama seperti message.received:
Code
"emoji": "" (string kosong) berarti reaksi dihapus.
Raw payload β WhatsApp Unofficial
Code
Raw payload β Telegram
Code
Array new_reaction kosong berarti reaksi dihapus.
Raw payload β Facebook Messenger
Meta mengirim reaksi sebagai entri messaging[] dengan reaction, bukan message β envelope yang sama seperti message.received:
Code
action menjadi "unreact" saat dihapus.
Raw payload β Instagram
Bentuk yang sama seperti Facebook, dibungkus dalam array top-level yang dipakai Instagram di seluruh halaman ini:
Code
conversation.assigned
Code
assigned_to.type adalah USER atau TEAM. Ini adalah aksi internal Chatmo β tidak pernah menyertakan raw_payload.
conversation.resolved
Code
resolved_by tidak disertakan jika percakapan di-resolve secara otomatis (AI atau Workflow), bukan oleh agen manusia. Ini juga aksi internal Chatmo β tidak pernah menyertakan raw_payload.
template.status_updated
Code
Khusus WhatsApp Official. status mengikuti status review template Meta (APPROVED, REJECTED, PAUSED, DISABLED, PENDING_DELETION, IN_APPEAL, PENDING).
Raw payload
Code
call.status_updated
Code
Khusus WhatsApp Official. status salah satu dari RINGING, IN_PROGRESS, COMPLETED, MISSED, NO_ANSWER, REJECTED, CANCELED, FAILED.
Raw payload
Code
