Lewati ke konten utama

Webhook Security & Verification

Wagy menggunakan webhook untuk mengirimkan data pesan masuk (incoming messages) dari WhatsApp secara real-time ke server Anda. Untuk menjamin keamanan dan integritas data, kami mengimplementasikan mekanisme verifikasi dua arah.

1. Verifikasi Kepemilikan URL (Handshake)

Saat Anda mendaftarkan atau memperbarui URL Webhook di User Panel, Wagy akan mengirimkan request GET ke URL tersebut untuk memastikan bahwa Anda adalah pemilik sah dari endpoint tersebut.

  • Method: GET
  • Query Parameter: challenge (string acak)

Persyaratan Respons

Server Anda harus merespons request tersebut dengan:

  1. Status code 200 OK.
  2. Body respons harus berisi hanya nilai dari parameter challenge tersebut (plain text).

Contoh (Node.js/Express):

app.get('/webhook', (req, res) => {
const challenge = req.query.challenge;
if (challenge) {
return res.status(200).send(challenge);
}
res.status(400).send('No challenge provided');
});

2. Signature Verification (HMAC-SHA256)

Setelah URL terverifikasi, Wagy akan menyertakan header X-Wagy-Signature pada setiap request POST (data pesan). Header ini berisi signature HMAC-SHA256 yang dibuat menggunakan Webhook Secret unik milik perangkat Anda.

Webhook Secret

Kunci rahasia (Webhook Secret) hanya akan dihasilkan dan muncul di User Panel setelah URL berhasil diverifikasi. Jangan berikan kunci ini kepada siapapun.

Cara Verifikasi Signature

Untuk memverifikasi bahwa request benar-benar berasal dari Wagy:

  1. Ambil raw JSON body dari request.
  2. Hitung HMAC-SHA256 dari body tersebut menggunakan Webhook Secret Anda.
  3. Bandingkan hasilnya dengan nilai header X-Wagy-Signature.
const crypto = require('crypto');

app.post('/webhook', (req, res) => {
const signature = req.headers['x-wagy-signature'];
const secret = 'YOUR_WEBHOOK_SECRET_FROM_PANEL';

if (!signature) {
return res.status(401).send('Missing signature');
}

// Hitung HMAC-SHA256 dari raw body
// Catatan: Pastikan Anda mengambil raw body sebelum di-parse oleh body-parser
const hmac = crypto.createHmac('sha256', secret);
const digest = hmac.update(JSON.stringify(req.body)).digest('hex');

// Bandingkan signature
if (signature !== digest) {
return res.status(401).send('Invalid signature');
}

// Signature valid, proses data
console.log('Verified message:', req.body);
res.sendStatus(200);
});

3. Payload Webhook

Setiap request POST menggunakan struktur Event-Based Payload agar konsisten untuk berbagai jenis kejadian.

Struktur Utama

FieldTipeDeskripsi
eventstringJenis kejadian (misal: message.received).
sourcestringSumber kejadian (whatsapp, api, manual, system).
dataobjectObjek pembungkus data utama.
data.idnumberID unik log webhook (audit ID).
data.device_idstringID perangkat Wagy.
data.contentobjectData spesifik event (lihat contoh di bawah).

Contoh Payload Berdasarkan Event

Wagy menggunakan struktur Event-Based Payload. Objek data.content akan memiliki struktur yang berbeda tergantung pada tipe eventnya.

1. Pesan Masuk (Inbound)

  • Event: message.received, message.edited
  • Source: whatsapp
{
"event": "message.received",
"source": "whatsapp",
"data": {
"id": 1001,
"device_id": "OFFICE-01",
"owner_jid": "62812345678@s.whatsapp.net",
"content": {
"pn_jid": "628999888777@s.whatsapp.net",
"lid_jid": "203998263034091@lid",
"content": "Halo, apakah stok ready?",
"message_id": "ABC123XYZ",
"timestamp": "2026-05-13T07:05:00Z",
"is_edit": false
},
"created_at": "2026-05-13T07:05:00Z"
}
}

2. Pesan Keluar Manual (Handset)

  • Event: message.manual_sent, message.manual_edited
  • Source: manual
{
"event": "message.manual_sent",
"source": "manual",
"data": {
"id": 1002,
"device_id": "OFFICE-01",
"owner_jid": "62812345678@s.whatsapp.net",
"content": {
"pn_jid": "628999888777@s.whatsapp.net",
"lid_jid": "203998263034091@lid",
"content": "Ready kak!",
"message_id": "XYZ789ABC",
"timestamp": "2026-05-13T07:10:00Z",
"is_edit": false
},
"created_at": "2026-05-13T07:10:00Z"
}
}

3. Status Pengiriman API

  • Event: message.sent, message.delivered, message.read, message.failed, message.cancelled
  • Source: api
{
"event": "message.delivered",
"source": "api",
"data": {
"id": 1003,
"device_id": "OFFICE-01",
"owner_jid": "62812345678@s.whatsapp.net",
"content": {
"message_id": "MSG_ID_WA_123",
"queue_id": 12345,
"pn_jid": "628999888777@s.whatsapp.net",
"lid_jid": "203998263034091@lid",
"content": "Terima kasih!",
"status": "DELIVERED"
},
"created_at": "2026-05-13T07:15:00Z"
}
}

4. Status Perangkat

  • Event: device.status_update
  • Source: system
{
"event": "device.status_update",
"source": "system",
"data": {
"id": 1004,
"device_id": "OFFICE-01",
"owner_jid": "62812345678@s.whatsapp.net",
"content": {
"device_id": "OFFICE-01",
"status": "CONNECTED",
"label": "Admin Sales"
},
"created_at": "2026-05-13T07:20:00Z"
}
}

Keamanan Webhook

Wagy mengirimkan header X-Wagy-Signature yang berisi HMAC-SHA256 dari body request. Gunakan Webhook Secret Anda untuk memverifikasi keaslian data.

Verifikasi itu Penting!

Selalu verifikasi signature untuk memastikan data benar-benar berasal dari server Wagy dan bukan serangan spoofing.