Skip to content
opis.Nutrition API

Standalone nutrition estimates

Already know what was eaten? A nutrition estimate (nue_…) runs only the nutrition capability: items and amounts in, 53 nutrients per item and per meal out, with the matched food and its source. Use it for text or voice logging, your own recogniser, or manual entry.

It is the same nutrition stage that runs inside a meal analysis, billed on the nutrition meter.

Create

HTTP
POST /v1/nutrition-estimates
curl https://platform.opis.health/v1/nutrition-estimates \
  -H "Authorization: Bearer $OPIS_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Prefer: wait=10" \
  -d '{
        "locale": "en-GB",
        "external_id": "diary-entry-981",
        "items": [
          { "name": "porridge with semi-skimmed milk", "grams": 250 },
          { "name": "banana", "quantity_text": "1 medium" },
          { "name": "flat white", "volume_ml": 240, "item_type": "drink" }
        ]
      }'

Most estimates finish in 3–10 seconds, so a Prefer: wait of 10–25 seconds usually returns the result directly (200, Preference-Applied: wait). Otherwise you get 202 and continue as with any async workflow.

Items

Send 1–30 items. Each has a name and, ideally, an amount:

FieldNotes
nameRequired. 1–200 characters, written as a person would (porridge with semi-skimmed milk). Treated as data, never as instructions.
grams0.1–5000. The most precise option; wins when sent together with quantity_text.
quantity_textFree text such as 1 medium, 2 slices, 250 ml. English locales only.
volume_ml0–5000, for drinks and other liquids.
item_typefood, drink, supplement, condiment or unknown. Helps matching drinks and condiments.

With neither grams nor quantity_text, a standard portion or a category default is used and the result is flagged portion_defaulted.

Each result item has origin: "provided" and a portion_source of provided, quantity_parsed, standard_portion or category_default.

Locales

locale defaults to en-GB. The quantity_text parser understands English only: with a non-English locale, items that have quantity_text but no grams are refused with 422 quantity_text_unsupported_locale. Send grams for those items instead.

Things to know

  • Unresolvable names are kept: the item gets match.source: "none", all nutrients null, and the result is flagged item_unresolved. Its grams still count for the meal.
  • Branded products (for example a supermarket ready meal) are matched to the closest generic food and marked match.approximate: true. Barcode lookup is not part of v1.
  • No images, no cross-check. The image cross-check only applies to meal analyses.
  • Nutrients are portion totals at the item's grams, null when not measured. See Nutrients.

Other operations

OperationEndpoint
GetGET /v1/nutrition-estimates/{id}
ListGET /v1/nutrition-estimates
CancelPOST /v1/nutrition-estimates/{id}/cancel
Delete (erase)DELETE /v1/nutrition-estimates/{id}

Webhooks: nutrition_estimate.succeeded and nutrition_estimate.failed.