Modern QR-based payment solution for Indonesia
QRIS (Quick Response Code Indonesian Standard) is a unified QR code standard in Indonesia that enables customers to make payments by scanning a QR code with their mobile banking apps. It's a modern, fast, and secure payment method supported by all major Indonesian banks.
The QRIS API allows you to:
Customers scan and pay instantly from their mobile banking app
Works with BRI, BNI, MANDIRI, BCA, PERMATA, CIMB, and all major banks
Get instant notifications when customers complete their payments
RSA 2048-bit encryption and signature verification for all transactions
Here's how the QRIS payment process works:
Include your API credentials in every request header:
-H "X-API-Client: your_client_key"
-H "X-API-Secret: your_secret_key"
-H "Content-Type: application/json"
$headers = [
'X-API-Client' => 'your_client_key',
'X-API-Secret' => 'your_secret_key',
'Content-Type' => 'application/json'
];
const headers = {
'X-API-Client': 'your_client_key',
'X-API-Secret': 'your_secret_key',
'Content-Type': 'application/json'
};
Send a POST request to create a new QRIS payment:
curl -X POST https://cicis.online/api/qris/checkout \
-H "Content-Type: application/json" \
-H "X-API-Client: your_client_key" \
-H "X-API-Secret: your_secret_key" \
-d '{
"customer_name": "Budi Santoso",
"customer_email": "budi@example.com",
"customer_phone": "081234567890",
"amount": 150000,
"currency": "IDR",
"payment_method": "qris",
"description": "Pembayaran VPN Premium"
}'
# Response includes:
# {
# "invoice_id": "GM-1705763403",
# "qr_url": "https://cicis.online/qr/generate/GM-1705763403"
# }
use Illuminate\Support\Facades\Http;
$response = Http::withHeaders([
'X-API-Client' => 'your_client_key',
'X-API-Secret' => 'your_secret_key'
])->post('https://cicis.online/api/qris/checkout', [
'customer_name' => 'Budi Santoso',
'customer_email' => 'budi@example.com',
'amount' => 150000,
'payment_method' => 'qris'
]);
$data = $response->json();
$invoiceId = $data['invoice_id'];
$qrUrl = "https://cicis.online/qr/generate/{$invoiceId}";
const response = await fetch('https://cicis.online/api/qris/checkout', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-API-Client': 'your_client_key',
'X-API-Secret': 'your_secret_key'
},
body: JSON.stringify({
customer_name: 'Budi Santoso',
customer_email: 'budi@example.com',
amount: 150000,
payment_method: 'qris'
})
});
const data = await response.json();
const invoiceId = data.invoice_id;
const qrUrl = `https://cicis.online/qr/generate/${invoiceId}`;
Show the QR code image to your customer. The image is now served from cicis domain:
<img src="https://cicis.online/qr/generate/GM-1705763403"
alt="Scan to Pay"
style="width: 300px; height: 300px;" />
Endpoint: GET https://cicis.online/qr/generate/{invoice_id}
Parameter: invoice_id - The invoice ID returned from the checkout response
Returns: PNG image (300x300px) - Can be cached and reused
Poll the API or use webhooks to check if payment was completed:
curl https://cicis.online/api/qris/status/GM-1705763403 \
-H "X-API-Client: your_client_key" \
-H "X-API-Secret: your_secret_key"
$response = Http::withHeaders([
'X-API-Client' => 'your_client_key',
'X-API-Secret' => 'your_secret_key'
])->get('https://cicis.online/api/qris/status/GM-1705763403');
if ($response->json()['status'] === 'SETTLED') {
// Payment received - activate service
}
const response = await fetch('https://cicis.online/api/qris/status/GM-1705763403', {
headers: {
'X-API-Client': 'your_client_key',
'X-API-Secret': 'your_secret_key'
}
});
const data = await response.json();
if (data.status === 'SETTLED') {
// Payment received - activate service
}
| Status | Description | What to do |
|---|---|---|
| PENDING | Payment just created, waiting for customer action | Display QR code to customer |
| CREATED | QR generated, waiting for payment | Awaiting customer scan and payment |
| PROCESSING | Payment is being processed by bank | Wait for settlement confirmation |
| ✓ SETTLED | Payment received successfully | ✅ Activate service immediately |
| ✓ SUCCESS | Payment confirmed | ✅ Activate service immediately |
| FAILED | Payment failed or rejected | Offer customer to retry payment |
| EXPIRED | Payment expired after 24 hours | Create new payment request |
| CANCELLED | Payment cancelled by customer | Ask customer to retry |
| Parameter | Type | Required | Description |
|---|---|---|---|
| customer_name | string | REQUIRED | Full name of customer (max 255 characters) |
| customer_email | string | REQUIRED | Valid email address for notifications |
| customer_phone | string | OPTIONAL | Phone number (max 20 characters) |
| amount | decimal | REQUIRED | Amount in IDR (minimum: 1,000 | maximum: 100,000,000) |
| currency | string | OPTIONAL | Currency code (default: IDR) |
| payment_method | string | REQUIRED | Must be exactly 'qris' |
| description | string | OPTIONAL | Order description or note (max 500 characters) |
| metadata | object | OPTIONAL | Custom data to pass through the payment (JSON object) |
Successful QRIS payment creation response:
{
"success": true,
"invoice_id": "GM-1705763403",
"order_id": 12345,
"customer_name": "Budi Santoso",
"customer_email": "budi@example.com",
"amount": 150000,
"currency": "IDR",
"payment_method": "qris",
"qr_url": "https://cicis.online/qr/generate/GM-1705763403",
"qr_content": "00020126360014ID.CO.BRI.BRIMO...",
"status": "CREATED",
"created_at": "2026-01-20T10:30:45Z",
"expires_at": "2026-01-21T10:30:45Z"
}
Webhooks are the recommended approach for production systems. They provide instant notifications when payments are received, without the overhead of continuous polling. This results in better performance and lower latency.