WA Gateway API
WhatsApp Gateway berbasis Baileys (multi-device, tanpa WhatsApp Business API). Satu server bisa menjalankan banyak nomor (device) sekaligus, masing-masing punya device key sendiri.
Base URL: https://151.245.136.93:8443
1. Mulai cepat
- Buka Admin Panel, login dengan password admin.
- Klik + Device Baru → beri nama (mis.
cs-bot). Simpan device key yang tampil. - Pairing — dua cara:
- QR scan: buka Kelola → tab Koneksi / QR → scan QR dari WhatsApp (Perangkat Tertaut → Tautkan perangkat). QR refresh otomatis tiap 4 detik.
- Pairing code: masukkan nomor (628xxx) → dapat kode 8 digit → WhatsApp → Perangkat Tertaut → Tautkan dengan nomor telepon.
- Setelah status
connected, device siap dipakai lewat REST API.
Kirim pesan pertama
curl -X POST https://151.245.136.93:8443/api/v1/send \
-H "X-Device-Key: wag_xxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{"to":"628123456789","type":"text","message":"Halo dari WA Gateway"}'
2. Autentikasi
Semua endpoint /api/v1/* butuh device key. Tiga cara:
X-Device-Key: wag_xxxxxxxxxxxxxxxx ← disarankan Authorization: Bearer wag_xxxxxxxxxxxxxxxx ?device_key=wag_xxxxxxxxxxxxxxxx ← untuk testing cepat
- Key tidak valid →
401 - Device belum
connected→409(pesannya menyebut status device-nya) - Key bisa di-rotate dari admin panel → key lama langsung mati
3. Device & pairing (bisa lewat API)
Supaya aplikasimu bisa onboarding nomor sendiri tanpa buka panel.
Ambil QR untuk di-scan (poll tiap ±4 detik sampai connected).
{
"success": true,
"status": "qr", // connected | qr | pairing | connecting | reconnecting | disconnected | stopped | logged_out | error
"connected": false,
"qr": "data:image/png;base64,iVBOR…", // tinggal
"qr_raw": "2@abc123…", // string QR mentah kalau mau generate sendiri
"qr_expires_in_ms": 12400,
"pairing_code": null,
"phone": null
}
Alternatif QR — kode 8 digit untuk nomor tertentu (hanya sebelum session terdaftar).
curl -X POST .../api/v1/device/pairing-code -H "X-Device-Key: wag_xxx" \
-d '{"phone":"628123456789"}'
{"success":true,"pairing_code":"V7H7NRKZ","phone":"628123456789"}
Jalankan / sambungkan ulang session. Body opsional {"phone":"628xxx"} untuk langsung masuk mode pairing code.
Putuskan session. Body {"logout":true} = logout dari WhatsApp (perlu pairing ulang).
Hapus kredensial session (paksa pairing ulang). Wajib kirim {"confirm":true}.
Info device + profil WhatsApp yang login.
Cek cepat: {"status":"connected","connected":true}
Cek nomor terdaftar WhatsApp. Body {"phone":"08123456789"}.
Status mengetik/online. {"to":"628xxx","type":"composing"}
Tandai sudah dibaca (centang biru). {"chat_id":"628xxx"}
4. Kirim pesan — satu endpoint
Semua tipe pesan lewat endpoint ini. Field type menentukan jenisnya — default text.
Parameter
| Field | Wajib | Keterangan |
|---|---|---|
| to | ya | Nomor (628xxx / 0812xxx) atau ID grup |
| type | tidak | text (default) | image | video | audio | document | sticker | location | contact | reaction |
| message | per tipe | Isi teks; untuk media jadi caption. Alias: text, caption |
| url | per tipe | URL media (bisa juga image/video/audio/document/sticker/media) |
| file | tidak | Upload langsung (multipart) — kalau ada, type terdeteksi otomatis dari MIME |
| filename / mimetype | tidak | Untuk document & audio |
| ptt | tidak | true = voice note (type audio) |
| latitude / longitude | ya (location) | Koordinat, plus name & address opsional |
| contacts | ya (contact) | [{"name":"Budi","phone":"628111"}] atau name+phone |
| message_id / emoji | ya (reaction) | Reaksi ke pesan tertentu |
| reply_to | tidak | wa_msg_id yang mau di-quote |
| is_group | tidak | true kalau to diisi ID grup tanpa suffix @g.us |
Contoh per tipe
# TEXT (default)
{"to":"628123456789","message":"Halo 👋"}
# IMAGE
{"to":"628123456789","type":"image","url":"https://contoh.com/foto.jpg","message":"caption"}
# VIDEO
{"to":"628123456789","type":"video","url":"https://contoh.com/video.mp4","message":"caption"}
# AUDIO (message → caption tidak dipakai; ptt:true = voice note)
{"to":"628123456789","type":"audio","url":"https://contoh.com/a.mp3","ptt":false}
# DOCUMENT
{"to":"628123456789","type":"document","url":"https://contoh.com/invoice.pdf",
"filename":"invoice.pdf","mimetype":"application/pdf","message":"Invoice"}
# STICKER
{"to":"628123456789","type":"sticker","url":"https://contoh.com/stiker.webp"}
# LOCATION
{"to":"628123456789","type":"location","latitude":-6.2088,"longitude":106.8456,
"name":"Kantor","address":"Jl. Contoh No. 1"}
# CONTACT
{"to":"628123456789","type":"contact","contacts":[{"name":"Budi","phone":"628111222333"}]}
# REACTION (emoji "" = hapus reaksi)
{"to":"628123456789","type":"reaction","message_id":"3EB0XXXX","emoji":"👍"}
Upload file sendiri (multipart)
curl -X POST https://151.245.136.93:8443/api/v1/send \ -H "X-Device-Key: wag_xxxxxxxx" \ -F "to=628123456789" \ -F "type=image" \ -F "message=caption dari HP" \ -F "file=@/path/foto.jpg"
Kalau type tidak dikirim, tipenya ditebak dari MIME file (image/* → image, video/* → video, audio/* → audio, lainnya → document). Maks. ukuran: 64 MB.
/send/text, /send/image, /send/video, /send/audio,
/send/document, /send/sticker, /send/location, /send/contact,
/send/media, /send/reaction) masih jalan untuk kompatibilitas, tapi tidak lagi
didokumentasikan di sini. Pakai /api/v1/send.
5. Bulk / broadcast
{
"delay_ms": 1500,
"messages": [
{"to":"628111111111","message":"Promo hari ini"},
{"to":"628222222222","message":"Promo hari ini"},
{"to":"[email protected]","message":"Promo di grup","is_group":true}
]
}
Response berisi ringkasan success/failed + detail per nomor. Jeda default 1,5 detik (anti-spam). Maks 500 nomor per request.
6. Grup
| Endpoint | Fungsi |
|---|---|
| GET /api/v1/groups | Daftar grup yang diikuti device |
| GET /api/v1/groups/:jid | Metadata grup + daftar peserta |
| POST /api/v1/groups | Buat grup: {"subject":"Nama","participants":["628111"]} |
| POST /api/v1/groups/:jid/participants | {"participants":["628111"],"action":"add"} — add | remove | promote | demote |
| POST /api/v1/groups/:jid/leave | Keluar dari grup |
7. Riwayat pesan
{
"success": true, "total": 128,
"messages": [{
"id": 128, "device_id": "cs-bot-1a2b3c", "direction": "in",
"chat_id": "[email protected]", "chat_name": "Budi",
"is_group": false, "type": "conversation", "body": "Halo min",
"media_url": null, "wa_msg_id": "3EB0…", "status": "received",
"created_at": 1792238000000, "created_at_iso": "2026-10-17T11:53:20.000Z"
}]
}
GET /api/v1/messages/:id untuk satu pesan. Media masuk otomatis diunduh dan tersedia di media_url.
POST /api/v1/message/delete — hapus pesan untuk semua orang: {"to":"628xxx","message_id":"3EB0…","from_me":true}
8. Webhook (pesan masuk)
Set URL per device di admin panel (tab Webhook). Gateway POST JSON tiap ada pesan masuk / keluar (pilih event-nya).
POST https://app-anda.com/webhook
Content-Type: application/json
X-Webhook-Event: message
X-Device-Id: cs-bot-1a2b3c
{
"event": "message",
"device_id": "cs-bot-1a2b3c",
"device_name": "cs-bot",
"sent_at": "2026-10-17T11:53:20.000Z",
"data": {
"message_id": 128, "direction": "in",
"chat_id": "[email protected]", "chat_name": "Budi",
"sender_id": "[email protected]", "sender_name": "Budi",
"is_group": false, "type": "conversation", "body": "Halo min",
"media_path": null, "wa_msg_id": "3EB0…", "status": "received"
}
}
Event: message (masuk), message.sent (keluar), test. Response 2xx = sukses; kegagalan tercatat di tab Webhook Log.
Test cepat: POST /api/v1/webhook/test body {"url":"https://app-anda.com/webhook"}
9. Admin Panel & API-nya
Panel: /admin/. Fitur: statistik, kelola device (QR, pairing code, start/stop/restart/logout/reset, rotate key, hapus), kirim uji (pilih tipe), log pesan, log webhook.
| Endpoint admin | Fungsi |
|---|---|
| POST /admin/api/login | {"password":"…"} → token admin (12 jam) |
| GET /admin/api/overview | Statistik + daftar device |
| POST /admin/api/devices | Buat device: {"name":"cs-bot","phone":"628xxx","webhook_url":"…"} |
| GET /admin/api/devices/:id/qr | QR + pairing code + status |
| POST /admin/api/devices/:id/pairing-code | Minta kode 8 digit |
| POST …/start | stop | restart | logout | reset-session | Kontrol session |
| PATCH /admin/api/devices/:id | Ubah nama/webhook/aktif/autostart |
| POST /admin/api/devices/:id/rotate-key | Ganti device key |
| DELETE /admin/api/devices/:id | Hapus device + session + riwayat |
| GET /admin/api/events | Server-Sent Events (update realtime panel) |
10. Operasional
Aplikasi jalan sebagai service systemd (wa-gateway.service) di /www/wwwroot/wa-gateway, port 8787 (internal), dan diakses publik lewat nginx 8443 (HTTPS).
sudo systemctl status wa-gateway sudo systemctl restart wa-gateway tail -f /www/wwwroot/wa-gateway/logs/server.out
Troubleshooting
| Masalah | Solusi |
|---|---|
Status logged_out | Device dikeluarkan dari HP → Reset session di panel, pairing ulang |
| QR tidak muncul | Klik Jalankan / Restart; pastikan server bisa akses internet ke WhatsApp |
409 belum terhubung | Pairing dulu sampai status connected |
| Nomor saling tendang | Satu nomor tidak boleh dipakai di dua device/HP web sekaligus |
| HTTPS error | Port publik hanya 8443; cek sertifikat nginx (/www/server/panel/vhost/nginx/wa-gateway-https.conf) |
Backup: sessions/ (kredensial WhatsApp) dan data/wa-gateway.db (device, key, riwayat). Spesifikasi mesin: /openapi.json.