---
name: log-food
description: Log a meal to the user's Eat My Words food diary from a natural-language description and return calorie and macronutrient totals.
---

# log-food

Log food to a user's Eat My Words diary using a plain-English description (e.g. "two eggs scrambled with butter and a slice of sourdough"). The server's nutrition model parses the description into one or more food items, persists them to the diary, and returns calories plus macros for each item.

## When to use

- The user describes something they ate or drank and wants it tracked.
- The user wants to know the calories or macros of a meal *and* is OK with logging it.

Skip if the user only wants a hypothetical estimate without saving — there is no estimate-only mode today.

## Endpoint

```
POST https://words.my/nutrition/process-text/
```

Headers:

| Header | Value |
| --- | --- |
| `Authorization` | `Api-Key <USER_KEY>` |
| `Content-Type` | `application/json` |

Body:

```json
{
  "text": "two eggs scrambled with butter and a slice of sourdough",
  "browser_timezone": "America/Toronto",
  "browser_timestamp": "2026-05-06T12:30:00Z"
}
```

| Field | Required | Notes |
| --- | --- | --- |
| `text` | yes | Plain-English description of one or more foods. Quantities and units welcome. |
| `browser_timezone` | no | IANA name. Sets the local time the entry is filed under. Falls back to the user's profile timezone, then UTC. |
| `browser_timestamp` | no | ISO-8601 UTC timestamp. Defaults to server time. |

## Response

Success (HTTP 200):

```json
{
  "success": true,
  "text": "two eggs scrambled with butter and a slice of sourdough",
  "food_items": [
    {
      "food_name": "scrambled eggs",
      "quantity": 100,
      "calories": 196,
      "carbohydrates": 1.5,
      "proteins": 13.0,
      "fats": 14.0,
      "fiber": 0,
      "sugars": 1,
      "sodium": 175,
      "water": 70,
      "alcohol": 0,
      "timestamp": "2026-05-06T08:30:00-04:00"
    }
  ],
  "created_ids": [12345]
}
```

Quantities are in grams; macros in grams; calories in kcal; sodium in mg.

Parse failure (HTTP 200, `success: false`):

```json
{
  "success": false,
  "error": "Could not extract nutrition information from your text. Please try again.",
  "text": "..."
}
```

When this happens, ask the user to rephrase with concrete foods and quantities — don't retry the same text.

## How to summarize for the user

After a successful call, condense the response into a short summary. Suggested format:

> Logged: scrambled eggs (100 g) — 196 kcal · 13 P / 1.5 C / 14 F
> Logged: sourdough toast (40 g) — 110 kcal · 4 P / 22 C / 0.5 F
> **Total: 306 kcal · 17 g protein · 23.5 g carbs · 14.5 g fat**

Rules:
- One line per item: name, mass in grams, calories, then `P / C / F` in grams.
- One total line summing `calories`, `proteins`, `carbohydrates`, `fats` across `food_items`.
- Round calories to whole numbers. Round macros to one decimal when below 10 g, whole numbers above.
- Don't surface fields the user didn't ask about (sodium, water, alcohol, fiber, sugars) unless they're relevant to the user's question.

## Authentication

Each user manages their own API keys at `https://words.my/users/profile/`. Keys are scoped to one user and inherit that user's data permissions. Treat them as secrets.

## Errors

| Status | Cause | Recovery |
| --- | --- | --- |
| 401 | Missing or invalid `Authorization` header | Ask the user to create an API key at their profile. |
| 400 | Body is not valid JSON, or `text` field missing | Fix the request body. |
| 200 with `success: false` | Model couldn't parse a food list out of the text | Ask the user for a more concrete description. |
| 5xx | Server error or transient AI outage | Retry once after a short delay; surface the error if it persists. |

## Example — curl

```bash
curl -sS https://words.my/nutrition/process-text/ \
  -H "Authorization: Api-Key $EMW_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"text": "a cup of black coffee and a banana"}'
```

## Related endpoints

- `GET /nutrition/api/food-logs/` — read recent diary entries (filter by `date_filter=today|week|month`).
- `GET /api/schema/` — full OpenAPI schema for every public endpoint.
