Untuk Developer

Dokumentasi API

Integrasikan QRIS, Virtual Account, dan E-Wallet ke website atau aplikasi kamu. Halaman bayar white-label, nominal sinkron dengan aplikasi pembayaran, dan status real-time.

Unduh SDK PHP Lihat Endpoint

0. Base URL

https://www.ruangnotif.com/api/v1

Semua endpoint di bawah memakai prefix ini. Request & response memakai JSON (Content-Type: application/json).

Production vs Sandbox

Saat mengintegrasikan payment gateway di website/aplikasi kamu, sediakan pilihan mode (Sandbox / Production). Mode menentukan apakah transaksi bersifat uji coba atau live.

Aturan integrasi (wajib dipatuhi)

  1. Di sisi website developer, sediakan select/toggle: Mode Sandbox dan Mode Production.
  2. Jika mode Production aktif → panggil API dengan "mode":"production" (atau tanpa field mode). Pelanggan diarahkan ke payment_url halaman bayar production (transaksi asli, memengaruhi saldo merchant setelah berhasil).
  3. Jika mode Sandbox aktif → panggil API dengan "mode":"sandbox". Pelanggan diarahkan ke payment_url halaman bayar sandbox (transaksi tidak asli: tidak mengkredit saldo akun user/merchant).
  4. Saat mengajukan merchant (status menunggu review admin), developer wajib memakai mode sandbox untuk uji coba transaksi. Admin mereview hasil uji sandbox sebelum menyetujui merchant ke production.
  5. Mode production hanya tersedia setelah merchant berstatus aktif (disetujui admin).
SandboxProduction
Field API "mode": "sandbox" "mode": "production" (default)
order_id Otomatis berprefix SANDBOX- jika belum ada Sesuai request kamu
Halaman bayar payment_url — alur QR/VA/timer sama, label uji coba payment_url — transaksi live
Saldo merchant Tidak berubah Bertambah setelah status berhasil
Merchant menunggu review Boleh (wajib untuk uji review) Ditolak (403) sampai merchant aktif
Merchant aktif Boleh (tetap untuk regression test) Boleh
Kredensial provider Sandbox (dikonfigurasi admin) Production

Contoh di backend developer: jika user memilih Sandbox di panel kamu, kirim body dengan "mode":"sandbox"; jika Production, kirim "mode":"production" atau omit field tersebut. Jangan memakai mode production untuk pelanggan sungguhan sebelum merchant disetujui dan uji sandbox selesai.

Alternatif uji tanpa API: menu Sandbox di dashboard akun RuangNotif (setelah login) — hasilnya sama-sama tidak memengaruhi saldo.

1. Autentikasi

Setiap request wajib menyertakan 2 header. Secret Key jangan pernah dipakai di sisi browser — selalu panggil API dari backend kamu.

X-Api-Key

API Key merchant (production atau sandbox — lihat tabel di bawah).

X-Signature

HMAC-SHA256 dari body JSON mentah (raw string) yang sama persis dikirim di request, ditandatangani dengan Secret Key pasangan dari API Key tersebut.

API Key & Secret Key — Production vs Merchant Sandbox

Merchant ProductionMerchant Sandbox
Cara buat Menu Merchant → Tambah Merchant (butuh KYC & approval admin) Menu Sandbox → Buat Merchant Sandbox (tanpa KYC, langsung aktif)
API Key pk_live_... pk_test_...
Secret Key sk_live_... sk_test_...
Header X-Api-Key Isi pk_live_... Isi pk_test_...
Signature HMAC-SHA256 body + sk_live_... HMAC-SHA256 body + sk_test_...
Mode API production (default) atau sandbox saat uji Selalu dipaksa sandbox (tidak bisa production)
Saldo Transaksi production mengkredit saldo Tidak pernah mengkredit saldo
Kode merchant MCH-XXXXXX SBX-XXXXXX
Penting: Jangan menukar pasangan key. Signature untuk pk_test_... harus memakai sk_test_... dari merchant sandbox yang sama. Secret Key hanya ditampilkan sekali saat pembuatan merchant — simpan di environment backend (.env), jangan di-commit ke git.

Contoh signature (PHP) — production

$apiKey    = 'pk_live_xxxxxxxx';
$secretKey = 'sk_live_xxxxxxxx';

$body = json_encode([
    'order_id' => 'INV-001',
    'amount'   => 50000,
    'method'   => 'qris',
    'mode'     => 'production',
], JSON_UNESCAPED_SLASHES);

$signature = hash_hmac('sha256', $body, $secretKey);
// Header: X-Api-Key: {apiKey}
// Header: X-Signature: {signature}

Contoh signature (PHP) — merchant sandbox

$apiKey    = 'pk_test_xxxxxxxx';  // dari Sandbox → Merchant Sandbox
$secretKey = 'sk_test_xxxxxxxx';

$body = json_encode([
    'order_id' => 'TEST-001',
    'amount'   => 10000,
    'method'   => 'qris',
    'mode'     => 'sandbox',
], JSON_UNESCAPED_SLASHES);

$signature = hash_hmac('sha256', $body, $secretKey);

Pastikan string yang di-hash identik dengan body yang dikirim (urutan field & encoding). SDK resmi sudah menangani ini otomatis.

POST /api/v1/transaction

Membuat transaksi pembayaran baru. Respons berisi payment_url — arahkan pelanggan ke URL tersebut untuk bayar (QRIS / VA / e-wallet, white-label, countdown timer otomatis).

Endpoint ini selalu production (transaksi asli). Untuk uji coba tanpa memengaruhi saldo — terutama saat pengajuan merchant masih di-review — gunakan mode Sandbox (lihat Production vs Sandbox).

Biaya channel selalu ditanggung pelanggan.

  • amount di request = nominal yang ingin kamu terima (request merchant).
  • Sistem menambahkan margin/biaya channel ke tagihan pelanggan.
  • amount di respons = total yang harus dibayar pelanggan (sama dengan halaman checkout & aplikasi bank/e-wallet).
  • Saldo yang dikreditkan ke merchant = nominal request (tanpa potongan margin platform).

Body Request

FieldTipeWajibKeterangan
order_idstringYaID unik dari sistem kamu, maks. 100 karakter. Dipakai sebagai kunci status & webhook.
amountintegerYaNominal request merchant (Rupiah). Minimal sesuai batas channel (lihat bagian 4). Bukan total akhir pelanggan.
methodstringYaKode channel atau kode custom white-label. Contoh: qris, bri_va. Lihat bagian 4.
descriptionstringTidakKeterangan transaksi (tampil di riwayat).
customer_namestringTidakNama pelanggan.
customer_emailstringTidakEmail pelanggan.
customer_phonestringTidakNomor HP pelanggan.
return_urlstringTidakURL website kamu untuk diarahkan balik pelanggan setelah pembayaran berhasil (query order_id & status=success otomatis ditambahkan). Kalau tidak diisi, pelanggan tetap lihat halaman sukses bawaan sistem.
modestringTidakproduction (default) atau sandbox. Lihat bagian Production vs Sandbox.

Contoh cURL

curl -X POST https://www.ruangnotif.com/api/v1/transaction \
  -H "Content-Type: application/json" \
  -H "X-Api-Key: API_KEY_KAMU" \
  -H "X-Signature: HASIL_HMAC_SHA256" \
  -d '{"order_id":"INV-001","amount":50000,"method":"qris","description":"Pembelian A","customer_name":"Budi","mode":"production"}'

Uji coba: ganti "mode":"sandbox". Response order_id akan berprefix SANDBOX-.

Contoh Respons (201 Created)

{
  "success": true,
  "data": {
    "order_id": "INV-001",
    "amount": 51250,
    "method": "qris",
    "status": "pending",
    "mode": "production",
    "payment_url": "https://www.ruangnotif.com/bayar/MCH-XXXX/checkout/INV-001",
    "expired_at": "2026-08-22T15:30:00+07:00"
  }
}

Field Respons

FieldKeterangan
order_idSama dengan request.
amountTotal tagihan pelanggan (request + biaya channel/margin, selaras dengan provider & m-banking).
methodKode channel tampilan (kode custom white-label jika kamu set).
statusAwalnya selalu pending.
modeproduction atau sandbox — sesuai request.
payment_urlURL halaman bayar. Redirect pelanggan ke sini. Berisi QR/VA, instruksi, dan timer countdown hingga expired_at. Production = transaksi asli; sandbox = uji coba tanpa kredit saldo.
expired_atBatas waktu bayar (ISO 8601, timezone aplikasi). Minimal ±60 menit dari saat dibuat. Setelah lewat, status menjadi expired.

Angka amount 51250 di contoh hanya ilustrasi setelah margin. Nilai aktual mengikuti pengaturan channel di dashboard. Kredit ke saldo merchant tetap = amount request (50000).

GET /api/v1/transaction/status/{order_id}

Cek status transaksi. Di-scope per merchant — kamu hanya bisa melihat transaksi milik merchant sendiri. Endpoint ini juga dipakai untuk memverifikasi webhook.

Header

Wajib X-Api-Key. Untuk GET tanpa body, signature mengikuti aturan middleware (biasanya body kosong / string kosong — SDK menangani otomatis).

Contoh Respons (200)

{
  "success": true,
  "data": {
    "order_id": "INV-001",
    "amount": 51250,
    "method": "qris",
    "status": "berhasil",
    "mode": "production",
    "paid_amount": 50000,
    "created_at": "2026-08-22T14:30:00+07:00",
    "expired_at": "2026-08-22T15:30:00+07:00"
  }
}
FieldKeterangan
amountTotal tagihan pelanggan (sama seperti create).
paid_amountNominal yang dikreditkan ke saldo merchant. Hanya terisi jika status = berhasil; selain itu null.
statuspending · berhasil · expired · gagal
created_atWaktu transaksi dibuat (ISO 8601).
expired_atBatas bayar. Jika lewat dan masih pending → otomatis expired.

3. Alur pembayaran & halaman checkout

  1. Backend kamu memanggil POST /api/v1/transaction.
  2. Simpan order_id, lalu redirect / tampilkan payment_url ke pelanggan.
  3. Di halaman bayar: QR/VA, instruksi, dan timer countdown hingga expired_at (format HH:MM:SS).
  4. Setelah bayar berhasil: webhook (jika di-set) + status API menjadi berhasil.
  5. Jika waktu habis tanpa bayar: status expired.

Timer & kadaluarsa. Halaman payment_url menampilkan hitung mundur berdasarkan expired_at. Sistem menjamin sisa waktu minimal sekitar 60 menit saat transaksi dibuat (meski provider mengembalikan nilai lebih pendek). Nominal di halaman bayar disamakan dengan total yang muncul di aplikasi bank/e-wallet.

4. Daftar Channel (method)

Real-time sesuai channel yang aktif. Bisa memakai kode custom white-label (di-set di dashboard) tanpa mengekspos nama provider. Detail biaya: Biaya Channel Pembayaran.

rn_qris_all rn_bca rn_ovo rn_dana rn_shopeepay rn_bcava rn_mandiriva rn_maybankva rn_bniva rn_cimbva rn_permatava rn_atmbersamava rn_arthagrahava rn_bncva rn_briva rn_alfamart rn_pos rn_indomart rn_qrisnusapay

5. Notifikasi Webhook

Atur URL Webhook di pengaturan Merchant. Sistem akan POST JSON ke URL tersebut saat pembayaran berhasil.

Body yang dikirim

{
  "order_id": "INV-001",
  "amount": 50000,
  "status": "success",
  "merchant_code": "MCH-XXXX"
}

amount pada webhook = nominal yang dikreditkan ke merchant (request), bukan total tagihan pelanggan.

Penting: Jangan mengandalkan body webhook saja. Selalu verifikasi ulang lewat GET /api/v1/transaction/status/{order_id} sebelum menandai order lunas. SDK PHP menyediakan isValidWebhookPayload() untuk ini.

6. Kode Status HTTP

KodeArti
201Transaksi berhasil dibuat.
200Request berhasil (cek status, dll).
401API Key / Signature tidak valid atau tidak disertakan.
404Transaksi dengan order_id tidak ditemukan.
422Validasi gagal atau gagal membuat transaksi (lihat field message).

7. Integrasi Siap Pakai

Tanpa coding berat — pasang modul, isi API Key & Secret Key, langsung jalan.

Modul WHMCS

WHMCS 8.x & 9.x

Invoice pelanggan mendapat tombol bayar QRIS/VA/E-Wallet. Status invoice otomatis Paid setelah terverifikasi.

  • Setup dari Admin WHMCS → Payments
  • Verifikasi ulang ke API sebelum invoice lunas
  • Mode Debug bawaan
Unduh Modul WHMCS

Plugin WooCommerce

WordPress 5.8+ · WooCommerce 6.0+

Muncul sebagai metode bayar di checkout. Pesanan otomatis diproses setelah pembayaran terverifikasi.

  • WooCommerce → Settings → Payments
  • Verifikasi ulang ke API sebelum order lunas
  • Log di WooCommerce → Status → Logs
Unduh Plugin WooCommerce

Callback (Webhook Merchant)

Setelah pembayaran berhasil, sistem mengirim HTTP POST JSON ke URL callback merchant kamu. Gunakan ini agar backend bisa menandai order lunas tanpa menunggu polling status.

1. Cara mendaftarkan URL Callback

  1. Merchant production: saat Tambah Merchant, isi field URL Webhook, atau edit merchant di dashboard.
  2. Merchant sandbox: saat Buat Merchant Sandbox, isi URL Webhook (opsional tapi disarankan untuk uji callback).
  3. URL harus publik (HTTPS disarankan), menerima method POST, dan merespons cepat (timeout server ~5 detik).
  4. Contoh: https://tokokamu.com/api/payment/callback

2. Request yang dikirim ke endpoint kamu

ItemNilai
MethodPOST
Content-Typeapplication/json
Kapan dikirimSaat status transaksi menjadi berhasil (setelah konfirmasi provider)
RetryTidak ada retry otomatis — jika endpoint gagal, cek status lewat API GET /api/v1/transaction/status/{order_id}

Body JSON (payload)

{
  "order_id": "INV-001",
  "amount": 50000,
  "status": "success",
  "merchant_code": "MCH-A1B2C3"
}
FieldTipeKeterangan
order_idstringOrder ID yang kamu kirim saat create (sandbox berprefix SANDBOX- jika mode sandbox).
amountintegerNominal yang dikreditkan ke merchant (production). Untuk sandbox tetap dikirim untuk uji, tanpa kredit saldo.
statusstringSelalu success pada callback sukses saat ini.
merchant_codestringKode merchant (MCH-... atau SBX-...).

3. Contoh endpoint penerima (PHP Laravel)

// routes/api.php
Route::post('/payment/callback', [PaymentCallbackController::class, 'handle']);

// app/Http/Controllers/PaymentCallbackController.php
public function handle(Request $request)
{
    $orderId = $request->input('order_id');
    $status  = $request->input('status');
    $amount  = (int) $request->input('amount');
    $mch     = $request->input('merchant_code');

    if ($status !== 'success' || ! $orderId) {
        return response()->json(['ok' => false], 400);
    }

    // 1) Idempotent: jangan proses order yang sama dua kali
    // 2) (Opsional) verifikasi ulang ke API status RuangNotif
    // 3) Update order lokal → lunas / kirim barang / aktivasi layanan

    return response()->json(['ok' => true], 200);
}

4. Contoh Node.js (Express)

app.post('/api/payment/callback', express.json(), async (req, res) => {
  const { order_id, amount, status, merchant_code } = req.body;

  if (status !== 'success') {
    return res.status(400).json({ ok: false });
  }

  // updateOrderPaid(order_id, amount);
  return res.json({ ok: true });
});

5. Best practice

SDK PHP Resmi

Signing, HTTP, dan verifikasi webhook sudah dibungkus — cukup panggil method create & status.

Unduh SDK PHP (.zip)
Berhasil Menyalin