跳转到主要内容

Recipes

The Recipe API calculates environmental impact data for dishes, meals, and complete menus. Each recipe returns CO2 values, nutritional ratings, and eligibility for the Eaternity Award.

For complete request and response examples, see the use cases Recipe impact assessment and Menus for menu plan display and reporting.

Overview​

Use the Recipe API to:

  • Calculate CO2 footprint for individual dishes
  • Batch-process entire menus for environmental analysis
  • Track recipe sustainability over time
  • Earn the Eaternity Award for low-impact recipes
  • Get nutritional quality ratings (A-E scale)
  • Analyze ingredient-level environmental contributions

Recipe ID Uniqueness​

The API knows a recipe by its id and nothing else. The kitchen-id and the date are stored with the recipe, but they do not make it a different recipe.

Send a recipe with an id that already exists, and the API overwrites the stored recipe, including its kitchen-id and date. The earlier serving is then gone from that kitchen and that day.

The rule: use a new id every time a dish is served in a kitchen on a day.

Example 1: Kitchen A and Kitchen B both serve pumpkin risotto on 1 April. Send two recipes with two different ids, for example risotto-kitchen-a-2026-04-01 and risotto-kitchen-b-2026-04-01. With one shared id, the second request would move the risotto to Kitchen B, and Kitchen A would lose it from its reports.

Example 2: Kitchen A serves the risotto again on 2 April. That is a third recipe with a third id, for example risotto-kitchen-a-2026-04-02. Reusing the id from 1 April would move the first serving to 2 April, and 1 April would lose it.

A simple way to get a new id every time: combine your own recipe number with the kitchen and the date.

Sub-recipes are the exception. A sub-recipe such as a sauce may keep the same id in every menu that uses it; see Sub-Recipes. For menus sent per kitchen and date, see Menus for menu plan display and reporting.

Sub-Recipes​

Recipes can reference other recipes as ingredients using the type: "recipes" ingredient field. This enables hierarchical composition of menu items from reusable sub-recipes.

All individual recipes may contain the identical sub-recipe (e.g., pumpkin risotto) as an ingredient, using the same ID each time.

Sub-Recipe ID Reuse

The drawback of reusing the same ID for a sub-recipe is that you will not be able to change its composition individually without impacting all recipes that reference it. Consider using individual IDs for sub-recipes if you need independent modification.

Sub-recipes are sent as transient: they count only through the menu that uses them. See Transient Recipes.

Query Parameters​

All recipe endpoints take the query parameters full-resource, indicators, nutrient-values, ingredients-declaration, return-uids and transient. Values and defaults: Query Parameters. For transient, see also Transient Recipes.

Examples​

# 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-Specific Parameters​

The /recipes/batch endpoint supports additional parameters:

ParameterTypeDefaultDescription
priorityinteger1Calculation priority: 0 (low) or 1 (high, processed first). Use 0 for background jobs.

Request Headers​

HeaderRequiredDescription
Content-TypeYesMust be application/json
AuthorizationYesBasic Auth with API key

Recipe Properties​

Ingredients

The fields of each line in ingredients are on their own page: Ingredients.

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": []
}
}

Property Definitions​

Request Properties​

PropertyTypeRequiredDescription
kitchen-idStringYesThe ID of the kitchen the recipe belongs to
idStringYesUnique recipe identifier. See Recipe ID Uniqueness for rules.
titlesArrayYesRecipe titles as array of language objects: [{"language": "en", "value": "..."}]
recipe-portionsFloatNoNumber of portions the ingredients are specified for. Defaults to 1.
dateISO DateBest practiceThe date the recipe is served (format: yyyy-mm-dd).
ingredientsArrayYesList of ingredient objects (min 1). See Ingredients.
weightIntegerNoFinal weight of the recipe per portion in grams. Used to factor evaporation and cooking losses. If not provided, defaults to the sum of ingredient weights. To model food loss of individual ingredients, prefer the per-ingredient loss-in-percent-of-amount field.
authorStringNoOriginal author of the recipe
locationStringNoLocation where the recipe is cooked. Address or country (arbitrary format). Falls back to kitchen location.
production-portionsFloatNoHow many portions of the recipe are planned to be produced
sold-portionsFloatNoHow many portions were actually sold (consumed). Used by the forecast endpoint to predict sales.
instructionsArrayNoCooking instructions as array of language objects: [{"language": "en", "value": "..."}]
menu-line-nameStringNoDescriptor for the menu line (e.g., "Fitness", "Garden Menu", "Vegan Menu")
menu-line-idIntegerNoNumeric identifier for the menu line
transientBooleanNoBatch item field, next to request-id. true makes the recipe transient: calculated and returned, not kept, not counted on its own.
Date Field Behavior

A recipe without date is calculated, but it is missing from date-based reports. Always include the date the recipe is served.

Response Properties​

PropertyTypeDescription
co2-valueIntegerTotal CO2 emissions of the whole recipe per serving (grams CO2-eq)
co2-value-improvement-percentageFloatComparison of this recipe's CO2 footprint per food unit to the average
co2-value-reduction-valueFloatGrams of CO2 saved by serving this recipe instead of an average recipe providing the same nutritional value
ratingStringEnvironmental rating (A-E scale, A is best)
eaternity-awardBooleantrue if the recipe is climate friendly
info-textStringNotes on the calculated CO2 value, e.g., remarks when properties like origin or transport are estimated
final-weight-per-portionFloatFinal weight per portion after cooking (grams)
indicators.vita-scoreObjectNutritional quality rating (A-E) and its risk factors (only when indicators=true is set). See Vita Score.
indicatorsObjectEnvironmental and nutritional indicators (only when indicators=true parameter is set)
nutrient-values-estimated-per-recipe-portionObjectAggregated nutrient values per portion, calculated by summing all ingredient nutrients and dividing by recipe-portions (when nutrient-values=true parameter is set)

Transient Recipes​

What transient means

A transient recipe is calculated, and its result comes back in the response. After that it is not kept:

  • It never counts in the reports on its own, even with a date. Its ingredients count only through the menu that uses it.
  • It cannot be retrieved later. A GET answers 404, and it is not in the kitchen's recipe list.
  • A menu can use it as a sub-recipe.

Where to set it​

WhereApplies to
Body field "transient": true on a batch item, next to request-idThat one recipe
Query parameter ?transient=trueEvery recipe in the request, the menus included

Put the body field on the batch item, not inside recipe. Inside recipe it is ignored and the recipe is stored as a normal one.

?transient=true on a menu batch makes the menus transient as well, so they drop out of the reports. For sub-recipes, use the body field.

When to use it​

  • Sub-recipes such as a sauce, a side or a base: transient.
  • Previews and tests: ?transient=true.
  • Menus that should count in the reports: not transient.

Batch Operations​

Process multiple recipes in a single request for optimal performance.

Request​

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

Request ID Tracking​

Each recipe in a batch can include an integer request-id field to help you track recipes in the response. This is especially useful when you do not use your own recipe IDs.

  • Either a request-id or a recipe id is required per entry
  • The request-id differs from the recipe id and has just the lifetime of a single request (not stored on the server)

Sub-Recipe Composition Example​

In the following request, one menu item "Fitness Risotto" contains a single recipe "Mushroom gravy on pumpkin risotto". This recipe is again composed of two sub-recipes: "pumpkin risotto" and "Mushroom gravy". All recipes are included in the batch.

The menu item is not transient ("transient": false), so it counts in the reports. The sub-recipes are transient ("transient": true): they are calculated with the menu and count only through it. The flag sits on each batch item, next to 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, one entry per recipe in the order of the request:

[
{
"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​

The Eaternity Award is a label for meals that are climate friendly. A recipe receives the Eaternity Award when it achieves an "A" CO2 rating.

The eaternity-award field is a boolean returned alongside the CO2 rating:

  • true — the meal is climate friendly (equivalent to an "A" CO2 rating)
  • false — the meal does not qualify

Rating System​

Recipes receive an environmental rating from A (best) to E (worst). Thresholds: Rating Scale.


Ingredients​

Ingredients

Every recipe line is an ingredient object. Fields, allowed values, types and matching: Ingredients.


Endpoints​