Open Platform API

Livello Open Platform API (1.1.1)

Download OpenAPI specification:

Programmatic access to Livello's autonomous retail infrastructure.

Production Endpoint: https://my.livello.com/api/v1

About Livello

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.

→ livello.com

What This API Provides

The Open Platform API gives machine-to-machine (M2M) clients access to:

  • Kiosk fleet: unit status, configuration, and real-time inventory levels
  • Products: product catalog (product meta) with metadata, categories, images, and product management
  • Product Lines: pricing management for products assigned to kiosk load cells
  • Transactions: purchase session history with line items and payment details
  • Refills: restocking session history with item-level detail
  • Users: user management (list, create, update)
  • Alerts: operational alerts and alert type definitions
  • Analytics: sales, transaction KPIs, refill statistics, inventory reports, and temperature telemetry
  • Discounts: discount instances, type catalog, priority ordering, resolution preview
  • Discount Codes: activation codes for code-gated discounts

The legacy Promocodes API is retired; use Discounts and Discount Codes instead.

All data is automatically scoped to your organization and its sub-organizations.

Quick Start

  1. Obtain credentials: request M2M client credentials from Livello (see Client Registration)
  2. Request a token: exchange your credentials for a JWT via POST /auth/token (see Authentication)
  3. Call endpoints: include the token in every request as Authorization: Bearer <token>
  4. Explore resources: start with Kiosks to list your fleet, then check Products for your catalog and Transactions for sales history
  5. Monitor operations: use Analytics for dashboards and Alerts for real-time notifications

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.

Client Registration

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.

IP Allowlisting

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.

Token Lifetime

Defaults to 24 hours, configurable per client. See Token Lifecycle for caching, renewal, and revocation details.

Key Concepts

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.

Using with Postman or Other API Clients

The OpenAPI specification is available as a downloadable JSON file. You can import it into Postman or any OpenAPI-compatible tool.

Postman import steps:

  1. Download openapi.json using the Download button at the top of this page
  2. In Postman, go to Import → File and select the downloaded JSON
  3. Endpoints are organized into folders matching the API tags: Kiosks, Products, Transactions, Analytics: Sales, and more
  4. Set a collection-level Authorization of type Bearer Token and paste your access token

Tip: Tags in the OpenAPI spec map directly to Postman collection folders, making it easy to navigate endpoints by resource type.

SDKs

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.

Installation

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

Usage Examples

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}`);
}

Timeouts

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) });

Debug Logging (Python)

Warning: Configuration.debug = True logs raw HTTP traffic, including the Authorization bearer token and the token request body (your client secret). Never enable it in production or with real credentials.

Authentication

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.

OAuth2 Client Credentials

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.

Token Request

POST /auth/token
Content-Type: application/json

{
  "client_id": "lv_m2m_abc123",
  "client_secret": "sk_live_xxxxxxxxxxxxxxxx",
  "grant_type": "client_credentials"
}

Token Response

{
  "access_token": "eyJhbGciOiJIUzI1NiIs...",
  "token_type": "Bearer",
  "expires_in": 86400,
  "scope": "kiosks:read inventory:read"
}

Using the Token

GET /kiosks
Authorization: Bearer eyJhbGciOiJIUzI1NiIs...

Token Lifecycle

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.

Scopes

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

IP Allowlisting

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).

Rate Limits

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.

Error Format

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"
}

Request an access token (OAuth2 Client Credentials)

Exchange M2M client credentials for a JWT access token. Tokens are cached server-side, so repeated requests return the same token until expiry.

Request Body schema: application/json
required
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)

Responses

Request samples

Content type
application/json
{
  • "client_id": "{{testClientId}}",
  • "client_secret": "{{testClientSecret}}",
  • "grant_type": "client_credentials"
}

Response samples

Content type
application/json
{
  • "access_token": "eyJhbGciOiJIUzI1NiIs...",
  • "token_type": "Bearer",
  • "expires_in": 86400,
  • "scope": "kiosks:read inventory:read"
}

Kiosks

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

List kiosks (paginated, org-scoped)

Authorizations:
JWT-auth
query Parameters
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)

Responses

Response samples

Content type
application/json
{
  • "total": 42,
  • "data": [
    • {
      }
    ]
}

Get kiosk detail by serial number

Authorizations:
JWT-auth
path Parameters
serialNumber
required
string

Kiosk serial number (e.g., LIV-0042)

Responses

Response samples

Content type
application/json
{
  • "_id": "LIV-0042",
  • "name": "Lobby Fridge",
  • "orgId": "123",
  • "serialNumber": "LIV-0042",
  • "isDoubleDoor": true,
  • "cabinetType": "FRIDGE",
  • "inventory": {
    • "loadCells": [
      ]
    },
  • "controller": {
    • "preAuth": 40,
    • "tabletLang": "de",
    • "tabletFont": "Arial",
    • "paymentType": "CreditOrDebitCard",
    • "minimumAge": 18,
    • "serviceCheck": {
      }
    },
  • "ownerOrganization": {
    • "_id": "123",
    • "name": "SuperMarkt GmbH",
    • "currency": "EUR",
    • "support": {
      },
    • "contact": {
      },
    • "kioskInitScreen": {}
    }
}

Get current inventory for a kiosk

Authorizations:
JWT-auth
path Parameters
serialNumber
required
string

Kiosk serial number (e.g., LIV-0042)

Responses

Response samples

Content type
application/json
[
  • {
    • "loadCellId": 1,
    • "planogramPosition": "A1",
    • "surfaceSize": "100.00",
    • "cellId": 456,
    • "productLineData": {
      }
    }
]

Get current/recent session for a kiosk

Authorizations:
JWT-auth
path Parameters
serialNumber
required
string

Kiosk serial number (e.g., LIV-0042)

query Parameters
maxAgeMinutes
number
Example: maxAgeMinutes=30

Max age in minutes for a session to be considered recent (default: 30)

Responses

Response samples

Content type
application/json
{
  • "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"
    }
}

Products

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

List product catalog (paginated, org-scoped)

Authorizations:
JWT-auth
query Parameters
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)

Responses

Response samples

Content type
application/json
{
  • "total": 156,
  • "data": [
    • {
      }
    ]
}

Create a product catalog entry

Required fields: name, organizationId, manufacturer, pricing (defaultPrice, defaultCost), packaging (grossWeightGrams, netWeightGrams, netWeightGramsUnit), capacities (at least one entry).

Authorizations:
JWT-auth
Request Body schema: application/json
required
name
required
string

Product name

manufacturer
required
string

Manufacturer

organizationId
required
number

Organization ID

required
object

Pricing info (required for creation)

defaultPrice
required
number

Gross price incl. VAT

defaultCost
required
number

Unit cost

defaultVat_id
number

VAT rate ID (from GET /organizations/:id/vat)

required
object

Packaging info (required for creation)

netWeightGrams
required
number

Net weight

grossWeightGrams
required
number

Gross weight

netWeightGramsUnit
required
string

Weight unit (e.g. ml, g)

ean
string
description
string
unitCount
number
shelfLifeDays
number

Shelf life in days

packageWeightGrams
number
tolerancePercentage
number
required
Array of objects (ProductMetaCapacityInput)

Load cell capacities (required for creation)

Array
surfaceSize
required
number

Shelf surface size

units
required
number

Number of units that fit

description
string
category
string
articleNumber
string
object (ProductMetaNutritionInput)
energy
string

Energy (kJ/kcal)

fat
string
fatSaturated
string
carbo
string
carboSugar
string
fiber
string
protein
string
salt
string
object (ProductMetaDietaryInfoInput)
glutenFree
boolean
vegetarian
boolean
vegan
boolean
allergens
string
ingredientsList
string
Array of objects (ProductMetaImageInput)
Array
data
required
string

Base64-encoded image data

copyImagesFromMetaId
number

Copy image(s) from this source meta id when no images are supplied

Responses

Request samples

Content type
application/json
Example
{
  • "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": [
    • {
      }
    ]
}

Response samples

Content type
application/json
{
  • "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",
  • "images": [],
  • "capacities": [
    • {
      }
    ],
  • "packaging": [
    • {
      }
    ],
  • "assignedKiosks": [
    • {
      }
    ]
}

Get product detail by ID

Authorizations:
JWT-auth
path Parameters
id
required
number

Product line meta ID

Responses

Response samples

Content type
application/json
{
  • "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",
  • "images": [],
  • "capacities": [
    • {
      }
    ],
  • "packaging": [
    • {
      }
    ],
  • "assignedKiosks": [
    • {
      }
    ]
}

Update a product catalog entry

Authorizations:
JWT-auth
path Parameters
id
required
number

Product line meta ID

Request Body schema: application/json
required
name
string

Product name

description
string
category
string
manufacturer
string

Manufacturer

articleNumber
string
organizationId
number

Organization ID

object (ProductMetaNutritionInput)
energy
string

Energy (kJ/kcal)

fat
string
fatSaturated
string
carbo
string
carboSugar
string
fiber
string
protein
string
salt
string
object (ProductMetaDietaryInfoInput)
glutenFree
boolean
vegetarian
boolean
vegan
boolean
allergens
string
ingredientsList
string
object

Pricing info (required for creation)

defaultPrice
required
number

Gross price incl. VAT

defaultCost
required
number

Unit cost

defaultVat_id
number

VAT rate ID (from GET /organizations/:id/vat)

Array of objects (ProductMetaImageInput)
Array
data
required
string

Base64-encoded image data

object

Packaging info (required for creation)

netWeightGrams
required
number

Net weight

grossWeightGrams
required
number

Gross weight

netWeightGramsUnit
required
string

Weight unit (e.g. ml, g)

ean
string
description
string
unitCount
number
shelfLifeDays
number

Shelf life in days

packageWeightGrams
number
tolerancePercentage
number
Array of objects (ProductMetaCapacityInput)

Load cell capacities (required for creation)

Array
surfaceSize
required
number

Shelf surface size

units
required
number

Number of units that fit

copyImagesFromMetaId
number

Copy image(s) from this source meta id when no images are supplied

Responses

Request samples

Content type
application/json
Example
{
  • "name": "Coca-Cola Zero 0.33L"
}

Response samples

Content type
application/json
{
  • "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",
  • "images": [],
  • "capacities": [
    • {
      }
    ],
  • "packaging": [
    • {
      }
    ],
  • "assignedKiosks": [
    • {
      }
    ]
}

Delete a product catalog entry

Authorizations:
JWT-auth
path Parameters
id
required
number

Product line meta ID

Responses

Product Lines

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.

See also: Products · Kiosks · Discounts

Update product line price

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.

Authorizations:
JWT-auth
path Parameters
id
required
number

Product line ID (not product meta ID)

Request Body schema: application/json
required
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)

Responses

Request samples

Content type
application/json
Example
{
  • "price": 1.99
}

Response samples

Content type
application/json
{
  • "success": true
}

Transactions

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

List purchase transactions (paginated, org-scoped)

Authorizations:
JWT-auth
query Parameters
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)

header Parameters
x-timezone
string

IANA timezone for date conversion (default: Europe/Berlin)

Responses

Response samples

Content type
application/json
{
  • "total": 523,
  • "membercardList": [
    • "MC-001",
    • "MC-002"
    ],
  • "data": [
    • {
      }
    ]
}

Get a single purchase transaction by ID

Authorizations:
JWT-auth
path Parameters
id
required
number

Transaction ID

header Parameters
x-timezone
string

IANA timezone for date conversion (default: Europe/Berlin)

Responses

Response samples

Content type
application/json
{
  • "id": 1001,
  • "created": "2025-03-18T14:30:00.000Z",
  • "total": 45.99,
  • "discountTotal": 5,
  • "session": {
    • "details": {
      }
    },
  • "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": [
    • {
      }
    ]
}

Refills

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

List refill sessions (paginated, org-scoped)

Authorizations:
JWT-auth
query Parameters
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)

header Parameters
x-timezone
string

IANA timezone for date conversion (default: Europe/Berlin)

Responses

Response samples

Content type
application/json
{
  • "total": 87,
  • "data": [
    • {
      }
    ]
}

Get a single refill session by ID

Authorizations:
JWT-auth
path Parameters
id
required
number

Refill ID

header Parameters
x-timezone
string

IANA timezone for date conversion (default: Europe/Berlin)

Responses

Response samples

Content type
application/json
{
  • "id": 201,
  • "created": "2025-03-18T08:15:00.000Z",
  • "type": "manual",
  • "kiosk": {
    • "id": 1,
    • "name": "Lobby Fridge",
    • "serialNumber": "LIV-0042"
    },
  • "itemsReplenished": [
    • {
      }
    ]
}

Organizations

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.

List organizations (paginated, RBAC-aware)

Authorizations:
JWT-auth
query Parameters
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

Responses

Response samples

Content type
application/json
{
  • "total": 25,
  • "data": [
    • {
      }
    ]
}

Create a new organization (RBAC-aware)

Required fields: name, type, currency, address.country. parentOrg is required for non-root users.

Authorizations:
JWT-auth
Request Body schema: application/json
required

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)

country
required
string

Country name

address
string
postalCode
string
city
string
state
string
countryCode
string

ISO alpha-2 country code

slug
string
description
string
eanPrefix
string
object (OrganizationContactInput)
contactPerson
string
role
string
email
string
phoneNumber
string
supportEmail
string
supportPhoneNumber
string
parentOrg
number or null

Parent organization ID. Required for non-superadmin users on create. Cannot be nullified on update.

privacyPolicyUrl
string
termsAndConditionsUrl
string

Responses

Request samples

Content type
application/json
Example
{
  • "name": "SuperMarkt GmbH",
  • "type": "client",
  • "currency": "eur",
  • "parentOrg": 42,
  • "address": {
    • "country": "Germany",
    • "countryCode": "DE"
    }
}

Response samples

Content type
application/json
{
  • "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"
}

Get organization by ID (RBAC-enforced)

Authorizations:
JWT-auth
path Parameters
id
required
number

Responses

Response samples

Content type
application/json
{
  • "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"
}

Update an organization

Authorizations:
JWT-auth
path Parameters
id
required
number
Request Body schema: application/json
required
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)

country
required
string

Country name

address
string
postalCode
string
city
string
state
string
countryCode
string

ISO alpha-2 country code

object (OrganizationContactInput)
contactPerson
string
role
string
email
string
phoneNumber
string
supportEmail
string
supportPhoneNumber
string
parentOrg
number or null

Parent organization ID. Required for non-superadmin users on create. Cannot be nullified on update.

privacyPolicyUrl
string
termsAndConditionsUrl
string

Responses

Request samples

Content type
application/json
Example
{
  • "name": "New Org Name"
}

Response samples

Content type
application/json
{
  • "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"
}

Get VAT rates for organization

Authorizations:
JWT-auth
path Parameters
id
required
number

Organization ID

Responses

Response samples

Content type
application/json
[
  • {
    • "id": 1,
    • "name": "Standard",
    • "value": 19,
    • "countryCode": "DE"
    }
]

Get product lines for organization

Authorizations:
JWT-auth
path Parameters
id
required
number

Organization ID

Responses

Response samples

Content type
application/json
[
  • {
    • "_id": "42",
    • "name": "Coca-Cola 0.33L",
    • "images": [
      ]
    }
]

Users

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.

List users (paginated, org-scoped)

Authorizations:
JWT-auth
query Parameters
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)

Responses

Response samples

Content type
application/json
{
  • "total": 48,
  • "data": [
    • {
      }
    ]
}

Create a consumer user

Creates a consumer user in the specified organization. Required fields: email, firstName, lastName, organizationId, status, lang.

Authorizations:
JWT-auth
Request Body schema: application/json
required
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)
address
string
city
string
postalCode
string
country
string

Responses

Request samples

Content type
application/json
{
  • "email": "john.doe@example.com",
  • "firstName": "John",
  • "lastName": "Doe",
  • "organizationId": 42,
  • "status": "ACTIVE",
  • "lang": "en"
}

Response samples

Content type
application/json
{
  • "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": [
    • {
      }
    ],
  • "address": {
    • "address": "Friedrichstraße 123",
    • "city": "Berlin",
    • "postalCode": "10117",
    • "country": "Germany"
    },
  • "membercards": [
    • "MC-001"
    ],
  • "rolesInOrganizations": [
    • {
      }
    ],
  • "created": "2025-01-15T10:00:00.000Z",
  • "updated": "2025-06-20T14:30:00.000Z"
}

Get user detail by ID

Authorizations:
JWT-auth
path Parameters
id
required
number

User ID

Responses

Response samples

Content type
application/json
{
  • "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": [
    • {
      }
    ],
  • "address": {
    • "address": "Friedrichstraße 123",
    • "city": "Berlin",
    • "postalCode": "10117",
    • "country": "Germany"
    },
  • "membercards": [
    • "MC-001"
    ],
  • "rolesInOrganizations": [
    • {
      }
    ],
  • "created": "2025-01-15T10:00:00.000Z",
  • "updated": "2025-06-20T14:30:00.000Z"
}

Update a user

Authorizations:
JWT-auth
path Parameters
id
required
number

User ID

Request Body schema: application/json
required
email
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)
address
string
city
string
postalCode
string
country
string

Responses

Request samples

Content type
application/json
Example
{
  • "firstName": "Jane",
  • "lastName": "Smith"
}

Response samples

Content type
application/json
{
  • "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": [
    • {
      }
    ],
  • "address": {
    • "address": "Friedrichstraße 123",
    • "city": "Berlin",
    • "postalCode": "10117",
    • "country": "Germany"
    },
  • "membercards": [
    • "MC-001"
    ],
  • "rolesInOrganizations": [
    • {
      }
    ],
  • "created": "2025-01-15T10:00:00.000Z",
  • "updated": "2025-06-20T14:30:00.000Z"
}

Alerts

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

List alerts (paginated, org-scoped)

Authorizations:
JWT-auth
query Parameters
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)

Responses

Response samples

Content type
application/json
{
  • "total": 156,
  • "data": [
    • {
      }
    ]
}

Get all alert type definitions

Authorizations:
JWT-auth

Responses

Response samples

Content type
application/json
[
  • {
    • "type": "HighTemperature",
    • "category": "Operational",
    • "defaultSeverity": "high",
    • "description": "Kiosk internal temperature exceeded threshold"
    }
]

Discounts

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

List discount types visible to an organization

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.

Authorizations:
JWT-auth
query Parameters
organizationId
required
number
Example: organizationId=42

Responses

Response samples

Content type
application/json
[
  • {
    • "type": "promocode",
    • "requiresActivation": true,
    • "acceptedConditionDimensions": [
      ],
    • "requiredConditionDimensions": [ ],
    • "acceptedCalculationMethods": [
      ]
    }
]

Get one discount type with its full schema

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.

Authorizations:
JWT-auth
path Parameters
type
required
string
Example: promocode
query Parameters
organizationId
required
number
Example: organizationId=42

Responses

Response samples

Content type
application/json
{
  • "type": "promocode",
  • "requiresActivation": true,
  • "acceptedConditionDimensions": [
    • "kiosk",
    • "time"
    ],
  • "requiredConditionDimensions": [ ],
  • "acceptedCalculationMethods": [
    • "percentage",
    • "flat"
    ]
}

Organization's live instances in resolution order

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.

Authorizations:
JWT-auth
query Parameters
organizationId
required
number
Example: organizationId=42

Responses

Response samples

Content type
application/json
[
  • {
    • "id": 1,
    • "name": "Summer promo",
    • "type": "promocode",
    • "priority": 1,
    • "enabled": true,
    • "status": "ACTIVE",
    • "conditionsSummary": "Mon–Fri"
    }
]

Atomically reassign priorities

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.

Authorizations:
JWT-auth
Request Body schema: application/json
required
organizationId
required
number
required
Array of objects (ApiDiscountPriorityMove)
Array
id
required
number
priority
required
number

New priority slot (1–100)

Responses

Request samples

Content type
application/json
{
  • "organizationId": 42,
  • "moves": [
    • {
      },
    • {
      }
    ]
}

Response samples

Content type
application/json
[
  • {
    • "id": 1,
    • "name": "Summer promo",
    • "type": "promocode",
    • "priority": 1,
    • "enabled": true,
    • "status": "ACTIVE",
    • "conditionsSummary": "Mon–Fri"
    }
]

Preview which discounts would apply on a kiosk at a given time (read-only)

Returns, per product line, the discounts eligible at that moment in resolution order, without creating a transaction. Configuration problems are returned as errors.

Authorizations:
JWT-auth
query Parameters
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

Responses

Response samples

Content type
application/json
{
  • "kioskSerialNumber": "LIV-0042",
  • "evaluatedAt": "2026-08-14T12:00:00.000Z",
  • "targets": [
    • {
      }
    ]
}

List discount instances

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).

Authorizations:
JWT-auth
query Parameters
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

Responses

Response samples

Content type
application/json
{
  • "total": 3,
  • "data": [
    • {
      }
    ]
}

Create a discount instance

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.

Authorizations:
JWT-auth
Request Body schema: application/json
required
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)
method
required
string
Enum: "percentage" "flat"
value
required
number

Percentage on the 0–100 scale (30 = 30%), or per-item flat amount

enabled
boolean
Default: true
conditions
object or null

Conditions JSON, validated against the discount type

object or null
kind
required
string
Enum: "fixed" "percentage"

fixed = hard limit in the organization currency; percentage = share of the gross line amounts the instance won

value
required
number
object or null
include
Array of numbers

Whitelist of eligible productline ids (mutually exclusive with exclude)

exclude
Array of numbers

Blacklist of excluded productline ids (mutually exclusive with include)

Responses

Request samples

Content type
application/json
{
  • "type": "promocode",
  • "name": "Summer promo",
  • "organizationId": 42,
  • "priority": 1,
  • "effect": {
    • "method": "percentage",
    • "value": 30
    },
  • "conditions": {
    • "time": {
      }
    },
  • "cap": {
    • "kind": "fixed",
    • "value": 5
    }
}

Response samples

Content type
application/json
{
  • "id": 1,
  • "type": "promocode",
  • "name": "Summer promo",
  • "organizationId": 42,
  • "priority": 1,
  • "enabled": true,
  • "effect": {
    • "method": "percentage",
    • "value": 30
    },
  • "conditions": {
    • "time": {
      }
    },
  • "cap": {
    • "kind": "fixed",
    • "value": 5
    },
  • "productOverrides": {
    • "include": [
      ],
    • "exclude": [
      ]
    },
  • "status": "ACTIVE",
  • "codesSummary": {
    • "total": 10,
    • "enabled": 8
    },
  • "deletedAt": null,
  • "createdAt": "2026-08-01T09:00:00.000Z",
  • "updatedAt": "2026-08-01T09:00:00.000Z"
}

Get a discount instance (deleted instances stay fetchable)

Returns the instance with its derived status and a summary of its non-deleted codes. Soft-deleted instances are returned with status DELETED.

Authorizations:
JWT-auth
path Parameters
id
required
number
Example: 1

Responses

Response samples

Content type
application/json
{
  • "id": 1,
  • "type": "promocode",
  • "name": "Summer promo",
  • "organizationId": 42,
  • "priority": 1,
  • "enabled": true,
  • "effect": {
    • "method": "percentage",
    • "value": 30
    },
  • "conditions": {
    • "time": {
      }
    },
  • "cap": {
    • "kind": "fixed",
    • "value": 5
    },
  • "productOverrides": {
    • "include": [
      ],
    • "exclude": [
      ]
    },
  • "status": "ACTIVE",
  • "codesSummary": {
    • "total": 10,
    • "enabled": 8
    },
  • "deletedAt": null,
  • "createdAt": "2026-08-01T09:00:00.000Z",
  • "updatedAt": "2026-08-01T09:00:00.000Z"
}

Partially update a discount instance (type and organizationId are immutable)

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.

Authorizations:
JWT-auth
path Parameters
id
required
number
Example: 1
Request Body schema: application/json
required
name
string
priority
number

1–100, lower wins, unique per organization

enabled
boolean
Default: true
object (ApiDiscountEffect)
method
required
string
Enum: "percentage" "flat"
value
required
number

Percentage on the 0–100 scale (30 = 30%), or per-item flat amount

conditions
object or null

Conditions JSON, validated against the discount type

object or null
kind
required
string
Enum: "fixed" "percentage"

fixed = hard limit in the organization currency; percentage = share of the gross line amounts the instance won

value
required
number
object or null
include
Array of numbers

Whitelist of eligible productline ids (mutually exclusive with exclude)

exclude
Array of numbers

Blacklist of excluded productline ids (mutually exclusive with include)

Responses

Request samples

Content type
application/json
{
  • "name": "Summer promo",
  • "priority": 1,
  • "enabled": true,
  • "effect": {
    • "method": "percentage",
    • "value": 30
    },
  • "conditions": { },
  • "cap": {
    • "kind": "fixed",
    • "value": 5
    },
  • "productOverrides": {
    • "include": [
      ],
    • "exclude": [
      ]
    }
}

Response samples

Content type
application/json
{
  • "id": 1,
  • "type": "promocode",
  • "name": "Summer promo",
  • "organizationId": 42,
  • "priority": 1,
  • "enabled": true,
  • "effect": {
    • "method": "percentage",
    • "value": 30
    },
  • "conditions": {
    • "time": {
      }
    },
  • "cap": {
    • "kind": "fixed",
    • "value": 5
    },
  • "productOverrides": {
    • "include": [
      ],
    • "exclude": [
      ]
    },
  • "status": "ACTIVE",
  • "codesSummary": {
    • "total": 10,
    • "enabled": 8
    },
  • "deletedAt": null,
  • "createdAt": "2026-08-01T09:00:00.000Z",
  • "updatedAt": "2026-08-01T09:00:00.000Z"
}

Soft-delete a discount instance (cascades to its codes)

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.

Authorizations:
JWT-auth
path Parameters
id
required
number
Example: 1

Responses

Response samples

Content type
application/json
{
  • "id": 1,
  • "type": "promocode",
  • "name": "Summer promo",
  • "organizationId": 42,
  • "priority": 1,
  • "enabled": true,
  • "effect": {
    • "method": "percentage",
    • "value": 30
    },
  • "conditions": {
    • "time": {
      }
    },
  • "cap": {
    • "kind": "fixed",
    • "value": 5
    },
  • "productOverrides": {
    • "include": [
      ],
    • "exclude": [
      ]
    },
  • "status": "ACTIVE",
  • "codesSummary": {
    • "total": 10,
    • "enabled": 8
    },
  • "deletedAt": null,
  • "createdAt": "2026-08-01T09:00:00.000Z",
  • "updatedAt": "2026-08-01T09:00:00.000Z"
}

Suspend a discount instance (enabled = false)

Stops the discount from applying to new transactions while keeping its configuration, priority, and codes. Suspending an already suspended instance is a no-op.

Authorizations:
JWT-auth
path Parameters
id
required
number
Example: 1

Responses

Response samples

Content type
application/json
{
  • "id": 1,
  • "type": "promocode",
  • "name": "Summer promo",
  • "organizationId": 42,
  • "priority": 1,
  • "enabled": true,
  • "effect": {
    • "method": "percentage",
    • "value": 30
    },
  • "conditions": {
    • "time": {
      }
    },
  • "cap": {
    • "kind": "fixed",
    • "value": 5
    },
  • "productOverrides": {
    • "include": [
      ],
    • "exclude": [
      ]
    },
  • "status": "ACTIVE",
  • "codesSummary": {
    • "total": 10,
    • "enabled": 8
    },
  • "deletedAt": null,
  • "createdAt": "2026-08-01T09:00:00.000Z",
  • "updatedAt": "2026-08-01T09:00:00.000Z"
}

Resume a discount instance (enabled = true)

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.

Authorizations:
JWT-auth
path Parameters
id
required
number
Example: 1

Responses

Response samples

Content type
application/json
{
  • "id": 1,
  • "type": "promocode",
  • "name": "Summer promo",
  • "organizationId": 42,
  • "priority": 1,
  • "enabled": true,
  • "effect": {
    • "method": "percentage",
    • "value": 30
    },
  • "conditions": {
    • "time": {
      }
    },
  • "cap": {
    • "kind": "fixed",
    • "value": 5
    },
  • "productOverrides": {
    • "include": [
      ],
    • "exclude": [
      ]
    },
  • "status": "ACTIVE",
  • "codesSummary": {
    • "total": 10,
    • "enabled": 8
    },
  • "deletedAt": null,
  • "createdAt": "2026-08-01T09:00:00.000Z",
  • "updatedAt": "2026-08-01T09:00:00.000Z"
}

Discount Codes

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

List discount codes

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.

Authorizations:
JWT-auth
query Parameters
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

Responses

Response samples

Content type
application/json
{
  • "total": 10,
  • "data": [
    • {
      }
    ]
}

Bulk-create 1–100 discount codes (single transaction)

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.

Authorizations:
JWT-auth
Request Body schema: application/json
required
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

Responses

Request samples

Content type
application/json
Example
{
  • "discountInstanceId": 1,
  • "quantity": 10,
  • "balance": 5,
  • "resetAmount": 5,
  • "resetDays": 1
}

Response samples

Content type
application/json
[
  • {
    • "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"
    }
]

Partially update a discount code (discountInstanceId and code are immutable)

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.

Authorizations:
JWT-auth
path Parameters
id
required
number
Example: 7
Request Body schema: application/json
required
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

Responses

Request samples

Content type
application/json
{
  • "userId": 0,
  • "enabled": true,
  • "balance": 5,
  • "resetAmount": 5,
  • "resetDays": 1,
  • "validFrom": "2026-08-01T00:00:00.000Z",
  • "validTo": null
}

Response samples

Content type
application/json
{
  • "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"
}

Soft-delete a discount code (its string stays reserved)

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.

Authorizations:
JWT-auth
path Parameters
id
required
number
Example: 7

Responses

Response samples

Content type
application/json
{
  • "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"
}

Analytics: Sales

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

Sales time series or aggregation (configurable via query params)

Returns sales data. Use granularity for time-series, aggregateBy for product/kiosk aggregation.

Authorizations:
JWT-auth
query Parameters
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)

header Parameters
x-timezone
string

IANA timezone (default: Europe/Berlin)

Responses

Response samples

Content type
application/json
[
  • {
    • "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
    }
]

Top 10 kiosks by net sales

Authorizations:
JWT-auth
query Parameters
startDate
string

Period start (ISO 8601)

endDate
string

Period end (ISO 8601)

header Parameters
x-timezone
string

IANA timezone

Responses

Response samples

Content type
application/json
[
  • {
    • "rank": 1,
    • "kioskSerialNumber": "LIV-0042",
    • "kioskName": "Lobby Fridge",
    • "netSales": 4523.5,
    • "netCost": 2100,
    • "profit": 2423.5
    }
]

Top 20 products by quantity sold

Authorizations:
JWT-auth
query Parameters
startDate
string

Period start (ISO 8601)

endDate
string

Period end (ISO 8601)

kioskSerialNumbers
string

Comma-separated kiosk filter

header Parameters
x-timezone
string

IANA timezone

Responses

Response samples

Content type
application/json
[
  • {
    • "rank": 1,
    • "product": {
      },
    • "quantitySold": 342,
    • "netSales": 513,
    • "netCost": 240,
    • "profit": 273
    }
]

Analytics: Transactions

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

Combined transaction KPIs (count, avg value, net/gross income)

Authorizations:
JWT-auth
query Parameters
startDate
string

Period start (ISO 8601)

endDate
string

Period end (ISO 8601)

kioskSerialNumbers
string

Comma-separated kiosk serial numbers

header Parameters
x-timezone
string

IANA timezone

Responses

Response samples

Content type
application/json
{
  • "totalNumberOfTransactions": 1523,
  • "averagePurchaseValue": 3.42,
  • "totalNumberOfProductsSold": 2847,
  • "totalNetIncome": 4382.5,
  • "totalGrossIncome": 5215.18
}

Peak sales hour (highest transaction count)

Authorizations:
JWT-auth
query Parameters
startDate
string

Period start (ISO 8601)

endDate
string

Period end (ISO 8601)

kioskSerialNumbers
string

Comma-separated kiosk serial numbers

header Parameters
x-timezone
string

IANA timezone

Responses

Response samples

Content type
application/json
{
  • "start": "14:00",
  • "end": "15:00",
  • "sum": 47
}

Daily profit chart data (net sales, cost, profit by day)

Authorizations:
JWT-auth
query Parameters
startDate
string

Period start (ISO 8601)

endDate
string

Period end (ISO 8601)

kioskSerialNumbers
string

Comma-separated kiosk serial numbers

header Parameters
x-timezone
string

IANA timezone

Responses

Response samples

Content type
application/json
[
  • {
    • "timestamp": "2025-10-01T02:00:00.000+02:00",
    • "total_sales": 1234.56,
    • "total_cost": 890.12,
    • "profit": 344.44
    }
]

Payment type breakdown (visa, mastercard, girocard, etc.)

Authorizations:
JWT-auth
query Parameters
startDate
string

Period start (ISO 8601)

endDate
string

Period end (ISO 8601)

kioskSerialNumbers
string

Comma-separated kiosk serial numbers

header Parameters
x-timezone
string

IANA timezone

Responses

Response samples

Content type
application/json
{
  • "visa": 423,
  • "mastercard": 312,
  • "girocard": 189,
  • "otherCreditCard": 45,
  • "membercard": 67,
  • "other": 12
}

Product lifecycle statistics (most/least sold, most refilled/removed)

Authorizations:
JWT-auth
query Parameters
startDate
string

Period start (ISO 8601)

endDate
string

Period end (ISO 8601)

kioskSerialNumbers
string

Comma-separated kiosk serial numbers

header Parameters
x-timezone
string

IANA timezone

Responses

Response samples

Content type
application/json
{
  • "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
    }
}

Analytics: Refills

Refill performance metrics: products added, products removed, spoilage rate, total restocking cost, and total sales value of restocked inventory.

See also: Refills · Analytics: Inventory

Combined refill statistics (products added/removed, spoilage, costs)

Authorizations:
JWT-auth
query Parameters
startDate
string

Period start (ISO 8601)

endDate
string

Period end (ISO 8601)

kioskSerialNumbers
string

Comma-separated kiosk serial numbers

header Parameters
x-timezone
string

IANA timezone

Responses

Response samples

Content type
application/json
{
  • "totalNumberOfProductsAdded": 2456,
  • "defaultTotalCostValueOfRefills": 3890.5,
  • "totalNumberOfProductsRemoved": 123,
  • "averageSpoilageRate": 0.05,
  • "defaultTotalSalesValueOfRefills": 6120,
  • "defaultTotalCostValueOfRemovedProducts": 195.5
}

Analytics: Inventory

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

Low/zero inventory report

Authorizations:
JWT-auth
query Parameters
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

Responses

Response samples

Content type
application/json
{
  • "total": 12,
  • "data": [
    • {
      }
    ]
}

Product statistics grid (paginated, aggregated by product)

Authorizations:
JWT-auth
query Parameters
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.

header Parameters
x-timezone
string

IANA timezone

Responses

Response samples

Content type
application/json
{
  • "total": 65,
  • "data": [
    • {
      }
    ]
}

Analytics: Temperature

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

Temperature time series at specified granularity

Authorizations:
JWT-auth
path Parameters
granularity
required
string
Enum: "minutely" "hourly" "daily" "weekly" "monthly" "custom"

Temporal resolution

query Parameters
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)

header Parameters
x-timezone
string

IANA timezone

Responses

Response samples

Content type
application/json
[
  • {
    • "sensorPosition": "top",
    • "kioskName": "Lobby Fridge",
    • "kioskSerial": "LIV-0042",
    • "values": [
      ]
    }
]