Introduction
NutriGraphAPI
Reference
NutriGraphAPI is a REST API returning food intelligence across 5M+ UPC-indexed products. Every response contains two root objects: scraped_data (on-label manufacturer declarations) and analysed_data (AI-qualified intelligence layer). Always build against analysed_data for application logic.
Full payload on the free tier. The Developer plan returns the identical response as paid plans. Every attribute, every score, every flag — from call one. The only limit is volume: 1,000 calls/month.
Base URL: https://barcode-api-140543331861.asia-south1.run.app/api
Authentication: X-API-Key header — request your key
Format: JSON, UTF-8, always
Authentication
Authentication
All requests must include your API key in the X-API-Key header. Keys are issued per legal entity. To request a key, email support@nutrigraphapi.com.
Keep your key private. Do not embed it in client-side code, commit it to public repositories, or expose it in browser network requests. If compromised, contact us immediately for a replacement.
curl -i \
-H "X-API-Key: YOUR_API_KEY" \
"https://barcode-api-140543331861.asia-south1.run.app/api/lookup?barcode=039978009579"
Getting started
Quick-start
Your first call in four languages. All return the identical full payload.
Node.js
const API_KEY = 'YOUR_API_KEY';
const barcode = '039978009579';
const res = await fetch(
`https://barcode-api-140543331861.asia-south1.run.app/api/lookup?barcode=${barcode}`,
{ headers: { 'X-API-Key': API_KEY } }
);
const { analysed_data } = await res.json();
// Access any attribute:
const nova = analysed_data.additionalInfo.nova_group;
const isVegan = analysed_data.additionalInfo.dietary_preference.Vegan;
const gluten = analysed_data.npiFoodPackagesAllergensIntolerances.glutenQualified;
Python
import requests
API_KEY = 'YOUR_API_KEY'
barcode = '039978009579'
resp = requests.get(
'https://barcode-api-140543331861.asia-south1.run.app/api/lookup',
params={'barcode': barcode},
headers={'X-API-Key': API_KEY}
)
data = resp.json()['analysed_data']
nova = data['additionalInfo']['nova_group']
is_vegan = data['additionalInfo']['dietary_preference']['Vegan']
allergens = data['npiFoodPackagesAllergensIntolerances']
clean = data['cleanLabel'] # 30+ fields
Swift
let apiKey = "YOUR_API_KEY"
let barcode = "039978009579"
let url = URL(string: "https://barcode-api-140543331861.asia-south1.run.app/api/lookup?barcode=\(barcode)")!
var request = URLRequest(url: url)
request.setValue(apiKey, forHTTPHeaderField: "X-API-Key")
let (data, _) = try await URLSession.shared.data(for: request)
let product = try JSONDecoder().decode(NutriGraphProduct.self, from: data)
Endpoints
Product lookup
Returns the full intelligence payload for a product identified by UPC-12 barcode. Both scraped_data and analysed_data are returned on every successful response.
Parameters
| Parameter | Type | Required | Description |
| barcode | string | Required | UPC-12 barcode of the product. Leading zeros must be preserved. Example: 039978009579 |
Example request
curl -i \
-H "X-API-Key: YOUR_API_KEY" \
"https://barcode-api-140543331861.asia-south1.run.app/api/lookup?barcode=039978009579"
Example response (condensed)
{
"scraped_data": { /* raw on-label manufacturer data */ },
"analysed_data": {
"generalData": {
"upc12": "039978009579",
"brandName": "Bob's Red Mill",
"category": "Steel Cut Oats",
"numberOfIngredients": 1
},
"additionalInfo": {
"nova_group": "1",
"nutriscore_grade": "B",
"ecoscore": "B",
"dietary_preference": {
"Vegan": true, "Vegetarian": true,
"KetoFriendly": false, "LowFodmap": false
},
"religious_labels": {
"Kosher": true, "Halal": false,
"Jain": false, "Hindu": false
},
"sustainability_labels": {
"PlantBased": true, "Recycled": true
}
},
"npiFoodPackagesAllergensIntolerances": {
"glutenLevelStated": "Gluten-free",
"glutenQualified": "Yes (certified on pack)",
"falcpaCommonAllergensStated": "No",
"additionalInfo": {
"traces": "May be processed in facility with tree nuts"
}
},
"cleanLabel": {
"artificialColorsQualified": "No",
"preservativesQualified": "No",
"gmoPresenceQualified": "Non-GMO",
"recognizableIngredientsQualified": "Yes"
},
"claims": {
"certifications": ["USDA Organic", "Non-GMO Project Verified", "Kosher"]
},
"ingredients": [
{
"name": "Organic Whole Grain Oats",
"allergens": { "Gluten": false, "Peanuts": false },
"dietary_preference": { "Vegan": true },
"religious_labels": { "Kosher": true }
}
]
}
}
Endpoints
Request a product
Submit a UPC that returned 404 for onboarding. Products are typically added within 48 hours. Bulk UPC lists are available on Enterprise plans — contact
support@nutrigraphapi.com.
| Body field | Type | Required | Description |
| barcode | string | Required | The UPC-12 that returned 404 |
| product_name | string | Optional | Helps us onboard faster |
| brand | string | Optional | Brand name |
curl -X POST \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"barcode":"012345678901","product_name":"Example Product","brand":"Example Brand"}' \
"https://barcode-api-140543331861.asia-south1.run.app/api/request"
Response schema
Allergens
Path: analysed_data.npiFoodPackagesAllergensIntolerances
Always use Qualified fields for safety logic. The Stated field reflects what the manufacturer declared on-label. The Qualified field is our AI-verified conclusion. For allergen filtering in your application, always use Qualified.
eggStatedstring— Egg allergen as declared on label
eggQualifiedstring— AI-verified egg allergen status
dairyStated / dairyQualifiedstring pair
glutenLevelStatedstring— e.g. "Gluten-free", "Contains gluten"
glutenQualifiedstring— AI-verified gluten status
fishStated / fishQualifiedstring pair
caseinStated / caseinQualifiedstring pair— Casein tracked separately from dairy
falcpaCommonAllergensStatedstring— FDA Big-9 declaration
fdaRegulatedAllergensstring— FALCPA summary
additionalInfo.tracesstring— May-contain / cross-contamination statement
ingredients[].allergensobject— Per-ingredient allergen tree
Peanuts, Milk, Egg, Wheat, Soy, Fish, Shellfish, Sesame, TreeNutsboolean
Response schema
Clean label
Path: analysed_data.cleanLabel — 30+ fields, each with a Stated (on-label) and Qualified (AI-verified) variant.
artificialColorsStated / artificialColorsQualifiedstring
artificialFlavorsStated / artificialFlavorsQualifiedstring
artificialSweetenersStated / artificialSweetenersQualifiedstring
preservativesStated / preservativesQualifiedstring
gmoPresenceStated / gmoPresenceQualifiedstring— e.g. "Non-GMO Project Verified"
highFructoseCornSyrupStated / highFructoseCornSyrupQualifiedstring
naturalColorsStated / naturalColorsQualifiedstring
sugarAlcoholsStated / sugarAlcoholsQualifiedstring
hormonesStated / antibioticsStatedstring
madeInUsaStatedstring
countOfIngredientsQualifiedstring— e.g. "Low (1 main ingredient)"
recognizableIngredientsQualifiedstring— "Yes" / "No"
Response schema
Dietary & religious
Path: analysed_data.additionalInfo — available at both product level and nested inside each ingredients[] item.
dietary_preferenceobject
Veganboolean
Vegetarianboolean
KetoFriendlyboolean
LowFodmapboolean
Pescatarianboolean
NoRedMeatboolean
religious_labelsobject
Kosherboolean
Halalboolean
Jainboolean
Hinduboolean
Response schema
Nutrition
Path: analysed_data.nutritionalInformation — two sub-objects: stated (from manufacturer) and qualified (AI-backfilled and verified). Per 100g with daily values.
Backfill flag. When qualified.backfillNutrientsProcessed is true, values were AI-enriched rather than sourced directly from a label. Reliable, but surface this distinction in clinical contexts.
stated.macronutrients[]array— Energy, Fat, SatFat, Carbs, Sugars, Fiber, Protein, Sodium
stated.micronutrients[]array— Iron + declared micros
qualified.macronutrients[]array— AI-verified macros + kJ
qualified.micronutrients[]array— Iron, Potassium, VitD, Calcium, VitA, VitC
each nutrient.valuefloat— Per 100g
each nutrient.dailyValuefloat— % Daily Value
each nutrient.sourcestring— Data provenance
servingSize.servingSizefloat— In grams
servingSize.servesPerPackinteger
qualified.backfillNutrientsProcessedboolean
Response schema
Quality scores
Path: analysed_data.additionalInfo and analysed_data.food_safety_labels — six scores returned in every response.
nova_groupstring "1"–"4"— NOVA processing level. 1=unprocessed, 4=ultra-processed
nutriscore_gradestring A–E— Nutri-Score nutritional quality
ecoscorestring A–E— Environmental impact
food_safety_labels.Organicboolean
food_safety_labels.NoGMOboolean
food_safety_labels.Carcinogenicboolean— Known carcinogenic ingredient flag
food_safety_labels.ProductRecallsboolean— Active recall flag
average_customer_ratingfloat— Marketplace rating
Response schema
Sustainability
Path: analysed_data.additionalInfo.sustainability_labels — six flags at product and ingredient level.
PlantBasedboolean
Recycledboolean— Recycled / recyclable packaging
SustainablePackagingboolean
OrganicPositioningboolean
SocialResponsibilityboolean
AnimalWelfareboolean
claims.sustainability.packaging[]string array— On-pack packaging claims
claims.sustainability.environmentalClaims[]string array
Reference
Error codes
All error responses use the same JSON envelope:
{
"error": "PRODUCT_NOT_FOUND",
"upc": "012345678901",
"message": "Submit via POST /api/request",
"request_id": "req_abc123xyz"
}
| Code | Meaning | Action |
| 200 OK | Successful response | Read analysed_data |
| 401 Unauthorized | Missing or invalid API key | Check your X-API-Key header |
| 404 Not Found | UPC not in database | Submit via POST /api/request — onboarded within 48h |
| 429 Too Many Requests | Rate limit exceeded | Wait for quota reset (1st of month for monthly plans) |
| 500 Server Error | Unexpected server error | Retry with exponential backoff. Contact support if persistent. |
Reference
Rate limits
| Plan | Monthly quota | On 429 |
| Developer (free) | 1,000 calls | Returns 429 until month resets |
| Professional | 100,000 calls | Overage billed at plan rate |
| Enterprise | 1,000,000 calls | Overage billed at plan rate |
Quotas reset on the 1st of each calendar month for monthly plans, or on the annual anniversary for annual plans.
Reference
Caching
Product data changes infrequently. We recommend a 24-hour client-side cache keyed on UPC-12 to reduce redundant calls and improve performance. Use the data_last_updated field to selectively invalidate.
const CACHE_TTL = 86400; // 24 hours in seconds
async function getProduct(upc) {
const cacheKey = `nutrigraph:${upc}`;
const cached = await redis.get(cacheKey);
if (cached) return JSON.parse(cached);
const res = await fetch(
`https://barcode-api-140543331861.asia-south1.run.app/api/lookup?barcode=${upc}`,
{ headers: { 'X-API-Key': API_KEY } }
);
const data = await res.json();
await redis.setex(cacheKey, CACHE_TTL, JSON.stringify(data));
return data;
}
Permitted under Terms. Caching API responses for performance is explicitly permitted. The 24-hour window is our recommendation, not a hard limit. See
Section 3 of the Terms for full details.
Reference
Changelog
June 2026 — v1.0
Initial public release. 5M+ products. Full analysed_data layer. Per-ingredient allergen trees. 30+ clean label fields. NovaScore, EcoScore, Nutri-Score. Four religious compliance labels. Six sustainability flags.
Questions or issues? Email support@nutrigraphapi.com — we respond within 24 hours.