Zum Hauptinhalt springen

Rezepte

Die Recipe API berechnet Umweltdaten für Gerichte, Mahlzeiten und ganze Menüs. Für jedes Rezept liefert sie CO2-Werte, Bewertungen der Ernährungsqualität und die Berechtigung für den Eaternity Award.

Vollständige Beispiele für Request und Response finden Sie in den Anwendungsfällen Umweltbewertung von Rezepten und Menüs für Menüplan-Anzeige und Reporting.

Überblick​

Mit der Recipe API können Sie:

  • den CO2-Fussabdruck einzelner Gerichte berechnen
  • ganze Menüs im Batch für die Umweltanalyse verarbeiten
  • die Nachhaltigkeit von Rezepten über die Zeit verfolgen
  • den Eaternity Award für Rezepte mit geringer Umweltwirkung erhalten
  • Bewertungen der Ernährungsqualität erhalten (Skala A–E)
  • den Umweltbeitrag einzelner Zutaten analysieren

Eindeutigkeit der Rezept-ID​

Die API kennt ein Rezept nur über seine id. Die kitchen-id und das date werden mit dem Rezept gespeichert, machen es aber nicht zu einem anderen Rezept.

Senden Sie ein Rezept mit einer id, die bereits existiert, überschreibt die API das gespeicherte Rezept, inklusive kitchen-id und date. Die frühere Ausgabe fehlt dann in dieser Küche und an diesem Tag.

Die Regel: Verwenden Sie jedes Mal eine neue id, wenn ein Gericht in einer Küche an einem Tag serviert wird.

Beispiel 1: Küche A und Küche B servieren beide am 1. April Kürbisrisotto. Senden Sie zwei Rezepte mit zwei verschiedenen IDs, zum Beispiel risotto-kitchen-a-2026-04-01 und risotto-kitchen-b-2026-04-01. Mit einer gemeinsamen ID würde der zweite Request das Risotto in Küche B verschieben, und Küche A würde es in ihren Berichten verlieren.

Beispiel 2: Küche A serviert das Risotto am 2. April erneut. Das ist ein drittes Rezept mit einer dritten ID, zum Beispiel risotto-kitchen-a-2026-04-02. Würden Sie die ID vom 1. April wiederverwenden, würde die erste Ausgabe auf den 2. April verschoben, und am 1. April würde sie fehlen.

Ein einfacher Weg zu einer neuen ID: Kombinieren Sie Ihre eigene Rezeptnummer mit der Küche und dem Datum.

Unterrezepte sind die Ausnahme. Ein Unterrezept wie eine Sauce darf in jedem Menü, das es verwendet, dieselbe ID behalten; siehe Unterrezepte. Zu Menüs, die pro Küche und Datum gesendet werden, siehe Menüs für Menüplan-Anzeige und Reporting.

Unterrezepte​

Rezepte können über das Zutatenfeld type: "recipes" andere Rezepte als Zutaten referenzieren. So lassen sich Menüpositionen hierarchisch aus wiederverwendbaren Unterrezepten zusammensetzen.

Alle einzelnen Rezepte dürfen dasselbe Unterrezept (z. B. Kürbisrisotto) als Zutat enthalten, jedes Mal mit derselben ID.

Wiederverwendung der Unterrezept-ID

Der Nachteil einer wiederverwendeten ID für ein Unterrezept: Sie können seine Zusammensetzung nicht einzeln ändern, ohne alle Rezepte zu beeinflussen, die es referenzieren. Verwenden Sie individuelle IDs für Unterrezepte, wenn Sie sie unabhängig ändern müssen.

Unterrezepte werden als transient gesendet: Sie zählen nur über das Menü, das sie verwendet. Siehe Transiente Rezepte.

Query-Parameter​

Alle Rezept-Endpoints akzeptieren die Query-Parameter full-resource, indicators, nutrient-values, ingredients-declaration, return-uids und transient. Werte und Standardwerte: Query-Parameter. Zu transient siehe auch Transiente Rezepte.

Beispiele​

# Get recipe with all indicators
curl "https://co2.eaternity.ch/api/kitchens/{kitchen_id}/recipes/{recipe_id}?indicators=true" \
-u YOUR_API_KEY:

# Preview: calculate a recipe without keeping it (transient)
curl -X POST "https://co2.eaternity.ch/api/kitchens/{kitchen_id}/recipes?transient=true" \
-u YOUR_API_KEY: \
-H "Content-Type: application/json" \
-d '{"recipe": {"titles": [{"language": "en", "value": "Test"}], "date": "2024-12-16", "ingredients": [...]}}'

# Get full response with internal UIDs
curl "https://co2.eaternity.ch/api/kitchens/{kitchen_id}/recipes/{recipe_id}?full-resource=true&return-uids=true" \
-u YOUR_API_KEY:

Batch-spezifische Parameter​

Der Endpoint /recipes/batch unterstützt zusätzliche Parameter:

ParameterTypStandardBeschreibung
priorityinteger1Berechnungspriorität: 0 (niedrig) oder 1 (hoch, wird zuerst verarbeitet). Verwenden Sie 0 für Hintergrundjobs.

Request-Header​

HeaderErforderlichBeschreibung
Content-TypeJaMuss application/json sein
AuthorizationJaBasic Auth mit API-Schlüssel

Rezepteigenschaften​

Zutaten

Die Felder jeder Zeile in ingredients stehen auf einer eigenen Seite: Zutaten.

Request-Schema​

PUT /kitchens/kitchen-restaurant-a/recipes/recipe-001
{
"recipe": {
"kitchen-id": "kitchen-restaurant-a",
"id": "recipe-001",
"titles": [{"language": "en", "value": "Grilled Salmon with Vegetables"}, {"language": "de", "value": "Gegrillter Lachs mit Gemüse"}],
"recipe-portions": 4,
"date": "2024-12-16",
"weight": 350,
"ingredients": [
{
"id": "salmon-filet",
"names": [{"language": "en", "value": "Salmon (farmed, fillet)"}],
"amount": 600,
"unit": "gram",
"origin": "Norway",
"transport": "air",
"production": "standard",
"conservation": "fresh",
"packaging": "plastic"
}
]
}
}

Response:

{
"statuscode": 200,
"message": "",
"request-id": 0,
"recipe-id": "recipe-001",
"recipe": {
"food-unit": 1.06,
"final-weight-per-portion": 350.0,
"eaternity-award": false,
"co2-value": 743,
"rating": "B",
"co2-value-improvement-percentage": 10,
"co2-value-reduction-value": 81,
"id": "recipe-001",
"kitchen-id": "kitchen-restaurant-a",
"titles": [{"language": "en", "value": "Grilled Salmon with Vegetables"}, {"language": "de", "value": "Gegrillter Lachs mit Gemüse"}],
"date": "2024-12-16",
"weight": 350.0,
"servings": 4,
"recipe-portions": 4,
"ingredients": []
}
}

Definition der Eigenschaften​

Request-Eigenschaften​

EigenschaftTypErforderlichBeschreibung
kitchen-idStringJaDie ID der Küche, zu der das Rezept gehört
idStringJaEindeutige Rezept-ID. Regeln siehe Eindeutigkeit der Rezept-ID.
titlesArrayJaRezepttitel als Array von Sprachobjekten: [{"language": "en", "value": "..."}]
recipe-portionsFloatNeinAnzahl Portionen, für die die Zutaten angegeben sind. Standard ist 1.
dateISO DateEmpfohlenDas Datum, an dem das Rezept serviert wird (Format: yyyy-mm-dd).
ingredientsArrayJaListe von Zutatenobjekten (mindestens 1). Siehe Zutaten.
weightIntegerNeinEndgewicht des Rezepts pro Portion in Gramm. Wird verwendet, um Verdunstungs- und Garverluste zu berücksichtigen. Ohne Angabe gilt die Summe der Zutatengewichte. Um Lebensmittelverluste einzelner Zutaten abzubilden, verwenden Sie besser das Feld loss-in-percent-of-amount pro Zutat.
authorStringNeinUrsprüngliche Autorin oder ursprünglicher Autor des Rezepts
locationStringNeinOrt, an dem das Rezept gekocht wird. Adresse oder Land (beliebiges Format). Ohne Angabe gilt der Standort der Küche.
production-portionsFloatNeinWie viele Portionen des Rezepts produziert werden sollen
sold-portionsFloatNeinWie viele Portionen tatsächlich verkauft (konsumiert) wurden. Wird vom Forecast-Endpoint zur Prognose der Verkäufe verwendet.
instructionsArrayNeinKochanleitung als Array von Sprachobjekten: [{"language": "en", "value": "..."}]
menu-line-nameStringNeinBezeichnung der Menülinie (z. B. "Fitness", "Garden Menu", "Vegan Menu")
menu-line-idIntegerNeinNumerische Kennung der Menülinie
transientBooleanNeinFeld des Batch-Eintrags, neben request-id. true macht das Rezept transient: Es wird berechnet und zurückgegeben, aber nicht gespeichert und nicht eigenständig gezählt.
Verhalten des Datumsfelds

Ein Rezept ohne date wird berechnet, fehlt aber in datumsbasierten Berichten. Geben Sie immer das Datum an, an dem das Rezept serviert wird.

Response-Eigenschaften​

EigenschaftTypBeschreibung
co2-valueIntegerGesamte CO2-Emissionen des ganzen Rezepts pro Portion (Gramm CO2-eq)
co2-value-improvement-percentageFloatVergleich des CO2-Fussabdrucks dieses Rezepts pro Food Unit mit dem Durchschnitt
co2-value-reduction-valueFloatGramm CO2, die eingespart werden, wenn dieses Rezept statt eines durchschnittlichen Rezepts mit demselben Nährwert serviert wird
ratingStringUmweltbewertung (Skala A–E, A ist am besten)
eaternity-awardBooleantrue, wenn das Rezept klimafreundlich ist
info-textStringHinweise zum berechneten CO2-Wert, z. B. Anmerkungen, wenn Eigenschaften wie Herkunft oder Transport geschätzt wurden
final-weight-per-portionFloatEndgewicht pro Portion nach dem Kochen (Gramm)
indicators.vita-scoreObjectBewertung der Ernährungsqualität (A–E) und ihre Risikofaktoren (nur wenn indicators=true gesetzt ist). Siehe Vita Score.
indicatorsObjectUmwelt- und Ernährungsindikatoren (nur wenn der Parameter indicators=true gesetzt ist)
nutrient-values-estimated-per-recipe-portionObjectAggregierte Nährwerte pro Portion: Summe der Nährwerte aller Zutaten, geteilt durch recipe-portions (wenn der Parameter nutrient-values=true gesetzt ist)

Transiente Rezepte​

Was transient bedeutet

Ein transientes Rezept wird berechnet, und sein Ergebnis kommt in der Response zurück. Danach wird es nicht gespeichert:

  • Es zählt in den Berichten nie eigenständig, auch nicht mit einem date. Seine Zutaten zählen nur über das Menü, das es verwendet.
  • Es kann später nicht abgerufen werden. Ein GET antwortet mit 404, und es erscheint nicht in der Rezeptliste der Küche.
  • Ein Menü kann es als Unterrezept verwenden.

Wo Sie es setzen​

WoGilt für
Body-Feld "transient": true auf einem Batch-Eintrag, neben request-idDieses eine Rezept
Query-Parameter ?transient=trueJedes Rezept im Request, inklusive der Menüs

Setzen Sie das Body-Feld auf den Batch-Eintrag, nicht in recipe. Innerhalb von recipe wird es ignoriert, und das Rezept wird als normales Rezept gespeichert.

?transient=true auf einem Menü-Batch macht auch die Menüs transient, sodass sie aus den Berichten fallen. Für Unterrezepte verwenden Sie das Body-Feld.

Wann Sie es verwenden​

  • Unterrezepte wie eine Sauce, eine Beilage oder eine Basis: transient.
  • Vorschauen und Tests: ?transient=true.
  • Menüs, die in den Berichten zählen sollen: nicht transient.

Batch-Operationen​

Verarbeiten Sie mehrere Rezepte in einem einzigen Request für optimale Performance.

Request​

POST /recipes/batch
Content-Type: application/json
Authorization: Basic {api_key}

Nachverfolgung mit Request-ID​

Jedes Rezept in einem Batch kann ein ganzzahliges Feld request-id enthalten, mit dem Sie Rezepte in der Response zuordnen können. Das ist besonders nützlich, wenn Sie keine eigenen Rezept-IDs verwenden.

  • Pro Eintrag ist entweder eine request-id oder eine Rezept-id erforderlich
  • Die request-id unterscheidet sich von der Rezept-id und gilt nur für die Dauer eines einzelnen Requests (sie wird nicht auf dem Server gespeichert)

Beispiel für die Zusammensetzung aus Unterrezepten​

Im folgenden Request enthält die Menüposition "Fitness Risotto" ein einzelnes Rezept "Mushroom gravy on pumpkin risotto". Dieses Rezept besteht wiederum aus zwei Unterrezepten: "pumpkin risotto" und "Mushroom gravy". Alle Rezepte sind im Batch enthalten.

Die Menüposition ist nicht transient ("transient": false) und zählt deshalb in den Berichten. Die Unterrezepte sind transient ("transient": true): Sie werden mit dem Menü berechnet und zählen nur über dieses. Das Flag steht auf jedem Batch-Eintrag, neben request-id.

POST /recipes/batch
[
{
"request-id": 0,
"transient": true,
"recipe": {
"id": "internal-recipe-id3",
"kitchen-id": "kitchen-restaurant-a",
"titles": [{"language": "en", "value": "Mushroom gravy on pumpkin risotto"}],
"recipe-portions": 1,
"ingredients": [
{
"id": "internal-recipe-id1",
"type": "recipes",
"amount": 250,
"unit": "gram"
},
{
"id": "internal-recipe-id2",
"type": "recipes",
"amount": 50,
"unit": "gram"
}
]
}
},
{
"request-id": 1,
"transient": true,
"recipe": {
"id": "internal-recipe-id1",
"kitchen-id": "kitchen-restaurant-a",
"titles": [{"language": "en", "value": "pumpkin risotto"}],
"recipe-portions": 100,
"ingredients": [
{
"id": "101",
"type": "conceptual-ingredients",
"names": [{"language": "en", "value": "Pumpkin"}],
"amount": 5000,
"unit": "gram",
"origin": "Italy",
"transport": "ground",
"conservation": "dried"
}
]
}
},
{
"request-id": 2,
"transient": true,
"recipe": {
"id": "internal-recipe-id2",
"kitchen-id": "kitchen-restaurant-a",
"titles": [{"language": "en", "value": "Mushroom gravy"}],
"recipe-portions": 5,
"ingredients": [
{
"id": "104",
"type": "conceptual-ingredients",
"names": [{"language": "en", "value": "onions"}],
"amount": 78,
"unit": "gram"
}
]
}
},
{
"request-id": 3,
"transient": false,
"recipe": {
"id": "menu-id1-fitness-2016-11-28",
"kitchen-id": "kitchen-restaurant-a",
"menu-line-name": "Fitness",
"menu-line-id": 1,
"titles": [{"language": "en", "value": "Fitness Risotto"}],
"recipe-portions": 1,
"date": "2016-11-28",
"ingredients": [
{
"id": "internal-recipe-id3",
"type": "recipes",
"amount": 288,
"unit": "gram"
}
]
}
}
]

Response, ein Eintrag pro Rezept in der Reihenfolge des Requests:

[
{
"statuscode": 200,
"message": "",
"recipe-id": "internal-recipe-id3",
"request-id": 0,
"recipe": {
"food-unit": 1.36,
"final-weight-per-portion": 300.0,
"eaternity-award": false,
"co2-value": 2030,
"rating": "C",
"co2-value-improvement-percentage": -91,
"co2-value-reduction-value": -969,
"id": "internal-recipe-id3",
"kitchen-id": "kitchen-restaurant-a",
"titles": [{"language": "en", "value": "Mushroom gravy on pumpkin risotto"}],
"servings": 1,
"recipe-portions": 1,
"ingredients": []
}
},
{
"statuscode": 200,
"message": "",
"recipe-id": "internal-recipe-id1",
"request-id": 1,
"recipe": {
"food-unit": 0.26,
"final-weight-per-portion": 50.0,
"eaternity-award": false,
"co2-value": 404,
"rating": "C",
"co2-value-improvement-percentage": -98,
"co2-value-reduction-value": -200,
"id": "internal-recipe-id1",
"kitchen-id": "kitchen-restaurant-a",
"titles": [{"language": "en", "value": "pumpkin risotto"}],
"servings": 100,
"recipe-portions": 100,
"ingredients": []
}
},
{
"statuscode": 200,
"message": "",
"recipe-id": "internal-recipe-id2",
"request-id": 2,
"recipe": {
"food-unit": 0.02,
"final-weight-per-portion": 15.600000000000001,
"eaternity-award": true,
"co2-value": 3,
"rating": "A",
"co2-value-improvement-percentage": 74,
"co2-value-reduction-value": 9,
"id": "internal-recipe-id2",
"kitchen-id": "kitchen-restaurant-a",
"titles": [{"language": "en", "value": "Mushroom gravy"}],
"servings": 5,
"recipe-portions": 5,
"ingredients": []
}
},
{
"statuscode": 200,
"message": "",
"recipe-id": "menu-id1-fitness-2016-11-28",
"request-id": 3,
"recipe": {
"food-unit": 1.31,
"final-weight-per-portion": 288.0,
"eaternity-award": false,
"co2-value": 1949,
"rating": "C",
"co2-value-improvement-percentage": -91,
"co2-value-reduction-value": -931,
"id": "menu-id1-fitness-2016-11-28",
"kitchen-id": "kitchen-restaurant-a",
"titles": [{"language": "en", "value": "Fitness Risotto"}],
"date": "2016-11-28",
"servings": 1,
"recipe-portions": 1,
"ingredients": [],
"menu-line-name": "Fitness",
"menu-line-id": 1
}
}
]

Eaternity Award​

Der Eaternity Award ist ein Label für klimafreundliche Mahlzeiten. Ein Rezept erhält den Eaternity Award, wenn es eine CO2-Bewertung "A" erreicht.

Das Feld eaternity-award ist ein Boolean, der zusammen mit der CO2-Bewertung zurückgegeben wird:

  • true — die Mahlzeit ist klimafreundlich (entspricht einer CO2-Bewertung "A")
  • false — die Mahlzeit erfüllt die Kriterien nicht

Bewertungssystem​

Rezepte erhalten eine Umweltbewertung von A (am besten) bis E (am schlechtesten). Schwellenwerte: Bewertungsskala.


Zutaten​

Zutaten

Jede Rezeptzeile ist ein Zutatenobjekt. Felder, erlaubte Werte, Typen und Matching: Zutaten.


Endpoints​