{
  "info": {
    "_postman_id": "b2e5a1e0-6f2d-4e9a-8c3a-supplier-api-live",
    "name": "book2eat Supplier API (Live)",
    "description": "Postman-Collection für die **produktive** book2eat Supplier API unter https://supplier-api.book2eat.eu/v1 — Anfragen hier verändern echte Daten (Speisepläne, Bestellungen). Vor der Nutzung unter dem Reiter \"Variables\" ausfüllen:\n\n- `username`/`password` — von tech2solutions vergebene Zugangsdaten (Anfrage an info@book2eat.eu)\n- `locationClientUid` — über \"GET Freigeschaltete Standorte\" abrufen\n- `menuId`/`itemId` — eigene externe IDs (aus dem sendenden System)\n\nDie Request-Bodies enthalten Platzhalter (GROSSBUCHSTABEN, z. B. `YYYY-MM-DD`) — vor dem Senden durch echte Werte ersetzen. `PUT`/`DELETE`-Requests wirken sich auf echte Speisepläne und ggf. bereits platzierte Bestellungen aus (Besteller werden per Mail benachrichtigt) — mit Bedacht verwenden.\n\nVollständige Dokumentation: https://supplier-api.book2eat.eu/docs/",
    "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
  },
  "auth": {
    "type": "basic",
    "basic": [
      { "key": "username", "value": "{{username}}", "type": "string" },
      { "key": "password", "value": "{{password}}", "type": "string" }
    ]
  },
  "variable": [
    { "key": "baseUrl", "value": "https://supplier-api.book2eat.eu/v1", "type": "string" },
    { "key": "username", "value": "", "type": "string" },
    { "key": "password", "value": "", "type": "string" },
    { "key": "locationClientUid", "value": "", "type": "string" },
    { "key": "menuId", "value": "", "type": "string" },
    { "key": "itemId", "value": "", "type": "string" }
  ],
  "item": [
    {
      "name": "Health",
      "item": [
        {
          "name": "GET Health-Check",
          "request": {
            "method": "GET",
            "header": [],
            "auth": { "type": "noauth" },
            "url": {
              "raw": "{{baseUrl}}/health",
              "host": ["{{baseUrl}}"],
              "path": ["health"]
            },
            "description": "Öffentlich, kein Auth nötig. Prüft zusätzlich die DB-Verbindung (503 bei Problemen)."
          },
          "response": []
        }
      ]
    },
    {
      "name": "Locations",
      "item": [
        {
          "name": "GET Freigeschaltete Standorte",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{baseUrl}}/locations",
              "host": ["{{baseUrl}}"],
              "path": ["locations"]
            },
            "description": "Listet die für den API-User freigeschalteten Standorte inkl. locationClientUid/locationId. Damit einen gültigen Wert für die Collection-Variable {{locationClientUid}} ermitteln, bevor die anderen Requests genutzt werden."
          },
          "response": []
        },
        {
          "name": "GET Menülinien-Mapping",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{baseUrl}}/menus/lines?locationClientUid={{locationClientUid}}",
              "host": ["{{baseUrl}}"],
              "path": ["menus", "lines"],
              "query": [{ "key": "locationClientUid", "value": "{{locationClientUid}}" }]
            },
            "description": "Listet die für {{locationClientUid}} gepflegten Menülinien-Mappings inkl. aktuellem Preis/USt. Damit vorab prüfen, ob eine menuLines[].id aus dem eigenen System korrekt verknüpft ist — fehlt sie hier, liefert POST/PUT für diese Linie 422 UNKNOWN_MENU_LINE."
          },
          "response": []
        }
      ]
    },
    {
      "name": "Menus",
      "item": [
        {
          "name": "POST Speiseplan anlegen",
          "request": {
            "method": "POST",
            "header": [{ "key": "Content-Type", "value": "application/json" }],
            "body": {
              "mode": "raw",
              "options": { "raw": { "language": "json" } },
              "raw": "{\n  \"id\": \"{{menuId}}\",\n  \"locationId\": \"EXTERNE-LOCATION-ID\",\n  \"locationName\": \"Name der Einrichtung\",\n  \"locationClientUid\": \"{{locationClientUid}}\",\n  \"week\": \"WOCHENNUMMER\",\n  \"year\": \"JAHR\",\n  \"startDate\": \"YYYY-MM-DD\",\n  \"endDate\": \"YYYY-MM-DD\",\n  \"orderDeadline\": \"YYYY-MM-DD HH:MM:SS\",\n  \"menuLines\": [\n    {\n      \"id\": \"EXTERNE-MENULINE-ID-1\",\n      \"name\": \"Tagessuppe\",\n      \"minOrderQuantity\": \"0\",\n      \"menuItems\": [\n        {\n          \"id\": \"{{itemId}}\",\n          \"name\": \"Beispiel-Gericht\",\n          \"date\": \"YYYY-MM-DD\",\n          \"isExtraMenu\": false,\n          \"allergens\": [\"A\", \"C\"],\n          \"additives\": [],\n          \"attributes\": [\"enthält Gluten\"],\n          \"nutritionValues\": { \"kJ\": 243, \"kcal\": 58 }\n        }\n      ]\n    },\n    {\n      \"id\": \"EXTERNE-MENULINE-ID-2\",\n      \"name\": \"Hauptspeise\",\n      \"minOrderQuantity\": \"0\",\n      \"menuItems\": [\n        {\n          \"id\": \"EXTERNE-MENUITEM-ID-2\",\n          \"name\": \"Beispiel-Hauptgericht\",\n          \"date\": \"YYYY-MM-DD\",\n          \"isExtraMenu\": false,\n          \"allergens\": [\"A\", \"D\", \"G\"],\n          \"additives\": [],\n          \"attributes\": [\"enthält Laktose\"],\n          \"nutritionValues\": { \"kJ\": 2607, \"kcal\": 624 }\n        }\n      ]\n    }\n  ]\n}"
            },
            "url": {
              "raw": "{{baseUrl}}/menus",
              "host": ["{{baseUrl}}"],
              "path": ["menus"]
            },
            "description": "Legt einen neuen Speiseplan an. ACHTUNG: erzeugt einen echten Speiseplan in book2eat. Alle GROSSGESCHRIEBENEN Platzhalter im Body vor dem Senden durch echte Werte ersetzen — insbesondere menuItem-IDs müssen global eindeutig sein (über alle Speisepläne hinweg, nicht nur innerhalb dieses Plans), sonst 409 ITEM_ID_EXISTS. minOrderQuantity wird immer ignoriert; price ist optional. Da es noch keine Bestellungen zu diesem Plan gibt, wird keine Benachrichtigung verschickt.\n\nErwartet: 201 mit `{ id, status: 'created', itemsImported }`. Erneutes Ausführen mit derselben id → 409 MENU_EXISTS (Änderungen laufen über PUT)."
          },
          "response": []
        },
        {
          "name": "GET Speiseplan abrufen",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{baseUrl}}/menus/{{menuId}}",
              "host": ["{{baseUrl}}"],
              "path": ["menus", "{{menuId}}"]
            },
            "description": "Liest den aktuell in book2eat gespeicherten Stand des Speiseplans {{menuId}} zurück. 404 falls menuId nicht existiert, 403 falls der Standort nicht freigeschaltet ist."
          },
          "response": []
        },
        {
          "name": "PUT Speiseplan komplett ersetzen",
          "request": {
            "method": "PUT",
            "header": [{ "key": "Content-Type", "value": "application/json" }],
            "body": {
              "mode": "raw",
              "options": { "raw": { "language": "json" } },
              "raw": "{\n  \"locationId\": \"EXTERNE-LOCATION-ID\",\n  \"locationName\": \"Name der Einrichtung\",\n  \"locationClientUid\": \"{{locationClientUid}}\",\n  \"week\": \"WOCHENNUMMER\",\n  \"year\": \"JAHR\",\n  \"startDate\": \"YYYY-MM-DD\",\n  \"endDate\": \"YYYY-MM-DD\",\n  \"orderDeadline\": \"YYYY-MM-DD HH:MM:SS\",\n  \"menuLines\": [\n    {\n      \"id\": \"EXTERNE-MENULINE-ID-1\",\n      \"name\": \"Tagessuppe\",\n      \"minOrderQuantity\": \"0\",\n      \"menuItems\": [\n        {\n          \"id\": \"{{itemId}}\",\n          \"name\": \"Beispiel-Gericht (aktualisiert)\",\n          \"date\": \"YYYY-MM-DD\",\n          \"isExtraMenu\": false,\n          \"allergens\": [\"A\", \"C\"],\n          \"additives\": [],\n          \"attributes\": [\"enthält Gluten\"],\n          \"nutritionValues\": { \"kJ\": 243, \"kcal\": 58 }\n        }\n      ]\n    }\n  ]\n}"
            },
            "url": {
              "raw": "{{baseUrl}}/menus/{{menuId}}",
              "host": ["{{baseUrl}}"],
              "path": ["menus", "{{menuId}}"]
            },
            "description": "ACHTUNG: ersetzt den kompletten Speiseplan {{menuId}} — Items, die im Payload fehlen, werden storniert (aktive Bestellungen werden gecancelt). Besteller mit aktiver Bestellung werden sowohl für aktualisierte als auch für entfernte Items per Mail benachrichtigt, nicht aber für neu angelegte. id kommt aus der URL, nicht aus dem Body.\n\nErwartet: 200 mit `{ id, status: 'replaced', created, updated, removed, protected, protectedItems, cancelledOrders }`."
          },
          "response": []
        }
      ]
    },
    {
      "name": "Menu Items",
      "item": [
        {
          "name": "PUT Menüpunkt ändern",
          "request": {
            "method": "PUT",
            "header": [{ "key": "Content-Type", "value": "application/json" }],
            "body": {
              "mode": "raw",
              "options": { "raw": { "language": "json" } },
              "raw": "{\n  \"name\": \"Neuer Name\",\n  \"orderDeadline\": \"YYYY-MM-DD HH:MM:SS\"\n}"
            },
            "url": {
              "raw": "{{baseUrl}}/menus/{{menuId}}/items/{{itemId}}",
              "host": ["{{baseUrl}}"],
              "path": ["menus", "{{menuId}}", "items", "{{itemId}}"]
            },
            "description": "ACHTUNG: ändert einen echten Speiseplaneintrag. Erlaubte Felder (alle optional, nur mitgeschickte werden geändert): name, date, allergens, orderDeadline, cancelDeadline, price. Besteller mit aktiver Bestellung werden per Mail benachrichtigt. 409 ITEM_LOCKED, wenn order-/cancelDeadline bereits verstrichen sind."
          },
          "response": []
        },
        {
          "name": "DELETE Menüpunkt löschen",
          "request": {
            "method": "DELETE",
            "header": [],
            "url": {
              "raw": "{{baseUrl}}/menus/{{menuId}}/items/{{itemId}}",
              "host": ["{{baseUrl}}"],
              "path": ["menus", "{{menuId}}", "items", "{{itemId}}"]
            },
            "description": "ACHTUNG: löscht einen echten Speiseplaneintrag unwiderruflich und storniert aktive Bestellungen (Besteller werden per Mail benachrichtigt)."
          },
          "response": []
        }
      ]
    },
    {
      "name": "Bestellzahlen",
      "item": [
        {
          "name": "GET Bestellzahlen für Speiseplan",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{baseUrl}}/menus/{{menuId}}/quantities",
              "host": ["{{baseUrl}}"],
              "path": ["menus", "{{menuId}}", "quantities"]
            },
            "description": "Bestellzahlen je menuItem eines einzelnen Speiseplans."
          },
          "response": []
        },
        {
          "name": "GET Bestellzahlen nach Woche",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{baseUrl}}/menus/quantities?locationClientUid={{locationClientUid}}&week=WOCHENNUMMER&year=JAHR",
              "host": ["{{baseUrl}}"],
              "path": ["menus", "quantities"],
              "query": [
                { "key": "locationClientUid", "value": "{{locationClientUid}}" },
                { "key": "week", "value": "WOCHENNUMMER" },
                { "key": "year", "value": "JAHR" }
              ]
            },
            "description": "Standortweite Bestellzahlen über alle Speisepläne einer Kalenderwoche. Zeitraum darf höchstens 400 Tage zurückliegen (bezogen auf die tatsächliche Kalenderwoche)."
          },
          "response": []
        },
        {
          "name": "GET Bestellzahlen nach Datumsbereich",
          "request": {
            "method": "GET",
            "header": [],
            "url": {
              "raw": "{{baseUrl}}/menus/quantities?locationClientUid={{locationClientUid}}&from=YYYY-MM-DD&to=YYYY-MM-DD",
              "host": ["{{baseUrl}}"],
              "path": ["menus", "quantities"],
              "query": [
                { "key": "locationClientUid", "value": "{{locationClientUid}}" },
                { "key": "from", "value": "YYYY-MM-DD" },
                { "key": "to", "value": "YYYY-MM-DD" }
              ]
            },
            "description": "Alternative zu week/year: fester Datumsbereich. Darf höchstens 400 Tage zurückliegen und höchstens 180 Tage insgesamt umfassen — sonst 400 VALIDATION_ERROR."
          },
          "response": []
        }
      ]
    },
    {
      "name": "Speiseplan löschen",
      "item": [
        {
          "name": "DELETE Speiseplan",
          "request": {
            "method": "DELETE",
            "header": [],
            "url": {
              "raw": "{{baseUrl}}/menus/{{menuId}}",
              "host": ["{{baseUrl}}"],
              "path": ["menus", "{{menuId}}"]
            },
            "description": "ACHTUNG: löscht einen echten Speiseplan unwiderruflich (Items mit bereits verstrichenen Deadlines bleiben als 'protected' erhalten) und storniert aktive Bestellungen (Besteller werden per Mail benachrichtigt)."
          },
          "response": []
        }
      ]
    }
  ]
}
