Dokumentasi API Payment Gateway Payantara
Setiap API key Payantara terikat secara permanen pada satu client, satu project, dan satu environment. Project transaksi ditentukan otomatis dari API key.
Quick Start
curl -X POST "https://gateway.paynesia.ngnplay.com/api/v1/payments" \
-H "Content-Type: application/json" \
-H "X-API-Key: sk_sandbox_xxxxxxxxx" \
-H "Idempotency-Key: ORDER-1001" \
-d '{
"order_id": "ORDER-1001",
"amount": 10000,
"payment_method": "QRIS",
"customer_name": "Budi",
"customer_email": "budi@example.com",
"customer_phone": "081234567890",
"expire_minutes": 15
}'
Authentication
Kirim satu API key project melalui header
X-API-Key pada setiap endpoint yang membutuhkan
autentikasi.
X-API-Key: sk_live_xxxxxxxxx
Content-Type: application/json
API key hanya boleh digunakan dari server backend. Jangan menaruh API key di browser, aplikasi mobile, repository, response publik, atau log aplikasi.
Project Scope
-
Client tidak perlu dan tidak boleh mengirim
project_id. - Project ditentukan otomatis dari API key yang terautentikasi.
- API key project lain tidak dapat membaca atau membatalkan transaksi tersebut.
-
Akses transaksi di luar scope project dikembalikan sebagai
HTTP
404.
SANDBOX & LIVE
| API Key | Project | Environment | Penggunaan |
|---|---|---|---|
sk_sandbox_... |
Project SANDBOX | SANDBOX | Pengujian tanpa pembayaran produksi. |
sk_live_... |
Project LIVE | LIVE | Transaksi produksi melalui provider aktif. |
API key SANDBOX tidak dapat digunakan untuk project LIVE. API key LIVE juga tidak dapat digunakan untuk project SANDBOX.
Idempotency
Gunakan nilai unik dan stabil untuk setiap order. Mengulang request pada project yang sama dengan idempotency key yang sama akan mengembalikan transaksi yang sama.
Idempotency-Key: ORDER-1001
Idempotency diproses dalam scope project. Dua project berbeda
dapat menggunakan nilai order_id atau
idempotency_key yang sama tanpa berbagi transaksi.
Payments
Resource pembayaran utama memakai path
/api/v1/payments.
Create Payment
/api/v1/payments
| Field | Type | Required | Keterangan |
|---|---|---|---|
order_id |
string | Ya | ID order unik dalam project API key. |
amount |
number | Ya | Nominal pembayaran dalam rupiah. |
payment_method |
string | Ya | Kode metode pembayaran aktif. |
idempotency_key |
string | Tidak |
Alternatif body untuk header
Idempotency-Key.
|
customer_name |
string | Tidak | Nama pembayar. |
customer_email |
string | Tidak | Email pembayar. |
customer_phone |
string | Tidak | Nomor telepon pembayar. |
expire_minutes |
integer | Tidak | Durasi kedaluwarsa pembayaran. |
return_url |
URL | Tidak | URL tujuan setelah checkout. |
project_id. Nilai project selalu
diambil dari API key.
Create Payment Response
{
"success": true,
"data": {
"transaction_id": "PAY-20260804-1234ABCD",
"order_id": "ORDER-1001",
"amount": 10000,
"status": "pending",
"qr_string": "000201...",
"va_number": null,
"payment_url": null,
"expired_at": "2026-08-04 17:45:00"
}
}
Get Payment Status
/api/v1/payments/{transaction_id_or_order_id}
Identifier dapat berupa transaction ID Payantara atau order ID client. Pencarian hanya dilakukan dalam project API key.
curl "https://gateway.paynesia.ngnplay.com/api/v1/payments/ORDER-1001" \
-H "X-API-Key: sk_live_xxxxxxxxx"
Cancel Pending Payment
/api/v1/payments/{transaction_id}/cancel
Endpoint cancel hanya menerima
transaction_id Payantara. Order ID client tidak
dapat digunakan pada endpoint cancel.
curl -X POST \
"https://gateway.paynesia.ngnplay.com/api/v1/payments/PAY-20260804-1234ABCD/cancel" \
-H "X-API-Key: sk_live_xxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{}'
Payment Status
| Status | Arti |
|---|---|
PENDING |
Menunggu pembayaran. |
PAID |
Pembayaran berhasil dan final. |
EXPIRED |
Pembayaran melewati batas waktu atau dibatalkan. |
FAILED |
Pembayaran tidak dapat diproses. |
Payment Channels
/api/v1/payment-methods
Endpoint ini bersifat publik dan tidak membutuhkan API key. Gunakan hasilnya sebagai sumber daftar channel, batas nominal, biaya, serta masa berlaku.
curl "https://gateway.paynesia.ngnplay.com/api/v1/payment-methods"
-
QRIS menggunakan field
qr_string. -
Virtual Account menggunakan field
va_number. -
E-wallet dapat menggunakan field
payment_url. - Tampilkan hanya field instruksi yang tersedia pada response.
Balance
/api/v1/balance
Endpoint balance membutuhkan X-API-Key. Saldo
dikembalikan pada level client pemilik API key.
curl "https://gateway.paynesia.ngnplay.com/api/v1/balance" \
-H "X-API-Key: sk_live_xxxxxxxxx"
Webhooks
Payantara mengirim perubahan status ke callback URL project pemilik transaksi. Callback dan webhook secret dikonfigurasi terpisah untuk setiap project.
X-Payantara-Webhook-Id: wh_xxx
X-Payantara-Idempotency-Key: idem_xxx
X-Payantara-Event: payment.paid
X-Payantara-Timestamp: 1780000000
X-Payantara-Signature: t=1780000000,v1=<hmac_sha256_hex>
X-Payantara-Signature-Version: v1
X-Payantara-Delivery-Attempt: 1
Events
| Event | Keterangan |
|---|---|
payment.paid |
Payment berubah menjadi PAID. |
payment.failed |
Payment berubah menjadi FAILED. |
payment.expired |
Payment berubah menjadi EXPIRED. |
webhook.test |
Event pengujian webhook project. |
PHP Signature Verification
<?php
$secret = getenv('PAYANTARA_WEBHOOK_SECRET') ?: '';
$rawBody = file_get_contents('php://input');
$timestamp = (int)(
$_SERVER['HTTP_X_PAYANTARA_TIMESTAMP'] ?? 0
);
$signature =
$_SERVER['HTTP_X_PAYANTARA_SIGNATURE'] ?? '';
$idempotencyKey =
$_SERVER['HTTP_X_PAYANTARA_IDEMPOTENCY_KEY'] ?? '';
if (!$timestamp || abs(time() - $timestamp) > 300) {
http_response_code(400);
exit('stale');
}
$expected =
't=' . $timestamp . ',v1=' .
hash_hmac(
'sha256',
$timestamp . '.' . $rawBody,
$secret
);
if (!hash_equals($expected, $signature)) {
http_response_code(401);
exit('invalid signature');
}
// Simpan idempotency key sebelum memproses event.
http_response_code(200);
echo json_encode(['success' => true]);
Error Codes
Detail internal provider, credential, dan routing tidak ditampilkan melalui response publik.
{
"success": false,
"error": {
"code": "PAYMENT_PROCESSING_FAILED",
"message": "Payment could not be processed. Please try again."
},
"request_id": "req_xxxxxxxxx"
}
| HTTP | Code | Keterangan |
|---|---|---|
| 400 | INVALID_REQUEST |
Request tidak dapat dibaca. |
| 401 | AUTHENTICATION_FAILED |
API key tidak valid atau tidak aktif. |
| 404 | PAYMENT_NOT_FOUND |
Payment tidak ditemukan dalam project API key. Response yang sama digunakan untuk akses cross-project. |
| 422 | VALIDATION_FAILED |
Field atau aturan transaksi tidak valid. |
| 429 | RATE_LIMITED |
Terlalu banyak request. |
| 503 | PAYMENT_PROCESSING_FAILED |
Payment belum dapat diproses. |
| 503 | PAYMENT_CANCEL_FAILED |
Payment belum dapat dibatalkan. |