Skip to main content

API reference

The endpoints an in-store integration uses. All requests are authenticated with your API key and made against https://api-live.kcpboundless.com.

note

This reference is maintained by hand for now. It will be generated directly from the API's OpenAPI specification, so the published reference always matches the running service.

Payments​

Take a payment​

POST /api/in-store/payments

Sends a bill to a terminal and returns the payment in AWAITING_TERMINAL. See Accept a payment for the request body and response.

Check a payment's status​

POST /api/in-store/payments/{id}/sync-status

Returns the current state of the payment, advancing it if the customer has finished at the device. Safe to call repeatedly.

Cancel a payment​

POST /api/in-store/payments/{id}/cancel

Withdraws a bill that is still waiting at the terminal. If the customer completed the payment first, their payment stands and the response reports that instead — always read the returned status. See Cancel — before the customer pays.

Void a payment​

POST /api/in-store/payments/{id}/void

Reverses a captured payment at the acquirer, same day, where the acquirer supports it. A confirmed void leaves the payment CANCELLED; a 200 with the payment still CAPTURED means the reversal is not yet confirmed. See Void — after the customer paid for the window, the preconditions, and the cases your till must handle.

Read a payment​

GET /api/transactions/{id}

The payment's current state, without contacting the terminal — the cheap call for routine polling. sync-status above is the one that refreshes from the device first.

Payment status history​

GET /api/transactions/by-payment/{paymentId}

The append-only status history for a payment, newest first — one element per status event. See Trace a payment.

List payments​

GET /api/transactions?merchantExternalId={merchantExternalId}
&from=&to=&status=&acquirerName=&q=&page=&size=

Paged, newest first. Filter by date range, status, or free text; page is 0-indexed and the response carries content plus totalElements / totalPages.

Stores​

GET /api/merchants/{merchantExternalId}/stores
GET /api/merchants/{merchantExternalId}/stores/search?q=&status=&country=&hasTerminals=&sort=&page=&size=
POST /api/merchants/{merchantExternalId}/stores
GET /api/merchants/{merchantExternalId}/stores/{storeExternalId}
PUT /api/merchants/{merchantExternalId}/stores/{storeExternalId}
DELETE /api/merchants/{merchantExternalId}/stores/{storeExternalId}[?force=true]

Create, read, update, and remove the stores under your business. The plain list is alphabetical; search adds free text, filters, sorting, and paging. Deletes cascade to the store's terminals and are guarded when the store took payments in the last 24 hours — see Removing safely.

Terminals​

GET /api/merchants/{merchantExternalId}/stores/{storeExternalId}/terminals
POST /api/merchants/{merchantExternalId}/stores/{storeExternalId}/terminals
GET /api/merchants/{merchantExternalId}/stores/{storeExternalId}/terminals/{terminalExternalId}
PUT /api/merchants/{merchantExternalId}/stores/{storeExternalId}/terminals/{terminalExternalId}
DELETE /api/merchants/{merchantExternalId}/stores/{storeExternalId}/terminals/{terminalExternalId}[?force=true]

Create, read, update, and remove the terminals under a store. The same delete guard applies.

Webhook configuration​

POST /api/webhooks/configs create a destination
GET /api/webhooks/configs list yours
GET /api/webhooks/configs/{id} read one
PUT /api/webhooks/configs/{id} update url or event selection
DELETE /api/webhooks/configs/{id} remove
POST /api/webhooks/configs/{id}/regenerate-key rotate the signing secret
POST /api/webhooks/configs/{id}/test send a TEST event now
GET /api/webhooks/configs/{id}/events delivery history
GET /api/webhooks/events/{eventId}/attempts per-delivery attempts

Create body: { "url": "https://...", "description": "...", "eventTypes": ["PAYMENT_CAPTURED"] } — omit eventTypes to receive every event. The response includes the signing secret. See Webhooks.

Errors​

Every error uses one shape:

{
"timestamp": "2026-09-08T06:20:11Z",
"status": 409,
"error": "Conflict",
"message": "Payment 01997b3e… is already CAPTURED"
}

Treat message as human-readable diagnostics, not a machine contract. Branch on the HTTP status and your own request context — never on message text, which may be reworded.

CodeWhenYour response
200 OKThe request succeeded.Read the returned status — success of the request is not the same as the outcome you asked for.
201 CreatedThe payment was accepted.Read the returned status — a 201 can carry a REFUSED payment on a busy terminal.
400 Bad RequestValidation failed — message names the field and the reason.Fix the request. Do not retry unchanged.
401 UnauthorizedMissing or invalid credentials.Check the key, and the bearer prefix rule. Do not retry.
403 ForbiddenValid credentials, but outside your permissions.Do not retry.
404 Not FoundThe resource does not exist — including anything that exists but belongs to another business.Do not retry.
409 ConflictThe request conflicts with the current state — the payment is already decided, a reversal is not permitted in its current state, or the terminal is not configured.Read the message; the state must change first.
429 Too Many RequestsRate limit exceeded.Honour Retry-After, then retry.
5xxA temporary problem on our side.Retry with backoff. A create is protected by reference idempotency.