Cara Menangani Status Pesan WhatsApp dari Webhook

Status pesan WhatsApp menunjukkan perkembangan pesan setelah aplikasi mengirimkan request melalui API. Dengan webhook, perubahan status tersebut dapat diterima secara otomatis oleh server sehingga aplikasi tidak perlu terus-menerus melakukan pengecekan status pesan.

Status pesan dapat digunakan untuk memperbarui riwayat pengiriman, menampilkan status pada dashboard, mencatat pesan yang gagal, atau menentukan proses lanjutan setelah pesan diterima oleh WhatsApp.

Cara Menangani Status Pesan WhatsApp dari Webhook

Alur sederhananya:

Aplikasi
   ↓
API WhatsApp
   ↓
Pesan dikirim
   ↓
Status pesan berubah
   ↓
Webhook
   ↓
Server
   ↓
Database / Dashboard
`

Diagram alur penanganan status pesan WhatsApp melalui webhook

Apa Itu Status Pesan WhatsApp?

Status pesan WhatsApp adalah informasi mengenai kondisi pesan dalam proses pengiriman.

Status ini berbeda dengan status koneksi device.

Status device menunjukkan apakah device WhatsApp terhubung, sedangkan status pesan menunjukkan kondisi pesan tertentu setelah dikirim.

Contohnya:

Device:
CONNECTED

berbeda dengan:

Pesan:
SENT
DELIVERED
READ

Aplikasi perlu menyimpan kedua jenis informasi tersebut secara terpisah jika membutuhkan monitoring device sekaligus monitoring pesan.

Mengapa Status Pesan Perlu Ditangani?

Ketika sistem mengirim ribuan pesan, aplikasi tidak cukup hanya mengetahui bahwa request API berhasil diterima.

Request berhasil diterima API belum tentu berarti pesan sudah sampai ke penerima.

Contoh alur:

Request berhasil
      ↓
Pesan diproses
      ↓
Pesan terkirim
      ↓
Pesan diterima
      ↓
Pesan dibaca

Dengan menerima event status melalui webhook, aplikasi dapat memperbarui informasi pesan berdasarkan event yang diterima.

Contohnya pada dashboard:

Pesan #12345
Status: READ

atau:

Pesan #12346
Status: FAILED

Buat Endpoint Webhook

Endpoint webhook harus dapat menerima HTTP request dari API.

Contoh menggunakan Node.js dan Express:

const express = require('express');

const app = express();

app.use(express.json());

app.post('/webhook/whatsapp', (req, res) => {
  console.log(
    JSON.stringify(req.body, null, 2)
  );

  res.sendStatus(200);
});

app.listen(3000, () => {
  console.log('Server berjalan di port 3000');
});

Pada tahap awal, tampilkan payload secara lengkap agar struktur event dapat diketahui.

Jangan langsung membuat kode berdasarkan asumsi nama field status. Gunakan payload aktual yang diterima dari API.

Membaca Payload Status

Setelah webhook menerima event, periksa isi request:

app.post('/webhook/whatsapp', (req, res) => {
  const data = req.body;

  console.log('Webhook diterima');
  console.log(JSON.stringify(data, null, 2));

  res.sendStatus(200);
});

Dari payload tersebut, tentukan:

  • ID pesan
  • Nomor tujuan
  • Status pesan
  • Waktu event
  • Device yang digunakan
  • Informasi lain yang diperlukan aplikasi

Nama field harus mengikuti struktur payload webhook yang digunakan.

Jika struktur payload belum diketahui, jangan membuat parser dengan nama field yang belum diverifikasi.

Simpan ID Pesan

ID pesan penting untuk menghubungkan event webhook dengan pesan yang sebelumnya dikirim.

Misalnya aplikasi mengirim pesan:

Pesan ID: ABC123
Tujuan: 628123456789
Status: SENT

Kemudian webhook menerima event untuk pesan yang sama.

Aplikasi dapat mencari:

message_id = ABC123

lalu memperbarui status pada database.

Alurnya:

Kirim pesan
    ↓
Simpan message_id
    ↓
Webhook menerima event
    ↓
Cari message_id
    ↓
Update status

Tanpa identifier yang konsisten, aplikasi akan kesulitan menentukan pesan mana yang harus diperbarui ketika jumlah pengiriman sudah besar.

Struktur Database untuk Status Pesan

Data pesan dan statusnya dapat disimpan pada tabel seperti:

messages
- id
- message_id
- device_id
- recipient
- message
- status
- created_at
- updated_at

Contoh:

Message ID Recipient Status
ABC123 628123456789 SENT
ABC124 628987654321 DELIVERED
ABC125 628555555555 READ

Ketika event baru diterima, aplikasi mencari message_id yang sesuai dan memperbarui status.

Update Status dari Webhook

Contoh struktur handler:

app.post('/webhook/whatsapp', async (req, res) => {
  const event = req.body;

  res.sendStatus(200);

  try {
    const messageId = extractMessageId(event);
    const status = extractMessageStatus(event);

    if (!messageId || !status) {
      return;
    }

    await updateMessageStatus(
      messageId,
      status
    );

  } catch (error) {
    console.error(
      'Gagal memproses status pesan:',
      error
    );
  }
});

Fungsi extractMessageId() dan extractMessageStatus() perlu disesuaikan dengan struktur payload yang benar-benar diterima.

Jangan Menganggap Request API = Pesan Berhasil Terkirim

Salah satu kesalahan umum adalah mengubah status pesan menjadi SENT hanya karena request API menghasilkan response sukses.

Contohnya:

Aplikasi
   ↓
POST API
   ↓
HTTP 200

Response HTTP yang sukses menunjukkan request telah diproses oleh API. Status pesan berikutnya tetap perlu ditangani sesuai event yang diterima.

Karena itu, sistem dapat menyimpan status secara bertahap:

REQUESTED
   ↓
SENT
   ↓
DELIVERED
   ↓
READ

Nama dan urutan status harus mengikuti event yang tersedia pada API yang digunakan.

Menangani Pesan Gagal

Status gagal perlu diproses secara khusus karena aplikasi mungkin perlu mengambil tindakan berikutnya.

Contohnya:

Status: FAILED
       ↓
Simpan alasan jika tersedia
       ↓
Tandai pesan gagal
       ↓
Masuk antrean retry jika diperlukan

Data dapat disimpan seperti:

message_id: ABC123
status: FAILED
error: ...
updated_at: ...

Jangan langsung melakukan retry setiap kali menerima status gagal.

Retry harus memiliki batas percobaan dan aturan yang jelas agar satu pesan tidak dikirim berulang kali tanpa kontrol.

Membuat Retry untuk Pesan Gagal

Jika sistem membutuhkan retry, simpan jumlah percobaan pengiriman.

Contoh:

messages
- message_id
- status
- retry_count
- last_retry_at

Alurnya:

FAILED
  ↓
retry_count < batas?
  ↙          ↘
Ya           Tidak
↓              ↓
Retry        Tandai gagal

Misalnya batas retry ditetapkan sebanyak tiga kali:

Percobaan 1 → FAILED
Percobaan 2 → FAILED
Percobaan 3 → FAILED
→ Berhenti retry

Batas tersebut harus disesuaikan dengan kebutuhan sistem.

Menangani Status READ

Status READ dapat digunakan untuk memperbarui tampilan pada dashboard.

Contohnya:

Pesan:
Halo, apakah masih tersedia?

Status:
READ

Database kemudian diperbarui:

UPDATE messages
SET status = 'READ'
WHERE message_id = 'ABC123';

Pada aplikasi nyata, gunakan query parameterized atau ORM agar query tidak dibuat dari string input secara langsung.

Menangani Status DELIVERED

Status DELIVERED menunjukkan pesan telah mencapai tahap penerimaan yang sesuai dengan status tersebut.

Aplikasi dapat menggunakannya untuk:

  • memperbarui dashboard;
  • menghitung statistik pengiriman;
  • mencatat waktu delivery;
  • membedakan pesan yang sudah diterima dan belum.

Contoh data:

message_id: ABC123
status: DELIVERED
delivered_at: 2026-09-30 10:30:12

Simpan waktu setiap status jika laporan pengiriman membutuhkan data tersebut.

Simpan Waktu Setiap Perubahan Status

Untuk laporan yang lebih detail, database dapat menyimpan timestamp setiap perubahan.

Contoh:

messages
- message_id
- status
- sent_at
- delivered_at
- read_at
- failed_at

Data tersebut dapat digunakan untuk mengetahui durasi antara pengiriman, penerimaan, dan pembacaan pesan.

Contohnya:

sent_at       → 10:00:00
delivered_at  → 10:00:03
read_at       → 10:01:15

Dari data tersebut, aplikasi dapat menghitung waktu yang dibutuhkan setiap tahap.

Hindari Status Mundur

Event webhook dapat datang tidak sesuai urutan waktu yang diharapkan jika aplikasi memproses banyak request secara bersamaan.

Contoh:

READ
↓
DELIVERED

Jika aplikasi langsung menyimpan event kedua, status pesan dapat berubah kembali dari READ menjadi DELIVERED.

Karena itu, aplikasi perlu memiliki aturan urutan status.

Contoh sederhana:

SENT < DELIVERED < READ

Jika status baru memiliki tingkat yang lebih rendah daripada status yang sudah tersimpan, aplikasi dapat mengabaikannya.

Contoh:

const statusOrder = {
  SENT: 1,
  DELIVERED: 2,
  READ: 3
};

if (
  statusOrder[newStatus] >=
  statusOrder[currentStatus]
) {
  await updateMessageStatus(
    messageId,
    newStatus
  );
}

Daftar status dan urutannya harus disesuaikan dengan status yang benar-benar digunakan oleh API.

Hindari Event Duplikat

Webhook dapat menerima event yang sama lebih dari sekali. Jika setiap event langsung diproses, database dapat mencatat perubahan yang sama berulang kali.

Contoh:

ABC123 → DELIVERED
ABC123 → DELIVERED
ABC123 → DELIVERED

Untuk mencegah pemrosesan berulang, gunakan identifier event atau kombinasi data yang dapat membedakan event.

Jika identifier event tidak tersedia, aplikasi dapat menggunakan kombinasi seperti:

message_id + status

sebagai pemeriksaan tambahan.

Namun, cara ini perlu disesuaikan dengan kebutuhan aplikasi karena satu status dapat muncul lebih dari sekali dalam kondisi tertentu.

Pisahkan Webhook dan Proses Status

Endpoint webhook sebaiknya tidak menjalankan terlalu banyak pekerjaan sebelum memberikan response.

Contoh:

app.post('/webhook/whatsapp', async (req, res) => {
  const event = req.body;

  res.sendStatus(200);

  await processMessageStatus(event);
});

Untuk volume tinggi, proses status dapat diteruskan ke queue:

Webhook
   ↓
Validasi
   ↓
Queue
   ↓
Worker
   ↓
Update database
   ↓
Dashboard

Dengan cara ini, endpoint tetap ringan ketika banyak event masuk secara bersamaan.

Contoh Proses Status Pesan

Struktur proses lengkap dapat dibuat seperti berikut:

async function processMessageStatus(event) {
  const messageId = extractMessageId(event);
  const newStatus = extractMessageStatus(event);

  if (!messageId || !newStatus) {
    return;
  }

  const message = await findMessage(messageId);

  if (!message) {
    return;
  }

  const currentStatus = message.status;

  if (
    shouldUpdateStatus(
      currentStatus,
      newStatus
    )
  ) {
    await updateMessageStatus(
      messageId,
      newStatus
    );
  }
}

Struktur ini memisahkan proses menjadi beberapa bagian:

  1. Membaca ID pesan.
  2. Membaca status.
  3. Mencari pesan pada database.
  4. Membandingkan status.
  5. Memperbarui status jika diperlukan.

Kode dapat dikembangkan tanpa membuat route webhook menjadi terlalu panjang.

Contoh Tampilan Status pada Dashboard

Data status dari webhook dapat ditampilkan seperti:

Penerima Pesan Status
628123456789 Pesanan diterima SENT
628987654321 Pembayaran berhasil DELIVERED
628555555555 Tiket dibuat READ
628111111111 OTP FAILED

Dashboard dapat menampilkan data terbaru berdasarkan status yang tersimpan di database.

Jika membutuhkan laporan, tambahkan filter:

Status:
[ Semua ]

[ SENT ]
[ DELIVERED ]
[ READ ]
[ FAILED ]

Cara Menguji Status Pesan

Pengujian dapat dilakukan dengan mengirim satu pesan terlebih dahulu.

Urutannya:

1. Kirim satu pesan melalui API
2. Simpan ID pesan
3. Periksa response API
4. Tunggu event webhook
5. Periksa payload
6. Cocokkan ID pesan
7. Periksa status
8. Pastikan database diperbarui

Gunakan log saat pengembangan:

console.log(
  JSON.stringify(req.body, null, 2)
);

Setelah struktur payload sudah diketahui, gunakan logging yang lebih terkontrol pada server production.

Jika Status Pesan Tidak Masuk

Jika status pesan tidak muncul pada webhook, periksa beberapa bagian berikut:

Webhook Aktif

Pastikan URL webhook sudah dikonfigurasi dengan benar.

Endpoint Dapat Diakses

Pastikan server dapat menerima request dari internet.

Route Menerima POST

Periksa method dan path endpoint.

Payload Terbaca

Pastikan middleware membaca request body.

Device Terhubung

Status device perlu diperiksa karena pengiriman dan event pesan bergantung pada koneksi device.

ID Pesan Tersimpan

Pastikan aplikasi menyimpan identifier pesan dari proses pengiriman sehingga event webhook dapat dikaitkan dengan data yang benar.

Log Server

Periksa apakah event benar-benar sampai ke aplikasi.

Status Pesan untuk Laporan Pengiriman

Data status dari webhook dapat digunakan untuk membuat laporan.

Contohnya:

Total pesan      : 10.000
SENT             : 9.700
DELIVERED        : 9.200
READ             : 8.500
FAILED           : 300

Data tersebut dapat dihitung berdasarkan status terakhir setiap pesan.

Jangan menghitung setiap event sebagai satu pesan. Satu pesan dapat menghasilkan beberapa perubahan status.

Contohnya:

ABC123 → SENT
ABC123 → DELIVERED
ABC123 → READ

Tetap dihitung sebagai satu pesan, bukan tiga pesan.

Kesimpulan

Cara menangani status pesan WhatsApp dari webhook dimulai dengan menerima event, mengambil identifier pesan dan status, kemudian memperbarui data pesan pada database.

Alurnya:

Pesan dikirim
      ↓
Simpan message ID
      ↓
Status berubah
      ↓
Webhook menerima event
      ↓
Cari message ID
      ↓
Periksa status
      ↓
Update database
      ↓
Dashboard / laporan

Hal penting yang perlu diperhatikan adalah membedakan status device dengan status pesan, menyimpan identifier pesan, menangani event duplikat, mencegah status mundur, dan tidak menganggap response API sebagai status akhir pesan.

Struktur webhook yang sederhana juga membuat proses status lebih mudah dikembangkan untuk dashboard, laporan pengiriman, retry, CRM, dan sistem notifikasi.

Scroll to Top