Skip to main content

Webhook Media dan Story

Webhook media dan story mengirimkan notifikasi otomatis ke server setiap kali file media diterima atau kontak mengunggah story baru. Data file disertakan langsung dalam payload dalam format base64.

Prasyarat

  • Webhook sudah dikonfigurasi dan opsi Webhook Media sudah diaktifkan di dashboard.

Panduan konfigurasi di Integrasi Notifikasi Webhook.

Event: media

Event media dikirim ke server setiap kali file media masuk ke nomor WhatsApp yang terhubung bisa berupa gambar, video, audio, dokumen, atau stiker. File dikirim dalam payload sebagai string base64 yang perlu didecode sebelum digunakan.

{
"type": "media", // Tipe webhook yang dikirim
"results": { // Kumpulan object dari event message
"key": { // Informasi pengirim
"remoteJid": "[email protected]", // Nomer pengirim
"fromMe": false, // Dikirim ke nomer sendiri ?
"id": "xxxxx" // ID pesan
},
"messageTimestamp": 1694502465, // Waktu pesan
"pushName": "xxxxx", // Nama Whatsapp
"broadcast": false, // Apakah pesan broadcast ?
"message": {
... // Object disini adalah raw pesan whatsapp, bisa berubah sewaktu2
},
"verifiedBizName": "WHAPI", // Object untuk nama whatsapp bisnis
"t": 1694502465, // Waktu pesan
"id": "xxxxx", // ID pesan
"from": "[email protected]", // Nomer pengirim
"fromMe": false, // Dikirim dari nomer sendiri ?
"chatId": "[email protected]", // Nomer pengirim
"isGroupMsg": false, // Apakah pesan dari grup ?
"isStories": false, // Apakah pesan story ?
"sender": "[email protected]", // Nomer pengirim
"pushname": "WHAPI", // Object untuk nama whatsapp bisnis
"timestamp": 1691639955, // Waktu pesan
"isEphemeralMessage": false,
"viewOnce": false, // Pesan dilihat 1x
"type": "imageMessage", // imageMessage | videoMessage | stickerMessage | audioMessage | documentMessage | documentWithCaptionMessage
"isMedia": true, // Apakah file media ?
"mimetype": "image/jpeg", // Mime type dari file, akan sesuai dengan file yang dikirim
"quotedMsg": { // Jika pesan berupa quote, akan ada data disini
... // Data object disini adalah raw dari whatsapp.
},
"mentionedJidList": [], // Mention nama akan muncul disini
"body": "Isi Pesan", // Object akan tampil jika file memiliki caption
"apiKey": "xxxxx" // Alamat API Key dari device
},
"base64_file": "..." // Isi dari base64 file
}

Nilai yang mungkin untuk field type:

NilaiKeterangan
imageMessageFile gambar
videoMessageFile video
audioMessageFile audio atau voice note
stickerMessageStiker
documentMessageDokumen
documentWithCaptionMessageDokumen dengan caption

Field base64_file berisi konten file dalam format base64. Decode terlebih dahulu sebelum digunakan sebagai file.

Event: stories

Event stories dikirim ke server setiap kali kontak yang tersimpan di nomor WhatsApp yang terhubung mengunggah story baru. Payload berisi data story beserta file media story dalam format base64.

{
"type": "stories",
"results": {
"key": {
"remoteJid": "status@broadcast",
"fromMe": false,
"id": "1D25F51B1367D75D029ED7203E629D60",
"participant": "[email protected]"
},
"messageTimestamp": 1694503269,
"pushName": "xxxxx", // Nama Whatsapp
"broadcast": true,
"message": {
"..."
},
"verifiedBizName": "WHAPI", // Object untuk nama whatsapp bisnis
"t": 1694503269,
"id": "xxxxx", // ID pesan
"from": "[email protected]", // Nomer pengirim
"fromMe": false, // Dikirim dari nomer sendiri ?
"chatId": "[email protected]", // Nomer pengirim
"isGroupMsg": false, // Apakah pesan dari grup ?
"isStories": true, // Apakah pesan story ?
"sender": "[email protected]",
"pushname": "WHAPI", // Object untuk nama whatsapp bisnis
"timestamp": 1691639955, // Waktu pesan
"isEphemeralMessage": false,
"viewOnce": false, // Pesan dilihat 1x
"type": "imageMessage",
"isMedia": true, // Apakah file media ?
"mimetype": "image/jpeg", // Mime type dari file, akan sesuai dengan file yang dikirim
"quotedMsg": {

} // Jika pesan berupa quote, akan ada data disini
"mentionedJidList": [], // Mention nama akan muncul disini
"body": "Isi Pesan", // Object akan tampil jika file memiliki caption
"apiKey": "xxxxx" // Alamat API Key dari device
},
"base64_file": "..." // Isi dari base64 file
}

Payload stories memiliki struktur yang sama dengan payload media. Perbedaannya ada di field isStories: true dan remoteJid: "status@broadcast".

Cara Decode Base64

Data file dalam field base64_file perlu didecode sebelum bisa digunakan.

header('Content-Type: application/json');

$raw_input = file_get_contents('php://input');
$data = json_decode($raw_input, true);

if (!$data) {
http_response_code(400);
echo json_encode(["status" => "error", "message" => "Invalid JSON payload"]);
exit;
}

// 1. Validasi: type harus 'stories' ATAU 'media'
$allowed_types = ['stories', 'media'];
$type = $data['type'] ?? '';

if (!in_array($type, $allowed_types)) {
http_response_code(400);
echo json_encode([
"status" => "error",
"message" => "Tipe data tidak valid. Hanya menerima tipe 'stories' atau 'media'."
]);
exit;
}

// 2. Proses decode file
if (isset($data['base64_file'])) {
$base64_string = $data['base64_file'];

if (preg_match('/^data:image\/(\w+);base64,/', $base64_string, $matches)) {
$base64_string = substr($base64_string, strpos($base64_string, ',') + 1);
}

$decoded_file = base64_decode($base64_string);
$file_name = 'hasil_download.jpg';
file_put_contents($file_name, $decoded_file);

echo json_encode(["status" => "success", "message" => "File dari webhook " . $type . " berhasil disimpan"]);
} else {
http_response_code(400);
echo json_encode(["status" => "error", "message" => "Data base64_file tidak ditemukan"]);
}