Authentifizierung
Alle Endpoints außer /v1/health erfordern HTTP Basic Auth über HTTPS. Die Zugangsdaten werden von tech2solutions vergeben — Anfragen dazu bitte an info@book2eat.eu. Jeder API-User ist für einen oder mehrere Standorte freigeschaltet — Requests für nicht freigeschaltete Standorte werden mit 403 abgelehnt.
curl -u benutzername:passwort https://supplier-api.book2eat.eu/v1/locations
Damit lässt sich der eigene Zugang testen, ohne bereits eine echte Speiseplan-ID zu kennen — die Antwort zeigt die freigeschalteten Standorte (siehe unten).
Datenformat
Alle Request- und Response-Bodies sind JSON (application/json; charset=utf-8). Datumsangaben: YYYY-MM-DD, Zeitstempel: YYYY-MM-DD HH:MM:SS (lokale Zeit, Europa/Wien).
orderDeadline kann pro menuItem mitgegeben werden und übersteuert dann den Wert auf Speiseplan-Ebene. cancelDeadline ist optional — fehlt sie, wird automatisch orderDeadline + 7 Tage gesetzt. minOrderQuantity wird entgegengenommen, aber derzeit nicht ausgewertet. Sobald bei einem menuItem sowohl orderDeadline als auch cancelDeadline verstrichen sind, gilt es als final (final: true) und kann über die API nicht mehr geändert oder gelöscht werden (409 ITEM_LOCKED) — die Bestellzahl steht dann endgültig fest.
Preis:
price ist auf jedem menuItem optional. Fehlt es, wird der Preis wie gehabt aus dem in book2eat gepflegten Menütyp übernommen; wird es mitgeschickt, überschreibt es diesen Preis für den jeweiligen Eintrag. Umsatzsteuer (vat) kommt immer aus book2eat und kann nicht per API gesetzt werden.
Freigeschaltete Standorte abrufen
Listet die Standorte, für die der authentifizierte API-User freigeschaltet ist — damit lässt sich vorab prüfen, ob die eigene locationClientUid korrekt mit book2eat verknüpft ist, bevor ein Speiseplan gesendet wird. linked: false bedeutet, dass der Standort zwar freigeschaltet, aber noch keiner locationClientUid zugeordnet ist — in dem Fall bitte tech2solutions kontaktieren. active spiegelt das bestehende Aktiv-Flag der Einrichtung in book2eat: ist eine Einrichtung hier false, schlägt POST/PUT mit 422 UNKNOWN_LOCATION fehl, auch wenn linked: true ist — book2eat findet die deaktivierte Einrichtung über locationClientUid dann nicht mehr.
[
{
"canteen_ID": 271,
"canteenName": "Kindergarten Obersulz",
"locationClientUid": "130669",
"locationId": "642",
"active": true,
"linked": true
}
]
Menülinien-Mapping abrufen
Listet die für diesen Standort in book2eat gepflegten Menülinien-Mappings (menuLines[].id → book2eat-Menütyp inkl. aktuellem Preis/USt.) — damit lässt sich vorab prüfen, ob eine ADAM-Menülinie korrekt verknüpft ist, bevor ein Speiseplan gesendet wird. Fehlt eine extLineId hier, liefert POST/PUT für genau diese Linie später 422 UNKNOWN_MENU_LINE — in dem Fall bitte tech2solutions kontaktieren, damit die Zuordnung ergänzt wird.
[
{
"extLineId": "4056",
"lineName": "Tagessuppe",
"typ_ID": 1,
"name": "Suppe",
"standard_price": "3.50",
"vat": "10.00"
},
{
"extLineId": "4057",
"lineName": "Hauptspeise",
"typ_ID": 2,
"name": "Hauptgericht",
"standard_price": "8.90",
"vat": "10.00"
}
]
Speiseplan anlegen
Legt einen Wochenspeiseplan an. Die Speiseplan-ID (id) sowie alle menuItem-IDs sind die IDs des sendenden Systems und bleiben in allen weiteren Requests die Referenz. Da es sich um einen neuen Speiseplan handelt, existieren noch keine Bestellungen dazu — es wird keine Benachrichtigung verschickt.
{
"id": "717304",
"locationId": "642",
"locationName": "Kindergarten Obersulz",
"locationClientUid": "130669",
"week": "17",
"year": "2026",
"startDate": "2026-04-20",
"endDate": "2026-04-26",
"orderDeadline": "2026-04-06 23:59:59",
"menuLines": [
{
"id": "4056",
"name": "Tagessuppe",
"minOrderQuantity": "0",
"menuItems": [
{
"id": "15323144",
"name": "Klare Hühnersuppe mit Reibteig",
"date": "2026-04-20",
"isExtraMenu": false,
"allergens": ["A", "C"],
"additives": [],
"attributes": ["enthält Gluten"],
"nutritionValues": { "kJ": 203, "kcal": 49 }
}
]
}
]
}
{ "id": "717304", "status": "created", "itemsImported": 10 }
Existiert die Speiseplan-ID bereits, antwortet die API mit 409 Conflict — Änderungen laufen über PUT.
Speiseplan abrufen
Liefert den aktuell in book2eat hinterlegten Stand des Speiseplans {id} — Name, Datum, Allergene und Deadlines je menuItem, so wie sie aktuell gespeichert sind (nicht zwingend identisch mit dem ursprünglich gesendeten Payload, falls es zwischenzeitlich Änderungen gab). additives, attributes und nutritionValues werden von book2eat nicht gespeichert und sind daher hier nicht enthalten.
{
"id": "717304",
"locationClientUid": "130669",
"week": 17,
"year": 2026,
"startDate": "2026-04-20",
"endDate": "2026-04-26",
"menuLines": [
{
"id": "4056",
"name": "Tagessuppe",
"menuItems": [
{
"id": 15323144,
"name": "Klare Hühnersuppe mit Reibteig",
"date": "2026-04-20",
"allergens": ["A", "C"],
"orderDeadline": "2026-04-06 23:59:59",
"cancelDeadline": "2026-04-13 23:59:59",
"orderDeadlinePassed": true,
"cancelDeadlinePassed": true,
"final": true
}
]
}
]
}
Bestellzahlen abrufen
Liefert die Bestellzahlen je menuItem für den Speiseplan {id}. Einträge ohne Bestellungen werden mit quantity: 0 ausgegeben. final zeigt an, ob die Zahl schon endgültig ist — also sowohl orderDeadline als auch cancelDeadline bereits verstrichen sind und sich die Bestellzahl nicht mehr ändern kann.
[
{
"id": 15323144,
"date": "2026-04-20",
"quantity": 15,
"orderDeadline": "2026-04-06 23:59:59",
"cancelDeadline": "2026-04-13 23:59:59",
"orderDeadlinePassed": true,
"cancelDeadlinePassed": true,
"final": true
}
]
Bestellzahlen über Woche/Zeitraum abrufen
Liefert Bestellzahlen kantinenweit über mehrere Speisepläne hinweg — wahlweise für eine ganze Woche oder einen freien Datumsbereich, ohne dass die einzelne Speiseplan-ID bekannt sein muss. Erfordert locationClientUid sowie entweder week+year oder from+to (YYYY-MM-DD) als Query-Parameter. planId im Ergebnis verweist auf die zugehörige Speiseplan-ID.
week+year anhand der tatsächlichen Kalenderwoche geprüft). Außerhalb dieser Grenzen antwortet die API mit 400 VALIDATION_ERROR.
curl -u benutzername:passwort \ "https://supplier-api.book2eat.eu/v1/menus/quantities?locationClientUid=130669&week=17&year=2026" curl -u benutzername:passwort \ "https://supplier-api.book2eat.eu/v1/menus/quantities?locationClientUid=130669&from=2026-04-20&to=2026-04-26"
[
{
"id": 15323144,
"planId": "717304",
"date": "2026-04-20",
"quantity": 15,
"orderDeadline": "2026-04-06 23:59:59",
"cancelDeadline": "2026-04-13 23:59:59",
"orderDeadlinePassed": true,
"cancelDeadlinePassed": true,
"final": true
}
]
Speiseplan komplett ersetzen
Ersetzt den Speiseplan durch den mitgeschickten Body (gleiche Struktur wie POST). Neue Einträge werden angelegt, bestehende (gleiche menuItem-ID) aktualisiert. Einträge, die im Body fehlen, werden entfernt — vorhandene Bestellungen dazu werden storniert. menuItems, die bereits final sind (siehe oben), bleiben unangetastet — weder Änderung noch Entfernung — und zählen in der Antwort als protected. Der restliche Speiseplan wird ganz normal verarbeitet.
menuItems werden Besteller mit einer aktiven Bestellung (nicht bereits stornierte) automatisch von book2eat per E-Mail benachrichtigt. Für neu angelegte Einträge sowie für protected Einträge gibt es keine Benachrichtigung.
{ "id": "717304", "status": "replaced", "created": 1, "updated": 8, "removed": 1, "protected": 0, "cancelledOrders": 12 }
Einzelnen Eintrag ändern
Detailänderung eines einzelnen Speiseplaneintrags — z. B. Komponententausch oder geändertes Bestellende. Erlaubte Felder: name, date, allergens, orderDeadline, cancelDeadline, price (optional). Nur mitgeschickte Felder werden geändert. Besteller mit einer aktiven Bestellung für diesen Eintrag werden automatisch von book2eat per E-Mail benachrichtigt. Ist das Item bereits final, antwortet die API mit 409 ITEM_LOCKED.
{
"name": "Kürbiscremesuppe mit Kernöl",
"allergens": ["G"],
"orderDeadline": "2026-04-08 23:59:59"
}
{ "id": "15323144", "status": "updated" }
Löschen
Löscht den kompletten Speiseplan. Alle offenen Bestellungen werden storniert. Bereits finale menuItems (siehe oben) werden dabei übersprungen statt gelöscht/storniert und zählen in der Antwort als protected.
menuItem werden automatisch von book2eat per E-Mail benachrichtigt. Für protected Einträge gibt es keine Benachrichtigung.
{ "id": "717304", "deleted": true, "items": 9, "protected": 1, "cancelledOrders": 33 }
Löscht einen einzelnen Speiseplaneintrag inklusive Storno der zugehörigen Bestellungen. Besteller mit einer aktiven Bestellung für diesen Eintrag werden automatisch von book2eat per E-Mail benachrichtigt. Ist das Item bereits final, antwortet die API mit 409 ITEM_LOCKED.
{ "id": "15323144", "deleted": true, "cancelledOrders": 4 }
Fehlercodes
| Status | Code | Bedeutung |
|---|---|---|
| 400 | VALIDATION_ERROR / INVALID_JSON | Body entspricht nicht dem Schema bzw. ist kein gültiges JSON. details enthält die Feldfehler. |
| 401 | UNAUTHORIZED | Fehlende oder falsche Zugangsdaten. |
| 403 | CANTEEN_NOT_ALLOWED | Der API-User ist für diesen Standort nicht freigeschaltet. |
| 404 | MENU_NOT_FOUND / ITEM_NOT_FOUND | Speiseplan bzw. Eintrag existiert nicht. |
| 409 | MENU_EXISTS | Speiseplan-ID bereits vorhanden — PUT verwenden. |
| 409 | ITEM_ID_EXISTS | Die menuItem-ID wird bereits in einem anderen Speiseplan verwendet — menuItem-IDs müssen global eindeutig sein, nicht nur innerhalb eines Speiseplans. |
| 409 | ITEM_LOCKED | order- und cancelDeadline des menuItems sind bereits verstrichen — keine Änderung/Löschung mehr möglich. |
| 422 | UNKNOWN_LOCATION, DATE_OUT_OF_RANGE, DUPLICATE_ITEM_ID | Fachlich ungültig — Meldung beschreibt das Problem. |
| 429 | — | Rate-Limit erreicht. Kurz warten und erneut senden. |
{
"error": {
"code": "UNKNOWN_LOCATION",
"message": "Der Standort mit locationClientUid 130699 ist in book2eat nicht angelegt.",
"details": null
}
}
Health-Check
Ohne Authentifizierung erreichbar, für Monitoring.
{ "status": "ok", "db": "ok", "time": "2026-07-14T09:00:00.000Z" }