Lewati ke konten
OmniChannels.ai

Panduan Webhook WhatsApp: Event, Keamanan, dan Retry

Cara kerja webhook WhatsApp: event pesan dan status, handler yang andal, pemeriksaan tanda tangan Meta, retry, idempotensi, dan pemulihan saat event hilang.

Diperbarui 10 menit baca

Oleh OmniChannels.ai Editorial Team · Ditinjau oleh BroadNet Messaging Solutions Team

Integrasi

Jawaban singkat

Webhook WhatsApp adalah endpoint HTTPS di server Anda yang menerima event: status pengiriman untuk pesan yang Anda kirim dan pesan yang dikirim pelanggan kepada Anda. Dengan OmniChannels.ai, status tiba sebagai SUBMITTED, SENT, DELIVERED, READ, FAILED, atau REJECTED. Simpan body mentah, jawab 2xx dengan cepat, deduplikasi berdasarkan ID pesan, dan proses secara asinkron. Meta menandatangani webhook-nya sendiri; dokumentasi kami tidak mendefinisikan header tanda tangan, jadi amankan endpoint Anda di tingkat transport dan aplikasi.

Di halaman ini
  1. Apa itu webhook WhatsApp dan mengapa memakainya?
  2. Event dan status apa yang akan saya terima?
  3. Bagaimana menyiapkan endpoint?
  4. Seperti apa payload-nya?
  5. Bagaimana menulis handler yang andal?
  6. Bagaimana mengamankan webhook WhatsApp?
  7. Apa yang terjadi ketika pengiriman gagal?
  8. Bagaimana memulihkan event yang hilang?
  9. Contoh kasus: pipeline notifikasi pengecer
  10. Apa saja kesalahan umum?
  11. Bagaimana OmniChannels.ai membantu

Poin penting

  • Webhook mengirim (push) status dan pesan masuk ke endpoint HTTPS Anda sehingga Anda tidak perlu polling; status WhatsApp dinormalisasi menjadi SUBMITTED, SENT, DELIVERED, READ, FAILED, dan REJECTED.
  • Handler yang andal melakukan tiga hal secara berurutan: simpan event mentah, kembalikan 2xx, lalu proses secara asinkron dan idempoten.
  • Status dapat tiba tidak berurutan atau dua kali, jadi beri peringkat dan jangan biarkan SENT yang terlambat menimpa DELIVERED yang sudah tersimpan.
  • Meta menandatangani webhook yang dikirim ke aplikasi dengan header X-Hub-Signature-256, tetapi spesifikasi API OmniChannels.ai tidak mendefinisikan tanda tangan webhook, jadi gunakan HTTPS, path yang tidak dapat ditebak, dan validasi body.
  • Jika event terlewat, baca status WhatsApp per batch dari endpoint bulk-insights alih-alih mengirim ulang pesan.

Panduan ini ditujukan bagi engineer yang perlu menerima event WhatsApp dengan andal: status pengiriman untuk pesan yang mereka kirim dan pesan masuk dari pelanggan. Panduan ini menjelaskan cara kerja webhook, apa yang harus dibangun di handler, bagaimana keamanan berbeda antara webhook Meta dan webhook kami, dan apa yang dilakukan ketika event hilang.

Apa itu webhook WhatsApp dan mengapa memakainya?

Webhook WhatsApp adalah callback HTTP. Ketika status pesan berubah atau pelanggan menulis kepada Anda, platform mengirim POST dengan body JSON ke endpoint Anda. Anda tidak perlu polling, dan Anda melihat event saat terjadi.

Dua keluarga event yang penting:

  • Event status untuk pesan yang Anda kirim: diantrekan, dikirim, terkirim, dibaca, gagal.
  • Pesan masuk dari pelanggan, yang membuka atau memperpanjang jendela layanan pelanggan 24 jam. Lihat panduan jendela kami.

Panggilan pengiriman hanya memberi tahu bahwa pesan telah diantrekan. Webhook adalah tempat Anda mengetahui apa yang terjadi pada setiap penerima.

Event dan status apa yang akan saya terima?

Di OmniChannels.ai setiap kanal melaporkan status ternormalisasi yang sama, sehingga satu handler dapat melayani WhatsApp, SMS, dan lainnya.

Status Arti Final?
SUBMITTED Diterima platform dan diantrekan Tidak
SENT Diserahkan ke kanal Tidak
DELIVERED Dikonfirmasi di perangkat penerima Biasanya; READ dapat menyusul
READ Dibuka oleh penerima, jika kanal melaporkan pembacaan Ya
FAILED Tidak terkirim; event membawa alasan jika tersedia Ya
REJECTED Ditolak, misalnya konten diblokir atau sender tidak terdaftar Ya

Perlakukan status sebagai progresi yang dapat tiba tidak berurutan, dan harapkan nilai baru dari waktu ke waktu. Jangan gagal pada status yang tidak Anda kenali. Lihat status pengiriman pesan dijelaskan.

Bagaimana menyiapkan endpoint?

Ekspos endpoint HTTPS, berikan URL-nya kepada provider Anda, lalu uji dengan nomor Anda sendiri.

  1. Buat endpoint yang menerima POST dengan body JSON, misalnya https://api.example.com/webhooks/omnichannels.
  2. Kirim URL kepada tim kami atau admin akun Anda untuk dikonfigurasi di akun Anda. Reseller dapat memiliki webhook terpisah per sub-akun.
  3. Kirim pesan uji ke nomor Anda sendiri dan pastikan event tiba.

Selama pengembangan, tunnel seperti ngrok memberi server lokal Anda URL HTTPS publik. Jika Anda juga menghubungkan aplikasi langsung ke Meta, verifikasi endpoint Meta adalah langkah terpisah: request GET yang membawa verify token dan nilai hub.challenge, yang Anda balas dengan 200 beserta challenge-nya, seperti dijelaskan dalam dokumentasi endpoint webhook Meta.

Seperti apa payload-nya?

Bervariasi menurut kanal. Spesifikasi API tidak mendefinisikan satu skema webhook tunggal, jadi catat body mentah terlebih dahulu dan petakan field yang Anda butuhkan dari event nyata di akun Anda. Contoh ini menunjukkan jenis informasi yang dibawa event pengiriman dan hanya bersifat ilustrasi.

{
  "messageId": "2603121407537573731",
  "channel": "SMS",
  "destination": "447700900123",
  "status": "DELIVERED",
  "timestamp": "2026-10-10T09:15:42Z",
  "reason": null
}

Jangan menulis kode berdasarkan nama field ini tanpa memeriksa event nyata. Minta onboarding engineer Anda contoh payload per kanal dan simpan sebagai fixture uji. Untuk dokumentasi yang lebih luas, lihat referensi webhook.

Bagaimana menulis handler yang andal?

Lakukan tiga hal secara berurutan: simpan event mentah, konfirmasi dengan 2xx, lalu proses secara asinkron. Handler di bawah mengikuti pola dalam dokumentasi kami.

import express from "express";

const app = express();

// Tangkap body mentah agar dapat disimpan persis seperti yang diterima.
app.post(
  "/webhooks/omnichannels",
  express.json({ verify: (req, _res, buf) => { req.rawBody = buf.toString("utf8"); } }),
  async (req, res) => {
    try {
      await db.webhookEvents.insert({ receivedAt: new Date(), body: req.rawBody });
    } catch (err) {
      return res.sendStatus(500); // penyimpanan gagal: biarkan event dicoba ulang
    }
    res.sendStatus(200);          // konfirmasi dengan cepat
    queue.publish("status-events", req.body); // kerjakan pekerjaan sebenarnya di tempat lain
  },
);

// Worker: pemrosesan idempoten
async function processEvent(event) {
  const id = event.messageId ?? event.message_id ?? event.id; // petakan per kanal
  const status = event.status;
  const rank = { SUBMITTED: 1, SENT: 2, DELIVERED: 3, READ: 4, FAILED: 4, REJECTED: 4 };

  const current = await db.messages.findOne({ providerId: id });
  if (!current) return; // pesan tidak dikenal: catat dan selidiki
  if ((rank[status] ?? 0) <= (rank[current.status] ?? 0)) return; // duplikat atau usang

  await db.messages.update({ providerId: id }, { status, updatedAt: new Date() });
}
from datetime import datetime, timezone
from flask import Flask, request

app = Flask(__name__)

RANK = {"SUBMITTED": 1, "SENT": 2, "DELIVERED": 3, "READ": 4, "FAILED": 4, "REJECTED": 4}


@app.post("/webhooks/omnichannels")
def omnichannels_webhook():
    raw = request.get_data(as_text=True)
    try:
        db.webhook_events.insert({"received_at": datetime.now(timezone.utc), "body": raw})
    except Exception:
        return "", 500           # penyimpanan gagal: biarkan event dicoba ulang
    queue.publish("status-events", raw)  # proses secara asinkron
    return "", 200               # konfirmasi dengan cepat

Objek db dan queue adalah penyimpanan dan antrean job milik Anda sendiri. Peta rank yang membuat pemrosesan idempoten: event duplikat atau usang bukan kemajuan, sehingga diabaikan.

Aturan untuk handler yang andal

  • Respons dalam beberapa detik. Jangan lakukan pekerjaan berat sebelum merespons.
  • Kembalikan 2xx hanya setelah event tersimpan. Jika penyimpanan gagal, kembalikan 5xx.
  • Deduplikasi berdasarkan ID pesan. Status yang sama dapat tiba lebih dari sekali.
  • Jangan pernah mengirim ulang pesan dari handler. Putuskan retry dalam job terpisah, setelah memeriksa status.
  • Simpan body mentah untuk troubleshooting dan untuk memutar ulang event setelah perbaikan.

Bagaimana mengamankan webhook WhatsApp?

Tergantung siapa yang mengirim ke endpoint Anda. Meta menandatangani webhook yang dikirimnya ke aplikasi yang Anda daftarkan di Meta. Spesifikasi API OmniChannels.ai tidak mendefinisikan header tanda tangan webhook, jadi jangan menunggunya.

Meta ke aplikasi Anda sendiri OmniChannels.ai ke endpoint Anda
Tanda tangan Header X-Hub-Signature-256, menurut dokumentasi Meta Tidak didefinisikan dalam spesifikasi API
Verifikasi HMAC-SHA256 dari payload mentah dengan app secret Anda, dibandingkan dengan header Tidak berlaku
Kontrol Anda Periksa tanda tangan pada setiap POST HTTPS dengan sertifikat valid, path yang tidak dapat ditebak, validasi body yang ketat

Untuk skema Meta, dokumentasi Meta menyatakan untuk membuat hash HMAC-SHA256 dari payload JSON memakai app secret Anda dan membandingkannya dengan nilai setelah sha256= pada header X-Hub-Signature-256. HMAC sendiri didefinisikan dalam RFC 2104. Hitung atas byte mentah, bukan objek yang diserialisasi ulang, dan bandingkan dalam waktu konstan.

Untuk endpoint kami:

  • Gunakan HTTPS saja, dengan sertifikat yang valid.
  • Gunakan path yang panjang dan tidak dapat ditebak, dan ganti jika bocor.
  • Validasi bentuk body dan tolak apa pun yang tidak terduga.
  • Perlakukan event sebagai notifikasi. Sebelum tindakan yang tidak dapat dibatalkan, seperti pengembalian dana atau penguncian fraud, konfirmasikan statusnya dengan panggilan polling.

Apa yang terjadi ketika pengiriman gagal?

Retry bergantung pada pengirim. Dokumentasi Meta menyatakan Meta mengulang pengiriman yang gagal dengan frekuensi yang menurun hingga 7 hari, yang dapat menghasilkan notifikasi duplikat. Itu alasan untuk idempoten meskipun Anda jarang melihat duplikat. Untuk event dari platform kami, konfirmasikan perilaku retry kepada onboarding engineer Anda dan jangan berasumsi sama dengan Meta.

Bagaimanapun, bangunlah untuk kehilangan dan juga duplikasi: endpoint Anda bisa mati saat deploy, dan aturan firewall dapat membuang request secara diam-diam.

Bagaimana memulihkan event yang hilang?

Poll batch-nya, jangan kirim ulang pesannya.

Kebutuhan Panggilan Catatan
Baca status WhatsApp per penerima GET /whatsapp/message/bulk-insights Filter batch menurut status atau destination; berhalaman dengan page dan size
Kirim ulang laporan pengiriman SMS POST /sms/resendDlr Filter menurut startDate, endDate, senderId, dan messageStatus
curl "https://api.broadnet.me/whatsapp/message/bulk-insights?batch_Id=2609091405000000001&page=0&size=100" \
  -H "Authorization: Bearer $BROADNET_TOKEN"

batch_Id adalah ID yang dikembalikan panggilan pengiriman, dan page dimulai dari nol. Jalankan rekonsiliasi malam hari yang membaca batch hari sebelumnya dan mengisi celah apa pun.

Checklist troubleshooting

  1. Apakah URL dikonfigurasi di akun atau sub-akun yang benar?
  2. Apakah endpoint dapat dijangkau melalui HTTPS dengan sertifikat valid?
  3. Apakah endpoint menjawab 2xx dengan cepat, atau timeout?
  4. Apakah aturan firewall atau WAF memblokir request?
  5. Apakah Anda mencatat body mentah sebelum parsing, agar error parser tidak menyembunyikan event?

Contoh kasus: pipeline notifikasi pengecer

"Souq Rafiq" (fiktif), pengecer di UEA, mengirim pembaruan pesanan lewat WhatsApp dan menginginkan status yang akurat di alat pesanannya.

  1. Pesanan dikirim dengan sendbulk, dan batchId disimpan pada pesanan. Lihat kirim pesan WhatsApp via API.
  2. Endpoint webhook menulis setiap event ke tabel, lalu mengembalikan 200.
  3. Worker memberi peringkat status dan memperbarui status pesan pada pesanan.
  4. Event FAILED membuat tugas untuk dukungan beserta alasannya, dan fallback SMS dipertimbangkan sesuai fallback kanal.
  5. Pesan masuk pelanggan diarahkan ke kotak masuk bersama agar agen dapat membalas di dalam jendela.
  6. Job malam hari memanggil bulk-insights untuk batch kemarin dan memperbaiki apa pun yang terlewat.

Apa saja kesalahan umum?

  • Pekerjaan berat sebelum merespons, yang menyebabkan timeout dan pengiriman berulang.
  • Mengonfirmasi sebelum menyimpan, yang menghilangkan event saat penyimpanan gagal.
  • Memercayai urutan. SENT yang terlambat menimpa DELIVERED.
  • Menulis kode berdasarkan payload ilustrasi alih-alih event nyata.
  • Menyerialisasi ulang JSON sebelum memeriksa tanda tangan, yang mengubah byte-nya.
  • Mengirim ulang dari handler, yang dapat berulang tanpa henti.
  • Batasan: panduan ini menjelaskan perilaku yang terdokumentasi di kami. Kebijakan retry dan field payload untuk akun Anda sebaiknya dikonfirmasi saat onboarding.

Bagaimana OmniChannels.ai membantu

OmniChannels.ai mengirim (push) status pengiriman dan pesan masuk untuk WhatsApp, SMS, RCS, dan kanal lain ke webhook Anda dalam satu format ternormalisasi, dengan webhook terpisah per sub-akun bagi reseller. BroadNet adalah Meta Business Solution Provider resmi, sehingga persyaratan webhook Meta sendiri sudah ditangani untuk Anda, dan Anda bekerja dengan API kami. Baca referensi webhook dan dokumentasi WhatsApp API, atau lihat bagaimana event tampil di kotak masuk bersama.

Pertanyaan yang sering diajukan

Apa itu webhook WhatsApp?

Webhook WhatsApp adalah URL di server Anda yang dipanggil platform dengan HTTP POST setiap kali sesuatu terjadi, seperti pesan terkirim, dibaca, atau gagal, atau pelanggan mengirim pesan kepada Anda. Webhook menggantikan polling. Anda mengekspos endpoint HTTPS, membagikannya kepada provider, dan memproses event JSON yang diterimanya.

Bagaimana cara memverifikasi tanda tangan webhook WhatsApp?

Untuk webhook yang dikirim Meta langsung ke aplikasi Anda sendiri, dokumentasi Meta menyatakan untuk menghitung HMAC-SHA256 dari payload mentah dengan app secret Anda dan membandingkannya dengan header X-Hub-Signature-256. Untuk webhook OmniChannels.ai, spesifikasi API tidak mendefinisikan header tanda tangan, jadi andalkan HTTPS, path yang tidak dapat ditebak, dan validasi body.

Apa yang terjadi jika endpoint webhook saya mati?

Dokumentasi Meta menyatakan Meta mengulang pengiriman yang gagal dengan frekuensi yang menurun hingga 7 hari, yang dapat menghasilkan duplikat. Untuk event dari platform kami, konfirmasikan perilaku retry kepada onboarding engineer Anda, dan gunakan endpoint bulk-insights untuk membaca status WhatsApp per penerima untuk sebuah batch. Untuk SMS, endpoint resendDlr mengirim ulang laporan pengiriman.

Bagaimana menangani event webhook duplikat?

Buat pemrosesan idempoten. Cari pesan berdasarkan ID-nya, bandingkan peringkat status yang masuk dengan yang tersimpan, dan abaikan event yang bukan kemajuan. Menerapkan event yang sama dua kali harus berdampak sama seperti sekali. Simpan body mentah setiap event agar Anda dapat memutarnya ulang setelah memperbaiki bug.

Seberapa cepat endpoint saya harus merespons?

Dalam beberapa detik. Simpan event mentah, kembalikan 2xx, dan lakukan pekerjaan sebenarnya di antrean atau worker. Jangan memanggil layanan lain, mengirim pesan, atau menjalankan query berat sebelum merespons. Jika penyimpanan gagal, kembalikan 5xx agar pengirim dapat mencoba lagi, alih-alih mengonfirmasi event yang hilang.

Bisakah saya memakai webhook untuk mengirim balasan otomatis?

Bisa, tetapi tidak dari dalam handler. Konfirmasi event, lalu tentukan balasan dalam job terpisah. Di dalam jendela layanan pelanggan 24 jam Anda dapat mengirim pesan bebas; di luarnya Anda membutuhkan template yang disetujui. Jangan pernah mengirim ulang pesan dari handler webhook itu sendiri, untuk menghindari perulangan dan duplikat.

Sumber

  1. Webhooks overview — WhatsApp Business Platform, Meta for Developers
  2. Create a webhook endpoint — WhatsApp Business Platform, Meta for Developers
  3. RFC 2104: HMAC: Keyed-Hashing for Message Authentication