Pembayaran, dengan alur yang jelas.
Buat QRIS, tampilkan halaman pembayaran, lalu periksa statusnya dari server Anda. Axiom Payment menggunakan satu merchant utama yang sudah terhubung; Anda tidak perlu menghubungkan merchant sendiri.
x-api-keyAPI memakai JSON melalui HTTPS. Kunci API dan sesi pelanggan hanya dapat mengakses catatan milik akun tersebut. Riwayat merchant utama tidak dibagikan kepada pelanggan.
Panduan ini hanya mencakup QRIS. Tidak ada integrasi virtual account langsung, kartu, atau webhook yang dijanjikan. Perubahan status diperiksa berkala melalui API (polling).
Akun & verifikasi email
Daftar dengan email Anda
Buka halaman pendaftaran. Pilih nama pengguna 3–32 karakter berupa huruf ASCII, angka, atau garis bawah; nama disimpan dalam huruf kecil. Kata sandi harus 12–128 karakter dan maksimal 512 byte.
Masukkan kode verifikasi
OTP enam digit dikirim ke email, berlaku 10 menit, hanya sekali pakai, dan maksimal lima percobaan. Pengiriman ulang tersedia setelah 60 detik. Jika layanan email tidak tersedia, pendaftaran ditolak sementara; kode tidak dianggap sudah terkirim.
Masuk, lalu buat kunci API
Verifikasi berhasil membuka sesi Anda. Untuk masuk kembali, gunakan nama pengguna dan kata sandi di halaman masuk, bukan kunci API. Kunci tidak dibuat otomatis saat mendaftar.
Endpoint akun untuk antarmuka web
Endpoint berikut menggunakan sesi cookie, bukan x-api-key. Permintaan browser yang mengubah data harus berasal dari origin layanan yang sama, menyertakan Content-Type: application/json dan X-Axiom-Request: 1. Gunakan credentials: 'same-origin'; jangan meniru sesi browser untuk integrasi server.
| Endpoint | Isi permintaan / hasil |
|---|---|
GET /api/auth/config | data.registration_available menunjukkan ketersediaan pendaftaran email; otp_expiry_seconds: 600, merchant_mode: "shared". |
POST /api/auth/register | {username, email, password}. HTTP 202 dengan data: {registration_id, email, expires_in, resend_after}; email disamarkan. |
POST /api/auth/resend | {registration_id}. HTTP 202 dengan bentuk hasil pendaftaran yang sama. |
POST /api/auth/verify | {registration_id, otp}; OTP berupa string enam digit. HTTP 201 dengan data.user dan cookie sesi. |
POST /api/auth/login | {username, password}. HTTP 200 dengan data.user dan cookie sesi. |
GET /api/me | HTTP 200 dengan data.user: {id, username, email, created_at}; HTTP 401 jika sesi tidak valid. |
POST /api/auth/logout | {}. Mencabut sesi dan menghapus cookie. |
Hasil sukses dibungkus dengan {success: true, data: …}, kecuali keluar sesi yang hanya memerlukan penanda sukses. Cookie sesi bersifat HttpOnly dan SameSite=Lax; HTTPS diperlukan untuk penggunaan produksi.
Kunci API milik akun Anda
Buka pengelolaan kunci di dasbor, beri nama, lalu buat kunci. Nama berisi 1–60 karakter. Maksimal 10 kunci aktif per akun.
Kunci lengkap hanya ditampilkan sekali. Salin ke pengelola rahasia server saat dibuat. Daftar kunci berikutnya hanya menampilkan metadata dan awalan kunci, bukan rahasianya. Jika kehilangan kunci, buat pengganti lalu cabut kunci lama.
| Endpoint sesi | Perilaku |
|---|---|
GET /api/keys | data.keys memuat id, name, prefix, created_at, last_used_at, revoked_at. Tidak mengembalikan rahasia atau hash. |
POST /api/keys | Kirim {name}. HTTP 201: data.key berisi metadata; data.secret berisi kunci lengkap untuk disimpan sekali. |
DELETE /api/keys/:id | Kirim {}. HTTP 200: {success: true}. Pencabutan langsung berlaku; ID bukan milik akun mendapat 404. |
Pengelolaan kunci hanya memakai sesi pelanggan. Konfirmasikan pencabutan di dasbor; aplikasi yang memakai kunci tersebut langsung kehilangan akses. Rotasi dengan memasang kunci baru di server sebelum mencabut yang lama.
Siapkan integrasi di server
Alamat dasar adalah origin layanan Axiom Payment yang Anda gunakan. Contoh di bawah memakai alamat halaman ini. Simpan kunci dalam variabel lingkungan AXIOM_API_KEY; jangan menaruhnya di kode browser, URL, repositori, atau log.
export AXIOM_BASE_URL='https://pembayaran.example.com'
read -r -s -p 'Kunci API: ' AXIOM_API_KEY
printf '\n'
export AXIOM_API_KEY$env:AXIOM_BASE_URL = 'https://pembayaran.example.com'
$secret = Read-Host 'Kunci API' -AsSecureString
$env:AXIOM_API_KEY = [System.Net.NetworkCredential]::new('', $secret).Password
Remove-Variable secretKedua contoh meminta kunci tanpa menampilkannya dan hanya mengatur lingkungan sesi ini. Untuk produksi, gunakan penyimpanan rahasia layanan Anda; batasi siapa yang dapat membaca lingkungan proses.
Autentikasi HTTP
Kirim x-api-key pada setiap permintaan API dari backend. Integrasi ini tidak memerlukan cookie atau header Origin. Jangan mengirim kunci di parameter query. Respons HTTP 401 berarti kredensial tidak diterima.
curl --silent --show-error --fail-with-body \
"$AXIOM_BASE_URL/api/payments?limit=25&offset=0&status=all" \
-H "x-api-key: $AXIOM_API_KEY"Contoh curl memerlukan curl 7.76 atau lebih baru. Gunakan contoh PowerShell berikut jika terminal Anda bukan Bash.
/create-qrisKunci API / sesiBuat pembayaran QRIS
Kirim nominal rupiah sebagai bilangan bulat 1–10.000.000, bukan desimal. Penyedia menentukan masa berlaku setiap QR; selalu gunakan expires_at dari respons sebagai batas waktu. Masa berlaku umumnya sekitar 15 menit, tetapi bukan jaminan durasi tetap.
Setiap tagihan QRIS dibuat oleh penyedia dan terikat pada order_id/transaction_id penyedia, bukan dicocokkan hanya berdasarkan nominal dan waktu. Beberapa pembayaran aktif boleh memakai nominal yang sama, termasuk milik pelanggan berbeda. Pembayar tetap harus membayar nominal persis; jangan menambahkan atau mengurangi sendiri.
Jika pembuatan belum dapat dikonfirmasi, respons galat memuat data.qris_id dan data.trx_id yang sudah dicadangkan. Simpan ID tersebut, lalu periksa statusnya sebelum membuat pengganti. Layanan tidak menggantinya dengan QR statis atau pencocokan nominal dan waktu.
curl --silent --show-error --fail-with-body \
-X POST "$AXIOM_BASE_URL/create-qris" \
-H "x-api-key: $AXIOM_API_KEY" \
-H 'Content-Type: application/json' \
--data '{"amount":15000}'$payment = Invoke-RestMethod `
-Method Post `
-Uri "$env:AXIOM_BASE_URL/create-qris" `
-Headers @{ 'x-api-key' = $env:AXIOM_API_KEY } `
-ContentType 'application/json' `
-Body (@{ amount = 15000 } | ConvertTo-Json)
$payment.data{
"success": true,
"data": {
"qris_id": "contoh_invoice_bukan_pembayaran",
"trx_id": "AXP-CONTOHBUKANPEMBAYARAN",
"amount": 15000,
"status": "PENDING",
"created_at": "2026-10-08T12:00:00.000Z",
"expires_at": "2026-10-08T12:15:00.000Z",
"qr_url": "https://pembayaran.example.com/qr/contoh_invoice_bukan_pembayaran",
"qris_string": "CONTOH_PAYLOAD_QRIS_BUKAN_UNTUK_DIBAYAR"
}
}Seluruh nilai di respons contoh bersifat ilustratif. qris_string di atas bukan payload QRIS yang valid dan tidak dapat dibayar. API sebenarnya menghasilkan payload QRIS pembayaran Anda.
Field data | Tipe | Keterangan |
|---|---|---|
qris_id | string | ID pembayaran sekaligus kapabilitas akses halaman pembayaran publik. Perlakukan sebagai rahasia. |
trx_id | string | Referensi transaksi untuk pencatatan dan pemeriksaan pemilik. |
amount | number | Nominal rupiah bulat yang harus dibayar persis. |
status | string | PENDING ketika dibuat. |
created_at, expires_at | string | Waktu ISO 8601; contoh berakhiran Z memakai UTC. |
qr_url | string | URL halaman pembayaran, bukan file gambar langsung. |
qris_string | string | Payload QRIS mentah. Dikembalikan saat membuat pembayaran. |
Simpan qris_id dan trx_id di server bersama pesanan Anda. Jika permintaan terputus setelah dikirim, periksa daftar pembayaran sebelum mengulang pembuatan agar tidak membuat tagihan tambahan.
QR & halaman pembayaran
Arahkan pembayar ke qr_url dari respons. Halaman /qr/:qris_id menampilkan nominal, QRIS, sisa waktu, serta pemeriksaan status tanpa meminta akun atau kunci API pembayar.
| Pilihan | Penggunaan |
|---|---|
GET /qr/:qris_id | Halaman pembayaran siap pakai dari qr_url. |
GET /qr/:qris_id?format=raw | Gambar PNG QRIS untuk pembayaran yang masih aktif. Menghasilkan 410 jika QR tidak lagi aktif. |
data.qris_string | Render payload menggunakan pustaka QR di aplikasi Anda. Jangan mengubah isi atau nominalnya. |
Berikan tautan hanya kepada pembayar terkait. Siapa pun yang memegang URL atau qris_id dapat melihat rincian dan status publik pembayaran itu; jangan memublikasikannya dalam analitik, tangkapan layar, atau repositori.
/check-paymentKunci API / sesiPeriksa pembayaran milik akun
Kirim qris_id atau trx_id. Field amount bersifat opsional; jika dikirim, nominal harus sesuai pembayaran. Kredensial hanya mengizinkan akses ke pembayaran pemilik akun. Mengetahui referensi pelanggan lain tidak memberikan akses lewat endpoint ini.
$status = Invoke-RestMethod `
-Method Post `
-Uri "$env:AXIOM_BASE_URL/check-payment" `
-Headers @{ 'x-api-key' = $env:AXIOM_API_KEY } `
-ContentType 'application/json' `
-Body (@{ qris_id = $payment.data.qris_id } | ConvertTo-Json)
$statusVariabel $payment berasal dari contoh pembuatan PowerShell di atas. Untuk memeriksa berdasarkan referensi, ganti isi body menjadi @{ trx_id = $payment.data.trx_id }.
Periksa berkala, bukan webhook
- Periksa dari backend setiap delapan detik sebagai interval awal yang wajar; tunggu satu permintaan selesai sebelum memulai berikutnya.
- Proses pesanan hanya saat respons sukses menunjukkan
paid: truedanstatus: "PAID". Cocokkan ID serta nominal dengan pesanan tersimpan; proses satu kali saja. - Hentikan pemeriksaan rutin ketika
PAIDatauEXPIRED. Jangan meminta pembayar membayar ulang saat status belum pasti. - Pada HTTP 429, perlambat pemeriksaan dan ikuti
Retry-Afterjika tersedia. Pada 503 atau gangguan jaringan, pertahankan status terakhir dan coba kembali dengan jeda; itu bukan bukti belum bayar.
Tidak ada callback atau webhook dalam integrasi ini. Pesan di browser pembayar bukan pengganti pemeriksaan status oleh server Anda.
/api/qr-status/:qris_idTautan rahasiaStatus halaman pembayaran publik
Endpoint ini sengaja tidak memerlukan sesi atau kunci API agar pembayar dapat memeriksa tagihan. qris_id berfungsi sebagai kapabilitas akses: siapa pun yang memilikinya dapat membaca rincian pembayaran itu. ID tidak dikenal menghasilkan 404.
POST /check-payment mengembalikan bentuk respons status yang sama, tetapi tetap memeriksa kepemilikan akun. Contoh berikut menunjukkan pembayaran yang masih menunggu.
{
"success": true,
"paid": false,
"status": "PENDING",
"data": {
"qris_id": "contoh_invoice_bukan_pembayaran",
"trx_id": "AXP-CONTOHBUKANPEMBAYARAN",
"amount": 15000,
"status": "PENDING",
"created_at": "2026-10-08T12:00:00.000Z",
"expires_at": "2026-10-08T12:15:00.000Z",
"qr_url": "https://pembayaran.example.com/qr/contoh_invoice_bukan_pembayaran"
}
}Saat pembayaran terkonfirmasi, paid menjadi true, status menjadi PAID, dan objek transaction memuat identitas, nominal, serta metode pembayaran. transaction_time dapat null bila provider tidak memberikan waktunya; confirmed_at adalah waktu portal mengonfirmasi, bukan waktu transaksi bank. Payload QR mentah tidak disertakan pada pemeriksaan status.
Jika penyedia tidak tersedia, endpoint mengembalikan HTTP 503 dengan success: false; metadata tagihan yang sudah dikenal tetap dapat dikembalikan. Jangan membaca nilai paid: false pada respons galat sebagai kepastian belum membayar.
/api/paymentsKunci API / sesiDaftar pembayaran
Daftar ini hanya memuat pembayaran yang dibuat akun Anda. Gunakan limit dan offset untuk paginasi; filter status menerima all, PENDING, PAID, atau EXPIRED.
curl --silent --show-error --fail-with-body \
"$AXIOM_BASE_URL/api/payments?limit=25&offset=0&status=PENDING" \
-H "x-api-key: $AXIOM_API_KEY"{
"success": true,
"data": {
"payments": [],
"total": 0,
"limit": 25,
"offset": 0
}
}Setiap elemen payments berisi qris_id, trx_id, amount, status, created_at, expires_at, qr_url. total adalah jumlah hasil sesuai filter, bukan jumlah item halaman ini. Naikkan offset sebesar limit untuk halaman berikutnya; berhenti ketika offset berikutnya mencapai total.
Daftar adalah catatan status tersimpan, bukan pengganti pemeriksaan pembayaran ke penyedia. Gunakan pemeriksaan pembayaran untuk mengonfirmasi pelunasan.
/transactionsKunci API / sesiRiwayat transaksi terverifikasi
Hanya transaksi terverifikasi yang sudah cocok dengan pembayaran akun Anda yang ditampilkan. Endpoint ini bukan akses ke seluruh riwayat merchant utama dan tidak menampilkan transaksi pelanggan lain.
Rentang maksimal 31 hari, berdasarkan waktu pembuatan invoice. Hanya invoice berstatus terbayar yang disertakan; waktu transaksi bank dapat tidak tersedia.
| Parameter query | Penggunaan |
|---|---|
startTime | Awal rentang waktu, Unix timestamp dalam detik, bukan milidetik. |
endTime | Akhir rentang waktu dalam detik; tidak boleh sebelum awal. |
pageSize | Bilangan bulat 1–100 untuk jumlah item per halaman; contoh memakai 50. |
from | Offset item berbasis nol, bukan nomor halaman; mulai dari 0, lalu 50, 100, dan seterusnya jika ukuran halaman 50. |
$end = [DateTimeOffset]::UtcNow.ToUnixTimeSeconds()
$start = $end - 86400
$uri = "$env:AXIOM_BASE_URL/transactions?startTime=$start&endTime=$end&pageSize=50&from=0"
Invoke-RestMethod -Uri $uri `
-Headers @{ 'x-api-key' = $env:AXIOM_API_KEY }{
"success": true,
"total": 0,
"from": 0,
"page_size": 50,
"total_amount": "0",
"data": { "transactions": [] }
}Setiap transaksi memuat amount, status, time, issuer, order_id, transaction_id, qris_id, trx_id. Nilai status transaksi adalah settlement; jangan menyamakannya dengan enum status tagihan. time adalah waktu transaksi. total_amount dikembalikan sebagai string; total, from, dan page_size berada di tingkat teratas respons.
Status & penanganan galat
| Status tagihan | Makna |
|---|---|
PENDING | Pembayaran belum terkonfirmasi; QR masih dalam masa berlaku. |
PAID | Transaksi cocok dan pembayaran terkonfirmasi. Jangan memproses pesanan lebih dari sekali. |
EXPIRED | Masa berlaku QR berakhir. Jangan tampilkan QR untuk pembayaran baru. Jika pembayar sudah membayar, simpan bukti dan periksa status; jangan langsung meminta pembayaran ulang. |
| HTTP | Makna / tindakan |
|---|---|
400 | Input tidak valid. Periksa nominal, ID, parameter, dan format JSON. |
401 | Sesi atau kunci tidak valid, kedaluwarsa, atau dicabut; periksa kredensial. Masuk ulang untuk permintaan sesi. |
403 | Permintaan tidak diizinkan. Untuk browser, periksa origin serta header perlindungan permintaan; jangan mencoba melewati batas akses. |
404 | Data tidak ditemukan atau tidak tersedia bagi akun ini. Jangan menebak ID lain. |
409 | Konflik akun, misalnya data pendaftaran yang sudah digunakan. Periksa pesan; jangan mengulang tanpa mengubah kondisi. Nominal pembayaran yang sama bukan konflik. |
410 | Gambar QR mentah tidak lagi aktif; hentikan penampilannya. |
429 | Terlalu banyak permintaan atau batas pengiriman OTP. Tunggu sebelum mencoba kembali. |
503 | Layanan pembayaran atau email sementara tidak tersedia. Ini bukan bukti pembayaran gagal; pertahankan status terakhir. |
{
"success": false,
"message": "Pendaftaran tidak dapat diproses karena konflik akun."
}Periksa kode HTTP dan success, bukan teks message saja. Teks pesan dapat berbeda sesuai penyebab; respons status pembayaran dapat menyertakan metadata tambahan pada galat.
Batas akun, bukan batas merchant
Semua pelanggan memakai merchant utama yang sama, tetapi kunci, tagihan, dan riwayat terverifikasi tetap dipisahkan per akun. Anda tidak memasukkan kredensial merchant dan tidak mendapatkan akses administratif ke merchant tersebut.
- Simpan kunci API hanya di backend. Jangan menaruhnya di penyimpanan browser atau membagikannya kepada pembayar.
- Batasi akses ke
qris_iddan URL halaman pembayaran. Keduanya mengizinkan pembacaan status publik satu pembayaran. - Gunakan HTTPS, lindungi kata sandi serta OTP, dan cabut kunci yang terpapar secepatnya.
- Cocokkan nominal dan identitas pembayaran pada server sebelum memenuhi pesanan. Jangan percaya nominal atau status yang dikirim browser.
- Setiap tagihan terikat pada identitas pesanan atau transaksi penyedia sehingga nominal sama tetap dapat dipisahkan dengan aman. QR tidak dibuat dari penggantian nominal pada QR statis.
- Gangguan penyedia bukan status pembayaran. Jangan mengubah pesanan menjadi gagal hanya karena pemeriksaan tidak tersedia.