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
POST /v1/nutrition-estimatescurl 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:
| Field | Notes |
|---|---|
name | Required. 1–200 characters, written as a person would (porridge with semi-skimmed milk). Treated as data, never as instructions. |
grams | 0.1–5000. The most precise option; wins when sent together with quantity_text. |
quantity_text | Free text such as 1 medium, 2 slices, 250 ml. English locales only. |
volume_ml | 0–5000, for drinks and other liquids. |
item_type | food, 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 nutrientsnull, and the result is flaggeditem_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,
nullwhen not measured. See Nutrients.
Other operations
| Operation | Endpoint |
|---|---|
| Get | GET /v1/nutrition-estimates/{id} |
| List | GET /v1/nutrition-estimates |
| Cancel | POST /v1/nutrition-estimates/{id}/cancel |
| Delete (erase) | DELETE /v1/nutrition-estimates/{id} |
Webhooks: nutrition_estimate.succeeded and nutrition_estimate.failed.