Logo Cutiezy
Cutiezy Portal / Dokumentasi
PT CUTIEZY ID NUSANTARA Production
PT CUTIEZY ID NUSANTARA Official API Docs

QRIS Dinamis & Payment Gateway API

Generate kode QRIS dinamis ber-nominal otomatis dengan timer kedaluwarsa, URL redirect callback, polling cek status pembayaran realtime, dan notifikasi Webhook instan.

โšก Aturan Biaya Kuota API & Ketentuan Paket Langganan

  • Syarat Paket Langganan: Layanan QRIS Dinamis mewajibkan akun memiliki langganan aktif Paket P3 (1 QRIS Toko - Rp 20.000 / bln) atau Paket P5 (Multi-QRIS Bebas / Banyak Toko - Rp 35.000 / bln). Jika akun belum berlangganan atau paket telah kedaluwarsa, sistem akan menolak permintaan dengan response 403 PLAN_P3_REQUIRED.
  • Biaya Kuota API Pembuatan QRIS: Setiap request pembuatan QRIS dinamis yang berhasil (status 201 Created) memotong 6 Hit Point dari saldo kuota akun Anda.
  • Pengecekan Status Realtime (Polling): Endpoint pengecekan status pembayaran via token (/qris/check-status/{token}) adalah 0 Hit Point (GRATIS) dan tidak memotong kuota sama sekali.
  • Whitelist IP Server: Pastikan IP VPS / server aplikasi Anda sudah didaftarkan pada Slot IP Dashboard untuk menghindari penolakan akses 403 IP_NOT_ALLOWED.

Alur Integrasi & Siklus Pembayaran

1 Upload QRIS Sumber

User login ke web panel lalu mengunggah gambar QRIS statis toko (GoPay, BRI Merchant, DANA Bisnis, Mandiri Livin', ShopeePay, dll) pada menu QRIS Dinamis. Sistem memvalidasi CRC dan menyimpan payload EMVCo sebagai sumber default.

2 Generate Tagihan API

Aplikasi/bot Anda mengirim HTTP POST ke /api/qris/create dengan nominal transaksi, batas waktu (menit), dan URL redirect. Sistem membuat QRIS dinamis instan dan mengembalikan payload mentah, gambar PNG, token, serta link checkout.

3 Pembayaran Pelanggan

Pelanggan memindai QRIS dinamis menggunakan e-wallet atau mobile banking apa saja dengan nominal yang sudah terkunci otomatis, atau diarahkan langsung ke halaman pembayaran siap pakai Cutiezy (/pay/{token}).

4 Verifikasi Otomatis

Sistem mencocokkan mutasi transaksi masuk secara realtime. Anda dapat memverifikasi via polling berkala /qris/check-status/{token} atau menerima notifikasi instan via HTTP POST Webhook event qris.payment.success.

Keamanan

Autentikasi API

Header / Query

Setiap request ke endpoint pembuatan QRIS dinamis wajib menyertakan API Key akun Anda. Disarankan menggunakan header:

X-API-Key: YOUR_API_KEY
Content-Type: application/json
Accept: application/json

Fallback juga didukung via header Authorization: Bearer YOUR_API_KEY atau query parameter URL ?apikey=YOUR_API_KEY.

Endpoint 1

1. Generate QRIS Dinamis (Create Invoice)

POST

Membuat kode QRIS dinamis dengan nominal transaksi tertentu dari sumber QRIS yang tersimpan di akun Anda.

Method

POST

URL Endpoint
https://api.cutiezy.id/api/qris/create
Alias URL yang didukung: https://api.cutiezy.id/api/qris/generate
Parameter Request (JSON Body / Form-Urlencoded):
Parameter Tipe Wajib Keterangan
amount integer Wajib Nominal pembayaran rupiah, bilangan bulat > 0 (contoh: 25000). Alias: total.
source_id integer Opsional ID spesifik sumber QRIS toko milik Anda jika memiliki banyak QRIS (contoh: 7). Jika dikosongkan, otomatis menggunakan QRIS default akun Anda. Alias: qris_id.
expiry_minutes integer Opsional Durasi masa aktif tagihan dalam menit. Pilihan durasi yang didukung: 3, 5, 10, 12, atau 15 menit (default: 15 menit). Menggunakan arsitektur Smart Active Window untuk verifikasi mutasi presisi secara realtime dan hemat daya. Alias: expired_minutes, valid_minutes, minutes.
redirect_url string Opsional URL redirect pengalihan otomatis pembeli setelah pembayaran berhasil di halaman checkout (contoh: https://tokoanda.com/order/inv-123/success). Alias: return_url, callback_url, link.
Contoh Response Sukses ยท HTTP 201 Created:
{
  "success": true,
  "ok": true,
  "message": "QRIS dinamis berhasil dibuat.",
  "hit_points_deducted": 6,
  "data": {
    "id": 142,
    "token": "4f9b8c2d1e0a3f5b7c9d1e2f3a4b5c6d",
    "source_id": 7,
    "label": "Toko Utama Cabang 1",
    "merchant_name": "CUTIEZY STORE",
    "amount": 25000,
    "qris_string": "00020101021226590014ID.LINKAJA.WWW01189360001400000000000208123456785204581253033605405250005802ID5913CUTIEZY STORE6007JAKARTA62070703A016304ABCD",
    "image_url": "https://api.cutiezy.id/public/generated/qris/20261011/qris_4f9b8c2d1e0a3f5b7c9d1e2f3a4b5c6d.png",
    "payment_url": "https://api.cutiezy.id/pay/4f9b8c2d1e0a3f5b7c9d1e2f3a4b5c6d",
    "checkout_url": "https://api.cutiezy.id/qris/pay/4f9b8c2d1e0a3f5b7c9d1e2f3a4b5c6d",
    "redirect_url": "https://tokoanda.com/order/inv-123/success",
    "expiry_minutes": 15,
    "expires_at": "2026-10-11 11:15:00",
    "status": "pending"
  },
  "remaining_quota": {
    "type": "membership",
    "remaining": 494,
    "limit": 500
  }
}

Penjelasan Field Output Data:

  • token: Token acak unik 32 karakter hexadesimal sebagai kunci identifikasi tagihan pembayaran. Digunakan pada endpoint cek status dan URL halaman checkout.
  • qris_string: String payload mentah standar EMVCo QRIS dinamis (Tag 01 = '12' Dynamic, Tag 54 = nominal, dengan CRC16 checksum valid). Dapat langsung dirender di frontend Anda menggunakan library barcode/QR.
  • image_url: URL file gambar PNG QRIS resolusi tinggi yang siap ditampilkan ke pembeli atau dicetak.
  • payment_url / checkout_url: Halaman web pembayaran siap pakai dari Cutiezy yang dapat langsung dibuka oleh pelanggan di browser handphone atau desktop.
  • expires_at: Tanggal dan jam kedaluwarsa tagihan sesuai parameter expiry_minutes.
  • hit_points_deducted: Jumlah hit point yang terpotong pada pembuatan QRIS ini (6 hit point).
Endpoint 2

2. Cek Status Pembayaran Realtime (Polling)

GET / POST

Memeriksa apakah tagihan QRIS dengan {token} tertentu sudah dibayar oleh pelanggan atau belum. Endpoint ini otomatis mencocokkan mutasi transaksi merchant secara realtime dan tidak memotong kuota Hit Point (0 Hit Point / GRATIS).

Method

GET / POST

URL Endpoint
https://api.cutiezy.id/qris/check-status/{token}
Ganti {token} dengan token 32 karakter dari respon pembuatan QRIS.
Response Jika Pembayaran Diterima (Status: paid)
{
  "ok": true,
  "status": "paid",
  "paid_at": "2026-10-11 10:45:12",
  "amount": 25000,
  "mutation_ref": "202610110987654321",
  "redirect_url": "https://tokoanda.com/order/inv-123/success",
  "message": "Pembayaran berhasil diverifikasi via mutasi!"
}
Response Jika Belum Dibayar (Status: pending)
{
  "ok": true,
  "status": "pending",
  "remaining_seconds": 840,
  "redirect_url": "https://tokoanda.com/order/inv-123/success",
  "message": "Menunggu pembayaran dari pelanggan..."
}
Response Jika Waktu Habis (Status: expired)
{
  "ok": true,
  "status": "expired",
  "remaining_seconds": 0,
  "redirect_url": "https://tokoanda.com/order/inv-123/success",
  "message": "Waktu pembayaran telah habis."
}
Response Jika Dibatalkan (Status: canceled)
{
  "ok": true,
  "status": "canceled",
  "remaining_seconds": 0,
  "redirect_url": "https://tokoanda.com/order/inv-123/failed",
  "message": "Tagihan QRIS telah dibatalkan."
}
Response Jika Token Tidak Ada ยท HTTP 404
{
  "ok": false,
  "status": "not_found",
  "message": "Tagihan QRIS tidak ditemukan."
}
Endpoint 3

3. Pembatalan Tagihan QRIS (Cancel Invoice)

POST

Membatalkan tagihan QRIS berstatus pending sebelum batas waktu kedaluwarsa habis. Gunakan endpoint ini saat pembeli membatalkan pesanan di kasir / checkout website Anda, mengganti nominal, atau menutup keranjang belanja. Pembatalan ini sekaligus mengistirahatkan gateway pemantau sehingga sistem tetap efisien dan cepat.

Method

POST

URL Endpoint
https://api.cutiezy.id/api/qris/cancel
Alias URL yang didukung via URI token: https://api.cutiezy.id/api/qris/cancel/{token}
Parameter Request (JSON Body / Form-Urlencoded):
Parameter Tipe Wajib Keterangan
token string Wajib* Token 32 karakter unik tagihan QRIS yang hendak dibatalkan. *Wajib jika memanggil POST /api/qris/cancel. Jika memanggil /api/qris/cancel/{token}, token dibaca otomatis dari path URL.
Response Berhasil Dibatalkan ยท HTTP 200 OK
{
  "success": true,
  "ok": true,
  "status": "canceled",
  "token": "4f9b8c2d1e0a3f5b7c9d1e2f3a4b5c6d",
  "amount": 25000,
  "redirect_url": "https://tokoanda.com/order/inv-123/failed",
  "message": "Tagihan QRIS berhasil dibatalkan."
}
Response Jika Sudah Lunas ยท HTTP 400
{
  "success": false,
  "ok": false,
  "status": "paid",
  "message": "Tagihan sudah dibayar dan tidak dapat dibatalkan."
}
Endpoint 4

4. Halaman Checkout Pembayaran Publik (No-Code UI)

GET (Browser / WebView)

Jika Anda tidak ingin membangun tampilan antarmuka kasir pembayaran sendiri, cukup arahkan pembeli ke link checkout publik Cutiezy. Halaman ini aman, responsif untuk layar handphone, dan dapat dibuka oleh siapa saja tanpa autentikasi.

Method

GET

URL Halaman Checkout
https://api.cutiezy.id/pay/{token}
Alias URL yang didukung: https://api.cutiezy.id/qris/pay/{token}
Fitur Otomatis di Halaman Checkout Cutiezy:
  • Menampilkan nama toko/merchant, total tagihan rupiah pas, dan gambar barcode QRIS.
  • Timer countdown realtime sesuai durasi expiry_minutes.
  • Fitur polling background otomatis yang mengecek status pembayaran setiap beberapa detik.
  • Jika pembayaran berhasil dan Anda menyertakan redirect_url, pembeli akan otomatis dialihkan ke website Anda dalam 2 detik.
Webhook Callback

Notifikasi Webhook Realtime (qris.payment.success)

Panduan Lengkap Webhook →

Selain menggunakan polling status, sistem Cutiezy otomatis mengirimkan HTTP POST Webhook ke server Anda seketika saat pembayaran QRIS dinamis berhasil diverifikasi mutasi rekening merchant.

Contoh Payload Webhook Event qris.payment.success:
{
  "event": "qris.payment.success",
  "token": "4f9b8c2d1e0a3f5b7c9d1e2f3a4b5c6d",
  "amount": 25000,
  "merchant_name": "CUTIEZY STORE",
  "qris_source_id": 7,
  "user_id": 12,
  "paid_at": "2026-10-11 10:45:12",
  "reference": "202610110987654321",
  "customer": "ANDI PRATAMA",
  "redirect_url": "https://tokoanda.com/order/inv-123/success"
}

Setiap pengiriman webhook dilengkapi header X-Cutiezy-Signature menggunakan tanda tangan kriptografi HMAC SHA-256 dari raw body JSON menggunakan Secret Key webhook Anda. Selengkapnya lihat di Dokumentasi Webhook Realtime.

Status Error

Daftar Kode Error Resmi Sistem

HTTP Response
HTTP Code Kode Error (error) Penyebab / Keterangan Solusi
401 UNAUTHORIZED / INVALID_API_KEY Header API Key tidak dikirim atau API Key salah. Pastikan menyertakan header X-API-Key: czw_... yang valid.
403 IP_NOT_ALLOWED Alamat IP pengirim belum di-whitelist di akun Anda. Daftarkan IP server Anda di menu Slot IP Dashboard.
403 PLAN_P3_REQUIRED Akun belum memiliki paket langganan aktif minimal Paket P3. Beli Paket P3 (Rp 20.000/bln) di menu Billing / Paket.
409 QRIS_SOURCE_REQUIRED User belum mengunggah gambar QRIS statis sumber di panel web. Buka menu QRIS Dinamis di web dan unggah QRIS toko Anda.
422 INVALID_QRIS_REQUEST Nominal amount kosong, bernilai <= 0, atau format angka salah. Kirimkan nominal bilangan bulat positif (contoh: 25000).
429 QUOTA_EXCEEDED Saldo kuota Hit Point akun Anda habis (dibutuhkan 6 Hit Point). Lakukan perpanjangan paket atau isi kuota di menu Billing.
429 RATE_LIMITED Terlalu banyak permintaan API dalam waktu singkat. Tunggu beberapa saat (lihat nilai retry_after) sebelum mencoba lagi.
503 QRIS_GENERATOR_UNAVAILABLE Modul generator QR atau ekstensi PHP GD server sedang bermasalah. Hubungi tim dukungan teknis Cutiezy jika kendala berlanjut.
Code Snippets

Contoh Kode Integrasi

Salin dan sesuaikan contoh kode di bawah untuk bahasa pemrograman yang Anda gunakan.

๐Ÿ“Ÿ cURL (Terminal / Bash)

# 1. Generate QRIS Dinamis Rp 25.000 (Pilihan durasi: 3, 5, 10, 12, atau 15 menit)
curl -X POST "https://api.cutiezy.id/api/qris/create" \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -d '{
    "amount": 25000,
    "expiry_minutes": 15,
    "redirect_url": "https://tokoanda.com/order/123/success"
  }'

# 2. Cek Status Pembayaran Realtime (Polling)
curl -X GET "https://api.cutiezy.id/qris/check-status/YOUR_TRANSACTION_TOKEN" \
  -H "Accept: application/json"

# 3. Batalkan Tagihan QRIS (Cancel Invoice)
curl -X POST "https://api.cutiezy.id/api/qris/cancel" \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"token": "YOUR_TRANSACTION_TOKEN"}'

๐Ÿ˜ PHP Native (cURL)

<?php
$apiKey = 'YOUR_API_KEY';

// 1. Buat Tagihan QRIS Dinamis (Pilihan durasi: 3, 5, 10, 12, atau 15 menit)
function createQrisInvoice($apiKey, $amount, $expiryMinutes = 15, $redirectUrl = null) {
    $url = 'https://api.cutiezy.id/api/qris/create';
    $payload = [
        'amount' => (int)$amount,
        'expiry_minutes' => $expiryMinutes,
    ];
    if ($redirectUrl) {
        $payload['redirect_url'] = $redirectUrl;
    }

    $ch = curl_init($url);
    curl_setopt_array($ch, [
        CURLOPT_POST => true,
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_TIMEOUT => 20,
        CURLOPT_HTTPHEADER => [
            'X-API-Key: ' . $apiKey,
            'Content-Type: application/json',
            'Accept: application/json',
        ],
        CURLOPT_POSTFIELDS => json_encode($payload),
    ]);

    $response = curl_exec($ch);
    curl_close($ch);
    return json_decode($response, true);
}

// 2. Fungsi Cek Status Pembayaran (Polling 0 Hit Point)
function checkQrisStatus($token) {
    $url = 'https://api.cutiezy.id/qris/check-status/' . rawurlencode($token);
    $ch = curl_init($url);
    curl_setopt_array($ch, [
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_TIMEOUT => 15,
        CURLOPT_HTTPHEADER => ['Accept: application/json'],
    ]);
    $response = curl_exec($ch);
    curl_close($ch);
    return json_decode($response, true);
}

// 3. Batalkan Tagihan QRIS (Cancel Invoice)
function cancelQrisInvoice($apiKey, $token) {
    $url = 'https://api.cutiezy.id/api/qris/cancel';
    $ch = curl_init($url);
    curl_setopt_array($ch, [
        CURLOPT_POST => true,
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_TIMEOUT => 15,
        CURLOPT_HTTPHEADER => [
            'X-API-Key: ' . $apiKey,
            'Content-Type: application/json',
            'Accept: application/json',
        ],
        CURLOPT_POSTFIELDS => json_encode(['token' => $token]),
    ]);
    $response = curl_exec($ch);
    curl_close($ch);
    return json_decode($response, true);
}

// Contoh Penggunaan:
$result = createQrisInvoice($apiKey, 25000, 15, 'https://tokoanda.com/order/success');
if (!empty($result['ok'])) {
    $data = $result['data'];
    echo "QRIS Dibuat!\n";
    echo "Token Tagihan : " . $data['token'] . "\n";
    echo "URL Gambar    : " . $data['image_url'] . "\n";
    echo "Link Checkout : " . $data['payment_url'] . "\n";
} else {
    echo "Gagal: " . ($result['message'] ?? 'Error');
}
?>

โšก JavaScript / Node.js (Fetch)

const API_KEY = "YOUR_API_KEY";

// 1. Generate QRIS Dinamis (Pilihan durasi: 3, 5, 10, 12, atau 15 menit)
async function generateQris(amount, expiryMinutes = 15, redirectUrl = null) {
  const res = await fetch("https://api.cutiezy.id/api/qris/create", {
    method: "POST",
    headers: {
      "X-API-Key": API_KEY,
      "Content-Type": "application/json",
      "Accept": "application/json"
    },
    body: JSON.stringify({
      amount: amount,
      expiry_minutes: expiryMinutes,
      redirect_url: redirectUrl
    })
  });
  return await res.json();
}

// 2. Polling Status Realtime (Panggil setiap 3 detik)
async function pollQrisStatus(token) {
  const res = await fetch(`https://api.cutiezy.id/qris/check-status/${token}`, {
    headers: { "Accept": "application/json" }
  });
  return await res.json();
}

// 3. Batalkan Tagihan QRIS (Cancel Invoice)
async function cancelQrisInvoice(token) {
  const res = await fetch("https://api.cutiezy.id/api/qris/cancel", {
    method: "POST",
    headers: {
      "X-API-Key": API_KEY,
      "Content-Type": "application/json",
      "Accept": "application/json"
    },
    body: JSON.stringify({ token })
  });
  return await res.json();
}

// Contoh Eksekusi:
(async () => {
  const invoice = await generateQris(25000, 15, "https://tokoanda.com/success");
  if (invoice.ok) {
    console.log("QRIS Berhasil Dibuat:", invoice.data.token);
    console.log("URL Gambar:", invoice.data.image_url);
    console.log("Link Bayar:", invoice.data.payment_url);

    // Mulai polling cek status
    const timer = setInterval(async () => {
      const check = await pollQrisStatus(invoice.data.token);
      console.log("Status:", check.status);
      if (check.status === "paid") {
        clearInterval(timer);
        console.log("โœ… Lunas! Mutasi Ref:", check.mutation_ref);
      } else if (check.status === "expired" || check.status === "canceled") {
        clearInterval(timer);
        console.log("โŒ Tagihan selesai dengan status:", check.status);
      }
    }, 3000);
  }
})();

๐Ÿ Python (requests)

import requests
import time

API_KEY = "YOUR_API_KEY"

# 1. Generate QRIS Dinamis (Pilihan durasi: 3, 5, 10, 12, atau 15 menit)
def create_qris(amount, expiry_minutes=15, redirect_url=None):
    url = "https://api.cutiezy.id/api/qris/create"
    headers = {
        "X-API-Key": API_KEY,
        "Content-Type": "application/json",
        "Accept": "application/json"
    }
    payload = {
        "amount": amount,
        "expiry_minutes": expiry_minutes,
        "redirect_url": redirect_url
    }
    res = requests.post(url, json=payload, headers=headers, timeout=20)
    return res.json()

# 2. Cek Status Polling
def check_status(token):
    url = f"https://api.cutiezy.id/qris/check-status/{token}"
    res = requests.get(url, timeout=15)
    return res.json()

# 3. Batalkan Tagihan QRIS (Cancel Invoice)
def cancel_qris(token):
    url = "https://api.cutiezy.id/api/qris/cancel"
    headers = {
        "X-API-Key": API_KEY,
        "Content-Type": "application/json",
        "Accept": "application/json"
    }
    res = requests.post(url, json={"token": token}, headers=headers, timeout=15)
    return res.json()

# Contoh Penggunaan:
invoice = create_qris(25000, 15, "https://tokoanda.com/order/success")
if invoice.get("ok"):
    data = invoice["data"]
    token = data["token"]
    print("QRIS Siap!")
    print(f"Token: {token}")
    print(f"Gambar: {data['image_url']}")
    print(f"Link Checkout: {data['payment_url']}")

    # Polling status loop
    while True:
        status = check_status(token)
        if status.get("status") == "paid":
            print(f"โœ… Lunas via mutasi: {status.get('mutation_ref')}")
            break
        elif status.get("status") in ["expired", "canceled"]:
            print(f"โŒ Tagihan selesai: {status.get('status')}")
            break
        print("Menunggu pembayaran...")
        time.sleep(3)
else:
    print("Gagal membuat QRIS:", invoice.get("message"))
Toko Fisik & Kios

Solusi Siap Pakai: Mode Kasir POS & Standee Meja

Tanpa Perlu Coding

Selain integrasi via REST API, Cutiezy menyediakan antarmuka khusus siap pakai bagi merchant toko fisik, UMKM, cafe, dan kasir:

๐Ÿช Mode Kasir POS

Buka /qris/kasir di tablet, iPad, atau HP kasir. Dilengkapi Numpad sentuh, tombol nominal cepat, hitung mundur, audio lonceng sukses, dan fullscreen.

๐Ÿ–จ๏ธ Standee Meja Siap Cetak

Akses /qris/stand/{id} untuk mencetak standee akrilik (ukuran A5/A6/A4) berlogo resmi QRIS & GPN yang siap ditempel di meja/kasir toko.

๐Ÿ“ฑ Kios Mandiri Pembeli

Saat pembeli men-scan standee di meja, URL /kios/{id} terbuka di HP pembeli. Pembeli tinggal mengetik nominal belanja, dan QRIS dinamis langsung muncul di layar HP mereka.