ECR Payments Guide
This guide explains how to use the API for the Pos payment method for:
- Creating a sale
- Retrieving a sale
- Configuring a webhook subscription for sale events
- Canceling a sale
- End-to-end example
Authentication
The API supports both OAuth 2.0 and API key authentication. The API key flow is recommended for most integrations and used in this guide. Follow the steps on the authentication pages for a more in depth look into the topic.
API key
Send your API key in the header: Buck-Api-Key: your_api_key
1. Creating a Sale
To create a POS Sale , use:
POST /v1/sales
A POS sale is a regular sale where:
paymentMethodsincludesPospaymentMethodOptions.pos.terminalIdspecifies the target terminal
Required POS-specific fields
At minimum, for a POS sale you should provide:
referencecurrencytotalAmountpaymentMethods: ["Pos"]paymentMethodOptions.pos.terminalIdsequenceType: "OneOff"intentType: "Pay"For a normal POS payment,Payis the most likely value.
Example request
{
"storeId": "s_1234abcd",
"reference": "order-10001",
"currency": "EUR",
"totalAmount": "49.95",
"description": "In-store purchase",
"locale": "nl-NL",
"sequenceType": "OneOff",
"intentType": "Pay",
"statementDescriptor": "Order #10001",
"paymentMethods": [
"Pos"
],
"paymentMethodOptions": {
"pos": {
"terminalId": "t_abcd1234efgh5678"
}
},
"metadata": {
"cashierId": "emp-001",
"basketId": "basket-789"
}
}Successful response
A successful create returns:
201 Created
Response body
{
"id": "sl_abcd1234efgh5678",
"storeId": "s_1234abcd",
"currency": "EUR",
"totalAmount": "49.95",
"openAmount": "49.95",
"paidAmount": "0.00",
"refundedAmount": "0.00",
"reversedAmount": "0.00",
"reference": "order-10001",
"status": "Open",
"description": "In-store purchase",
"locale": "nl-NL",
"sequenceType": "OneOff",
"paymentMethods": [
"Pos"
],
"paymentMethodOptions": {
"pos": {
"terminalId": "t_abcd1234efgh5678"
}
},
"metadata": {
"cashierId": "emp-001",
"basketId": "basket-789"
}
"createdAt": "2024-05-16T10:30:00Z"
}Common error responses
400 Bad Request401 Unauthorized404 Not Found
Example problem response:
{
"title": "Bad Request",
"status": 400,
"detail": "The request is invalid.",
"errorCode": "VS01"
}2. Retrieving a Sale
To retrieve a specific sale, use:
GET /v1/sales/{saleId}
Path parameter
saleId: the sale identifier
Successful response
A successful retrieval returns:
200 OK
Response body: SaleContract
Example response
{
"id": "sl_abcd1234efgh5678",
"storeId": "s_1234abcd",
"currency": "EUR",
"totalAmount": "49.95",
"openAmount": "0.00",
"paidAmount": "49.95",
"refundedAmount": "0.00",
"reversedAmount": "0.00",
"reference": "order-10001",
"status": "Paid",
"description": "In-store purchase",
"sequenceType": "OneOff",
"paymentMethods": [
"Pos"
],
"paymentMethodOptions": {
"pos": {
"terminalId": "t_abcd1234efgh5678"
}
},
"transactions": [
{
"id": "t_abcd1234efgh5678",
"storeId": "s_1234abcd",
"terminalId": "t_abcd1234efgh5678",
"serviceCode": "POS",
"intentType": "Pay",
"collectionType": "Processing",
"sequenceType": "OneOff",
"currency": "EUR",
"amount": "49.95",
"merchantReference": "order-10001",
"status": "Successful",
"saleId": "sl_abcd1234efgh5678",
"createdAt": "2024-05-16T10:31:00Z"
}
],
"timeline": [
{
"eventLogType": "Sale was paid",
"eventDateTime": "2024-05-16T10:31:00Z"
}
],
"metadata": {
"cashierId": "emp-001",
"basketId": "basket-789"
}
"createdAt": "2024-05-16T10:30:00Z"
}Useful fields in the response
status: current sale statusopenAmount: remaining unpaid amountpaidAmount: amount already paidtransactions: underlying POS transaction(s)timeline: lifecycle events for the sale
Possible sale statuses
OpenPaidCancelledFailedExpired
Error responses
400 Bad Request401 Unauthorized404 Not Found
3. Configuring a Webhook Subscription for Sale Events
Webhooks let your system receive notifications when sale-related events occur.
There are two relevant endpoints:
GET /v1/webhooks/eventsto list available event typesPOST /v1/webhooksto create a webhook subscription
Step 1: List available event types
GET /v1/webhooks/events
This returns the event types your webhook can subscribe to.
Example response
{
"eventTypes": [
{
"code": "TRANSACTION.CREATE",
"description": [
{
"locale": "en-US",
"value": "Transaction created"
}
]
}
]
}The schema allows event type codes as strings. The webhook examples in the spec include sale events such as:
SALE.CREATESALE.UPDATE
Because the request examples use these values, those are the appropriate sale-related event codes to use in your webhook configuration.
Step 2: Create the webhook
POST /v1/webhooks
Request body fields
url: destination endpointstoreId: optional, to scope the webhook to a specific storeeventTypes: list of event codesmaxConcurrency: maximum concurrent deliveriessecret: secret used to sign webhook payloads
Example request
{
"url": "https://example.com/webhooks/sales",
"storeId": "s_1234abcd",
"eventTypes": [
"SALE.CREATE",
"SALE.UPDATE"
],
"maxConcurrency": 10,
"secret": "your-webhook-secret"
}Successful response
A successful create returns:
201 Created
Response body:
{
"id": "es_1234abcd5678efgh",
"url": "https://example.com/webhooks/sales",
"storeId": "s_1234abcd",
"eventTypes": [
"SALE.CREATE",
"SALE.UPDATE"
],
"maxConcurrency": 10,
"secret": "your-webhook-secret",
"status": "Active",
"createdAt": "2024-05-16T00:00:00Z"
}Webhook status values
ActiveInactive
Error responses
400 Bad Request401 Unauthorized404 Not Found
4. Canceling a Sale
To cancel a sale, use:
POST /v1/sales/{saleId}/cancel
Path parameter
saleId: the identifier of the sale to cancel
Example request
POST /v1/sales/sl_abcd1234efgh5678/cancel
This endpoint does not require a request body.
Successful response
A successful cancellation returns:
200 OK
Response body: updated SaleContract
Example response
{
"id": "sl_abcd1234efgh5678",
"storeId": "s_1234abcd",
"currency": "EUR",
"totalAmount": "49.95",
"openAmount": "0.00",
"paidAmount": "0.00",
"refundedAmount": "0.00",
"reversedAmount": "0.00",
"reference": "order-10001",
"status": "Cancelled",
"paymentMethods": [
"Pos"
],
"paymentMethodOptions": {
"pos": {
"terminalId": "t_abcd1234efgh5678"
}
},
"createdAt": "2024-05-16T10:30:00Z"
}When to use this endpoint
Use this endpoint when you want to cancel the sale resource itself.
Related terminal cancel endpoints
The API also exposes terminal-level cancel endpoints:
- POST
/v1/pos/terminals/smart/{terminalId}/cancel - POST
/v1/pos/terminals/internal/{terminalId}/cancel
These endpoints cancel the current action or terminal transaction at device level, while POST /v1/sales/{saleId}/cancel cancels the sale resource.
If your flow is sale-centric, prefer the sale cancel endpoint. If your flow is terminal-operation-centric, the terminal cancel endpoint may also be relevant.
Error responses
400 Bad Request401 Unauthorized404 Not Found
End-to-end example
1. Create POS sale
POST /v1/sales
{
"reference": "order-10001",
"currency": "EUR",
"totalAmount": "49.95",
"sequenceType": "OneOff",
"intentType": "Pay",
"paymentMethods": ["Pos"],
"paymentMethodOptions": {
"pos": {
"terminalId": "t_abcd1234efgh5678"
}
}
}2. Status
2A. Poll sale status
GET /v1/sales/sl_abcd1234efgh5678
Watch for the status field to change to a final value (Paid, Cancelled, Failed or Expired)
2B. Receive sale updates through webhooks
Create a webhook subscribed to:
[
"SALE.CREATE",
"SALE.UPDATE"
]3. Cancel if needed
POST /v1/sales/sl_abcd1234efgh5678/cancel
Updated about 1 month ago