API Reference
Complete reference for the NutrientAPI recipe analysis endpoint. One endpoint handles parsing, matching, nutrient calculation, and label classification.
Base URL
https://api.nutrientapi.com
All requests must use HTTPS.
Authentication
Authenticate every request with a Bearer token in the Authorization header.
Authorization: Bearer YOUR_API_KEY
Get your API key by signing up at nutrientapi.com. The free tier includes 100 recipes per month.
POST /v1/analyze
Analyze a recipe's nutritional content. Send natural language ingredients and receive structured nutrient data, confidence scores, and diet/health labels.
Request headers
| Header | Value | Required |
|---|---|---|
Authorization |
Bearer YOUR_API_KEY |
Yes |
Content-Type |
application/json |
Yes |
Request body
| Field | Type | Required | Description |
|---|---|---|---|
title |
string | Yes | Recipe title. Provides context for ingredient disambiguation (e.g., "salsa" in a Mexican recipe vs. a pasta recipe). |
ingredients |
string[] | Yes | Array of ingredient strings in natural language. Each string should describe one ingredient with a quantity, unit, and food name. |
servings |
integer | Yes | Number of servings the recipe yields. Used to calculate per_serving values. Must be 1 or greater. |
Example request
curl https://api.nutrientapi.com/v1/analyze \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"title": "Greek Salad",
"ingredients": [
"2 cups chopped romaine lettuce",
"1 medium tomato, diced",
"1/2 cup sliced cucumber",
"1/4 cup crumbled feta cheese",
"2 tbsp extra virgin olive oil",
"1 tbsp red wine vinegar"
],
"servings": 1
}'
Response body
| Field | Type | Description |
|---|---|---|
status |
string | "success" or "quality_check_failed". A quality check failure means one or more ingredients had confidence scores below the minimum threshold. |
ingredients |
object[] | Per-ingredient breakdown. See ingredient object below. |
totals |
object | Summed nutrients for the full recipe. Contains all 14 nutrients. |
per_serving |
object | Nutrients divided by the servings count. Contains all 14 nutrients. |
diet_labels |
string[] | Diet classifications based on macronutrient ratios. See diet labels. |
health_labels |
string[] | Health classifications based on ingredient categories. See health labels. |
Ingredient object
Each entry in the ingredients array contains the following:
| Field | Type | Description |
|---|---|---|
text |
string | The original ingredient string you sent. |
parsed.qty |
number | Extracted quantity (e.g., 2 from "2 cups flour"). |
parsed.unit |
string | Extracted unit (e.g., "cup" from "2 cups flour"). |
parsed.food |
string | Matched USDA food description. |
parsed.gram_weight |
number | Final weight in grams after unit conversion. |
confidence.match |
number | Food matching confidence (0–1). See confidence scores. |
confidence.conversion |
number | Unit conversion confidence (0–1). See confidence scores. |
confidence.overall |
number | Combined confidence: match * conversion. |
nutrients |
object | Calculated nutrients for this ingredient. Contains all 14 nutrients. |
Example response
{
"status": "success",
"ingredients": [
{
"text": "2 cups chopped romaine lettuce",
"parsed": {
"qty": 2,
"unit": "cup",
"food": "Lettuce, cos or romaine, raw",
"gram_weight": 94.0
},
"confidence": {
"match": 0.95,
"conversion": 1.0,
"overall": 0.95
},
"nutrients": {
"calories": 15.98,
"protein": 1.15,
"fat_total": 0.28,
"fat_saturated": 0.04,
"fat_trans": 0.0,
"cholesterol": 0.0,
"sodium": 7.52,
"carbs_total": 3.1,
"carbs_sugar": 1.17,
"carbs_fiber": 1.97,
"vitamin_d": 0.0,
"calcium": 30.08,
"iron": 0.87,
"potassium": 229.36
}
},
{
"text": "1/4 cup crumbled feta cheese",
"parsed": {
"qty": 0.25,
"unit": "cup",
"food": "Cheese, feta",
"gram_weight": 37.5
},
"confidence": {
"match": 0.96,
"conversion": 1.0,
"overall": 0.96
},
"nutrients": {
"calories": 99.0,
"protein": 5.36,
"fat_total": 8.03,
// ...
}
}
// ... remaining ingredients
],
"totals": {
"calories": 382.4,
"protein": 8.92,
"fat_total": 34.6,
"fat_saturated": 7.82,
"fat_trans": 0.0,
"cholesterol": 25.13,
"sodium": 422.8,
"carbs_total": 12.4,
"carbs_sugar": 6.12,
"carbs_fiber": 3.8,
"vitamin_d": 0.19,
"calcium": 228.5,
"iron": 1.94,
"potassium": 512.3
},
"per_serving": {
"calories": 382.4,
"protein": 8.92,
"fat_total": 34.6,
// ... same as totals when servings=1
},
"diet_labels": ["low-carb"],
"health_labels": ["vegetarian", "gluten-free"]
}
Nutrients
Every nutrient object (totals, per_serving, and each ingredient's nutrients) contains these 14 fields. All values are calculated from USDA FoodData Central data stored per 100g and scaled to the ingredient's gram weight.
| Field | Unit | Description |
|---|---|---|
calories |
kcal | Energy |
protein |
g | Total protein |
fat_total |
g | Total fat |
fat_saturated |
g | Saturated fat |
fat_trans |
g | Trans fat |
cholesterol |
mg | Cholesterol |
sodium |
mg | Sodium |
carbs_total |
g | Total carbohydrates |
carbs_sugar |
g | Total sugars |
carbs_fiber |
g | Dietary fiber |
vitamin_d |
mcg | Vitamin D |
calcium |
mg | Calcium |
iron |
mg | Iron |
potassium |
mg | Potassium |
Confidence scores
Every ingredient in the response includes three confidence scores between 0 and 1. These scores let you decide programmatically whether to trust the result, flag it for manual review, or reject it.
match
How confident the system is that it found the correct USDA food for the ingredient text. This score comes from the AI matching step.
- 0.90–1.0 — High confidence. The text closely matches a specific USDA food (e.g., "chicken breast" → "Chicken, broilers or fryers, breast, meat only, raw").
- 0.70–0.89 — Moderate confidence. The match is reasonable but there may be ambiguity (e.g., "salsa" could be many products).
- Below 0.70 — Low confidence. The ingredient may be unusual, brand-specific, or too vague for a reliable match.
conversion
How confident the system is in the gram weight conversion. This score is deterministic — it reflects the quality of the available portion data, not AI judgment.
- 1.0 — The input was already in grams, or a USDA portion record provided an exact conversion (e.g., "1 large egg" has a USDA-defined gram weight).
- 0.80–0.99 — A close portion match was used (e.g., the USDA has "1 cup, chopped" and the input was "1 cup").
- Below 0.80 — The conversion required estimation (e.g., no USDA portion data exists for the unit used).
overall
The product of match and conversion. This single number captures the end-to-end reliability of the nutrient calculation for that ingredient.
overall = match * conversion
Use overall as your primary threshold when deciding whether to accept or review a result. A common approach:
// Accept results above 0.8, flag others for review
if (ingredient.confidence.overall >= 0.8) {
// Use the nutrients directly
} else {
// Flag for manual review or show a warning
}
quality_check_failed status
When the API returns "status": "quality_check_failed", it means one or more ingredients fell below the internal quality threshold. The response still includes all data so you can inspect what went wrong, but the results should not be presented to users as reliable.
Diet and health labels
Diet labels
Diet labels are calculated from the per-serving macronutrient calorie ratios. A recipe can have multiple diet labels or none.
| Label | Criteria |
|---|---|
high-protein |
Protein provides ≥ 25% of total calories |
low-carb |
Carbohydrates provide ≤ 20% of total calories |
low-fat |
Fat provides ≤ 15% of total calories |
balanced |
Protein 15–25%, carbohydrates 40–60% of total calories |
Health labels
Health labels are determined by the USDA food categories of the matched ingredients. They indicate the absence of specific ingredient types, not a threshold-based calculation.
| Label | Criteria |
|---|---|
vegan |
No animal-derived ingredients (no meat, poultry, fish, dairy, eggs, or honey) |
vegetarian |
No meat, poultry, or fish (dairy and eggs are allowed) |
gluten-free |
No wheat, barley, rye, or other gluten-containing grain categories |
dairy-free |
No milk, cheese, yogurt, butter, or other dairy category ingredients |
Errors
The API uses standard HTTP status codes. Error responses include a JSON body with a message field describing the problem.
| Status | Meaning | Common causes |
|---|---|---|
401 |
Unauthorized | Missing or invalid API key. |
422 |
Unprocessable Entity | Validation error: missing required fields, empty ingredients array, or servings less than 1. |
429 |
Too Many Requests | Rate limit exceeded. See rate limits. |
503 |
Service Unavailable | The AI parsing service is temporarily unavailable. Retry after a brief delay. |
Error response format
{
"status": "error",
"message": "Ingredients must be a non-empty array of strings"
}
Handling 422 errors
A 422 response means your request was well-formed JSON but failed validation. Check that:
titleis a non-empty stringingredientsis an array with at least one stringservingsis an integer of 1 or greater
Handling 503 errors
A 503 response means the AI service used for ingredient parsing is temporarily unavailable. This is rare but can occur during upstream provider outages. Implement exponential backoff and retry:
# Retry with exponential backoff
max_retries = 3
retries = 0
while retries < max_retries
response = make_request()
break unless response.status == 503
sleep(2 ** retries) # 1s, 2s, 4s
retries += 1
end
Rate limits
Rate limits are applied per API key based on your plan tier. Limits are measured in requests per second.
| Plan | Requests/second | Recipes/month |
|---|---|---|
| Free | 3 | 100 |
| Developer | 10 | 2,500 |
| Startup | 25 | 10,000 |
| Scale | 50 | 50,000 |
When you exceed the rate limit, the API returns a 429 Too Many Requests response. Wait and retry — the limit resets every second.
Data source
All nutrient data comes from the USDA FoodData Central database, which includes over 2 million food items across four datasets:
- SR Legacy — The classic USDA nutrient database with ~7,800 common foods
- Foundation — Enhanced analytical data for ~2,400 foods
- FNDDS — Survey foods with portion weight data (~8,500 items)
- Branded — Manufacturer-reported data for packaged foods (~2M items)
Nutrient values are stored per 100g and scaled proportionally to the matched portion weight. Unit conversions use USDA's own portion data (gram weights per described portion) rather than generic conversion tables.