pixpay

Dokumentasi API

Semua yang kamu butuhkan untuk menerima pembayaran QRIS di aplikasimu — dari aktivasi hingga live di produksi.

Base URL/api/v1

pixpay bertindak sebagai jembatan antara QR pembayaran kamu dan sistem deteksi notifikasi. Dana selalu diterima langsung ke rekening e-wallet atau bank milikmu.

Mulai Pakai pixpay

Ikuti langkah-langkah ini agar sistem QRIS kamu siap menerima pembayaran nyata.

1

Aktifkan Akun & Pilih Paket

Masuk ke pixpay dan pilih paket yang sesuai skala bisnismu: Trial untuk coba-coba, atau Pro tanpa batas.

2

Daftarkan QRIS Kamu

Upload foto atau file QR statis dari e-wallet yang kamu gunakan (DANA, OVO, GoPay, ShopeePay, dll.) lewat menu QRIS di dashboard. Setelah diverifikasi, kamu akan mendapat ID QRIS unik.

3

Ambil API Key

Buka menu API Keys di dashboard, buat key baru, dan catat License Key serta Webhook Secret yang dihasilkan.

Kirim x-license-key di setiap header request. Webhook Secret hanya untuk server-side — jangan ditaruh di kode frontend yang bisa dilihat publik.
4

Pasang Aplikasi Android

Install APK pixpay, aktifkan izin baca notifikasi, masukkan License Key, lalu pilih QRIS yang akan digunakan untuk mendeteksi pembayaran masuk.

Agar pembayaran selalu terdeteksi real-time: set baterai ke Tanpa Batasan, aktifkan Autostart, dan jangan swipe-close aplikasi.
5

Hubungkan ke Aplikasimu

Panggil endpoint /generate/qris dari server-side aplikasimu, tampilkan qr_string sebagai gambar QR ke pembeli, lalu pantau status pembayaran via polling /generate/check-status.

Selalu gunakan totalAmount (bukan originalAmount) saat useUniqueCode aktif agar pembayaran terdeteksi dengan tepat.

Referensi API

Semua endpoint menggunakan header x-license-key sebagai autentikasi. Tidak perlu Bearer token untuk integrasi sisi server.

POST/generate/qrisBuat Transaksi QRIS

Membuat sesi pembayaran QRIS baru. Respons berisi qr_string yang siap dirender jadi gambar QR, dan transactionId untuk memantau status pembayaran.

Headers
x-license-keyLicense key dari dashboard (wajib)
content-typeapplication/json
Request Body
{
  "id": "qris-uuid",
  "amount": 10000,
  "useUniqueCode": true,
  "packageIds": [
    "id.dana"
  ],
  "expiredInMinutes": 15
}
Response
{
  "status": 200,
  "data": {
    "qr_string": "000201010211...",
    "transactionId": "5fd73e8b-169a-4453-b11d-ac4bcbbc0d10",
    "originalAmount": 10000,
    "totalAmount": 10003,
    "uniqueNominal": 3,
    "useUniqueCode": true,
    "packageIds": [
      "id.dana"
    ]
  }
}

Catatan penting

• id — ID QRIS dari dashboard (yang sudah diverifikasi), bukan ID paket atau kategori.

• useUniqueCode — tambahkan angka unik ke nominal agar transaksi yang berjalan bersamaan tidak saling tertukar.

• Tampilkan totalAmount ke pembeli. Jika pembeli membayar originalAmount saat useUniqueCode aktif, pembayaran bisa tidak terbaca oleh sistem.

• packageIds — daftar package name aplikasi e-wallet yang dipantau. Contoh DANA: ["id.dana"].

POST/generate/v2/qrisTransaksi QRIS v2

Versi yang lebih fleksibel dengan pilihan tipe QR (dynamic/static) dan metode pembayaran (qris/ewallet). Cocok untuk skenario pembayaran yang lebih beragam.

Headers
x-license-keyLicense key dari dashboard (wajib)
content-typeapplication/json
Request Body
{
  "qr_id": "qris-uuid",
  "amount": 10000,
  "useUniqueCode": true,
  "packageIds": [
    "id.dana"
  ],
  "expiredInMinutes": 15,
  "qrType": "dynamic",
  "paymentMethod": "qris",
  "useQris": true
}
Response
{
  "status": 200,
  "data": {
    "transactionId": "f6a1bc8e-1c2a-4c95-8df8-55e7c9a1cd32",
    "originalAmount": 10000,
    "totalAmount": 10003,
    "uniqueNominal": 3,
    "qrType": "dynamic",
    "paymentMethod": "qris",
    "qr_string": "000201010211...",
    "status": "pending"
  }
}

Catatan penting

• qrType "dynamic" menghasilkan QR yang terikat ke satu transaksi. "static" memakai QRIS statis milikmu dengan nominal yang diinjeksi.

• paymentMethod "ewallet" + useQris false: tidak ada QR yang dibuat — pixpay hanya mendeteksi masuknya saldo dari notifikasi e-wallet.

• Gunakan qr_id (bukan id) di v2.

POST/generate/check-statusCek Status Pembayaran

Ambil status terkini dari sebuah transaksi. Polling endpoint ini setiap beberapa detik sebagai cara termudah untuk mendeteksi pembayaran berhasil.

Headers
x-license-keyLicense key dari dashboard (wajib)
Request Body
{
  "transactionId": "5fd73e8b-169a-4453-b11d-ac4bcbbc0d10"
}
Response
{
  "status": 200,
  "data": {
    "transactionId": "5fd73e8b-169a-4453-b11d-ac4bcbbc0d10",
    "amount": 10003,
    "status": "paid",
    "expiredAt": "2026-03-28T12:00:00.000Z"
  }
}

Catatan penting

• Status yang mungkin: pending → menunggu bayar, paid → lunas, expired → melewati batas waktu, cancel → dibatalkan.

• Pembayaran yang masuk setelah expired tetap bisa diterima tergantung e-wallet pembeli — gunakan expiry hanya sebagai batas logika order-mu.

POST/generate/cancel-statusBatalkan Transaksi

Tandai transaksi sebagai dibatalkan. Berguna untuk membersihkan order yang sudah tidak relevan dari sisi bisnis.

Headers
x-license-keyLicense key dari dashboard (wajib)
Request Body
{
  "transactionId": "5fd73e8b-169a-4453-b11d-ac4bcbbc0d10"
}
Response
{
  "status": 200,
  "message": "Transaksi dibatalkan",
  "data": {
    "transactionId": "5fd73e8b-169a-4453-b11d-ac4bcbbc0d10",
    "status": "cancel",
    "canceledAt": "2026-03-28T12:00:00.000Z"
  }
}

Catatan penting

• Pembatalan hanya memengaruhi status di sistem pixpay. Jika pembeli sudah mentransfer sebelum dibatalkan, dana tetap masuk ke rekeningmu.

GET/generate/listDaftar Pembayaran

Tarik daftar seluruh transaksi milikmu dengan dukungan filter, pencarian, dan paginasi.

Headers
x-license-keyLicense key dari dashboard (wajib)
Query Params
statusFilter status: paid | cancel | expired | pending (opsional)
pageNomor halaman, default: 1
limitJumlah data per halaman, default: 10
sortUrutan data: newest (default) | oldest
searchPencarian berdasarkan transaction ID atau QR string
Response
{
  "status": 200,
  "data": {
    "page": 1,
    "limit": 5,
    "total": 12,
    "pages": 3,
    "items": [
      {
        "transactionId": "TXN-A1",
        "amount": 50000,
        "status": "paid",
        "packageIds": [
          "id.dana"
        ],
        "expiredAt": "2026-03-28T12:00:00Z"
      }
    ]
  }
}
POST/generate/list-deleteHapus Riwayat

Bersihkan riwayat transaksi — bisa satu per satu, sekelompok ID, atau semua sekaligus.

Headers
x-license-keyLicense key dari dashboard (wajib)
Request Body
// Hapus satu transaksi:
{ "transactionId": "TXN123456" }

// Hapus beberapa sekaligus:
{ "transactionIds": ["TXN123456", "TXN654321"] }

// Bersihkan semua riwayat:
{ "clearAll": true }
Response
{
  "status": 200,
  "message": "Riwayat pembayaran dihapus",
  "data": {
    "transactionId": "TXN123456"
  }
}

Catatan penting

• Penghapusan massal dengan clearAll: true bersifat permanen dan tidak dapat dikembalikan.

POST/generate/confirm-paymentKonfirmasi Pembayaran

Dipakai oleh Android Notification Listener untuk menandai transaksi pending menjadi paid secara otomatis berdasarkan notifikasi pembayaran masuk.

Headers
x-license-keyLicense key dari dashboard (wajib)
content-typeapplication/json
Request Body
{
  "amount": 10003,
  "packageName": "id.dana",
  "source_app": "id.dana",
  "listener_name": "Pixpay Android Listener"
}
Response
{
  "status": 200,
  "data": {
    "transactionId": "5fd73e8b-169a-4453-b11d-ac4bcbbc0d10",
    "status": "paid",
    "amount": 10003,
    "matchedBy": "amount+packageName"
  }
}

Catatan penting

• permission API key yang direkomendasikan: transaction:update (key lama dengan transaction:create tetap didukung).

• amount harus sama dengan totalAmount transaksi (termasuk kode unik jika useUniqueCode aktif).

• Jika listener webhook aktif, pixpay akan meneruskan callback ke Webhook URL setelah status berubah.

GET/generate/listener-configKonfigurasi Listener

Mengambil konfigurasi listener berdasarkan API key untuk sinkronisasi aplikasi Android (aplikasi yang dipantau dan status aktif listener).

Headers
x-license-keyLicense key dari dashboard (wajib)
Response
{
  "status": 200,
  "data": {
    "monitored_apps": [
      "id.dana",
      "com.gojek.gopay"
    ],
    "is_active": true
  }
}

Catatan penting

• Jika listener belum dibuat di dashboard, endpoint akan mengembalikan not found.

• Gunakan endpoint ini saat startup aplikasi Android untuk memastikan konfigurasi selalu terbaru.

Webhook & Security

Gunakan Webhook URL untuk menerima callback pembayaran. Verifikasi header X-PixPay-Signature dengan Webhook Secret agar callback tidak bisa dipalsukan.

Header Callback

X-PixPay-Signature = HMAC SHA256 dari raw body, dihitung dengan Webhook Secret.

X-License-Key = tetap dikirim untuk kompatibilitas sistem lama.

Checklist Implementasi Aman

• Simpan Webhook Secret di server env var, jangan di aplikasi frontend/mobile.

• Hitung signature dari raw body asli (bukan JSON yang sudah di-serialize ulang).

• Bandingkan signature dengan timing-safe compare, tolak jika tidak cocok.

• Balas HTTP 2xx jika payload valid; gunakan 4xx saat signature invalid.

Node.js (Express) — Verify Signature
import express from 'express'
import crypto from 'crypto'

const app = express()

app.use(express.json({
  verify: (req, _res, buf) => {
    req.rawBody = buf
  }
}))

const WEBHOOK_SECRET = process.env.WEBHOOK_SECRET || ''

app.post('/webhook/pixpay', (req, res) => {
  const signature = req.header('X-PixPay-Signature') || ''

  const expected = crypto
    .createHmac('sha256', WEBHOOK_SECRET)
    .update(req.rawBody || Buffer.from(''))
    .digest('hex')

  const a = Buffer.from(signature, 'utf8')
  const b = Buffer.from(expected, 'utf8')

  if (a.length !== b.length || !crypto.timingSafeEqual(a, b)) {
    return res.status(401).json({ error: 'invalid signature' })
  }

  // proses payload di sini
  return res.status(200).json({ ok: true })
})
Go (net/http) — Verify Signature
package main

import (
  "crypto/hmac"
  "crypto/sha256"
  "encoding/hex"
  "io"
  "net/http"
  "os"
)

func webhookHandler(w http.ResponseWriter, r *http.Request) {
  secret := os.Getenv("WEBHOOK_SECRET")
  signature := r.Header.Get("X-PixPay-Signature")

  body, err := io.ReadAll(r.Body)
  if err != nil {
    http.Error(w, "bad request", http.StatusBadRequest)
    return
  }

  mac := hmac.New(sha256.New, []byte(secret))
  mac.Write(body)
  expected := hex.EncodeToString(mac.Sum(nil))

  if !hmac.Equal([]byte(signature), []byte(expected)) {
    http.Error(w, "invalid signature", http.StatusUnauthorized)
    return
  }

  w.WriteHeader(http.StatusOK)
  w.Write([]byte(`{"ok":true}`))
}
curl — Uji Signature Valid
WEBHOOK_SECRET='ganti-dengan-webhook-secret-kamu'
PAYLOAD='{"transactionId":"TXN-123","amount":10003,"status":"paid","packageName":"id.dana","source_app":"id.dana"}'

SIG=$(printf '%s' "$PAYLOAD" | openssl dgst -sha256 -hmac "$WEBHOOK_SECRET" -hex | sed 's/^.* //')

curl -X POST 'https://endpoint-kamu.com/webhook/pixpay'   -H 'Content-Type: application/json'   -H "X-PixPay-Signature: $SIG"   -d "$PAYLOAD"
curl — Uji Signature Invalid
# Contoh signature salah (receiver seharusnya balas 401/403)
PAYLOAD='{"transactionId":"TXN-123","amount":10003,"status":"paid"}'

curl -X POST 'https://endpoint-kamu.com/webhook/pixpay'   -H 'Content-Type: application/json'   -H 'X-PixPay-Signature: invalid-signature'   -d "$PAYLOAD"

QR Code Kustom

Jadikan QR pembayaranmu lebih menarik dengan menggabungkan qr_string dari API pixpay dengan generator QR visual ini.

https://larabert-qrgen.hf.space/v1/create-qr-code?size=500x500&style=2&color=000000&data=[DATA_KAMU]

Parameter
sizeDimensi gambar output. Contoh: 400x400, 500x500
style1 = kotak klasik, 2 = sudut membulat, 3 = titik-titik
colorWarna utama QR dalam format hex tanpa tanda #. Contoh: 000000, 1a56db
dataTeks atau URL yang dienkode ke dalam QR. Gunakan encodeURIComponent() agar karakter khusus tidak merusak URL.
Coba Sekarang

Generated URL

https://larabert-qrgen.hf.space/v1/create-qr-code?size=400x400&style=2&color=000000&data=https%3A%2F%2Fpixpay.app

Preview (Style 1 / 2 / 3)
QR Style 1Style 1
QR Style 2Style 2
QR Style 3Style 3

Tip: isi data dengan qr_string dari respons API pixpay untuk menampilkan QR pembayaran yang lebih menarik ke customer.

Praktik Terbaik

Hal-hal yang perlu diperhatikan agar integrasi pixpay berjalan stabil dan aman di lingkungan produksi.

1

Lindungi Kredensial API

License key dan webhook secret adalah kunci aksesmu — jangan taruh di kode frontend atau repositori publik. Gunakan environment variable di sisi server.

2

Aktifkan Kode Unik

Saat useUniqueCode aktif, pixpay menambahkan angka kecil ke nominal agar setiap pembayaran bisa dibedakan. Pastikan kamu menampilkan totalAmount ke pembeli, bukan originalAmount.

3

Pahami Masa Berlaku

expiredInMinutes mengontrol kapan QR kamu kedaluwarsa di sisi UX. Namun pembayaran yang masuk setelah waktu habis bisa tetap diterima — gunakan status sebagai penjaga logika order, bukan waktu.

4

Jaga Aplikasi Tetap Aktif

Untuk deteksi pembayaran real-time, set baterai Android ke Tanpa Batasan, aktifkan Autostart, dan pinned di Recent Apps. Jika aplikasi tertutup, notifikasi tidak terbaca.

5

Alur Pembayaran yang Benar

① Buat transaksi dari server → ② Simpan transactionId dan totalAmount → ③ Render qr_string sebagai gambar QR → ④ Polling status tiap 3 detik → ⑤ Tandai order selesai saat status paid.

6

Polling yang Hemat Sumber Daya

Hentikan polling segera setelah status paid, expired, atau cancel. Interval di bawah 2 detik tidak diperlukan dan boros bandwidth. Gunakan exponential backoff saat koneksi bermasalah.