Skip to content

QRIS Codes

Manage the merchant’s registered static QRIS — the source every dynamic QRIS in Transactions is generated from.

MethodPathPurpose
POST/v1/qris-codesUpload and validate a static QRIS (image or raw string)
GET/v1/qris-codesList registered QRIS codes (limit, offset)
DELETE/v1/qris-codes/:idSoft-delete a QRIS code (history is preserved)

POST /v1/qris-codesmultipart/form-data:

FieldRequiredNotes
qris_stringone of these twoRaw EMV QRIS string
qris_imageone of these twoImage file; the QR is decoded server-side

Exactly one of qris_string/qris_image must be given. The decoded/given string is validated against the EMV QRIS structure (required tags, CRC) before being stored — 400 INVALID_QRIS_FORMAT if it fails. label is not a request field — it’s read straight from the merchant name already embedded in the QRIS (tag 59), so it always matches what the QR itself says.

Scoped by mode like everything else: which X-API-Key (api_key_live/api_key_sandbox) you authenticate with decides whether the upload is registered live or sandbox, and GET/DELETE only see codes in that same mode — a live key can’t list, generate from, or delete a sandbox code and vice versa. A sandbox upload additionally has its CRC deliberately corrupted before storage, so every QR generated from it — live never touched — fails EMV validation and can’t be paid for real, even if scanned. See Known limitations.

DELETE is a soft delete: the code is hidden from GET/generate but any transaction history already generated from it is preserved untouched.

POST /v1/qris-codes:

{
"success": true,
"message": "QRIS successfully uploaded and validated",
"data": { "id": "37242f6d-90cc-4950-826e-3d92258bf416", "label": "Contoh Toko", "created_at": "2026-07-08T09:34:35.920Z" }
}

GET /v1/qris-codes:

{
"success": true,
"data": [
{ "id": "37242f6d-90cc-4950-826e-3d92258bf416", "label": "Contoh Toko", "provider": "ID.CO.GOJEK.WWW", "created_at": "2026-07-08T09:34:35.920Z" }
],
"pagination": { "total": 1, "limit": 20, "offset": 0 }
}

provider is a best-effort acquirer identifier read straight from the QRIS payload itself (not mapped to a brand name) — null if it can’t be parsed out.

DELETE /v1/qris-codes/:id:

{ "success": true, "message": "QRIS code deleted", "data": { "id": "37242f6d-90cc-4950-826e-3d92258bf416", "label": "Contoh Toko" } }

List endpoints return data plus pagination: { total, limit, offset } (default limit 20, max 100). See Errors for what a failed request looks like.

Continue to Transactions