For the complete documentation index, see llms.txt. This page is also available as Markdown.

Food analysis

Turn food into structured data three ways: a photo of a meal, a photo of a packaged food's nutrition label, or a plain-English description. Every analysis returns the same detection object, so a result round-trips into a correction unchanged.

If you already know the food, look it up under Foods instead.

Image analysis uses the reasoning-based analyzer by default: omit reasoning, or send "reasoning": { "effort": "xhigh" }. Send "reasoning": { "effort": "none" } for the standard analyzer. Both return the same response shape and cost the same credits and rate-limit budget. An analysis can take tens of seconds for a complex meal, so show progress. An image that can't be used fails with one of the image_* codes in Errors; retrying the same image fails the same way.

Each detected food carries its food id and its serving.id. Send them as food_id and serving_id to log the food.

Each operation's description states what it costs — see Credits and pricing.

Analyze a food or label photo

post

API key or client token.

Costs 10 credits per successful call.

Analyzes a food photo and returns the detected foods with their nutrition and an aggregated total. The photo can show the food itself or a packaged product — the front of the pack, the ingredient list, or the Nutrition Facts panel all work, and a packaged product comes back as a single detection in the usual result shape. image accepts either an http(s) URL or a base64 data URI. Analysis can take tens of seconds for complex meals. Omit reasoning or set reasoning.effort to xhigh to use the reasoning-based analyzer; set its effort to none to use the standard analyzer. Both modes return the same response shape and use the same rate-limit bucket and credit cost. An optional context note (beta) adds details the photo may not show.

Beta: label reading is in testing — returned nutrition can be incomplete or differ from the printed values, so validate results before relying on them. A photo of nothing but a barcode is rejected; use GET /v1.2/foods/barcode/{barcode} for those. Best results come from sharp, well-lit photos with the food or the complete panel large in the frame; ~1,024 px on the shorter side is plenty, and downsizing huge images lowers latency.

Callable with a client token carrying the food_analysis:write scope.

Authorizations
AuthorizationstringRequired

Your credential, sent as Authorization: Bearer <credential>. Two kinds reach this API, and the prefix tells them apart.

API key (sk-…) — created in the Developer Dashboard, it authenticates your whole account. Use it only where you control the machine — never inside a mobile app or a browser. Every endpoint accepts it.

Client token (ct-…) — a short-lived credential bound to one of your end users, minted from your API key by POST /v1.2/auth/client-tokens on your backend and relayed to the device. Safe to hold on a phone: it expires within 2 hours and acts only as the user it was minted for. Endpoints that open with API key or client token accept one and name the scope it must carry; endpoints that open with API key only refuse it.

Body
imagestringRequired

The food photo — the food itself or a packaged product's label — as an http(s) URL or a base64 data URI (data:image/jpeg;base64,…). Formats: JPG, PNG, WEBP, and non-animated GIF. Around 1,024 px on the shorter side is enough for reliable results (a recommendation, not a validation rule). A URL must be publicly fetchable server-side — hosts that block hotlinking or require a login cannot be read — and has no enforced size cap, though very large files slow the analysis and can time out. Base64 must be a complete data URI and fit the 5 MB request-body cap, so keep raw images under ~3.5 MB before encoding (base64 inflates by ~33%). Prefer the URL when the image is already hosted.

Example: https://january-food-image-dataset-public.s3.us-east-1.amazonaws.com/salmon-green-beans-potatoes.jpg
contextstring · max: 1000 · nullableOptional

Beta. A note about the meal from the person or app that took the photo: details the image may not show, such as how it was cooked, oils and sauces, hidden ingredients, how many items, or the brand or restaurant. The analysis takes it into account alongside the photo.

Example: cooked in olive oil
Responses
200

The foods detected in the photo, with per-item and total nutrition.

application/json
meal_namestring · max: 256 · nullableRequired

A name for the meal as a whole. Null on text analyses — the caller already has the words. Corrections preserve a null meal name.

Example: Breakfast BowlPattern: \S
post/v1.2/food-analysis/image
POST /v1.2/food-analysis/image HTTP/1.1
Host: partners.january.ai
Authorization: Bearer YOUR_SECRET_TOKEN
Content-Type: application/json
Accept: */*
Content-Length: 175

{
  "image": "https://january-food-image-dataset-public.s3.us-east-1.amazonaws.com/salmon-green-beans-potatoes.jpg",
  "reasoning": {
    "effort": "xhigh"
  },
  "context": "cooked in olive oil"
}
{
  "meal_name": "Breakfast Bowl",
  "total_nutrients": {
    "calories": {
      "value": 300,
      "unit": "g"
    },
    "protein": {
      "value": 300,
      "unit": "g"
    },
    "carbohydrates": {
      "value": 300,
      "unit": "g"
    },
    "net_carbohydrates": {
      "value": 300,
      "unit": "g"
    },
    "total_fat": {
      "value": 300,
      "unit": "g"
    },
    "trans_fat": {
      "value": 300,
      "unit": "g"
    },
    "saturated_fat": {
      "value": 300,
      "unit": "g"
    },
    "fiber": {
      "value": 300,
      "unit": "g"
    },
    "total_sugars": {
      "value": 300,
      "unit": "g"
    },
    "added_sugars": {
      "value": 300,
      "unit": "g"
    },
    "cholesterol": {
      "value": 300,
      "unit": "g"
    },
    "calcium": {
      "value": 300,
      "unit": "g"
    },
    "iron": {
      "value": 300,
      "unit": "g"
    },
    "potassium": {
      "value": 300,
      "unit": "g"
    },
    "sodium": {
      "value": 300,
      "unit": "g"
    },
    "vitamin_d": {
      "value": 300,
      "unit": "g"
    }
  },
  "detections": [
    {
      "confidence": "high",
      "food": {
        "name": "Oatmeal",
        "brand_name": null,
        "id": "70379835",
        "quantity": 0.4,
        "serving": {
          "id": "34237662",
          "quantity": 1,
          "unit": "cup",
          "weight_grams": 60
        },
        "nutrients": {
          "calories": {
            "value": 300,
            "unit": "g"
          },
          "protein": {
            "value": 300,
            "unit": "g"
          },
          "carbohydrates": {
            "value": 300,
            "unit": "g"
          },
          "net_carbohydrates": {
            "value": 300,
            "unit": "g"
          },
          "total_fat": {
            "value": 300,
            "unit": "g"
          },
          "trans_fat": {
            "value": 300,
            "unit": "g"
          },
          "saturated_fat": {
            "value": 300,
            "unit": "g"
          },
          "fiber": {
            "value": 300,
            "unit": "g"
          },
          "total_sugars": {
            "value": 300,
            "unit": "g"
          },
          "added_sugars": {
            "value": 300,
            "unit": "g"
          },
          "cholesterol": {
            "value": 300,
            "unit": "g"
          },
          "calcium": {
            "value": 300,
            "unit": "g"
          },
          "iron": {
            "value": 300,
            "unit": "g"
          },
          "potassium": {
            "value": 300,
            "unit": "g"
          },
          "sodium": {
            "value": 300,
            "unit": "g"
          },
          "vitamin_d": {
            "value": 300,
            "unit": "g"
          }
        }
      }
    }
  ]
}

Analyze a meal description

post

API key or client token.

Costs 5 credits per successful call.

Parses free text like "a bowl of oatmeal with honey" into detected foods with quantities and nutrition — the text counterpart of POST /v1.2/food-analysis/image. Text analyses return meal_name: null (the caller already has the words) and grade nothing, so every detection carries confidence: null. For keyword search over the food database, use GET /v1.2/foods.

Callable with a client token carrying the food_analysis:write scope.

Authorizations
AuthorizationstringRequired

Your credential, sent as Authorization: Bearer <credential>. Two kinds reach this API, and the prefix tells them apart.

API key (sk-…) — created in the Developer Dashboard, it authenticates your whole account. Use it only where you control the machine — never inside a mobile app or a browser. Every endpoint accepts it.

Client token (ct-…) — a short-lived credential bound to one of your end users, minted from your API key by POST /v1.2/auth/client-tokens on your backend and relayed to the device. Safe to hold on a phone: it expires within 2 hours and acts only as the user it was minted for. Endpoints that open with API key or client token accept one and name the scope it must carry; endpoints that open with API key only refuse it.

Body
textstring · max: 512Required

Natural-language description of what was eaten; parsed into detected foods with quantities.

Example: a bowl of oatmeal with honey and a banana
Responses
200

The foods detected in the text, with per-item and total nutrition.

application/json
meal_namestring · max: 256 · nullableRequired

A name for the meal as a whole. Null on text analyses — the caller already has the words. Corrections preserve a null meal name.

Example: Breakfast BowlPattern: \S
post/v1.2/food-analysis/text
POST /v1.2/food-analysis/text HTTP/1.1
Host: partners.january.ai
Authorization: Bearer YOUR_SECRET_TOKEN
Content-Type: application/json
Accept: */*
Content-Length: 52

{
  "text": "a bowl of oatmeal with honey and a banana"
}
{
  "meal_name": "Breakfast Bowl",
  "total_nutrients": {
    "calories": {
      "value": 300,
      "unit": "g"
    },
    "protein": {
      "value": 300,
      "unit": "g"
    },
    "carbohydrates": {
      "value": 300,
      "unit": "g"
    },
    "net_carbohydrates": {
      "value": 300,
      "unit": "g"
    },
    "total_fat": {
      "value": 300,
      "unit": "g"
    },
    "trans_fat": {
      "value": 300,
      "unit": "g"
    },
    "saturated_fat": {
      "value": 300,
      "unit": "g"
    },
    "fiber": {
      "value": 300,
      "unit": "g"
    },
    "total_sugars": {
      "value": 300,
      "unit": "g"
    },
    "added_sugars": {
      "value": 300,
      "unit": "g"
    },
    "cholesterol": {
      "value": 300,
      "unit": "g"
    },
    "calcium": {
      "value": 300,
      "unit": "g"
    },
    "iron": {
      "value": 300,
      "unit": "g"
    },
    "potassium": {
      "value": 300,
      "unit": "g"
    },
    "sodium": {
      "value": 300,
      "unit": "g"
    },
    "vitamin_d": {
      "value": 300,
      "unit": "g"
    }
  },
  "detections": [
    {
      "confidence": "high",
      "food": {
        "name": "Oatmeal",
        "brand_name": null,
        "id": "70379835",
        "quantity": 0.4,
        "serving": {
          "id": "34237662",
          "quantity": 1,
          "unit": "cup",
          "weight_grams": 60
        },
        "nutrients": {
          "calories": {
            "value": 300,
            "unit": "g"
          },
          "protein": {
            "value": 300,
            "unit": "g"
          },
          "carbohydrates": {
            "value": 300,
            "unit": "g"
          },
          "net_carbohydrates": {
            "value": 300,
            "unit": "g"
          },
          "total_fat": {
            "value": 300,
            "unit": "g"
          },
          "trans_fat": {
            "value": 300,
            "unit": "g"
          },
          "saturated_fat": {
            "value": 300,
            "unit": "g"
          },
          "fiber": {
            "value": 300,
            "unit": "g"
          },
          "total_sugars": {
            "value": 300,
            "unit": "g"
          },
          "added_sugars": {
            "value": 300,
            "unit": "g"
          },
          "cholesterol": {
            "value": 300,
            "unit": "g"
          },
          "calcium": {
            "value": 300,
            "unit": "g"
          },
          "iron": {
            "value": 300,
            "unit": "g"
          },
          "potassium": {
            "value": 300,
            "unit": "g"
          },
          "sodium": {
            "value": 300,
            "unit": "g"
          },
          "vitamin_d": {
            "value": 300,
            "unit": "g"
          }
        }
      }
    }
  ]
}

Correct an analysis in plain English

post

API key or client token.

Costs 5 credits per successful call — one is free for every successful POST /v1.2/food-analysis/image in your billing period.

Revises an analysis result. Send back the analysis object exactly as POST /v1.2/food-analysis/image or /text returned it, plus instruction describing the correction; the response is a corrected result with recalculated totals. Adjust portions through instruction ("it was about half of that") rather than editing serving quantities by hand. Nutrient keys a detection omits are filled in as zero automatically, and each detection must carry its selected catalog serving and consumed serving count.

Callable with a client token carrying the food_analysis:write scope.

Authorizations
AuthorizationstringRequired

Your credential, sent as Authorization: Bearer <credential>. Two kinds reach this API, and the prefix tells them apart.

API key (sk-…) — created in the Developer Dashboard, it authenticates your whole account. Use it only where you control the machine — never inside a mobile app or a browser. Every endpoint accepts it.

Client token (ct-…) — a short-lived credential bound to one of your end users, minted from your API key by POST /v1.2/auth/client-tokens on your backend and relayed to the device. Safe to hold on a phone: it expires within 2 hours and acts only as the user it was minted for. Endpoints that open with API key or client token accept one and name the scope it must carry; endpoints that open with API key only refuse it.

Body
instructionstring · max: 1000Required

Plain-English description of what to correct.

Example: The oatmeal was steel-cut, about 2 cups, and there was no honey.
Responses
200

The corrected analysis, with recalculated per-item and total nutrition.

application/json
meal_namestring · max: 256 · nullableRequired

A name for the meal as a whole. Null on text analyses — the caller already has the words. Corrections preserve a null meal name.

Example: Breakfast BowlPattern: \S
post/v1.2/food-analysis/corrections
POST /v1.2/food-analysis/corrections HTTP/1.1
Host: partners.january.ai
Authorization: Bearer YOUR_SECRET_TOKEN
Content-Type: application/json
Accept: */*
Content-Length: 569

{
  "analysis": {
    "meal_name": "Breakfast Bowl",
    "total_nutrients": {
      "calories": {
        "value": 166,
        "unit": "kcal"
      },
      "protein": {
        "value": 5.94,
        "unit": "g"
      },
      "carbohydrates": {
        "value": 28.1,
        "unit": "g"
      }
    },
    "detections": [
      {
        "confidence": "high",
        "food": {
          "id": "70379835",
          "name": "oatmeal",
          "brand_name": null,
          "nutrients": {
            "calories": {
              "value": 166,
              "unit": "kcal"
            },
            "protein": {
              "value": 5.94,
              "unit": "g"
            },
            "carbohydrates": {
              "value": 28.1,
              "unit": "g"
            }
          },
          "quantity": 1,
          "serving": {
            "id": "34237662",
            "quantity": 1,
            "unit": "cup",
            "weight_grams": null
          }
        }
      }
    ]
  },
  "instruction": "There was no honey, and the oatmeal was about half a cup."
}
{
  "meal_name": "Breakfast Bowl",
  "total_nutrients": {
    "calories": {
      "value": 300,
      "unit": "g"
    },
    "protein": {
      "value": 300,
      "unit": "g"
    },
    "carbohydrates": {
      "value": 300,
      "unit": "g"
    },
    "net_carbohydrates": {
      "value": 300,
      "unit": "g"
    },
    "total_fat": {
      "value": 300,
      "unit": "g"
    },
    "trans_fat": {
      "value": 300,
      "unit": "g"
    },
    "saturated_fat": {
      "value": 300,
      "unit": "g"
    },
    "fiber": {
      "value": 300,
      "unit": "g"
    },
    "total_sugars": {
      "value": 300,
      "unit": "g"
    },
    "added_sugars": {
      "value": 300,
      "unit": "g"
    },
    "cholesterol": {
      "value": 300,
      "unit": "g"
    },
    "calcium": {
      "value": 300,
      "unit": "g"
    },
    "iron": {
      "value": 300,
      "unit": "g"
    },
    "potassium": {
      "value": 300,
      "unit": "g"
    },
    "sodium": {
      "value": 300,
      "unit": "g"
    },
    "vitamin_d": {
      "value": 300,
      "unit": "g"
    }
  },
  "detections": [
    {
      "confidence": "high",
      "food": {
        "name": "Oatmeal",
        "brand_name": null,
        "id": "70379835",
        "quantity": 0.4,
        "serving": {
          "id": "34237662",
          "quantity": 1,
          "unit": "cup",
          "weight_grams": 60
        },
        "nutrients": {
          "calories": {
            "value": 300,
            "unit": "g"
          },
          "protein": {
            "value": 300,
            "unit": "g"
          },
          "carbohydrates": {
            "value": 300,
            "unit": "g"
          },
          "net_carbohydrates": {
            "value": 300,
            "unit": "g"
          },
          "total_fat": {
            "value": 300,
            "unit": "g"
          },
          "trans_fat": {
            "value": 300,
            "unit": "g"
          },
          "saturated_fat": {
            "value": 300,
            "unit": "g"
          },
          "fiber": {
            "value": 300,
            "unit": "g"
          },
          "total_sugars": {
            "value": 300,
            "unit": "g"
          },
          "added_sugars": {
            "value": 300,
            "unit": "g"
          },
          "cholesterol": {
            "value": 300,
            "unit": "g"
          },
          "calcium": {
            "value": 300,
            "unit": "g"
          },
          "iron": {
            "value": 300,
            "unit": "g"
          },
          "potassium": {
            "value": 300,
            "unit": "g"
          },
          "sodium": {
            "value": 300,
            "unit": "g"
          },
          "vitamin_d": {
            "value": 300,
            "unit": "g"
          }
        }
      }
    }
  ]
}

Last updated

Was this helpful?