Bagian 3–5

Payin

Membuat payin, membaca instruksi QRIS/VA, mengambil gambar QR, daftar, dan status.

Membuat payin

POST/api/v1/payinspayins:writeRespons 202 Accepted

API menerima permintaan pembuatan instruksi; respons ini belum membuktikan pelanggan sudah membayar.

FieldWajibKeterangan
referenceYaNomor pesanan unik merchant.
amount / currencyYaNominal rupiah dan IDR.
channelYaQRIS_GOPAY, QRIS_QOIN, VA_QOIN, atau BANK_TRANSFER.
bank_codeYa*Wajib untuk VA_QOIN dan BANK_TRANSFER; ambil dari GET /channels. Tidak dikirim untuk QRIS.
customer_referenceTidakID pelanggan di sistem merchant, maksimum 64 karakter.
metadataTidakInformasi tambahan sesuai batas pada Format data.
Request
POST /api/v1/payins
Authorization: Bearer <api_key>
Idempotency-Key: order-0001-create
Content-Type: application/json

{
  "reference": "ORDER-0001",
  "amount": "100000",
  "currency": "IDR",
  "channel": "QRIS_GOPAY",
  "customer_reference": "CUST-100",
  "metadata": { "order_id": "ORDER-0001" }
}
Response 202
{
  "data": {
    "id": "pin_example_001",
    "reference": "ORDER-0001",
    "status": "QUEUED",
    "status_url": "/api/v1/payins/pin_example_001",
    "created_at": "2026-10-15T05:00:00Z"
  },
  "request_id": "req_example_001"
}
Instruksi dibuat secara asinkron. Simpan id dan reference, lakukan polling GET detail sampai instruksi tersedia. Jangan meminta pembuatan QR baru berulang kali ketika status QUEUED/CREATING. Untuk pergantian metode pembayaran, buat pesanan/payin baru hanya setelah risiko pembayaran instruksi lama ditangani.

Field tidak dikenal ditolak. Expiry ditetapkan kanal/provider dan dikembalikan pada detail. Client tidak boleh mengasumsikan durasi QR atau VA selalu sama. Kanal yang tidak aktif atau batas nominal tidak sesuai akan ditolak sebelum intent diterima.

Detail payin

GET/api/v1/payins/{id}payins:readRespons 200

payment_instruction bernilai null selama instruksi belum tersedia. Fee dan net pada transaksi yang belum dibayar merupakan estimasi dari kebijakan saat pembuatan.

Response 200
{
  "data": {
    "id": "pin_example_001",
    "reference": "ORDER-0001",
    "status": "AWAITING_PAYMENT",
    "channel": "QRIS_GOPAY",
    "amount": "100000",
    "fee": "1500",
    "net": "98500",
    "currency": "IDR",
    "settlement_status": "NOT_ELIGIBLE",
    "resource_version": 2,
    "payment_instruction": {
      "type": "QR",
      "image_path": "/api/v1/payins/pin_example_001/qr",
      "expires_at": "2026-10-15T05:15:00Z"
    },
    "created_at": "2026-10-15T05:00:00Z",
    "updated_at": "2026-10-15T05:00:20Z",
    "paid_at": null
  },
  "request_id": "req_example_002"
}

Bentuk payment_instruction untuk VA dan bank

VA_QOIN
{
  "type": "VA",
  "bank_code": "BANK_CODE",
  "account_number": "880012345678",
  "account_name": "NAMA PEMBAYARAN",
  "amount": "100000",
  "currency": "IDR",
  "expires_at": "2026-10-15T06:00:00Z"
}
BANK_TRANSFER
{
  "type": "BANK_TRANSFER",
  "bank_code": "BANK_CODE",
  "account_number": "1234567890",
  "account_name": "NAMA REKENING ANTARAPAY",
  "amount": "100000",
  "currency": "IDR",
  "payment_reference": null,
  "expires_at": "2026-10-15T06:00:00Z"
}
Contoh bank_code, nomor rekening, nama, ID, dan waktu adalah ilustrasi. Tampilkan nilai hasil API tanpa mengganti rekening atau menambahkan kode unik sendiri. Jika payment_reference tersedia, sampaikan instruksinya kepada pelanggan. Jangan mengasumsikan bukti unggahan pelanggan berarti pembayaran sukses.

Usulan fee pada contoh: 1,5% payin berhasil, dipotong dari hak merchant. Gross Rp100.000 → fee Rp1.500 → net Rp98.500. Gunakan nilai fee/net dari respons sebagai acuan integrasi; konfirmasi tarif efektif dan pembebanan saat aktivasi.

Mengambil gambar QR

GET/api/v1/payins/{id}/qrpayins:readRespons 200 image/png

Respons sukses berupa binary PNG dengan Content-Type: image/png dan Cache-Control: private, no-store; endpoint ini tidak mengembalikan envelope JSON ketika berhasil.

Contoh request
curl "$ANTARAPAY_BASE_URL/api/v1/payins/pin_example_001/qr" \
  -H "Authorization: Bearer $ANTARAPAY_API_KEY" \
  -H "Accept: image/png" --output qris.png

Backend merchant mengambil image dan menyajikannya melalui endpoint milik merchant yang mengotorisasi pesanan pelanggan. API key tidak dikirim ke browser. Error tetap JSON:

HTTPCodeArti
409QR_NOT_READYInstruksi belum siap; lanjutkan polling detail.
409INVALID_STATETransaksi tidak lagi menunggu pembayaran.
410QR_EXPIREDQR sudah kedaluwarsa.
422CHANNEL_NOT_QRKanal payin bukan QRIS.

Daftar payin

GET/api/v1/payins?reference=ORDER-0001&limit=50payins:read

Filter opsional: reference, channel, status, from, to, cursor, limit. Filter tanggal menggunakan created_at. Pencarian reference bersifat exact match. List berisi ringkasan tanpa payment_instruction; ambil detail untuk instruksi.

Response 200
{
  "data": [
    {
      "id": "pin_example_001",
      "reference": "ORDER-0001",
      "status": "SUCCEEDED",
      "channel": "QRIS_GOPAY",
      "amount": "100000",
      "fee": "1500",
      "net": "98500",
      "currency": "IDR",
      "settlement_status": "COMPLETED",
      "created_at": "2026-10-15T05:00:00Z"
    }
  ],
  "pagination": { "next_cursor": null, "has_more": false },
  "request_id": "req_example_003"
}

Status payin

StatusTindakan client
QUEUED / CREATINGTampilkan proses menyiapkan pembayaran; tunggu atau polling.
AWAITING_PAYMENTTampilkan instruksi dan expiry; tunggu konfirmasi server.
SUCCEEDEDPembayaran terverifikasi; proses pesanan secara idempotent.
EXPIRED / FAILEDHentikan tampilan instruksi lama; baca error/detail bila ada.
NEEDS_REVIEWTampilkan sedang diperiksa; jangan menganggap berhasil atau membuat retry buta.

Berhasil bukan berarti saldo tersedia

GET payin SUCCEEDED dipetakan menjadi completed pada webhook, tetapi saldo belum tentu masuk Active Balance: settlement_status dapat WAITING_FUNDS. Payin EXPIRED dapat menjadi SUCCEEDED setelah pembayaran terlambat diverifikasi; proses webhook completed dengan resource_version lebih baru.

Polling usulan 2 detik dengan backoff hingga 30 detik; hormati rate limit. Status antrean dan review tidak dikirim sebagai webhook final.