Quickstart
Integrasi BITS Pay dalam 3 langkah: buat charge, tampilkan QRIS, konfirmasi pembayaran.
0. Dapatkan API key
Daftar di dashboard (panduan lengkap: Panduan Dashboard),
buat aplikasi di workspace kamu. API key (sk_...) hanya
ditampilkan sekali saat create/rotate — simpan di tempat aman. Semua
request /v1/* pakai header:
Authorization: Bearer sk_xxxxxxxxxxxxxxxx
Base URL: https://api.pay.bits.co.id. Response sukses selalu
{ "success": true, "data": ... }, error
{ "success": false, "error": { "code", "message" } }.
1. Buat charge (QRIS dinamis)
1POST /v1/charges
Kirim order_id (unik per aplikasi, idempoten) dan
amount (minimal Rp 100). API mengembalikan QRIS dinamis dengan
kode unik: amount_due = amount + fee + unique_code (fee
= biaya admin opsional, dikirim di request — default 0).
const res = await fetch('https://api.pay.bits.co.id/v1/charges', {
method: 'POST',
headers: {
Authorization: 'Bearer sk_xxxxxxxxxxxxxxxx',
'Content-Type': 'application/json',
},
body: JSON.stringify({
order_id: 'ORD-001',
amount: 150000,
description: 'Pembayaran invoice #001',
}),
});
const { success, data, error } = await res.json();
if (!success) throw new Error(`${error.code}: ${error.message}`);
console.log(data.amount_due); // 150001
console.log(data.qr_image); // data:image/png;base64,...
console.log(data.expired_at); // batas bayar, ISO-8601 UTC: "2026-09-02T12:45:00Z"
Tampilkan data.qr_image sebagai <img src> ke pelanggan.
Pelanggan bayar nominal persis amount_due.
2. Cek status pembayaran
2GET /v1/payments/:id
Poll status transaksi, atau terima update real-time via
webhook. Untuk rekonsiliasi massal pakai
GET /v1/payments (filter order_id/status,
paginated).
const res = await fetch(`https://api.pay.bits.co.id/v1/payments/${id}`, {
headers: { Authorization: 'Bearer sk_xxxxxxxxxxxxxxxx' },
});
const { data } = await res.json();
// data.status: 'pending' | 'success' | 'failed' | 'expired' | 'pending_review'
3. Konfirmasi pembayaran
3POST /v1/payments/:id/confirm
Kirim multipart/form-data berisi amount (harus sama persis
dengan amount_due) dan opsional proof_image (JPG/PNG, maks 5MB)
untuk auto-confirm via OCR.
const form = new FormData();
form.append('amount', '150001'); // = amount_due
form.append('proof_image', fileInput.files[0]); // opsional
const res = await fetch(`https://api.pay.bits.co.id/v1/payments/${id}/confirm`, {
method: 'POST',
headers: { Authorization: 'Bearer sk_xxxxxxxxxxxxxxxx' },
body: form,
});
const { data } = await res.json();
// Request valid SELALU HTTP 200 — cek data.status:
// 'success' → auto_confirm (lunas)
// 'pending_review' → OCR confidence rendah, direview admin
// 'failed' → nominal tidak cocok / bukti tidak disertakan
Error handling
| Code | HTTP | Arti |
|---|---|---|
validation_error |
400 | Body tidak valid (cek error.details) |
unauthorized |
401 | API key salah / aplikasi nonaktif |
not_found |
404 | Transaksi tidak ditemukan |
duplicate_order |
409 | order_id sudah dipakai transaksi aktif |
duplicate_hash |
409 | Bukti bayar sudah dipakai |
expired |
400 | Transaksi kedaluwarsa |
rate_limited |
429 | Rate limit / kuota tercapai |
X-RateLimit-Limit, X-RateLimit-Remaining, dan
X-RateLimit-Reset.