L'API Nectar donne accès à notre base nutritionnelle et à nos moteurs d'analyse. Huit endpoints, une clé, un seul compteur.
URL de base : https://app.mynectarapp.com/api/public/v1
| Aliments | 10k+, dont 8k+ produits de marque |
| Nutriments par aliment | ~100 |
| Portions ménagères | 24k |
| Produits scannables | 7k+ |
| Couverture du score NOVA | 98 % |
| Tranches d'apports de référence | 772 |
Authentification
Chaque requête porte votre clé dans l'en-tête x-api-key. Les clés commencent par nec_ et vous sont délivrées par votre interlocuteur Nectar. Tous les endpoints sont en POST, avec un corps JSON.
curl -X POST https://app.mynectarapp.com/api/public/v1/food/search \
-H "x-api-key: nec_votre_cle_ici" \
-H "Content-Type: application/json" \
-d '{"search": "pomme"}'
N'exposez jamais votre clé dans du code client — page web, application mobile, dépôt public. Elle appelle l'API en votre nom et consomme votre quota. Passez toujours par votre serveur.
Comprendre les jetons
Un seul compteur pour tout. Chaque appel consomme un nombre de jetons connu à l'avance, rappelé dans la réponse par tokensCharged. Le compteur repart à zéro le 1er de chaque mois.
Le barème
| Appel | Jetons | Ce que vous recevez |
|---|---|---|
food/search | 1 | Jusqu'à 50 aliments : identité, traductions, calories, macronutriments |
portions/convert | 1 | Une portion ménagère convertie en grammes |
nutrition/reference-intakes | 1 | Les apports de référence d'une personne |
food/details/{id} | 1 à 8 | 1 de base, +1 par bloc de nutriments, +1 pour les portions |
food/barcode | 2 | Le produit correspondant au code-barres |
nutrition/compute | 2 + | Le bilan d'un repas. +1 par bloc de nutriments. |
meal/parse | 10 | Un repas décrit en texte, transformé en aliments et quantités |
vision/analyze | 25 | Une photo de repas, transformée en aliments et quantités |
Servir une ligne d'aliment ne nous coûte quasiment rien : les endpoints sur la base et les calculs sont à 1 ou 2 jetons. Une analyse par IA mobilise un modèle à chaque appel : elle coûte 10 ou 25 jetons. C'est la seule raison de l'écart.
Dépassement : deux comportements
Sur la base et les calculs, dépasser votre quota n'interrompt rien. Les requêtes continuent d'aboutir, l'excédent est relevé et fait l'objet d'un échange.
Sur les deux endpoints d'IA, le quota est bloquant. Une fois les jetons épuisés, ils répondent 402 jusqu'à la réinitialisation — et le modèle n'est jamais appelé, donc un appel refusé n'est jamais facturé.
Suivre sa consommation
Chaque réponse porte l'état de votre quota :
X-Token-Quota-Month: 15000
X-Token-Used-Month: 11240
X-Token-Remaining: 3760
Déclenchez votre alerte sur X-Token-Remaining : c'est ce qui vous évite de découvrir un 402 en pleine journée.
Limites de débit
Indépendantes du quota mensuel. 60 requêtes par minute et 1 000 par heure par défaut, ajustables par clé. Au-delà, l'API répond 429 avec les en-têtes X-RateLimit-Limit-Minute et X-RateLimit-Limit-Hour. Prévoyez une reprise avec délai progressif.
Rechercher un aliment
POST /food/search — 1 jeton
Recherche floue et insensible aux accents sur tout le catalogue. Renvoie une liste allégée avec un lien detailsUrl par aliment. Un jeton quel que soit le nombre de résultats.
| Paramètre | Requis | Description |
|---|---|---|
search | Oui | 2 caractères minimum. La correspondance est floue : tommate trouve Tomate. |
type | Non | base (génériques) ou commercial (marques). Les deux par défaut. |
limit | Non | Résultats par page, 50 au maximum et par défaut. |
offset | Non | Résultats à ignorer. 0 par défaut. |
Une recherche renvoie au maximum 50 aliments. Pour atteindre un produit précis, passez par son code-barres ou par le detailsUrl d'un résultat plutôt que par une pagination profonde.
{
"data": [
{
"id": "53bff494-e435-5cfd-b8e4-529668939d5d",
"type": "base",
"label": "Pomme, crue",
"brand": null,
"trueCalories": 52,
"rawCalories": 54,
"translations": { "fr": { "label": "Pomme, crue" }, "en": { "label": "Apple, raw" } },
"nutrients": [],
"detailsUrl": "https://.../food/details/53bff494-..."
}
],
"total": 1,
"limit": 50,
"offset": 0,
"tokensCharged": 1
}
Scanner un code-barres
POST /food/barcode — 2 jetons
Résolution exacte d'un code-barres vers sa fiche Nectar. 7k+ produits du catalogue en portent un. La réponse a exactement la forme d'un résultat de recherche, ce qui permet de partager le même code de traitement.
curl -X POST https://app.mynectarapp.com/api/public/v1/food/barcode \
-H "x-api-key: nec_votre_cle_ici" \
-H "Content-Type: application/json" \
-d '{"barcode": "3017620422003"}'
La recherche porte uniquement sur les produits de marque. Un code-barres absent du catalogue renvoie 404 et n'est pas facturé.
Fiche détaillée
POST /food/details/{id} — 1 à 8 jetons
La fiche complète d'un aliment. Vous ne payez que ce que vous demandez : un jeton pour la base, puis un jeton par bloc de nutriments et un pour les portions.
| Bloc | Contenu | Coût |
|---|---|---|
fatty-acid | Acides gras et lipides, cholestérol inclus | +1 |
vitamin | Vitamines | +1 |
mineral | Minéraux et oligo-éléments | +1 |
amino-acid | Acides aminés essentiels | +1 |
sugar | Sucres et polyols | +1 |
nova | Score de transformation NOVA, de 1 à 4 | +1 |
withPortions: true | Les portions ménagères de l'aliment | +1 |
# Vitamines + minéraux + NOVA + portions = 1 + 3 + 1 = 5 jetons
curl -X POST https://app.mynectarapp.com/api/public/v1/food/details/53bff494-... \
-H "x-api-key: nec_votre_cle_ici" \
-H "Content-Type: application/json" \
-d '{"blocks": ["vitamin", "mineral", "nova"], "withPortions": true}'
Une recherche pour trouver, puis un détail uniquement sur l'aliment réellement retenu par l'utilisateur. Demander tous les blocs sur l'ensemble des résultats d'une recherche multiplie la facture sans bénéfice : la plupart ne seront jamais affichés.
Analyser une photo de repas
POST /vision/analyze — 25 jetons · quota bloquant
Une photo entre, les aliments qu'elle montre sortent — matchés dans la base, avec une estimation de poids. C'est le même moteur que celui qu'utilisent les diététiciennes dans Nectar.
| Paramètre | Requis | Description |
|---|---|---|
photo | Oui | Data URL en base64. JPEG, PNG, GIF ou WebP, jusqu'à 10 Mo décodés. |
note | Non | Ce qu'était le repas, en texte libre, 500 caractères maximum. |
La note fait autorité sur la photo. Contre-intuitif mais vérifié : une photo ne distingue pas la semoule du boulgour, le veau du porc, ni un yaourt à 0 % d'un yaourt entier. Quand la note nomme un aliment, elle est suivie. La photo reste seule maîtresse de ce qu'elle seule peut donner : les quantités, les aliments oubliés et le mode de cuisson.
{
"data": {
"dish": { "query": "pad thaï", "confidence": 0.92, "grams": 320, "candidates": [] },
"foods": [
{
"query": "filet de saumon",
"grams": 120,
"unitCount": 0,
"confidence": 0.9,
"needsReview": false,
"candidates": []
}
],
"suggestions": [{ "query": "huile d'olive", "reason": "Aspect brillant", "grams": 10 }],
"cookingMethod": "grill"
},
"tokensCharged": 25
}
| Champ | À quoi il sert |
|---|---|
dish | Le plat entier, quand le modèle reconnaît une recette que nous avons. Permet d'enregistrer un repas en une étape au lieu de confirmer sept ingrédients. null est le cas normal. |
foods[].grams | Le poids à enregistrer. Pas toujours l'estimation brute du modèle : un aliment compté à l'unité est pesé par notre portion. |
foods[].unitCount | Unités entières comptées. 0 pour tout ce qui se mesure en vrac. |
needsReview | true en dessous de 0,7 de confiance. À faire confirmer. |
suggestions | Ingrédients que la photo implique sans les montrer : huile, beurre, sel. Proposés avec une raison, jamais ajoutés d'office. Un même aliment peut y figurer deux fois, pour deux raisons différentes. |
Faites confirmer avant d'enregistrer. Chaque aliment arrive avec une confiance et jusqu'à trois candidats précisément pour qu'un humain corrige le choix. C'est ainsi que la fonctionnalité est utilisée dans Nectar.
Aucune photo n'est conservée. L'image est analysée puis écartée, jamais écrite sur nos disques. Seul le résultat vous est renvoyé.
Analyser un repas écrit
POST /meal/parse — 10 jetons · quota bloquant
« 2 œufs et 150 g de riz » devient la même liste structurée qu'une photo. À utiliser partout où vos utilisateurs écrivent plutôt qu'ils ne photographient : un champ de saisie rapide, une transcription vocale, un agent conversationnel.
| Paramètre | Requis | Description |
|---|---|---|
text | Oui | Le repas en texte libre, 1 000 caractères maximum. Le français donne les meilleurs résultats. |
Réponse de forme identique à celle de la photo — un seul analyseur pour les deux endpoints.
Une quantité énoncée fait foi. C'est la seule différence de comportement avec la photo, et elle compte si vous comparez les résultats. 150 g de riz renvoie 150 g, sans réestimation. deux œufs renvoie 2 unités, et les grammes viennent de notre portion. une cuillère à soupe d'huile est convertie. Sans quantité, la portion est standard et la confiance baisse.
curl -X POST https://app.mynectarapp.com/api/public/v1/meal/parse \
-H "x-api-key: nec_votre_cle_ici" \
-H "Content-Type: application/json" \
-d '{"text": "2 œufs brouillés et 150 g de riz complet"}'
Bilan d'un repas
POST /nutrition/compute — 2 jetons + 1 par bloc
Une liste d'aliments et de poids, le bilan nutritionnel complet. Les mêmes blocs que la fiche détaillée s'appliquent, au même tarif.
{
"items": [
{ "foodId": "53bff494-...", "grams": 150 },
{ "foodId": "a7c21e08-...", "grams": 120 }
],
"blocks": ["vitamin"]
}
La réponse porte trois vues du même calcul :
| Champ | Ce que c'est |
|---|---|
total | Ce que le repas délivre réellement. La valeur qu'un journal alimentaire enregistre. |
per100g | La densité du mélange. Ce qu'une étiquette afficherait, et ce qui permet de comparer deux plats. |
items[] | La contribution de chaque aliment, pour un détail ou un recalcul de votre côté. |
totalGrams | Le poids combiné. |
unknownFoodIds | Les identifiants que nous ne portons pas. Le reste est calculé quand même. |
50 aliments au maximum. Si tous les identifiants sont inconnus, l'appel renvoie 404 et n'est pas facturé.
Convertir une portion
POST /portions/convert — 1 jeton
« 1 bol de riz » devient 200 g. Nectar en détient 24k, aliment par aliment — parce qu'un bol de riz et un bol de soupe ne pèsent pas la même chose, et qu'aucune table générique ne peut le dire.
| Paramètre | Requis | Description |
|---|---|---|
foodId | Oui | L'aliment concerné |
label | Non | Le nom de la portion. Insensible à la casse et aux accents, et tolérant au fragment. Omettez-le pour lister toutes les portions. |
quantity | Non | Combien de portions. 1 par défaut. |
La liste complète des portions revient même sur un libellé introuvable, pour que vous puissiez montrer ce que l'aliment propose. L'appel est facturé dans les deux cas : la recherche a eu lieu.
curl -X POST https://app.mynectarapp.com/api/public/v1/portions/convert \
-H "x-api-key: nec_votre_cle_ici" \
-H "Content-Type: application/json" \
-d '{"foodId": "f14b1be0-...", "label": "filet", "quantity": 2}'
Apports de référence
POST /nutrition/reference-intakes — 1 jeton
Combien de chaque nutriment une personne donnée devrait recevoir. C'est ce qui transforme un chiffre en jugement : afficher « 12 mg de fer » ne dit rien, afficher « 150 % de la référence pour une femme de 30 ans » est la fonctionnalité.
| Paramètre | Requis | Valeurs |
|---|---|---|
age | Oui | En années, de 0 à 130 |
gender | Oui | male ou female |
pregnancyStatus | Non | not_pregnant (défaut), pregnant, lactation. Valide uniquement avec female. |
Une recommandation est un intervalle, pas une cible. min est l'apport à atteindre, max le plafond à ne pas dépasser, et l'un des deux peut être null : beaucoup de nutriments ont un plancher sans limite haute connue, quelques-uns l'inverse.
Le statut de grossesse change réellement les valeurs : 23 nutriments diffèrent entre une femme enceinte et non enceinte. La caféine passe de 400 à 200 mg, l'iode de 150 à 220 µg. C'est la même résolution que celle utilisée par l'application Nectar, donc vos chiffres correspondent à ce qu'une diététicienne verrait.
L'objet aliment
| Champ | Description |
|---|---|
id | Identifiant stable, utilisable partout ailleurs |
type | base (générique) ou commercial (marque) |
label | Nom interne de l'aliment |
brand | Marque, pour les produits commerciaux |
trueCalories | Calories réellement métabolisées pour 100 g, selon la formule Nectar |
rawCalories | Calories brutes pour 100 g, méthode Atwater standard |
translations | Libellés français et anglais, indexés par code de langue |
nutrients | Valeurs pour 100 g, avec identifiant USDA, unité et source |
portions | Portions ménagères en grammes, sur la fiche détaillée |
novaScore | Degré de transformation de 1 à 4, si le bloc a été demandé |
Affichez les traductions, pas le libellé.
labelest notre nom interne et sa langue varie d'une fiche à l'autre — une même réponse peut mêler « Purée de pomme de terre » et « Salmon, wild ».translations.frettranslations.ensont renseignées pour tous les aliments : ce sont elles que vos utilisateurs doivent voir.
Deux mesures de calories. trueCalories est la valeur propre à Nectar : elle tient compte de ce que l'organisme absorbe réellement, là où rawCalories propose la mesure calorique brute, selon le calcul standard Atwater. L'écart est net sur les fibres et sur les paramètres d'absorption et de métabolisation (CUD et ADS). Affichez celle qui correspond à ce que vous promettez à vos utilisateurs.
Codes d'erreur
| Code | Signification | Que faire |
|---|---|---|
400 | Paramètre manquant ou invalide | Le message dit lequel |
401 | Clé absente, mal formée ou inconnue | Vérifier l'en-tête et le préfixe nec_ |
402 | Quota épuisé sur un endpoint d'IA | Attendre la réinitialisation ou changer de formule. Non facturé. |
403 | Clé désactivée | Contacter votre interlocuteur Nectar |
404 | Ressource introuvable | Identifiant, code-barres ou aliments inconnus. Non facturé. |
413 | Photo trop volumineuse | Au-delà de 10 Mo décodés |
429 | Limite de débit atteinte | Réessayer avec un délai progressif |
500 | Erreur serveur | Réessayer ; nous signaler si cela persiste |
Version 1 de l'API. Toute évolution incompatible fera l'objet d'un préavis et d'une nouvelle version ; la v1 restera servie.
Dernière mise à jour : 11 septembre 2026