Paymenku Docs
Transaksi

Membuat transaksi

Satu endpoint untuk semua kanal — field wajib, fee, dan bentuk responsnya.

POST /transaction/create membuat transaksi pembayaran pada satu kanal.

curl https://paymenku.com/api/v1/transaction/create \
  --request POST \
  --header 'Authorization: Bearer sk_live_xxxxxxxxxxxxxxxx' \
  --header 'Content-Type: application/json' \
  --data '{
    "channel_code": "qris",
    "amount": 15000,
    "reference_id": "INV-20261027-001",
    "customer_name": "Budi Santoso",
    "customer_email": "budi@example.com",
    "return_url": "https://tokoanda.com/selesai"
  }'

Field

FieldWajibKeterangan
channel_codeYaKode kanal dari GET /payment-channels
amountYaNominal dasar dalam rupiah
reference_idYaIdentitas unik pesanan di sistem Anda, maks. 255 karakter
customer_nameYaNama pelanggan
customer_emailYaEmail pelanggan
return_urlYaTujuan redirect setelah pembayaran selesai
customer_phoneTidakWajib untuk OVO
order_itemsTidakRincian produk, maksimal 100 baris

Item pesanan berbentuk:

{
  "order_items": [
    { "name": "Paket Internet 30 Hari", "quantity": 1 }
  ]
}

Nominal dan fee

amount yang Anda kirim adalah nominal dasar. Nominal yang akhirnya dibayar pelanggan bergantung pada fee_mode kanal:

fee_modeDibayar pelangganDiterima merchant
merchantamountamount − fee
customeramount + feeamount
splitamount + bagian pelangganamount − bagian merchant

Nilai yang dibebankan ke pelanggan dibulatkan ke rupiah utuh agar halaman bayar dan QR ke bank tidak pernah berbeda.

fee_mode dapat berbeda antar kanal pada merchant yang sama — pada data produksi, bca_va bermode merchant sementara kanal lain customer. Jangan mengasumsikan satu mode untuk semua kanal.

Batas nominal

Minimum global adalah Rp 1.000, tetapi tiap kanal punya batasnya sendiri (VA Rp 10.000, gerai ritel Rp 15.000). Pakai min_amount dan max_amount dari daftar kanal, jangan menanamkan angkanya.

Respons

{
  "status": "success",
  "data": {
    "trx_id": "IDP202610271005522956",
    "reference_id": "INV-20261027-001",
    "amount": "15305.00",
    "status": "pending",
    "pay_url": "https://paymenku.com/pay/IDP202610271005522956",
    "payment_info": {
      "transaction_id": "QRIS-o4fH8BHfTObhwNrG",
      "transaction_status": "pending",
      "qr_url": "https://paymenku.com/api/qris/IDP202610271005522956",
      "qr_string": "QRIS-IDP202610271005522956-15305-ZyyCBJkg",
      "expiration_date": "2026-10-27T10:20:40+07:00"
    }
  }
}
FieldArti
trx_idID Paymenku. Prefix IDP untuk live, SBOX untuk sandbox
amountNominal yang dibayar pelanggan, string desimal
statusSelalu pending saat dibuat
pay_urlHalaman pembayaran Paymenku; aman dibagikan ke pelanggan
payment_infoInstruksi pembayaran; bentuknya berbeda per tipe kanal

Bentuk payment_info per kanal

Bentuknya bergantung tipe kanal dan penyedia:

Tipe kanalField
Virtual Accounttransaction_id, transaction_status, bank, va_number, expiration_date
QRIStransaction_id, transaction_status, qr_url, qr_string, expiration_date
QRIS Customqr_url, qr_string, merchant_name, expiration_date — tanpa transaction_id
E-wallettransaction_id, transaction_status, checkout_url, expiration_date; sebagian kanal menambahkan payment_actions atau checkout_url_app
Gerai riteltransaction_id, transaction_status, store, payment_code, expiration_date

Periksa field yang ada, jangan mengasumsikan satu bentuk. transaction_id tidak selalu tersedia — QRIS Custom tidak mengembalikannya.

Pada transaksi sandbox, payment_info juga memuat sandbox: true dan simulator_url, sedangkan respons tingkat atas memuat sandbox_mode dan sandbox_notice.

Galat yang sering terjadi

HTTPArtiContoh pesan
400Kanal tidak aktif secara globalPayment channel is inactive.
403Kanal belum diaktifkan untuk merchantPayment channel is not enabled for your merchant account.
403KYC belum disetujuiForbidden. KYC verification required before using live API.
422Field wajib kosongValidation failed + errors
422Nominal di luar batasMinimum amount for BCA Virtual Account is Rp 10.000
429Melebihi kuotaRate limit exceeded.
500Penyedia menolak permintaanPesan galat dari penyedia + error_code

Bentuk galat validasi:

{
  "status": "error",
  "message": "Validation failed",
  "errors": {
    "amount": ["validation.required"],
    "reference_id": ["validation.required"],
    "customer_name": ["validation.required"],
    "customer_email": ["validation.required"],
    "return_url": ["validation.required"]
  }
}

Panduan per metode

On this page