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.

Keep your key server-side. Never expose your API key in client-side JavaScript, mobile app bundles, or public repositories. If a key is compromised, rotate it immediately from your dashboard.

POST /v1/analyze

Analyze a recipe's nutritional content. Send natural language ingredients and receive structured nutrient data, confidence scores, and diet/health labels.

POST https://api.nutrientapi.com/v1/analyze

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
  }'
Ingredient tips. Write ingredients the way you'd write them in a recipe. The API handles common abbreviations (tbsp, oz, lb), fractions (1/2, 1/4), and descriptors (diced, steamed, raw). More specific descriptions produce better matches.

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
These 14 nutrients align with the fields required on a US FDA Nutrition Facts label.

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
Calorie ratios use standard conversion factors: protein = 4 kcal/g, carbohydrates = 4 kcal/g, fat = 9 kcal/g.

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
Not a substitute for allergen testing. Health labels are based on USDA food category classifications. They do not account for cross-contamination, trace amounts, or manufacturer-specific formulations. Do not use these labels as medical or allergen guidance.

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:

  • title is a non-empty string
  • ingredients is an array with at least one string
  • servings is 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.

Cache your results. Unlike some competitors, NutrientAPI allows full caching of all API responses with no restrictions. Cache aggressively to reduce API calls and stay within your rate limit.

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.