---
search:
  tags:
    - Nutrition
    - POST
seo:
  description: >-
    Uploads 1–5 photos of a single meal, sends them to Claude vision for
    per-item… Reference for the POST /api/nutrition/analyze endpoint in the
    skcal API.
sidebar:
  label: Log a meal from photos
  badge: POST
title: Log a meal from photos
type: openapi-operation
---
Uploads 1–5 photos of a single meal, sends them to Claude vision for per-item calorie and protein estimates, stores the photos plus a meal, and returns the analysis.

`POST /api/nutrition/analyze`

**Request body** (`multipart/form-data`, required)

The meal photos (multipart field \`photos\`), plus an optional \`note\` caption for context.

- `photos` (string<binary>[], required) — 1–5 photos of a single meal, possibly from multiple angles (JPEG, PNG, WebP, or GIF; max 8MB each).
- `note` (string) — Optional caption to disambiguate the photo; passed to the model and stored as the meal note.

Request body example:

```json
{
  "photos": [
    "@plate.jpg",
    "@plate-side.jpg"
  ],
  "note": "the white sauce is toum, and that's a 12oz steak"
}
```

**Responses**

- `200` — The meal was analyzed and logged.
- `400` — The request body or parameters failed validation.
- `502` — The upstream model call failed.
- `503` — A required secret (model key or ingest token) is not configured.

Response example, 200:

```json
{
  "ok": true,
  "mealId": "3f8b1c2a-5d6e-4f70-8a1b-2c3d4e5f6071",
  "items": [
    {
      "name": "grilled chicken breast",
      "kcal": 284,
      "proteinG": 53.4
    },
    {
      "name": "toum",
      "kcal": 90,
      "proteinG": 0.4
    }
  ],
  "totalKcal": 374,
  "totalProteinG": 54,
  "note": "assumed a single chicken breast and one tablespoon of toum",
  "photoKeys": [
    "nick@mintlify.com/2026-06-29/3f8b1c2a-5d6e-4f70-8a1b-2c3d4e5f6071"
  ]
}
```
