Forfait Free

API de base de données alimentaire

Une source unique pour 6,1 millions d'aliments. Récupérez une fiche produit complète par ID — nom, marque, ingrédients, allergènes, Nutri-Score, groupe NOVA, images, et plus encore.

200 OK
GET /v1/foods/{id}
curl -H "X-API-Key: food_•••" \
  "https://foodbase.dev/v1/foods/62ea12b8-b260-c288-5c38-3a4906f5d6dd"

{
  "id": "62ea12b8-b260-c288-5c38-3a4906f5d6dd",
  "name_default": "Original Taste",
  "brand": "Coca-Cola",
  "category": "...,Carbonated drinks,Sodas,Colas",
  "ingredients_default": "carbonated water, sugar, ...",
  "allergens": null,
  "nutriscore": "e",
  "nova_group": 4,
  "image_url": "https://images..."
}

Vous préférez cliquer ? Essayez l'explorateur de produits ou le bac à sable photo.

Ce que vous obtenez

Identité

id, barcode, source, name, brand, category.

Ingrédients

Texte complet des ingrédients plus allergènes et traces structurés.

Scores

Nutri-Score, groupe NOVA et Eco-Score quand ils sont disponibles.

Médias et langues

URL de l'image du produit et noms multilingues.

Un seul schéma

Chaque produit normalisé dans une forme cohérente.

Inclus dans le forfait gratuit — 100 requêtes/jour, sans carte bancaire. Voir les forfaits →

Exemples de code

La même requête en curl, JavaScript et Python. Remplacez YOUR_API_KEY par une clé de votre tableau de bord.


              curl "https://foodbase.dev/v1/foods/62ea12b8-b260-c288-5c38-3a4906f5d6dd?lang=fr" \
  -H "X-API-Key: YOUR_API_KEY"
            

Comment ça marche

Ce que fait une requête

GET /v1/foods/{id} prend l'UUID obtenu par une recherche ou une recherche par code-barres et renvoie toute la fiche normalisée. Pas de sélection de champs ni de pagination : la fiche de 62ea12b8-b260-c288-5c38-3a4906f5d6dd (code-barres 5449000000996, source openfoodfacts) revient avec toutes les clés du schéma 200, et ce qui manque à la source vaut null au lieu d'être omis.

Authentifiez-vous avec l'en-tête X-API-Key. La seule entrée facultative est ?lang=, parmi en, fr, es, de, it ou bg. Elle ajoute category_localized, category_segments_localized et allergens_localized et ne touche à aucune autre clé : ajouter lang plus tard ne casse donc jamais un parseur existant. Chaque réponse porte aussi un en-tête X-Request-Id à citer dans vos demandes de support.

Noms, ingrédients et entrée principale

name et ingredients sont des tableaux de {lang, text}. La première entrée a lang main et reprend name_default et ingredients_default ; product_lang vous indique quelle langue réelle c'est. Sur la fiche Coca-Cola, le nom principal est Original Taste, l'entrée fr est Coca-Cola en canette et l'entrée bg est Кока-Кола. Choisissez l'entrée correspondant à la langue de votre interface et repliez-vous sur name_default.

Attendez-vous à ce que ingredients soit plus long que le nombre de langues : Open Food Facts stocke le texte des ingrédients par variante d'emballage, si bien qu'une même lang peut apparaître plusieurs fois sur une fiche, souvent avec un texte identique, comme ici. Dédoublonnez sur lang et gardez la première occurrence. Le texte est saisi par les contributeurs et renvoyé tel quel ; l'entrée ar contient ici des fragments d'étiquette qui ne sont pas des ingrédients : validez-le avant de le transformer en structures.

Catégorie, tags, allergènes et lang

category est une chaîne unique jointe par des virgules, du général au précis : Beverages and beverages preparations,Beverages,Carbonated drinks,Sodas,Colas,pt:bebidas cafeína. Découpez sur la virgule ; le dernier niveau est le plus précis. categories_tags contient les mêmes niveaux sous forme de tags machine (en:beverages, en:carbonated-drinks, en:colas) et c'est la valeur stable sur laquelle filtrer ou regrouper, car la chaîne d'affichage change quand des contributeurs modifient le produit.

allergens et traces utilisent les mêmes tags de style en:milk, tout comme countries (en:albania, en:austria, en:belgium) et labels. null signifie que la source n'a rien indiqué, pas que le produit est sans allergènes ; cette fiche a allergens: null et traces: null, donc un avertissement allergie doit afficher inconnu, pas aucun.

Avec ?lang=bg, l'API ajoute category_localized en une chaîne traduite, category_segments_localized avec une entrée par niveau de hiérarchie, et allergens_localized parallèle à allergens. Un niveau ou un tag sans entrée de dictionnaire vaut null dans le tableau : gardez l'index aligné sur categories_tags ou allergens et repliez-vous sur le tag anglais pour les cases null.

Scores, portion et nutriments résumés

nutriscore est une lettre minuscule (e ici), nova_group un nombre (4) et ecoscore_grade une chaîne qui peut être une lettre ou une valeur sentinelle comme not-applicable, ce que renvoie cette boisson. Traitez les trois comme pouvant être null et n'associez pas not-applicable à une couleur.

serving_size_raw et quantity sont du texte libre copié depuis l'étiquette. serving_size_raw indique 1 can (330 ml) et convient à l'affichage ; quantity indique 0kg sur cette fiche, une erreur de contributeur : ne calculez jamais le poids de l'emballage à partir de ce champ sans contrôle de cohérence.

nutrition_summary donne six valeurs pour 100 g : energy_kcal, proteins_g, carbs_g, fat_g, sugars_g et fiber_g. Chacune peut être null séparément et l'objet peut être null quand la source n'a pas de tableau nutritionnel. Il suffit pour une ligne de liste ou une comparaison rapide ; les 40+ nutriments complets sont sur l'API de nutrition à /v1/foods/{id}/nutrients avec le même id.

Id stables, cache et flux habituel

L'id est déterministe, dérivé de la source et de l'identifiant produit propre à la source : le même produit obtient le même UUID à chaque réimportation. Stockez les id dans vos propres tables et récupérez-les à nouveau des mois plus tard sans étape de remappage. barcode peut être null dans le schéma : préférez l'id au code-barres comme clé de jointure.

Un 200 porte Cache-Control: public, max-age=300 et un 404 max-age=60 : un CDN ou un cache HTTP devant votre service les respecte sans configuration. Si vous mettez en cache dans votre propre base, indexez sur id plus lang, car les clés localisées diffèrent selon la langue.

Le flux habituel : obtenez un id avec l'API de recherche alimentaire ou l'API de recherche par code-barres, stockez-le, et appelez cet endpoint quand une vue de détail a besoin de la fiche complète. Pour rafraîchir de nombreux id stockés à la fois, l'API de consultation groupée d'aliments accepte une liste en une requête à partir de Starter. Les images sont des photos de contributeurs Open Food Facts hébergées sur images.openfoodfacts.org et les fiches d'autres sources peuvent ne pas en avoir : affichez une image par défaut chaque fois que image_url vaut null.

Ce que vous pouvez créer

Pages produit

Affichez une page alimentaire riche à partir d'une seule fiche canonique.

Pipelines d'enrichissement

Complétez votre catalogue avec ingrédients, allergènes et scores.

Recherche et analyse

Travaillez sur une vue propre et normalisée de deux jeux de données publics.

Limites par forfait

Free 100 requêtes/jour, 1/s en continu, rafale de 5
Starter 5 000 requêtes/jour, 5/s en continu, rafale de 25
Pro 25 000 requêtes/jour, 20/s en continu, rafale de 100
Enterprise 100 000 requêtes/jour, 50/s en continu, rafale de 250

Chaque réponse contient des en-têtes X-RateLimit-* indiquant le budget restant ; chaque 429 contient Retry-After . Comparer les forfaits →

Erreurs et comment les gérer

401 — L'en-tête X-API-Key est absent ou la clé n'est pas valide.

Envoyez une clé active de votre tableau de bord ; le corps est {error, message} comme pour toutes les autres erreurs.

404 — L'id est un UUID bien formé mais aucun produit ne le porte.

Retirez l'id de votre stockage ; le 404 peut être mis en cache 60 secondes, ne réessayez donc pas en boucle.

422 — L'id du chemin n'est pas un UUID (par exemple un code-barres ou un slug).

Résolvez les codes-barres via l'API de recherche par code-barres et ne passez ici que des UUID.

429 — La clé a dépassé sa rafale par seconde ou le compte a épuisé son quota quotidien.

Attendez les secondes indiquées dans Retry-After, puis reprenez ; surveillez X-RateLimit-Second-Remaining et X-RateLimit-Daily-Remaining pour ralentir plus tôt.

Comparaison avec d'autres API

La plupart des API de données alimentaires vous livrent soit un dump brut d'Open Food Facts, soit une fiche uniquement USDA, chacune dans sa propre forme. FoodBase renvoie les deux sources dans un seul schéma : un produit openfoodfacts et un produit USDA partagent les mêmes clés et les mêmes règles de nullabilité, et vous écrivez un seul parseur. Les id sont déterministes plutôt que des numéros de ligne, ils survivent donc aux réimportations, et la fiche inclut déjà les tags de catégorie, les tags d'allergènes et six nutriments résumés. La contrepartie : c'est une vue normalisée, pas l'éditeur en amont. Les erreurs de contributeurs comme une quantity de 0kg arrivent telles quelles, et le tableau nutritionnel complet se trouve sur l'API de nutrition plutôt que dans cette réponse.

Voir la comparaison complète des API de données alimentaires →

Questions fréquentes

Où obtenir un id à passer à cet endpoint ? +

Chaque résultat de l'API de recherche alimentaire et chaque fiche de l'API de recherche par code-barres contient l'id. Il est dérivé de la source et de son identifiant produit : stockez-le une fois et réutilisez-le d'une importation à l'autre.

Pourquoi name est-il un tableau, et que signifie lang main ? +

Les produits portent des noms en plusieurs langues, donc name liste des paires {lang, text}. L'entrée avec lang main reprend name_default et correspond au texte principal de la source ; choisissez l'entrée qui correspond à la langue de votre interface et repliez-vous sur name_default.

Que change ?lang= ? +

Il ajoute category_localized, category_segments_localized et allergens_localized pour en, fr, es, de, it ou bg. Rien d'autre ne change dans la fiche, et tout tag sans traduction vaut null dans ces champs.

allergens: null signifie-t-il que le produit n'a pas d'allergènes ? +

Non. null signifie que la source n'a enregistré aucune donnée d'allergènes : affichez un état inconnu plutôt qu'une mention rassurante. Seul un tableau non vide est une information positive, et même alors il reflète ce que les contributeurs ont transcrit depuis l'emballage.

Les nutriments de cette réponse sont-ils le tableau complet ? +

Non. nutrition_summary contient energy_kcal, proteins_g, carbs_g, fat_g, sugars_g et fiber_g pour 100 g ; l'ensemble des 40+ nutriments est servi par l'API de nutrition à /v1/foods/{id}/nutrients avec le même id.

Puis-je mettre la fiche en cache de mon côté ? +

Oui. Un 200 est marqué Cache-Control: public, max-age=300 et un 404 max-age=60 : n'importe quel cache HTTP ou CDN peut les conserver ; pour un stockage plus long, indexez la fiche par id et lang et rafraîchissez-la à votre rythme.

Cet endpoint a-t-il son propre quota ? +

Non. Il puise dans le quota de requêtes ordinaire du forfait, partagé par toutes les clés du compte, tandis que la limite par seconde s'applique à chaque clé. Seule l'API de nutrition a une limite quotidienne séparée sur le forfait Free.

Commencez à développer avec l'API de base de données alimentaire

Gratuit pour démarrer. Sans carte bancaire.

Obtenir une clé API Aller au tableau de bord