Mulai
Contoh kode
Salin-tempel contoh integrasi: cURL, PHP, Laravel, Node.js, dan Python.
Contoh siap pakai untuk skenario yang paling umum. Ganti YOUR_API_KEY dengan API key device Anda, dan simpan key di environment variable.
Fungsi kirim pesan
Bungkus pemanggilan API dalam satu fungsi yang menangani error dengan benar.
PHP
function bgwaKirim(string $to, string $text, array $extra = []): array
{
$ch = curl_init('https://bgwa.web.id/api/v1/messages');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 15,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('BGWA_API_KEY'),
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode(['to' => $to, 'text' => $text] + $extra),
]);
$body = json_decode(curl_exec($ch), true) ?: [];
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
return ['http' => $status] + $body;
}
$r = bgwaKirim('081234567890', 'Halo dari PHP!');
if ($r['http'] === 200) {
echo 'Antre, id = ' . $r['id'];
} else {
echo 'Gagal: ' . ($r['error'] ?? $r['http']);
}
Laravel
use Illuminate\Support\Facades\Http;
// config/services.php => 'bgwa' => ['key' => env('BGWA_API_KEY')]
$response = Http::withToken(config('services.bgwa.key'))
->acceptJson()
->timeout(15)
->post('https://bgwa.web.id/api/v1/messages', [
'to' => $order->customer_phone,
'text' => "{Halo|Hai} {$order->customer_name}, pesanan #{$order->number} sudah kami proses.",
]);
if ($response->successful()) {
$order->update(['wa_outbox_id' => $response->json('id')]);
} elseif (in_array($response->status(), [429, 503], true)) {
// coba lagi nanti sesuai Retry-After
dispatch(new KirimUlangWa($order))->delay((int) $response->header('Retry-After', 60));
} else {
report(new RuntimeException($response->json('error', 'BGWA error ' . $response->status())));
}
Node.js
async function bgwaKirim(to, text, extra = {}) {
const res = await fetch('https://bgwa.web.id/api/v1/messages', {
method: 'POST',
headers: {
Authorization: 'Bearer ' + process.env.BGWA_API_KEY,
'Content-Type': 'application/json',
},
body: JSON.stringify({ to, text, ...extra }),
signal: AbortSignal.timeout(15000),
});
return { http: res.status, ...(await res.json()) };
}
const r = await bgwaKirim('081234567890', 'Halo dari Node.js!');
console.log(r.http === 200 ? 'Antre, id = ' + r.id : 'Gagal: ' + r.error);
Python
import os
import requests
def bgwa_kirim(to, text, **extra):
r = requests.post(
"https://bgwa.web.id/api/v1/messages",
headers={"Authorization": "Bearer " + os.environ["BGWA_API_KEY"]},
json={"to": to, "text": text, **extra},
timeout=15,
)
return r.status_code, r.json()
status, data = bgwa_kirim("081234567890", "Halo dari Python!")
print("Antre, id =", data["id"]) if status == 200 else print("Gagal:", data.get("error"))
Notifikasi tagihan dengan variasi pesan
Kirim tagihan ke banyak pelanggan tanpa isi yang identik. BGWA mengatur jeda, jadi cukup kirim satu per satu.
PHP
$template = '{Halo|Hai|Selamat pagi} {nama}, tagihan {bulan} sebesar Rp {jumlah} jatuh tempo {tanggal}. {Terima kasih|Terima kasih atas kepercayaan Anda}.';
foreach ($pelanggan as $p) {
$r = bgwaKirim($p['hp'], $template, [
'vars' => [
'nama' => $p['nama'],
'bulan' => 'November',
'jumlah' => number_format($p['tagihan'], 0, ',', '.'),
'tanggal' => $p['jatuh_tempo'],
],
]);
if ($r['http'] === 429 || $r['http'] === 503) {
break; // batas tercapai: lanjutkan nanti
}
// simpan $r['id'] untuk mencocokkan webhook
}
Kirim OTP
PHP
$kode = random_int(100000, 999999);
// simpan hash $kode + masa berlaku di database Anda, lalu:
$r = bgwaKirim($hp, "Kode verifikasi Anda: {$kode}. Berlaku 5 menit. Jangan bagikan ke siapa pun.", [
'type' => 'otp',
]);
Node.js
import crypto from 'node:crypto';
const kode = crypto.randomInt(100000, 1000000);
// simpan hash kode + masa berlaku, lalu:
await bgwaKirim(hp, `Kode verifikasi Anda: ${kode}. Berlaku 5 menit. Jangan bagikan ke siapa pun.`, {
type: 'otp',
});
Kirim gambar (struk, poster)
cURL
curl -X POST https://bgwa.web.id/api/v1/messages \
-H "Authorization: Bearer YOUR_API_KEY" \
-F "to=081234567890" \
-F "text=Terima kasih, ini struk Anda." \
-F "image=@/path/ke/struk.png"
Laravel
$response = Http::withToken(config('services.bgwa.key'))
->attach('image', file_get_contents($path), 'struk.png')
->post('https://bgwa.web.id/api/v1/messages', [
'to' => $hp,
'text' => 'Terima kasih, ini struk Anda.',
]);
// pastikan gambar benar-benar ikut
if ($response->successful() && ! $response->json('image')) {
// keterangan terlalu panjang: terkirim sebagai teks saja
}
Penerima webhook lengkap
Contoh endpoint yang memverifikasi tanda tangan, membuang duplikat, lalu memperbarui status pesan di database Anda.
Laravel
// routes/web.php (kecualikan dari CSRF)
Route::post('/hooks/bgwa', function (Request $request) {
$ts = $request->header('X-BGWA-Timestamp', '');
$body = $request->getContent(); // body mentah
$sig = 'sha256=' . hash_hmac('sha256', $ts . '.' . $body, config('services.bgwa.webhook_secret'));
abort_unless(hash_equals($sig, (string) $request->header('X-BGWA-Signature')), 401);
abort_if(abs(time() - (int) $ts) > 300, 400);
$delivery = $request->header('X-BGWA-Delivery');
if (Cache::add('bgwa:' . $delivery, 1, now()->addDay()) === false) {
return response()->noContent(); // duplikat, sudah diproses
}
$event = $request->json()->all();
Pesan::where('bgwa_id', $event['id'] ?? null)->update([
'status' => $event['status'] ?? $event['event'],
'alasan' => $event['reason'] ?? null,
]);
return response()->noContent();
});
Node.js (Express)
const seen = new Set(); // produksi: pakai Redis/DB dengan masa kedaluwarsa
app.post('/hooks/bgwa', express.raw({ type: 'application/json' }), async (req, res) => {
const ts = req.get('X-BGWA-Timestamp') || '';
const raw = req.body.toString('utf8');
const expected = 'sha256=' + crypto.createHmac('sha256', process.env.BGWA_WEBHOOK_SECRET)
.update(ts + '.' + raw).digest('hex');
const got = req.get('X-BGWA-Signature') || '';
if (got.length !== expected.length || !crypto.timingSafeEqual(Buffer.from(got), Buffer.from(expected))) {
return res.sendStatus(401);
}
const delivery = req.get('X-BGWA-Delivery');
if (seen.has(delivery)) return res.sendStatus(200);
seen.add(delivery);
const event = JSON.parse(raw);
await db.pesan.update({ bgwaId: event.id }, { status: event.status, alasan: event.reason });
res.sendStatus(200);
});
Cek koneksi sebelum kirim massal
cURL
STATUS=$(curl -s https://bgwa.web.id/api/v1/device -H "Authorization: Bearer YOUR_API_KEY" | grep -o '"status":"[a-z]*"')
[ "$STATUS" = '"status":"open"' ] && echo "Device siap" || echo "Device belum terhubung"