Unified Food Search
Plan & Token Requirements
Feature available in the following LogMeal Plans:
Accessible by the following User Types:
What It Does
Unified Food Search provides a single normalized search interface for the different food sources that can be used when creating or confirming an intake.
Instead of querying dishes, ingredients, favorites and custom recipes independently and merging their different response formats on the client, you can use
GET /v2/food/search
to retrieve them through one common structure.
The endpoint currently supports these top-level food types:
dishā a regular LogMeal dish.ingredientā a regular LogMeal ingredient that can be used to build an ingredient-only food item.favoriteā a saved favorite belonging to the target APIUser.custom_recipeā a custom recipe available to the target userās APICompany.barcode_food_itemā a previously resolved barcode product stored in LogMeal.
Each result contains both a type and an id.
The id is only unique within its own food type, so clients should always store and use type and id together.
For example, dish with id=123 and favorite with id=123 are different resources, even though they share the same numeric ID.
When a search result is later used in endpoints such as POST /v2/intake/manualInput/\{userId\} or POST /v2/image/confirm/dish, the type tells the API how the corresponding id must be interpreted.
When to Use It / Outcomes
Use Unified Food Search when:
- You want to build one food picker instead of separate selectors for dishes, ingredients, favorites and custom recipes.
- Users need to compose a manual mixed intake containing different kinds of foods.
- Users need to confirm or correct an existing image intake with regular dishes, custom foods or previously saved resources.
- You need the backend to apply the correct ownership and company restrictions for favorites and custom recipes.
- You want all selected food sources to participate in one common ranking and pagination process.
- You want food names returned using LogMealās localized language support.
Output: a normalized JSON response containing:
food_items: the globally ranked results for the requested page.offset: the applied global offset.limit: the requested page size.total: the total number of matches before pagination.
Each item includes:
typeidnameimage_url
Depending on the food type, additional information such as default_quantity, unit, barcode and cooking_measures may also be returned.
Example:
{
"food_items": [
{
"type": "dish",
"id": 123,
"name": "Apple pie",
"image_url": null,
"default_quantity": 150,
"unit": "g"
},
{
"type": "favorite",
"id": 2124166,
"name": "Apple breakfast",
"image_url": "https://..."
},
{
"type": "ingredient",
"id": 388,
"name": "Apple",
"image_url": null,
"default_quantity": 100,
"unit": "g"
}
],
"offset": 0,
"limit": 20,
"total": 3
}Feature-Specific Details
Supported Food Types
The supported top-level food types can be retrieved dynamically through
GET /v2/food/types.
Its response also indicates which types require non-empty search text.
Currently:
| Type | Search text required | Purpose |
|---|---|---|
dish | Yes | Regular LogMeal dishes |
ingredient | Yes | Regular LogMeal ingredients |
favorite | No | Saved favorites owned by the target APIUser |
custom_recipe | No | Custom recipes belonging to the target APIUser's APICompany |
barcode_food_item | Yes | Barcode products already stored in LogMeal |
barcode_ingredient is not a search result type.
It is a nested ingredient type used inside the unified intake contract when a barcode product is added as an ingredient of another food item.
Search Text
The query parameter is required whenever the requested types include:
dishingredientbarcode_food_item
For example:
GET /v2/food/search?query=apple&types=dish,ingredientFavorites and custom recipes can be browsed without text:
GET /v2/food/search?types=favorite,custom_recipeIf types is omitted, all supported food types are selected. Because that includes types requiring search text, a query must also be provided.
Global Ranking
Results from all requested food types are merged into one common ranking.
Text matches are ordered by:
- exact match;
- prefix match;
- partial match.
Favorites and custom recipes receive a small priority boost only when their text-match quality is the same.
For example, an exact dish match still appears before a favorite that only matches by prefix.
The order supplied in types does not determine the result order.
For example:
GET /v2/food/search?query=apple&types=favorite,dishand:
GET /v2/food/search?query=apple&types=dish,favoriteuse the same global ranking rules.
Global Pagination
Pagination is performed after results from the requested food sources have been merged and ranked.
Conceptually:
Dishes āāāāāāāāāāāāāāā
Ingredients āāāāāāāāāā¤
Favorites āāāāāāāāāāāā¤
Custom recipes āāāāāāā¼āāāŗ Global ranking āāŗ offset / limit āāŗ food_items
Barcode products āāāāāThis means offset and limit refer to the complete combined result set, not to each food source independently.
total represents the number of matching results before this global pagination is applied.
The default pagination values are:
limit = 20
offset = 0and limit can contain a maximum of 100 results.
Private Foods & APIUserManager Searches
Favorites and custom recipes depend on the target APIUser.
For š“ APIUser tokens, the userās own context is used automatically.
For šµ APIUserManager tokens, user_id must be provided:
GET /v2/food/search?types=favorite,custom_recipe&user_id=1234The manager must have access to that APIUser.
This target user determines:
- which favorites are visible;
- which APICompany is used to retrieve custom recipes.
This allows managers to build the same food picker that the managed APIUser would see while preserving resource ownership and company boundaries.
Localized Food Names
Unified Food Search supports LogMealās standard language resolution.
You can provide the language parameter where required:
GET /v2/food/search?query=apple&types=dish,ingredient&language=spaLocalized names are returned when translations are available.
If the language is omitted, the standard API language resolution is used.
See Multi-language Responses & Localized Food Names for more information.
Barcode Products
barcode_food_item searches barcode products that have already been stored in LogMeal.
They can be matched using:
- their stored product name;
- their barcode value.
For example:
GET /v2/food/search?query=8410376026962&types=barcode_food_itemSearching barcode products is different from scanning or resolving a new barcode.
If the product has not yet been resolved, use
POST /v2/barcode_scan/{barcode_id}
first.
The returned barcode dish_id represents the corresponding BarcodeClass GeneralClass ID and can then be used as a barcode_food_item in the unified intake contract.
Cooking Measures
Set:
cooking_measures=trueto include available cooking-measure IDs in each result where supported.
For example:
GET /v2/food/search?query=rice&types=dish,ingredient&cooking_measures=trueRegular dishes, ingredients and custom recipes may provide available cooking measures.
Favorites can contain multiple independent food items, so they do not expose one aggregate cooking measure and return an empty list.
Barcode food items currently use their stored OpenFoodFacts serving or weight and also return an empty cooking-measures list.
Using Search Results in an Intake
The normalized type and id returned by Unified Food Search can be used directly by the unified mixed-intake contract.
For example, a search result:
{
"type": "dish",
"id": 123,
"name": "Chicken curry"
}can become:
{
"type": "dish",
"id": 123,
"quantity": 250
}inside a manual intake.
A favorite result:
{
"type": "favorite",
"id": 2124166,
"name": "Usual lunch"
}can be submitted as:
{
"type": "favorite",
"id": 2124166
}The same normalized contract is used by:
- POST /v2/intake/manualInput/{userId}
- POST /v2/image/confirm/dish
This allows the same food-picker component to be reused both for manually reporting food and for correcting an image-based intake.
Related Endpoints
Search contract
- GET /v2/food/types ā š“ šµ Returns the supported unified food types and identifies which ones require search text.
- GET /v2/food/search ā š“ šµ Searches and normalizes dishes, ingredients, favorites, custom recipes and stored barcode products.
Use selected foods
- POST /v2/intake/manualInput/{userId} ā š“ šµ Creates a manual intake using legacy foods or the unified typed food-item contract.
- POST /v2/image/confirm/dish ā š“ šµ Confirms or corrects an image intake and accepts the same unified typed food-item contract.
Barcode resolution
- POST /v2/barcode_scan/{barcode_id} ā š“ Resolves a barcode product without creating an intake. Use this flow when a barcode product is not already available through Unified Food Search.
Underlying catalogs
- GET /v2/dataset/dishes ā ā« š“ šµ Returns the regular LogMeal dish catalog directly.
- GET /v2/dataset/ingredients ā ā« š“ šµ Returns the regular LogMeal ingredient catalog directly.
Typical Workflow
A common unified food-picker workflow is:
- Call GET /v2/food/types to retrieve the currently supported food types.
- Let the user enter search text or browse favorites/custom recipes.
- Call GET /v2/food/search with the required
types,query, pagination and language parameters. - Keep both
typeandidfor every selected result. - Allow the user to combine different result types in the same intake.
- Submit the selected foods through:
- If the user scans a barcode that is not available in search, resolve it through POST /v2/barcode_scan/{barcode_id} and normalize it as
barcode_food_item.
Related Use Cases
Unified Food Search is especially useful for:
- Building one reusable food picker for manual reporting and image confirmation.
- Creating heterogeneous intakes containing regular dishes, individual ingredients, favorites, custom recipes and barcode products.
- Allowing APIUserManagers to compose or correct food intakes in the context of a managed APIUser.
- Building multilingual food-selection interfaces while keeping stable IDs independent from localized names.
Updated about 2 hours ago
