Retail Outlet is currently offered to selected merchants only. To enable it for your merchant, contact your Singapay account manager. Create requests from merchants without access are rejected with
422.Cash payments
Accept cash from customers who don’t have a bank account, e-wallet, or card.
Nationwide coverage
Customers pay at any Alfamart or Indomaret cashier — no app or registration needed.
Webhook on payment
Singapay notifies your
transaction_notif_url as soon as the cashier confirms the payment.Payment flow
Key difference: one code = one transaction
Cannot do
- Reuse a payment code for another payment
- Accept partial payments or overpayments
- Change the amount or outlet after the code is created
- Create a code without an expiry time
Must do
- Create a new payment code for each transaction
- Set the exact amount and the outlet (
retail_code) at creation - Set
expired_atto a time in the future - Tell the customer which store to go to: Alfamart or Indomaret
Supported outlets
Alfamart
ALFAMARTPayment code can only be paid at Alfamart cashiers.
Indomaret
INDOMARETPayment code can only be paid at Indomaret cashiers.
A payment code only works at the outlet you selected in
retail_code. An Alfamart code cannot be paid at Indomaret, and an Indomaret code cannot be paid at Alfamart.Transaction status
Settlement is not a separate status. Check the
has_settle and settle_at fields to see whether a paid transaction has been settled.Recommended flow
1
Create a payment code
Call Create Payment Code with
retail_code, amount, customer_name, and expired_at. Send your own order ID in merchant_reff_no so you can match the transaction later.2
Save the transaction
Store the
transaction_id and payment_code from the response. You need transaction_id to look up the transaction later.3
Give the code to the customer
Show the
payment_code, the amount, the outlet (Alfamart or Indomaret), and the expiry time to the customer.4
Customer pays at the cashier
The customer tells the cashier they want to make a payment, shows the payment code, and pays the exact amount in cash.
5
Receive the webhook
Singapay sends a
retail-transaction webhook to your transaction_notif_url when the transaction becomes paid. Update the order on your side.6
Verify the status (optional)
Call Show Transaction to confirm the latest status, for example if you did not receive the webhook.
Important notes
Amount limits
Amount limits
By default, the amount must be between IDR 15,000 and IDR 2,500,000 per transaction. Your merchant may have different limits based on its configuration. If the amount is outside the limit, the request is rejected with
422 and a message showing the allowed min or max.Expiry time
Expiry time
expired_at is required and must be a Unix timestamp in milliseconds (13 digits) set to a future time. After it passes, an unpaid transaction changes to expired and the code can no longer be paid. If you subscribe to the Transaction Money-In Expiration Webhook, expired Retail transactions are included in it.Webhook notification
Webhook notification
When a transaction becomes
paid, Singapay sends a POST request to your transaction_notif_url with event = retail-transaction. This URL is also used by other money-in products, so route requests by the event field. See Shared Webhook Endpoints and verify every request as described in Security and Signature Validation.No list or inquiry endpoint
No list or inquiry endpoint
The API has two endpoints only: create and show. There is no separate inquiry-status endpoint — Show Transaction always returns the latest status. To browse or export Retail transactions, use the Singapay merchant dashboard.
Fees and settlement
Fees and settlement
A fee is charged per transaction and returned in
fees.amount. The balance from a paid transaction follows your merchant’s configured settlement method, the same as Virtual Account. Track settlement with the has_settle and settle_at fields.Timestamp format
Timestamp format
In API responses,
expired_at, processed_timestamp, post_timestamp, and settle_at are Unix timestamps in milliseconds. processed_timestamp and settle_at stay null until the transaction is paid or settled.Rate limit
Rate limit
The Create Payment Code endpoint is rate-limited per merchant. If you send too many requests, you will receive
429 Too Many Requests. Wait before you try again.Available endpoints
Create Payment Code
Create a one-time Alfamart or Indomaret payment code for a fixed amount.
Show Transaction
Get the details and latest status of a Retail transaction by its
transaction_id.All endpoints require authentication. See Authentication.
