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.
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:
| Parameter | Type | Default | Description |
|---|---|---|---|
priority | integer | 1 | Calculation priority: 0 (low) or 1 (high, processed first). Use 0 for background jobs. |
Request Headers
| Header | Required | Description |
|---|---|---|
Content-Type | Yes | Must be application/json |
Authorization | Yes | Basic Auth with API key |
Recipe Properties
The fields of each line in ingredients are on their own page: Ingredients.
Request Schema
{
"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
| Property | Type | Required | Description |
|---|---|---|---|
kitchen-id | String | Yes | The ID of the kitchen the recipe belongs to |
id | String | Yes | Unique recipe identifier. See Recipe ID Uniqueness for rules. |
titles | Array | Yes | Recipe titles as array of language objects: [{"language": "en", "value": "..."}] |
recipe-portions | Float | No | Number of portions the ingredients are specified for. Defaults to 1. |
date | ISO Date | Best practice | The date the recipe is served (format: yyyy-mm-dd). |
ingredients | Array | Yes | List of ingredient objects (min 1). See Ingredients. |
weight | Integer | No | Final 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. |
author | String | No | Original author of the recipe |
location | String | No | Location where the recipe is cooked. Address or country (arbitrary format). Falls back to kitchen location. |
production-portions | Float | No | How many portions of the recipe are planned to be produced |
sold-portions | Float | No | How many portions were actually sold (consumed). Used by the forecast endpoint to predict sales. |
instructions | Array | No | Cooking instructions as array of language objects: [{"language": "en", "value": "..."}] |
menu-line-name | String | No | Descriptor for the menu line (e.g., "Fitness", "Garden Menu", "Vegan Menu") |
menu-line-id | Integer | No | Numeric identifier for the menu line |
transient | Boolean | No | Batch item field, next to request-id. true makes the recipe transient: calculated and returned, not kept, not counted on its own. |
A recipe without date is calculated, but it is missing from date-based reports. Always include the date the recipe is served.
Response Properties
| Property | Type | Description |
|---|---|---|
co2-value | Integer | Total CO2 emissions of the whole recipe per serving (grams CO2-eq) |
co2-value-improvement-percentage | Float | Comparison of this recipe's CO2 footprint per food unit to the average |
co2-value-reduction-value | Float | Grams of CO2 saved by serving this recipe instead of an average recipe providing the same nutritional value |
rating | String | Environmental rating (A-E scale, A is best) |
eaternity-award | Boolean | true if the recipe is climate friendly |
info-text | String | Notes on the calculated CO2 value, e.g., remarks when properties like origin or transport are estimated |
final-weight-per-portion | Float | Final weight per portion after cooking (grams) |
indicators.vita-score | Object | Nutritional quality rating (A-E) and its risk factors (only when indicators=true is set). See Vita Score. |
indicators | Object | Environmental and nutritional indicators (only when indicators=true parameter is set) |
nutrient-values-estimated-per-recipe-portion | Object | Aggregated nutrient values per portion, calculated by summing all ingredient nutrients and dividing by recipe-portions (when nutrient-values=true parameter is set) |
Transient Recipes
transient meansA 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
GETanswers404, and it is not in the kitchen's recipe list. - A menu can use it as a sub-recipe.
Where to set it
| Where | Applies to |
|---|---|
Body field "transient": true on a batch item, next to request-id | That one recipe |
Query parameter ?transient=true | Every 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-idor a recipeidis required per entry - The
request-iddiffers from the recipeidand 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.
[
{
"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
Every recipe line is an ingredient object. Fields, allowed values, types and matching: Ingredients.
Endpoints
📄️ Create or update a batch of recipes
Batch operations allow you to create, update or delete multiple recipes at once.
📄️ Delete a batch of recipes
Delete multiple recipes at once by providing a list of recipe IDs.
📄️ Create a recipe
Create a new recipe without specifying an ID (ID will be generated).
📄️ Get a recipe
Retrieve a recipe by its ID with calculated CO₂ values and indicators.
📄️ Update or create a recipe
Update an existing recipe or create a new one with the specified ID.
📄️ Delete a recipe
Delete a recipe by its ID.
📄️ Create a recipe in a kitchen
Create a new recipe associated with a specific kitchen.
📄️ Get all recipes in a kitchen
Returns a list of recipe IDs contained in this kitchen.
📄️ Get a recipe from a kitchen
Retrieve a specific recipe from a kitchen.
📄️ Create or update a recipe in a kitchen
Update or create a recipe with the specified ID in a specific kitchen.
📄️ Delete a recipe from a kitchen
Delete a specific recipe from a kitchen.