Produits
Un produit est un article que vous achetez ou vendez sous forme finie : une denrée emballée, un composant prêt à l'emploi que vous achetez, un article du catalogue d'un fournisseur. Sa composition provient généralement de la liste des ingrédients figurant sur l'emballage.
Vous l'enregistrez une fois, sous votre propre id, et vous récupérez son empreinte calculée. Un produit enregistré peut aussi être utilisé dans une recette : référencez-le avec type: "products".
Enregistrer un produit
PUT /products/{id}, avec votre propre id dans l'URL. La réponse contient déjà le calcul terminé : aucune deuxième request n'est nécessaire.
{
"id": "carrot-puree-500g",
"gtin": "00123456789023",
"names": [{"language": "de", "value": "Karottenpüree"}],
"amount": 500,
"unit": "gram",
"producer": "ACME Foods",
"ingredients-declaration": "Karotten, Wasser, Salz",
"nutrient-values": {
"energy-kcal": 35,
"fat-gram": 0.2,
"protein-gram": 0.9,
"carbohydrates-gram": 7.5
}
}
C'est l'ingredients-declaration qui nous indique la composition réelle du produit : incluez-la chaque fois que l'emballage en comporte une. Sans elle, le produit est identifié à partir de son seul nom.
Pour charger un catalogue, utilisez POST /products/batch. Chaque produit est traité séparément et reçoit sa propre entrée dans la réponse : un produit qui ne peut pas être calculé ne bloque pas les autres. Associez les entrées à votre request par product-id, ou par le request-id que vous avez envoyé.
Une fois le chargement effectué, tenez votre copie locale à jour avec GET /products?updated-since : voir Garder vos données à jour.
Garder vos données à jour
Les valeurs que nous calculons ne sont pas figées. Elles s'améliorent avec le temps (un ingrédient est mis en correspondance plus précisément, les données d'arrière-plan sont actualisées) : un produit chargé il y a plusieurs mois peut donc avoir aujourd'hui une meilleure valeur de CO₂.
GET /products renvoie les id de vos produits. Ajoutez updated-since avec la date de votre dernière synchronisation : vous ne recevez alors que ceux qui valent la peine d'être récupérés à nouveau :
GET /products?updated-since=2026-07-01
{
"products": ["carrot-puree-500g", "tomato-sauce-400g"]
}
C'est-à-dire : les produits que vous avez modifiés, ceux qui n'ont jamais été calculés et ceux dont les valeurs ont pu changer parce qu'un élément dont ils dépendent s'est amélioré. Récupérez chacun avec GET /products/{id}. Un produit chargé via POST /products/batch se comporte dans ce flux exactement comme un produit chargé avec un seul PUT.
Un seul espace de noms d'id
Les produits et les ingrédients ordinaires partagent un seul espace de noms d'id : un id appartient soit à un produit, soit à un ingrédient, jamais aux deux à la fois. GET /products/{id} renvoie celui qui le détient, et le champ type indique lequel :
type | Ce qui détient l'id |
|---|---|
products | Un produit. Il ne change que via les endpoints des produits. |
conceptual-ingredients | Un ingrédient ordinaire. Une recette ou une fourniture le définit, et toute recette ou fourniture le modifie. |
Une recette ou une fourniture qui envoie un id modifie l'ingrédient ordinaire correspondant à cet id, jamais un produit. Pour enregistrer un produit sous un id déjà détenu par un ingrédient ordinaire, définissez convert-ingredient-to-product=true.
Propriétés du produit
Propriétés de la request
| Propriété | Type | Obligatoire | Description |
|---|---|---|---|
id | String | Oui | Votre identifiant unique du produit |
names | Array | Oui | Nom du produit sous forme de tableau d'objets de langue : [{"language": "de", "value": "Karottenpüree"}] |
ingredients-declaration | String | Recommandé | Liste des ingrédients telle que déclarée sur l'emballage. Analysée pour déterminer la composition du produit. |
nutrient-values | Object | Recommandé | Valeurs nutritionnelles pour 100 g telles que déclarées sur l'emballage (voir Référence) |
gtin | String | Recommandé | Global Trade Item Number (www.gtin.info) |
amount | Float | Recommandé | Quantité du produit dans l'unité indiquée. Sans elle, l'empreinte porte sur un kilogramme. |
unit | String | Non | Unité : kg, gram ou liter. Valeur par défaut : gram |
producer | String | Recommandé | Le producteur ou la marque du produit |
date | String | Non | Date de production pour les calculs de saisonnalité. Format : YYYY-MM-DD |
origin | String | Recommandé | Lieu de production : adresse postale ou pays |
transport | String | Recommandé | Moyen de transport : air ou ground |
production | String | Recommandé | Mode de production : standard, greenhouse, organic, fair-trade, farm, wild-caught, sustainable-fish |
processing | String | Non | Niveau de transformation : raw, unboned, boned, skinned, beheaded, fillet, cut, boiled, peeled |
conservation | String | Recommandé | Mode de conservation : fresh, frozen, dried, conserved, canned, boiled-down |
packaging | String | Non | Type d'emballage : none, plastic, paper, pet, tin, alu, glas, cardboard, tetra |
Propriétés de la réponse
Le produit est renvoyé sous product, à côté d'un statuscode qui indique s'il a pu être calculé.
| Propriété | Type | Description |
|---|---|---|
statuscode | Integer | 200 lorsque le produit a été calculé. Voir Codes de statut. |
message | String | Explique le statuscode lorsqu'il n'est pas 200 |
product-id | String | L'id du produit auquel appartient cette entrée |
product | Object | Le produit et ses valeurs calculées (ci-dessous) |
| Propriété | Type | Description |
|---|---|---|
id | String | Identifiant du produit |
type | String | products (protégé en écriture) ou conceptual-ingredients (toute recette peut l'écraser) |
names | Array | Noms du produit sous forme de tableau d'objets de langue |
co2-value | Integer | Émissions de CO₂ en grammes de CO₂e pour l'amount indiqué (voir la remarque ci-dessous) |
rating | String | Notation CO₂ (A-E). A est la meilleure, E la moins bonne. |
eaternity-award | Boolean | true si le produit est respectueux du climat |
co2-value-improvement-percentage | Float | Comparaison de l'empreinte carbone de ce produit par food unit avec la moyenne |
co2-value-reduction-value | Float | Grammes de CO₂ économisés par rapport à un produit moyen de même valeur nutritionnelle |
food-unit | Float | Valeur nutritionnelle du produit pour l'amount indiqué |
amount | Float | Quantité du produit, reprise de votre request |
unit | String | Unité de mesure |
gtin | String | Global Trade Item Number |
date | String | Date de production |
ingredients-declaration | String | Le texte original de la liste des ingrédients (lorsque ingredients-declaration=true est défini) |
nutrient-values-estimated-per-specified-amount | Object | Valeurs nutritionnelles estimées par le backend, rapportées à la quantité indiquée (lorsque nutrient-values=true est défini) |
indicators | Object | Indicateurs environnementaux (lorsque indicators=true est défini) |
co2-value et food-unit sont calculés pour l'amount (et l'unit) de votre request : dix fois la quantité donne dix fois l'empreinte. 500 gram et 0.5 kilogram donnent le même résultat. Si vous n'envoyez aucune quantité, l'empreinte porte sur un kilogramme.
Si vous référencez plutôt le produit depuis une recette, c'est l'amount de cette ligne de recette qui le met à l'échelle : l'amount propre au produit n'est pas repris.
Exemple de réponse
{
"statuscode": 200,
"message": "",
"request-id": 0,
"product-id": "carrot-puree-500g",
"product": {
"food-unit": 0.62,
"eaternity-award": true,
"co2-value": 77,
"rating": "A",
"co2-value-improvement-percentage": 84,
"co2-value-reduction-value": 403,
"id": "carrot-puree-500g",
"gtin": "00123456789023",
"names": [{"language": "de", "value": "Karottenpüree"}],
"amount": 500.0,
"unit": "gram",
"producer": "ACME Foods",
"origin": "",
"transport": "",
"production": "",
"processing": "",
"conservation": "",
"packaging": "",
"type": "products"
}
}
Codes de statut
En plus des codes de statut habituels, les produits utilisent :
| Code | Signification | Que faire |
|---|---|---|
| 612 | Le produit référencé n'existe pas | Enregistrez d'abord le produit, puis envoyez la recette |
| 613 | Une écriture qu'un produit n'accepte pas : soit une recette a tenté de définir un ingrédient sous l'id d'un produit, soit l'écriture d'un produit convertirait un ingrédient existant | Référencez le produit avec type: "products" au lieu de le définir. Pour convertir volontairement un ingrédient, ajoutez convert-ingredient-to-product=true. |
Remarque : produits et ingrédients
Un produit et un ingrédient décrivent la même chose : un aliment avec un nom, une quantité et des attributs comme l'origine, la production et la conservation. Ils diffèrent par la façon dont ils sont enregistrés. Un produit est enregistré une fois sous son propre id et ne change que via les endpoints des produits. Un ingrédient est défini dans une recette ou une fourniture.
Endpoints
📄️ List products
Returns the ids of all products stored for your account.
📄️ Create or update a batch of products
Create or update many products in a single request - the recommended way to upload a product
📄️ Create or update a product
Create or update a single product. The response already contains the finished calculation, so
📄️ Get a product
Retrieve a product together with its calculated values.
📄️ Delete a product
Delete a product. Like the read, this also resolves an ordinary ingredient stored under this