Dokumentasi API
Kirim pesan WhatsApp dari aplikasi Anda lewat satu endpoint REST.
Mulai cepat
SENDAL WAGU adalah gateway WhatsApp tidak resmi. Hubungkan nomor Anda sekali, lalu kirim pesan dari aplikasi apa pun lewat satu endpoint REST.
- Pilih paket. Buka menu Pilih Paket di panel customer.
- Hubungkan WhatsApp. Di Sesi WhatsApp, klik Buat sesi baru, lalu Lihat QR dan scan lewat WhatsApp › Perangkat tertaut. Tunggu status
connected. - Buat API key. Buka API Akses lalu klik Buat API key.
- Kirim pesan. Salin contoh kode di bagian Kirim pesan.
Autentikasi
Semua request ke API wajib membawa API key milik akun Anda. Kirim apa adanya lewat header Authorization, tanpa awalan Bearer. Header X-Api-Key dan Token, atau field api_key di body, juga diterima.
https://send.alkhaf.com/api/v1
https://send.alkhaf.com/api/v1/messages
Endpoint kirim pesan adalah Base URL ditambah /messages.
| Header | Nilai | |
|---|---|---|
Authorization | <API_KEY> | wajib |
Content-Type | application/json | wajib |
Accept | application/json | disarankan |
Kirim pesan teks
https://send.alkhaf.com/api/v1/messages
Parameter body
| Nama | Tipe | Keterangan |
|---|---|---|
session opsional |
string | Nama sesi dari menu Sesi WhatsApp, misalnya budi_628123456789 (format username_nomor). Status sesi harus connected. Jika dikosongkan, dipakai sesi default (menu API Akses) atau satu-satunya sesi yang terhubung. |
to wajib |
string | Nomor tujuan dalam format internasional tanpa tanda +, misalnya 628123456789. Awalan 0 otomatis diubah menjadi 62. |
message wajib |
string | Isi pesan teks. |
Contoh request
curl -X POST "https://send.alkhaf.com/api/v1/messages" \
-H "Authorization: <API_KEY_ANDA>" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-d '{
"session": "nama_sesi_anda",
"to": "628123456789",
"message": "Halo dari SENDAL WAGU!"
}'
<?php
$ch = curl_init('https://send.alkhaf.com/api/v1/messages');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: <API_KEY_ANDA>',
'Accept: application/json',
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode([
'session' => 'nama_sesi_anda',
'to' => '628123456789',
'message' => 'Halo dari SENDAL WAGU!',
]),
]);
$response = curl_exec($ch);
curl_close($ch);
echo $response;
const res = await fetch('https://send.alkhaf.com/api/v1/messages', {
method: 'POST',
headers: {
Authorization: '<API_KEY_ANDA>',
Accept: 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
session: 'nama_sesi_anda',
to: '628123456789',
message: 'Halo dari SENDAL WAGU!',
}),
});
console.log(res.status, await res.json());
import requests
res = requests.post(
"https://send.alkhaf.com/api/v1/messages",
headers={"Authorization": "<API_KEY_ANDA>", "Accept": "application/json"},
json={
"session": "nama_sesi_anda",
"to": "628123456789",
"message": "Halo dari SENDAL WAGU!",
},
)
print(res.status_code, res.json())
Respons
Jika berhasil, API membalas 200 dan kuota pesan berkurang satu. Isi data adalah respons mentah dari mesin WhatsApp dan bisa berbeda antarversi. Daftar respons gagal ada di Kode respons.
{
"message": "Pesan terkirim.",
"data": { "id": "..." }
}
POST /messages.
Integrasi aplikasi lain
Untuk aplikasi pihak ketiga (sistem kost, kasir, ERP, dan sejenisnya) yang punya kolom pengaturan gateway, isi seperti berikut.
| Kolom di aplikasi | Isi |
|---|---|
| API URL / Base URL | https://send.alkhaf.com/api/v1/messages. Jika aplikasi menambahkan path sendiri di belakang URL, cukup https://send.alkhaf.com/api/v1. |
| API Key / Token | API key dari menu API Akses. |
| Device token / secret | Kosongkan. |
| Nomor / sesi pengirim | Nomor WhatsApp sesi Anda atau nama sesi. Jika kosong atau tidak cocok, dipakai sesi default (menu API Akses) atau satu-satunya sesi yang terhubung. |
Nama field alternatif yang diterima: tujuan to / phone / target / number; isi pesan message / text / body; pengirim session / sender / from / device. Path alternatif: /send dan /send-message di bawah /api atau /api/v1.
Webhook
Terima pesan masuk dan perubahan status secara real-time di aplikasi Anda. Daftarkan URL di menu Webhook (grup Developer), pilih event, lalu klik Kirim tes. Untuk sesi lama, klik sekali Daftarkan ulang webhook di Sesi WhatsApp. Riwayat pengiriman ada di menu Log Webhook.
| Event | Kapan dikirim |
|---|---|
message | Ada pesan masuk dari pelanggan (bukan grup). |
message.ack | Status pesan berubah: terkirim, diterima, atau dibaca. |
session.status | Status sesi berubah, misalnya WORKING atau STOPPED. |
ping | Tes manual dari tombol Kirim tes. |
Request yang Anda terima
Server kami mengirim POST berformat JSON dengan header berikut.
| Header | Isi |
|---|---|
X-Sendal-Event | Nama event. |
X-Sendal-Delivery | ID unik pengiriman (sama dengan id di body). Pakai untuk menghindari proses ganda. |
X-Sendal-Timestamp | Waktu kirim (detik, Unix). |
X-Sendal-Signature | sha256= + HMAC-SHA256 dari timestamp + "." + body mentah dengan secret webhook Anda. |
{
"id": "0b2f6f5e-7d0e-4d0a-9b3a-6f1d5c1f2a10",
"event": "message",
"session": "toko1",
"timestamp": 1790000000,
"data": {
"message_id": "false_628123456789@c.us_3EB0...",
"chat_id": "628123456789@c.us",
"phone": "628123456789",
"from_me": false,
"text": "Halo, apakah barang ini masih ada?",
"has_media": false,
"timestamp": 1790000000
},
"payload": { }
}
Field payload berisi data mentah dari mesin WhatsApp dan bisa berbeda antarversi; andalkan field data.
Verifikasi tanda tangan
Hitung ulang tanda tangan dari body mentah (sebelum di-decode) dan bandingkan dengan aman. Tolak bila selisih waktu lebih dari 5 menit.
$body = file_get_contents('php://input');
$ts = $_SERVER['HTTP_X_SENDAL_TIMESTAMP'] ?? '';
$sig = $_SERVER['HTTP_X_SENDAL_SIGNATURE'] ?? '';
$expected = 'sha256=' . hash_hmac('sha256', $ts . '.' . $body, 'whsec_SECRET_ANDA');
if (!hash_equals($expected, $sig) || abs(time() - (int) $ts) > 300) {
http_response_code(401);
exit;
}
$event = json_decode($body, true);
// proses $event['event'] dan $event['data'] ...
http_response_code(200);
const crypto = require('crypto');
app.post('/webhook', express.raw({ type: 'application/json' }), (req, res) => {
const ts = req.get('X-Sendal-Timestamp') || '';
const expected = 'sha256=' + crypto
.createHmac('sha256', process.env.WEBHOOK_SECRET)
.update(ts + '.' + req.body.toString())
.digest('hex');
const sig = req.get('X-Sendal-Signature') || '';
const ok = sig.length === expected.length &&
crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(expected));
if (!ok || Math.abs(Date.now() / 1000 - Number(ts)) > 300) return res.sendStatus(401);
const event = JSON.parse(req.body.toString());
// proses event.event dan event.data ...
res.sendStatus(200);
});
2xx maksimal 8 detik. Jika gagal, kami mencoba lagi sampai 3 kali. Webhook dinonaktifkan otomatis setelah 20 kegagalan beruntun; aktifkan lagi dari menu Webhook. Hanya alamat publik yang diizinkan (server lokal/privat ditolak) dan redirect tidak diikuti. Riwayat 14 hari terakhir ada di menu Log Webhook.
Status sesi
Status tampil di menu Sesi WhatsApp dan diperbarui otomatis. Pesan hanya bisa dikirim saat status connected.
| Status | Arti |
|---|---|
| starting | Sesi sedang disiapkan di server. |
| scan_qr | Menunggu QR discan dari aplikasi WhatsApp. |
| connected | Terhubung. Siap dipakai mengirim pesan. |
| disconnected | Terputus. Buat ulang sesi lalu scan QR kembali. |
| stopped | Sesi dihentikan. |
session.status di Webhook kalau aplikasi Anda perlu tahu otomatis.
Kode respons
Setiap respons berupa JSON dengan kunci message. Gunakan kode status HTTP untuk menentukan langkah berikutnya.
| Kode | Penyebab | Contoh body |
|---|---|---|
| 200 | Pesan berhasil dikirim. | {"message":"Pesan terkirim."} |
| 401 | Unauthorized API key salah, kosong, atau sudah diganti. |
{"message":"API key tidak valid."} |
| 402 | Payment Required Tidak ada paket aktif, atau kuota pesan habis. |
{"message":"Kuota pesan Anda sudah habis."} |
| 404 | Not Found Nama sesi tidak ditemukan di akun Anda. |
{"message":"Sesi WhatsApp tidak ditemukan."} |
| 409 | Conflict Sesi ada, tetapi belum berstatus connected. |
{"message":"Sesi WhatsApp belum terhubung."} |
| 422 | Unprocessable Parameter wajib kosong atau formatnya salah, atau session tidak dikirim padahal ada beberapa sesi terhubung dan belum ada sesi default. |
{"message":"The to field is required.","errors":{"to":["The to field is required."]}} |
| 502 | Bad Gateway Server WhatsApp menolak atau tidak merespons. |
{"message":"Gagal mengirim pesan.","detail":{}} |
Kuota dan paket
- Kuota berkurang satu untuk setiap pesan yang berhasil (respons
200). Request yang gagal tidak mengurangi kuota. - Paket unlimited tidak memiliki batas jumlah pesan.
- Jumlah sesi WhatsApp dibatasi sesuai paket.
- Pesan dari paket gratis (harga Rp0) otomatis diberi watermark di akhir pesan. Paket berbayar tidak memakai watermark.
- Setelah masa aktif berakhir atau kuota habis, API membalas
402. Paket baru bisa dipilih setelah paket lama berakhir.
FAQ
Kenapa saya mendapat status 409?
Sesi belum terhubung. Buka Sesi WhatsApp (status diperbarui otomatis tiap 10 detik) dan scan ulang QR jika perlu.
Apakah layanan ini resmi dari WhatsApp?
Bukan. Layanan berjalan di atas WhatsApp Web tidak resmi, sehingga nomor berisiko dibatasi oleh WhatsApp. Kirim hanya ke kontak yang mengharapkan pesan dan hindari pesan massal yang tidak diminta.
Kenapa pesan ke nomor baru gagal (error 463 atau 475)?
WhatsApp membatasi jumlah kontak baru yang boleh dihubungi sebuah akun. Sesi tetap terhubung. Balas percakapan yang sudah ada, kurangi pesan ke kontak baru, lalu coba lagi nanti.
Kenapa pesan saya ada tambahan teks di akhir?
Itu watermark paket gratis. Upgrade ke paket berbayar agar pesan terkirim tanpa tambahan teks.
Bagaimana format nomor tujuan?
Gunakan kode negara tanpa +, misalnya 628123456789. Nomor berawalan 0 akan diubah otomatis ke 62.
API key saya bocor, apa yang harus dilakukan?
Buka API Akses lalu klik Buat ulang API key. Key lama langsung tidak bisa dipakai.