Developer Documentation

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.

Base URL: https://gateway.paynesia.ngnplay.com Authentication: X-API-Key Project-scoped API Docs V3.24.2.10

Quick Start

Gunakan API key SANDBOX untuk pengujian dan API key LIVE untuk transaksi produksi. Endpoint tetap sama; environment dan project mengikuti API key.
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

Satu API key hanya dapat membuat, membaca, dan membatalkan transaksi milik project yang terhubung dengan API key tersebut.
  • 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.
Gunakan API key berbeda untuk setiap merchant atau project. Jangan menggunakan satu API key untuk beberapa project.

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

POST /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.
Jangan mengirim 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

GET /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

POST /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

GET /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

GET /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.