跳转到主要内容

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.

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

For every time a recipe is offered in a kitchen, a new ID must be used. A recipe is uniquely identified by the combination of its id, kitchen-id, and date.

Example 1:

Your business runs Kitchen A and Kitchen B. On the 1st of April, both kitchens offer pumpkin risotto, using the same ingredients. You will have to create two different recipes with two different IDs.

Example 2:

Your business runs Kitchen A and Kitchen B. On the 1st of April, both kitchens offer pumpkin risotto. On the 2nd of April, Kitchen A offers pumpkin risotto again. You will have to create three different recipes with three different IDs.

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 sub-recipe will be stored only once in the database.

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.

Important: Always use the transient: true flag for sub-recipes. Sub-recipes marked as transient will not be included in the monthly summary on their own — they only contribute when referenced by a non-transient parent recipe.

Query Parameters

All recipe endpoints support the following query parameters:

ParameterTypeDefaultDescription
full-resourcebooleanfalseReturn complete JSON response with all fields (except indicators). Saves bandwidth when false.
indicatorsbooleanfalseInclude additional environmental indicators: Vita Score, water footprint, rainforest impact, animal welfare, seasonality, local sourcing.
nutrient-valuesbooleanfalseInclude nutrient-values-estimated-per-specified-amount for each ingredient without requiring the full indicators response.
ingredients-declarationbooleanfalseInclude parsed ingredients-declaration data for each ingredient.
return-uidsbooleanfalseInclude internal uid fields in response. Useful for tracking internal identifiers.
transientbooleanfalseRecipe is calculated but not permanently stored — it will not appear in reports or statistics. See Transient Recipes for the distinction with the body field.

Examples

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

# Calculate recipe without permanently storing it (transient)
curl -X POST "https://co2.eaternity.ch/api/recipes/{kitchen_id}?transient=true" \
-u YOUR_API_KEY: \
-H "Content-Type: application/json" \
-d '{"id": "test", "titles": [{"language": "en", "value": "Test"}], ...}'

# Get full response with internal UIDs
curl "https://co2.eaternity.ch/api/recipes/{kitchen_id}/{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-3). Higher values are processed first. Use 0 for background jobs, 3 for real-time UI.

Request Headers

HeaderRequiredDescription
Content-TypeYesMust be application/json
AuthorizationYesBasic Auth with API key
skip_calcNoSet to true to skip environmental calculations. Useful for CRUD operations only.

Recipe Properties

Request Schema

{
"kitchen-id": "550e8400-e29b-41d4-a716-446655440000",
"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": "Fresh Salmon Filet"}
],
"amount": 600,
"unit": "gram",
"origin": "Norway",
"transport": "air",
"production": "aquaculture",
"conservation": "fresh",
"packaging": "plastic-tray"
}
]
}

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 below.
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.
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
transientBooleanNoWhen true in a batch request body, the recipe is saved but excluded from the monthly summary. Use for sub-recipes, test submissions, or any recipe you do not want in reports. See Transient Recipes.
Date Field Behavior

If no date is provided, only a rating of the recipe is returned — no full CO2 calculation is performed. Always include a date for complete environmental impact results.

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)
vita-scoreStringNutritional quality rating (A-E)
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

The transient flag has two different meanings depending on where it is used:

ContextMeaning
Query parameter ?transient=trueThe recipe is calculated but not permanently stored. Use for testing, preview calculations, or any recipe you do not want in reports.
Body field "transient": true (in batch requests)The recipe is saved but excluded from the monthly summary. Use for sub-recipes, intermediate compositions, or recipes that should not appear in reports.

The per-recipe body field transient can be set selectively per recipe inside a batch. Transient recipes only contribute to the monthly summary and kitchen statistics when they are used as sub-recipes in other recipes that are not transient. Set transient: true for sub-recipes, test submissions, or any recipe you do not want included in reports.

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 marked as not transient ("transient": false), meaning it will be included in the monthly summary. The sub-recipes are transient ("transient": true), meaning they will only be stored for reference but not counted individually in the summary.

[
{
"request-id": 0,
"recipe": {
"id": "internal-recipe-id3",
"transient": true,
"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,
"recipe": {
"id": "internal-recipe-id1",
"transient": true,
"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,
"recipe": {
"id": "internal-recipe-id2",
"transient": true,
"kitchen-id": "kitchen-restaurant-a",
"titles": [
{"language": "en", "value": "Mushroom gravy"}
],
"recipe-portions": 5,
"ingredients": [
{
"id": "104",
"type": "conceptual-ingredients",
"names": [
{"language": "de", "value": "onions"}
],
"amount": 78,
"unit": "gram"
}
]
}
},
{
"request-id": 3,
"recipe": {
"id": "menu-id1-fitness-2016-11-28",
"kitchen-id": "kitchen-restaurant-a",
"transient": false,
"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"
}
]
}
}
]

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).

Rating Thresholds

RatingCO2 per PortionDescription
A≤ 400gExcellent - Very low environmental impact
B401-600gGood - Low environmental impact
C601-1000gAverage - Moderate environmental impact
D1001-1500gBelow Average - High environmental impact
E> 1500gPoor - Very high environmental impact

Ingredients

Ingredients are the building blocks of recipes and products. They are included within recipe or product requests, not as standalone resources.

Ingredient Schema

{
"id": "tomatoes-001",
"names": [
{"language": "en", "value": "Cherry Tomatoes"},
{"language": "de", "value": "Kirschtomaten"}
],
"amount": 200,
"unit": "gram",
"origin": "Italy",
"transport": "truck",
"production": "organic",
"conservation": "fresh",
"packaging": "plastic-tray",
"producer": "BioFarm AG"
}

Required Properties

PropertyTypeRequiredDescription
idStringYesUnique ingredient identifier within recipe (max 255 chars)
namesArrayYesIngredient name in at least one language, as array of language objects: [{"language": "en", "value": "..."}]. Used for database matching.
amountFloatYesQuantity of ingredient (must be > 0)
unitStringYesMeasurement unit (gram or liter)

Optional Core Properties

PropertyTypeDefaultDescription
typeStringconceptual-ingredientsIngredient type: conceptual-ingredients (normal ingredient) or recipes (references existing recipe as sub-recipe)
originString-Origin of the ingredient: postal address or country
transportString-Means of transport from origin to kitchen: air or ground
productionString-Production method: standard, greenhouse, organic, fair-trade, farm, wild-caught, sustainable-fish
processingString-Processing level: raw. Meat/fish: unboned, boned. Fish: skinned, beheaded, fillet. Vegetables/fruits: cut, boiled, peeled.
conservationString-Conservation method: fresh, frozen, dried, conserved, canned, boiled-down
packagingString-Packaging type: none, plastic, paper, pet, tin, alu, glas, cardboard, tetra
producerString-Producer or brand of the product. Especially important for combined products (products with multiple ingredients).
gtinString-Global Trade Item Number (barcode) for packaged products
ingredients-declarationString-Ingredient list as declared on packaged foods
nutrient-valuesObject-Structured nutrient values per 100g (see Reference)
Multi-Value Fields

The origin, transport, production, processing, conservation, and packaging fields accept comma-separated values when multiple apply. For example: "production": "organic, fair-trade".

Ingredient Response Fields

These fields are returned for each ingredient when full-resource=true:

PropertyTypeDescription
ratingStringCO₂ rating for this ingredient (A-E). A is best, E is worst.
co2-valueIntegerAbsolute CO₂ emissions for the ingredient in grams for the specified amount
co2-value-improvement-percentageFloatComparison of this ingredient's CO₂ footprint per food unit to the average
co2-value-reduction-valueFloatGrams of CO₂ saved compared to an average product providing the same nutritional value
bar-chartFloatPercentage contribution of this ingredient to total recipe CO₂ (0-100%)
foodUnitFloatNutritional density value
nutrient-values-estimated-per-specified-amountObjectBackend-estimated nutrient values for the specified amount (when nutrient-values=true is set)
indicatorsObjectEnvironmental indicators for this ingredient (when indicators=true is set)

Ingredient Types

The type field determines how the ingredient is processed:

// Normal ingredient (default)
{
"id": "rice-001",
"type": "conceptual-ingredients",
"names": [{"language": "en", "value": "Arborio Rice"}],
"amount": 200,
"unit": "gram"
}

// Sub-recipe reference
{
"id": "sauce-ref",
"type": "recipes",
"names": [{"language": "en", "value": "tomato-sauce-001"}], // References existing recipe ID
"amount": 150,
"unit": "gram"
}

Units

The API only accepts two base units:

  • gram: For solid ingredients (food items, spices, etc.)
  • liter: For liquid ingredients (water, milk, oil, etc.)
Unit Conversion

Always convert to grams or liters:

  • 1 kg = 1000 grams
  • 1 ml = 0.001 liters
  • 1 oz ≈ 28.35 grams
  • 1 cup ≈ 240 ml = 0.24 liters

Ingredient Matching

The API uses fuzzy matching to identify ingredients in Eaternity's database of 50,000+ entries.

How Matching Works:

  1. Name normalization: Removes special characters, normalizes spelling
  2. Database search: Searches 50,000+ ingredient entries
  3. Similarity scoring: Calculates match confidence (0-100%)
  4. Best match selection: Returns highest-confidence match
  5. Fallback: Uses generic category if no close match found

Improving Match Quality:

  • Use specific names: "Parmesan Cheese" instead of "Cheese"
  • Include preparation method: "Fresh Cherry Tomatoes" instead of "Tomatoes"
  • Specify cut or form: "Beef Sirloin Steak" instead of "Beef"
  • Add brand via producer field for packaged items
Reduce Ambiguity

To reduce ambiguity and minimize manual follow-ups, we strongly recommend specifying certain ingredient attributes even if technically optional. These include indicators such as air-freighted, fresh, deep-frozen, dried, preserved, baked, canned, boiled, organic, Fairtrade certified, and aquaculture-sourced (for fish). Providing this data up front helps prevent incorrect assumptions and eliminates the need for iterative clarification.


Endpoints