Reverse a payment
Two reversals are available to your point of sale, and choosing the wrong one is the most common integration error. They differ by where the money currently is.
| The situation | Money state | Use |
|---|---|---|
| The customer changes their mind before presenting their card | Nothing paid; the amount is sitting on the device | Cancel |
| A sale needs undoing after the customer paid, on the same day | Paid, not yet settled | Void |
A useful rule for the till: cancel is what you press while the customer is still being asked to pay. Void is what you press when they have already paid and you are undoing the sale on the spot.
Past the void window, a reversal is no longer a till action. It is handled as a refund by the merchant's back office, outside this API.
Cancel — before the customer pays
A waiting payment can be cancelled from either side: by your point of sale, or at the terminal itself by the cashier or the customer. Both end the same way, and your till must handle both.
From the point of sale
curl -X POST https://api-live.kcpboundless.com/api/in-store/payments/01997b3e-6c31-7a42-9f10-4d2c8b5e7a01/cancel \
-H "X-API-Key: bndl_live_..."
This sends a cancel instruction to the device and withdraws the amount from its screen. No money has moved, so there is nothing to reverse with the acquirer.
Boundless does not take the cancel command's own reply as the answer. It re-reads the payment from the acquirer afterwards and applies what it actually finds. If the acquirer cannot be reached for that confirmation, the payment is deliberately left open rather than being marked cancelled on an unconfirmed result — the background sweep will settle it. Read the returned status; do not assume.
At the device
The cashier or customer can cancel on the terminal directly, with no involvement from your point of
sale. Boundless discovers this the next time the payment is read — that is, on your next
sync-status call, or on the background sweep, whichever comes first.
The payment ends CANCELLED, with a reason recorded as cancelled at the terminal.
CANCELLED without asking for itA till that treats an unrequested CANCELLED as an error state will strand the bill. Close it
cleanly and let the cashier start over.
The race you must handle
The customer may complete the payment in the moment between the cashier pressing cancel and the
request arriving. If they do, their payment stands and the cancellation does not take effect. A
200 means the request was processed, not that the payment was cancelled.
Always read the returned status.
Payments nobody decides are closed out automatically after their timeout, so an abandoned bill never blocks a terminal permanently.
Void — after the customer paid
A sale the customer changes their mind about seconds later is the same till action as a cancel. The only difference is that they have already paid, so the reversal has to happen at the acquirer rather than on the device.
curl -X POST https://api-live.kcpboundless.com/api/in-store/payments/01997b3e-6c31-7a42-9f10-4d2c8b5e7a01/void \
-H "X-API-Key: bndl_live_..."
The window
A void uses the acquirer's same-day reversal facility, so it is time-bounded. The window runs from the moment of capture — not from the start of the sale, and not from the store's calendar day — and is measured in UTC.
The current window is 23 hours 15 minutes from capture: the acquirer's same-day facility with a margin held back inside the day. Treat the exact figure as configuration confirmed at onboarding rather than a constant to hard-code; design your till to react to the platform's answer, not to its own clock.
Preconditions
All of the following must hold, or the call is refused with 409 Conflict and a message explaining
which one failed:
| Requirement | If it fails |
|---|---|
The payment is currently CAPTURED | 409 — a payment that is still waiting is cancelled, not voided; one already reversed cannot be reversed twice |
| The capture is inside the void window | 409 |
| The acquirer supports voids | 409 |
| The payment was taken through the platform | 409 — payments recorded from an acquirer's settlement report cannot be reversed here |
| The store and terminal are still fully configured | 409 / 404 |
The outcome
There is no separate "voided" status. A confirmed void leaves the payment CANCELLED, with
previousStatus CAPTURED. The status-history entry (see
Trace a payment) carries an actionReference prefixed VOID-, which is how
you tell a void apart from a plain cancel after the fact.
The case you must handle
A 200 OK does not mean the payment was voided.
The acquirer may accept the reversal without confirming it in time for your call to return. When
that happens, Boundless responds 200 with the payment still CAPTURED. The reversal may yet
complete.
200 + status CANCELLED → voided. Reverse the sale in the till.
200 + status CAPTURED → not yet confirmed. Do not tell the cashier it is done.
Re-read the payment, or retry the void.
409 → refused, and the message says why. Payment stays CAPTURED.
Read the returned status on every void, without exception. A till that treats 200 as success
will tell a cashier a sale was reversed while the customer's money is still captured.
Retrying
The call is safe to repeat while the payment is CAPTURED — that is the correct response to the
unconfirmed case above. Two things to know:
- Each retry submits another reversal to the acquirer. Retry deliberately, with backoff, not in a tight loop.
- Once the void is confirmed, a further retry returns
409, because the payment is no longerCAPTURED. That409means it already worked; check the status before treating it as a failure.
When neither applies
Once the void window has passed — or the acquirer does not offer voids — the money has moved on and a refund is the correct instrument. Refunds are a back-office action performed by a signed-in dashboard user, not a till action through this API.
Unresponsive terminals
Forcing a bill off a device that cannot be reached is a separate, operator-only action, because it interrupts the terminal itself rather than simply withdrawing a bill. Contact Boundless if a terminal is stuck with a bill you cannot cancel normally.