Saltar al contenido principal

Recetas

La Recipe API calcula datos de impacto ambiental para platos, comidas y menús completos. Cada receta devuelve valores de CO2, calificaciones nutricionales y si cumple los requisitos del Eaternity Award.

Para ejemplos completos de solicitud y respuesta, consultad los casos de uso Evaluación del impacto de recetas y Menús para mostrar el plan de menús y para los informes.

Visión general​

Usad la Recipe API para:

  • Calcular la huella de CO2 de platos individuales
  • Procesar menús enteros en lote para el análisis ambiental
  • Seguir la sostenibilidad de las recetas a lo largo del tiempo
  • Obtener el Eaternity Award para recetas de bajo impacto
  • Obtener calificaciones de calidad nutricional (escala A-E)
  • Analizar la contribución ambiental de cada ingrediente

Unicidad del ID de receta​

La API identifica una receta solo por su id. El kitchen-id y la date se guardan con la receta, pero no la convierten en una receta distinta.

Si enviáis una receta con un id que ya existe, la API sobrescribe la receta guardada, incluidos su kitchen-id y su date. La ración anterior desaparece entonces de esa cocina y de ese día.

La regla: usad un id nuevo cada vez que un plato se sirve en una cocina en un día.

Ejemplo 1: la cocina A y la cocina B sirven risotto de calabaza el 1 de abril. Enviad dos recetas con dos ids distintos, por ejemplo risotto-kitchen-a-2026-04-01 y risotto-kitchen-b-2026-04-01. Con un id compartido, la segunda solicitud movería el risotto a la cocina B, y la cocina A lo perdería en sus informes.

Ejemplo 2: la cocina A vuelve a servir el risotto el 2 de abril. Es una tercera receta con un tercer id, por ejemplo risotto-kitchen-a-2026-04-02. Reutilizar el id del 1 de abril movería la primera ración al 2 de abril, y el 1 de abril la perdería.

Una forma sencilla de obtener un id nuevo cada vez: combinad vuestro propio número de receta con la cocina y la fecha.

Las subrecetas son la excepción. Una subreceta, como una salsa, puede mantener el mismo id en todos los menús que la usan; ved Subrecetas. Para menús enviados por cocina y fecha, ved Menús para mostrar el plan de menús y para los informes.

Subrecetas​

Las recetas pueden usar otras recetas como ingredientes mediante el campo de ingrediente type: "recipes". Así se componen los platos del menú de forma jerárquica a partir de subrecetas reutilizables.

Todas las recetas individuales pueden contener la misma subreceta (p. ej., risotto de calabaza) como ingrediente, con el mismo ID cada vez.

Reutilización del ID de subreceta

La desventaja de reutilizar el mismo ID para una subreceta es que no podréis cambiar su composición de forma individual sin afectar a todas las recetas que la usan. Usad IDs individuales para las subrecetas si necesitáis modificarlas por separado.

Las subrecetas se envían como transitorias: solo cuentan a través del menú que las usa. Ved Recetas transitorias.

Parámetros de consulta​

Todos los endpoints de recetas aceptan los parámetros de consulta full-resource, indicators, nutrient-values, ingredients-declaration, return-uids y transient. Valores y valores por defecto: Parámetros de consulta. Para transient, ved también Recetas transitorias.

Ejemplos​

# 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:

Parámetros específicos de lote​

El endpoint /recipes/batch admite parámetros adicionales:

ParámetroTipoPor defectoDescripción
priorityinteger1Prioridad de cálculo: 0 (baja) o 1 (alta, se procesa primero). Usad 0 para trabajos en segundo plano.

Cabeceras de la solicitud​

CabeceraObligatoriaDescripción
Content-TypeSíDebe ser application/json
AuthorizationSíBasic Auth con la clave de API

Propiedades de la receta​

Ingredientes

Los campos de cada línea de ingredients están en su propia página: Ingredientes.

Esquema de la solicitud​

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

Respuesta:

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

Definiciones de las propiedades​

Propiedades de la solicitud​

PropiedadTipoObligatoriaDescripción
kitchen-idStringSíEl ID de la cocina a la que pertenece la receta
idStringSíIdentificador único de la receta. Ved Unicidad del ID de receta para las reglas.
titlesArraySíTítulos de la receta como array de objetos de idioma: [{"language": "en", "value": "..."}]
recipe-portionsFloatNoNúmero de raciones para las que se indican los ingredientes. Por defecto 1.
dateISO DateBuena prácticaLa fecha en que se sirve la receta (formato: yyyy-mm-dd).
ingredientsArraySíLista de objetos de ingrediente (mínimo 1). Ved Ingredientes.
weightIntegerNoPeso final de la receta por ración en gramos. Se usa para tener en cuenta la evaporación y las pérdidas de cocción. Si no se indica, se usa la suma de los pesos de los ingredientes. Para modelar la pérdida de alimentos de ingredientes individuales, usad preferentemente el campo por ingrediente loss-in-percent-of-amount.
authorStringNoAutor original de la receta
locationStringNoLugar donde se cocina la receta. Dirección o país (formato libre). Si falta, se usa la ubicación de la cocina.
production-portionsFloatNoCuántas raciones de la receta se planea producir
sold-portionsFloatNoCuántas raciones se vendieron (consumieron) realmente. El endpoint de forecast lo usa para predecir las ventas.
instructionsArrayNoInstrucciones de cocción como array de objetos de idioma: [{"language": "en", "value": "..."}]
menu-line-nameStringNoNombre de la línea de menú (p. ej., "Fitness", "Garden Menu", "Vegan Menu")
menu-line-idIntegerNoIdentificador numérico de la línea de menú
transientBooleanNoCampo del elemento del lote, junto a request-id. true hace que la receta sea transitoria: se calcula y se devuelve, pero no se guarda ni cuenta por sí sola.
Comportamiento del campo de fecha

Una receta sin date se calcula, pero falta en los informes basados en fechas. Incluid siempre la fecha en que se sirve la receta.

Propiedades de la respuesta​

PropiedadTipoDescripción
co2-valueIntegerEmisiones totales de CO2 de toda la receta por ración (gramos de CO2-eq)
co2-value-improvement-percentageFloatComparación de la huella de CO2 de esta receta por unidad alimentaria con la media
co2-value-reduction-valueFloatGramos de CO2 ahorrados al servir esta receta en lugar de una receta media que aporte el mismo valor nutricional
ratingStringCalificación ambiental (escala A-E, A es la mejor)
eaternity-awardBooleantrue si la receta es respetuosa con el clima
info-textStringNotas sobre el valor de CO2 calculado, p. ej., observaciones cuando se estiman propiedades como el origen o el transporte
final-weight-per-portionFloatPeso final por ración después de la cocción (gramos)
indicators.vita-scoreObjectCalificación de calidad nutricional (A-E) y sus factores de riesgo (solo con indicators=true). Ved Vita Score.
indicatorsObjectIndicadores ambientales y nutricionales (solo con el parámetro indicators=true)
nutrient-values-estimated-per-recipe-portionObjectValores de nutrientes agregados por ración, calculados sumando los nutrientes de todos los ingredientes y dividiendo por recipe-portions (con el parámetro nutrient-values=true)

Recetas transitorias​

Qué significa transient

Una receta transitoria se calcula y su resultado vuelve en la respuesta. Después no se guarda:

  • Nunca cuenta por sí sola en los informes, ni siquiera con una date. Sus ingredientes solo cuentan a través del menú que la usa.
  • No se puede recuperar más tarde. Un GET responde 404, y no aparece en la lista de recetas de la cocina.
  • Un menú puede usarla como subreceta.

Dónde indicarlo​

DóndeSe aplica a
Campo del cuerpo "transient": true en un elemento del lote, junto a request-idEsa receta
Parámetro de consulta ?transient=trueTodas las recetas de la solicitud, incluidos los menús

Poned el campo del cuerpo en el elemento del lote, no dentro de recipe. Dentro de recipe se ignora y la receta se guarda como una receta normal.

?transient=true en un lote de menús hace que también los menús sean transitorios, de modo que desaparecen de los informes. Para las subrecetas, usad el campo del cuerpo.

Cuándo usarlo​

  • Subrecetas como una salsa, una guarnición o una base: transitorias.
  • Vistas previas y pruebas: ?transient=true.
  • Menús que deben contar en los informes: no transitorios.

Operaciones por lotes​

Procesad varias recetas en una sola solicitud para un rendimiento óptimo.

Solicitud​

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

Seguimiento con request ID​

Cada receta de un lote puede incluir un campo entero request-id para ayudaros a localizar las recetas en la respuesta. Es especialmente útil cuando no usáis vuestros propios IDs de receta.

  • Cada entrada necesita un request-id o un id de receta
  • El request-id es distinto del id de la receta y solo existe durante una única solicitud (no se guarda en el servidor)

Ejemplo de composición con subrecetas​

En la siguiente solicitud, un plato del menú "Fitness Risotto" contiene una sola receta "Mushroom gravy on pumpkin risotto". Esta receta se compone a su vez de dos subrecetas: "pumpkin risotto" y "Mushroom gravy". Todas las recetas van incluidas en el lote.

El plato del menú no es transitorio ("transient": false), así que cuenta en los informes. Las subrecetas son transitorias ("transient": true): se calculan con el menú y solo cuentan a través de él. El indicador va en cada elemento del lote, junto a 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"
}
]
}
}
]

Respuesta, una entrada por receta en el orden de la solicitud:

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

El Eaternity Award es una etiqueta para comidas respetuosas con el clima. Una receta recibe el Eaternity Award cuando obtiene una calificación de CO2 "A".

El campo eaternity-award es un booleano que se devuelve junto con la calificación de CO2:

  • true — la comida es respetuosa con el clima (equivale a una calificación de CO2 "A")
  • false — la comida no cumple los requisitos

Sistema de calificación​

Las recetas reciben una calificación ambiental de A (la mejor) a E (la peor). Umbrales: Escala de calificación.


Ingredientes​

Ingredientes

Cada línea de una receta es un objeto de ingrediente. Campos, valores permitidos, tipos y matching: Ingredientes.


Endpoints​