NawaPayNawaPay Docs

Referensi endpoint

Seluruh endpoint berada di bawah https://api.nawapay.co.id/v1 dan memerlukan tanda tangan HMAC. Endpoint yang menulis juga memerlukan Idempotency-Key. Semua nominal adalah bilangan bulat satuan terkecil.

Ringkasan

MetodeJalurKeterangan
POST/v1/paymentsMembuat pembayaran
GET/v1/payments/{reference}Status pembayaran
POST/v1/payments/{reference}/cancelMembatalkan pembayaran
POST/v1/refundsRefund penuh atau parsial
GET/v1/refunds/{uuid}Status refund
GET/v1/balancesSaldo merchant
GET/v1/settlementsDaftar batch settlement
GET/v1/disputesDaftar sengketa
GET/v1/healthKesehatan layanan

Siklus hidup pembayaran

StatusArtiAkhir?
pendingDibuat, menunggu pembayaran dari pelanggan.Tidak
processingDana sedang diproses penyedia.Tidak
succeededDana diterima; kewajiban ke merchant tercatat di buku besar.Ya
failedDitolak penyedia atau ditolak mesin deteksi penipuan.Ya
expiredMelewati expires_at tanpa dibayar.Ya
canceledDibatalkan merchant sebelum dibayar.Ya
partially_refundedSebagian dana sudah dikembalikan.Tidak
refundedSeluruh nominal sudah dikembalikan.Ya

Membuat pembayaran

POST /v1/payments

Membuat satu maksud pembayaran dan memilih penyedia sesuai aturan perutean. Memerlukan Idempotency-Key.

Parameter

BidangTipeKeterangan
amount_minorinteger, wajibNominal dalam satuan terkecil. Harus lebih besar dari nol.
currencystring, wajibKode ISO 4217, contoh IDR.
payment_methodstring, wajibqris, va, card, ewallet, atau bank_transfer.
reference_idstring, wajibIdentitas pesanan di sistem kamu. Unik per merchant, maksimum 64 karakter.
descriptionstring, opsionalKeterangan singkat, maksimum 255 karakter.
expires_ininteger, opsionalMasa berlaku dalam detik. Bawaan 1800, maksimum 86400.
customerobjek, opsionalname, email, phone. Dipakai mesin deteksi penipuan dan pengiriman instruksi.
callback_urlstring, opsionalMenimpa alamat webhook bawaan untuk pembayaran ini.
metadataobjek, opsionalMaksimum 20 pasangan kunci-nilai bertipe teks. Dikembalikan apa adanya.

Permintaan

POST /v1/payments
Authorization: Bearer ak_test_9f2c1d7b4a05
X-Timestamp: 1785200130
X-Signature: 6c1f0a…
Idempotency-Key: 4f8c1f6e-2c1a-4d5b-9d61-3f0b7a2c9e14
Content-Type: application/json

{
  "amount_minor": 150000,
  "currency": "IDR",
  "payment_method": "qris",
  "reference_id": "ORD-10427",
  "description": "Langganan Agustus",
  "expires_in": 1800,
  "customer": {
    "name": "Rina Astuti",
    "email": "[email protected]",
    "phone": "+628120000000"
  },
  "metadata": { "channel": "web", "plan": "pro" }
}

Respons 201 Created

{
  "reference": "pay_01J9Q4M2T7K3XW",
  "status": "pending",
  "amount_minor": 150000,
  "currency": "IDR",
  "exponent": 0,
  "fee_minor": 2100,
  "net_minor": 147900,
  "refunded_minor": 0,
  "payment_method": "qris",
  "reference_id": "ORD-10427",
  "description": "Langganan Agustus",
  "gateway_code": "qris_sandbox",
  "environment": "sandbox",
  "risk": { "decision": "approve", "score": 12 },
  "instructions": {
    "type": "qr_string",
    "value": "00020101021226610014COM.NAWAPAY…",
    "expires_at": "2026-08-04T02:45:30Z"
  },
  "metadata": { "channel": "web", "plan": "pro" },
  "created_at": "2026-08-04T02:15:30Z",
  "updated_at": "2026-08-04T02:15:30Z"
}
Bidang instructions berbeda menurut metode: QRIS mengembalikan qr_string, VA mengembalikan nomor rekening virtual beserta nama bank, dompet elektronik mengembalikan redirect_url. Perlakukan bidang ini sebagai objek yang bentuknya dapat bertambah.

Status pembayaran

GET /v1/payments/{reference}

Mengambil satu pembayaran. Hasil selalu disaring menurut kepemilikan merchant: pembayaran milik merchant lain menghasilkan 404 PAYMENT_NOT_FOUND, bukan 403 — supaya keberadaan objek itu pun tidak bocor.

Kamu juga dapat mencari berdasarkan identitas pesanan sendiri dengan GET /v1/payments?reference_id=ORD-10427.

{
  "reference": "pay_01J9Q4M2T7K3XW",
  "status": "succeeded",
  "amount_minor": 150000,
  "currency": "IDR",
  "exponent": 0,
  "fee_minor": 2100,
  "net_minor": 147900,
  "refunded_minor": 0,
  "payment_method": "qris",
  "reference_id": "ORD-10427",
  "gateway_code": "qris_sandbox",
  "environment": "sandbox",
  "paid_at": "2026-08-04T02:18:04Z",
  "settlement": {
    "status": "pending",
    "estimated_date": "2026-08-05"
  },
  "created_at": "2026-08-04T02:15:30Z",
  "updated_at": "2026-08-04T02:18:04Z"
}

Membatalkan pembayaran

POST /v1/payments/{reference}/cancel

Hanya berlaku untuk pembayaran berstatus pending. Pembayaran yang sudah succeeded tidak dapat dibatalkan — gunakan refund. Memerlukan Idempotency-Key.

POST /v1/payments/pay_01J9Q4M2T7K3XW/cancel
{ "reason": "Dibatalkan pelanggan" }

200 OK
{
  "reference": "pay_01J9Q4M2T7K3XW",
  "status": "canceled",
  "canceled_at": "2026-08-04T02:22:10Z",
  "reason": "Dibatalkan pelanggan"
}

Membuat refund

POST /v1/refunds

Mengembalikan seluruh atau sebagian nominal pembayaran yang sudah berhasil. Refund dicatat sebagai entri pembalik pada grup jurnal pembayaran aslinya. Memerlukan Idempotency-Key.

BidangTipeKeterangan
payment_referencestring, wajibPembayaran yang dikembalikan.
amount_minorinteger, opsionalKosongkan untuk refund penuh atas sisa yang belum dikembalikan.
reasonstring, opsionalAlasan, maksimum 255 karakter. Tersimpan pada jejak audit.
POST /v1/refunds
Idempotency-Key: 9b1d4c7a-55e2-4f60-8f11-2a3c6d8e0b47

{
  "payment_reference": "pay_01J9Q4M2T7K3XW",
  "amount_minor": 50000,
  "reason": "Satu item tidak tersedia"
}

201 Created
{
  "uuid": "rfd_01J9Q6H1N4P8ZC",
  "payment_reference": "pay_01J9Q4M2T7K3XW",
  "status": "succeeded",
  "amount_minor": 50000,
  "currency": "IDR",
  "exponent": 0,
  "remaining_refundable_minor": 100000,
  "reason": "Satu item tidak tersedia",
  "environment": "sandbox",
  "created_at": "2026-08-04T03:01:12Z"
}
Total seluruh refund tidak boleh melebihi amount_minor pembayaran asli. Permintaan yang melampaui sisa ditolak dengan 422 REFUND_EXCEEDS_PAYMENT dan tidak ada dana yang bergerak.

Status refund

GET /v1/refunds/{uuid}
{
  "uuid": "rfd_01J9Q6H1N4P8ZC",
  "payment_reference": "pay_01J9Q4M2T7K3XW",
  "status": "succeeded",
  "amount_minor": 50000,
  "currency": "IDR",
  "exponent": 0,
  "environment": "sandbox",
  "created_at": "2026-08-04T03:01:12Z",
  "completed_at": "2026-08-04T03:01:13Z"
}

Status refund: pending, succeeded, atau failed. Refund yang gagal tidak pernah menyisakan entri jurnal separuh jalan.

Saldo merchant

GET /v1/balances

Mengembalikan saldo per mata uang. available_minor adalah dana yang dapat disettle, held_minor adalah dana yang ditahan — misalnya karena sengketa yang sedang berjalan.

{
  "environment": "sandbox",
  "as_of": "2026-08-04T03:10:00Z",
  "data": [
    {
      "currency": "IDR",
      "exponent": 0,
      "available_minor": 12480500,
      "held_minor": 150000,
      "pending_settlement_minor": 3120000
    },
    {
      "currency": "USD",
      "exponent": 2,
      "available_minor": 42150,
      "held_minor": 0,
      "pending_settlement_minor": 0
    }
  ]
}

Batch settlement

GET /v1/settlements

Daftar batch settlement, terbaru lebih dulu. Filter yang tersedia: status, currency, date_from, date_to, ditambah parameter paginasi limit dan starting_after.

GET /v1/settlements?currency=IDR&status=paid&limit=2

{
  "data": [
    {
      "uuid": "set_01J9Q7X4B1M0QD",
      "status": "paid",
      "currency": "IDR",
      "exponent": 0,
      "period_start": "2026-08-02T00:00:00Z",
      "period_end": "2026-08-02T23:59:59Z",
      "gross_minor": 8450000,
      "fee_minor": 118300,
      "refund_minor": 200000,
      "net_minor": 8131700,
      "payment_count": 63,
      "paid_at": "2026-08-03T09:12:44Z",
      "bank_reference": "TRF-20260803-0091"
    },
    {
      "uuid": "set_01J9Q0M8R2A7FE",
      "status": "processing",
      "currency": "IDR",
      "exponent": 0,
      "period_start": "2026-08-03T00:00:00Z",
      "period_end": "2026-08-03T23:59:59Z",
      "gross_minor": 3120000,
      "fee_minor": 43680,
      "refund_minor": 0,
      "net_minor": 3076320,
      "payment_count": 24,
      "paid_at": null,
      "bank_reference": null
    }
  ],
  "has_more": true,
  "next_cursor": "set_01J9PQ2K7Y5T3B"
}

Invarian yang selalu berlaku: net_minor = gross_minor − fee_minor − refund_minor. Bila rekonsiliasi kamu menemukan selisih, kirimkan uuid batch beserta request_id.

Sengketa

GET /v1/disputes

Sengketa muncul ketika pemegang instrumen pembayaran menyanggah sebuah transaksi. Selama sengketa berjalan, dana sebesar nominal yang disanggah ditahan dari saldo tersedia.

{
  "data": [
    {
      "uuid": "dsp_01J9QA3F6V2H8N",
      "payment_reference": "pay_01J9Q4M2T7K3XW",
      "status": "under_review",
      "reason": "product_not_received",
      "amount_minor": 150000,
      "currency": "IDR",
      "exponent": 0,
      "evidence_due_at": "2026-08-11T23:59:59Z",
      "opened_at": "2026-08-04T04:00:00Z",
      "resolved_at": null,
      "outcome": null
    }
  ],
  "has_more": false,
  "next_cursor": null
}
StatusArti
needs_responseMenunggu bukti dari merchant sebelum evidence_due_at.
under_reviewBukti sedang ditelaah.
wonSengketa dimenangkan merchant; dana yang ditahan dilepas.
lostSengketa kalah; dana dipindahkan keluar dari saldo merchant.
withdrawnSanggahan ditarik; dana dilepas.

Pengiriman bukti dilakukan melalui portal merchant. Endpoint pengunggahan bukti melalui API belum tersedia.

Kesehatan layanan

GET /v1/health

Satu-satunya endpoint yang tidak memerlukan autentikasi. Dipakai halaman status dan pemantauan kamu sendiri.

{
  "status": "ok",
  "service": "npy-api",
  "version": "0.1.0",
  "environment": "sandbox",
  "dependencies": {
    "core_ledger": "ok",
    "database": "ok"
  },
  "time": "2026-08-04T03:15:00Z"
}

NawaPay berada dalam tahap pengembangan. Seluruh contoh pada dokumentasi ini merujuk pada lingkungan sandbox; sistem belum berizin sebagai penyelenggara jasa pembayaran dan belum memproses transaksi uang sungguhan.

© 2026 NawaPay · docs.nawapay.co.id