Static QR
One QR printed once, used many times. Best for small merchants and any acceptance setup where you can't display a fresh QR per transaction.
A static QR is one code printed once and presented over and over. Customers scan the same code for every transaction. You either let the customer enter the amount on their phone, or you update the amount on the code from your backend before each sale.
This is the cheapest pattern to deploy — no screen, no terminal, just a printed sticker. It's the most common acceptance method for informal merchants, market stalls, food trucks, hair salons, and small retail.
When to use a static QR
| ✅ Good fit | ❌ Wrong fit |
|---|---|
| Counter or wall poster at a single merchant | Multiple amounts displayed simultaneously |
| One terminal, one cashier | High-volume tills where amounts vary in seconds |
| Outdoor signage or sticker on equipment | Customer expects a per-transaction QR on a screen |
| Cash-business augmentation | E-commerce checkouts (use Bluebox hosted checkout instead) |
For high-volume terminals where the amount changes per transaction, use a Dynamic QR instead — fresh code per sale, amount embedded.
Setup — once per device
You create the static code one time and use it forever.
curl -X POST "https://qa.scantopay.io/pluto/code/create" \
-u "$USERNAME:$PASSWORD" \
-H 'Content-Type: application/json' \
-d '{
"merchantReference": "static-counter-01",
"amount": 0,
"useOnce": false,
"shortDescription": "Pay Acme Coffee"
}'Response:
{
"code": "0123456789",
"expiryDate": 0,
"codeUrl": null
}Two important fields:
amount: 0— zero means variable amount. The customer enters the amount they want to pay on their phone.useOnce: false— re-usable across transactions. Withtrue, the code would invalidate after the first successful payment.
Print the 10-digit code as a QR — see Rendering the QR.
Default expiry. Static codes withexpiryDate: 0never expire. If you omitexpiryDate, the platform applies the default 30-minute expiry which isn't what you want for a printed sticker. Always setexpiryDate: 0for printed codes.
Per-transaction — variant A: variable amount
If you created the code with amount: 0, the customer enters the amount on their phone. There's nothing else for you to do on the backend until the payment notification arrives.
The flow is:
- Customer scans the QR.
- The Scan to Pay app prompts for the amount.
- Customer enters the amount and authorises with PIN or 3DS.
- Scan to Pay POSTs the webhook to your notification URL.
- Your handler returns HTTP 200 within 45 seconds.
Per-transaction — variant B: server-updated amount
If you'd prefer not to let the customer type the amount — for accuracy, audit, or display purposes — you can update the amount on the existing code from your backend before each sale:
curl -X PUT "https://qa.scantopay.io/pluto/code/0123456789/amount" \
-u "$USERNAME:$PASSWORD" \
-H 'Content-Type: application/json' \
-d '{
"amount": 75.00,
"merchantReference": "static-counter-01-sale-2025-05-14-001"
}'This updates the code to a fixed amount of R75. The next scan presents the customer with R75 to confirm; they can't change it. After the payment completes, the code returns to its previous state and is ready to be updated again with a new amount.
Each amount update should include a freshmerchantReferenceto keep your reconciliation clean. The originalmerchantReferencefrom the create call stays on the code; the update reference flows through to the transaction record.
See Managing QR codes for the full update-amount API.
Receiving the payment notification
Both variants result in a standard webhook delivery to your notification URL. The payload contains the transaction outcome, amount, and bank response. See Webhooks.
The reference field on the webhook payload is the merchantReference you passed (either on create for variant A, or on update-amount for variant B), which is how you reconcile to your sale record.
What's next
- Generate a styled PNG of your QR → Rendering the QR
- Update the amount, block, unblock, or delete a code → Managing QR codes
- Understand what states a code can be in → QR code lifecycle
- Test it end to end → Quickstart
- Handle the resulting webhook → Webhooks
Updated 4 days ago
