Simplefy Logo
Simplefy
KI-Speisekartenmanager für die Gastronomie
🚀 7 Tage kostenlos testen
Konto erstellen
In wenigen Sekunden startklar –
kostenlos & unverbindlich
5,0 ★★★★★ · 300+ Restaurants · Made in 🇩🇪
Mit Google fortfahren Mit Apple fortfahren
oder
✉️ Mit E-Mail-Adresse registrieren lädt…

Mit der Anmeldung stimmst du unseren AGB und Datenschutzbestimmungen zu.

OrderKitApiDocs

OrderKit-Schnittstelle — Doku für externe Systeme

Was ein externer MCP-Server an uns senden muss, damit Öffnungszeiten, Sondertage und Vorlaufzeiten im Shop-Ordering ankommen.

1. Grundlagen

Gilt für alle Endpunkte.

  • Basis-URL: https://ki-speisekarte.de/functions
  • Format: JSON, Content-Type: application/json. Schreiben immer per POST.
  • Ein Token = ein Betrieb. Es gibt keine Betriebs-ID im Body — der Betrieb wird ausschließlich über den Token bestimmt.
  • Token-Übergabe (eine Variante genügt): Header x-api-key: <TOKEN>, Query ?token=<TOKEN> oder Feld "token" im Body. Empfohlen: Header.
  • Voraussetzung: Der Betrieb muss die Anbindung in Simplefy freigeschaltet haben. Sonst: 403 mit code: "ORDERKIT_DISABLED".
  • Simplefy ist die führende Quelle. Der externe Dienst liest die komplette Konfiguration und schreibt nur gezielt einzelne Bereiche zurück.
  • Zeiten immer als "HH:MM" (24 h), Datum immer als "YYYY-MM-DD", jeweils in der Zeitzone des Shops (Feld timezone, i.d.R. Europe/Berlin).
  • Wochentage: Schlüssel "0"–"6", wobei 0 = Sonntag … 6 = Samstag.
  • CORS ist offen; OPTIONS wird beantwortet.

2. Pflicht-Ablauf: erst lesen, dann schreiben

Ohne diesen Ablauf entstehen Überschreibungen und Endlos-Schleifen.

  1. orderKitConfig aufrufen und die Antwort komplett übernehmen (kein Mergen mit altem eigenem Stand).
  2. Die gelesene config_version merken.
  3. Beim Schreiben diese config_version mitsenden.
  4. Kommt 409 mit code: "VERSION_CONFLICT", ist der eigene Stand veraltet: die im Fehler mitgelieferte config übernehmen und den Schreibvorgang mit der neuen Version wiederholen.

Wichtig: Alle Schreib-Endpunkte akzeptieren config_version optional — wird sie weggelassen, entfällt der Schutz gegen versehentliches Überschreiben. Bitte immer mitsenden.

3. Lesen — komplette Konfiguration

Der Einstiegspunkt für jeden Abgleich.

GEThttps://ki-speisekarte.de/functions/orderKitConfig?token=<TOKEN>

Liefert alles: Zeitzone, allgemeine Öffnungszeiten, Liefer-/Abholzeiten, Vorlaufzeiten (global und je Kategorie), Sondertage sowie die Tagessperre. Alternativ als POST mit { "token": "..." } im Body.

Antwort

{
  "config_version": "2026-08-18T09:41:02.113Z",
  "restaurant": { "id": "abc123", "name": "Gasthaus Beispiel", "business_type": "restaurant" },
  "timezone": "Europe/Berlin",
  "accepting_orders": true,
  "channels": { "delivery_offered": true, "pickup_offered": false },
  "blocked_today": { "delivery": false, "pickup": false },
  "business_hours": { "0": [], "1": [{ "from": "11:00", "to": "22:00" }] },
  "delivery_hours": { "1": [{ "from": "17:00", "to": "21:00" }] },
  "pickup_hours":   { "1": [{ "from": "11:30", "to": "21:00" }] },
  "max_days_ahead": 3,
  "default_order_type": "delivery",
  "lead_times": {
    "delivery_lead_time_days": 0,
    "delivery_lead_time_hours": 0,
    "delivery_lead_time_minutes": 45,
    "delivery_earliest_time": "",
    "delivery_lead_time_mode": "calendar_days",
    "pickup_lead_time_days": 0,
    "pickup_lead_time_hours": 0,
    "pickup_lead_time_minutes": 30,
    "pickup_earliest_time": "",
    "pickup_lead_time_mode": "open_days_only"
  },
  "categories": [
    { "id": "cat_1", "name": "Partyservice",
      "delivery_lead_time_days": 2, "delivery_lead_time_hours": 0,
      "delivery_lead_time_minutes": 0, "delivery_earliest_time": "10:00",
      "pickup_lead_time_days": 2, "pickup_lead_time_hours": 0,
      "pickup_lead_time_minutes": 0, "pickup_earliest_time": "10:00" }
  ],
  "kartenarten": [
    { "id": "card_1", "name": "Partyplatte",
      "category_ids": ["cat_1", "cat_7"] }
  ],
  "special_days": [ /* alle Sondertage */ ],
  "closures": [ /* nur is_closed = true  */ ],
  "lead_time_exceptions": [ /* nur is_closed = false */ ]
}

categories enthält nur aktive Kategorien. Kategorien können über diese Schnittstelle NICHT angelegt oder gelöscht werden — nur deren Vorlaufzeiten geändert. channels sagt, welche Bestellarten der Betrieb überhaupt anbietet: steht delivery_offered oder pickup_offered auf false, darf für diese Bestellart NICHTS angeboten werden — Bestellungen darüber werden mit 403 und code: CHANNEL_OFF abgelehnt. channels ist nur lesbar und wird ausschließlich in Simplefy umgestellt. kartenarten listet die aktiven Kartenarten (z.B. 'Partyplatte') mit den Kategorien, die über ihre Artikel dazugehören — abgeleitet aus der Kartenzuordnung der Artikel (Hauptkategorie; die Zweitkategorie zählt bewusst nicht mit, da nur die Hauptkategorie die Vorlaufzeit- und Sondertag-Logik steuert). Damit lässt sich beim Schreiben eines Sondertags die passende category_ids-Liste füllen. Nur lesbar.

4. Schreiben — Sonderöffnungszeiten / Schließtage

Feiertage, Betriebsurlaub, abweichende Zeitfenster, abweichende Vorlaufzeiten.

POSThttps://ki-speisekarte.de/functions/orderKitSetSpecialDays

Legt Sondertage an, ändert sie oder löscht sie. Eintrag MIT id = ändern, OHNE id = neu anlegen. Es werden nur die übergebenen Einträge angefasst — die Liste ist kein Vollersatz.

Request Body

{
  "token": "<TOKEN>",
  "config_version": "2026-08-18T09:41:02.113Z",

  "special_days": [
    {
      "date": "2026-12-24",
      "date_to": "",
      "label": "Heiligabend",
      "applies_to": "both",
      "category_ids": [],
      "is_closed": false,
      "windows": [{ "from": "09:00", "to": "13:00" }],
      "lead_time_days": 2,
      "lead_time_hours": 0
    },
    {
      "id": "sd_9f2",
      "date": "2026-12-27",
      "date_to": "2027-01-04",
      "label": "Betriebsurlaub",
      "applies_to": "both",
      "is_closed": true,
      "windows": []
    }
  ],

  "delete_ids": ["sd_alt1"]
}

Antwort

{
  "success": true,
  "created": 1, "updated": 1, "deleted": 1,
  "config_version": "2026-08-18T11:02:44.907Z",
  "special_days": [ ... ], "closures": [ ... ], "lead_time_exceptions": [ ... ]
}

Feldregeln: date = Pflicht (YYYY-MM-DD). date_to leer = einzelner Tag, sonst Zeitraum und darf nicht vor date liegen. applies_to = both | delivery | pickup (Standard both). category_ids leer = gilt für alle Kategorien, sonst müssen es bestehende Kategorie-IDs aus orderKitConfig sein. is_closed true = an diesen Tagen keine Bestellung möglich. windows = abweichende Zeitfenster (leer = normale Wochentagszeiten gelten), to muss größer als from sein. lead_time_days / lead_time_hours = abweichende Vorlaufzeit für diese Tage (0 = keine Abweichung). Statt special_days können auch die getrennten Listen closures (immer is_closed=true) und lead_time_exceptions (immer is_closed=false) gesendet werden.

Es wird zuerst alles geprüft und erst dann geschrieben — bei einem Fehler (400) bleibt der Bestand unverändert. Unbekannte IDs melden sich als code: "UNKNOWN_SPECIAL_DAY", unbekannte Kategorien als Klartext-Fehler.

5. Schreiben — Liefer- und Abholzeiten

Wochenplan, Vorausbestell-Fenster, Standard-Bestellart.

POSThttps://ki-speisekarte.de/functions/orderKitSetHours

Ersetzt die übergebenen Wochenpläne vollständig. Nur mitgesendete Felder werden geändert.

Request Body

{
  "token": "<TOKEN>",
  "config_version": "2026-08-18T09:41:02.113Z",
  "business_hours": { "1": [{ "from": "11:00", "to": "22:00" }], "0": [] },
  "delivery_hours": { "1": [{ "from": "17:00", "to": "21:00" }] },
  "pickup_hours":   { "1": [{ "from": "11:30", "to": "21:00" }] },
  "max_days_ahead": 3,
  "default_order_type": "delivery"
}

Antwort

{ "success": true, "config_version": "…", "config": { /* komplette neue Konfiguration */ } }

Ein Wochentag mit leerem Array = geschlossen. Ein NICHT übergebener Wochentag gilt ebenfalls als geschlossen — deshalb immer den vollständigen Wochenplan senden. max_days_ahead: 0–365. default_order_type: delivery | pickup.

6. Schreiben — Vorlaufzeiten

Global für den Shop und je Kategorie.

POSThttps://ki-speisekarte.de/functions/orderKitSetLeadTimes

Allgemeine Vorlaufzeit des Shops. Nur übergebene Felder werden geändert.

Request Body

{
  "token": "<TOKEN>",
  "config_version": "…",
  "delivery_lead_time_days": 0,
  "delivery_lead_time_hours": 1,
  "delivery_lead_time_minutes": 30,
  "delivery_earliest_time": "",
  "delivery_lead_time_mode": "calendar_days",
  "pickup_lead_time_days": 2,
  "pickup_lead_time_hours": 0,
  "pickup_lead_time_minutes": 30,
  "pickup_earliest_time": "11:30",
  "pickup_lead_time_mode": "open_days_only"
}

Antwort

{ "success": true, "config_version": "…", "lead_times": { ... } }

*_lead_time_mode ist nur hier (am Betrieb) erlaubt, NICHT je Kategorie. Zulässig sind ausschließlich calendar_days und open_days_only — jeder andere Wert führt zu 400.

POSThttps://ki-speisekarte.de/functions/orderKitSetCategoryLeadTimes

Vorlaufzeiten einzelner Kategorien (z.B. Partyservice ab 2 Tagen). Nur bestehende Kategorie-IDs aus orderKitConfig.

Request Body

{
  "token": "<TOKEN>",
  "config_version": "…",
  "categories": [
    { "id": "cat_1",
      "delivery_lead_time_days": 2, "delivery_earliest_time": "10:00",
      "pickup_lead_time_days": 2,   "pickup_earliest_time": "10:00" }
  ]
}

Antwort

{ "success": true, "updated": 1, "config_version": "…", "categories": [ ... ] }

Unbekannte IDs → 400 mit code: UNKNOWN_CATEGORY.

Bedeutung der Felder

*_lead_time_days     = Vorlauf in KALENDERTAGEN (1 = frühestens morgen, unabhängig von der Uhrzeit)
*_lead_time_hours    = zusätzlicher Vorlauf in Stunden, rollend ab Bestellzeitpunkt
*_lead_time_minutes  = zusätzlicher Vorlauf in Minuten, rollend ab Bestellzeitpunkt
*_earliest_time      = früheste Uhrzeit am Termintag, "HH:MM" oder "" (keine Grenze)
*_lead_time_mode     = Zählweise der Vorlauf-TAGE (nur am Betrieb, nicht je Kategorie):
                       calendar_days   = jeder Kalendertag zählt mit (Standard)
                       open_days_only  = nur Tage mit Zeitfenstern und ohne Schließtag
                                         zählen mit ("nur Werktage")
Alle Zahlen: ganzzahlig und >= 0.

Reihenfolge der Berechnung des frühesten Termins

1. Vorlauf-TAGE anwenden — Zählweise gemäß *_lead_time_mode.
   Bei open_days_only werden geschlossene Tage (kein Zeitfenster ODER Schließtag
   aus closures) übersprungen und zählen nicht als Vorlauftag.
2. Vorlauf STUNDEN + MINUTEN rollend ab Bestellzeitpunkt addieren
   (davon ist *_lead_time_mode NICHT betroffen).
3. Kategorie-Vorlaufzeiten: pro Artikel gilt die HAUPTKATEGORIE; bei gemischtem
   Warenkorb gewinnt die längste Vorlaufzeit. Zweitkategorien zählen nicht.
4. Abweichende Vorlaufzeiten aus lead_time_exceptions für den Zieltag anwenden.
5. *_earliest_time als untere Grenze der Uhrzeit am Termintag anwenden.
6. Termin muss in ein Zeitfenster (delivery_hours / pickup_hours bzw. windows
   eines Sondertags) fallen und darf max_days_ahead nicht überschreiten.

6b. Bestellarten — „nur Lieferung“ / „nur Abholung“

Nur lesbar. Wird ausschließlich in Simplefy umgestellt.

Feld in orderKitConfig

"channels": { "delivery_offered": true, "pickup_offered": false }
  • Steht ein Kanal auf false, darf diese Bestellart dem Kunden gar nicht angeboten werden — keine Zeiten, keine Termine, keine Bestellung.
  • Wird trotzdem eine Bestellung dieser Art gesendet, wird sie abgelehnt: 403 mit code: "CHANNEL_OFF".
  • Mindestens einer der beiden Kanäle ist immer aktiv.
  • Über die Schnittstelle nicht schreibbar — es gibt bewusst keinen Endpunkt dafür.
  • Zusätzlich beachten: accepting_orders: false stoppt alle Bestellungen, blocked_today nur den heutigen Tag (je Kanal).

7. Schreiben — Tagessperre („heute zu“)

Für Krankheit, Küche voll, spontane Pause.

POSThttps://ki-speisekarte.de/functions/orderKitBlockToday

Sperrt den heutigen Tag. Gilt nur für heute (Zeitzone des Shops) und endet automatisch um Mitternacht — es muss nichts zurückgesetzt werden.

Request Body

{ "token": "<TOKEN>", "scope": "all", "blocked": true }

Antwort

{ "success": true, "date": "2026-08-18", "blocked_today": { "delivery": true, "pickup": true } }

scope: all | delivery | pickup. blocked: false hebt die Sperre auf. Dieser Endpunkt braucht keine config_version.

8. Antworten & Fehlerbehandlung

Was der externe Dienst auswerten muss.

Statuscodes

200  Erfolg — Antwort enthält success: true und die neue config_version
400  Ungültige Daten — "error" enthält den Klartext-Grund, ggf. "code"
     (UNKNOWN_SPECIAL_DAY, UNKNOWN_CATEGORY). Es wurde NICHTS geschrieben.
401  Token fehlt
403  Token ungültig ODER Anbindung deaktiviert (code: ORDERKIT_DISABLED)
     ODER Bestellart nicht angeboten (code: CHANNEL_OFF, siehe channels)
405  Falsche Methode (Schreiben nur per POST)
409  code: VERSION_CONFLICT — eigener Stand veraltet, "config" übernehmen und erneut senden
500  Serverfehler — später erneut versuchen
  • Nach jedem erfolgreichen Schreiben die zurückgegebene config_version als neuen eigenen Stand speichern.
  • Bei 409 nicht blind erneut senden, sondern zuerst die mitgelieferte config übernehmen.
  • Bei 400 nicht wiederholen — die Daten sind fehlerhaft; die Meldung in error ist für Menschen lesbar.
  • Bei 500 / Netzfehler mit Abstand erneut versuchen (z.B. 5 s, 30 s, 2 min).
  • Keine Schreib-Schleifen: nur schreiben, wenn sich fachlich etwas geändert hat — nicht periodisch denselben Stand zurückschreiben.

9. Kurz-Checkliste für die Umsetzung

  • Token pro Betrieb sicher hinterlegt (nicht im Client, nur serverseitig).
  • orderKitConfig gelesen, config_version gespeichert.
  • channels ausgewertet: nicht angebotene Bestellarten werden dem Kunden gar nicht erst angeboten.
  • *_lead_time_mode ausgewertet: bei open_days_only werden geschlossene Tage bei den Vorlauftagen übersprungen.
  • accepting_orders und blocked_today vor jedem Bestellangebot geprüft.
  • Beim Schreiben: nur den betroffenen Endpunkt, mit config_version.
  • Wochenpläne immer vollständig senden, Sondertage nur als Delta (mit id zum Ändern, delete_ids zum Löschen).
  • 409-Behandlung implementiert; 400-Meldungen werden protokolliert und nicht wiederholt.