"QRIS" Payment Method
Payment Method Definition
displayedPaymentMethods
displayedPaymentMethodsdefines which payment methods are shown to the payer on the Hosted Checkout form. It is the Hosted Checkout alternative topaymentMethodName, which is used in Host-to-Host integrations.Provide this parameter in
paymentIntent.formDetails.displayedPaymentMethods.To make QRIS available on the checkout form, include the
QRISvalue. IfQRISis the only value in the array, the payment-method selection step is skipped and the payer is taken directly to the QRIS flow.
Payment Method Features
| Feature | Value |
|---|---|
| Country | Indonesia |
| Processing Currencies | IDR |
| Payments | Yes |
| -- Min per transaction amount | 1 000 IDR, unless another limit is defined in your contract |
| -- Max per transaction amount | 10 000 000 IDR, unless another limit is defined in your contract |
| Refunds | Yes — full amount only |
| -- Partial refunds | No |
| Chargebacks | No |
IDR is a zero-decimal currency: send whole numbers (e.g.
150000), not150000.00.
Workflow
- Create an Intent with
useCheckoutFormset totrueand includeQRISinpaymentIntent.formDetails.displayedPaymentMethods. - Receive the Hosted Checkout URL in
paymentIntent.additionalData.url. - Redirect the payer to the returned URL.
- The platform creates a QRIS payment and displays its QR code and copyable QRIS payload on the checkout form. No information is collected from the payer — there is no data-entry step.
- The payer scans the QR code, or copies the QRIS payload, in any Indonesian banking or e-wallet application and confirms the payment.
- Wait for the payment webhook. Treat the payment as successful only when its status becomes
CAPTURED.
The synchronous Intent response confirms that the Hosted Checkout session was created. It does not create a successful QRIS payment and does not confirm that the payer completed the transfer.
The initial response contains the URL of the Carusell Hosted Checkout form, not the QRIS payload. QRIS payment data is created and displayed later, inside the checkout flow.
Create Intent Request
Specifics
- We use one unified Intent creation request for all supported payment methods: POST /processing/api/v1/intents.
- The overall structure is the same, but some fields change depending on the integration type: Host-to-Host or Hosted Checkout.
- For Host-to-Host, complete the
Paymentobject.- For Hosted Checkout, complete the
PaymentIntentobject.- For QRIS Hosted Checkout:
- Set
useCheckoutFormtotrue.- Provide
paymentIntentinstead ofpayments.- Include
QRISinpaymentIntent.formDetails.displayedPaymentMethods.- Do not send
paymentMethodName,paymentInstrument, or QRISincomingDetailsin the initial Intent request.- The checkout form collects no data from the payer. For QRIS it only creates and displays the QRIS payment (QR code and copyable payload) — there is no name, document, email, or phone entry step.
paymentIntent.submittedAmount.currencycan beIDRor another supported currency when FX conversion is enabled. The QRIS payment itself is authorised inIDR.- Provide
paymentIntent.webhookUrland wait for payment status updates instead of treating the Intent creation response as confirmation of payment.
'Intent' vs 'Payment' vs 'PaymentIntent'
Some objects and parameters in this API may appear similar, but they represent different concepts and are used in different integration scenarios. The explanation below clarifies the purpose of each term.
| Term | Meaning |
|---|---|
| Intent |
|
| Payment |
|
| PaymentIntent |
|
Request/Response Description
Request Description
{
"clientReferenceId": "order-20260909-0001",
"useCheckoutForm": true,
"paymentIntent": {
"formDetails": {
"displayedPaymentMethods": ["QRIS"],
"backToStoreRedirectUrl": "https://merchant.example.com/orders/order-20260909-0001"
},
"submittedAmount": {
"value": 150000,
"currency": "IDR"
},
"description": "Order 20260909-0001",
"webhookUrl": "https://merchant.example.com/webhooks/payments"
}
}Top-Level Request Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
clientReferenceId | String | Required | Order or Intent reference in the merchant system. |
useCheckoutForm | Boolean | Conditional | Optional in the general Intent contract. Must be set to true when using Hosted Checkout. |
paymentIntent | Object | Conditional | Optional in the general Intent contract. Must be provided when using Hosted Checkout. Do not send a payments array for the flow described on this page. |
description | String | Optional | Intent-level order description. |
merchant | Object | Optional | Merchant information. Provide it when merchant details must be associated with the Intent or displayed on the checkout form according to your configuration. |
paymentIntent
| Parameter | Type | Required | Description |
|---|---|---|---|
formDetails | Object | Required | Checkout-form configuration. Required for Carusell Hosted Checkout. |
submittedAmount | Object | Required | Order amount and submitted currency. |
authorizationAmount | Object | Optional | Authorisation amount and currency when these are supplied explicitly under an agreed FX flow. For QRIS, the authorisation currency must be IDR. Do not send this object unless the FX flow is enabled for you. |
description | String | Optional | Order title or payment reason. Recommended: a meaningful value improves payer recognition and reconciliation. |
webhookUrl | String | Required | HTTPS URL to which payment status change webhooks for payments created within the Intent will be sent. |
formDetails
| Parameter | Type | Required | Description |
|---|---|---|---|
template | String | Optional | Name of a checkout template configured for the settlement account. If omitted, the default template is used. |
displayedPaymentMethods | Array of Strings | Conditional | Include QRIS to make QRIS available on the checkout form. If only QRIS is provided, the payment-method selection step is skipped. If omitted, the form shows the methods available under the account configuration. |
backToStoreRedirectUrl | String | Optional | HTTPS URL to which the payer can return after leaving or completing the checkout flow. The Back to Store control is unavailable when this parameter is omitted. |
submittedAmount
| Parameter | Type | Required | Description |
|---|---|---|---|
value | Number | Required | Submitted order amount. IDR is zero-decimal — use whole numbers (e.g. 150000). The applicable QRIS limit is normally from 1 000 to 10 000 000 IDR unless another limit is defined in your contract. |
currency | String | Required | Submitted currency in ISO 4217 alpha-3 format. Use IDR when no FX conversion is required. Another supported currency may be used when FX is enabled. |
authorizationAmount
| Parameter | Type | Required | Description |
|---|---|---|---|
value | Number | Required | Explicit QRIS authorisation amount. Supply it only as part of an agreed FX flow. |
currency | String | Required | Authorisation currency in ISO 4217 alpha-3 format. For QRIS, the value must be IDR. |
merchant
| Parameter | Type | Required | Description |
|---|---|---|---|
name | String | Optional | Store name that may be displayed on the checkout form when this presentation is configured. |
website | String | Optional | Merchant website associated with the Intent. |
Response Description
{
"intentId": "232510340021612544",
"checkoutForm": true,
"paymentIntent": {
"intentSessionId": "232510340080332800",
"backToStoreRedirectUrl": "https://merchant.example.com/orders/order-20260909-0001",
"displayedPaymentMethods": ["QRIS"],
"submittedAmount": {
"value": 150000,
"currency": "IDR"
},
"description": "Order 20260909-0001",
"webhookUrl": "https://merchant.example.com/webhooks/payments",
"additionalData": {
"url": "https://checkout.carusell.world/session/232510340080332800",
"expirationDateTime": "2026-09-09T14:20:00Z"
}
},
"clientReferenceIntentId": "order-20260909-0001",
"intentStatus": "CREATED"
}The
paymentIntentobject is flattened in the response. Checkout-form fields such asbackToStoreRedirectUrlanddisplayedPaymentMethodsare returned directly underpaymentIntent, not insideformDetails. The request'stemplatefield is not echoed back.The response does not contain a
paymentsarray because the payer has not yet created a QRIS payment. A Payment is created later from the Hosted Checkout session.
Top-Level Response Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
intentId | String | Required | Unique identifier of the Intent in our platform. |
checkoutForm | Boolean | Optional | true when the response contains a Hosted Checkout session; omitted otherwise. |
paymentIntent | Object | Conditional | Required in a successful Hosted Checkout Intent response. |
clientReferenceIntentId | String | Required | Merchant's Intent reference returned from clientReferenceId in the request. |
merchant | Object | Optional | Merchant information returned when it was provided in the request. |
processingStatusCode | String | Optional | Intent-level error code (CODE_PI0000 = "Unknown error"). Present only when intent processing fails; omitted from a successful response. |
statusMessage | String | Optional | Error message. Returned only together with processingStatusCode when intent processing fails. |
description | String | Optional | Intent-level description returned when it was supplied in the request. |
intentStatus | String | Required | Current Intent status. A newly created Hosted Checkout Intent normally has the CREATED status. |
paymentIntent
| Parameter | Type | Required | Description |
|---|---|---|---|
intentSessionId | String | Optional | Internal identifier of the checkout session associated with the Payment Intent. |
backToStoreRedirectUrl | String | Required | URL supplied in the request, or the platform response value used for the checkout's return-to-store behaviour. |
displayedPaymentMethods | Array of Strings | Optional | Payment methods made available to the payer. For the QRIS-only flow, the value is ["QRIS"]. |
submittedAmount | Object | Required | Submitted order amount and currency returned from the request. |
description | String | Optional | Payment Intent description returned from the request. |
webhookUrl | String | Required | Webhook URL for payments created within this Intent, returned from the request. |
additionalData | Object | Required | Checkout access information, including the Hosted Checkout URL and session expiration. |
payer | Object | Optional | Payer details when they were supplied in the request or otherwise associated with the Payment Intent. |
payee | Object | Optional | Payee details when applicable. |
submittedAmount
| Parameter | Type | Required | Description |
|---|---|---|---|
value | Number | Required | Submitted order amount returned from the request. |
currency | String | Required | Submitted currency returned from the request. It may differ from the QRIS authorisation currency when FX conversion is applied. |
additionalData
| Parameter | Type | Required | Description |
|---|---|---|---|
url | String | Required | Carusell Hosted Checkout URL. Redirect the payer to this URL to continue the payment. It is not the QRIS payload and must not be displayed as a QRIS QR code. |
expirationDateTime | DateTime | Optional | Date and time when the checkout session expires, in ISO 8601 format. The default session lifetime is 20 minutes unless another value is configured for your account. Until expiry, the payer can access the form and may make multiple payment attempts. After expiry, create a new Intent if another attempt is required. |
merchant
| Parameter | Type | Required | Description |
|---|---|---|---|
name | String | Optional | Store name returned from the request. It may be displayed on the checkout form when configured. |
website | String | Optional | Merchant website returned from the request. |
QRIS Checkout Experience
The payer completes all QRIS steps on the Carusell Hosted Checkout form. The merchant must redirect the payer to
paymentIntent.additionalData.url; the merchant does not render the QRIS QR code or payload in this integration.
QRIS Hosted Checkout collects no information from the payer. There is no name, document, email, or phone entry step — the form goes straight to displaying the QRIS payment.
Once the payment is created, the checkout form displays both representations of the same QRIS payment:
- a QR code for scanning from another device;
- a copyable QRIS payload for pasting into a QRIS-enabled banking or wallet application.
The payer must not modify the QRIS payload, amount, CRC, or any other character in the copyable value.
Payment Statuses
| Status | Meaning | Merchant action |
|---|---|---|
AUTHORIZATION_REQUESTED | The QRIS payment was created and is waiting for the payer to complete the transfer. | Wait for a webhook. Do not fulfil the order. |
CAPTURED | The QRIS transfer was successfully completed. | Fulfil the order. |
DECLINED | The payment was rejected. | Do not fulfil the order. The payer may start another attempt while the checkout session remains active. |
CANCELLED | The payment was cancelled or the QR expired before completion. | Do not fulfil the order. The payer may start another attempt while the checkout session remains active. |
ERROR | A technical or processing error prevented the payment from completing. | Do not fulfil the order. Use the error fields for diagnostics and allow another attempt only when appropriate. |
A checkout session and a QRIS payment have separate lifecycles.
paymentIntent.additionalData.expirationDateTimedescribes the checkout session lifetime. A QRIS QR created during that session has its own payment status and may expire independently.
Refunds
QRIS payments completed through Hosted Checkout support the same refund flow as QRIS payments created through Host-to-Host integration.
- A refund can be created only after the QRIS payment reaches
CAPTURED. - Use the payment
idreceived through the payment webhook or retrieved from the Intent or Payment API. - Create the refund with POST /processing/api/v1/refunds.
- Full refunds only — QRIS does not support partial refunds. The refund is returned to the original QRIS payment source.
- Only one refund per payment is possible.
- Refund processing is asynchronous. Treat it as successful only when the refund reaches
REFUNDED.
Webhooks
Payment status notifications
- The platform sends payment webhooks to
paymentIntent.webhookUrlwhenever the status of a QRIS payment created within the checkout session changes.- The synchronous Intent response only creates the checkout session. Fulfil the order only after receiving a payment with status
CAPTURED.- A payer may make multiple payment attempts during the checkout session lifetime. Correlate each webhook by its platform payment ID and correlate the overall checkout flow by the Intent ID.
- Webhooks may be delivered more than once. Process them idempotently.
- If a webhook is delayed or missed, retrieve the Intent or Payment by ID to reconcile the latest state.
For more information about payment webhooks, see the dedicated page.
Updated about 1 hour ago
