Errors & status codes
Semua error memakai envelope yang sama dengan respons sukses, jadi penanganannya seragam: cek status_code, baca message, lalu tentukan retry atau tidak.
Bentuk error
json
{
"status_code": 403,
"message": "Forbidden resource"
}HTTP / status_code
| Kode | Arti | Retry? |
|---|---|---|
200 / 201 | Sukses | — |
400 | Validasi gagal / state tidak valid (mis. order bukan Created) | Tidak (perbaiki request) |
401 | JWT tidak valid/kedaluwarsa | Tidak (login ulang) |
403 | API key salah/kosong, atau bukan pemilik resource | Tidak |
404 | Order/link tidak ditemukan | Tidak |
429 | Rate limit terlampaui | Ya, dengan backoff |
500 | Kesalahan internal | Ya, dengan backoff |
503 | Layanan sementara tidak tersedia | Ya, dengan backoff |
Error umum & solusi
| Pesan | Penyebab | Solusi |
|---|---|---|
Forbidden resource | Header api-key hilang/salah | Kirim API key merchant yang benar (lihat Authentication) |
Order not found | order_no/merchant_id tidak cocok | Pastikan order dibuat di lingkungan (testnet/mainnet) yang sama |
Order is not in Created status | Order sudah dibayar/kedaluwarsa | Buat order baru untuk pembayaran berikutnya |
Payment link is no longer available | Kuota habis / link nonaktif | Buat payment link baru |
Insufficient balance | Saldo settlement kurang untuk withdrawal | Kurangi nominal atau tunggu settlement berikutnya |
Too many login attempts | Lockout sementara (5 percobaan / 15 menit) | Tunggu durasi lockout |
No deposit address available for this network | Channel/jaringan belum aktif untuk merchant | Aktifkan channel di dashboard atau hubungi tim Hashpay |
Strategi retry
Backoff eksponensial dengan jitter
async function withRetry(fn, attempts = 4) {
for (let i = 0; i < attempts; i++) {
try {
return await fn();
} catch (err) {
const retriable = [429, 500, 503].includes(err.status);
if (!retriable || i === attempts - 1) throw err;
const delay = Math.min(2 ** i * 500, 8000) + Math.random() * 250;
await new Promise((r) => setTimeout(r, delay));
}
}
}