NawaPayNawaPay Docs

Idempotensi

Jaringan tidak dapat diandalkan. Permintaan yang kamu kirim bisa saja sudah diterima dan diproses, lalu responsnya hilang di jalan. Tanpa mekanisme pengaman, percobaan ulang akan membuat pembayaran kedua — dan pelanggan tertagih dua kali. Idempotensi menghapus kemungkinan itu.

Aturan di NPY Engine: setiap permintaan yang menggerakkan uang wajib membawa Idempotency-Key. Permintaan tanpa kunci ditolak, bukan diproses diam-diam.

Kapan kunci diperlukan

EndpointKunci
POST /v1/paymentsWajib
POST /v1/refundsWajib
POST /v1/payments/{reference}/cancelWajib
GET /v1/*Tidak perlu — sudah aman diulang

Memilih nilai kunci

  • Format bebas, panjang 8–255 karakter ASCII. UUID versi 4 adalah pilihan yang baik.
  • Satu kunci untuk satu niat bisnis, bukan untuk satu percobaan HTTP. Bangkitkan kunci ketika pesanan dibuat, simpan bersama pesanan itu, lalu pakai kunci yang sama pada setiap percobaan ulang.
  • Jangan membangkitkan kunci baru di dalam blok percobaan ulang. Itu justru menghilangkan perlindungannya.
  • Jangan memakai satu kunci untuk dua operasi berbeda — misalnya nomor pesanan yang sama untuk pembayaran dan untuk refund.
# Benar — kunci melekat pada pesanan, bertahan lintas percobaan
order.idempotency_key = order.idempotency_key or str(uuid.uuid4())
order.save()

for attempt in range(5):
    res = post("/payments", payload, idempotency_key=order.idempotency_key)
    if res.status_code < 500:
        break
    time.sleep(2 ** attempt)

# Salah — kunci baru setiap percobaan; pembayaran ganda bisa terjadi
for attempt in range(5):
    res = post("/payments", payload, idempotency_key=str(uuid.uuid4()))

Apa yang terjadi saat permintaan diulang

Kunci disimpan bersama sidik SHA-256 dari badan permintaan dan respons yang pernah dikembalikan. Ketika kunci yang sama datang lagi:

KeadaanHTTPYang terjadi
Kunci baru 201 Permintaan dieksekusi seperti biasa; hasilnya disimpan.
Kunci sama, badan identik, sudah selesai 200 Respons tersimpan dikembalikan apa adanya, disertai header X-Idempotent-Replay: true. Tidak ada eksekusi ulang, tidak ada uang yang bergerak dua kali.
Kunci sama, badan berbeda 409 IDEMPOTENCY_CONFLICT. Permintaan ditolak — memakai ulang kunci untuk isi yang berbeda hampir selalu berarti ada kekeliruan di sisi pemanggil.
Kunci sama, permintaan pertama masih berjalan 409 IDEMPOTENCY_IN_PROGRESS. Coba lagi setelah beberapa detik; jangan mengubah kuncinya.
Kunci tidak dikirim 422 IDEMPOTENCY_KEY_REQUIRED. Tidak ada yang dieksekusi.
Kunci melanggar format 422 IDEMPOTENCY_KEY_INVALID — terlalu pendek, terlalu panjang, atau mengandung karakter non-ASCII.

Contoh respons konflik

HTTP/1.1 409 Conflict
Content-Type: application/json

{
  "error": {
    "code": "IDEMPOTENCY_CONFLICT",
    "message": "Idempotency-Key sudah dipakai untuk permintaan dengan isi berbeda.",
    "request_id": "req_01J9Q4M2T7K3XW",
    "details": {
      "idempotency_key": "4f8c1f6e-2c1a-4d5b-9d61-3f0b7a2c9e14",
      "first_seen_at": "2026-08-04T02:15:30Z"
    }
  }
}

Contoh respons pengulangan yang berhasil

HTTP/1.1 200 OK
X-Idempotent-Replay: true
Content-Type: application/json

{
  "reference": "pay_01J9Q4M2T7K3XW",
  "status": "pending",
  "amount_minor": 150000,
  "currency": "IDR",
  "reference_id": "ORD-10427",
  "environment": "sandbox",
  "created_at": "2026-08-04T02:15:30Z"
}
Perhatikan status 200, bukan 201. Perbedaan itu memberi tahu kamu bahwa objeknya sudah ada sebelumnya. Perlakukan keduanya sebagai keberhasilan.

Masa simpan kunci

Kunci beserta responsnya disimpan 72 jam sejak permintaan pertama. Setelah itu kunci yang sama dianggap baru dan permintaan akan dieksekusi lagi. Karena itu, percobaan ulang yang tertunda sangat lama sebaiknya diverifikasi dulu dengan GET /v1/payments?reference_id=… sebelum dikirim ulang.

Idempotensi berlapis

Kunci yang kamu kirim melindungi lapisan API. Di dalam sistem, setiap pergerakan dana membawa operation_key tersendiri pada buku besar. Artinya walaupun ada percobaan ulang di dalam sistem — misalnya karena batas waktu jaringan internal — jurnal yang sama tidak akan pernah dicatat dua kali.

Idempotency-Key (kamu -> API)      pesan HTTP tidak dieksekusi dua kali
        │
        └── operation_key (API -> buku besar)   jurnal tidak dicatat dua kali
                    │
                    └── entri debit + kredit    jumlah selalu nol, hanya-tambah

Praktik percobaan ulang yang disarankan

  • Ulangi hanya pada galat jaringan, batas waktu, 429, dan 5xx. Jangan mengulang 4xx lain — hasilnya akan sama.
  • Gunakan jeda menaik dengan sedikit keacakan: 1 dtk, 2 dtk, 4 dtk, 8 dtk, maksimum lima percobaan.
  • Setiap percobaan memakai X-Timestamp dan X-Signature yang baru, tetapi Idempotency-Key yang sama.
  • Bila semua percobaan gagal, jangan menyimpulkan pembayaran gagal. Periksa statusnya lewat GET /v1/payments/{reference} atau tunggu webhook.

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