> For the complete documentation index, see [llms.txt](https://docs.january.ai/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.january.ai/rest-api/foods.md).

# Foods

Search the food database by name or barcode, and get healthier alternatives for any food.

## Search foods by name

> Full-text search over the January food database, returning up to 40 ranked matches. To look up a scanned barcode, use \`GET /v1.2/foods/barcode/{upc}\` instead.

```json
{"openapi":"3.0.0","info":{"title":"January AI - Nutrition Intelligence APIs","version":"1.2"},"tags":[{"name":"foods","description":"Search the food database by name or barcode, and get healthier alternatives for any food."}],"servers":[{"url":"https://partners.january.ai"}],"security":[{"api-key":[]}],"components":{"securitySchemes":{"api-key":{"scheme":"bearer","bearerFormat":"JWT","type":"http","description":"Your API key (sk-…), minted through the developer portal."}},"schemas":{"FoodSearchResponseDto":{"type":"object","properties":{"total_count":{"type":"number","description":"Match count reported by the food database. It currently reports a fixed page size rather than a true total, so do not compute page counts from it — request more results with `limit` instead."},"items":{"type":"array","items":{"$ref":"#/components/schemas/FoodDto"}}},"required":["total_count","items"]},"FoodDto":{"type":"object","properties":{"id":{"type":"number"},"name":{"type":"string"},"brand_name":{"type":"string","description":"Absent for generic (non-branded) foods."},"nutrients":{"description":"Per-serving nutrition in the shared nutrient vocabulary. Keys are omitted when the database has no value.","allOf":[{"$ref":"#/components/schemas/NutrientsDto"}]},"glycemic_index":{"type":"number","description":"Glycemic index."},"glycemic_load":{"type":"number","description":"Glycemic load."},"image_url":{"type":"string","description":"URL of a picture of the food, when the database has one."},"upc":{"type":"string","description":"The product's barcode, for branded foods that have one."},"servings":{"type":"array","items":{"$ref":"#/components/schemas/FoodServingDto"}}},"required":["id","name","nutrients","servings"]},"NutrientsDto":{"type":"object","properties":{"calories":{"$ref":"#/components/schemas/NutrientAmountDto"},"protein":{"$ref":"#/components/schemas/NutrientAmountDto"},"carbohydrates":{"$ref":"#/components/schemas/NutrientAmountDto"},"net_carbohydrates":{"$ref":"#/components/schemas/NutrientAmountDto"},"total_fat":{"$ref":"#/components/schemas/NutrientAmountDto"},"trans_fat":{"$ref":"#/components/schemas/NutrientAmountDto"},"saturated_fat":{"$ref":"#/components/schemas/NutrientAmountDto"},"fiber":{"$ref":"#/components/schemas/NutrientAmountDto"},"total_sugars":{"$ref":"#/components/schemas/NutrientAmountDto"},"added_sugars":{"$ref":"#/components/schemas/NutrientAmountDto"},"cholesterol":{"$ref":"#/components/schemas/NutrientAmountDto"},"calcium":{"$ref":"#/components/schemas/NutrientAmountDto"},"iron":{"$ref":"#/components/schemas/NutrientAmountDto"},"potassium":{"$ref":"#/components/schemas/NutrientAmountDto"},"sodium":{"$ref":"#/components/schemas/NutrientAmountDto"},"vitamin_d":{"$ref":"#/components/schemas/NutrientAmountDto"}}},"NutrientAmountDto":{"type":"object","properties":{"value":{"type":"number"},"unit":{"type":"string","description":"Canonical across the API: g, mg, kcal, IU."}},"required":["value","unit"]},"FoodServingDto":{"type":"object","properties":{"id":{"type":"number"},"quantity":{"type":"number"},"unit":{"type":"string"},"scaling_factor":{"type":"number","description":"Multiplier applied to the food's nutrition values for this serving."},"weight_grams":{"type":"number","nullable":true},"is_primary":{"type":"boolean","description":"Whether this is the default serving for the food."}},"required":["id","quantity","unit","scaling_factor","weight_grams","is_primary"]},"ApiErrorDto":{"type":"object","properties":{"message":{"type":"string","description":"A developer-facing explanation of what went wrong and how to fix it."},"code":{"type":"string","description":"A stable machine-readable identifier for the class of failure — build retry logic on this, never on message wording. Current values: invalid_request, unauthorized, forbidden, not_found, not_implemented, payload_too_large, rate_limited, internal_error, upstream_error, service_unavailable, upstream_timeout. Only rate_limited, internal_error, upstream_error, service_unavailable, and upstream_timeout are safe to retry (with backoff) — not_implemented is permanent until the feature ships. New codes may be added over time; treat an unknown code according to its HTTP status class."},"docs_url":{"type":"string","description":"Link to the developer documentation."}},"required":["message","code","docs_url"]}}},"paths":{"/v1.2/foods":{"get":{"operationId":"searchFoods","summary":"Search foods by name","description":"Full-text search over the January food database, returning up to 40 ranked matches. To look up a scanned barcode, use `GET /v1.2/foods/barcode/{upc}` instead.","parameters":[{"name":"x-end-user-id","in":"header","description":"Optional: your stable ID for the end user this request acts on behalf of. Opaque to January.","required":false,"schema":{"type":"string"}},{"name":"query","required":true,"in":"query","description":"The food name to search for.","schema":{"maxLength":256,"type":"string"}},{"name":"category","required":false,"in":"query","description":"Narrows results to one food category.","schema":{"default":"general","enum":["general","branded","recipe"],"type":"string"}},{"name":"limit","required":false,"in":"query","description":"Maximum number of results to return.","schema":{"minimum":1,"maximum":40,"default":10,"type":"number"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FoodSearchResponseDto"}}}},"400":{"description":"A parameter is missing or invalid; the message names the parameter and the accepted values.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorDto"}}}},"401":{"description":"The Authorization header is missing or the API key is invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorDto"}}}},"429":{"description":"Either a rate limit was exceeded (`code: rate_limited`) or the monthly credit allowance is spent (`code: credit_limit_exceeded`). When Retry-After is present, wait that many seconds; a per-day allowance resets 24 hours after the first request in its window. Credit exhaustion carries no Retry-After and retrying does not help — the allowance returns at the start of the next calendar month. Call `GET /v1.2/credits` for the balance and reset date.","headers":{"Retry-After":{"description":"Seconds to wait before retrying; present when the window is known.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorDto"}}}},"default":{"description":"Any other error: the HTTP status plus { message, code, docs_url }. Retry only rate_limited and the transient 5xx codes — never not_implemented.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorDto"}}}}},"tags":["foods"]}}}}
```

## Autocomplete food names

> Lightweight food suggestions for a partial name, built for type-ahead ("ban" → banana, banana bread, …): generic foods first, then branded, each with its id, name, brand, a thumbnail and calories. Once the user picks one, fetch \`GET /v1.2/foods/{food\_id}\` for servings and full nutrition. \`items\` is empty for fewer than 2 letters or digits, no match, or a search-index error (the suggestion service fails open so a typing user is not interrupted); an unreachable service still answers with the standard 502/504.

```json
{"openapi":"3.0.0","info":{"title":"January AI - Nutrition Intelligence APIs","version":"1.2"},"tags":[{"name":"foods","description":"Search the food database by name or barcode, and get healthier alternatives for any food."}],"servers":[{"url":"https://partners.january.ai"}],"security":[{"api-key":[]}],"components":{"securitySchemes":{"api-key":{"scheme":"bearer","bearerFormat":"JWT","type":"http","description":"Your API key (sk-…), minted through the developer portal."}},"schemas":{"FoodSuggestionsResponseDto":{"type":"object","properties":{"items":{"description":"Ranked suggestions, generic foods before branded. Empty when nothing matches.","type":"array","items":{"$ref":"#/components/schemas/FoodSuggestionDto"}}},"required":["items"]},"FoodSuggestionDto":{"type":"object","properties":{"id":{"type":"number"},"name":{"type":"string","description":"Generic foods are lowercase; branded foods keep their product name."},"brand_name":{"type":"string","description":"Absent for generic (non-branded) foods."},"image_url":{"type":"string","description":"Thumbnail of the food, when the database has one."},"nutrients":{"description":"Calories per default serving, in the shared nutrient vocabulary — the one nutrient a suggestion carries. Fetch the food for the full panel.","allOf":[{"$ref":"#/components/schemas/NutrientsDto"}]}},"required":["id","name"]},"NutrientsDto":{"type":"object","properties":{"calories":{"$ref":"#/components/schemas/NutrientAmountDto"},"protein":{"$ref":"#/components/schemas/NutrientAmountDto"},"carbohydrates":{"$ref":"#/components/schemas/NutrientAmountDto"},"net_carbohydrates":{"$ref":"#/components/schemas/NutrientAmountDto"},"total_fat":{"$ref":"#/components/schemas/NutrientAmountDto"},"trans_fat":{"$ref":"#/components/schemas/NutrientAmountDto"},"saturated_fat":{"$ref":"#/components/schemas/NutrientAmountDto"},"fiber":{"$ref":"#/components/schemas/NutrientAmountDto"},"total_sugars":{"$ref":"#/components/schemas/NutrientAmountDto"},"added_sugars":{"$ref":"#/components/schemas/NutrientAmountDto"},"cholesterol":{"$ref":"#/components/schemas/NutrientAmountDto"},"calcium":{"$ref":"#/components/schemas/NutrientAmountDto"},"iron":{"$ref":"#/components/schemas/NutrientAmountDto"},"potassium":{"$ref":"#/components/schemas/NutrientAmountDto"},"sodium":{"$ref":"#/components/schemas/NutrientAmountDto"},"vitamin_d":{"$ref":"#/components/schemas/NutrientAmountDto"}}},"NutrientAmountDto":{"type":"object","properties":{"value":{"type":"number"},"unit":{"type":"string","description":"Canonical across the API: g, mg, kcal, IU."}},"required":["value","unit"]},"ApiErrorDto":{"type":"object","properties":{"message":{"type":"string","description":"A developer-facing explanation of what went wrong and how to fix it."},"code":{"type":"string","description":"A stable machine-readable identifier for the class of failure — build retry logic on this, never on message wording. Current values: invalid_request, unauthorized, forbidden, not_found, not_implemented, payload_too_large, rate_limited, internal_error, upstream_error, service_unavailable, upstream_timeout. Only rate_limited, internal_error, upstream_error, service_unavailable, and upstream_timeout are safe to retry (with backoff) — not_implemented is permanent until the feature ships. New codes may be added over time; treat an unknown code according to its HTTP status class."},"docs_url":{"type":"string","description":"Link to the developer documentation."}},"required":["message","code","docs_url"]}}},"paths":{"/v1.2/foods/autocomplete":{"get":{"operationId":"autocompleteFoods","summary":"Autocomplete food names","description":"Lightweight food suggestions for a partial name, built for type-ahead (\"ban\" → banana, banana bread, …): generic foods first, then branded, each with its id, name, brand, a thumbnail and calories. Once the user picks one, fetch `GET /v1.2/foods/{food_id}` for servings and full nutrition. `items` is empty for fewer than 2 letters or digits, no match, or a search-index error (the suggestion service fails open so a typing user is not interrupted); an unreachable service still answers with the standard 502/504.","parameters":[{"name":"x-end-user-id","in":"header","description":"Optional: your stable ID for the end user this request acts on behalf of. Opaque to January.","required":false,"schema":{"type":"string"}},{"name":"query","required":true,"in":"query","description":"The characters the user has typed so far. Fewer than 2 letters or digits yield no suggestions.","schema":{"maxLength":64,"type":"string"}},{"name":"category","required":false,"in":"query","description":"Narrows suggestions to one category. Omitted, generic and branded foods are suggested together, generic first.","schema":{"enum":["general","branded"],"type":"string"}},{"name":"limit","required":false,"in":"query","description":"Maximum number of suggestions to return.","schema":{"minimum":1,"maximum":20,"default":8,"type":"number"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FoodSuggestionsResponseDto"}}}},"400":{"description":"A parameter is missing or invalid; the message names the parameter and the accepted values.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorDto"}}}},"401":{"description":"The Authorization header is missing or the API key is invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorDto"}}}},"429":{"description":"Either a rate limit was exceeded (`code: rate_limited`) or the monthly credit allowance is spent (`code: credit_limit_exceeded`). When Retry-After is present, wait that many seconds; a per-day allowance resets 24 hours after the first request in its window. Credit exhaustion carries no Retry-After and retrying does not help — the allowance returns at the start of the next calendar month. Call `GET /v1.2/credits` for the balance and reset date.","headers":{"Retry-After":{"description":"Seconds to wait before retrying; present when the window is known.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorDto"}}}},"default":{"description":"Any other error: the HTTP status plus { message, code, docs_url }. Retry only rate_limited and the transient 5xx codes — never not_implemented.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorDto"}}}}},"tags":["foods"]}}}}
```

## Suggest healthier alternatives for a food

> Returns healthier alternatives for a food, honoring the given dietary restrictions and preferences. Omit either array (or send \`\[]\`) if it does not apply. An empty \`alternatives\` result is valid — no suitable alternatives were found.

```json
{"openapi":"3.0.0","info":{"title":"January AI - Nutrition Intelligence APIs","version":"1.2"},"tags":[{"name":"foods","description":"Search the food database by name or barcode, and get healthier alternatives for any food."}],"servers":[{"url":"https://partners.january.ai"}],"security":[{"api-key":[]}],"components":{"securitySchemes":{"api-key":{"scheme":"bearer","bearerFormat":"JWT","type":"http","description":"Your API key (sk-…), minted through the developer portal."}},"schemas":{"FoodAlternativesRequestDto":{"type":"object","properties":{"diet_restrictions":{"type":"array","description":"Allergens/ingredients to avoid. Omit it (or send []) if none apply.","items":{"type":"string","enum":["gluten","lactose","yeast","tree_nuts","peanuts","dairy","eggs","sulfites","soy","wheat","shellfish","fish","mushrooms","sesame","msg","caffeine","fodmaps"]}},"diet_preferences":{"type":"array","description":"Dietary patterns to match. Omit it (or send []) if none apply.","items":{"type":"string","enum":["vegetarian","vegan","keto","paleo","pescatarian","low_carbohydrate","high_protein","kosher","halal"]}}}},"FoodAlternativesResponseDto":{"type":"object","properties":{"alternatives":{"description":"Healthier alternatives matching the restrictions and preferences. An empty array is a valid result, not an error.","type":"array","items":{"$ref":"#/components/schemas/FoodAlternativeDto"}}},"required":["alternatives"]},"FoodAlternativeDto":{"type":"object","properties":{"food":{"$ref":"#/components/schemas/AlternativeFoodDto"}},"required":["food"]},"AlternativeFoodDto":{"type":"object","properties":{"id":{"type":"number"},"name":{"type":"string"},"brand_name":{"type":"string","description":"Empty for generic (non-branded) foods."},"nutrients":{"$ref":"#/components/schemas/MacroNutrientsDto"},"servings":{"type":"array","items":{"$ref":"#/components/schemas/ServingSummaryDto"}}},"required":["name","nutrients"]},"MacroNutrientsDto":{"type":"object","properties":{"calories":{"$ref":"#/components/schemas/NutrientAmountDto"},"protein":{"$ref":"#/components/schemas/NutrientAmountDto"},"carbohydrates":{"$ref":"#/components/schemas/NutrientAmountDto"},"net_carbohydrates":{"$ref":"#/components/schemas/NutrientAmountDto"},"total_fat":{"$ref":"#/components/schemas/NutrientAmountDto"},"saturated_fat":{"$ref":"#/components/schemas/NutrientAmountDto"},"fiber":{"$ref":"#/components/schemas/NutrientAmountDto"},"total_sugars":{"$ref":"#/components/schemas/NutrientAmountDto"},"added_sugars":{"$ref":"#/components/schemas/NutrientAmountDto"},"sodium":{"$ref":"#/components/schemas/NutrientAmountDto"}}},"NutrientAmountDto":{"type":"object","properties":{"value":{"type":"number"},"unit":{"type":"string","description":"Canonical across the API: g, mg, kcal, IU."}},"required":["value","unit"]},"ServingSummaryDto":{"type":"object","properties":{"id":{"type":"number"},"quantity":{"type":"number"},"unit":{"type":"string"}},"required":["id","unit"]},"ApiErrorDto":{"type":"object","properties":{"message":{"type":"string","description":"A developer-facing explanation of what went wrong and how to fix it."},"code":{"type":"string","description":"A stable machine-readable identifier for the class of failure — build retry logic on this, never on message wording. Current values: invalid_request, unauthorized, forbidden, not_found, not_implemented, payload_too_large, rate_limited, internal_error, upstream_error, service_unavailable, upstream_timeout. Only rate_limited, internal_error, upstream_error, service_unavailable, and upstream_timeout are safe to retry (with backoff) — not_implemented is permanent until the feature ships. New codes may be added over time; treat an unknown code according to its HTTP status class."},"docs_url":{"type":"string","description":"Link to the developer documentation."}},"required":["message","code","docs_url"]}}},"paths":{"/v1.2/foods/{food_id}/alternatives":{"post":{"operationId":"suggestAlternatives","summary":"Suggest healthier alternatives for a food","description":"Returns healthier alternatives for a food, honoring the given dietary restrictions and preferences. Omit either array (or send `[]`) if it does not apply. An empty `alternatives` result is valid — no suitable alternatives were found.","parameters":[{"name":"x-end-user-id","in":"header","description":"Optional: your stable ID for the end user this request acts on behalf of. Opaque to January.","required":false,"schema":{"type":"string"}},{"name":"food_id","required":true,"in":"path","description":"Numeric food id from a search, scan, or detection result. The example is brown rice.","schema":{"type":"string","pattern":"^[0-9]{1,16}$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FoodAlternativesRequestDto"}}}},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FoodAlternativesResponseDto"}}}},"400":{"description":"A field is missing or a value is not in the allowed vocabulary; the message names it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorDto"}}}},"401":{"description":"The Authorization header is missing or the API key is invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorDto"}}}},"404":{"description":"No food with this id.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorDto"}}}},"429":{"description":"Either a rate limit was exceeded (`code: rate_limited`) or the monthly credit allowance is spent (`code: credit_limit_exceeded`). When Retry-After is present, wait that many seconds; a per-day allowance resets 24 hours after the first request in its window. Credit exhaustion carries no Retry-After and retrying does not help — the allowance returns at the start of the next calendar month. Call `GET /v1.2/credits` for the balance and reset date.","headers":{"Retry-After":{"description":"Seconds to wait before retrying; present when the window is known.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorDto"}}}},"default":{"description":"Any other error: the HTTP status plus { message, code, docs_url }. Retry only rate_limited and the transient 5xx codes — never not_implemented.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorDto"}}}}},"tags":["foods"]}}}}
```

## Look up a food by barcode

> Exact lookup of a food by its barcode. For free-text search, use \`GET /v1.2/foods\` instead.

```json
{"openapi":"3.0.0","info":{"title":"January AI - Nutrition Intelligence APIs","version":"1.2"},"tags":[{"name":"foods","description":"Search the food database by name or barcode, and get healthier alternatives for any food."}],"servers":[{"url":"https://partners.january.ai"}],"security":[{"api-key":[]}],"components":{"securitySchemes":{"api-key":{"scheme":"bearer","bearerFormat":"JWT","type":"http","description":"Your API key (sk-…), minted through the developer portal."}},"schemas":{"FoodSearchResponseDto":{"type":"object","properties":{"total_count":{"type":"number","description":"Match count reported by the food database. It currently reports a fixed page size rather than a true total, so do not compute page counts from it — request more results with `limit` instead."},"items":{"type":"array","items":{"$ref":"#/components/schemas/FoodDto"}}},"required":["total_count","items"]},"FoodDto":{"type":"object","properties":{"id":{"type":"number"},"name":{"type":"string"},"brand_name":{"type":"string","description":"Absent for generic (non-branded) foods."},"nutrients":{"description":"Per-serving nutrition in the shared nutrient vocabulary. Keys are omitted when the database has no value.","allOf":[{"$ref":"#/components/schemas/NutrientsDto"}]},"glycemic_index":{"type":"number","description":"Glycemic index."},"glycemic_load":{"type":"number","description":"Glycemic load."},"image_url":{"type":"string","description":"URL of a picture of the food, when the database has one."},"upc":{"type":"string","description":"The product's barcode, for branded foods that have one."},"servings":{"type":"array","items":{"$ref":"#/components/schemas/FoodServingDto"}}},"required":["id","name","nutrients","servings"]},"NutrientsDto":{"type":"object","properties":{"calories":{"$ref":"#/components/schemas/NutrientAmountDto"},"protein":{"$ref":"#/components/schemas/NutrientAmountDto"},"carbohydrates":{"$ref":"#/components/schemas/NutrientAmountDto"},"net_carbohydrates":{"$ref":"#/components/schemas/NutrientAmountDto"},"total_fat":{"$ref":"#/components/schemas/NutrientAmountDto"},"trans_fat":{"$ref":"#/components/schemas/NutrientAmountDto"},"saturated_fat":{"$ref":"#/components/schemas/NutrientAmountDto"},"fiber":{"$ref":"#/components/schemas/NutrientAmountDto"},"total_sugars":{"$ref":"#/components/schemas/NutrientAmountDto"},"added_sugars":{"$ref":"#/components/schemas/NutrientAmountDto"},"cholesterol":{"$ref":"#/components/schemas/NutrientAmountDto"},"calcium":{"$ref":"#/components/schemas/NutrientAmountDto"},"iron":{"$ref":"#/components/schemas/NutrientAmountDto"},"potassium":{"$ref":"#/components/schemas/NutrientAmountDto"},"sodium":{"$ref":"#/components/schemas/NutrientAmountDto"},"vitamin_d":{"$ref":"#/components/schemas/NutrientAmountDto"}}},"NutrientAmountDto":{"type":"object","properties":{"value":{"type":"number"},"unit":{"type":"string","description":"Canonical across the API: g, mg, kcal, IU."}},"required":["value","unit"]},"FoodServingDto":{"type":"object","properties":{"id":{"type":"number"},"quantity":{"type":"number"},"unit":{"type":"string"},"scaling_factor":{"type":"number","description":"Multiplier applied to the food's nutrition values for this serving."},"weight_grams":{"type":"number","nullable":true},"is_primary":{"type":"boolean","description":"Whether this is the default serving for the food."}},"required":["id","quantity","unit","scaling_factor","weight_grams","is_primary"]},"ApiErrorDto":{"type":"object","properties":{"message":{"type":"string","description":"A developer-facing explanation of what went wrong and how to fix it."},"code":{"type":"string","description":"A stable machine-readable identifier for the class of failure — build retry logic on this, never on message wording. Current values: invalid_request, unauthorized, forbidden, not_found, not_implemented, payload_too_large, rate_limited, internal_error, upstream_error, service_unavailable, upstream_timeout. Only rate_limited, internal_error, upstream_error, service_unavailable, and upstream_timeout are safe to retry (with backoff) — not_implemented is permanent until the feature ships. New codes may be added over time; treat an unknown code according to its HTTP status class."},"docs_url":{"type":"string","description":"Link to the developer documentation."}},"required":["message","code","docs_url"]}}},"paths":{"/v1.2/foods/barcode/{upc}":{"get":{"operationId":"lookupBarcode","summary":"Look up a food by barcode","description":"Exact lookup of a food by its barcode. For free-text search, use `GET /v1.2/foods` instead.","parameters":[{"name":"x-end-user-id","in":"header","description":"Optional: your stable ID for the end user this request acts on behalf of. Opaque to January.","required":false,"schema":{"type":"string"}},{"name":"upc","required":true,"in":"path","description":"The numeric barcode: 6 to 14 digits (UPC-E, UPC-A, EAN-8, EAN-13 or GTIN-14). The example is a Coca-Cola can.","schema":{"type":"string","pattern":"^[0-9]{6,14}$"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FoodSearchResponseDto"}}}},"400":{"description":"The barcode is not a 6 to 14 digit number.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorDto"}}}},"401":{"description":"The Authorization header is missing or the API key is invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorDto"}}}},"404":{"description":"No food matches this barcode.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorDto"}}}},"429":{"description":"Either a rate limit was exceeded (`code: rate_limited`) or the monthly credit allowance is spent (`code: credit_limit_exceeded`). When Retry-After is present, wait that many seconds; a per-day allowance resets 24 hours after the first request in its window. Credit exhaustion carries no Retry-After and retrying does not help — the allowance returns at the start of the next calendar month. Call `GET /v1.2/credits` for the balance and reset date.","headers":{"Retry-After":{"description":"Seconds to wait before retrying; present when the window is known.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorDto"}}}},"default":{"description":"Any other error: the HTTP status plus { message, code, docs_url }. Retry only rate_limited and the transient 5xx codes — never not_implemented.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorDto"}}}}},"tags":["foods"]}}}}
```

## Get a food

> One food's full record — most importantly the \*\*complete list of serving sizes\*\*. Search, barcode, and scan results carry a single default serving; fetch the food here to let an end user pick "1 cup" vs "100 g" vs "1 medium" when logging or predicting. Nutrition is per the default serving, in the shared nutrient vocabulary.

```json
{"openapi":"3.0.0","info":{"title":"January AI - Nutrition Intelligence APIs","version":"1.2"},"tags":[{"name":"foods","description":"Search the food database by name or barcode, and get healthier alternatives for any food."}],"servers":[{"url":"https://partners.january.ai"}],"security":[{"api-key":[]}],"components":{"securitySchemes":{"api-key":{"scheme":"bearer","bearerFormat":"JWT","type":"http","description":"Your API key (sk-…), minted through the developer portal."}},"schemas":{"FoodDto":{"type":"object","properties":{"id":{"type":"number"},"name":{"type":"string"},"brand_name":{"type":"string","description":"Absent for generic (non-branded) foods."},"nutrients":{"description":"Per-serving nutrition in the shared nutrient vocabulary. Keys are omitted when the database has no value.","allOf":[{"$ref":"#/components/schemas/NutrientsDto"}]},"glycemic_index":{"type":"number","description":"Glycemic index."},"glycemic_load":{"type":"number","description":"Glycemic load."},"image_url":{"type":"string","description":"URL of a picture of the food, when the database has one."},"upc":{"type":"string","description":"The product's barcode, for branded foods that have one."},"servings":{"type":"array","items":{"$ref":"#/components/schemas/FoodServingDto"}}},"required":["id","name","nutrients","servings"]},"NutrientsDto":{"type":"object","properties":{"calories":{"$ref":"#/components/schemas/NutrientAmountDto"},"protein":{"$ref":"#/components/schemas/NutrientAmountDto"},"carbohydrates":{"$ref":"#/components/schemas/NutrientAmountDto"},"net_carbohydrates":{"$ref":"#/components/schemas/NutrientAmountDto"},"total_fat":{"$ref":"#/components/schemas/NutrientAmountDto"},"trans_fat":{"$ref":"#/components/schemas/NutrientAmountDto"},"saturated_fat":{"$ref":"#/components/schemas/NutrientAmountDto"},"fiber":{"$ref":"#/components/schemas/NutrientAmountDto"},"total_sugars":{"$ref":"#/components/schemas/NutrientAmountDto"},"added_sugars":{"$ref":"#/components/schemas/NutrientAmountDto"},"cholesterol":{"$ref":"#/components/schemas/NutrientAmountDto"},"calcium":{"$ref":"#/components/schemas/NutrientAmountDto"},"iron":{"$ref":"#/components/schemas/NutrientAmountDto"},"potassium":{"$ref":"#/components/schemas/NutrientAmountDto"},"sodium":{"$ref":"#/components/schemas/NutrientAmountDto"},"vitamin_d":{"$ref":"#/components/schemas/NutrientAmountDto"}}},"NutrientAmountDto":{"type":"object","properties":{"value":{"type":"number"},"unit":{"type":"string","description":"Canonical across the API: g, mg, kcal, IU."}},"required":["value","unit"]},"FoodServingDto":{"type":"object","properties":{"id":{"type":"number"},"quantity":{"type":"number"},"unit":{"type":"string"},"scaling_factor":{"type":"number","description":"Multiplier applied to the food's nutrition values for this serving."},"weight_grams":{"type":"number","nullable":true},"is_primary":{"type":"boolean","description":"Whether this is the default serving for the food."}},"required":["id","quantity","unit","scaling_factor","weight_grams","is_primary"]},"ApiErrorDto":{"type":"object","properties":{"message":{"type":"string","description":"A developer-facing explanation of what went wrong and how to fix it."},"code":{"type":"string","description":"A stable machine-readable identifier for the class of failure — build retry logic on this, never on message wording. Current values: invalid_request, unauthorized, forbidden, not_found, not_implemented, payload_too_large, rate_limited, internal_error, upstream_error, service_unavailable, upstream_timeout. Only rate_limited, internal_error, upstream_error, service_unavailable, and upstream_timeout are safe to retry (with backoff) — not_implemented is permanent until the feature ships. New codes may be added over time; treat an unknown code according to its HTTP status class."},"docs_url":{"type":"string","description":"Link to the developer documentation."}},"required":["message","code","docs_url"]}}},"paths":{"/v1.2/foods/{food_id}":{"get":{"operationId":"getFood","summary":"Get a food","description":"One food's full record — most importantly the **complete list of serving sizes**. Search, barcode, and scan results carry a single default serving; fetch the food here to let an end user pick \"1 cup\" vs \"100 g\" vs \"1 medium\" when logging or predicting. Nutrition is per the default serving, in the shared nutrient vocabulary.","parameters":[{"name":"x-end-user-id","in":"header","description":"Optional: your stable ID for the end user this request acts on behalf of. Opaque to January.","required":false,"schema":{"type":"string"}},{"name":"food_id","required":true,"in":"path","description":"Numeric food id from a search, scan, or detection result.","schema":{"type":"string","pattern":"^[0-9]{1,10}$"}}],"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FoodDto"}}}},"400":{"description":"food_id is not a numeric id; the message shows the expected form.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorDto"}}}},"401":{"description":"The Authorization header is missing or the API key is invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorDto"}}}},"404":{"description":"No food with this id.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorDto"}}}},"429":{"description":"Either a rate limit was exceeded (`code: rate_limited`) or the monthly credit allowance is spent (`code: credit_limit_exceeded`). When Retry-After is present, wait that many seconds; a per-day allowance resets 24 hours after the first request in its window. Credit exhaustion carries no Retry-After and retrying does not help — the allowance returns at the start of the next calendar month. Call `GET /v1.2/credits` for the balance and reset date.","headers":{"Retry-After":{"description":"Seconds to wait before retrying; present when the window is known.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorDto"}}}},"default":{"description":"Any other error: the HTTP status plus { message, code, docs_url }. Retry only rate_limited and the transient 5xx codes — never not_implemented.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiErrorDto"}}}}},"tags":["foods"]}}}}
```
