---
search:
  tags:
    - Nutrition
    - POST
seo:
  description: >-
    Uploads 1–5 photos, classifies what they show — food, workout evidence
    (machine console,… Reference for the POST /api/log/analyze endpoint in the
    skcal API.
sidebar:
  label: Log a meal or workout from photos
  badge: POST
title: Log a meal or workout from photos
type: openapi-operation
---
Uploads 1–5 photos, classifies what they show — food, workout evidence (machine console, app/watch summary, whiteboard), a scale readout, or a tape-measure/measuring-app reading — and logs the matching entry (meal, workout, weigh-in, or body measurement). Returns the classification in `kind`.

`POST /api/log/analyze`

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

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

- `photos` (string<binary>[], required) — 1–5 photos of one meal or one workout (JPEG, PNG, WebP, or GIF; max 8MB each).
- `note` (string) — Optional caption; trusted over the pixels when they disagree.

Request body example:

```json
{
  "photos": [
    "@treadmill.jpg"
  ],
  "note": "today's treadmill session"
}
```

**Responses**

- `200` — The photos were classified and, unless \`kind\` is \`other\`, 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
{
  "kind": "workout",
  "ok": true,
  "mealId": "3f8b1c2a-5d6e-4f70-8a1b-2c3d4e5f6071",
  "items": [
    {
      "name": "grilled chicken breast",
      "kcal": 284,
      "proteinG": 53.4
    }
  ],
  "totalKcal": 374,
  "totalProteinG": 54,
  "note": "assumed a single chicken breast",
  "photoKeys": [
    "nick@mintlify.com/2026-06-29/3f8b1c2a"
  ],
  "workout": {
    "id": "9c2d1e4f-7a8b-4c5d-9e0f-1a2b3c4d5e6f",
    "source": "manual",
    "activityType": "run",
    "summary": "5k run + pullups",
    "description": "ran 5k easy, then 3x10 pullups",
    "startedAt": 1783100000000,
    "durationS": 1680,
    "movingDurationS": null,
    "distanceM": 5000,
    "elevationGainM": null,
    "energyKcal": 320,
    "avgHr": 148,
    "maxHr": null,
    "avgPowerW": null,
    "avgCadence": null,
    "exercises": [
      {
        "exercise": "pullups",
        "sets": 3,
        "reps": 10,
        "weightLb": null,
        "durationS": null,
        "distanceM": null,
        "notes": null
      }
    ],
    "createdAt": 1783100001000
  },
  "pounds": 158.2,
  "weightKg": 71.8,
  "bodyFatPct": 17.2,
  "site": "waist",
  "inches": 31.8,
  "needSite": false
}
```
