Referensi API
Kode error
Daftar kode HTTP, alasan penolakan, dan cara menanganinya.
BGWA memakai kode status HTTP standar. Semua respons error berupa JSON dengan field error (penjelasan yang bisa ditampilkan ke pengguna).
Penolakan dari penjaga pengiriman juga memuat reason (kode mesin) dan, bila relevan, retry_after (detik).
Contoh penolakan 429
{
"error": "Batas pengiriman ke penerima baru jam ini sudah tercapai. Coba lagi nanti.",
"reason": "hourly_new_limit",
"retry_after": 1320
}
Header Retry-After ikut dikirim bersama retry_after agar klien HTTP standar dapat menunggu otomatis.
Kode status HTTP
| Status | Arti | Perlu dicoba ulang? |
|---|---|---|
200 | Berhasil. Untuk POST /messages berarti pesan diterima ke antrean. | – |
401 | API key tidak valid, tidak dikirim, atau sudah dicabut. | Tidak. Perbaiki key. |
403 | Langganan pemilik device tidak aktif atau akun disuspend. | Tidak, sampai paket diperpanjang. |
404 | Pesan tidak ditemukan (ID salah atau milik device lain). | Tidak. |
409 | Device belum terhubung ke WhatsApp, atau webhook belum diatur. | Setelah masalah diperbaiki. |
422 | Permintaan tidak valid atau ditolak aturan: nomor salah, duplikat, isi seragam, terlalu banyak tautan, penerima berhenti, nomor tidak terdaftar. | Tidak, ubah dulu permintaannya. |
429 | Terlalu banyak request, kuota habis, batas penerima baru tercapai, atau antrean penuh. | Ya, setelah Retry-After. |
502 | Worker WhatsApp tidak merespons. | Ya, dengan jeda singkat. |
503 | Pengiriman sementara dijeda (device dijeda, kontak baru dijeda, daftar nomor kotor, sistem sibuk). | Ya, setelah Retry-After. |
Kode reason penolakan
Muncul pada POST /messages ketika penjaga menolak pesan. Pesan yang ditolak tidak memakai kuota.
| Reason | HTTP | Arti dan solusi |
|---|---|---|
not_on_whatsapp | 422 | Nomor tujuan tidak terdaftar di WhatsApp. Hapus dari daftar Anda. |
duplicate_message | 422 | Pesan sama ke nomor sama dalam 10 menit. Tunggu atau ubah isi. |
content_repetitive | 422 | Isi terlalu seragam untuk banyak penerima baru. Variasikan dengan spintax atau {nama}. |
too_many_links | 422 | Lebih dari 2 tautan dalam satu pesan. Kurangi tautan. |
recipient_opted_out | 422 | Penerima membalas STOP/berhenti. Jangan dikirimi lagi. |
otp_invalid | 422 | OTP lebih dari 200 karakter atau berisi tautan. |
otp_rate_limited | 429 | Batas OTP per jam tercapai. Tunggu sesuai retry_after. |
daily_new_limit | 429 | Batas penerima baru harian tercapai. Coba lagi besok. |
hourly_new_limit | 429 | Batas penerima baru per jam tercapai. |
daily_existing_limit | 429 | Batas pesan harian ke kontak lama tercapai. |
queue_full | 429 | Antrean device sudah penuh. Tunggu beberapa menit. |
schedule_unavailable | 429 | Pesan tidak bisa dijadwalkan saat ini. Coba lagi nanti. |
new_contacts_paused | 503 | WhatsApp membatasi akun memulai chat baru, jadi pengiriman ke kontak baru dijeda. Kontak lama tetap bisa. |
invalid_numbers_high | 503 | Terlalu banyak nomor tidak terdaftar belakangan ini. Bersihkan daftar nomor. |
device_paused | 503 | Device dijeda sementara karena gangguan. Coba lagi beberapa saat. |
queue_busy | 503 | Sistem sedang sibuk. Coba lagi sebentar. |
Kesalahan validasi
Bila field wajib hilang atau salah format, API menjawab 422 dengan struktur validasi:
422 Unprocessable Content
{
"message": "The to field is required.",
"errors": {
"to": ["The to field is required."]
}
}
Nomor yang tidak bisa dinormalkan dijawab dengan {"error": "Nomor tujuan tidak valid. Gunakan format 08... atau 62..."}.
Menangani error dengan benar
Contoh penanganan (Node.js)
async function kirim(to, text) {
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 }),
});
const data = await res.json();
if (res.ok) return data; // antre: simpan data.id
if (res.status === 429 || res.status === 503) {
const wait = Number(res.headers.get('Retry-After') || 60);
throw Object.assign(new Error(data.error), { retryAfter: wait }); // jadwalkan ulang
}
if (res.status === 401 || res.status === 403 || res.status === 409) {
throw new Error('Perlu tindakan: ' + data.error); // jangan diulang otomatis
}
throw new Error(data.error || 'Gagal (' + res.status + ')'); // 422: perbaiki permintaan
}