Download OpenAPI specification:Download
OpenEOS ist ein Kassen- und Bestellsystem für Vereinsfeste. Diese Referenz beschreibt die REST-API unter https://api.openeos.de/api (selbst gehostet: https://<deine-api>/api).
Für Skripte, Automatisierungen (z. B. Zapier) und KI-Agenten gibt es API-Tokens je Organisation. Dieselben Tokens öffnen den MCP-Server unter https://api.openeos.de/mcp (Streamable HTTP, außerhalb von /api) für Claude, Cursor und eigene Agenten — die Werkzeuge dort folgen denselben Scopes. Ein Token wirkt wie die Person, die ihn ausgestellt hat — beschränkt auf eine Organisation, auf die gewählten Scopes und auf die hier mit API-token markierten Endpunkte. Alles andere (Kasse, Zahlungen, Mitglieder, Abrechnung, Löschen, Freischaltung) bleibt der Anmeldung in der App vorbehalten.
Token anlegen: In der Web-App unter Einstellungen → Organisation → Zugänge (Organisations-Admin) oder per POST /api/organizations/{organizationId}/api-tokens mit einer angemeldeten Sitzung. Der Token (oeos_…) wird genau einmal angezeigt; gespeichert wird nur ein Hash. Höchstens 20 aktive Tokens je Organisation.
Verwenden: Authorization: Bearer oeos_… — derselbe Header wie für Sitzungs-JWTs. Welche Organisation gemeint ist, steht im Pfad; ein Token erreicht nur seine eigene (sonst 403 API_TOKEN_WRONG_ORGANIZATION).
| Scope | Erlaubt |
|---|---|
read |
Organisation, Veranstaltungen, Kategorien, Produkte, Pfandarten, Tische, Stationen, Bon-Vorlagen, Drucker, Schichtpläne, Geräte, Berichte und Bestellungen lesen |
catalog:write |
Kategorien, Produkte und Pfandarten anlegen und ändern |
events:write |
Veranstaltungen und Produktionsstationen anlegen und ändern (keine Freischaltung) |
tables:write |
Bereiche, Tische und Tischplan bearbeiten |
staff:write |
Schichtpläne, Jobs, Schichten und Helfer-Anmeldungen bearbeiten |
devices:write |
Bon-Vorlagen anlegen und ändern |
settings:write |
Organisationseinstellungen ändern |
Schreib-Scopes schließen read nicht ein. Jeder Endpunkt nennt den nötigen Scope als x-api-token-scope; fehlt er am Token, antwortet die API mit 403 API_TOKEN_SCOPE_MISSING, bei nicht freigegebenen Endpunkten mit 403 API_TOKEN_NOT_ALLOWED.
Je Token:
Darüber hinaus 429 API_TOKEN_RATE_LIMITED mit Retry-After. Zusätzlich gilt die allgemeine Grenze je IP-Adresse.
Jede Fehlerantwort hat die Form { "error": { "code", "reason", "message", "params", "details", "requestId", "timestamp" } }. code ist die allgemeine Klasse (FORBIDDEN, NOT_FOUND, …), reason der konkrete Fall (API_TOKEN_SCOPE_MISSING, EVENT_NOT_FOUND, …).
Nur die Endpunkte, die ein API-Token erreichen kann, plus die Verwaltung der Tokens selbst (nur mit Anmeldung). Alle anderen Teile der API — Anmeldung und Sitzungen der Web-App, Kasse und Geräte-API (/api/device-api/*), Zahlungen, Mitglieder, Abrechnung, Admin — sind absichtlich nicht dokumentiert: Sie sind für die Apps von OpenEOS gedacht und keine stabile Schnittstelle für Integrationen. Wer OpenEOS selbst betreibt, findet die vollständige Beschreibung im Repository (docs/openapi.json) und außerhalb der Produktion unter /docs.
Zu jedem Endpunkt steht der nötige Scope (x-api-token-scope). Die Texte sind auf Deutsch; die Referenz ist für beide Sprachen der Doku-Seite dieselbe.
Ändert Name, Kontaktdaten oder Einstellungen (z. B. bargeldloser Modus). Scope settings:write, nur für Administratoren; geänderte Einstellungen gehen sofort an die Kassen.
| id required | string <uuid> ID der Organisation |
| name | string Name der Organisation |
| logoUrl | string URL des Organisationslogos |
| settings | object Organisationseinstellungen |
| isActive | boolean Gibt an, ob die Organisation aktiv ist |
{- "name": "Musterverein e.V.",
- "settings": {
- "currency": "EUR",
- "timezone": "Europe/Berlin"
}, - "isActive": true
}Veranstaltungen anlegen, ändern und lesen. Freischalten und aktivieren geht nur in der App.
Alle Veranstaltungen der Organisation, neueste zuerst, seitenweise (page, limit). Scope read.
| organizationId required | string <uuid> ID der Organisation |
| page | number >= 1 Default: 1 Example: page=1 Seite, beginnend bei 1 |
| limit | number [ 1 .. 500 ] Default: 20 Example: limit=20 Einträge je Seite (höchstens 500) |
| data | Array of objects |
object Seitenangaben |
{- "data": [
- {
- "id": "2f6c1a9e-5b1d-4c7e-9a3f-0d8e7b6a5c41",
- "organizationId": "8c1e2d3f-4a5b-4c6d-8e7f-9a0b1c2d3e4f",
- "copiedFromEventId": null,
- "name": "Sommerfest 2026",
- "description": "Festwochenende am Sportplatz",
- "startDate": "2026-07-10T16:00:00.000Z",
- "endDate": "2026-07-12T22:00:00.000Z",
- "status": "active",
- "settings": {
- "orderNumberPrefix": "SF",
- "orderingMode": "immediate",
- "enableOnlineOrdering": false,
- "enableTableService": true,
- "enableTakeaway": true
}, - "billingStatus": "paid",
- "paidAt": "2026-06-01T09:12:44.000Z",
- "priceCharged": 29,
- "billedDays": 3,
- "invoiceStatus": null,
- "invoiceDueAt": null,
- "invoicePaidAt": null,
- "invoiceHostedUrl": null,
- "invoicePdfUrl": null,
- "unlockedStartDate": "2026-07-10T00:00:00.000Z",
- "createdAt": "2026-05-20T18:30:12.000Z",
- "updatedAt": "2026-07-10T15:58:03.000Z"
}, - {
- "id": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
- "organizationId": "8c1e2d3f-4a5b-4c6d-8e7f-9a0b1c2d3e4f",
- "copiedFromEventId": null,
- "name": "Weihnachtsmarkt 2025",
- "description": null,
- "startDate": "2025-12-06T14:00:00.000Z",
- "endDate": "2025-12-07T20:00:00.000Z",
- "status": "inactive",
- "settings": {
- "orderNumberPrefix": "WM",
- "orderingMode": "immediate"
}, - "billingStatus": "paid",
- "paidAt": "2025-11-02T10:05:00.000Z",
- "priceCharged": 29,
- "billedDays": 2,
- "invoiceStatus": null,
- "invoiceDueAt": null,
- "invoicePaidAt": null,
- "invoiceHostedUrl": null,
- "invoicePdfUrl": null,
- "unlockedStartDate": "2025-12-06T00:00:00.000Z",
- "createdAt": "2025-10-28T19:02:40.000Z",
- "updatedAt": "2025-12-07T21:10:00.000Z"
}
], - "meta": {
- "page": 1,
- "limit": 20,
- "total": 2,
- "totalPages": 1,
- "hasNext": false,
- "hasPrev": false
}
}Legt eine neue Veranstaltung mit Status inactive an. Scope events:write und Modulrecht Veranstaltungen; freischalten und aktivieren geht nur in der App.
| organizationId required | string <uuid> ID der Organisation |
| name required | string Name des Events |
| startDate required | string Beginn der Veranstaltung. Pflichtangabe — der Preis und die Shop-Öffnungszeiten leiten sich davon ab. |
| description | string Beschreibung des Events |
| endDate | string Ende der Veranstaltung. Ohne Angabe endet sie am Starttag. Darf über Mitternacht hinausgehen. |
| settings | object Event-Einstellungen |
{- "name": "Sommerfest 2024",
- "description": "Jährliches Sommerfest mit Livemusik und Buffet",
- "startDate": "2024-07-15T10:00:00.000Z",
- "endDate": "2024-07-16T02:00:00.000Z",
- "settings": {
- "allowOnlineOrders": true,
- "requireTableNumber": false
}
}Ändert Name, Beschreibung, Zeitraum oder Einstellungen. Scope events:write; der Status (aktiv, Test) lässt sich hier nicht setzen.
| organizationId required | string <uuid> ID der Organisation |
| eventId required | string <uuid> ID der Veranstaltung |
| name | string Name des Events |
| description | string Beschreibung des Events |
| startDate | string Startdatum und -zeit des Events |
| endDate | string Enddatum und -zeit des Events |
| settings | object Event-Einstellungen |
{- "name": "Sommerfest 2024",
- "description": "Jährliches Sommerfest mit Livemusik und Buffet",
- "startDate": "2024-07-15T10:00:00.000Z",
- "endDate": "2024-07-15T22:00:00.000Z",
- "settings": {
- "allowOnlineOrders": true,
- "requireTableNumber": false
}
}Kopiert Kategorien und Produkte aus sourceEventId in diese Veranstaltung; was übernommen wird, steuert der Body. Scope events:write.
| organizationId required | string <uuid> ID der Organisation |
| eventId required | string <uuid> ID der Ziel-Veranstaltung |
| sourceEventId required | string <uuid> ID der Veranstaltung, aus der kopiert wird |
| categoryIds | Array of strings IDs der zu kopierenden Kategorien. Wenn leer, werden alle Kategorien kopiert. |
| productIds | Array of strings IDs der zu kopierenden Produkte. Wenn leer und categoryIds leer, werden alle Produkte kopiert. |
| copyStock | boolean Wenn true, wird auch der Bestand kopiert. Standard: false (Bestand wird auf 0 gesetzt) |
{- "categoryIds": [
- "550e8400-e29b-41d4-a716-446655440000"
], - "productIds": [
- "550e8400-e29b-41d4-a716-446655440001"
], - "copyStock": false
}Legt eine Kategorie in der Veranstaltung an. Scope catalog:write und Modulrecht Produkte.
| eventId required | string <uuid> ID der Veranstaltung |
| name required | string Name der Kategorie |
| description | string Beschreibung der Kategorie |
| parentId | string ID der übergeordneten Kategorie |
| color | string Farbcode der Kategorie (Hex-Format) |
| icon | string Icon-Name für die Kategorie |
| sortOrder | number Sortierreihenfolge |
| isActive | boolean Gibt an, ob die Kategorie aktiv ist |
| printSettings | object Druckeinstellungen für die Kategorie |
| productionStationId | string ID des Produktionsstandorts |
{- "name": "Hauptgerichte",
- "description": "Warme Hauptspeisen und Gerichte",
- "parentId": "550e8400-e29b-41d4-a716-446655440000",
- "color": "#FF5733",
- "icon": "restaurant",
- "sortOrder": 1,
- "isActive": true,
- "printSettings": {
- "printToKitchen": true,
- "printerIds": [ ]
}, - "productionStationId": "550e8400-e29b-41d4-a716-446655440000"
}Ändert Name, Farbe, Icon oder Sichtbarkeit einer Kategorie. Scope catalog:write.
| eventId required | string <uuid> ID der Veranstaltung |
| categoryId required | string <uuid> ID der Kategorie |
| name | string Name der Kategorie |
| description | string Beschreibung der Kategorie |
| parentId | object ID der übergeordneten Kategorie |
| color | object Farbcode der Kategorie (Hex-Format) |
| icon | object Icon-Name für die Kategorie |
| sortOrder | number Sortierreihenfolge |
| isActive | boolean Gibt an, ob die Kategorie aktiv ist |
| printSettings | object Druckeinstellungen für die Kategorie |
| productionStationId | object ID des Produktionsstandorts |
{- "name": "Hauptgerichte",
- "description": "Warme Hauptspeisen und Gerichte",
- "parentId": "550e8400-e29b-41d4-a716-446655440000",
- "color": "#FF5733",
- "icon": "restaurant",
- "sortOrder": 1,
- "isActive": true,
- "printSettings": {
- "printToKitchen": true,
- "printerIds": [ ]
}, - "productionStationId": "550e8400-e29b-41d4-a716-446655440000"
}Setzt die Reihenfolge aller Kategorien anhand der übergebenen ID-Liste. Scope catalog:write.
| eventId required | string <uuid> ID der Veranstaltung |
| categoryIds | Array of strings Sortierte Liste der Kategorie-IDs |
{- "categoryIds": [
- "550e8400-e29b-41d4-a716-446655440000",
- "550e8400-e29b-41d4-a716-446655440001"
]
}Alle Produkte der Veranstaltung mit Kategorie, sortiert nach Reihenfolge und Name, seitenweise (page, limit; Standard 50). Scope read.
| eventId required | string <uuid> ID der Veranstaltung |
| page | number >= 1 Default: 1 Example: page=1 Seite, beginnend bei 1 |
| limit | number [ 1 .. 500 ] Default: 20 Example: limit=20 Einträge je Seite (höchstens 500) |
| data | Array of objects |
object Seitenangaben |
{- "data": [
- {
- "id": "5d4c3b2a-1f0e-4d9c-8b7a-6f5e4d3c2b1a",
- "eventId": "2f6c1a9e-5b1d-4c7e-9a3f-0d8e7b6a5c41",
- "categoryId": "9e8d7c6b-5a4f-4e3d-9c2b-1a0f9e8d7c6b",
- "name": "Bratwurst im Brötchen",
- "description": "Vom Grill, mit Senf oder Ketchup",
- "price": 4.5,
- "taxRate": 7,
- "imageUrl": null,
- "icon": "pos-icon:sausage-bun",
- "isFavorite": true,
- "isActive": true,
- "isAvailable": true,
- "trackInventory": true,
- "stockQuantity": 120,
- "stockUnit": "Stück",
- "lowStockThreshold": 20,
- "options": {
- "groups": [
- {
- "name": "Soße",
- "type": "single",
- "required": false,
- "options": [
- {
- "name": "Senf",
- "priceModifier": 0,
- "default": true
}, - {
- "name": "Ketchup",
- "priceModifier": 0
}
]
}
]
}, - "printSettings": null,
- "sortOrder": 1,
- "productionStationId": "c0ffee00-1111-4222-8333-444455556666",
- "pfandTypeId": null,
- "category": {
- "id": "9e8d7c6b-5a4f-4e3d-9c2b-1a0f9e8d7c6b",
- "eventId": "2f6c1a9e-5b1d-4c7e-9a3f-0d8e7b6a5c41",
- "name": "Grill",
- "sortOrder": 1,
- "isActive": true
}, - "createdAt": "2026-05-21T08:14:02.000Z",
- "updatedAt": "2026-07-10T17:40:11.000Z"
}, - {
- "id": "6e5d4c3b-2a1f-4e0d-9c8b-7a6f5e4d3c2b",
- "eventId": "2f6c1a9e-5b1d-4c7e-9a3f-0d8e7b6a5c41",
- "categoryId": "f1e2d3c4-b5a6-4978-8a9b-0c1d2e3f4a5b",
- "name": "Pils 0,5 l",
- "description": null,
- "price": 4,
- "taxRate": 19,
- "imageUrl": null,
- "icon": "pos-icon:beer-glass",
- "isFavorite": false,
- "isActive": true,
- "isAvailable": true,
- "trackInventory": false,
- "stockQuantity": 0,
- "stockUnit": "Stück",
- "lowStockThreshold": null,
- "options": {
- "groups": [ ]
}, - "printSettings": null,
- "sortOrder": 2,
- "productionStationId": null,
- "pfandTypeId": "d1e2f3a4-b5c6-4d7e-8f9a-0b1c2d3e4f5a",
- "category": {
- "id": "f1e2d3c4-b5a6-4978-8a9b-0c1d2e3f4a5b",
- "eventId": "2f6c1a9e-5b1d-4c7e-9a3f-0d8e7b6a5c41",
- "name": "Getränke",
- "sortOrder": 2,
- "isActive": true
}, - "createdAt": "2026-05-21T08:14:02.000Z",
- "updatedAt": "2026-07-10T17:40:11.000Z"
}
], - "meta": {
- "page": 1,
- "limit": 50,
- "total": 2,
- "totalPages": 1,
- "hasNext": false,
- "hasPrev": false
}
}Legt ein Produkt in einer Kategorie der Veranstaltung an: Preis, Steuersatz, Optionen, Pfandart, Station, Bestand. Scope catalog:write und Modulrecht Produkte.
| eventId required | string <uuid> ID der Veranstaltung |
| categoryId required | string ID der Kategorie |
| name required | string Name des Produkts |
| price required | number Verkaufspreis in Euro |
| description | string Beschreibung des Produkts |
| taxRate | number Umsatzsteuersatz in Prozent. 0 heißt steuerfrei. |
| imageUrl | string URL des Produktbilds |
| icon | string Icon: |
| isFavorite | boolean Favorit: erscheint an der Kasse unter „Favoriten“ |
| isActive | boolean Gibt an, ob das Produkt aktiv ist |
| isAvailable | boolean Gibt an, ob das Produkt verfügbar ist |
| trackInventory | boolean Gibt an, ob der Lagerbestand verfolgt wird |
| stockQuantity | number Anfänglicher Lagerbestand |
| stockUnit | string Einheit für den Lagerbestand |
| options | object Produktoptionen |
| printSettings | object Druckeinstellungen |
| sortOrder | number Sortierreihenfolge |
| productionStationId | string ID des Produktionsstandorts (überschreibt Kategorie-Einstellung) |
| pfandTypeId | object ID des Pfand-Typs (optional) |
{- "categoryId": "550e8400-e29b-41d4-a716-446655440000",
- "name": "Wiener Schnitzel",
- "description": "Paniertes Kalbsschnitzel mit Kartoffelsalat",
- "price": 12.5,
- "taxRate": 19,
- "icon": "oe:beer",
- "isFavorite": false,
- "isActive": true,
- "isAvailable": true,
- "trackInventory": false,
- "stockQuantity": 50,
- "stockUnit": "Stück",
- "options": {
- "sizes": [
- "S",
- "M",
- "L"
], - "extras": [
- "Pommes",
- "Salat"
]
}, - "printSettings": {
- "printToKitchen": true,
- "copies": 1
}, - "sortOrder": 1,
- "productionStationId": "550e8400-e29b-41d4-a716-446655440000",
- "pfandTypeId": "550e8400-e29b-41d4-a716-446655440000"
}Legt mehrere Produkte aus einer CSV-Liste in einem Aufruf an, fehlende Kategorien werden ergänzt; mit dryRun nur Vorschau. Scope catalog:write.
| eventId required | string <uuid> ID der Veranstaltung |
| csv required | string Roher CSV-Inhalt der Produktliste |
| mode | string Default: "skip" Enum: "skip" "update" "create" Verhalten bei vorhandenen Produkten (gleicher Name + Kategorie): überspringen, aktualisieren oder immer neu anlegen |
| dryRun | boolean Default: true true = nur Vorschau berechnen, nichts speichern |
{- "csv": "string",
- "mode": "skip",
- "dryRun": true
}Ändert beliebige Felder eines Produkts; nicht genannte Felder bleiben. Scope catalog:write.
| eventId required | string <uuid> ID der Veranstaltung |
| productId required | string <uuid> ID des Produkts |
| categoryId | string ID der Kategorie |
| name | string Name des Produkts |
| description | object Beschreibung des Produkts |
| price | number Verkaufspreis in Euro |
| taxRate | number Umsatzsteuersatz in Prozent. 0 heißt steuerfrei. |
| imageUrl | object URL des Produktbilds |
| icon | object Icon: |
| isFavorite | boolean Favorit: erscheint an der Kasse unter „Favoriten“ |
| isActive | boolean Gibt an, ob das Produkt aktiv ist |
| isAvailable | boolean Gibt an, ob das Produkt verfügbar ist |
| trackInventory | boolean Gibt an, ob der Lagerbestand verfolgt wird |
| stockQuantity | number Aktueller Lagerbestand |
| stockUnit | string Einheit für den Lagerbestand |
| options | object Produktoptionen |
| printSettings | object Druckeinstellungen |
| sortOrder | number Sortierreihenfolge |
| productionStationId | object ID des Produktionsstandorts (überschreibt Kategorie-Einstellung) |
| pfandTypeId | object ID des Pfand-Typs (optional) |
{- "categoryId": "550e8400-e29b-41d4-a716-446655440000",
- "name": "Wiener Schnitzel",
- "description": "Paniertes Kalbsschnitzel mit Kartoffelsalat",
- "price": 12.5,
- "taxRate": 19,
- "icon": "oe:beer",
- "isFavorite": false,
- "isActive": true,
- "isAvailable": true,
- "trackInventory": true,
- "stockQuantity": 50,
- "stockUnit": "Stück",
- "options": {
- "sizes": [
- "S",
- "M",
- "L"
], - "extras": [
- "Pommes",
- "Salat"
]
}, - "printSettings": {
- "printToKitchen": true,
- "copies": 1
}, - "sortOrder": 1,
- "productionStationId": "550e8400-e29b-41d4-a716-446655440000",
- "pfandTypeId": "550e8400-e29b-41d4-a716-446655440000"
}Markiert ein Produkt als verfügbar oder ausverkauft, ohne es zu deaktivieren; die Kassen übernehmen das sofort. Scope catalog:write.
| eventId required | string <uuid> ID der Veranstaltung |
| productId required | string <uuid> ID des Produkts |
| isAvailable required | boolean true = verfügbar, false = ausverkauft |
{- "isAvailable": false
}Legt eine Pfandart (z. B. Glas 2 €) für die Organisation an. Scope catalog:write und Modulrecht Pfand.
| organizationId required | string <uuid> ID der Organisation |
| name required | string Name des Pfand-Typs |
| amount required | number Pfandbetrag pro Einheit in EUR |
| isActive | boolean Ob der Pfand-Typ aktiv (an der Kasse nutzbar) ist |
| sortOrder | number Sortierreihenfolge |
{- "name": "Becher",
- "amount": 2,
- "isActive": true,
- "sortOrder": 0
}Ändert Name, Betrag oder Sichtbarkeit einer Pfandart. Scope catalog:write.
| organizationId required | string <uuid> ID der Organisation |
| pfandTypeId required | string <uuid> ID der Pfandart |
| name | string Name des Pfand-Typs |
| amount | number Pfandbetrag pro Einheit in EUR |
| isActive | boolean Ob der Pfand-Typ aktiv (an der Kasse nutzbar) ist |
| sortOrder | number Sortierreihenfolge |
{- "name": "Becher",
- "amount": 2,
- "isActive": true,
- "sortOrder": 0
}Legt einen Bereich (z. B. Festzelt, Biergarten) an. Scope tables:write und Modulrecht Veranstaltungen.
| organizationId required | string <uuid> ID der Organisation |
| name required | string Name des Bereichs |
| width | number Breite der Karte |
| height | number Höhe der Karte |
| gridSize | number Rasterweite |
{- "name": "Zelt A",
- "width": 1200,
- "height": 800,
- "gridSize": 20
}Setzt die Reihenfolge der Bereiche anhand der übergebenen ID-Liste. Scope tables:write.
| organizationId required | string <uuid> ID der Organisation |
| ids required | Array of strings Bereichs-IDs in neuer Reihenfolge |
{- "ids": [
- "string"
]
}Ändert Name, Größe, Raster oder Deko eines Bereichs. Scope tables:write.
| organizationId required | string <uuid> ID der Organisation |
| areaId required | string <uuid> ID des Bereichs |
| name | string Name des Bereichs |
| width | number Breite der Karte |
| height | number Höhe der Karte |
| gridSize | number Rasterweite |
Array of objects (TableAreaDecorDto) | |
Array of objects or null (TableAreaPointDto) Umriss des Raums (Polygon, 3–100 Punkte); null = ganze Karte |
{- "name": "Zelt A",
- "width": 1200,
- "height": 800,
- "gridSize": 20,
- "decor": [
- {
- "id": "d1",
- "type": "bar",
- "x": 0,
- "y": 0,
- "width": 0,
- "height": 0,
- "rotation": 0,
- "points": [
- {
- "x": 120,
- "y": 40
}
], - "thickness": 10,
- "zoneType": "kitchen",
- "label": "Theke"
}
], - "outline": [
- {
- "x": 120,
- "y": 40
}
]
}Ersetzt die Karte eines Bereichs (Positionen der Tische und Deko) vollständig. Scope tables:write.
| organizationId required | string <uuid> ID der Organisation |
| areaId required | string <uuid> ID des Bereichs |
required | Array of objects (LayoutTableDto) |
Array of objects (TableAreaDecorDto) | |
Array of objects or null (TableAreaPointDto) Umriss des Raums (Polygon, 3–100 Punkte); null = ganze Karte |
{- "tables": [
- {
- "id": "string",
- "x": 0,
- "y": 0,
- "width": 0,
- "height": 0,
- "rotation": 0,
- "shape": "rect"
}
], - "decor": [
- {
- "id": "d1",
- "type": "bar",
- "x": 0,
- "y": 0,
- "width": 0,
- "height": 0,
- "rotation": 0,
- "points": [
- {
- "x": 120,
- "y": 40
}
], - "thickness": 10,
- "zoneType": "kitchen",
- "label": "Theke"
}
], - "outline": [
- {
- "x": 120,
- "y": 40
}
]
}Legt einen Tisch in einem Bereich an. Scope tables:write.
| organizationId required | string <uuid> ID der Organisation |
| areaId required | string |
| label required | string Bezeichnung (1–20 Zeichen) |
| seats | object or null |
| shape | string Enum: "rect" "round" |
| x | number |
| y | number |
| width | number |
| height | number |
| rotation | number |
{- "areaId": "string",
- "label": "A03",
- "seats": 6,
- "shape": "rect",
- "x": 0,
- "y": 0,
- "width": 80,
- "height": 80,
- "rotation": 0
}Legt mehrere Tische mit fortlaufender Nummer in einem Aufruf an (z. B. A01–A12). Scope tables:write.
| organizationId required | string <uuid> ID der Organisation |
| areaId required | string |
| prefix required | string Präfix, darf leer sein |
| start required | number |
| count required | number 1–100 Tische |
| padding required | number Stellen der Nummer (0–3) |
| seats | number |
| shape | string Enum: "rect" "round" |
object (BulkLayoutDto) |
{- "areaId": "string",
- "prefix": "A",
- "start": 1,
- "count": 12,
- "padding": 2,
- "seats": 6,
- "shape": "rect",
- "layout": {
- "cols": 6,
- "gap": 40
}
}Ändert Name, Plätze, Position oder Bereich eines Tischs. Scope tables:write.
| organizationId required | string <uuid> ID der Organisation |
| tableId required | string <uuid> ID des Tischs |
| areaId | string |
| label | string Bezeichnung (1–20 Zeichen) |
| seats | object or null |
| shape | string Enum: "rect" "round" |
| x | number |
| y | number |
| width | number |
| height | number |
| rotation | number |
| isActive | boolean |
{- "areaId": "string",
- "label": "A03",
- "seats": 6,
- "shape": "rect",
- "x": 0,
- "y": 0,
- "width": 80,
- "height": 80,
- "rotation": 0,
- "isActive": true
}Produktionsstationen (Küche, Ausgabe, Bar) je Veranstaltung, an die Bestellpositionen gehen
Legt eine Produktionsstation (Küche, Ausgabe, Bar) für die Veranstaltung an, optional mit Drucker. Scope events:write und Modulrecht Veranstaltungen.
| eventId required | string <uuid> ID der Veranstaltung |
| name required | string Name des Produktionsstandorts |
| description | string Beschreibung |
| color | string Farbcode (Hex-Format) |
| sortOrder | number Sortierreihenfolge |
| isActive | boolean Gibt an, ob der Standort aktiv ist |
| printerId | object ID des zugewiesenen Druckers |
| handoffStationId | object ID des Übergabe-Standorts (nächste Station in der Kette) |
{- "name": "Küche",
- "description": "Hauptküche für warme Speisen",
- "color": "#FF5733",
- "sortOrder": 0,
- "isActive": true,
- "printerId": "550e8400-e29b-41d4-a716-446655440000",
- "handoffStationId": "550e8400-e29b-41d4-a716-446655440000"
}Ändert Name, Drucker oder Einstellungen einer Station. Scope events:write.
| eventId required | string <uuid> ID der Veranstaltung |
| stationId required | string <uuid> ID der Station |
| name | string Name des Produktionsstandorts |
| description | object Beschreibung |
| color | object Farbcode (Hex-Format) |
| sortOrder | number Sortierreihenfolge |
| isActive | boolean Gibt an, ob der Standort aktiv ist |
| printerId | object ID des zugewiesenen Druckers |
| handoffStationId | object ID des Übergabe-Standorts (nächste Station in der Kette) |
{- "name": "Küche",
- "description": "Hauptküche für warme Speisen",
- "color": "#FF5733",
- "sortOrder": 0,
- "isActive": true,
- "printerId": "550e8400-e29b-41d4-a716-446655440000",
- "handoffStationId": "550e8400-e29b-41d4-a716-446655440000"
}Alle Drucker der Organisation mit Verbindungsstatus, seitenweise (page, limit). Scope read; anlegen, ändern und Testdruck gehen nur in der App.
| organizationId required | string <uuid> ID der Organisation |
| page | number >= 1 Default: 1 Example: page=1 Seite, beginnend bei 1 |
| limit | number [ 1 .. 500 ] Default: 20 Example: limit=20 Einträge je Seite (höchstens 500) |
Alle Bon-Vorlagen der Organisation, seitenweise (page, limit). Scope read.
| organizationId required | string <uuid> ID der Organisation |
| page | number >= 1 Default: 1 Example: page=1 Seite, beginnend bei 1 |
| limit | number [ 1 .. 500 ] Default: 20 Example: limit=20 Einträge je Seite (höchstens 500) |
Legt eine Vorlage für Bons oder Bestellzettel an. Scope devices:write und Modulrecht Geräte.
| organizationId required | string <uuid> ID der Organisation |
| name required | string Name der Druckvorlage |
| type required | string Enum: "receipt" "kitchen_ticket" "order_ticket" Typ der Druckvorlage |
| template | object Vorlagen-Definition |
| isDefault | boolean Gibt an, ob dies die Standardvorlage ist |
{- "name": "Kassenbon Standard",
- "type": "receipt",
- "template": {
- "header": "Musterverein e.V.",
- "showLogo": true
}, - "isDefault": false
}Ändert Name, Typ oder Definition einer Vorlage. Scope devices:write.
| organizationId required | string <uuid> ID der Organisation |
| templateId required | string <uuid> ID der Vorlage |
| name | string Name der Druckvorlage |
| template | object Vorlagen-Definition |
| isDefault | boolean Gibt an, ob dies die Standardvorlage ist |
{- "name": "Kassenbon Standard",
- "template": {
- "header": "Musterverein e.V.",
- "showLogo": true
}, - "isDefault": true
}Rendert die Vorlage mit Beispieldaten und liefert das Ergebnis als HTML (data.html), ohne zu drucken. Scope read.
| organizationId required | string <uuid> ID der Organisation |
| templateId required | string <uuid> ID der Vorlage |
Schichtpläne mit Jobs, Schichten und Helfer-Anmeldungen. E-Mail-Versand und Löschen bleiben der App vorbehalten.
Legt einen Schichtplan als Entwurf an. Scope staff:write und Modulrecht Schichtpläne.
| organizationId required | string <uuid> ID der Organisation |
| name required | string Name of the shift plan |
| description | string Description shown to helpers |
| eventId | string Optional linked event ID |
| publicSlug | string Custom URL slug (auto-generated if not provided) |
| requireApproval | boolean Default: true Whether registrations require admin approval |
| allowMultipleShifts | boolean Default: true Allow registering for multiple shifts |
| reminderDaysBefore | number Default: 1 Days before shift to send reminder email |
| maxShiftsPerPerson | number Max shifts per person (0 = unlimited) |
| verificationReminderEnabled | boolean Default: true Whether the cron sends verification reminders for pending_email helpers |
| verificationReminderIntervalHours | number Default: 24 Hours between two verification reminders |
| verificationReminderMaxCount | number Default: 5 Max number of verification reminders per helper-group |
{- "name": "Vereinsfest 2024 Schichtplan",
- "description": "string",
- "eventId": "string",
- "publicSlug": "vereinsfest-2024",
- "requireApproval": true,
- "allowMultipleShifts": true,
- "reminderDaysBefore": 1,
- "maxShiftsPerPerson": 0,
- "verificationReminderEnabled": true,
- "verificationReminderIntervalHours": 24,
- "verificationReminderMaxCount": 5
}Ändert Name, Zeitraum, Beschreibung oder Einstellungen eines Schichtplans. Scope staff:write.
| organizationId required | string <uuid> ID der Organisation |
| planId required | string <uuid> ID des Schichtplans |
| name | string Name of the shift plan |
| description | string Description shown to helpers |
| eventId | string Optional linked event ID |
| publicSlug | string Custom URL slug (auto-generated if not provided) |
| requireApproval | boolean Default: true Whether registrations require admin approval |
| allowMultipleShifts | boolean Default: true Allow registering for multiple shifts |
| reminderDaysBefore | number Default: 1 Days before shift to send reminder email |
| maxShiftsPerPerson | number Max shifts per person (0 = unlimited) |
| verificationReminderEnabled | boolean Default: true Whether the cron sends verification reminders for pending_email helpers |
| verificationReminderIntervalHours | number Default: 24 Hours between two verification reminders |
| verificationReminderMaxCount | number Default: 5 Max number of verification reminders per helper-group |
{- "name": "Vereinsfest 2024 Schichtplan",
- "description": "string",
- "eventId": "string",
- "publicSlug": "vereinsfest-2024",
- "requireApproval": true,
- "allowMultipleShifts": true,
- "reminderDaysBefore": 1,
- "maxShiftsPerPerson": 0,
- "verificationReminderEnabled": true,
- "verificationReminderIntervalHours": 24,
- "verificationReminderMaxCount": 5
}Schaltet den Plan für die öffentliche Helfer-Anmeldung frei (400 SHIFT_PLAN_ALREADY_PUBLISHED, wenn er schon offen ist). Scope staff:write.
| organizationId required | string <uuid> ID der Organisation |
| planId required | string <uuid> ID des Schichtplans |
Liefert den Plan mit allen Jobs, Schichten und eingetragenen Helfern als Datei (application/pdf). Scope read.
| organizationId required | string <uuid> ID der Organisation |
| planId required | string <uuid> ID des Schichtplans |
Legt eine Aufgabe (z. B. Ausschank, Kasse) im Schichtplan an. Scope staff:write.
| organizationId required | string <uuid> ID der Organisation |
| planId required | string <uuid> ID des Schichtplans |
| name required | string Name of the job |
| description | string Description of what this job involves |
| color | string Color code for UI display |
| sortOrder | number Default: 0 Sort order (lower = first) |
| requiredWorkers | number Default: 1 Default number of helpers per shift |
{- "name": "Zapfen",
- "description": "string",
- "color": "#3b82f6",
- "sortOrder": 0,
- "requiredWorkers": 1
}Ändert Name, Beschreibung oder Reihenfolge eines Jobs. Scope staff:write.
| organizationId required | string <uuid> ID der Organisation |
| jobId required | string <uuid> ID des Jobs |
| name | string Name of the job |
| description | string Description of what this job involves |
| color | string Color code for UI display |
| sortOrder | number Default: 0 Sort order (lower = first) |
| requiredWorkers | number Default: 1 Default number of helpers per shift |
{- "name": "Zapfen",
- "description": "string",
- "color": "#3b82f6",
- "sortOrder": 0,
- "requiredWorkers": 1
}Legt eine Schicht (Zeitraum, benötigte Helfer) für einen Job an. Scope staff:write.
| organizationId required | string <uuid> ID der Organisation |
| jobId required | string <uuid> ID des Jobs |
| date required | string Date of the shift |
| startTime required | string Start time (HH:mm) |
| endTime required | string End time (HH:mm) |
| requiredWorkers | number Default: 1 Number of workers needed |
| notes | string Internal notes (not shown to helpers) |
{- "date": "2024-07-20",
- "startTime": "14:00",
- "endTime": "18:00",
- "requiredWorkers": 1,
- "notes": "string"
}Legt mehrere Schichten für einen Job in einem Aufruf an. Scope staff:write.
| organizationId required | string <uuid> ID der Organisation |
| jobId required | string <uuid> ID des Jobs |
required | Array of objects (CreateShiftDto) Schichten, die angelegt werden | ||||||||||
Array
| |||||||||||
{- "shifts": [
- {
- "date": "2024-07-20",
- "startTime": "14:00",
- "endTime": "18:00",
- "requiredWorkers": 1,
- "notes": "string"
}
]
}Ändert Zeitraum, benötigte Helfer oder Notiz einer Schicht. Scope staff:write.
| organizationId required | string <uuid> ID der Organisation |
| shiftId required | string <uuid> ID der Schicht |
| date | string Date of the shift |
| startTime | string Start time (HH:mm) |
| endTime | string End time (HH:mm) |
| requiredWorkers | number Default: 1 Number of workers needed |
| notes | string Internal notes (not shown to helpers) |
{- "date": "2024-07-20",
- "startTime": "14:00",
- "endTime": "18:00",
- "requiredWorkers": 1,
- "notes": "string"
}Bestätigt eine Helfer-Anmeldung; der Helfer bekommt eine E-Mail, optional mit Nachricht. Scope staff:write.
| organizationId required | string <uuid> ID der Organisation |
| registrationId required | string <uuid> ID der Anmeldung |
| message | string Optional message to include in confirmation email |
{- "message": "string"
}Lehnt eine Helfer-Anmeldung ab; der Grund geht per E-Mail an den Helfer. Scope staff:write.
| organizationId required | string <uuid> ID der Organisation |
| registrationId required | string <uuid> ID der Anmeldung |
| reason | string Reason for rejection (shown to helper) |
{- "reason": "string"
}Ändert Name, Kontakt, Notizen oder Schicht einer Anmeldung; auf Wunsch wird der Helfer per E-Mail informiert. Scope staff:write.
| organizationId required | string <uuid> ID der Organisation |
| registrationId required | string <uuid> ID der Anmeldung |
| name | string |
string | |
| phone | string |
| notes | string |
| adminNotes | string |
| shiftId | string Move the registration to a different shift. The helper will be notified by default unless |
| notifyMessage | string Optional note included in the change-notification email. |
| notify | boolean Default: true When true and the shift is moved, send the helper an update email. Default true. |
{- "name": "string",
- "email": "string",
- "phone": "string",
- "notes": "string",
- "adminNotes": "string",
- "shiftId": "string",
- "notifyMessage": "string",
- "notify": true
}Speichert eine Notiz, die nur Organisatoren sehen. Scope staff:write.
| organizationId required | string <uuid> ID der Organisation |
| registrationId required | string <uuid> ID der Anmeldung |
| adminNotes | string Internal admin notes |
{- "adminNotes": "string"
}Trägt einen Helfer direkt in eine Schicht ein, ohne öffentliche Anmeldung. Scope staff:write.
| organizationId required | string <uuid> ID der Organisation |
| shiftId required | string <uuid> ID der Schicht |
| name required | string Helper name |
string Helper email — used for notifications. Optional when adding helpers manually. | |
| phone | string Phone number |
| notes | string Helper-side notes (visible to admin too) |
| adminNotes | string Admin-only notes |
| notify | boolean Default: false When true, send a confirmation email to the helper. Default false (silent admin add). |
| registrationGroupId | string Append the new registration to an existing helper-group. When omitted, a fresh group ID is created (= a new standalone helper). |
{- "name": "Max Mustermann",
- "email": "max@example.com",
- "phone": "string",
- "notes": "string",
- "adminNotes": "string",
- "notify": false,
- "registrationGroupId": "string"
}Auswertungen über Umsatz, Produkte, Zahlarten, Geräte und Bestand. Der Token-Besitzer braucht das Modulrecht „Auswertung“.
Umsatz, Bestellungen und Durchschnittsbon im Zeitraum (startDate, endDate), optional je Veranstaltung und gruppiert (groupBy). Scope read und Modulrecht Auswertung.
| organizationId required | any <uuid> ID der Organisation |
| eventId | string Example: eventId=550e8400-e29b-41d4-a716-446655440000 Filter nach Event-ID |
| startDate | string Example: startDate=2024-01-01T00:00:00.000Z Startdatum für den Bericht |
| endDate | string Example: endDate=2024-12-31T23:59:59.000Z Enddatum für den Bericht |
| groupBy | string Enum: "day" "week" "month" "category" "product" "payment_method" Example: groupBy=day Gruppierung der Berichtsdaten |
Verkaufte Menge und Umsatz je Produkt im Zeitraum, optional je Veranstaltung. Scope read und Modulrecht Auswertung.
| organizationId required | any <uuid> ID der Organisation |
| eventId | string Example: eventId=550e8400-e29b-41d4-a716-446655440000 Filter nach Event-ID |
| startDate | string Example: startDate=2024-01-01T00:00:00.000Z Startdatum für den Bericht |
| endDate | string Example: endDate=2024-12-31T23:59:59.000Z Enddatum für den Bericht |
| groupBy | string Enum: "day" "week" "month" "category" "product" "payment_method" Example: groupBy=day Gruppierung der Berichtsdaten |
Summen und Anzahl je Zahlart (bar, Karte, SumUp, Rabatt) im Zeitraum. Scope read und Modulrecht Auswertung.
| organizationId required | any <uuid> ID der Organisation |
| eventId | string Example: eventId=550e8400-e29b-41d4-a716-446655440000 Filter nach Event-ID |
| startDate | string Example: startDate=2024-01-01T00:00:00.000Z Startdatum für den Bericht |
| endDate | string Example: endDate=2024-12-31T23:59:59.000Z Enddatum für den Bericht |
| groupBy | string Enum: "day" "week" "month" "category" "product" "payment_method" Example: groupBy=day Gruppierung der Berichtsdaten |
Bestellungen und Umsatz je Stunde im Zeitraum, für Stoßzeiten und Personalplanung. Scope read und Modulrecht Auswertung.
| organizationId required | any <uuid> ID der Organisation |
| eventId | string Example: eventId=550e8400-e29b-41d4-a716-446655440000 Filter nach Event-ID |
| startDate | string Example: startDate=2024-01-01T00:00:00.000Z Startdatum für den Bericht |
| endDate | string Example: endDate=2024-12-31T23:59:59.000Z Enddatum für den Bericht |
| groupBy | string Enum: "day" "week" "month" "category" "product" "payment_method" Example: groupBy=day Gruppierung der Berichtsdaten |
Bestellungen und Umsatz je Kanal (Kasse, Online, QR-Bestellung) im Zeitraum. Scope read und Modulrecht Auswertung.
| organizationId required | any <uuid> ID der Organisation |
| eventId | string Example: eventId=550e8400-e29b-41d4-a716-446655440000 Filter nach Event-ID |
| startDate | string Example: startDate=2024-01-01T00:00:00.000Z Startdatum für den Bericht |
| endDate | string Example: endDate=2024-12-31T23:59:59.000Z Enddatum für den Bericht |
| groupBy | string Enum: "day" "week" "month" "category" "product" "payment_method" Example: groupBy=day Gruppierung der Berichtsdaten |
Verkaufte Menge, Umsatz und Anteil je Kategorie im Zeitraum. Scope read und Modulrecht Auswertung.
| organizationId required | any <uuid> ID der Organisation |
| eventId | string Example: eventId=550e8400-e29b-41d4-a716-446655440000 Filter nach Event-ID |
| startDate | string Example: startDate=2024-01-01T00:00:00.000Z Startdatum für den Bericht |
| endDate | string Example: endDate=2024-12-31T23:59:59.000Z Enddatum für den Bericht |
| groupBy | string Enum: "day" "week" "month" "category" "product" "payment_method" Example: groupBy=day Gruppierung der Berichtsdaten |
Produkt- und Kategoriezeilen zeigen den Warenwert netto (Storno und erstattete Mengen ab, Rabatt anteilig, ohne Pfand und Trinkgeld). Hier steht, was keiner Position gehört: itemsRevenue + unassignedRefunds (Kulanz-Erstattungen ohne Position, negativ) + tips = netRevenue (wie totalRevenue im Umsatzbericht). Die Summe der gerundeten Zeilen kann bei Rabatten um Cent von itemsRevenue abweichen. Scope read und Modulrecht Auswertung.
| organizationId required | any <uuid> ID der Organisation |
| eventId | string Example: eventId=550e8400-e29b-41d4-a716-446655440000 Filter nach Event-ID |
| startDate | string Example: startDate=2024-01-01T00:00:00.000Z Startdatum für den Bericht |
| endDate | string Example: endDate=2024-12-31T23:59:59.000Z Enddatum für den Bericht |
| groupBy | string Enum: "day" "week" "month" "category" "product" "payment_method" Example: groupBy=day Gruppierung der Berichtsdaten |
Bestellungen und Umsatz je Kasse im Zeitraum. Scope read und Modulrecht Auswertung.
| organizationId required | any <uuid> ID der Organisation |
| eventId | string Example: eventId=550e8400-e29b-41d4-a716-446655440000 Filter nach Event-ID |
| startDate | string Example: startDate=2024-01-01T00:00:00.000Z Startdatum für den Bericht |
| endDate | string Example: endDate=2024-12-31T23:59:59.000Z Enddatum für den Bericht |
| groupBy | string Enum: "day" "week" "month" "category" "product" "payment_method" Example: groupBy=day Gruppierung der Berichtsdaten |
Alle Bestandsbewegungen (Verkauf, Korrektur, Inventur) im Zeitraum, optional je Veranstaltung. Scope read und Modulrecht Auswertung.
| organizationId required | any <uuid> ID der Organisation |
| eventId | string Example: eventId=550e8400-e29b-41d4-a716-446655440000 Filter nach Event-ID |
| startDate | string Example: startDate=2024-01-01T00:00:00.000Z Startdatum für den Bericht |
| endDate | string Example: endDate=2024-12-31T23:59:59.000Z Enddatum für den Bericht |
| groupBy | string Enum: "day" "week" "month" "category" "product" "payment_method" Example: groupBy=day Gruppierung der Berichtsdaten |
type wählt den Bericht, format das Dateiformat; die Antwort ist ein Download (Content-Disposition: attachment). Scope read und Modulrecht Auswertung.
| organizationId required | any <uuid> ID der Organisation |
| format required | string Enum: "csv" "excel" "json" Example: format=csv Exportformat des Berichts |
| eventId | string Example: eventId=550e8400-e29b-41d4-a716-446655440000 Filter nach Event-ID |
| startDate | string Example: startDate=2024-01-01T00:00:00.000Z Startdatum für den Bericht |
| endDate | string Example: endDate=2024-12-31T23:59:59.000Z Enddatum für den Bericht |
| groupBy | string Enum: "day" "week" "month" "category" "product" "payment_method" Example: groupBy=day Gruppierung der Berichtsdaten |
| type | string Enum: "sales" "products" "payments" "hourly" "channels" "categories" "devices" "inventory" Welcher Bericht exportiert wird (Standard: sales) |
Bestellungen lesen und auswerten. Anlegen, Kassieren, Stornieren und Erstatten sind der Kasse und der App vorbehalten.
Bestellungen der Organisation, neueste zuerst, seitenweise (höchstens 100 je Seite) und filterbar nach Veranstaltung, Status, Zahlart, Gerät und Zeitraum; includeItems=true liefert die Positionen mit. Scope read. Anlegen, Stornieren und Erstatten sind der Kasse und der App vorbehalten.
| organizationId required | string <uuid> ID der Organisation |
| page | number >= 1 Default: 1 Example: page=1 Seite, beginnend bei 1 |
| limit | number [ 1 .. 500 ] Default: 20 Example: limit=50 Anzahl pro Seite (max. 100) |
| eventId | string Example: eventId=550e8400-e29b-41d4-a716-446655440000 Filter nach Event-ID |
| status | string Enum: "open" "in_progress" "ready" "completed" "cancelled" Example: status=open Filter nach Bestellstatus |
| paymentStatus | string Enum: "unpaid" "partly_paid" "paid" "refunded" Example: paymentStatus=pending Filter nach Zahlungsstatus |
| source | string Enum: "pos" "online" "qr_order" Example: source=pos Filter nach Bestellquelle |
| fulfillmentType | string Enum: "table_service" "counter_pickup" Example: fulfillmentType=counter_pickup Filter nach Erfüllungstyp |
| dateFrom | string Example: dateFrom=2024-01-01T00:00:00.000Z Startdatum für Filterung |
| dateTo | string Example: dateTo=2024-12-31T23:59:59.000Z Enddatum für Filterung |
| includeItems | boolean Example: includeItems=true Bestellpositionen einschließen |
| q | string Example: q=Burger Suche: Bestell-/Tagesnummer, Tisch, Name oder Produkt |
| displayStatus | string Example: displayStatus=unpaid,refunded Status wie in der Kasse (kommagetrennt): in_kitchen, ready, completed, unpaid, cancelled, partly_refunded, refunded |
| paymentMethod | string Example: paymentMethod=cash,sumup Zahlart (kommagetrennt): cash, card, sumup, discount |
| deviceId | string Nur Bestellungen dieses Geräts |
| data | Array of objects |
object Seitenangaben |
{- "data": [
- {
- "id": "0a1b2c3d-4e5f-4a6b-8c7d-9e0f1a2b3c4d",
- "organizationId": "8c1e2d3f-4a5b-4c6d-8e7f-9a0b1c2d3e4f",
- "eventId": "2f6c1a9e-5b1d-4c7e-9a3f-0d8e7b6a5c41",
- "orderNumber": "SF-0042",
- "dailyNumber": 42,
- "tableNumber": "A03",
- "tableId": "1234abcd-5678-4ef0-9abc-def012345678",
- "acknowledgedAt": "2026-07-11T18:05:30.000Z",
- "clientRequestId": null,
- "isTest": false,
- "customerName": null,
- "customerPhone": null,
- "status": "completed",
- "paymentStatus": "paid",
- "source": "pos",
- "subtotal": 12.5,
- "taxTotal": 1.49,
- "total": 14.5,
- "paidAmount": 14.5,
- "tipAmount": 0,
- "discountAmount": 0,
- "discountReason": null,
- "refundedAmount": 0,
- "pfandTotal": 2,
- "notes": null,
- "priority": "normal",
- "fulfillmentType": "table_service",
- "estimatedReadyAt": null,
- "readyAt": "2026-07-11T18:12:03.000Z",
- "completedAt": "2026-07-11T18:15:47.000Z",
- "cancelledAt": null,
- "cancellationReason": null,
- "createdByUserId": null,
- "createdByDeviceId": "7f6e5d4c-3b2a-4190-8f7e-6d5c4b3a2910",
- "onlineSessionId": null,
- "createdByUser": null,
- "createdByDevice": {
- "id": "7f6e5d4c-3b2a-4190-8f7e-6d5c4b3a2910",
- "name": "Kasse Festzelt 1"
}, - "displayStatus": "completed",
- "paymentMethods": [
- "cash"
], - "createdAt": "2026-07-11T18:04:58.000Z",
- "updatedAt": "2026-07-11T18:15:47.000Z"
}, - {
- "id": "1b2c3d4e-5f6a-4b7c-9d8e-0f1a2b3c4d5e",
- "organizationId": "8c1e2d3f-4a5b-4c6d-8e7f-9a0b1c2d3e4f",
- "eventId": "2f6c1a9e-5b1d-4c7e-9a3f-0d8e7b6a5c41",
- "orderNumber": "SF-0041",
- "dailyNumber": 41,
- "tableNumber": null,
- "tableId": null,
- "acknowledgedAt": "2026-07-11T18:05:30.000Z",
- "clientRequestId": null,
- "isTest": false,
- "customerName": null,
- "customerPhone": null,
- "status": "open",
- "paymentStatus": "unpaid",
- "source": "qr_order",
- "subtotal": 8,
- "taxTotal": 1.28,
- "total": 8,
- "paidAmount": 0,
- "tipAmount": 0,
- "discountAmount": 0,
- "discountReason": null,
- "refundedAmount": 0,
- "pfandTotal": 0,
- "notes": null,
- "priority": "normal",
- "fulfillmentType": "counter_pickup",
- "estimatedReadyAt": null,
- "readyAt": null,
- "completedAt": null,
- "cancelledAt": null,
- "cancellationReason": null,
- "createdByUserId": null,
- "createdByDeviceId": null,
- "onlineSessionId": null,
- "createdByUser": null,
- "createdByDevice": null,
- "displayStatus": "unpaid",
- "paymentMethods": [ ],
- "createdAt": "2026-07-11T18:03:10.000Z",
- "updatedAt": "2026-07-11T18:03:10.000Z"
}
], - "meta": {
- "page": 1,
- "limit": 50,
- "total": 2,
- "totalPages": 1,
- "hasNext": false,
- "hasPrev": false
}
}Anzahl, Umsatz, Durchschnittsbon und Pfand über alle Bestellungen, die zu den Filtern passen — ohne Seitenwechsel; stornierte zählen in count, aber nicht in die Beträge. Scope read.
| organizationId required | string <uuid> ID der Organisation |
| page | number >= 1 Default: 1 Example: page=1 Seite, beginnend bei 1 |
| limit | number [ 1 .. 500 ] Default: 20 Example: limit=50 Anzahl pro Seite (max. 100) |
| eventId | string Example: eventId=550e8400-e29b-41d4-a716-446655440000 Filter nach Event-ID |
| status | string Enum: "open" "in_progress" "ready" "completed" "cancelled" Example: status=open Filter nach Bestellstatus |
| paymentStatus | string Enum: "unpaid" "partly_paid" "paid" "refunded" Example: paymentStatus=pending Filter nach Zahlungsstatus |
| source | string Enum: "pos" "online" "qr_order" Example: source=pos Filter nach Bestellquelle |
| fulfillmentType | string Enum: "table_service" "counter_pickup" Example: fulfillmentType=counter_pickup Filter nach Erfüllungstyp |
| dateFrom | string Example: dateFrom=2024-01-01T00:00:00.000Z Startdatum für Filterung |
| dateTo | string Example: dateTo=2024-12-31T23:59:59.000Z Enddatum für Filterung |
| includeItems | boolean Example: includeItems=true Bestellpositionen einschließen |
| q | string Example: q=Burger Suche: Bestell-/Tagesnummer, Tisch, Name oder Produkt |
| displayStatus | string Example: displayStatus=unpaid,refunded Status wie in der Kasse (kommagetrennt): in_kitchen, ready, completed, unpaid, cancelled, partly_refunded, refunded |
| paymentMethod | string Example: paymentMethod=cash,sumup Zahlart (kommagetrennt): cash, card, sumup, discount |
| deviceId | string Nur Bestellungen dieses Geräts |
Kassen und Displays der Organisation lesen. Koppeln, sperren und löschen geht nur in der App.
Kassen und Displays der Organisation mit Status, seitenweise (page, limit). Scope read; koppeln, sperren und löschen geht nur in der App.
| organizationId required | string <uuid> ID der Organisation |
| page | number >= 1 Default: 1 Example: page=1 Seite, beginnend bei 1 |
| limit | number [ 1 .. 500 ] Default: 20 Example: limit=20 Einträge je Seite (höchstens 500) |
Schlägt zu Produktnamen passende Icons aus @openeos/pos-icons vor: Stufe 1 ohne Modell (Namen und Suchbegriffe der Icons), Stufe 2 fragt bei unklaren Namen das Klassifikationsmodell. icon ist die Referenz pos-icon:<id>. Scope read; 404 AI_DISABLED ohne Anbieter, 403 ASSISTANT_DISABLED ohne Opt-in der Organisation.
| organizationId required | string <uuid> ID der Organisation |
| names required | Array of strings Produktnamen (1–100) |
{- "names": [
- "Currywurst mit Pommes",
- "Radler 0,5 l"
]
}API-Tokens der Organisation ausstellen und widerrufen — nur mit Anmeldung (JWT) als Administrator, nicht per Token.
Alle Tokens der Organisation, auch widerrufene und abgelaufene, neueste zuerst. Vom Geheimnis bleibt nur tokenPrefix sichtbar. Nur mit Anmeldung (JWT) als Administrator — nicht per Token.
| organizationId required | string <uuid> ID der Organisation |
Stellt einen Token mit Name, Scopes und optionalem Ablauf aus. Das Geheimnis (data.token, oeos_…) kommt genau einmal in dieser Antwort; gespeichert wird nur ein Hash. Höchstens 20 aktive Tokens je Organisation (409 API_TOKEN_LIMIT_REACHED). Nur mit Anmeldung als Administrator.
| organizationId required | string <uuid> ID der Organisation |
| name required | string <= 100 characters Wofür der Token gedacht ist — erscheint in der Übersicht |
| scopes required | Array of strings Items Enum: "read" "catalog:write" "events:write" "tables:write" "staff:write" "devices:write" "settings:write" Was der Token darf. Schreib-Scopes schließen |
| expiresAt | string ISO-8601. Ohne Angabe läuft der Token nicht ab |
{- "name": "Claude Desktop",
- "scopes": [
- "read",
- "catalog:write"
], - "expiresAt": "2027-01-01T00:00:00.000Z"
}Widerruft einen Token sofort; der Eintrag bleibt mit revokedAt in der Liste. Jeder Administrator der Organisation darf jeden Token der Organisation widerrufen. Nur mit Anmeldung.
| organizationId required | string <uuid> ID der Organisation |
| id required | string <uuid> ID des Tokens |