AKD Pay Docs
EnglishEN Dashboard
LIVE Dokumentasi ini sama untuk sandbox dan live.

Referensi API

Pembayaran

Membuat pembayaran QRIS atau Virtual Account, membaca statusnya, dan mengulang request dengan aman.

§4 Membuat pembayaran#

POST /v1/payments
Authorization: Bearer <api_key>
Idempotency-Key: order-10023-attempt-1
Content-Type: application/json
{
  "project_id": "8f1c2d3e-4a5b-6c7d-8e9f-0a1b2c3d4e5f",
  "external_order_id": "ORDER-10023",
  "amount": 150000,
  "currency": "IDR",
  "payment_method": "QRIS",
  "metadata": { "customer_id": "C-77" },
  "return_url": "https://shop.example.com/orders/ORDER-10023"
}
Field Wajib Keterangan
project_id ya project milik merchant Anda
external_order_id ya ID pesanan Anda; unik per project. Jangan dipakai ulang untuk pesanan lain
amount ya IDR, bilangan bulat > 0, minimal sesuai metode
currency ya hanya IDR
payment_method ya QRIS atau VIRTUAL_ACCOUNT
metadata tidak objek JSON bebas untuk Anda; ikut dihitung dalam idempotensi
return_url tidak URL https:// untuk kanal yang mengarahkan pembeli kembali
location tidak request_country, customer_country, country_source, timezone untuk analitik

Body dibaca ketat: field yang tidak dikenal ditolak 400 invalid request body.

Respons 200:

{
  "payment_id": "2b8f6c1e-0d5a-4c1b-9f3e-7a6d5c4b3a21",
  "external_order_id": "ORDER-10023",
  "status": "PENDING",
  "amount": 150000,
  "currency": "IDR",
  "payment_method": "QRIS",
  "expires_at": "2026-11-01T03:30:00Z",
  "checkout": {
    "type": "QRIS",
    "qr_string": "00020101021226…"
  },
  "refunded_amount": 0,
  "refund_status": "NONE"
}
  • Untuk VIRTUAL_ACCOUNT, checkout berisi {"type":"VIRTUAL_ACCOUNT","account_number":"…"}.
  • payment_url hanya ada di sandbox (halaman bayar AKD). Di live, tampilkan checkout di aplikasi Anda.
  • expires_at mengikuti masa berlaku pembayaran (saat ini 30 menit). Setelah lewat, pembayaran menjadi EXPIRED dan Anda menerima payment.expired.
  • Simpan payment_id; semua webhook dan pembacaan status memakainya.
  • refunded_amount (total refund yang berhasil) dan refund_status (NONE, PARTIAL, FULL) ada sejak v1.0.3. Refund tidak mengubah status; lihat payment.refunded di bagian 7.

Varian halaman bayar (hanya sandbox): POST /v1/hosted/payments dengan body dan header yang sama mengembalikan payment_url.

Simulasi di sandbox: POST /v1/payments/{payment_id}/simulate (tanpa body) meminta Xendit Test membayar pembayaran PENDING. Jawaban 202 {"status":"simulation_requested"}, atau 200 {"status":"already_paid"}. Webhook payment.paid menyusul beberapa detik kemudian.

§5 Membaca status pembayaran#

GET /v1/payments/{payment_id}
Authorization: Bearer <api_key>

Respons sama dengan pembuatan pembayaran. Pembayaran merchant lain dijawab 404. Gunakan ini bila webhook terlambat atau bila Anda ragu: webhook adalah sinyal, GET /v1/payments/{id} adalah kebenaran.

§10 Idempotensi#

  • Idempotency-Key wajib pada POST /v1/payments dan POST /v1/hosted/payments; tanpa header dijawab 400 missing Idempotency-Key.
  • Key berlaku per merchant. Request ulang dengan key dan body yang sama (project_id, external_order_id, amount, currency, payment_method, metadata, return_url) mengembalikan pembayaran yang sama, termasuk expires_at aslinya. Aman untuk retry setelah timeout.
  • Key yang sama dengan body berbeda dijawab 409 idempotency key conflicts with an existing payment.
  • Gunakan satu key per percobaan pembuatan pembayaran untuk satu pesanan, misalnya <order_id>-<nomor percobaan>. Untuk membuat pembayaran baru bagi pesanan yang sama (misalnya setelah EXPIRED), pakai external_order_id dan key baru.
  • Di sisi webhook, idempotensi Anda adalah deduplikasi X-AKD-Event-ID.