DOCS / API REFERENCE
MERCHANT API v1
Dokumentasi lengkap untuk integrasi SantakaPay ke aplikasi merchant Anda. Semua request menggunakan JSON dan diautentikasi dengan API key.
QUICKSTART
Empat langkah supaya transaksi pertama Anda jalan: ambil API key, buat transaksi, arahkan pelanggan ke instruksi pembayaran, lalu verifikasi statusnya.
01
Minta API key
Tersedia di dashboard merchant, halaman Developers API.
02
Buat transaksi
POST /api/transactions dengan orderId dan amount.
03
Bayar
Pelanggan memakai nomor VA atau scan QRIS yang Anda terima.
04
Verifikasi
Cek GET /api/transactions/:id atau tunggu webhook paid.
CONTOH RESPON SINGKAT
{
"success": true,
"data": {
"transactionNo": "SP-20260929-12345",
"status": "pending",
"vaNumber": "3901001234512345",
"expiryTime": "2026-09-29T17:00:00.000Z"
}
}AUTHENTICATION
Semua request API harus menyertakan header x-api-key yang berisi API key merchant Anda. Key diberikan saat registrasi merchant.
HEADER
x-api-key: sk_live_xxxxxxxxxxxxxxxxxxxxxxxxCURL EXAMPLE
curl -X POST https://api.santakapay.id/transactions \
-H "Content-Type: application/json" \
-H "x-api-key: sk_live_xxxxxxxxxxxxxxxxxxxxxxxx" \
-d '{ "orderId": "ORDER-001", "amount": 150000, "paymentMethod": "va_bca" }'Simpan key di environment variable server Anda — jangan pernah menaruhnya di kode frontend atau repository publik.
CREATE TRANSACTION
/api/transactionsMembuat transaksi baru. Jika menggunakan VA, response akan menyertakan nomor Virtual Account. Jika QRIS, menyertakan string QR code.
| FIELD | TYPE | REQUIRED | DESCRIPTION |
|---|---|---|---|
orderId | string | Ya | ID pesanan dari sistem merchant Anda |
amount | integer | Ya | Jumlah dalam Rupiah (tanpa desimal) |
paymentMethod | string | Ya | Kode metode pembayaran (lihat Payment Methods) |
paymentChannel | string | Tidak | Channel spesifik dalam metode pembayaran |
customerName | string | Tidak | Nama pelanggan |
customerEmail | string | Tidak | Email pelanggan |
customerPhone | string | Tidak | Nomor telepon pelanggan |
items | array | Tidak | Detail item: [{ id, name, price, quantity }] |
metadata | object | Tidak | Custom fields untuk kebutuhan merchant |
expiryMinutes | integer | Tidak | Waktu kedaluwarsa dalam menit (default: 60) |
REQUEST BODY
{
"orderId": "ORDER-001",
"amount": 150000,
"paymentMethod": "va_bca",
"customerName": "John Doe",
"customerEmail": "john@email.com",
"customerPhone": "081234567890",
"items": [
{
"id": "PROD-001",
"name": "Product A",
"price": 75000,
"quantity": 2
}
],
"metadata": {
"custom_field": "value"
}
}RESPONSE — 201 CREATED
{
"success": true,
"data": {
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"transactionNo": "SP-20260929-12345",
"orderId": "ORDER-001",
"amount": 150000,
"fee": 2250,
"netAmount": 147750,
"status": "pending",
"paymentMethod": "va_bca",
"vaNumber": "3901001234512345",
"vaBank": "BCA",
"expiryTime": "2026-09-29T17:00:00.000Z",
"createdAt": "2026-09-29T10:00:00.000Z"
}
}CHECK STATUS
/api/transactions/:idCek status transaksi berdasarkan transactionNo atau id. Gunakan endpoint ini untuk memverifikasi status pembayaran sebelum memproses order.
| FIELD | TYPE | WAJIB? | DESCRIPTION |
|---|---|---|---|
id | string | Ya | UUID transaksi,(created otomatis oleh SantakaPay) |
transactionNo | string | Tidak | Nomor transaksi berformat SP-YYYYMMDD-XXXXX |
orderId | string | Tidak | ID pesanan merchant pada transaksi |
amount | integer | Tidak | Nominal transaksi dalam Rupiah |
fee | integer | Tidak | Biaya merchant dalam Rupiah |
netAmount | integer | Tidak | Nominal bersih yang diterima merchant |
status | string | Tidak | Status transaksi terkini |
vaNumber | string | Tidak | Nomor Virtual Account (khusus VA) |
vaBank | string | Tidak | Kode bank Virtual Account |
expiryTime | datetime | Tidak | Batas akhir pembayaran (ISO 8601) |
paidAt | datetime | Tidak | Waktu pembayaran diterima (ISO 8601) |
createdAt | datetime | Tidak | Waktu transaksi dibuat (ISO 8601) |
RESPONSE — 200 OK
{
"success": true,
"data": {
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"transactionNo": "SP-20260929-12345",
"orderId": "ORDER-001",
"amount": 150000,
"fee": 2250,
"netAmount": 147750,
"status": "paid",
"paymentMethod": "va_bca",
"paidAt": "2026-09-29T10:30:00.000Z",
"createdAt": "2026-09-29T10:00:00.000Z"
}
}Status yang mungkin: pending, paid, expired, failed, refunded, partial_refund
REFUND
/api/transactions/refundRefund sebagian atau seluruh transaksi yang sudah berstatus paid. Transaksi hanya bisa direfund sekali.
| FIELD | TYPE | REQUIRED | DESCRIPTION |
|---|---|---|---|
transactionNo | string | Ya | Nomor transaksi yang akan direfund |
amount | integer | Tidak | Jumlah refund (kosongkan untuk full refund) |
reason | string | Tidak | Alasan refund |
REQUEST BODY
{
"transactionNo": "SP-20260929-12345",
"amount": 50000,
"reason": "Permintaan pelanggan"
}RESPONSE — 200 OK
{
"success": true,
"data": {
"transactionNo": "SP-20260929-12345",
"status": "partial_refund",
"refundAmount": 50000,
"remainingAmount": 100000
}
}WEBHOOKS
SantakaPay akan mengirim HTTP POST ke URL webhook yang didaftarkan merchant saat status transaksi berubah. Server merchant harus merespons dengan 200 OK dalam 30 detik. Jika gagal, SantakaPay akan melakukan retry sebanyak 3 kali dengan interval 1 menit.
PAYLOAD FORMAT
WEBHOOK BODY — POST
{
"event": "transaction.paid",
"transactionNo": "SP-20260929-12345",
"orderId": "ORDER-001",
"amount": 150000,
"fee": 2250,
"netAmount": 147750,
"status": "paid",
"paidAt": "2026-09-29T10:30:00.000Z",
"signature": "a1b2c3d4e5f6..."
}SIGNATURE VERIFICATION
Setiap webhook menyertakan field signature yang dihasilkan dari HMAC SHA256. Verifikasi signature untuk memastikan webhook berasal dari SantakaPay.
VERIFICATION (Node.js)
const crypto = require('crypto');
function verifyWebhookSignature(payload, signature, secret) {
const expected = crypto
.createHmac('sha256', secret)
.update(JSON.stringify(payload))
.digest('hex');
return expected === signature;
}EVENT TYPES
| EVENT | DESCRIPTION |
|---|---|
transaction.paid | Pembayaran berhasil diterima |
transaction.expired | Transaksi kedaluwarsa tanpa pembayaran |
transaction.failed | Pembayaran gagal |
transaction.refunded | Transaksi telah direfund |
settlement.completed | Pencairan dana selesai diproses |
INTEGRATION GUIDE
Alur integrasi minimum yang direkomendasikan: buat transaksi di server Anda, kirim nomor VA atau QR string ke halaman pembayaran, lalu majukan pesanan hanya setelah statusnya paid.
POLA INTEGRASI (NODE.JS)
// 1. Buat transaksi
const res = await fetch("https://api.santakapay.id/transactions", {
method: "POST",
headers: {
"Content-Type": "application/json",
"x-api-key": process.env.SANTAKAPAY_API_KEY,
},
body: JSON.stringify({
orderId: order.id,
amount: order.total,
paymentMethod: "va_bca",
}),
});
const { data } = await res.json();
// 2. Tampilkan instruksi pembayaran ke pelanggan
renderPaymentInstructions({
transactionNo: data.transactionNo,
vaNumber: data.vaNumber,
expiresAt: data.expiryTime,
});
// 3. Terima webhook transaction.paid, lalu majukan pesanan
app.post("/webhooks/santakapay", async (req, res) => {
const valid = verifyWebhookSignature(
req.body,
req.headers["x-signature"],
process.env.SANTAKAPAY_WEBHOOK_SECRET,
);
if (!valid) return res.status(400).send("signature tidak valid");
await fulfillOrder(req.body.orderId);
res.status(200).send("OK");
});Semua pemanggilan harus keluar dari server Anda — panggilan langsung dari browser akan membocorkan API key.
PAYMENT METHODS
/api/payment-methodsDaftar metode pembayaran yang tersedia beserta batas minimum dan maksimum transaksi.
RESPONSE — 200 OK
{
"success": true,
"data": [
{ "code": "qr_code", "name": "QRIS", "category": "qr_code", "minAmount": 1000, "maxAmount": 50000000 },
{ "code": "va_bca", "name": "Virtual Account BCA", "category": "bank_transfer", "minAmount": 1000, "maxAmount": 50000000 },
{ "code": "va_mandiri", "name": "Virtual Account Mandiri", "category": "bank_transfer", "minAmount": 1000, "maxAmount": 50000000 },
{ "code": "va_bri", "name": "Virtual Account BRI", "category": "bank_transfer", "minAmount": 1000, "maxAmount": 50000000 },
{ "code": "va_bni", "name": "Virtual Account BNI", "category": "bank_transfer", "minAmount": 1000, "maxAmount": 50000000 },
{ "code": "ewallet_gopay", "name": "GoPay", "category": "ewallet", "minAmount": 1000, "maxAmount": 20000000 },
{ "code": "ewallet_ovo", "name": "OVO", "category": "ewallet", "minAmount": 1000, "maxAmount": 20000000 },
{ "code": "ewallet_dana", "name": "DANA", "category": "ewallet", "minAmount": 1000, "maxAmount": 20000000 },
{ "code": "cc", "name": "Kartu Kredit/Debit", "category": "card", "minAmount": 1000, "maxAmount": 100000000 },
{ "code": "convenience_store", "name": "Convenience Store", "category": "convenience_store", "minAmount": 10000, "maxAmount": 5000000 }
]
}SETTLEMENT
/api/settlements?page=1&limit=20Daftar settlement (pencairan dana) ke rekening bank merchant. Settlement diproses otomatis berdasarkan siklus yang dikonfigurasi (D+0 s/d D+7).
RESPONSE — 200 OK
{
"success": true,
"data": [
{
"id": "settle-uuid-001",
"amount": 1425000,
"txCount": 12,
"settlePeriod": "2026-09-28",
"status": "completed",
"bankName": "BCA",
"bankAccount": "1234567890",
"bankHolder": "PT Merchant Jaya",
"referenceNo": "TRF-20260929001",
"processedAt": "2026-09-29T01:00:00.000Z",
"completedAt": "2026-09-29T01:15:00.000Z"
}
],
"pagination": {
"page": 1,
"limit": 20,
"total": 45,
"pages": 3
}
}ERROR CODES
Semua error response mengikuti format:
ERROR FORMAT
{
"success": false,
"error": {
"code": "ERROR_CODE",
"message": "Deskripsi error dalam Bahasa Indonesia"
}
}| CODE | HTTP | DESCRIPTION |
|---|---|---|
MISSING_API_KEY | 401 | Header x-api-key wajib |
INVALID_API_KEY | 401 | API key tidak valid atau tidak ditemukan |
MERCHANT_INACTIVE | 403 | Merchant tidak aktif atau ditangguhkan |
VALIDATION_ERROR | 400 | Parameter wajib tidak lengkap |
DUPLICATE_ORDER_ID | 409 | Order ID sudah ada pada merchant ini |
DUPLICATE_EMAIL | 409 | Email sudah terdaftar |
INVALID_AMOUNT | 400 | Jumlah tidak valid atau di luar batas |
INVALID_PAYMENT_METHOD | 400 | Metode pembayaran tidak tersedia |
TRANSACTION_NOT_FOUND | 404 | Transaksi tidak ditemukan |
TRANSACTION_EXPIRED | 400 | Transaksi sudah kedaluwarsa |
TRANSACTION_NOT_PENDING | 400 | Status transaksi sudah berubah dari pending |
REFUND_EXCEEDS | 400 | Jumlah refund melebihi sisa yang bisa direfund |
INTERNAL_ERROR | 500 | Kesalahan internal server |
RATE LIMITS
Batas.request dihitung per API key. Melebihi batas akan mendapat HTTP 429 beserta header Retry-After.
| ENDPOINT | LIMIT | CATATAN |
|---|---|---|
| Create transaction | 60 req / menit | Dihitung per API key |
| Check status | 300 req / menit | Pengecekan status transaksi |
| Refund | 30 req / menit | Operasi tidak dapat dibatalkan |
| Webhook delivery | 3 percobaan | Interval 1 menit antar percobaan |
TESTING
Uji integrasi Anda di Sandbox lebih dulu. Key sandbox berawalan sk_test_ dan tidak pernah memindahkan uang sungguhan.
UJI TRANSAKSI SANDBOX
curl -X POST https://api.santakapay.id/transactions \
-H "Content-Type: application/json" \
-H "x-api-key: sk_test_xxxxxxxxxxxxxxxxxxxxxxxx" \
-d '{ "orderId": "TEST-001", "amount": 10000, "paymentMethod": "qr_code" }'- Simulasikan pembayaran dari halaman Sandbox POS di dashboard.
- Pastikan webhook Anda dipanggil dan signature valid.
- Uji refund sebagian dan full refund pada transaksi paid.
GO LIVE
Checklist singkat sebelum produksi. Centang semua, lalu tukar key sandbox dengan key live.
- Simpan API key di secret manager, bukan di kode sumber.
- Verifikasi signature webhook dan tolak payload yang tidak cocok.
- Siapkan halaman sukses/failure untuk alur pembayaran.
- Pantau halaman webhook logs saat transaksi pertama masuk.
- Siapkan prosedur refund dan nomor kontak support.
CHANGELOG
| VERSI | TANGGAL | PERUBAHAN |
|---|---|---|
| v2.4 | 29 Sep 2026 | QRIS Forge, webhook HMAC SHA256, refund sebagian |
| v2.3 | 12 Agu 2026 | Payment Link API & paginasi settlement |
| v2.2 | 03 Jul 2026 | Virtual Account BCA/Mandiri/BRI/BNI |
| v2.1 | 20 Mei 2026 | Rate limit per endpoint dan idempotency key |
SANTAKAPAY API v1 — ARCADE PAYMENT GATEWAY INDONESIA