Getting Started
DompetPay Merchant API memungkinkan Anda menerima pembayaran QRIS langsung dari website, bot Telegram/Discord, atau aplikasi Anda sendiri — tanpa pernah menyentuh alamat server backend kami secara langsung.
| 1 | Login / daftar akun merchant di dompetpay.biz.id |
| 2 | Generate API Key dari Settings → Integrasi API |
| 3 | Copy API Key (hanya ditampilkan sekali!) |
| 4 | Atur Callback URL (redirect setelah user bayar) |
| 5 | Atur Webhook URL (notifikasi server-to-server) |
| 6 | Buat QRIS pertama Anda lewat endpoint Create Payment |
| 7 | Terima Webhook saat user membayar |
| 8 | Update status transaksi di sistem Anda sendiri |
https://dompetpay.biz.id/api/v1 — domain WEB kami, BUKAN alamat server backend. Jangan pernah panggil alamat backend (IP/port) secara langsung dari aplikasi Anda; base URL publik ini yang wajib dipakai, dan tetap sama walau backend kami berpindah server kapan pun.
Authentication
Ada dua cara autentikasi tergantung endpoint yang dipanggil:
| Tipe | Header | Dipakai untuk |
|---|---|---|
| API Key | X-API-Key: dpay_live_xxx | Endpoint pembayaran (QRIS, cek status) — dipanggil dari server/bot Anda |
| Bearer Token | Authorization: Bearer <access_token> | Endpoint akun (kelola API Key, profil) — dipanggil setelah merchant login |
Contoh header lengkap untuk memanggil endpoint pembayaran:
API Key
API Key adalah kredensial utama untuk endpoint pembayaran — perlakukan seperti password: jangan taruh di kode frontend/client, jangan commit ke git publik.
Buat API Key baru
Daftar API Key
Cabut API Key
Base URL
Semua endpoint Merchant API memakai satu base URL publik ini:
https://dompetpay.biz.id/api/v1
Backend kami boleh berjalan di server mana pun, port berapa pun (Node.js/NestJS) — merchant TIDAK PERNAH memanggilnya langsung. Semua request selalu lewat domain publik ini, yang diteruskan (reverse proxy) ke backend asli secara server-to-server. Ini praktik umum yang sama dipakai Stripe, Midtrans, dan Xendit, supaya:
- Base URL tetap stabil walau backend dipindah server/port
- Alamat/port backend asli tidak pernah terekspos ke publik
- Bisa ganti provider hosting backend kapan saja tanpa merchant perlu update kode integrasi apa pun
SDK Download
SDK resmi membungkus pemanggilan API + verifikasi signature webhook supaya Anda tidak perlu menulis boilerplate HTTP request sendiri. Isi tiap ZIP: source code, README, contoh integrasi, contoh webhook, contoh callback, contoh error handling, contoh auto order, contoh konfigurasi.
Pakai Node.js SDK di atas untuk sementara — API-nya sama persis.
Pakai PHP SDK di atas untuk sementara, sudah kompatibel Laravel Http:: facade.
Lihat tab kode Python di tiap endpoint sebagai referensi sementara.
Lihat tab kode Go di tiap endpoint sebagai referensi sementara.
Lihat tab kode Java di tiap endpoint sebagai referensi sementara.
Lihat tab kode Flutter di tiap endpoint sebagai referensi sementara.
Pakai Node.js SDK + contoh Telegraf di tab "Telegram Bot" tiap endpoint.
Pakai Node.js SDK + contoh discord.js di tab "Discord Bot" tiap endpoint.
Kami sengaja jujur soal status: Node.js & PHP sudah SDK sungguhan yang bisa langsung dipakai. SDK bahasa lain masih roadmap — tab kode di tiap endpoint di halaman ini tetap 100% akurat dan bisa langsung dipakai walau belum dibungkus jadi package resmi.
QRIS — Create Payment
Generate QRIS baru untuk satu transaksi. Endpoint ini benar-benar memanggil Pakasir dan membuat baris transaksi baru di database — bukan simulasi.
| Field | Tipe | Wajib | Keterangan |
|---|---|---|---|
amount | number | Ya | Nominal dalam Rupiah, minimum 1.000 |
referenceId | string | Ya | ID unik dari sistem Anda (order ID), dipakai mencocokkan pembayaran |
🧪 API Explorer — Coba Langsung (Request Sungguhan)
Form ini benar-benar memanggil POST /api/v1/merchant/payments pakai API Key Anda sendiri — QRIS yang muncul adalah QRIS ASLI dari Pakasir, bukan contoh/simulasi. Baris transaksi baru akan tercatat di dashboard Anda.
Transaction — Cek Status
Cek status transaksi kapan saja (untuk polling dari sisi Anda, walau kami sarankan pakai Webhook supaya real-time tanpa polling).
| Status | Arti |
|---|---|
PENDING | QRIS dibuat, menunggu pembayaran |
PAID | Pembayaran diterima & dikonfirmasi |
EXPIRED | Melewati batas waktu, tidak dibayar |
FAILED | Gagal diproses gateway |
Simulasi Pembayaran Sandbox Only
Endpoint ini SENGAJA disediakan Pakasir khusus mode sandbox, supaya Anda bisa test alur webhook tanpa scan QRIS asli. Otomatis ditolak (403) kalau project Anda sudah mode Live — bukan fitur "simulasi" yang menggantikan pembayaran asli.
Withdraw Roadmap
Withdraw lewat Merchant API (tarik dana hasil penjualan langsung dari kode Anda) belum tersedia — kami jujur soal ini daripada mendokumentasikan endpoint yang belum ada.
Saat ini withdraw hanya tersedia untuk pemilik akun wallet pribadi (bukan endpoint merchant), lewat aplikasi web DompetPay langsung atau bot Telegram pribadi Anda (/withdraw <jumlah> <bank> <no_rekening>), dengan approval manual admin demi keamanan. Endpoint Withdraw untuk merchant ada di roadmap kami berikutnya.
Merchant
Endpoint untuk mengelola pengaturan akun merchant Anda — semuanya butuh Bearer Token (login dulu), bukan API Key.
Atur Webhook URL
Wajib HTTPS. {id} adalah ID API Key (didapat dari response Buat API Key atau Daftar API Key), BUKAN API Key itu sendiri.
User
Ambil data profil akun yang sedang login (Bearer Token) — dipakai kalau Anda membangun dashboard sendiri di atas akun DompetPay pengguna Anda.
Statistics Roadmap
Endpoint ringkasan statistik transaksi (total omzet, grafik harian, dsb) lewat API belum tersedia. Untuk sekarang, data ini bisa dilihat langsung di Dashboard web. Endpoint GET /merchant/statistics ada di roadmap kami.
Webhook
Webhook adalah notifikasi server-to-server yang kami kirim ke Webhook URL Anda setiap ada perubahan status pembayaran — cara paling reliable untuk tahu transaksi sudah dibayar, tanpa perlu polling.
Cara Kerja
- User scan & bayar QRIS
- Pakasir mengonfirmasi pembayaran ke server DompetPay
- Server DompetPay mengirim
POSTke Webhook URL Anda, berisi payload transaksi + header signature - Server Anda WAJIB verifikasi signature sebelum memproses (lihat di bawah)
- Server Anda balas HTTP 200 dalam <10 detik — kalau tidak, kami anggap gagal & retry
Contoh Payload
{
"event": "payment.paid",
"paymentRequestId": "pay_9f21ac...",
"referenceId": "ORDER-1234",
"amount": 50000,
"status": "PAID",
"paidAt": "2026-07-19T10:15:00.000Z"
}
Signature Verification
Tiap request webhook membawa header X-DompetPay-Signature — HMAC-SHA256 dari body mentah (raw, sebelum di-parse JSON), pakai Webhook Secret Anda sebagai key. WAJIB diverifikasi supaya tidak ada pihak lain yang bisa memalsukan notifikasi "sudah dibayar".
import crypto from 'crypto';
app.post('/webhook/dompetpay', express.raw({ type: 'application/json' }), (req, res) => {
const signature = req.headers['x-dompetpay-signature'];
const expected = crypto
.createHmac('sha256', process.env.DOMPETPAY_WEBHOOK_SECRET)
.update(req.body) // raw body, BUKAN hasil JSON.parse
.digest('hex');
if (signature !== expected) return res.status(401).send('Invalid signature');
const payload = JSON.parse(req.body);
if (payload.event === 'payment.paid') {
// update status order di database Anda pakai payload.referenceId
}
res.status(200).send('OK');
});
Retry & Timeout
| Timeout tunggu response | 10 detik |
| Percobaan ulang | 3x (1 menit, 5 menit, 15 menit setelah gagal) |
| Dianggap sukses | Response HTTP 2xx apa pun |
| Dianggap gagal | Non-2xx, timeout, atau koneksi refused |
🧪 Webhook Tester
Kirim webhook percobaan SUNGGUHAN (bukan simulasi lokal) ke URL Anda, lengkap signature HMAC asli — supaya Anda bisa test endpoint penerima webhook tanpa perlu bayar QRIS beneran dulu.
Callback
Beda dengan Webhook (server-to-server, diam-diam di belakang layar), Callback URL adalah halaman yang dilihat USER setelah selesai membayar — mirip halaman "Terima kasih" di e-commerce.
- Menerima callback: user diarahkan browser mereka ke Callback URL Anda dengan query string
?referenceId=ORDER-1234&status=PAID - Validasi: JANGAN percaya query string ini untuk update status final (bisa dimanipulasi user) — cukup pakai untuk tampilan "Pembayaran berhasil!", validasi SUNGGUHAN tetap lewat Webhook server-to-server
- Update status: selalu jadikan Webhook sebagai satu-satunya sumber kebenaran status transaksi, Callback murni untuk UX
Error Code
| HTTP | Kode | Pesan | Solusi |
|---|---|---|---|
| 400 | BAD_REQUEST | Body/parameter tidak valid | Cek field wajib & tipe data sesuai tabel di tiap endpoint |
| 401 | UNAUTHORIZED | API Key/token tidak ada atau tidak valid | Cek header X-API-Key/Authorization terkirim benar |
| 403 | FORBIDDEN | Tidak punya akses ke resource ini | Pastikan ID milik akun Anda sendiri, atau role cukup (endpoint admin) |
| 404 | NOT_FOUND | Resource tidak ditemukan | Cek ID benar, transaksi belum expired dari sistem |
| 409 | CONFLICT | Data sudah ada/duplikat | Mis. email/referenceId sudah dipakai sebelumnya |
| 429 | TOO_MANY_REQUESTS | Rate limit terlampaui | Lihat Rate Limit, tunggu sampai window reset |
| 500 | INTERNAL_ERROR | Kesalahan tak terduga di server | Coba lagi; kalau berulang, hubungi Support dengan request ID |
Rate Limit
Berlaku per API Key / per akun, bukan per IP — jadi aman dipakai di belakang proxy/load balancer manapun.
Sisa kuota & waktu reset dikirim di header response tiap request (X-RateLimit-Remaining, X-RateLimit-Reset) — cek header response API Explorer di atas untuk lihat contoh nyatanya.
Changelog
Dokumentasi v2 + perbaikan infrastruktur
Base URL Merchant API resmi jadi /api/v1. Bot login & bot admin pindah ke long polling (tidak butuh HTTPS/domain publik backend lagi). OTP email sekarang benar-benar terkirim lewat SMTP.
Login Google via JWKS
Verifikasi token Google tidak lagi butuh service account di backend — cukup project ID publik.
Payment Gateway: Pakasir (QRIS)
QRIS live lewat Pakasir, withdraw manual dengan approval admin via bot Telegram.