Dokumentasi API SoraPay
SoraPay menerima pembayaran QRIS lewat akun pusat SoraPay: kamu membuat pembayaran lewat API, pembeli membayar QRIS dinamis di halaman checkout, dan pembayaran terverifikasi masuk ke saldo merchant setelah dipotong fee Rp 250 + 0,7% per transaksi.
Base URL API: https://api.sorapay.biz.id · Semua rute versi di awalan /v1.
1. Autentikasi
Integrasi server-ke-server memakai API key merchant (dari Dashboard → Pengaturan → API Key Merchant) pada header X-Api-Key. Jangan pernah menaruh API key di kode frontend publik. JWT sesi panel hanya untuk dashboard dan tidak dipakai integrasi.
X-Api-Key: sp_live_xxxxxxxxxxxx2. Buat pembayaran
POST /v1/payments — field wajib: order_ref (unik per merchant) dan amount (nominal dasar dalam rupiah, minimal Rp1.000). Field opsional: title, description, expires_minutes. Server menambahkan kode unik 1–999 sehingga total yang dibayar pembeli adalah amount_total.
curl -X POST https://api.sorapay.biz.id/v1/payments \
-H "X-Api-Key: sp_live_xxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{"order_ref":"INV-001","amount":100000,"title":"Tagihan Kos Kamar 4"}'Respons memuat objek payment (termasuk id berawalan pay_, amount_base, unique_code, amount_total, status, expires_at) dan checkout_url — halaman bayar publik yang dibagikan ke pembeli.
3. Cek status pembayaran
GET /v1/payments/{id} dengan API key yang sama. Status yang mungkin: pending, paid, expired, cancelled, refunded. Setelah lunas, respons memuat paid_at, fee_total, dan net_amount. Halaman publik pembeli bisa dibaca tanpa autentikasi lewat GET /v1/public/payments/{id} (data terbatas).
4. Webhook & verifikasi tanda tangan
Atur URL webhook di Dashboard → Pengaturan. Setiap pembayaran terverifikasi memicu POST JSON ke URL kamu dengan header X-SoraPay-Signature berisi HMAC-SHA256 (hex) dari body mentah, dikunci secret webhook merchant kamu. Selalu verifikasi tanda tangan sebelum memproses order, dan balas 2xx.
// Node.js — verifikasi webhook SoraPay
const crypto = require("crypto");
function verify(rawBody, signatureHeader, webhookSecret) {
const expected = crypto
.createHmac("sha256", webhookSecret)
.update(rawBody) // body MENTAH, sebelum JSON.parse
.digest("hex");
const a = Buffer.from(expected);
const b = Buffer.from(signatureHeader || "");
return a.length === b.length && crypto.timingSafeEqual(a, b);
}Event utama: payment.paid. Isi payload mengikuti objek pembayaran (id, order_ref, amount_total, fee_total, net_amount, paid_at). Bila pengiriman gagal, perlakukan endpoint cek status sebagai sumber kebenaran cadangan (polling).
5. Kode error
Error berbentuk {"error": "<kode>"} dengan status HTTP semantik. Kode yang umum:
invalid_api_key— API key salah/dicabut (401).order_ref_required/order_ref_exists— referensi order kosong atau sudah dipakai.invalid_amount/amount_too_small— nominal tidak valid / di bawah Rp1.000.payment_not_found— pembayaran tidak ditemukan (404).unique_amount_unavailable— kode unik sedang penuh, coba lagi sebentar.account_disabled— akun merchant dinonaktifkan.validation/invalid_json— data yang dikirim tidak valid.
Butuh bantuan integrasi? Lihat halaman Bantuan atau buka dashboard kamu.