- In-person
- Take payments
Take a payment in person
Send a cart to an enrolled phone or terminal with POST /ipp/v1/sessions, handle the ipp.* callbacks and store the order_id that ipp.session.finalized carries.
When the customer is ready to pay, your backend creates a session — the cart plus the device
in front of them. Kustom pushes it to that device, the clerk collects the payment, and
callbacks tell you how it went. The one that matters carries the order_id of the order
Kustom created.
- Create a sessionYour server → KustomPOST/
ipp/ the cart and a device_idv1/ sessions Kustom → Your serversession_idKustom → Your serveripp.session.createdasynchronous: it can arrive before the response - Kustom pushes it to the deviceKustom → Kustom POS apppush notification with the session_idyou don't pollKustom POS app → Kustomfetch the session
- The clerk collects the paymentClerk and customer → Kustom POS appthe clerk picks a payment methodKustom POS app → Kustomattach the paymentKustom → Your serveripp.session.activatedClerk and customer → Kustom POS appthe customer pays by card
- Payment succeeds one of 3Kustom POS app → Kustomfinalize the paymentKustom → Your serveripp.session.finalizedcarries the order_id: store itKustom POS app → Clerk and customerreceipt or QR code
- Card declined, and the clerk retries one of 3Kustom POS app → Kustomfinalize the paymentKustom → Your serveripp.payment.failednothing for your backend to doKustom POS app → Clerk and customerpayment failed, try again
- The sale is off one of 3Your server → KustomPOST/
ipp/ v1/ sessions/ {session_id}/ cancel Kustom → Your serveripp.session.cancelledfinal, and also sent when the clerk cancels
Before you start
Section titled “Before you start”- At least one enrolled device and its
device_id— or, in Playground, a simulated one. - A webhook endpoint configured for your account in the Kustom Portal. It’s one endpoint for the whole account, not one per session — see Webhooks.
Step by step
Section titled “Step by step”1. Create a session
Section titled “1. Create a session”POST /ipp/v1/sessions with the cart and the
device_id. Kustom pushes the session to the device by push notification — you don’t poll
for delivery.
- All amounts are in minor units.
19900is199.00in the session’s currency. - There’s no
location_idon the session. The location comes from the device, which was bound to one when it enrolled.
Store the session_id from the response. There’s no order_id until the session is
finalized.
2. Handle the callbacks
Section titled “2. Handle the callbacks”Kustom POSTs lifecycle events to your webhook endpoint as the session moves. Answer
200 — Kustom takes anything else as a failure. Every in-person event is prefixed ipp.,
so you can route them apart from other Kustom webhooks arriving at the same endpoint.
ipp.session.created is asynchronous and can reach you before you’ve finished
handling the create response. Correlate on session_id, which both carry, and make the
handler idempotent.
3. Store the order from ipp.session.finalized
Section titled “3. Store the order from ipp.session.finalized”That’s the event that matters. It carries the order_id of the order in Order Management:
{ "id": "kevt_62EvxyMEaAaHSGeoDTza47", "merchant_id": "DM11917000", "timestamp": "2026-06-05T18:33:39.608920367Z", "type": "ipp.session.finalized", "data": { "session_id": "dc01aa86-fb99-4d05-97dc-e79a22650f9a", "order_id": "ccf4e76a-f56d-4d3a-abf9-f4fe941f0a1f" }}Link it to your own order record. From here it’s an ordinary order, and the Order
Management API takes it by that order_id:
- Capture it once the goods are handed over, if your capture method is manual.
- Refund all or part of the amount.
- Cancel it to void the transaction, while nothing is captured.
A failed payment needs nothing from your backend. ipp.payment.failed is information,
not the end of the sale: the clerk retries on the device and the session carries on.
Session states and callbacks has every state and payload.
4. Cancel when the sale is off
Section titled “4. Cancel when the sale is off”Cancel the session from your backend at any point before it reaches a final state. Cancellation is final — no payment can be collected on that session afterwards.
To read a session’s current state without waiting for a callback, get the session.
Check that it works
Section titled “Check that it works”Test without hardware runs this whole flow in Playground with a simulated device and card tap. You’re done when:
ipp.session.finalizedreaches your handler and itsorder_idis linked to your order.- A declined tap reaches you as
ipp.payment.failedwithout ending the sale. - A session you cancel arrives as
ipp.session.cancelled.
Troubleshooting
Section titled “Troubleshooting”Callbacks never arrive. The webhook endpoint is set per account in the Portal, not in
the session call. Check it’s set, and that it answers 200.
A callback arrived before the create response was handled. Expected —
ipp.session.created is asynchronous. Correlate on session_id.
The /ipp/v1 endpoints return 404 or 403. In-person payments isn’t enabled on the
account. Ask your Kustom representative.
Related
Section titled “Related”- Capture an order — collecting the money when capture is manual
- Refunds — returning it
- Session states and callbacks — every state, payload and card tap outcome
This page is also available as Markdown — append .md to its URL — and is indexed in llms.txt.