Download OpenAPI specification:
Programmatic access to Livello's autonomous retail infrastructure.
Production Endpoint: https://my.livello.com/api/v1
The future of autonomous retail. Livello's intelligent smart kiosks make fresh meals, snacks, beverages, and daily essentials available around the clock, anywhere people live, work, and stay.
With automatic product recognition, real-time inventory tracking, and a 10-second average checkout time, each compact unit (just 1m²) operates autonomously without on-site staff. Our clients manage all their units digitally and stay connected to their units and users 24/7.
Our solutions are deployed across Europe in canteens, offices, hotels, healthcare facilities, and educational institutions. Built and engineered in Germany, Livello's patented technology provides a reliable foundation for autonomous retail operations.
The Open Platform API gives your systems direct, programmatic access to this infrastructure, so you can build integrations that keep your data in sync and your operations running automatically.
The Open Platform API gives machine-to-machine (M2M) clients access to:
The legacy Promocodes API is retired; use Discounts and Discount Codes instead.
All data is automatically scoped to your organization and its sub-organizations.
POST /auth/token (see Authentication)Authorization: Bearer <token>Example: request a token and list your kiosks
# 1. Get a token
TOKEN=$(curl -s -X POST https://my.livello.com/api/v1/auth/token \
-H "Content-Type: application/json" \
-d '{"client_id":"lv_m2m_abc123","client_secret":"sk_live_xxx","grant_type":"client_credentials"}' \
| jq -r .access_token)
# 2. List kiosks
curl -s https://my.livello.com/api/v1/kiosks \
-H "Authorization: Bearer $TOKEN" | jq
Tokens are valid for 24 hours and are cached server-side, so repeated requests with the same credentials return the same token until it expires. See Authentication for scopes, rate limits, and error handling.
To access the API, you need M2M (machine-to-machine) client credentials. These are provisioned by Livello upon request. Contact the Livello Service Team via Service@livello.com or +49 211 63556321.
Each client receives:
| Credential | Format | Description |
|---|---|---|
| Client ID | lv_m2m_<hex> |
Public identifier for your integration |
| Client Secret | sk_live_<hex> |
Private key used to request access tokens |
| Scopes | e.g. kiosks:read inventory:read |
Controls which endpoints your client can access (see Scopes) |
Store your secret securely. The client secret is delivered once and cannot be recovered. If lost, a new one must be issued.
Optional but recommended for production. Restrict token issuance to specific
IP addresses or CIDR ranges. When enabled, token requests from unlisted IPs are
rejected with 403 Forbidden.
Configured during registration or on request. Contact Livello to set up or modify.
Defaults to 24 hours, configurable per client. See Token Lifecycle for caching, renewal, and revocation details.
The following terms appear throughout the API and reflect how Livello models its autonomous retail operations.
| Term | Description |
|---|---|
| Organization | The root entity for data ownership. Every kiosk, product, user, and transaction belongs to an organization. Organizations can be nested (parent -> child) for multi-level structures. All API data is automatically scoped to your organization and its descendants. |
| Kiosk | A physical smart vending unit identified by a unique serialNumber (e.g., LIV-0042). Each kiosk contains multiple load cells, and each load cell holds a different product. |
| Load Cell | A physical compartment inside a kiosk equipped with a weight sensor. Each load cell is assigned one product line and tracks inventory by measuring weight changes. Identified by a planogramPosition (e.g., A11, B21) and a hardware cellId. |
| Product Meta | The abstract definition of a sellable product: a catalog template shared across all kiosks in an organization. Contains name, manufacturer, category, nutrition, images, and default pricing. This is what the /products endpoints return. |
| Product Line | The binding between a product meta and a load cell. Defines how that product is sold on that particular scale: pricing, tax rules, and capacity. Each load cell is assigned one product line. Visible in the /kiosks/:serialNumber/inventory response. |
| Product | An individual physical item sitting inside the kiosk. Each product belongs to a product line and tracks its own EAN, expiration date, and state (availableForPurchase, sold, removed). The inventory count on a load cell equals the number of products in availableForPurchase state. |
| Transaction | A purchase session representing the full customer lifecycle: payment authorization → door opens → customer takes items → door closes → inventory reconciled → receipt generated. Listed via /transactions. |
| Refill | A restocking session initiated by an operator entering a PIN code on the kiosk. The unit unlocks, the operator adds or removes products, and inventory is recalculated when the door closes. Listed via /refills. |
The OpenAPI specification is available as a downloadable JSON file. You can import it into Postman or any OpenAPI-compatible tool.
Postman import steps:
openapi.json using the Download button at the top of this pageBearer Token and paste your access tokenTip: Tags in the OpenAPI spec map directly to Postman collection folders, making it easy to navigate endpoints by resource type.
Official client libraries for the Livello Open Platform API. Each SDK is generated from the OpenAPI specification, so method signatures and models always match the live API.
| Language | Package | Runtime |
|---|---|---|
| Python | livello-api |
Python 3.8+ (Pydantic models, urllib3) |
| TypeScript | @livello/open-platform-sdk |
Node.js / Browser (Fetch API, full type definitions) |
SDK download links are provided as part of your M2M client onboarding. Contact your Livello account manager if you haven't received them.
Python: install directly from URL with pip:
# Latest version
pip install https://my.livello.com/developer/sdks/livello-python-sdk-latest.zip
# Specific version
pip install https://my.livello.com/developer/sdks/1.0.0/livello-python-sdk-1.0.0.zip
TypeScript: download, extract, and install as a local package:
# Latest version
curl -O https://my.livello.com/developer/sdks/livello-typescript-sdk-latest.zip
unzip livello-typescript-sdk-latest.zip -d livello-sdk
npm install ./livello-sdk
# Specific version
curl -O https://my.livello.com/developer/sdks/1.0.0/livello-typescript-sdk-1.0.0.zip
unzip livello-typescript-sdk-1.0.0.zip -d livello-sdk
npm install ./livello-sdk
Both examples authenticate with client credentials, then list all kiosks, following the same flow shown in the Quick Start using curl.
Python:
from livello_api import ApiClient, Configuration, AuthenticationApi, KiosksApi
from livello_api.models import TokenRequestDto
# 1. Get a token
auth_api = AuthenticationApi()
token_response = auth_api.get_token(
TokenRequestDto(
client_id="lv_m2m_abc123",
client_secret="sk_live_xxx",
grant_type="client_credentials",
)
)
# 2. Configure the client with the token
config = Configuration(access_token=token_response.access_token)
client = ApiClient(config)
# 3. List kiosks
kiosks_api = KiosksApi(client)
response = kiosks_api.get_kiosks()
for kiosk in response.data:
print(f"{kiosk.serial_number}: {kiosk.name}")
TypeScript:
import {
AuthenticationApi,
KiosksApi,
Configuration,
} from "@livello/open-platform-sdk";
// 1. Get a token
const authApi = new AuthenticationApi();
const { accessToken } = await authApi.getToken({
tokenRequestDto: {
clientId: "lv_m2m_abc123",
clientSecret: "sk_live_xxx",
grantType: "client_credentials",
},
});
// 2. Configure the client with the token
const config = new Configuration({ accessToken });
const kiosksApi = new KiosksApi(config);
// 3. List kiosks
const { data } = await kiosksApi.getKiosks();
for (const kiosk of data) {
console.log(`${kiosk.serialNumber}: ${kiosk.name}`);
}
Neither SDK sets a default request timeout, so a stalled connection can hang indefinitely. Set one per call.
Python (_request_timeout: seconds, or a (connect, read) tuple):
response = kiosks_api.get_kiosks(_request_timeout=(3, 10))
TypeScript (an AbortSignal passed as the second argument):
const { data } = await kiosksApi.getKiosks({}, { signal: AbortSignal.timeout(10000) });
Warning:
Configuration.debug = Truelogs raw HTTP traffic, including theAuthorizationbearer token and the token request body (your client secret). Never enable it in production or with real credentials.
Obtain and manage API access tokens. You need M2M client credentials before using the API. See Client Registration for how to obtain your client ID, client secret, and scopes.
Exchange your client_id and client_secret for a JWT access token.
The token is included as a Bearer token in the Authorization header of all subsequent requests.
POST /auth/token
Content-Type: application/json
{
"client_id": "lv_m2m_abc123",
"client_secret": "sk_live_xxxxxxxxxxxxxxxx",
"grant_type": "client_credentials"
}
{
"access_token": "eyJhbGciOiJIUzI1NiIs...",
"token_type": "Bearer",
"expires_in": 86400,
"scope": "kiosks:read inventory:read"
}
GET /kiosks
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...
| Aspect | Details |
|---|---|
| Expiration | 24 hours (default, configurable per client) |
| Caching | Tokens are cached server-side. Repeated requests with the same credentials return the same JWT until it expires. |
| Renewal | Request a new token after expiry using the same credentials. |
| Revocation | Immediate. Cached tokens are invalidated on the next API call. New token requests are rejected. |
Your client is granted specific scopes that determine which endpoints are accessible.
Requesting an endpoint without the required scope returns 403 Forbidden.
| Scope | Description |
|---|---|
kiosks:read |
List kiosks, get kiosk details, capacity, and current session |
inventory:read |
Get kiosk inventory (load cells, product quantities, pricing) and the low/zero inventory report |
products:read |
Browse product catalog, get product detail and images |
products:write |
Create, update, and delete product catalog entries; update product line prices |
transactions:read |
List and retrieve purchase transactions |
refills:read |
List and retrieve refill/restocking sessions |
organizations:read |
List organizations, get organization detail |
organizations:write |
Create and update organizations |
users:read |
List users, get user detail |
users:write |
Create and update users |
alerts:read |
List alerts and retrieve alert type definitions |
reports:read |
Access analytics endpoints (sales, transactions, refills, product statistics, temperature); the low/zero inventory report requires inventory:read |
discounts:read |
Discount type catalog, instances, priority overview, resolution preview |
discounts:write |
Create, update, suspend, resume, delete, and reorder discount instances |
discount-codes:read |
List discount codes |
discount-codes:write |
Create, update, and delete discount codes |
Optional. When configured, only token requests from allowed IP addresses or CIDR
ranges are accepted. Requests from unlisted IPs receive 403 Forbidden.
IP restrictions are enforced at token issuance, not on individual API calls. Contact Livello to configure (see Client Registration).
| Scope | Limit |
|---|---|
| All API endpoints | 1,000 requests per hour per client |
POST /auth/token |
10 requests per minute per client |
All API responses include standard rate limit headers:
| Header | Description |
|---|---|
RateLimit-Limit |
Maximum requests allowed in the current window |
RateLimit-Remaining |
Requests remaining in the current window |
RateLimit-Reset |
Seconds until the window resets |
Retry-After |
Seconds to wait (only present on 429 responses) |
Exceeding either limit returns 429 Too Many Requests.
All errors follow the RFC 7807 Problem Details standard:
{
"type": "https://api.livello.com/errors/forbidden",
"title": "Forbidden",
"status": 403,
"detail": "Insufficient scope. Required: kiosks:read",
"instance": "/api/v1/kiosks"
}
Exchange M2M client credentials for a JWT access token. Tokens are cached server-side, so repeated requests return the same token until expiry.
| client_id required | string The public client ID assigned to the M2M client |
| client_secret required | string The client secret for authentication |
| grant_type required | string Must be "client_credentials" (OAuth2 grant type) |
{- "client_id": "{{testClientId}}",
- "client_secret": "{{testClientSecret}}",
- "grant_type": "client_credentials"
}{- "access_token": "eyJhbGciOiJIUzI1NiIs...",
- "token_type": "Bearer",
- "expires_in": 86400,
- "scope": "kiosks:read inventory:read"
}A kiosk is a physical smart vending unit identified by a unique serial number
(e.g., LIV-0042). Each kiosk contains multiple load cells, and each load cell
holds one product.
Query your kiosk fleet: list units, get details, check real-time inventory, and view the current or most recent session.
See also: Products · Product Lines · Alerts
| sort | number 1 = ASC, -1 = DESC |
| sortColumn | string Sort by: name, serialNumber, networkLastOnline, organizationName, latestTemperature, todaySalesTotal |
| name | string Filter by name (partial match) |
| limit | number Example: limit=25 Page size |
| page | number Example: page=1 Page number (1-based) |
{- "total": 42,
- "data": [
- {
- "id": 1,
- "name": "Lobby Fridge",
- "serialNumber": "LIV-0042",
- "networkLastOnline": "2025-06-15T10:30:00.000Z",
- "online": true,
- "doorStatus": "closed",
- "latestTemperature": 4.5,
- "organizationName": "SuperMarkt GmbH",
- "organizationCurrency": "EUR",
- "todaySalesTotal": 127.5,
- "isDoubleDoor": true,
- "cabinetType": "FRIDGE"
}
]
}| serialNumber required | string Kiosk serial number (e.g., LIV-0042) |
{- "_id": "LIV-0042",
- "name": "Lobby Fridge",
- "orgId": "123",
- "serialNumber": "LIV-0042",
- "isDoubleDoor": true,
- "cabinetType": "FRIDGE",
- "inventory": {
- "loadCells": [
- {
- "cellId": "12",
- "maxQty": 12,
- "occupancy": 8,
- "planogramPosition": "A1",
- "surfaceSize": "100",
- "products": [
- {
- "_id": "pl-789"
}
], - "priceTag": "3.50",
- "productLine": {
- "_id": "789",
- "name": "Coca-Cola 0.33L",
- "articleNumber": "ART-001",
- "packagingOptions": {
- "ean": "4005808262106",
- "grossWeightGrams": 200,
- "tolerancePercentage": 5,
- "packageWeightGrams": 50
}, - "energy": "200 kcal",
- "fat": "5g",
- "fatSaturated": "2g",
- "carbo": "30g",
- "carboSugar": "15g"
}
}
]
}, - "controller": {
- "preAuth": 40,
- "tabletLang": "de",
- "tabletFont": "Arial",
- "paymentType": "CreditOrDebitCard",
- "minimumAge": 18,
- "serviceCheck": {
- "enabled": true
}
}, - "ownerOrganization": {
- "_id": "123",
- "name": "SuperMarkt GmbH",
- "currency": "EUR",
- "support": {
- "email": "support@org.com",
- "hotline": "+49123456789"
}, - "contact": {
- "supportEmail": "support@org.com",
- "supportPhoneNumber": "+49123456789"
}, - "kioskInitScreen": {
- "headerTextColor": "#000000",
- "bgColor": "#FFFFFF",
- "bodyTextColor": "#000000"
}
}
}| serialNumber required | string Kiosk serial number (e.g., LIV-0042) |
[- {
- "loadCellId": 1,
- "planogramPosition": "A1",
- "surfaceSize": "100.00",
- "cellId": 456,
- "productLineData": {
- "maxCapacity": 12,
- "availableCount": 8,
- "productInfo": {
- "name": "Coca-Cola 0.33L",
- "images": [
- "string"
], - "price": 3.5,
- "defaultPrice": 3.5,
- "productLineId": 0,
- "productLineMetaId": 0,
- "description": "Refreshing carbonated drink",
- "category": "Beverages",
- "manufacturer": "The Coca-Cola Company",
- "articleNumber": "ART-001",
- "organizationName": "SuperMarkt GmbH",
- "nutrition": {
- "energy": "200 kcal",
- "fat": "5g",
- "fatSaturated": "2g",
- "carbo": "30g",
- "carboSugar": "15g",
- "fiber": "2g",
- "protein": "3g",
- "salt": "0.5g"
}, - "dietaryInfo": {
- "glutenFree": false,
- "vegetarian": true,
- "vegan": false,
- "allergens": "Nuts, Milk",
- "ingredientsList": "Sugar, Water, Cocoa Butter..."
}, - "packaging": {
- "ean": "4005808262106",
- "description": "100g box",
- "unitCount": 10,
- "shelfLifeDays": 180,
- "netWeightGrams": 100,
- "grossWeightGrams": 150,
- "packageWeightGrams": 50,
- "netWeightGramsUnit": "g",
- "tolerancePercentage": 5,
- "state": "active"
}, - "capacities": [
- {
- "surfaceSize": "100.00",
- "units": 12
}
]
}
}
}
]| serialNumber required | string Kiosk serial number (e.g., LIV-0042) |
| maxAgeMinutes | number Example: maxAgeMinutes=30 Max age in minutes for a session to be considered recent (default: 30) |
{- "status": "CLOSED",
- "type": "transaction",
- "createdAt": "2025-10-15T09:00:00.000Z",
- "updatedAt": "2025-10-15T09:30:00.000Z",
- "isTerminal": true,
- "details": {
- "sessionClosedAt": "2025-10-15T09:30:00.000Z",
- "endedWithPurchase": true,
- "externalTransactionId": "ext-txn-abc123"
}
}A product (product meta) is the catalog definition of a sellable item, shared across all kiosks in your organization. Contains name, manufacturer, category, nutrition data, images, and default pricing.
Browse, create, update, and delete catalog entries.
See also: Product Lines · Kiosks
| name | string Filter by product name (partial match) |
| category | string Filter by category |
| manufacturer | string Filter by manufacturer |
| sort | number Enum: 1 -1 1 = ASC, -1 = DESC (default: 1) |
| sortBy | string Enum: "name" "manufacturer" "weight" "cost" "price" Column to sort by. Unknown values fall back to the default (name). |
| limit | number Example: limit=25 Page size (max 100) |
| page | number Example: page=1 Page number (1-based) |
{- "total": 156,
- "data": [
- {
- "id": 10,
- "name": "Coca-Cola 0.33L",
- "description": "Carbonated soft drink",
- "category": "Beverages",
- "manufacturer": "The Coca-Cola Company",
- "articleNumber": "ART-001",
- "organizationId": 5,
- "organizationName": "SuperMarkt GmbH",
- "organizationCurrency": "EUR",
- "netPrice": "1.50",
- "defaultPrice": 1.5,
- "vatValue": 19,
- "price": "1.79",
- "cost": 0.85,
- "weight": 330,
- "weightUnit": "g",
- "updatedAt": "2025-03-15T10:00:00.000Z",
- "createdAt": "2025-01-01T08:00:00.000Z",
}
]
}Required fields: name, organizationId, manufacturer, pricing (defaultPrice, defaultCost), packaging (grossWeightGrams, netWeightGrams, netWeightGramsUnit), capacities (at least one entry).
| name required | string Product name | ||||||||||||||||||
| manufacturer required | string Manufacturer | ||||||||||||||||||
| organizationId required | number Organization ID | ||||||||||||||||||
required | object Pricing info (required for creation) | ||||||||||||||||||
| |||||||||||||||||||
required | object Packaging info (required for creation) | ||||||||||||||||||
| |||||||||||||||||||
required | Array of objects (ProductMetaCapacityInput) Load cell capacities (required for creation) | ||||||||||||||||||
Array
| |||||||||||||||||||
| description | string | ||||||||||||||||||
| category | string | ||||||||||||||||||
| articleNumber | string | ||||||||||||||||||
object (ProductMetaNutritionInput) | |||||||||||||||||||
| |||||||||||||||||||
object (ProductMetaDietaryInfoInput) | |||||||||||||||||||
| |||||||||||||||||||
Array of objects (ProductMetaImageInput) | |||||||||||||||||||
Array
| |||||||||||||||||||
| copyImagesFromMetaId | number Copy image(s) from this source meta id when no images are supplied | ||||||||||||||||||
{- "name": "Coca-Cola 0.33L",
- "organizationId": 42,
- "manufacturer": "The Coca-Cola Company",
- "pricing": {
- "defaultPrice": 1.79,
- "defaultCost": 0.85
}, - "packaging": {
- "grossWeightGrams": 345,
- "netWeightGrams": 330,
- "netWeightGramsUnit": "ml"
}, - "capacities": [
- {
- "surfaceSize": 1,
- "units": 6
}
]
}{- "id": 10,
- "organizationId": 5,
- "organizationName": "SuperMarkt GmbH",
- "organizationCurrency": "EUR",
- "name": "Coca-Cola 0.33L",
- "description": "string",
- "category": "string",
- "manufacturer": "string",
- "articleNumber": "string",
- "nutrition": {
- "energy": "139 kcal",
- "fat": "0",
- "fatSaturated": "0",
- "carbo": "35",
- "carboSugar": "35",
- "fiber": "0",
- "protein": "0",
- "salt": "0"
}, - "dietaryInfo": {
- "glutenFree": true,
- "vegetarian": true,
- "vegan": true,
- "allergens": "none",
- "ingredientsList": "Water, sugar, carbon dioxide"
}, - "pricing": {
- "netPrice": 1.5,
- "defaultPrice": 1.785,
- "defaultCost": 0.85,
- "defaultVat_id": 2,
- "vatName": "Standard",
- "vatValue": 19
}, - "createdAt": "2025-01-01T08:00:00.000Z",
- "updatedAt": "2025-03-15T10:00:00.000Z",
- "capacities": [
- {
- "surfaceSize": "10.00",
- "units": 8
}
], - "packaging": [
- {
- "ean": "5449000000996",
- "description": "string",
- "unitCount": 1,
- "shelfLifeDays": 180,
- "netWeightGrams": 330,
- "grossWeightGrams": 350,
- "packageWeightGrams": 20,
- "netWeightGramsUnit": "g",
- "tolerancePercentage": 5,
- "state": "active",
- "createdAt": "2025-01-01T08:00:00.000Z",
- "updatedAt": "2025-03-15T10:00:00.000Z"
}
], - "assignedKiosks": [
- {
- "id": 271,
- "name": "Office Berlin",
- "serialNumber": "LIV-0042"
}
]
}| id required | number Product line meta ID |
{- "id": 10,
- "organizationId": 5,
- "organizationName": "SuperMarkt GmbH",
- "organizationCurrency": "EUR",
- "name": "Coca-Cola 0.33L",
- "description": "string",
- "category": "string",
- "manufacturer": "string",
- "articleNumber": "string",
- "nutrition": {
- "energy": "139 kcal",
- "fat": "0",
- "fatSaturated": "0",
- "carbo": "35",
- "carboSugar": "35",
- "fiber": "0",
- "protein": "0",
- "salt": "0"
}, - "dietaryInfo": {
- "glutenFree": true,
- "vegetarian": true,
- "vegan": true,
- "allergens": "none",
- "ingredientsList": "Water, sugar, carbon dioxide"
}, - "pricing": {
- "netPrice": 1.5,
- "defaultPrice": 1.785,
- "defaultCost": 0.85,
- "defaultVat_id": 2,
- "vatName": "Standard",
- "vatValue": 19
}, - "createdAt": "2025-01-01T08:00:00.000Z",
- "updatedAt": "2025-03-15T10:00:00.000Z",
- "capacities": [
- {
- "surfaceSize": "10.00",
- "units": 8
}
], - "packaging": [
- {
- "ean": "5449000000996",
- "description": "string",
- "unitCount": 1,
- "shelfLifeDays": 180,
- "netWeightGrams": 330,
- "grossWeightGrams": 350,
- "packageWeightGrams": 20,
- "netWeightGramsUnit": "g",
- "tolerancePercentage": 5,
- "state": "active",
- "createdAt": "2025-01-01T08:00:00.000Z",
- "updatedAt": "2025-03-15T10:00:00.000Z"
}
], - "assignedKiosks": [
- {
- "id": 271,
- "name": "Office Berlin",
- "serialNumber": "LIV-0042"
}
]
}| id required | number Product line meta ID |
| name | string Product name | ||||||||||||||||||
| description | string | ||||||||||||||||||
| category | string | ||||||||||||||||||
| manufacturer | string Manufacturer | ||||||||||||||||||
| articleNumber | string | ||||||||||||||||||
| organizationId | number Organization ID | ||||||||||||||||||
object (ProductMetaNutritionInput) | |||||||||||||||||||
| |||||||||||||||||||
object (ProductMetaDietaryInfoInput) | |||||||||||||||||||
| |||||||||||||||||||
object Pricing info (required for creation) | |||||||||||||||||||
| |||||||||||||||||||
Array of objects (ProductMetaImageInput) | |||||||||||||||||||
Array
| |||||||||||||||||||
object Packaging info (required for creation) | |||||||||||||||||||
| |||||||||||||||||||
Array of objects (ProductMetaCapacityInput) Load cell capacities (required for creation) | |||||||||||||||||||
Array
| |||||||||||||||||||
| copyImagesFromMetaId | number Copy image(s) from this source meta id when no images are supplied | ||||||||||||||||||
{- "name": "Coca-Cola Zero 0.33L"
}{- "id": 10,
- "organizationId": 5,
- "organizationName": "SuperMarkt GmbH",
- "organizationCurrency": "EUR",
- "name": "Coca-Cola 0.33L",
- "description": "string",
- "category": "string",
- "manufacturer": "string",
- "articleNumber": "string",
- "nutrition": {
- "energy": "139 kcal",
- "fat": "0",
- "fatSaturated": "0",
- "carbo": "35",
- "carboSugar": "35",
- "fiber": "0",
- "protein": "0",
- "salt": "0"
}, - "dietaryInfo": {
- "glutenFree": true,
- "vegetarian": true,
- "vegan": true,
- "allergens": "none",
- "ingredientsList": "Water, sugar, carbon dioxide"
}, - "pricing": {
- "netPrice": 1.5,
- "defaultPrice": 1.785,
- "defaultCost": 0.85,
- "defaultVat_id": 2,
- "vatName": "Standard",
- "vatValue": 19
}, - "createdAt": "2025-01-01T08:00:00.000Z",
- "updatedAt": "2025-03-15T10:00:00.000Z",
- "capacities": [
- {
- "surfaceSize": "10.00",
- "units": 8
}
], - "packaging": [
- {
- "ean": "5449000000996",
- "description": "string",
- "unitCount": 1,
- "shelfLifeDays": 180,
- "netWeightGrams": 330,
- "grossWeightGrams": 350,
- "packageWeightGrams": 20,
- "netWeightGramsUnit": "g",
- "tolerancePercentage": 5,
- "state": "active",
- "createdAt": "2025-01-01T08:00:00.000Z",
- "updatedAt": "2025-03-15T10:00:00.000Z"
}
], - "assignedKiosks": [
- {
- "id": 271,
- "name": "Office Berlin",
- "serialNumber": "LIV-0042"
}
]
}A product line binds a product to a specific load cell inside a kiosk. It defines how that product is sold on that particular scale: pricing, tax rate, and capacity. Each load cell has exactly one product line.
The product line ID is separate from the product (meta) ID; use the inventory endpoint under Kiosks to discover product line IDs.
Inserts a new price history record for a product line (the binding of a product to a load cell). The product line ID is NOT the same as the product meta ID. It identifies a specific slot in a kiosk.
| id required | number Product line ID (not product meta ID) |
| price required | number New gross price including VAT |
| productLineId | number Product line ID (overridden by URL param in REST; omit for REST calls) |
| validFrom | string Valid from (ISO 8601, defaults to now) |
| validTo | string Valid until (ISO 8601, null = indefinite) |
{- "price": 1.99
}{- "success": true
}A transaction represents a complete purchase session: payment authorization → door opens → customer takes items → door closes → inventory reconciled → receipt generated.
List and retrieve transaction history with line items and payment details.
Supports timezone conversion via the x-timezone header (default: Europe/Berlin).
See also: Kiosks · Analytics: Sales · Analytics: Transactions
| sort | number Enum: 1 -1 1 = ASC, -1 = DESC (default: -1) |
| sortBy | string Enum: "created" "total" "kioskName" "type" Column to sort by. Unknown values fall back to the default (created). |
| startDate | string Example: startDate=2025-01-01T00:00:00.000Z Start date (ISO 8601) |
| endDate | string Example: endDate=2025-12-31T23:59:59.999Z End date (ISO 8601) |
| kioskSerialNumbers | string Comma-separated kiosk serial numbers |
| limit | number Example: limit=25 Page size |
| skip | number Example: skip=0 Pagination offset (0-based) |
| x-timezone | string IANA timezone for date conversion (default: Europe/Berlin) |
{- "total": 523,
- "membercardList": [
- "MC-001",
- "MC-002"
], - "data": [
- {
- "id": 1001,
- "created": "2025-03-18T14:30:00.000Z",
- "total": 45.99,
- "discountTotal": 5,
- "session": {
- "details": {
- "promoCode": {
- "code": "SPRING25"
}
}
}, - "type": "immediate_guarantee",
- "userId": 0,
- "kiosk": {
- "id": 1,
- "name": "Lobby Fridge",
- "serialNumber": "LIV-0042"
}, - "paymentMethod": {
- "isPaid": true,
- "membercardId": "MC-001",
- "paymentCardType": "Credit",
- "cardType": "Visa",
- "paymentType": "string",
- "externalTransactionId": "string"
}, - "itemsPurchased": [
- {
- "price": 3.5,
- "vat": 0.56,
- "productLine": {
- "id": 789,
- "productLineMetaId": 0,
- "name": "Coca-Cola 0.33L",
- "articleNumber": "ART-001",
- "manufacturer": "The Coca-Cola Company",
- "imageUrl": "string"
}, - "kiosk": {
- "id": 1,
- "name": "Lobby Fridge",
- "serialNumber": "LIV-0042"
}, - "productPosition": "A1"
}
]
}
]
}| id required | number Transaction ID |
| x-timezone | string IANA timezone for date conversion (default: Europe/Berlin) |
{- "id": 1001,
- "created": "2025-03-18T14:30:00.000Z",
- "total": 45.99,
- "discountTotal": 5,
- "session": {
- "details": {
- "promoCode": {
- "code": "SPRING25"
}
}
}, - "type": "immediate_guarantee",
- "userId": 0,
- "kiosk": {
- "id": 1,
- "name": "Lobby Fridge",
- "serialNumber": "LIV-0042"
}, - "paymentMethod": {
- "isPaid": true,
- "membercardId": "MC-001",
- "paymentCardType": "Credit",
- "cardType": "Visa",
- "paymentType": "string",
- "externalTransactionId": "string"
}, - "itemsPurchased": [
- {
- "price": 3.5,
- "vat": 0.56,
- "productLine": {
- "id": 789,
- "productLineMetaId": 0,
- "name": "Coca-Cola 0.33L",
- "articleNumber": "ART-001",
- "manufacturer": "The Coca-Cola Company",
- "imageUrl": "string"
}, - "kiosk": {
- "id": 1,
- "name": "Lobby Fridge",
- "serialNumber": "LIV-0042"
}, - "productPosition": "A1"
}
]
}A refill is a restocking session initiated by an operator entering a PIN on the kiosk. The unit unlocks, the operator adds or removes products, and inventory is recalculated when the door closes.
List and retrieve refill history with item-level detail.
Supports timezone conversion via the x-timezone header (default: Europe/Berlin).
See also: Kiosks · Analytics: Refills
| sort | number 1 = ASC, -1 = DESC (default: -1) |
| startDate | string Example: startDate=2025-01-01T00:00:00.000Z Start date (ISO 8601) |
| endDate | string Example: endDate=2025-12-31T23:59:59.999Z End date (ISO 8601) |
| kioskSerialNumbers | string Comma-separated kiosk serial numbers |
| limit | number Example: limit=25 Page size |
| skip | number Example: skip=0 Pagination offset (0-based) |
| x-timezone | string IANA timezone for date conversion (default: Europe/Berlin) |
{- "total": 87,
- "data": [
- {
- "id": 201,
- "created": "2025-03-18T08:15:00.000Z",
- "type": "manual",
- "kiosk": {
- "id": 1,
- "name": "Lobby Fridge",
- "serialNumber": "LIV-0042"
}, - "itemsReplenished": [
- {
- "productLineId": 0,
- "productLineMetaId": 0,
- "productName": "Coca-Cola 0.33L",
- "articleNumber": "ART-001",
- "imageUrl": "string",
- "status": "Added",
- "count": 5,
- "cellId": 0,
- "weight": 250.5,
- "cost": 0.85,
- "totalCost": 4.25
}
]
}
]
}| id required | number Refill ID |
| x-timezone | string IANA timezone for date conversion (default: Europe/Berlin) |
{- "id": 201,
- "created": "2025-03-18T08:15:00.000Z",
- "type": "manual",
- "kiosk": {
- "id": 1,
- "name": "Lobby Fridge",
- "serialNumber": "LIV-0042"
}, - "itemsReplenished": [
- {
- "productLineId": 0,
- "productLineMetaId": 0,
- "productName": "Coca-Cola 0.33L",
- "articleNumber": "ART-001",
- "imageUrl": "string",
- "status": "Added",
- "count": 5,
- "cellId": 0,
- "weight": 250.5,
- "cost": 0.85,
- "totalCost": 4.25
}
]
}An organization is the root entity for data ownership. Every kiosk, product, user, and transaction belongs to an organization. Organizations can be nested (parent → child) for multi-level structures.
All API data is automatically scoped to your organization and its descendants.
| sortBy | string Enum: "name" "kioskCount" Column to sort by. Unknown values fall back to the default (name). |
| sort | number Enum: 1 -1 1 = ASC, -1 = DESC (default: 1) |
| postalCode | string Postal code filter |
| country | string Country filter |
| city | string City filter |
| organizationType | string Filter by org type |
| name | string Search by name |
| limit | number Pagination size |
| skip | number Pagination offset |
{- "total": 25,
- "data": [
- {
- "id": 42,
- "name": "SuperMarkt GmbH",
- "slug": "supermarkt-gmbh",
- "type": "CLIENT",
- "imageUrl": "string",
- "currency": "EUR",
- "description": "string",
- "kioskCount": 3,
- "parentOrg": 1,
- "parentOrgName": "Livello GmbH",
- "address": {
- "address": "Friedrichstraße 123",
- "postalCode": "10117",
- "city": "Berlin",
- "state": "Berlin",
- "country": "Germany"
}
}
]
}Required fields: name, type, currency, address.country. parentOrg is required for non-root users.
Organization creation input
| name required | string Organization name | ||||||||||||
| type required | string Enum: "general" "client" "manufacturer" Organization type | ||||||||||||
| currency required | string Enum: "eur" "chf" "gbp" "usd" "czk" Payment currency | ||||||||||||
required | object Organization address (required for creation) | ||||||||||||
| |||||||||||||
| slug | string | ||||||||||||
| description | string | ||||||||||||
| eanPrefix | string | ||||||||||||
object (OrganizationContactInput) | |||||||||||||
| |||||||||||||
| parentOrg | number or null Parent organization ID. Required for non-superadmin users on create. Cannot be nullified on update. | ||||||||||||
| privacyPolicyUrl | string | ||||||||||||
| termsAndConditionsUrl | string | ||||||||||||
{- "name": "SuperMarkt GmbH",
- "type": "client",
- "currency": "eur",
- "parentOrg": 42,
- "address": {
- "country": "Germany",
- "countryCode": "DE"
}
}{- "id": 42,
- "name": "SuperMarkt GmbH",
- "slug": "supermarkt-gmbh",
- "type": "CLIENT",
- "description": "string",
- "imageUrl": "string",
- "address": {
- "address": "Friedrichstraße 123",
- "postalCode": "10117",
- "city": "Berlin",
- "state": "Berlin",
- "country": "Germany"
}, - "currency": "EUR",
- "parentOrg": 1,
- "parentOrgName": "Livello GmbH",
- "contact": {
- "email": "info@supermarkt.de",
- "phoneNumber": "+49 30 1234567",
- "supportEmail": "support@supermarkt.de",
- "supportPhoneNumber": "+49 30 7654321"
}, - "kioskInitScreen": {
- "headerURI": "string",
- "headerTextColor": "#FFFFFF",
- "bodyTextColor": "#000000",
- "bgURI": "string",
- "bgColor": "#FFFFFF"
}, - "privacyPolicyUrl": "string",
- "appleId": "string"
}| id required | number |
{- "id": 42,
- "name": "SuperMarkt GmbH",
- "slug": "supermarkt-gmbh",
- "type": "CLIENT",
- "description": "string",
- "imageUrl": "string",
- "address": {
- "address": "Friedrichstraße 123",
- "postalCode": "10117",
- "city": "Berlin",
- "state": "Berlin",
- "country": "Germany"
}, - "currency": "EUR",
- "parentOrg": 1,
- "parentOrgName": "Livello GmbH",
- "contact": {
- "email": "info@supermarkt.de",
- "phoneNumber": "+49 30 1234567",
- "supportEmail": "support@supermarkt.de",
- "supportPhoneNumber": "+49 30 7654321"
}, - "kioskInitScreen": {
- "headerURI": "string",
- "headerTextColor": "#FFFFFF",
- "bodyTextColor": "#000000",
- "bgURI": "string",
- "bgColor": "#FFFFFF"
}, - "privacyPolicyUrl": "string",
- "appleId": "string"
}| id required | number |
| name | string Organization name | ||||||||||||
| slug | string | ||||||||||||
| type | string Enum: "general" "client" "manufacturer" Organization type | ||||||||||||
| description | string | ||||||||||||
| currency | string Enum: "eur" "chf" "gbp" "usd" "czk" Payment currency | ||||||||||||
| eanPrefix | string | ||||||||||||
object Organization address (required for creation) | |||||||||||||
| |||||||||||||
object (OrganizationContactInput) | |||||||||||||
| |||||||||||||
| parentOrg | number or null Parent organization ID. Required for non-superadmin users on create. Cannot be nullified on update. | ||||||||||||
| privacyPolicyUrl | string | ||||||||||||
| termsAndConditionsUrl | string | ||||||||||||
{- "name": "New Org Name"
}{- "id": 42,
- "name": "SuperMarkt GmbH",
- "slug": "supermarkt-gmbh",
- "type": "CLIENT",
- "description": "string",
- "imageUrl": "string",
- "address": {
- "address": "Friedrichstraße 123",
- "postalCode": "10117",
- "city": "Berlin",
- "state": "Berlin",
- "country": "Germany"
}, - "currency": "EUR",
- "parentOrg": 1,
- "parentOrgName": "Livello GmbH",
- "contact": {
- "email": "info@supermarkt.de",
- "phoneNumber": "+49 30 1234567",
- "supportEmail": "support@supermarkt.de",
- "supportPhoneNumber": "+49 30 7654321"
}, - "kioskInitScreen": {
- "headerURI": "string",
- "headerTextColor": "#FFFFFF",
- "bodyTextColor": "#000000",
- "bgURI": "string",
- "bgColor": "#FFFFFF"
}, - "privacyPolicyUrl": "string",
- "appleId": "string"
}A user represents an account within your organization. The API supports managing consumer users: end customers who interact with kiosks.
List, create, and update users within your organization scope.
| skip | number Example: skip=0 Pagination offset (0-based) |
| limit | number Example: limit=25 Page size |
| sort | number Enum: 1 -1 1 = ASC, -1 = DESC |
| sortBy | string Enum: "firstName" "role" "organizationName" "updated" Column to sort by. Unknown values fall back to the default (firstName). |
| name | string Filter by name (partial match) |
| role | string Filter by role (admin, superadmin, consumer, operator) |
{- "total": 48,
- "data": [
- {
- "id": 1,
- "email": "john@example.com",
- "firstName": "John",
- "lastName": "Doe",
- "role": "admin",
- "organizationName": "SuperMarkt GmbH",
- "status": "ACTIVE",
- "termsAccepted": true,
- "mobile": "+49 170 1234567",
- "avatarUrl": "string",
- "note": "string",
- "lang": "en",
- "created": "2025-01-15T10:00:00.000Z",
- "updated": "2025-06-20T14:30:00.000Z"
}
]
}Creates a consumer user in the specified organization. Required fields: email, firstName, lastName, organizationId, status, lang.
| email required | string User email address | ||||||||
| firstName required | string First name | ||||||||
| lastName required | string Last name | ||||||||
| status required | string Enum: "ACTIVE" "INACTIVE" User status | ||||||||
| lang required | string Enum: "en" "de" "it" "fr" Language | ||||||||
| organizationId required | number Organization ID to assign the user to | ||||||||
| mobile | string | ||||||||
| note | string | ||||||||
| avatarUrl | string | ||||||||
| membercards | Array of strings Membercard IDs | ||||||||
object (UserAddressInput) | |||||||||
| |||||||||
{- "email": "john.doe@example.com",
- "firstName": "John",
- "lastName": "Doe",
- "organizationId": 42,
- "status": "ACTIVE",
- "lang": "en"
}{- "id": 1,
- "email": "john@example.com",
- "firstName": "John",
- "lastName": "Doe",
- "status": "ACTIVE",
- "lang": "en",
- "termsAccepted": true,
- "mobile": "+49 170 1234567",
- "avatarUrl": "string",
- "hasValidPaymentMethod": false,
- "note": "string",
- "consent": [
- {
- "hasAcceptedTerms": true,
- "consentTimestamp": "2025-01-15T10:00:00.000Z",
- "hasSubscribedForUpdates": false,
- "orgId": 42
}
], - "address": {
- "address": "Friedrichstraße 123",
- "city": "Berlin",
- "postalCode": "10117",
- "country": "Germany"
}, - "membercards": [
- "MC-001"
], - "rolesInOrganizations": [
- {
- "id": 1,
- "organizationId": 42,
- "organizationName": "SuperMarkt GmbH",
- "role": "admin",
- "status": "active"
}
], - "created": "2025-01-15T10:00:00.000Z",
- "updated": "2025-06-20T14:30:00.000Z"
}{- "id": 1,
- "email": "john@example.com",
- "firstName": "John",
- "lastName": "Doe",
- "status": "ACTIVE",
- "lang": "en",
- "termsAccepted": true,
- "mobile": "+49 170 1234567",
- "avatarUrl": "string",
- "hasValidPaymentMethod": false,
- "note": "string",
- "consent": [
- {
- "hasAcceptedTerms": true,
- "consentTimestamp": "2025-01-15T10:00:00.000Z",
- "hasSubscribedForUpdates": false,
- "orgId": 42
}
], - "address": {
- "address": "Friedrichstraße 123",
- "city": "Berlin",
- "postalCode": "10117",
- "country": "Germany"
}, - "membercards": [
- "MC-001"
], - "rolesInOrganizations": [
- {
- "id": 1,
- "organizationId": 42,
- "organizationName": "SuperMarkt GmbH",
- "role": "admin",
- "status": "active"
}
], - "created": "2025-01-15T10:00:00.000Z",
- "updated": "2025-06-20T14:30:00.000Z"
}| id required | number User ID |
string User email address | |||||||||
| firstName | string First name | ||||||||
| lastName | string Last name | ||||||||
| mobile | string | ||||||||
| note | string | ||||||||
| avatarUrl | string | ||||||||
| status | string Enum: "ACTIVE" "INACTIVE" User status | ||||||||
| membercards | Array of strings Membercard IDs | ||||||||
| lang | string Enum: "en" "de" "it" "fr" Language | ||||||||
object (UserAddressInput) | |||||||||
| |||||||||
{- "firstName": "Jane",
- "lastName": "Smith"
}{- "id": 1,
- "email": "john@example.com",
- "firstName": "John",
- "lastName": "Doe",
- "status": "ACTIVE",
- "lang": "en",
- "termsAccepted": true,
- "mobile": "+49 170 1234567",
- "avatarUrl": "string",
- "hasValidPaymentMethod": false,
- "note": "string",
- "consent": [
- {
- "hasAcceptedTerms": true,
- "consentTimestamp": "2025-01-15T10:00:00.000Z",
- "hasSubscribedForUpdates": false,
- "orgId": 42
}
], - "address": {
- "address": "Friedrichstraße 123",
- "city": "Berlin",
- "postalCode": "10117",
- "country": "Germany"
}, - "membercards": [
- "MC-001"
], - "rolesInOrganizations": [
- {
- "id": 1,
- "organizationId": 42,
- "organizationName": "SuperMarkt GmbH",
- "role": "admin",
- "status": "active"
}
], - "created": "2025-01-15T10:00:00.000Z",
- "updated": "2025-06-20T14:30:00.000Z"
}An alert is an operational notification generated by a kiosk: inventory
warnings, temperature issues, connectivity problems, and more. Each alert has
a severity (low, mid, high) and a lifecycle: open → raised → resolved.
List alerts with filtering by kiosk, type, severity, and status. Retrieve alert type definitions for reference.
See also: Kiosks
| offset | number Example: offset=0 Pagination offset (0-based) |
| limit | number Example: limit=50 Page size |
| kioskSerialNumbers | string Comma-separated kiosk serial numbers |
| types | string Comma-separated alert types |
| severities | string Comma-separated severities (low, mid, high) |
| statuses | string Comma-separated statuses (open, raised, resolved) |
| isAck | boolean Filter by acknowledgment status |
| startDateFrom | string Alerts created after (ISO 8601) |
| startDateTo | string Alerts created before (ISO 8601) |
| orderBy | string Sort field: startDate or createdAt |
| orderDirection | string ASC or DESC (default: DESC) |
{- "total": 156,
- "data": [
- {
- "id": 42,
- "type": "HighTemperature",
- "severity": "high",
- "status": "raised",
- "isAck": false,
- "startDate": "2025-10-15T08:30:00.000Z",
- "endDate": "2025-10-15T09:00:00.000Z",
- "kioskSerialNumber": "LIV-0042",
- "kioskName": "Lobby Fridge",
- "detailsJson": "string",
- "createdAt": "2025-10-15T08:30:00.000Z",
- "updatedAt": "2025-10-15T09:00:00.000Z"
}
]
}A discount instance is a configured discount of a given type (see the type catalog) owned by an organization. Each instance defines its effect, an optional cap, and a priority; when several instances apply at checkout, the priority order decides which one wins.
Browse discount types, create and manage instances, suspend or resume them, reorder priorities, and preview which instances would apply on a kiosk.
See also: Discount Codes · Product Lines
Returns the registered discount types the organization may use: public types plus restricted types granted to the organization or one of its ancestors. Each entry states whether the type needs a discount code, which condition dimensions it accepts or requires, and which calculation methods it supports.
| organizationId required | number Example: organizationId=42 |
[- {
- "type": "promocode",
- "requiresActivation": true,
- "acceptedConditionDimensions": [
- "kiosk",
- "time"
], - "requiredConditionDimensions": [ ],
- "acceptedCalculationMethods": [
- "percentage",
- "flat"
]
}
]Returns a single type from the catalog. A type that is not registered and a type that is not visible to the organization both return 404.
| type required | string Example: promocode |
| organizationId required | number Example: organizationId=42 |
{- "type": "promocode",
- "requiresActivation": true,
- "acceptedConditionDimensions": [
- "kiosk",
- "time"
], - "requiredConditionDimensions": [ ],
- "acceptedCalculationMethods": [
- "percentage",
- "flat"
]
}Returns the non-deleted instances of the organization sorted by priority ascending (the lower value wins when several discounts compete for a product line), each with its derived status and a one-line conditions summary.
| organizationId required | number Example: organizationId=42 |
[- {
- "id": 1,
- "name": "Summer promo",
- "type": "promocode",
- "priority": 1,
- "enabled": true,
- "status": "ACTIVE",
- "conditionsSummary": "Mon–Fri"
}
]Applies every (id, priority) move or none of them, then returns the fresh priority overview. This is the only way to move an instance onto an occupied slot, e.g. swapping two instances. Each instance may appear once, target priorities must be distinct and within 1–100, and a target slot held by an instance not included in the moves returns 409.
| organizationId required | number | ||||
required | Array of objects (ApiDiscountPriorityMove) | ||||
Array
| |||||
{- "organizationId": 42,
- "moves": [
- {
- "id": 1,
- "priority": 2
}, - {
- "id": 3,
- "priority": 1
}
]
}[- {
- "id": 1,
- "name": "Summer promo",
- "type": "promocode",
- "priority": 1,
- "enabled": true,
- "status": "ACTIVE",
- "conditionsSummary": "Mon–Fri"
}
]Returns, per product line, the discounts eligible at that moment in resolution order, without creating a transaction. Configuration problems are returned as errors.
| kioskSerialNumber required | string Example: kioskSerialNumber=LIV-0042 |
| timestamp | string ISO 8601 UTC instant; defaults to now |
| userId | number |
| activationCode | string Discount code to include in the preview |
{- "kioskSerialNumber": "LIV-0042",
- "evaluatedAt": "2026-08-14T12:00:00.000Z",
- "targets": [
- {
- "productlineId": 101,
- "weighingAreaId": 26,
- "candidates": [
- {
- "instanceId": 1,
- "type": "promocode",
- "rank": 1,
- "effect": {
- "method": "percentage",
- "value": 30
}, - "cap": {
- "kind": "fixed",
- "value": 5
}, - "activation": {
- "codeId": 7,
- "code": "12345",
- "remainingBalance": 5
}
}
]
}
]
}Paginated list sorted by priority. Without organizationId, covers every organization in the caller scope. Soft-deleted instances are hidden unless includeDeleted is true or status is DELETED. Status is derived from enabled, deletion, and the configured date range; activeBetweenStart/End keep instances whose date range overlaps the given days (instances without a date range always match).
| organizationId | number |
| type | string Example: type=promocode |
| status | string Enum: "ACTIVE" "SCHEDULED" "SUSPENDED" "EXPIRED" "DELETED" Derived status filter |
| activeBetweenStart | string YYYY-MM-DD; set together with activeBetweenEnd |
| activeBetweenEnd | string |
| includeDeleted | boolean |
| page | number 1-based, default 1 |
| limit | number Default 25 |
{- "total": 3,
- "data": [
- {
- "id": 1,
- "type": "promocode",
- "name": "Summer promo",
- "organizationId": 42,
- "priority": 1,
- "enabled": true,
- "effect": {
- "method": "percentage",
- "value": 30
}, - "conditions": {
- "time": {
- "daysOfWeek": [
- 1,
- 2,
- 3,
- 4,
- 5
]
}
}, - "cap": {
- "kind": "fixed",
- "value": 5
}, - "productOverrides": {
- "include": [
- 0
], - "exclude": [
- 0
]
}, - "status": "ACTIVE",
- "codesSummary": {
- "total": 10,
- "enabled": 8
}, - "deletedAt": null,
- "createdAt": "2026-08-01T09:00:00.000Z",
- "updatedAt": "2026-08-01T09:00:00.000Z"
}
]
}Creates a discount of a registered type for an organization. The type must be visible to the organization, and effect and conditions are validated against the type; all field errors are returned together in fieldErrors. A priority already held by another live instance of the organization returns 409.
| type required | string Registered discount type | ||||
| name required | string | ||||
| organizationId required | number | ||||
| priority required | number 1–100, lower wins, unique per organization | ||||
required | object (ApiDiscountEffect) | ||||
| |||||
| enabled | boolean Default: true | ||||
| conditions | object or null Conditions JSON, validated against the discount type | ||||
object or null | |||||
| |||||
object or null | |||||
| |||||
{- "type": "promocode",
- "name": "Summer promo",
- "organizationId": 42,
- "priority": 1,
- "effect": {
- "method": "percentage",
- "value": 30
}, - "conditions": {
- "time": {
- "daysOfWeek": [
- 1,
- 2,
- 3,
- 4,
- 5
]
}
}, - "cap": {
- "kind": "fixed",
- "value": 5
}
}{- "id": 1,
- "type": "promocode",
- "name": "Summer promo",
- "organizationId": 42,
- "priority": 1,
- "enabled": true,
- "effect": {
- "method": "percentage",
- "value": 30
}, - "conditions": {
- "time": {
- "daysOfWeek": [
- 1,
- 2,
- 3,
- 4,
- 5
]
}
}, - "cap": {
- "kind": "fixed",
- "value": 5
}, - "productOverrides": {
- "include": [
- 0
], - "exclude": [
- 0
]
}, - "status": "ACTIVE",
- "codesSummary": {
- "total": 10,
- "enabled": 8
}, - "deletedAt": null,
- "createdAt": "2026-08-01T09:00:00.000Z",
- "updatedAt": "2026-08-01T09:00:00.000Z"
}Returns the instance with its derived status and a summary of its non-deleted codes. Soft-deleted instances are returned with status DELETED.
| id required | number Example: 1 |
{- "id": 1,
- "type": "promocode",
- "name": "Summer promo",
- "organizationId": 42,
- "priority": 1,
- "enabled": true,
- "effect": {
- "method": "percentage",
- "value": 30
}, - "conditions": {
- "time": {
- "daysOfWeek": [
- 1,
- 2,
- 3,
- 4,
- 5
]
}
}, - "cap": {
- "kind": "fixed",
- "value": 5
}, - "productOverrides": {
- "include": [
- 0
], - "exclude": [
- 0
]
}, - "status": "ACTIVE",
- "codesSummary": {
- "total": 10,
- "enabled": 8
}, - "deletedAt": null,
- "createdAt": "2026-08-01T09:00:00.000Z",
- "updatedAt": "2026-08-01T09:00:00.000Z"
}Omitted fields keep their value; null clears conditions, cap, or productOverrides, while name, priority, and effect cannot be null. The merged result is re-validated against the type. Changing the priority onto an occupied slot returns 409; use priority-reorder for swaps. Soft-deleted instances cannot be updated.
| id required | number Example: 1 |
| name | string | ||||
| priority | number 1–100, lower wins, unique per organization | ||||
| enabled | boolean Default: true | ||||
object (ApiDiscountEffect) | |||||
| |||||
| conditions | object or null Conditions JSON, validated against the discount type | ||||
object or null | |||||
| |||||
object or null | |||||
| |||||
{- "name": "Summer promo",
- "priority": 1,
- "enabled": true,
- "effect": {
- "method": "percentage",
- "value": 30
}, - "conditions": { },
- "cap": {
- "kind": "fixed",
- "value": 5
}, - "productOverrides": {
- "include": [
- 0
], - "exclude": [
- 0
]
}
}{- "id": 1,
- "type": "promocode",
- "name": "Summer promo",
- "organizationId": 42,
- "priority": 1,
- "enabled": true,
- "effect": {
- "method": "percentage",
- "value": 30
}, - "conditions": {
- "time": {
- "daysOfWeek": [
- 1,
- 2,
- 3,
- 4,
- 5
]
}
}, - "cap": {
- "kind": "fixed",
- "value": 5
}, - "productOverrides": {
- "include": [
- 0
], - "exclude": [
- 0
]
}, - "status": "ACTIVE",
- "codesSummary": {
- "total": 10,
- "enabled": 8
}, - "deletedAt": null,
- "createdAt": "2026-08-01T09:00:00.000Z",
- "updatedAt": "2026-08-01T09:00:00.000Z"
}Marks the instance deleted, frees its priority slot, and soft-deletes all its live codes in one transaction. Deletion cannot be undone; recreate the instance instead. The deleted instance stays fetchable by id.
| id required | number Example: 1 |
{- "id": 1,
- "type": "promocode",
- "name": "Summer promo",
- "organizationId": 42,
- "priority": 1,
- "enabled": true,
- "effect": {
- "method": "percentage",
- "value": 30
}, - "conditions": {
- "time": {
- "daysOfWeek": [
- 1,
- 2,
- 3,
- 4,
- 5
]
}
}, - "cap": {
- "kind": "fixed",
- "value": 5
}, - "productOverrides": {
- "include": [
- 0
], - "exclude": [
- 0
]
}, - "status": "ACTIVE",
- "codesSummary": {
- "total": 10,
- "enabled": 8
}, - "deletedAt": null,
- "createdAt": "2026-08-01T09:00:00.000Z",
- "updatedAt": "2026-08-01T09:00:00.000Z"
}Stops the discount from applying to new transactions while keeping its configuration, priority, and codes. Suspending an already suspended instance is a no-op.
| id required | number Example: 1 |
{- "id": 1,
- "type": "promocode",
- "name": "Summer promo",
- "organizationId": 42,
- "priority": 1,
- "enabled": true,
- "effect": {
- "method": "percentage",
- "value": 30
}, - "conditions": {
- "time": {
- "daysOfWeek": [
- 1,
- 2,
- 3,
- 4,
- 5
]
}
}, - "cap": {
- "kind": "fixed",
- "value": 5
}, - "productOverrides": {
- "include": [
- 0
], - "exclude": [
- 0
]
}, - "status": "ACTIVE",
- "codesSummary": {
- "total": 10,
- "enabled": 8
}, - "deletedAt": null,
- "createdAt": "2026-08-01T09:00:00.000Z",
- "updatedAt": "2026-08-01T09:00:00.000Z"
}Re-enables a suspended discount. It applies again once its date range and other conditions are met. Resuming an enabled instance is a no-op.
| id required | number Example: 1 |
{- "id": 1,
- "type": "promocode",
- "name": "Summer promo",
- "organizationId": 42,
- "priority": 1,
- "enabled": true,
- "effect": {
- "method": "percentage",
- "value": 30
}, - "conditions": {
- "time": {
- "daysOfWeek": [
- 1,
- 2,
- 3,
- 4,
- 5
]
}
}, - "cap": {
- "kind": "fixed",
- "value": 5
}, - "productOverrides": {
- "include": [
- 0
], - "exclude": [
- 0
]
}, - "status": "ACTIVE",
- "codesSummary": {
- "total": 10,
- "enabled": 8
}, - "deletedAt": null,
- "createdAt": "2026-08-01T09:00:00.000Z",
- "updatedAt": "2026-08-01T09:00:00.000Z"
}A discount code activates a code-gated discount instance at checkout. Codes belong to one instance and can carry a balance, a validity window, and an optional user binding.
List, bulk-create, update, and delete codes. Deleted code strings stay reserved.
See also: Discounts
Scope by discountInstanceId or organizationId (exactly one is required). Paginated, sorted by id. Soft-deleted codes, including those cascaded from a deleted instance, are hidden unless includeDeleted is true.
| discountInstanceId | number |
| organizationId | number |
| enabled | boolean |
| hasRemainingBalance | boolean true = usable balance (unlimited or > 0); false = exhausted |
| validAt | string ISO 8601 instant the validity window must contain |
| includeDeleted | boolean |
| page | number 1-based, default 1 |
| limit | number Default 25 |
{- "total": 10,
- "data": [
- {
- "id": 7,
- "discountInstanceId": 1,
- "code": "12345",
- "userId": 0,
- "enabled": true,
- "balance": 5,
- "resetAmount": 5,
- "resetDays": 1,
- "lastResetAt": "2026-08-01T00:00:00.000Z",
- "validFrom": "2026-08-01T00:00:00.000Z",
- "validTo": null,
- "deletedAt": null,
- "createdAt": "2026-08-01T09:00:00.000Z",
- "updatedAt": "2026-08-01T09:00:00.000Z"
}
]
}Creates codes under a live instance whose type needs a discount code. Codes are 5-digit strings, generated unless an explicit code is given, and unique per organization; strings of deleted codes stay reserved. An explicit code or a user binding requires quantity 1, and a user can hold at most one live code per instance. A null balance means no spending limit; resetAmount and resetDays, set together, reset the balance to resetAmount every resetDays days.
| discountInstanceId required | number |
| quantity | number Default: 1 How many codes to create (1–100). Explicit code or userId requires 1. |
| code | string or null Explicit 5-digit code; omitted = generated |
| userId | number or null Bind the code to a user (at most one live code per user per instance) |
| enabled | boolean Default: true |
| balance | number or null |
| resetAmount | number or null Set together with resetDays |
| resetDays | number or null Set together with resetAmount |
| validFrom | string or null ISO 8601; defaults to now |
| validTo | string or null |
{- "discountInstanceId": 1,
- "quantity": 10,
- "balance": 5,
- "resetAmount": 5,
- "resetDays": 1
}[- {
- "id": 7,
- "discountInstanceId": 1,
- "code": "12345",
- "userId": 0,
- "enabled": true,
- "balance": 5,
- "resetAmount": 5,
- "resetDays": 1,
- "lastResetAt": "2026-08-01T00:00:00.000Z",
- "validFrom": "2026-08-01T00:00:00.000Z",
- "validTo": null,
- "deletedAt": null,
- "createdAt": "2026-08-01T09:00:00.000Z",
- "updatedAt": "2026-08-01T09:00:00.000Z"
}
]Omitted fields keep their value; null clears userId, balance, the reset settings, or validTo, while enabled and validFrom cannot be null. balance is written only when sent, so an update never overwrites a concurrent draw-down or scheduled reset. Soft-deleted codes cannot be updated.
| id required | number Example: 7 |
| userId | number or null Bind the code to a user (at most one live code per user per instance) |
| enabled | boolean Default: true |
| balance | number or null |
| resetAmount | number or null Set together with resetDays |
| resetDays | number or null Set together with resetAmount |
| validFrom | string or null ISO 8601; defaults to now |
| validTo | string or null |
{- "userId": 0,
- "enabled": true,
- "balance": 5,
- "resetAmount": 5,
- "resetDays": 1,
- "validFrom": "2026-08-01T00:00:00.000Z",
- "validTo": null
}{- "id": 7,
- "discountInstanceId": 1,
- "code": "12345",
- "userId": 0,
- "enabled": true,
- "balance": 5,
- "resetAmount": 5,
- "resetDays": 1,
- "lastResetAt": "2026-08-01T00:00:00.000Z",
- "validFrom": "2026-08-01T00:00:00.000Z",
- "validTo": null,
- "deletedAt": null,
- "createdAt": "2026-08-01T09:00:00.000Z",
- "updatedAt": "2026-08-01T09:00:00.000Z"
}Marks the code deleted so it can no longer be entered at a kiosk. Deletion cannot be undone, and the code string cannot be reused in the organization.
| id required | number Example: 7 |
{- "id": 7,
- "discountInstanceId": 1,
- "code": "12345",
- "userId": 0,
- "enabled": true,
- "balance": 5,
- "resetAmount": 5,
- "resetDays": 1,
- "lastResetAt": "2026-08-01T00:00:00.000Z",
- "validFrom": "2026-08-01T00:00:00.000Z",
- "validTo": null,
- "deletedAt": null,
- "createdAt": "2026-08-01T09:00:00.000Z",
- "updatedAt": "2026-08-01T09:00:00.000Z"
}Revenue and sales performance analytics. Query time-series data (hourly, daily, weekly, monthly) or aggregate by product or kiosk. Includes top-selling kiosks and products rankings.
See also: Transactions · Kiosks · Products
Returns sales data. Use granularity for time-series, aggregateBy for product/kiosk aggregation.
| granularity required | string Enum: "hourly" "daily" "weekly" "monthly" Time granularity for grouping |
| aggregateBy | string Enum: "product" "kiosk" Aggregation dimension (omit for time-series) |
| kioskSerialNumber | string Filter to single kiosk (time-series mode) |
| kioskSerialNumbers | string Comma-separated kiosk filter (aggregateBy=kiosk) |
| startDate | string Period start (ISO 8601) |
| endDate | string Period end (ISO 8601) |
| x-timezone | string IANA timezone (default: Europe/Berlin) |
[- {
- "date": "2025-10-01",
- "hour": "2025-10-01T13:00:00",
- "week": 40,
- "period": "2025-10",
- "kioskSerialNumber": "LIV-0042",
- "productLineId": 42,
- "totalSales": 234.5,
- "totalNetSales": 197.06,
- "totalTax": 37.44,
- "totalCost": 120,
- "profit": 77.06
}
]| startDate | string Period start (ISO 8601) |
| endDate | string Period end (ISO 8601) |
| x-timezone | string IANA timezone |
[- {
- "rank": 1,
- "kioskSerialNumber": "LIV-0042",
- "kioskName": "Lobby Fridge",
- "netSales": 4523.5,
- "netCost": 2100,
- "profit": 2423.5
}
]| startDate | string Period start (ISO 8601) |
| endDate | string Period end (ISO 8601) |
| kioskSerialNumbers | string Comma-separated kiosk filter |
| x-timezone | string IANA timezone |
[- {
- "rank": 1,
- "product": {
- "name": "Coca-Cola 0.33L",
- "manufacturer": "The Coca-Cola Company",
- "imageUrl": "string"
}, - "quantitySold": 342,
- "netSales": 513,
- "netCost": 240,
- "profit": 273
}
]Transaction-level KPIs and operational metrics: total transactions, average purchase value, daily profit, peak sales hours, payment type breakdown, and product lifecycle statistics (most sold, least sold, most refilled, most removed).
See also: Transactions · Analytics: Sales
| startDate | string Period start (ISO 8601) |
| endDate | string Period end (ISO 8601) |
| kioskSerialNumbers | string Comma-separated kiosk serial numbers |
| x-timezone | string IANA timezone |
{- "totalNumberOfTransactions": 1523,
- "averagePurchaseValue": 3.42,
- "totalNumberOfProductsSold": 2847,
- "totalNetIncome": 4382.5,
- "totalGrossIncome": 5215.18
}| startDate | string Period start (ISO 8601) |
| endDate | string Period end (ISO 8601) |
| kioskSerialNumbers | string Comma-separated kiosk serial numbers |
| x-timezone | string IANA timezone |
{- "start": "14:00",
- "end": "15:00",
- "sum": 47
}| startDate | string Period start (ISO 8601) |
| endDate | string Period end (ISO 8601) |
| kioskSerialNumbers | string Comma-separated kiosk serial numbers |
| x-timezone | string IANA timezone |
[- {
- "timestamp": "2025-10-01T02:00:00.000+02:00",
- "total_sales": 1234.56,
- "total_cost": 890.12,
- "profit": 344.44
}
]| startDate | string Period start (ISO 8601) |
| endDate | string Period end (ISO 8601) |
| kioskSerialNumbers | string Comma-separated kiosk serial numbers |
| x-timezone | string IANA timezone |
{- "visa": 423,
- "mastercard": 312,
- "girocard": 189,
- "otherCreditCard": 45,
- "membercard": 67,
- "other": 12
}| startDate | string Period start (ISO 8601) |
| endDate | string Period end (ISO 8601) |
| kioskSerialNumbers | string Comma-separated kiosk serial numbers |
| x-timezone | string IANA timezone |
{- "mostSoldProductMeta": {
- "productMetaId": 10,
- "productMetaName": "Coca-Cola 0.33L",
- "imageUrl": "string",
- "count": 142
}, - "leastSoldProductMeta": {
- "productMetaId": 10,
- "productMetaName": "Coca-Cola 0.33L",
- "imageUrl": "string",
- "count": 142
}, - "mostRefilledProductMeta": {
- "productMetaId": 10,
- "productMetaName": "Coca-Cola 0.33L",
- "imageUrl": "string",
- "count": 142
}, - "mostRemovedProductMeta": {
- "productMetaId": 10,
- "productMetaName": "Coca-Cola 0.33L",
- "imageUrl": "string",
- "count": 142
}
}Refill performance metrics: products added, products removed, spoilage rate, total restocking cost, and total sales value of restocked inventory.
See also: Refills · Analytics: Inventory
| startDate | string Period start (ISO 8601) |
| endDate | string Period end (ISO 8601) |
| kioskSerialNumbers | string Comma-separated kiosk serial numbers |
| x-timezone | string IANA timezone |
{- "totalNumberOfProductsAdded": 2456,
- "defaultTotalCostValueOfRefills": 3890.5,
- "totalNumberOfProductsRemoved": 123,
- "averageSpoilageRate": 0.05,
- "defaultTotalSalesValueOfRefills": 6120,
- "defaultTotalCostValueOfRemovedProducts": 195.5
}Inventory status reports: low/zero stock alerts across kiosks, and a product statistics grid with sold, refilled, and removed counts plus revenue and cost.
See also: Kiosks · Alerts · Analytics: Refills
| skip | number Example: skip=0 Pagination offset |
| limit | number Example: limit=25 Page size |
| kioskSerialNumbers | string Comma-separated kiosk filter |
| threshold | number Example: threshold=0 Inventory threshold (default: 0, products with qty <= threshold) |
| manufacturers | string Comma-separated manufacturer filter |
{- "total": 12,
- "data": [
- {
- "productName": "Coca-Cola 0.33L",
- "productlineProductMetaId": 10,
- "currentInventory": 0,
- "cableId": 3,
- "kioskName": "Lobby Fridge",
- "kioskSerialNumber": "LIV-0042"
}
]
}| skip | number Example: skip=0 Pagination offset |
| limit | number Example: limit=25 Page size |
| startDate | string Filter start date (ISO 8601) |
| endDate | string Filter end date (ISO 8601) |
| kioskSerialNumbers | string Comma-separated kiosk filter |
| sortColumn | string Sort column (sold, refilled, removed, totalGrossSales, totalCost) |
| sortDirection | string ASC or DESC |
| includeZeroActivity | boolean Include products with no sales, refills, or removals in the window. Defaults to false. |
| x-timezone | string IANA timezone |
{- "total": 65,
- "data": [
- {
- "product": {
- "productMetaId": 10,
- "name": "Coca-Cola 0.33L",
- "imageUrl": "string",
- "defaultPrice": 1.5,
- "defaultCost": 0.85
}, - "totalCost": 890.12,
- "totalGrossSales": 1234.56,
- "totalRemovedCost": 45.5,
- "refilled": 1047,
- "sold": 892,
- "removed": 34
}
]
}Temperature telemetry from kiosk sensors. Query time-series data at various granularities (minutely, hourly, daily, weekly, monthly, or custom). Required for cold-chain compliance monitoring. Requires a specific kiosk serial number.
See also: Kiosks
| granularity required | string Enum: "minutely" "hourly" "daily" "weekly" "monthly" "custom" Temporal resolution |
| kioskSerialNumber required | string Kiosk serial number |
| startDate | string Period start (ISO 8601) |
| endDate | string Period end (ISO 8601) |
| grouping | string Enum: "minute" "hour" "day" "week" "month" Custom grouping (only for granularity=custom) |
| x-timezone | string IANA timezone |
[- {
- "sensorPosition": "top",
- "kioskName": "Lobby Fridge",
- "kioskSerial": "LIV-0042",
- "values": [
- {
- "timestamp": "2025-10-15T14:00:00.000Z",
- "temperature": 4.2
}
]
}
]