Dokumentasi API

REST API untuk mengirim pesan, membaca inbox, dan menerima webhook. Semua contoh bisa langsung dicoba dengan API key Anda.

Mulai cepat

  1. Daftar dan verifikasi email.
  2. Menu Device → Tambah device → scan QR dari WhatsApp di HP.
  3. Menu API Keys → Buat key. Simpan, key hanya tampil sekali.
  4. Kirim pesan:
curl -X POST https://www.watsapbro.com/api/v1/messages/text \
  -H "Authorization: Bearer wsb_xxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{"to":"08123456789","message":"Halo dari WatsapBro"}'

Base URL: https://www.watsapbro.com/api/v1. Semua request dan response memakai JSON.

Autentikasi

Kirim API key di header Authorization: Bearer <API_KEY> (atau X-Api-Key: <API_KEY>). Rate limit: 60 request/menit per API key.

Format response selalu:

{ "success": true, "message": "...", "data": { ... } }

Format nomor tujuan (to)

InputKeterangan
08123456789Otomatis jadi 628123456789
628123456789Format internasional tanpa +
120363xxxx@g.usID grup WhatsApp

POST/messages/text

FieldTipeWajibKeterangan
tostringNomor tujuan
messagestringMaks 4096 karakter. Mendukung *tebal* _miring_ ~coret~
device_idintDevice pengirim. Kosong = device terhubung pertama
typing_timeint (ms)Tampilkan "sedang mengetik" sebelum kirim, 0–10000
{
  "to": "08123456789",
  "message": "*Pembayaran diterima*\nInvoice INV-001 sebesar Rp150.000 sudah lunas.",
  "typing_time": 1500
}

Response 200:

{
  "success": true,
  "message": "Pesan terkirim.",
  "quota_remaining": 1874,
  "data": { "log_id": 1024, "message_id": "3EB0B430A2B52B67D0", "device_id": 3, "to": "08123456789" }
}

quota_remaining = sisa kuota bulan ini, null kalau paket unlimited.

POST/messages/image

FieldTipeWajibKeterangan
tostring
image_urlurlURL publik JPG/PNG
captionstringMaks 1024 karakter
device_id, typing_timeSama seperti teks
{ "to": "08123456789", "image_url": "https://cdn.toko.com/promo.jpg", "caption": "Promo minggu ini" }

POST/messages/document

FieldTipeWajibKeterangan
tostring
document_urlurlURL publik file
filenamestringNama file yang tampil di WhatsApp
mimetypestringDefault application/pdf
captionstring
{
  "to": "08123456789",
  "document_url": "https://app.toko.com/invoice/INV-001.pdf",
  "filename": "INV-001.pdf",
  "caption": "Invoice Oktober"
}

POST/numbers/check

Cek apakah nomor terdaftar di WhatsApp sebelum mengirim.

{ "phone": "08123456789", "device_id": 3 }

GET/devices

Daftar device milik Anda beserta status. GET/devices/{id} untuk satu device.

{
  "success": true,
  "data": [
    { "id": 3, "name": "CS Toko", "phone": "628123456789", "status": "connected", "connected_at": "2026-10-17T09:12:00+07:00" }
  ]
}
statusArti
connectedSiap kirim
connectingSedang menyambung ulang, coba lagi beberapa detik
qr_readyPerlu scan QR ulang di dashboard
disconnectedTerputus, sistem akan reconnect otomatis

GET/me

Info akun: paket, tanggal berakhir, limit device, dan pemakaian kuota bulan ini. Kuota dihitung dari pesan yang berhasil terkirim (API, broadcast, dan pesan tes) dan direset tiap tanggal 1.

{
  "success": true,
  "data": {
    "name": "Toko Budi",
    "email": "budi@toko.com",
    "plan": "Starter",
    "plan_expires_at": "2026-11-17T10:00:00+07:00",
    "device_limit": 1,
    "devices": 1,
    "quota_monthly": 2000,
    "quota_used": 126,
    "quota_remaining": 1874
  }
}

Webhook pesan masuk

Isi URL webhook di halaman detail device (menu Device). WatsapBro mengirim POST JSON ke URL tersebut setiap ada pesan masuk ke nomor itu, dan saat status device berubah. Pesan yang Anda kirim sendiri tidak diteruskan.

HeaderIsi
X-Webhook-Eventmessage, device.status, atau test
X-Webhook-DeliveryUUID unik per event. Simpan untuk mencegah proses ganda saat retry.
X-Webhook-Signaturesha256= + HMAC-SHA256 dari raw body memakai signing secret device

Contoh body event message:

{
  "event": "message",
  "delivery_id": "6f1c2a0e-6c1e-4b0a-9a51-2d0f0b8e7c11",
  "device": { "id": 3, "name": "CS Toko", "phone": "628123456789" },
  "data": {
    "id": "3EB0C767D26A8B4E1F",
    "from": "6281298765432@c.us",
    "text": "Halo, pesanan saya sudah dikirim?",
    "timestamp": 1760668200
  },
  "timestamp": "2026-10-17T10:30:00+07:00"
}

Event device.status berisi data.status dan data.previous (nilai sama dengan tabel status device di atas).

Balas HTTP 2xx dalam 10 detik. Kalau URL Anda timeout, membalas 5xx, atau 429, event dikirim ulang hingga 4 kali (10 detik, 1 menit, 5 menit, 15 menit). Balasan 4xx lain dianggap ditolak dan tidak dikirim ulang. Proses berat sebaiknya dimasukkan ke queue di aplikasi Anda.

Verifikasi signature

// Laravel
$raw = $request->getContent();
$expected = 'sha256=' . hash_hmac('sha256', $raw, env('WEBHOOK_SECRET'));
abort_unless(hash_equals($expected, (string) $request->header('X-Webhook-Signature')), 401);

$event = $request->json('event');
if ($event === 'message') {
    $from = $request->json('data.from');   // 6281298765432@c.us
    $text = $request->json('data.text');
}
// Go
func verify(body []byte, sig, secret string) bool {
    mac := hmac.New(sha256.New, []byte(secret))
    mac.Write(body)
    expected := "sha256=" + hex.EncodeToString(mac.Sum(nil))
    return hmac.Equal([]byte(expected), []byte(sig))
}
// Node.js (Express: pakai express.raw({ type: 'application/json' }))
const crypto = require('crypto');
const expected = 'sha256=' + crypto.createHmac('sha256', process.env.WEBHOOK_SECRET).update(req.body).digest('hex');
const ok = crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(req.get('X-Webhook-Signature') || ''));

GET/conversations

Daftar percakapan inbox (urut terbaru). Query opsional: device_id, unread=1, needs_human=1, per_page (maks 100), page.

{
  "success": true,
  "data": [
    { "id": 41, "device_id": 3, "chat_id": "6281298765432@s.whatsapp.net", "name": "Sari", "phone": "6281298765432",
      "is_group": false, "unread": 2, "needs_human": false, "ai": "on",
      "last_message": "Masih ada stok ukuran M?", "last_message_at": "2026-10-18T09:12:00+07:00" }
  ],
  "meta": { "page": 1, "per_page": 30, "total": 128 }
}

GET/conversations/{id}/messages

Pesan dalam percakapan, urut lama ke baru. Query: limit (maks 100), before_id untuk halaman sebelumnya. Field source: contact (dari pelanggan), ai, autoreply, api, broadcast, dashboard, phone.

AI & auto reply

Balasan otomatis diatur dari dashboard, tidak perlu kode: Auto Reply (kata kunci) diperiksa dulu, lalu AI Agent yang dipasang di device. AI memakai API key milik Anda (OpenAI, Anthropic, Gemini, Groq, DeepSeek, OpenRouter, atau endpoint OpenAI-compatible) dan membaca Knowledge Base Anda. Balasan otomatis tercatat di inbox (bisa dibaca lewat /conversations) dan terhitung kuota pesan.

Otomasi berhenti sementara untuk sebuah chat ketika Anda membalas manual dari inbox atau dari HP, dan ketika pelanggan meminta CS manusia (handover).

Kode error

HTTPArtiRetry?
401API key tidak ada / tidak validTidak
402Paket tidak aktif atau device melebihi limit paketTidak, perpanjang paket
403Email akun belum diverifikasiTidak
404Device tidak ditemukan / tidak ada device terhubungTidak
409Device belum terhubungYa, setelah device connected
422Validasi gagal atau nomor tidak validTidak
429Rate limit terlampaui, atau kuota pesan bulan ini habis (lihat message)Rate limit: ya, dengan jeda. Kuota: tidak, upgrade paket
502 / 503Gateway WhatsApp sedang tidak tersediaYa, backoff 1s, 4s, 9s

Contoh kode

Laravel

use Illuminate\Support\Facades\Http;

$res = Http::withToken(env('API_KEY'))
    ->retry(3, 1000, fn ($e) => $e instanceof \Illuminate\Http\Client\ConnectionException
        || in_array(optional($e->response)->status(), [409, 429, 502, 503]))
    ->post('https://www.watsapbro.com/api/v1/messages/text', [
        'to' => '08123456789',
        'message' => 'Kode OTP Anda: 482910',
    ]);

if (! $res->json('success')) {
    logger()->error('WA gagal', $res->json());
}

Go

body, _ := json.Marshal(map[string]any{"to": "08123456789", "message": "Halo dari Go"})
req, _ := http.NewRequest("POST", "https://www.watsapbro.com/api/v1/messages/text", bytes.NewReader(body))
req.Header.Set("Authorization", "Bearer "+os.Getenv("API_KEY"))
req.Header.Set("Content-Type", "application/json")
res, err := http.DefaultClient.Do(req)

Node.js

const res = await fetch("https://www.watsapbro.com/api/v1/messages/text", {
  method: "POST",
  headers: {
    "Authorization": `Bearer ${process.env.API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({ to: "08123456789", message: "Halo dari Node" }),
});
const json = await res.json();

PHP native

$ch = curl_init('https://www.watsapbro.com/api/v1/messages/text');
curl_setopt_array($ch, [
    CURLOPT_POST => true,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('API_KEY'), 'Content-Type: application/json'],
    CURLOPT_POSTFIELDS => json_encode(['to' => '08123456789', 'message' => 'Halo']),
]);
$result = json_decode(curl_exec($ch), true);

Tips supaya nomor tidak diblokir

  • Untuk kirim massal, pakai menu Broadcast (upload CSV, jeda acak otomatis) daripada loop API tanpa jeda.
  • Pakai nomor khusus (sebaiknya WhatsApp Business), bukan nomor pribadi.
  • Kirim ke orang yang memang kenal Anda: pelanggan, member, user aplikasi.
  • Untuk banyak penerima, beri jeda minimal 3–5 detik antar pesan dan pakai typing_time.
  • Hindari pesan identik ke ratusan nomor sekaligus; personalisasi dengan nama.
  • Buka WhatsApp di HP utama minimal sekali tiap 2 minggu.
  • Kirim lewat queue di aplikasi Anda, jangan di request user secara langsung.