API Loyalty by SWiP mobile app in Kiosk Self-Service
Self-Service Orders API
Overview
The Self-Service Orders API provides endpoints for managing self-service order operations in the SmartWallet Self-Service system. This API enables Self-Service terminals to create orders, check customer binding status, calculate loyalty benefits, and mark orders as closed.
Authentication: terminal authentication required
Business Flow
Standard Kiosk Flow
Order Creation: Kiosk creates a POS-controlled order and displays QR code from response
Customer Binding: Customer scans QR code
Status Monitoring: System checks binding status and retrieves customer data with calculated loyalty for order
Redeem points: Calculate additional loyalty benefits (withdrawal of available points) based on customer profile
Order Closure: Mark order as closed with final payment amount
Order Cancellation: Mark order as closed with 0 amount
Multi-check Kiosk Flow
Order Creation: Kiosk creates multiple POS-controlled orders separately. Main binding is done using
parentOrderRefpassed to each orderCustomer Binding: Customer scans QR code
Status Monitoring: System checks binding status and retrieves customer data with calculated loyalty for order
Redeem points: Calculate additional loyalty benefits (withdrawal of available points) based on customer profile
Order Closure: Mark each order as closed with final payment amount
Order Cancellation: Mark each order as closed with amount = 0
Transport and protocol
The API uses HTTPS as a protocol. Messages are represented in the JSON format.
Authentification
Authentification is implemented by a static token. The token must be sent in the header of HTTP requests.
The header in every API request should include:
Field name | Value example | Description |
|---|---|---|
Authorization | Bearer 8c6b8b64-6815-6084-0a3e-178401251b68 | Token from the merchant’s marketing engine. |
X-Merchant-ID | ABCD | The value is sent by the SWiP employee after the merchant's onboarding. Four-letter codes are used at the moment. The values can be expanded in the future. |
X-Store-ID | Test storeID | The Store ID that the SWiP employee sends after the merchant's onboarding. The value is taken from the merchant's system: either the real identifier of the store or, if it cannot be received from the terminal, the value from the SWiP plugin settings. |
X-Cash-ID | 1231 | Terminal ID in the merchant's system. |
Api-Version | 3 | API version. |
Integration scenarios
Endpoints
1. Create POS-Controlled Order
POST /pos-orders
Creates a new POS-controlled order and returns a QR code for customer binding.
Request Headers
Header | Type | Required | Description |
|---|---|---|---|
| string | Yes | Cash authentication token |
| string | Yes |
|
Request Body
{
"merchantOrderId": "string",
"merchantOrderNumber": "string",
"total": "number",
"purchases": [
{
"id": "uuid",
"productId": "string",
"amount": "number",
"name": "string",
"quantity": "number",
"price": "number",
"unit": "string",
"discount": "number",
"merchantDiscount": "number",
"parentId": "string",
"orderId": "uuid",
"mrp": "number",
"priceWithoutDiscount": "number",
"productSizeId": "number",
"productSizeName": "string"
}
],
"tableNumber": "integer",
"positionalDiscount": "boolean",
"fiscalCheckBeforePayment": "boolean",
"parentRefId": "string"
}
Request Parameters
Parameter | Type | Required | Description |
|---|---|---|---|
| string | Yes | POS system's internal order ID |
| string | No | Human-readable order number |
| number | Yes | Total order amount |
| array of Purchase Objects | Yes | List of purchased items |
| integer | No | Table number for restaurant orders |
| boolean | No | Enable positional discounts (default: true) |
| boolean | No | Require fiscal check before payment (default: false) |
| string | No | Links orders for multi-order business flow |
Response
Status: 200 OK
{
"orderId": "string",
"qr": "string"
}
Response Fields
Field | Type | Description |
|---|---|---|
| string | Generated order ID |
| string | QR code for customer binding |
Example
POST /pos-orders
Authorization: Bearer <cash-token>
Content-Type: application/json
{
"merchantOrderId": "a89e961d-ee8d-4f66-88db-a5879006f656",
"merchantOrderNumber": "123456",
"total": 490.00,
"purchases": [
{
"id": "550e8400-e29b-41d4-a716-446655440001",
"productId": "COFFEE_LATTE",
"amount": 220.00,
"name": "Latte Grande",
"quantity": 2,
"price": 110.00,
"unit": "pcs",
"discount": 0,
"merchantDiscount": 0,
"priceWithoutDiscount": 110.00,
"mrp": 0.00,
"productSizeId": 2,
"productSizeName": "Grande"
},
{
"id": "550e8400-e29b-41d4-a716-446655440002",
"productId": "PASTRY_CROISSANT",
"amount": 100,
"name": "Chocolate Croissant",
"quantity": 1,
"price": 100,
"unit": "pcs",
"discount": 0,
"merchantDiscount": 0,
"priceWithoutDiscount": 100,
"mrp": 0.00
},
{
"id": "15358e70-d163-4266-b2a0-1614b76d3ccd",
"productId": "JUICE_ORANGE",
"amount": 170.00,
"name": "Fresh Orange Juice",
"quantity": 2,
"price": 85.00,
"unit": "pcs",
"discount": 0,
"merchantDiscount": 0,
"priceWithoutDiscount": 85.00
}
],
"tableNumber": 7,
"positionalDiscount": true,
"fiscalCheckBeforePayment": false,
"parentRefId": null
}
{
"orderId": "a89e961d-ee8d-4f66-88db-a5879006f656",
"qr": "https://swip.one/?o=a89e961d-ee8d-4f66-88db-a5879006f656&flow=POS_CONTROLLED"
}
2. Check Order Binding Status
GET /pos-orders/{orderId}
Checks the binding status of a POS-controlled order and returns order details if bound.
Path Parameters
Parameter | Type | Required | Description |
|---|---|---|---|
| string | Yes | The order ID to check |
Request Headers
Header | Type | Required | Description |
|---|---|---|---|
| string | Yes | Cash authentication token |
Response
Status: 200 OK
{
"id": "string",
"merchantOrderId": "string",
"purchases": [
{
"id": "uuid",
"productId": "string",
"amount": "number",
"name": "string",
"quantity": "number",
"price": "number",
"unit": "string",
"discount": "number",
"merchantDiscount": "number",
"priceWithoutDiscount": "number"
}
],
"total": "number",
"totalOriginal": "number",
"swipDiscount": "number",
"loyaltyCalcStats": {
"collectedTotal": "integer",
"awardsTotal": "integer",
"favoriteDiscount": "number",
"discount": "number"
},
"pointCalcResult": {
"total": "integer",
"availablePoints": "integer",
"pointsAsDiscount": "number",
"pointRate": "number"
},
"timeZoneId": "string"
}
Response Fields
Field | Type | Description |
|---|---|---|
| string | The order ID |
| string | POS system's internal order ID |
| array of Purchase Objects | List of purchased items |
| number | Totla order amount after applied loyalty. Equals totalOriginal if no loyalty was applied. |
| number | Total order amount provided by POS on creation |
| number | Amount of total discount |
| Contains customer’s loyalty statistic for this merchant | |
| Contains customer’s point info for this order | |
| string | Time Zone ID of POS |
Example
GET /pos-orders/a89e961d-ee8d-4f66-88db-a5879006f656
Authorization: Bearer <cash-token>
{
"id": "a89e961d-ee8d-4f66-88db-a5879006f656",
"merchantOrderId": "a89e961d-ee8d-4f66-88db-a5879006f656",
"purchases": [
{
"id": "550e8400-e29b-41d4-a716-446655440001",
"productId": "COFFEE_LATTE",
"amount": 220.0,
"name": "Latte Grande",
"quantity": 2.0,
"price": 110.0,
"unit": "pcs",
"discount": 0.59,
"merchantDiscount": 0.0,
"parentId": null,
"orderId": null,
"mrp": 0.0,
"priceWithoutDiscount": 109.7,
"productSizeId": 2,
"productSizeName": "Grande"
},
{
"id": "550e8400-e29b-41d4-a716-446655440002",
"productId": "PASTRY_CROISSANT",
"amount": 100.0,
"name": "Chocolate Croissant",
"quantity": 1.0,
"price": 100.0,
"unit": "pcs",
"discount": 0.26,
"merchantDiscount": 0.0,
"parentId": null,
"orderId": null,
"mrp": 0.0,
"priceWithoutDiscount": 99.74,
"productSizeId": null,
"productSizeName": null
},
{
"id": "15358e70-d163-4266-b2a0-1614b76d3ccd",
"productId": "JUICE_ORANGE",
"amount": 170.0,
"name": "Fresh Orange Juice",
"quantity": 2.0,
"price": 85.0,
"unit": "pcs",
"discount": 84.15,
"merchantDiscount": 0.0,
"parentId": null,
"orderId": null,
"mrp": null,
"priceWithoutDiscount": 42.92,
"productSizeId": null,
"productSizeName": null
}
],
"total": 405.0,
"totalOriginal": 490.0,
"loyaltyCalcStats": {
"collectedTotal": 0,
"awardsTotal": 0,
"favoriteDiscount": 0.0,
"discount": 0.0
},
"pointCalcResult": {
"total": 202,
"availablePoints": 232,
"pointsAsDiscount": 0.0,
"pointRate": 1.0,
"lines": [
{
"programId": 1349,
"description": "b в TestApiSelfService",
"purchaseCount": 0,
"cboRequiredCount": 0,
"awardPurchaseCount": null,
"points": 202
}
]
}
}
3. Recalculate Loyalty Benefits with points
POST /pos-orders/{orderId}/actions/points-recalculate
Calculates loyalty points and discounts for the order based on customer's loyalty status.
Path Parameters
Parameter | Type | Required | Description |
|---|---|---|---|
| string | Yes | The order ID to calculate loyalty for |
Request Headers
Header | Type | Required | Description |
|---|---|---|---|
| string | Yes | Cash authentication token |
| string | Yes |
|
Request Body
{
"points": "integer"
}
Request Parameters
Parameter | Type | Required | Description |
|---|---|---|---|
| integer | No | Points to redeem (default: 0) |
Response
Status: 200 OK
{
"id": "string",
"merchantOrderId": "string",
"purchases": [
{
"id": "uuid",
"productId": "string",
"amount": "number",
"name": "string",
"quantity": "number",
"price": "number",
"unit": "string",
"discount": "number",
"merchantDiscount": "number",
"priceWithoutDiscount": "number"
}
],
"total": "number",
"totalOriginal": "number",
"swipDiscount": "number",
"loyaltyCalcStats": {
"collectedTotal": "integer",
"awardsTotal": "integer",
"favoriteDiscount": "number",
"discount": "number"
},
"pointCalcResult": {
"total": "integer",
"availablePoints": "integer",
"pointsAsDiscount": "number",
"pointRate": "number"
},
"timeZoneId": "string"
}
Response Fields
Field | Type | Description |
|---|---|---|
| string | The order ID |
| string | POS system's internal order ID |
| array of Purchase Objects | List of purchased items |
| number | Totla order amount after applied loyalty. Equals totalOriginal if no loyalty was applied. |
| number | Total order amount provided by POS on creation |
| number | Amount of total discount including redeemed points in currency value |
| Contains customer’s loyalty statistic for this merchant | |
| Contains customer’s point info for this order | |
| string | Time Zone ID of POS |
Example
POST /pos-orders/f9145570-61b7-479c-8557-91e676afcb17/actions/points-recalculate
Authorization: Bearer <cash-token>
Content-Type: application/json
{
"points": 200
}
{
"id": "a89e961d-ee8d-4f66-88db-a5879006f656",
"merchantOrderId": "a89e961d-ee8d-4f66-88db-a5879006f656",
"purchases": [
{
"id": "550e8400-e29b-41d4-a716-446655440001",
"productId": "COFFEE_LATTE",
"amount": 220.0,
"name": "Latte Grande",
"quantity": 2.0,
"price": 110.0,
"unit": "pcs",
"discount": 137.72,
"merchantDiscount": 0.0,
"parentId": null,
"orderId": null,
"mrp": 0.0,
"priceWithoutDiscount": 41.14,
"productSizeId": 2,
"productSizeName": "Grande"
},
{
"id": "550e8400-e29b-41d4-a716-446655440002",
"productId": "PASTRY_CROISSANT",
"amount": 100.0,
"name": "Chocolate Croissant",
"quantity": 1.0,
"price": 100.0,
"unit": "pcs",
"discount": 62.6,
"merchantDiscount": 0.0,
"parentId": null,
"orderId": null,
"mrp": 0.0,
"priceWithoutDiscount": 37.4,
"productSizeId": null,
"productSizeName": null
},
{
"id": "15358e70-d163-4266-b2a0-1614b76d3ccd",
"productId": "JUICE_ORANGE",
"amount": 170.0,
"name": "Fresh Orange Juice",
"quantity": 2.0,
"price": 85.0,
"unit": "pcs",
"discount": 84.68,
"merchantDiscount": 0.0,
"parentId": null,
"orderId": null,
"mrp": null,
"priceWithoutDiscount": 42.66,
"productSizeId": null,
"productSizeName": null
}
],
"total": 205.0,
"totalOriginal": 490.0,
"swipDiscount": 285.0
"loyaltyCalcStats": {
"collectedTotal": 0,
"awardsTotal": 0,
"favoriteDiscount": 0.0,
"discount": 0.0
},
"pointCalcResult": {
"total": 0,
"availablePoints": 232,
"pointsAsDiscount": 200.0,
"pointRate": 1.0,
"lines": []
}
}
4. Recalculate Loyalty Benefits with points for Multi Check
POST /pos-orders/actions/points-multi-recalculate
Calculates loyalty points and discounts for the order based on customer's loyalty status.
Path Parameters
None
Request Headers
Header | Type | Required | Description |
|---|---|---|---|
| string | Yes | Cash authentication token |
| string | Yes |
|
Request Body
{
"parentOrderRef": "sdf2234rsfsdfsd24"
"points": "integer"
}
Request Parameters
Parameter | Type | Required | Description |
|---|---|---|---|
| string | Yes | Parent order reference used for multi calculation |
| integer | No | Points to redeem (default: 0) or specific points |
Response
Status: 200 OK
{
"id": "string",
"merchantOrderId": "string",
"purchases": [
{
"id": "uuid",
"productId": "string",
"amount": "number",
"name": "string",
"quantity": "number",
"price": "number",
"unit": "string",
"discount": "number",
"merchantDiscount": "number",
"priceWithoutDiscount": "number"
}
],
"total": "number",
"totalOriginal": "number",
"swipDiscount": "number",
"loyaltyCalcStats": {
"collectedTotal": "integer",
"awardsTotal": "integer",
"favoriteDiscount": "number",
"discount": "number"
},
"pointCalcResult": {
"total": "integer",
"availablePoints": "integer",
"pointsAsDiscount": "number",
"pointRate": "number"
},
"timeZoneId": "string"
}
Example
POST /pos-orders/f9145570-61b7-479c-8557-91e676afcb17/actions/points-recalculate
Authorization: Bearer <cash-token>
Content-Type: application/json
{
"points": 200
}
{
"id": "a89e961d-ee8d-4f66-88db-a5879006f656",
"merchantOrderId": "a89e961d-ee8d-4f66-88db-a5879006f656",
"purchases": [
{
"id": "550e8400-e29b-41d4-a716-446655440001",
"productId": "COFFEE_LATTE",
"amount": 220.0,
"name": "Latte Grande",
"quantity": 2.0,
"price": 110.0,
"unit": "pcs",
"discount": 137.72,
"merchantDiscount": 0.0,
"parentId": null,
"orderId": null,
"mrp": 0.0,
"priceWithoutDiscount": 41.14,
"productSizeId": 2,
"productSizeName": "Grande"
},
{
"id": "550e8400-e29b-41d4-a716-446655440002",
"productId": "PASTRY_CROISSANT",
"amount": 100.0,
"name": "Chocolate Croissant",
"quantity": 1.0,
"price": 100.0,
"unit": "pcs",
"discount": 62.6,
"merchantDiscount": 0.0,
"parentId": null,
"orderId": null,
"mrp": 0.0,
"priceWithoutDiscount": 37.4,
"productSizeId": null,
"productSizeName": null
},
{
"id": "15358e70-d163-4266-b2a0-1614b76d3ccd",
"productId": "JUICE_ORANGE",
"amount": 170.0,
"name": "Fresh Orange Juice",
"quantity": 2.0,
"price": 85.0,
"unit": "pcs",
"discount": 84.68,
"merchantDiscount": 0.0,
"parentId": null,
"orderId": null,
"mrp": null,
"priceWithoutDiscount": 42.66,
"productSizeId": null,
"productSizeName": null
}
],
"total": 205.0,
"totalOriginal": 490.0,
"loyaltyCalcStats": {
"collectedTotal": 0,
"awardsTotal": 0,
"favoriteDiscount": 0.0,
"discount": 0.0
},
"pointCalcResult": {
"total": 0,
"availablePoints": 232,
"pointsAsDiscount": 200.0,
"pointRate": 1.0,
"lines": []
}
}
5. Mark Order as Closed
POST /pos-orders/{orderId}/actions/mark-as-closed
Marks the POS-controlled order as closed after payment completion.
Path Parameters
Parameter | Type | Required | Description |
|---|---|---|---|
| string | Yes | The order ID to close |
Request Headers
Header | Type | Required | Description |
|---|---|---|---|
| string | Yes | Cash authentication token |
| string | Yes |
|
Request Body
{
"amount": "number",
"tags": ["string"]
}
Request Parameters
Parameter | Type | Required | Description |
|---|