Webhook
Webhook adalah cara Kareeb mengabari sistem Anda bila sesuatu terjadi: status kirim pesan, pesan masuk, kampanye selesai, dan lainnya. Kareeb mengirim POST berisi JSON ke URL Anda, ditandatangani dengan secret milik langganan itu.
Berlangganan
Langganan dibuat oleh admin organisasi Anda di Kareeb, bukan dengan token API.
- Admin membuka menu Webhook (grup Sistem) dan menambahkan URL endpoint Anda. URL harus diawali
https://atauhttp://dan bisa dijangkau dari internet; alamatlocalhostdan jaringan internal ditolak. - Admin memilih peristiwa yang ingin diterima, minimal satu.
- Kareeb menampilkan secret webhook satu kali. Simpan untuk memverifikasi tanda tangan.
- Tombol Kirim uji mengirim peristiwa
pingke endpoint itu saat itu juga, apa pun peristiwa yang dipilih. Isinya{"message": "Halo dari Kareeb."}. Jawab2xxuntukpingjuga, walaupun sistem Anda tidak memprosesnya.
Amplop
Setiap kiriman memakai bentuk yang sama:
POST https://sistem-anda.example/webhook/kareeb
Content-Type: application/json
User-Agent: Kareeb-Webhook/1
X-Kareeb-Event: message.status
X-Kareeb-Delivery: 5521
X-Kareeb-Signature: 3f1a...
{
"id": "0b6f2c1e-6d0a-4f7b-9a51-3c2d8e4f1a20",
"timestamp": "2026-11-04T03:15:02+00:00",
"event": "message.status",
"data": {
"message_id": 9137,
"conversation_id": 412,
"wa_message_id": "wamid.HBgM...",
"status": "failed",
"occurred_at": "2026-11-04T03:15:00+00:00",
"failure_reason": "Message undeliverable"
}
}
| Bagian | Arti |
|---|---|
id | Id kejadian. Sama untuk satu kejadian di semua endpoint dan di semua percobaan ulang. Pakai untuk membuang duplikat. |
timestamp | Waktu kejadian diantrekan. |
event | Nama peristiwa. |
data | Isi peristiwa, lihat tabel di bawah. |
X-Kareeb-Event | Nama peristiwa, sama dengan event. |
X-Kareeb-Delivery | Id kiriman ke endpoint Anda. Sama pada setiap percobaan ulang kiriman itu, tetapi berbeda untuk setiap endpoint dan berbeda dengan id di badan. |
X-Kareeb-Signature | Tanda tangan HMAC-SHA256 dari badan mentah, hex huruf kecil, tanpa awalan sha256=. |
Sembilan peristiwa
| Peristiwa | Kapan dikirim | Isi data |
|---|---|---|
message.status | Meta melaporkan sent, delivered, read, atau failed untuk pesan yang dikirim Kareeb, dari API, broadcast, maupun kotak masuk. | message_id, conversation_id, wa_message_id, status, occurred_at, dan failure_reason (hanya pada failed, judul dari Meta dalam bahasa Inggris). Tanpa teks dan tanpa nomor telepon. |
message.inbound | Pelanggan mengirim pesan. | Kolom yang sama dengan GET /api/export/messages (id, conversation_id, contact_id, direction, wa_message_id, msg_type, body, media_id, media_mime, created_at), ditambah wa_id, contact_name, dan channel. Peristiwa ini memuat isi pesan dan nomor pelanggan. |
campaign.finished | Antrean kampanye habis. | Baris kampanye yang dibaca ulang setelah selesai, termasuk id, name, template_name, source, state, started_at, finished_at. |
conversation.status_changed | Percakapan ditutup, dibuka lagi, atau dikembalikan ke antrean. | conversation_id, from_status, status. |
lead.created | Kartu baru muncul di Pipeline. | Baris lead: id, contact_id, conversation_id, stage, value_idr, note, created_at, updated_at. |
lead.stage_changed | Kartu dipindah ke tahap lain. | Baris lead ditambah from_stage. |
pemantauan.status_changed | Operator mengubah status sebutan di halaman Pemantauan. | pemantauan_id, referensi, sumber, external_id, from_status, status, at. |
call.finished | Panggilan Agen AI suara di aplikasi Anda berakhir. | call_id, channel, conversation_id, contact_id, session_ref, duration_s, outcome (completed, handoff, atau failed), handoff, ended_at. Tanpa transkrip. |
agen_ai.sambungan | Sambungan ke model Agen AI berganti antara menjawab dan gagal. | status (ok atau gagal), kode, host, sejak. |
Peristiwa perubahan status hanya dikirim bila statusnya benar berubah. Contoh lengkap setiap peristiwa ada di Referensi API, bagian Webhooks.
Jawaban, waktu, dan percobaan ulang
- Jawab
2xxsecepatnya, lalu proses isinya setelah itu. Jawaban selain2xx, atau tanpa jawaban dalam 10 detik, dianggap gagal. - Kiriman tidak berangkat seketika. Kareeb mengantrekan setiap kejadian, lalu penjadwal mengirimnya pada putaran berikutnya, sekitar tiap 5 menit.
- Kiriman yang gagal dicoba lagi pada putaran berikutnya, paling banyak 5 kali (sekitar 20 menit).
- Setelah 10 kegagalan berturut-turut, langganan dinonaktifkan otomatis dan admin mendapat pemberitahuan di Kareeb. Setelah endpoint Anda pulih, admin perlu mengaktifkannya lagi di menu Webhook. Satu kiriman yang berhasil mengembalikan hitungan kegagalan ke nol.
Membuang duplikat
Pengiriman bersifat at least once: kejadian yang sama bisa datang lebih dari sekali, misalnya bila endpoint Anda memproses kiriman tetapi jawabannya tidak sampai ke Kareeb.
- Simpan
iddari badan, dan abaikan kiriman yangid-nya sudah pernah Anda proses. - Untuk
message.status, Meta sendiri kadang mengulang status yang sama. Kareeb mengantrekannya lagi denganidbaru, jadi buang juga duplikat berdasarkan pasangan (wa_message_id,status). - Urutan kedatangan tidak dijamin. Status
readbisa datang sebelumdelivered.
Memeriksa tanda tangan
Hitung HMAC-SHA256 dari byte badan persis seperti diterima dengan secret webhook, lalu bandingkan dengan header X-Kareeb-Signature memakai perbandingan waktu tetap. Jangan mengurai JSON lalu menyusunnya ulang sebelum menghitung, karena hasilnya bisa berbeda satu byte dan tanda tangannya tidak cocok.
- Python
- Node.js
- PHP
import hashlib
import hmac
def sah(raw_body: bytes, header: str, secret: str) -> bool:
expected = hmac.new(secret.encode(), raw_body, hashlib.sha256).hexdigest()
return hmac.compare_digest(header, expected)
const crypto = require("crypto");
function sah(rawBody, header, secret) {
const expected = crypto.createHmac("sha256", secret).update(rawBody).digest("hex");
return expected.length === header.length &&
crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(header));
}
// Express: pakai express.raw({ type: "application/json" }) agar req.body tetap byte mentah.
$raw = file_get_contents("php://input");
$expected = hash_hmac("sha256", $raw, $secret);
$sah = hash_equals($expected, $_SERVER["HTTP_X_KAREEB_SIGNATURE"] ?? "");
Tolak kiriman yang tanda tangannya tidak cocok, dan jangan simpan isinya.