{"openapi":"3.1.0","info":{"title":"Labelify API","description":"\nLabelify is a SaaS platform for creating nutrition facts labels that comply with Canadian (CFIA) and US (FDA) regulations. This API provides programmatic access to manage ingredients, recipes, and labels.\n\n## Core Data Model\n\nThe API is organized around three main resources:\n\n- **Foods** (called \"Ingredients\" in the UI): Nutritional entities with nutriment data, allergens, and metadata. Foods are either tenant-created (custom) or from public databases (CNF for Canadian Nutrient File, USDA for US Department of Agriculture). Use the `source` query parameter with values USER, CNF, or USDA to filter by origin.\n- **Recipes**: Collections of ingredients with quantities. Recipes calculate aggregate nutritional values from their components. Recipes can be nested by adding a recipe directly as an ingredient using `source_recipe_id` instead of `food_id`.\n- **Labels**: Nutrition Facts Tables (NFT) generated from recipes according to regulatory requirements (CAN2016 for Canadian 2016 regulations, US for United States).\n\n**Important terminology note**: The Labelify UI calls foods \"Ingredients\". The API term `ingredient` means something different: a line item inside a recipe that references a food (via `food_id`) or another recipe (via `source_recipe_id`) with a quantity.\n\n## Automatic Updates\n\nRecipes automatically recalculate when their components change:\n- When a food is updated, all recipes containing it are recalculated\n- When a nested recipe (added via `source_recipe_id`) is updated, parent recipes are recalculated\n\nThese automatic updates trigger webhook events with `user_name: System`.\n\n## Subrecipes (Legacy)\n\nSubrecipes are foods created from recipes via `POST /v1/foods?recipe_id_to_subrecipe={recipe_id}`. This is a legacy approach; prefer adding recipes directly as ingredients using `source_recipe_id`.\n\nKey difference: Subrecipes do **not** automatically update. You must manually sync them via `POST /v1/foods/{food_id}/subrecipe` when the source recipe changes.\n\n## Authentication\n\nAll API requests require authentication via API key. Pass your key in the `Authorization` header:\n\n```\nAuthorization: API-XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX\n```\n\nAPI keys can be generated in the Labelify web application under Settings > API. Each key is scoped to a single tenant (organization).\n\n## Base URL\n\nAll endpoints are prefixed with `/v1/`. The OpenAPI specification is available at `/labelify_openapi.json`.\n\n## Rate Limiting\n\nRate limits are applied per API key (tenant):\n\n- **Authenticated requests**: 500 requests/minute, 7200 requests/hour\n- **Concurrent requests**: Maximum 10 simultaneous in-flight requests\n\nWhen rate limited, the API returns HTTP 429 with a `Retry-After` header indicating seconds until the limit resets.\n\n## Webhooks\n\nConfigure webhooks in the API settings page. Webhooks send HTTP POST requests to your configured endpoint containing batches of events approximately every 10 seconds.\n\n**Tracked Events:** `created`, `updated`, `deleted` for foods, recipes, labels, and fop_labels. Child operations use `updated.*` prefix (e.g., `updated.added_ingredient`, `updated.removed_custom_unit`).\n\n**Payload Format:**\n```json\n{\n  \"tenant_id\": \"...\",\n  \"sent_at\": \"2024-01-15T10:30:00Z\",\n  \"events\": [\n    {\n      \"event\": \"updated\",\n      \"entity_type\": \"food\",\n      \"entity_id\": \"...\",\n      \"url\": \"/v1/foods/...\",\n      \"version_id\": 5,\n      \"user_id\": \"...\",\n      \"user_name\": \"John Doe\",\n      \"timestamp\": \"2024-01-15T10:29:55Z\"\n    }\n  ]\n}\n```\n\n**Security:** Verify `X-Webhook-Signature` header using HMAC-SHA256 with your webhook secret.\n\n**Response:** Your endpoint must return HTTP 200. Other status codes trigger retry with exponential backoff over ~30 minutes (11 attempts).\n\n**System Events:** When foods or recipes update, all dependent recipes receive automated update events (`user_name: System`).\n\n## The expand Parameter\n\nMany GET endpoints support an `expand` query parameter that loads additional computed or related fields. Values are comma-separated. This pattern exists because some fields are expensive to compute (e.g., `nutriments_100g` requires normalization calculations) or involve additional database queries (e.g., `tags`).\n\nExample: `GET /v1/foods/{id}?expand=nutriment_100g,tags`\n\nEach endpoint documents its supported expand values. Common values include:\n- `nutriments`, `nutriments_100g`: Calculated nutritional values\n- `tags`: Associated tags\n- `ingredients.nutriments`: Per-ingredient nutriments in recipes\n\n## Pagination\n\nList endpoints support pagination via:\n\n- `page`: Page number (1-indexed, default: 1)\n- `page_size`: Items per page (default: 20, max: 200)\n- `short`: When true (default), returns abbreviated responses. When false, returns full entities but limits `page_size` to 20 maximum.\n\nResponses include `page_info` with: `page_size`, `next_page`, `previous_page`, `total`.\n\n## Optimistic Locking (version_id)\n\nMost entities include a `version_id` field for concurrent edit detection:\n\n- If you send `version_id` on update and it doesn't match the current version, the API returns 400 with code 1010 (StaleDataException)\n- If you omit `version_id`, the update proceeds without checking (silent overwrite)\n\nUse this to prevent overwrites when multiple users edit simultaneously: fetch the entity, send back its `version_id` on update, handle 1010 errors by re-fetching and retrying.\n\n## Error Response Format\n\nAll errors return a JSON object:\n\n```json\n{\n  \"code\": 1005,\n  \"message_en\": \"Invalid or missing\",\n  \"message_fr\": \"invalide ou manquant\",\n  \"type\": \"InvalidOrMissing\"\n}\n```\n\nCommon status codes:\n- **400**: Various errors (codes 1000-1013)\n- **404**: Not found (code 1005) or page out of bounds (code 1006)\n- **422**: Validation error (code 1001) with `detail` array of field errors\n- **429**: Rate limit exceeded (code 4029) with `retry_after` seconds\n- **503**: Service unavailable (maintenance mode)\n\n## Render Endpoints\n\nLabel and FOP label render endpoints (`/render.{format}`) return binary content (PDF, PNG, JPG, BMP, EPS). The filename is provided in the `Content-Disposition` header.\n\n## POST vs PATCH Update Behavior\n\nBoth POST and PATCH only update fields present in the request; omitted fields are preserved. The difference is how they handle sub-entities (children):\n\n- **POST** (sub-entity replacement): Sub-entities like `nutriments`, `custom_units`, `ingredients`, or `label_additional_recipes` are replaced entirely. Items not included are deleted. Omitting the sub-entity field preserves existing data; sending empty `{}` clears it.\n- **PATCH** (sub-entity merge): Sub-entities are merged. Only items present are added or updated; existing items not mentioned are retained.\n\nUse POST when you have the complete sub-entity state. Use PATCH for partial sub-entity updates.\n","version":"1.0"},"paths":{"/v1/me/organization/logo":{"get":{"tags":["me"],"summary":"Download Organization Logo","description":"Download the organization's logo image.\n\nReturns the logo as a binary download. Returns empty response if no logo is set.\n\n**Restrictions:**\n- Trial accounts cannot use this endpoint (returns 403)","operationId":"download_organization_logo_v1_me_organization_logo_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPBadRequest"}}}},"429":{"description":"Rate limit exceeded. Authenticated requests: 500/minute, 7200/hour. Concurrent limit: 10 requests. Check Retry-After header for reset time.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPRateLimitExceeded"}}}}},"security":[{"APIKeyHeader":[]}]},"post":{"tags":["me"],"summary":"Add Organization Logo","description":"Upload or replace the organization's logo.\n\nReplaces any existing logo. Only one logo can be stored per organization.\n\n**Restrictions:**\n- Trial accounts cannot use this endpoint (returns 403)\n- Allowed extensions: jpg, jpeg, png\n\n**Request format:** multipart/form-data with field `upload_file`","operationId":"add_organization_logo_v1_me_organization_logo_post","requestBody":{"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_add_organization_logo_v1_me_organization_logo_post"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPBadRequest"}}}},"429":{"description":"Rate limit exceeded. Authenticated requests: 500/minute, 7200/hour. Concurrent limit: 10 requests. Check Retry-After header for reset time.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPRateLimitExceeded"}}}}},"security":[{"APIKeyHeader":[]}]},"delete":{"tags":["me"],"summary":"Remove Organization Logo","description":"Delete the organization's logo.\n\n**Restrictions:**\n- Trial accounts cannot use this endpoint (returns 403)\n\nReturns 204 No Content on success.","operationId":"remove_organization_logo_v1_me_organization_logo_delete","responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPBadRequest"}}}},"429":{"description":"Rate limit exceeded. Authenticated requests: 500/minute, 7200/hour. Concurrent limit: 10 requests. Check Retry-After header for reset time.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPRateLimitExceeded"}}}}},"security":[{"APIKeyHeader":[]}]}},"/v1/foods":{"get":{"tags":["foods"],"summary":"List Food","description":"List or search ingredients (foods).\n\nReturns a paginated list of ingredients. By default, returns only your organization's custom ingredients.\nUse `all=true` to include public database ingredients (CNF, USDA).\n\n**Response modes:**\n- `short=true` (default): Returns 14 fields per ingredient\n- `short=false`: Returns 48 fields including nutriments, allergens, and custom units. Page size capped at 20.","operationId":"list_food_v1_foods_get","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"short","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"description":"Returns a condensed response with a subset of fields (14 fields). When `false`, the full object is returned (48 fields) but `page_size` is capped at 20 to limit memory usage.","default":true,"title":"Short"},"description":"Returns a condensed response with a subset of fields (14 fields). When `false`, the full object is returned (48 fields) but `page_size` is capped at 20 to limit memory usage."},{"name":"all","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"description":"When `true`, returns your organization's ingredients plus all public database ingredients (CNF and USDA). When `false` (default), returns only your organization's custom ingredients. Required when using `source=CNF` or `source=USDA` filters.","default":false,"title":"All"},"description":"When `true`, returns your organization's ingredients plus all public database ingredients (CNF and USDA). When `false` (default), returns only your organization's custom ingredients. Required when using `source=CNF` or `source=USDA` filters."},{"name":"search","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Search pattern. Searches `name`, `name_en`/`name_fr` (based on `lang`), `common_name`, and `product_code`. For exact product_code lookup, use GET /v1/foods/by_product_code/{product_code}.","title":"Search"},"description":"Search pattern. Searches `name`, `name_en`/`name_fr` (based on `lang`), `common_name`, and `product_code`. For exact product_code lookup, use GET /v1/foods/by_product_code/{product_code}."},{"name":"lang","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Language for search matching. Only applies when `search` is provided. Valid values: `en`, `fr`.","default":"en","title":"Lang"},"description":"Language for search matching. Only applies when `search` is provided. Valid values: `en`, `fr`."},{"name":"source","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by ingredient origin. Only applies when `all=true` with `search`. Values: `USER` (tenant-created, CNF/USDA fields null), `CNF` (Canadian Nutrient File), `USDA` (US Department of Agriculture). Comma-separated for multiple: `USER,CNF`.","title":"Source"},"description":"Filter by ingredient origin. Only applies when `all=true` with `search`. Values: `USER` (tenant-created, CNF/USDA fields null), `CNF` (Canadian Nutrient File), `USDA` (US Department of Agriculture). Comma-separated for multiple: `USER,CNF`."},{"name":"include_legacy_datasets","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"description":"When `true`, results also include ingredients from legacy dataset generations (e.g., CNF 2016 after the CNF 2026 refresh). Applies to search and to `all=true` browsing. Legacy results have `legacy_dataset=true` and their `dataset_version` set.","default":false,"title":"Include Legacy Datasets"},"description":"When `true`, results also include ingredients from legacy dataset generations (e.g., CNF 2016 after the CNF 2026 refresh). Applies to search and to `all=true` browsing. Legacy results have `legacy_dataset=true` and their `dataset_version` set."},{"name":"recipe_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"(Legacy) Filter to subrecipe foods linked to this recipe ID. Subrecipes are legacy; prefer adding recipes directly as ingredients using `source_recipe_id`.","title":"Recipe Id"},"description":"(Legacy) Filter to subrecipe foods linked to this recipe ID. Subrecipes are legacy; prefer adding recipes directly as ingredients using `source_recipe_id`."},{"name":"ids","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by specific ingredient IDs. Comma-separated list. Example: `abc123,def456`.","title":"Ids"},"description":"Filter by specific ingredient IDs. Comma-separated list. Example: `abc123,def456`."},{"name":"tags","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by tag IDs. Comma-separated list. Not applicable when `all=true` (tag filtering only works for your organization's ingredients).","title":"Tags"},"description":"Filter by tag IDs. Comma-separated list. Not applicable when `all=true` (tag filtering only works for your organization's ingredients)."},{"name":"expand","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Comma-separated list of additional fields to include. Valid values: `nutriments_100g` (adds normalized nutriments per 100g), `tags` (adds tag associations).","title":"Expand"},"description":"Comma-separated list of additional fields to include. Valid values: `nutriments_100g` (adds normalized nutriments per 100g), `tags` (adds tag associations)."},{"name":"page","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"The page number","default":1,"title":"Page"},"description":"The page number"},{"name":"page_size","in":"query","required":false,"schema":{"anyOf":[{"type":"integer","maximum":200},{"type":"null"}],"description":"The number of element per page","default":20,"title":"Page Size"},"description":"The number of element per page"},{"name":"order_by","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"The field name of the element to sort by (Limited)","title":"Order By"},"description":"The field name of the element to sort by (Limited)"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/FoodListOut"},{"$ref":"#/components/schemas/ShortFoodListOut"}],"title":"Response List Food V1 Foods Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPBadRequest"}}}},"429":{"description":"Rate limit exceeded. Authenticated requests: 500/minute, 7200/hour. Concurrent limit: 10 requests. Check Retry-After header for reset time.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPRateLimitExceeded"}}}}},"x-llm-hint":"By default, only returns the tenant's custom ingredients. To search public databases (CNF, USDA) alongside custom ingredients, you MUST pass all=true. The source parameter filters by origin (USER, CNF, USDA) but does not enable database search."},"post":{"tags":["foods"],"summary":"Add Food","description":"Create a new ingredient (food).\n\n**Three creation modes:**\n1. **Standard create**: Provide ingredient data in request body. At minimum, `name_en` or `name_fr` should be provided.\n2. **Duplicate**: Use `food_id_to_duplicate` to clone an existing ingredient. Request body is ignored.\n3. **Subrecipe (Legacy)**: Use `recipe_id_to_subrecipe` to create a food from a recipe. Prefer adding recipes directly as ingredients using `source_recipe_id`.\n\n**Defaults applied on creation:**\n- `mass_quantity`: \"100\"\n- `mass_unit`: \"g\"\n- `refuse_pct`: \"0\"\n- `name`: \"New ingredient\" (or \"Nouvel ingredient\" if `default_name_lang=fr`)","operationId":"add_food_v1_foods_post","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"default_name_lang","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Language for the default name when no name is provided. Valid values: `en` (creates 'New ingredient'), `fr` (creates 'Nouvel ingredient').","default":"en","title":"Default Name Lang"},"description":"Language for the default name when no name is provided. Valid values: `en` (creates 'New ingredient'), `fr` (creates 'Nouvel ingredient')."},{"name":"food_id_to_duplicate","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Duplicate an existing ingredient by ID. When provided, the request body is ignored. The duplicated ingredient's name will have ' (Copy)' appended, and `source` will be set to `ID:{original_id}` for provenance tracking.","title":"Food Id To Duplicate"},"description":"Duplicate an existing ingredient by ID. When provided, the request body is ignored. The duplicated ingredient's name will have ' (Copy)' appended, and `source` will be set to `ID:{original_id}` for provenance tracking."},{"name":"recipe_id_to_subrecipe","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"(Legacy) Create a subrecipe food from a recipe. Prefer adding recipes directly as ingredients using `source_recipe_id`. When provided, request body is ignored.","title":"Recipe Id To Subrecipe"},"description":"(Legacy) Create a subrecipe food from a recipe. Prefer adding recipes directly as ingredients using `source_recipe_id`. When provided, request body is ignored."},{"name":"rename","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"description":"Override name for duplicate or subrecipe operations. Only used with `food_id_to_duplicate` or `recipe_id_to_subrecipe`.","title":"Rename"},"description":"Override name for duplicate or subrecipe operations. Only used with `food_id_to_duplicate` or `recipe_id_to_subrecipe`."},{"name":"no_default_name","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"description":"When `true`, do not assign a default name if none is provided. The `name` field will compute from `name_en` or `name_fr`.","default":false,"title":"No Default Name"},"description":"When `true`, do not assign a default name if none is provided. The `name` field will compute from `name_en` or `name_fr`."},{"name":"expand","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Comma-separated list of additional fields to include. Valid values: `nutriments_100g`, `tags`.","title":"Expand"},"description":"Comma-separated list of additional fields to include. Valid values: `nutriments_100g`, `tags`."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddFoodIn"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FoodOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPBadRequest"}}}},"429":{"description":"Rate limit exceeded. Authenticated requests: 500/minute, 7200/hour. Concurrent limit: 10 requests. Check Retry-After header for reset time.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPRateLimitExceeded"}}}}},"x-llm-hint":"This endpoint has THREE modes controlled by query parameters: (1) Standard create: no query params, provide body with name and nutriments. (2) Duplicate: pass food_id_to_duplicate={id}, body can be empty {}. (3) Create subrecipe from recipe: pass recipe_id_to_subrecipe={recipe_id}, body can be empty {}. Only use one mode at a time."}},"/v1/foods/batch_remove":{"post":{"tags":["foods"],"summary":"Batch Remove","description":"Delete multiple ingredients in a single request.\n\n**Behavior:**\n- Returns `true` on success\n- Stops on first error: if an invalid ID is encountered, remaining IDs are not processed\n- Invalid ID returns error code 1400 \"Invalid or missing food\"","operationId":"batch_remove_v1_foods_batch_remove_post","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"ids","in":"query","required":false,"schema":{"type":"string","description":"Ingredient IDs to delete. Comma-separated list. Example: `abc123,def456`.","title":"Ids"},"description":"Ingredient IDs to delete. Comma-separated list. Example: `abc123,def456`."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"boolean","title":"Response Batch Remove V1 Foods Batch Remove Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPBadRequest"}}}},"429":{"description":"Rate limit exceeded. Authenticated requests: 500/minute, 7200/hour. Concurrent limit: 10 requests. Check Retry-After header for reset time.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPRateLimitExceeded"}}}}},"x-llm-hint":"IDs are passed via query parameter 'ids' (comma-separated), NOT in request body. Stops on first error: if any ID is invalid, remaining IDs are not processed. Body should be empty {}."}},"/v1/foods/batch_csv_export":{"post":{"tags":["foods"],"summary":"Batch Csv Export","description":"Export multiple ingredients to CSV format.\n\nReturns a CSV file with all nutriment columns, ingredient metadata, allergens, and tag associations.\n\n**Restrictions:**\n- Trial accounts cannot use this endpoint (returns 403)\n- Returns error if no valid IDs provided","operationId":"batch_csv_export_v1_foods_batch_csv_export_post","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"ids","in":"query","required":false,"schema":{"type":"string","description":"Ingredient IDs to export. Comma-separated list. Example: `abc123,def456`.","title":"Ids"},"description":"Ingredient IDs to export. Comma-separated list. Example: `abc123,def456`."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPBadRequest"}}}},"429":{"description":"Rate limit exceeded. Authenticated requests: 500/minute, 7200/hour. Concurrent limit: 10 requests. Check Retry-After header for reset time.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPRateLimitExceeded"}}}}},"x-llm-hint":"IDs are passed via query parameter 'ids' (comma-separated), NOT in request body. Returns CSV text (not JSON). Requires paid subscription, blocked for trial accounts."}},"/v1/foods/{food_id}":{"get":{"tags":["foods"],"summary":"Get Food","description":"Get a single ingredient by ID.\n\nReturns the full ingredient object including nutriments, allergens, custom units, and warnings.","operationId":"get_food_v1_foods__food_id__get","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"food_id","in":"path","required":true,"schema":{"type":"string","description":"Ingredient ID to retrieve","title":"Food Id"},"description":"Ingredient ID to retrieve"},{"name":"expand","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Comma-separated list of additional fields to include. Valid values: `nutriments_100g` (adds normalized nutriments per 100g), `tags` (adds tag associations).","title":"Expand"},"description":"Comma-separated list of additional fields to include. Valid values: `nutriments_100g` (adds normalized nutriments per 100g), `tags` (adds tag associations)."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FoodOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPBadRequest"}}}},"429":{"description":"Rate limit exceeded. Authenticated requests: 500/minute, 7200/hour. Concurrent limit: 10 requests. Check Retry-After header for reset time.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPRateLimitExceeded"}}}}}},"post":{"tags":["foods"],"summary":"Edit Food","description":"Update an ingredient (full replacement mode).\n\n**Full update:** Sub-entities (`nutriments`, `custom_units`, `allergies`, `may_contains`) follow these rules:\n- **Omitting** a sub-entity field: existing data is **preserved**\n- **Sending empty** sub-entity (e.g., `\"nutriments\": {}`): existing data is **cleared**\n- **Sending partial** sub-entity: provided values replace existing, unlisted values are **cleared**\n\nUse PATCH to merge sub-entities instead of replacing.","operationId":"edit_food_v1_foods__food_id__post","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"food_id","in":"path","required":true,"schema":{"type":"string","description":"Ingredient ID to update","title":"Food Id"},"description":"Ingredient ID to update"},{"name":"expand","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Comma-separated list of additional fields to include. Valid values: `nutriments_100g`, `tags`.","title":"Expand"},"description":"Comma-separated list of additional fields to include. Valid values: `nutriments_100g`, `tags`."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EditFoodIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FoodOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPBadRequest"}}}},"429":{"description":"Rate limit exceeded. Authenticated requests: 500/minute, 7200/hour. Concurrent limit: 10 requests. Check Retry-After header for reset time.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPRateLimitExceeded"}}}}},"x-llm-hint":"POST replaces sub-entities (nutriments, custom_units, allergies). Omitting a field preserves existing data; sending empty object {} clears it. For partial updates that preserve existing sub-entities, use PATCH instead."},"patch":{"tags":["foods"],"summary":"Patch Food","description":"Update an ingredient (merge mode).\n\n**Partial update:** Sub-entities (`nutriments`, `custom_units`, `allergies`, `may_contains`) are **merged**.\n- Only provided values are added or updated\n- Existing values not present in the request are left untouched\n- To clear a specific nutriment, set its `amount` to `null`\n\nUse POST to replace sub-entities entirely.","operationId":"patch_food_v1_foods__food_id__patch","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"food_id","in":"path","required":true,"schema":{"type":"string","description":"Ingredient ID to update","title":"Food Id"},"description":"Ingredient ID to update"},{"name":"expand","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Comma-separated list of additional fields to include. Valid values: `nutriments_100g`, `tags`.","title":"Expand"},"description":"Comma-separated list of additional fields to include. Valid values: `nutriments_100g`, `tags`."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EditFoodIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FoodOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPBadRequest"}}}},"429":{"description":"Rate limit exceeded. Authenticated requests: 500/minute, 7200/hour. Concurrent limit: 10 requests. Check Retry-After header for reset time.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPRateLimitExceeded"}}}}},"x-llm-hint":"PATCH merges sub-entities: only items present in request are added/updated, existing items not mentioned are retained. For full replacement of sub-entities, use POST instead."},"delete":{"tags":["foods"],"summary":"Remove Food","description":"Delete an ingredient.\n\nReturns 204 No Content on success.\nReturns error 1400 \"Invalid or missing food\" if the ingredient does not exist or is not accessible.","operationId":"remove_food_v1_foods__food_id__delete","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"food_id","in":"path","required":true,"schema":{"type":"string","description":"Ingredient ID to delete","title":"Food Id"},"description":"Ingredient ID to delete"}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPBadRequest"}}}},"429":{"description":"Rate limit exceeded. Authenticated requests: 500/minute, 7200/hour. Concurrent limit: 10 requests. Check Retry-After header for reset time.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPRateLimitExceeded"}}}}}}},"/v1/foods/by_product_code/{product_code}":{"get":{"tags":["foods"],"summary":"Get Food By Product Code","description":"Get an ingredient by its product code (UPC/SKU).\n\nProduct codes are user-defined identifiers typically mapping to barcodes or internal SKUs.\nReturns the first match if multiple ingredients share the same product code.\nReturns error 1400 \"Invalid or missing food\" if no match found.","operationId":"get_food_by_product_code_v1_foods_by_product_code__product_code__get","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"product_code","in":"path","required":true,"schema":{"type":"string","description":"Product code/SKU to look up","title":"Product Code"},"description":"Product code/SKU to look up"},{"name":"expand","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Comma-separated list of additional fields to include. Valid values: `nutriments_100g` (adds normalized nutriments per 100g), `tags` (adds tag associations).","title":"Expand"},"description":"Comma-separated list of additional fields to include. Valid values: `nutriments_100g` (adds normalized nutriments per 100g), `tags` (adds tag associations)."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FoodOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPBadRequest"}}}},"429":{"description":"Rate limit exceeded. Authenticated requests: 500/minute, 7200/hour. Concurrent limit: 10 requests. Check Retry-After header for reset time.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPRateLimitExceeded"}}}}}}},"/v1/foods/{food_id}/custom_units":{"post":{"tags":["foods"],"summary":"Add Custom Unit","description":"Add a custom unit of measure to an ingredient.\n\nCustom units allow users to enter quantities like \"1 cup\" or \"1 slice\" by defining a conversion rate.\nExample: \"1 cup = 240 g\" would be `{name_en: \"cup\", rate: \"240\", unit_to: \"g\"}`.\n\nThe new custom unit appears in the ingredient's `available_units` array with its `id` as the `key`.","operationId":"add_custom_unit_v1_foods__food_id__custom_units_post","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"food_id","in":"path","required":true,"schema":{"type":"string","description":"Ingredient ID to add custom unit to","title":"Food Id"},"description":"Ingredient ID to add custom unit to"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddCustomUnitIn"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustomUnitOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPBadRequest"}}}},"429":{"description":"Rate limit exceeded. Authenticated requests: 500/minute, 7200/hour. Concurrent limit: 10 requests. Check Retry-After header for reset time.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPRateLimitExceeded"}}}}}}},"/v1/foods/{food_id}/custom_units/{custom_unit_id}":{"get":{"tags":["foods"],"summary":"Get Custom Unit","description":"Get a single custom unit by ID.","operationId":"get_custom_unit_v1_foods__food_id__custom_units__custom_unit_id__get","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"food_id","in":"path","required":true,"schema":{"type":"string","description":"Ingredient ID containing the custom unit","title":"Food Id"},"description":"Ingredient ID containing the custom unit"},{"name":"custom_unit_id","in":"path","required":true,"schema":{"type":"string","description":"Custom unit ID to retrieve","title":"Custom Unit Id"},"description":"Custom unit ID to retrieve"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustomUnitOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPBadRequest"}}}},"429":{"description":"Rate limit exceeded. Authenticated requests: 500/minute, 7200/hour. Concurrent limit: 10 requests. Check Retry-After header for reset time.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPRateLimitExceeded"}}}}}},"post":{"tags":["foods"],"summary":"Edit Custom Unit","description":"Update a custom unit.\n\nOnly provided fields are updated; omitted fields are preserved.","operationId":"edit_custom_unit_v1_foods__food_id__custom_units__custom_unit_id__post","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"food_id","in":"path","required":true,"schema":{"type":"string","description":"Ingredient ID containing the custom unit","title":"Food Id"},"description":"Ingredient ID containing the custom unit"},{"name":"custom_unit_id","in":"path","required":true,"schema":{"type":"string","description":"Custom unit ID to update","title":"Custom Unit Id"},"description":"Custom unit ID to update"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EditCustomUnitIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustomUnitOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPBadRequest"}}}},"429":{"description":"Rate limit exceeded. Authenticated requests: 500/minute, 7200/hour. Concurrent limit: 10 requests. Check Retry-After header for reset time.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPRateLimitExceeded"}}}}}},"delete":{"tags":["foods"],"summary":"Remove Custom Unit","description":"Delete a custom unit from an ingredient.\n\n**Note:** Request body must be provided (can be empty `{}`).\nReturns 204 No Content on success.","operationId":"remove_custom_unit_v1_foods__food_id__custom_units__custom_unit_id__delete","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"food_id","in":"path","required":true,"schema":{"type":"string","description":"Ingredient ID containing the custom unit","title":"Food Id"},"description":"Ingredient ID containing the custom unit"},{"name":"custom_unit_id","in":"path","required":true,"schema":{"type":"string","description":"Custom unit ID to delete","title":"Custom Unit Id"},"description":"Custom unit ID to delete"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeleteFoodIn"}}}},"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPBadRequest"}}}},"429":{"description":"Rate limit exceeded. Authenticated requests: 500/minute, 7200/hour. Concurrent limit: 10 requests. Check Retry-After header for reset time.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPRateLimitExceeded"}}}}}}},"/v1/foods/{food_id}/technical_file":{"get":{"tags":["foods"],"summary":"Download Technical File","description":"Download the technical file (specification sheet) attached to an ingredient.\n\nReturns the raw file content as a binary download with appropriate Content-Disposition header.\n\n**Restrictions:**\n- Trial accounts cannot use this endpoint (returns 403)\n- Returns empty response if no file is attached","operationId":"download_technical_file_v1_foods__food_id__technical_file_get","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"food_id","in":"path","required":true,"schema":{"type":"string","description":"Ingredient ID to download technical file from","title":"Food Id"},"description":"Ingredient ID to download technical file from"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPBadRequest"}}}},"429":{"description":"Rate limit exceeded. Authenticated requests: 500/minute, 7200/hour. Concurrent limit: 10 requests. Check Retry-After header for reset time.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPRateLimitExceeded"}}}}}},"post":{"tags":["foods"],"summary":"Add Technical File","description":"Upload a technical file (specification sheet) for an ingredient.\n\nOnly one file can be attached per ingredient. Uploading replaces any existing file.\n\n**Restrictions:**\n- Trial accounts cannot use this endpoint (returns 403)\n- Disallowed extensions: py, php, js, html, exe, sh\n\n**Request format:** multipart/form-data with field `upload_file`","operationId":"add_technical_file_v1_foods__food_id__technical_file_post","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"food_id","in":"path","required":true,"schema":{"type":"string","description":"Ingredient ID to attach technical file to","title":"Food Id"},"description":"Ingredient ID to attach technical file to"}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_add_technical_file_v1_foods__food_id__technical_file_post"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TechnicalFileOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPBadRequest"}}}},"429":{"description":"Rate limit exceeded. Authenticated requests: 500/minute, 7200/hour. Concurrent limit: 10 requests. Check Retry-After header for reset time.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPRateLimitExceeded"}}}}}},"delete":{"tags":["foods"],"summary":"Remove Technical File","description":"Delete the technical file from an ingredient.\n\n**Note:** Request body must be provided (can be empty `{}`).\n\n**Restrictions:**\n- Trial accounts cannot use this endpoint (returns 403)\n\nReturns 204 No Content on success.","operationId":"remove_technical_file_v1_foods__food_id__technical_file_delete","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"food_id","in":"path","required":true,"schema":{"type":"string","description":"Ingredient ID to remove technical file from","title":"Food Id"},"description":"Ingredient ID to remove technical file from"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RemoveTechnicalFileIn"}}}},"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPBadRequest"}}}},"429":{"description":"Rate limit exceeded. Authenticated requests: 500/minute, 7200/hour. Concurrent limit: 10 requests. Check Retry-After header for reset time.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPRateLimitExceeded"}}}}}}},"/v1/foods/{food_id}/subrecipe":{"post":{"tags":["foods"],"summary":"Update Subrecipe","description":"(Legacy) Sync a subrecipe food with its source recipe.\n\nSubrecipes are legacy; prefer adding recipes directly as ingredients using `source_recipe_id`, which auto-updates.\n\nUpdates the food's nutriments and allergens to match the current calculated values of the linked recipe.\nReturns error if the food is not a subrecipe (no `recipe_id` link).","operationId":"update_subrecipe_v1_foods__food_id__subrecipe_post","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"food_id","in":"path","required":true,"schema":{"type":"string","description":"Subrecipe ingredient ID to sync","title":"Food Id"},"description":"Subrecipe ingredient ID to sync"},{"name":"expand","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Comma-separated list of additional fields to include. Valid values: `nutriments_100g`, `tags`.","title":"Expand"},"description":"Comma-separated list of additional fields to include. Valid values: `nutriments_100g`, `tags`."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FoodOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPBadRequest"}}}},"429":{"description":"Rate limit exceeded. Authenticated requests: 500/minute, 7200/hour. Concurrent limit: 10 requests. Check Retry-After header for reset time.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPRateLimitExceeded"}}}}},"x-llm-hint":"SYNC operation, not create. Updates an existing subrecipe food to match current state of its source recipe. Updates nutriments and recipe_version_id. Does NOT update food name even if recipe name changed. Only works on foods that have recipe_id set."},"delete":{"tags":["foods"],"summary":"Unlink Subrecipe","description":"(Legacy) Unlink a subrecipe food from its source recipe.\n\nSubrecipes are legacy; prefer adding recipes directly as ingredients using `source_recipe_id`.\n\nConverts the subrecipe into a regular custom food by clearing `recipe_id` and `recipe_version_id`.\nThe food's nutriment data is preserved. Returns 204 No Content on success.","operationId":"unlink_subrecipe_v1_foods__food_id__subrecipe_delete","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"food_id","in":"path","required":true,"schema":{"type":"string","description":"Subrecipe ingredient ID to unlink","title":"Food Id"},"description":"Subrecipe ingredient ID to unlink"},{"name":"expand","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Comma-separated list of additional fields to include. Valid values: `nutriments_100g`, `tags`.","title":"Expand"},"description":"Comma-separated list of additional fields to include. Valid values: `nutriments_100g`, `tags`."}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPBadRequest"}}}},"429":{"description":"Rate limit exceeded. Authenticated requests: 500/minute, 7200/hour. Concurrent limit: 10 requests. Check Retry-After header for reset time.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPRateLimitExceeded"}}}}},"x-llm-hint":"UNLINK operation. Breaks the connection between a subrecipe food and its source recipe. Sets recipe_id and recipe_version_id to null. The food becomes a regular USER food that can be edited independently."}},"/v1/recipes":{"get":{"tags":["recipes"],"summary":"List Recipes","description":"List or search recipes.\n\nReturns a paginated list of recipes belonging to your organization.\n\n**Response modes:**\n- `short=true` (default): Returns 8 fields per recipe\n- `short=false`: Returns full recipe with ingredients, allergens, weights, etc. Page size capped at 20.\n\n**Filtering:**\n- `food_id`: Find recipes using a specific ingredient\n- `recipe_id`: Find recipes containing another recipe as a nested ingredient","operationId":"list_recipes_v1_recipes_get","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"short","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"description":"Returns a condensed response with a subset of fields (8 fields). When `false`, the full object is returned (39+ fields) but `page_size` is capped at 20 to limit memory usage.","default":true,"title":"Short"},"description":"Returns a condensed response with a subset of fields (8 fields). When `false`, the full object is returned (39+ fields) but `page_size` is capped at 20 to limit memory usage."},{"name":"search","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Search pattern. Searches `name` and `product_code`. For exact product_code lookup, use GET /v1/recipes/by_product_code/{product_code}.","title":"Search"},"description":"Search pattern. Searches `name` and `product_code`. For exact product_code lookup, use GET /v1/recipes/by_product_code/{product_code}."},{"name":"food_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter to recipes containing this ingredient (food) ID.","title":"Food Id"},"description":"Filter to recipes containing this ingredient (food) ID."},{"name":"recipe_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter to recipes containing this recipe as a nested ingredient.","title":"Recipe Id"},"description":"Filter to recipes containing this recipe as a nested ingredient."},{"name":"ids","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by specific recipe IDs. Comma-separated list. Example: `abc123,def456`.","title":"Ids"},"description":"Filter by specific recipe IDs. Comma-separated list. Example: `abc123,def456`."},{"name":"tags","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by tag IDs. Comma-separated list.","title":"Tags"},"description":"Filter by tag IDs. Comma-separated list."},{"name":"expand","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Comma-separated list of additional fields to include. Valid values: `nutriments` (calculated values), `nutriments_100g` (normalized per 100g), `previews` (legacy format), `previews_CAN2016`, `previews_US`, `nutriments_overwrite`, `volume`, `edible_volume`, `tags`, `ingredients.nutriments`, `ingredients.volume`, `ingredients.volume_display`, `ingredients.edible_volume`, `ingredients.edible_volume_display`.","title":"Expand"},"description":"Comma-separated list of additional fields to include. Valid values: `nutriments` (calculated values), `nutriments_100g` (normalized per 100g), `previews` (legacy format), `previews_CAN2016`, `previews_US`, `nutriments_overwrite`, `volume`, `edible_volume`, `tags`, `ingredients.nutriments`, `ingredients.volume`, `ingredients.volume_display`, `ingredients.edible_volume`, `ingredients.edible_volume_display`."},{"name":"page","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"The page number","default":1,"title":"Page"},"description":"The page number"},{"name":"page_size","in":"query","required":false,"schema":{"anyOf":[{"type":"integer","maximum":200},{"type":"null"}],"description":"The number of element per page","default":20,"title":"Page Size"},"description":"The number of element per page"},{"name":"order_by","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"The field name of the element to sort by (Limited)","title":"Order By"},"description":"The field name of the element to sort by (Limited)"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/RecipeListOut"},{"$ref":"#/components/schemas/ShortRecipeListOut"}],"title":"Response List Recipes V1 Recipes Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPBadRequest"}}}},"429":{"description":"Rate limit exceeded. Authenticated requests: 500/minute, 7200/hour. Concurrent limit: 10 requests. Check Retry-After header for reset time.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPRateLimitExceeded"}}}}}},"post":{"tags":["recipes"],"summary":"Add Recipe","description":"Create a new recipe.\n\n**Two creation modes:**\n1. **Standard create**: Provide recipe data in request body.\n2. **Duplicate**: Use `recipe_id_to_duplicate` to clone an existing recipe. Request body is ignored.\n\n**Defaults applied on creation:**\n- `yield_qty`: \"100\"\n- `yield_unit`: \"%\" (percentage of total weight)\n- `name`: \"New recipe\" (or \"Nouvelle recette\" if `default_name_lang=fr`)","operationId":"add_recipe_v1_recipes_post","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"default_name_lang","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Language for the default name when no name is provided. Valid values: `en` (creates 'New recipe'), `fr` (creates 'Nouvelle recette').","default":"en","title":"Default Name Lang"},"description":"Language for the default name when no name is provided. Valid values: `en` (creates 'New recipe'), `fr` (creates 'Nouvelle recette')."},{"name":"recipe_id_to_duplicate","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Duplicate an existing recipe by ID. When provided, the request body is ignored.","title":"Recipe Id To Duplicate"},"description":"Duplicate an existing recipe by ID. When provided, the request body is ignored."},{"name":"duplicate_scale","in":"query","required":false,"schema":{"anyOf":[{"example":"99.5","type":"string","format":"decimal"},{"type":"null"}],"description":"Scale factor for ingredient quantities when duplicating. Example: `2` doubles all quantities. Only used with `recipe_id_to_duplicate`.","title":"Duplicate Scale"},"description":"Scale factor for ingredient quantities when duplicating. Example: `2` doubles all quantities. Only used with `recipe_id_to_duplicate`."},{"name":"rename","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"description":"Override the name for the duplicated recipe. Only used with `recipe_id_to_duplicate`.","title":"Rename"},"description":"Override the name for the duplicated recipe. Only used with `recipe_id_to_duplicate`."},{"name":"expand","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Comma-separated list of additional fields to include. See GET /v1/recipes for valid values.","title":"Expand"},"description":"Comma-separated list of additional fields to include. See GET /v1/recipes for valid values."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddRecipeIn"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecipeOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPBadRequest"}}}},"429":{"description":"Rate limit exceeded. Authenticated requests: 500/minute, 7200/hour. Concurrent limit: 10 requests. Check Retry-After header for reset time.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPRateLimitExceeded"}}}}}}},"/v1/recipes/batch_remove":{"post":{"tags":["recipes"],"summary":"Batch Remove","description":"Delete multiple recipes in a single request.\n\n**Behavior:**\n- Returns `true` on success\n- Stops on first error: if an invalid ID is encountered, remaining IDs are not processed","operationId":"batch_remove_v1_recipes_batch_remove_post","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"ids","in":"query","required":false,"schema":{"type":"string","description":"Recipe IDs to delete. Comma-separated list. Example: `abc123,def456`.","title":"Ids"},"description":"Recipe IDs to delete. Comma-separated list. Example: `abc123,def456`."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"boolean","title":"Response Batch Remove V1 Recipes Batch Remove Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPBadRequest"}}}},"429":{"description":"Rate limit exceeded. Authenticated requests: 500/minute, 7200/hour. Concurrent limit: 10 requests. Check Retry-After header for reset time.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPRateLimitExceeded"}}}}},"x-llm-hint":"IDs are passed via query parameter 'ids' (comma-separated), NOT in request body. Body should be empty {}."}},"/v1/recipes/batch_csv_export":{"post":{"tags":["recipes"],"summary":"Batch Csv Export","description":"Export multiple recipes to CSV format.\n\nReturns a CSV file with recipe metadata and nutriment data.\n\n**Restrictions:**\n- Trial accounts cannot use this endpoint (returns 403)","operationId":"batch_csv_export_v1_recipes_batch_csv_export_post","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"ids","in":"query","required":false,"schema":{"type":"string","description":"Recipe IDs to export. Comma-separated list. Example: `abc123,def456`.","title":"Ids"},"description":"Recipe IDs to export. Comma-separated list. Example: `abc123,def456`."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPBadRequest"}}}},"429":{"description":"Rate limit exceeded. Authenticated requests: 500/minute, 7200/hour. Concurrent limit: 10 requests. Check Retry-After header for reset time.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPRateLimitExceeded"}}}}},"x-llm-hint":"IDs are passed via query parameter 'ids' (comma-separated), NOT in request body. Returns CSV text (not JSON). Requires paid subscription."}},"/v1/recipes/{recipe_id}":{"get":{"tags":["recipes"],"summary":"Get Recipe","description":"Get a single recipe by ID.\n\nReturns the full recipe object including ingredients, allergens, and computed weights.\n\n**Resized view:** Use `resized_view_qty` and `resized_view_unit` to get a virtual copy with all\ningredient quantities scaled proportionally. The original recipe is not modified.","operationId":"get_recipe_v1_recipes__recipe_id__get","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"recipe_id","in":"path","required":true,"schema":{"type":"string","description":"Recipe ID to retrieve","title":"Recipe Id"},"description":"Recipe ID to retrieve"},{"name":"resized_view_qty","in":"query","required":false,"schema":{"anyOf":[{"example":"99.5","type":"string","format":"decimal"},{"type":"null"}],"description":"Get a resized view with all values scaled to this quantity. Does not modify the recipe.","title":"Resized View Qty"},"description":"Get a resized view with all values scaled to this quantity. Does not modify the recipe."},{"name":"resized_view_unit","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"description":"Unit for resized_view_qty. Example: 'g', 'kg', 'lb'.","title":"Resized View Unit"},"description":"Unit for resized_view_qty. Example: 'g', 'kg', 'lb'."},{"name":"expand","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Comma-separated list of additional fields to include. See GET /v1/recipes for valid values.","title":"Expand"},"description":"Comma-separated list of additional fields to include. See GET /v1/recipes for valid values."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecipeOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPBadRequest"}}}},"429":{"description":"Rate limit exceeded. Authenticated requests: 500/minute, 7200/hour. Concurrent limit: 10 requests. Check Retry-After header for reset time.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPRateLimitExceeded"}}}}}},"post":{"tags":["recipes"],"summary":"Edit Recipe","description":"Update a recipe (full replacement mode).\n\n**Full update:** Sub-entities (`ingredients`, `extra_allergies`, `extra_may_contains`) follow these rules:\n- **Omitting** a sub-entity field: existing data is **preserved**\n- **Sending empty array** (e.g., `\"ingredients\": []`): existing items are **deleted**\n- **Sending items**: provided items replace existing items entirely\n\nUse PATCH to merge ingredients instead of replacing.","operationId":"edit_recipe_v1_recipes__recipe_id__post","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"recipe_id","in":"path","required":true,"schema":{"type":"string","description":"Recipe ID to update","title":"Recipe Id"},"description":"Recipe ID to update"},{"name":"expand","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Comma-separated list of additional fields to include. See GET /v1/recipes for valid values.","title":"Expand"},"description":"Comma-separated list of additional fields to include. See GET /v1/recipes for valid values."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EditRecipeIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecipeOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPBadRequest"}}}},"429":{"description":"Rate limit exceeded. Authenticated requests: 500/minute, 7200/hour. Concurrent limit: 10 requests. Check Retry-After header for reset time.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPRateLimitExceeded"}}}}},"x-llm-hint":"POST replaces the ingredients list entirely. Sending ingredients: [] deletes all ingredients. Omitting ingredients field preserves existing. For partial updates, use PATCH instead."},"patch":{"tags":["recipes"],"summary":"Patch Recipe","description":"Update a recipe (merge mode).\n\n**Partial update:** Sub-entities (`ingredients`, `extra_allergies`, `extra_may_contains`) are **merged**.\n- Only provided items are added or updated\n- Existing items not present in the request are left untouched\n- To remove an ingredient, use DELETE /v1/recipes/{recipe_id}/ingredients/{ingredient_id}\n\nUse POST to replace sub-entities entirely.","operationId":"patch_recipe_v1_recipes__recipe_id__patch","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"recipe_id","in":"path","required":true,"schema":{"type":"string","description":"Recipe ID to update","title":"Recipe Id"},"description":"Recipe ID to update"},{"name":"expand","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Comma-separated list of additional fields to include. See GET /v1/recipes for valid values.","title":"Expand"},"description":"Comma-separated list of additional fields to include. See GET /v1/recipes for valid values."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EditRecipeIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecipeOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPBadRequest"}}}},"429":{"description":"Rate limit exceeded. Authenticated requests: 500/minute, 7200/hour. Concurrent limit: 10 requests. Check Retry-After header for reset time.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPRateLimitExceeded"}}}}},"x-llm-hint":"PATCH merges ingredients: existing ingredients not mentioned are retained. For full replacement, use POST instead."},"delete":{"tags":["recipes"],"summary":"Remove Recipe","description":"Delete a recipe.\n\nReturns 204 No Content on success.\nReturns error 1400 \"Invalid or missing recipe\" if the recipe does not exist or is not accessible.","operationId":"remove_recipe_v1_recipes__recipe_id__delete","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"recipe_id","in":"path","required":true,"schema":{"type":"string","description":"Recipe ID to delete","title":"Recipe Id"},"description":"Recipe ID to delete"}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPBadRequest"}}}},"429":{"description":"Rate limit exceeded. Authenticated requests: 500/minute, 7200/hour. Concurrent limit: 10 requests. Check Retry-After header for reset time.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPRateLimitExceeded"}}}}}}},"/v1/recipes/by_product_code/{product_code}":{"get":{"tags":["recipes"],"summary":"Get Recipe By Product Code","description":"Get a recipe by its product code (UPC/SKU).\n\nProduct codes are user-defined identifiers typically mapping to barcodes or internal SKUs.\nReturns the first match if multiple recipes share the same product code.\nReturns error 1400 \"Invalid or missing recipe\" if no match found.","operationId":"get_recipe_by_product_code_v1_recipes_by_product_code__product_code__get","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"product_code","in":"path","required":true,"schema":{"type":"string","description":"Product code/SKU to look up","title":"Product Code"},"description":"Product code/SKU to look up"},{"name":"expand","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Comma-separated list of additional fields to include. See GET /v1/recipes for valid values.","title":"Expand"},"description":"Comma-separated list of additional fields to include. See GET /v1/recipes for valid values."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecipeOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPBadRequest"}}}},"429":{"description":"Rate limit exceeded. Authenticated requests: 500/minute, 7200/hour. Concurrent limit: 10 requests. Check Retry-After header for reset time.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPRateLimitExceeded"}}}}}}},"/v1/recipes/{recipe_id}/nutriments":{"get":{"tags":["recipes"],"summary":"Get Recipe Nutriments","description":"Get calculated nutriments for a recipe.\n\nReturns nutritional values for the complete recipe, or scaled to a specific quantity if `qty` and `unit` are provided.\n\nUseful for calculating per-serving or per-portion nutriment values without modifying the recipe.","operationId":"get_recipe_nutriments_v1_recipes__recipe_id__nutriments_get","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"recipe_id","in":"path","required":true,"schema":{"type":"string","description":"Recipe ID to get nutriments for","title":"Recipe Id"},"description":"Recipe ID to get nutriments for"},{"name":"qty","in":"query","required":false,"schema":{"anyOf":[{"example":"99.5","type":"string","format":"decimal"},{"type":"null"}],"description":"Quantity to calculate nutriments for. If omitted, returns nutriments for the complete recipe.","title":"Qty"},"description":"Quantity to calculate nutriments for. If omitted, returns nutriments for the complete recipe."},{"name":"unit","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"description":"Unit for qty. Example: 'g', 'serving'. Uses recipe's available_units.","title":"Unit"},"description":"Unit for qty. Example: 'g', 'serving'. Uses recipe's available_units."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NutrimentsOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPBadRequest"}}}},"429":{"description":"Rate limit exceeded. Authenticated requests: 500/minute, 7200/hour. Concurrent limit: 10 requests. Check Retry-After header for reset time.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPRateLimitExceeded"}}}}}}},"/v1/recipes/{recipe_id}/xlsx_report":{"post":{"tags":["recipes"],"summary":"Xlsx Report","description":"Generate an Excel (XLSX) report for a recipe.\n\nReturns a downloadable XLSX file containing recipe details, ingredients, and nutritional breakdown.\n\n**Restrictions:**\n- Trial accounts cannot use this endpoint (returns 403)","operationId":"xlsx_report_v1_recipes__recipe_id__xlsx_report_post","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"recipe_id","in":"path","required":true,"schema":{"type":"string","description":"Recipe ID to generate report for","title":"Recipe Id"},"description":"Recipe ID to generate report for"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPBadRequest"}}}},"429":{"description":"Rate limit exceeded. Authenticated requests: 500/minute, 7200/hour. Concurrent limit: 10 requests. Check Retry-After header for reset time.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPRateLimitExceeded"}}}}}}},"/v1/recipes/{recipe_id}/ingredients":{"post":{"tags":["recipes"],"summary":"Add Ingredient","description":"Add an ingredient line to a recipe.\n\nRequires either `food_id` (for a food/ingredient) or `food_recipe_id` (for a nested recipe).\nThe ingredient is added at the end of the recipe's ingredient list by default.","operationId":"add_ingredient_v1_recipes__recipe_id__ingredients_post","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"recipe_id","in":"path","required":true,"schema":{"type":"string","description":"Recipe ID to add ingredient to","title":"Recipe Id"},"description":"Recipe ID to add ingredient to"},{"name":"expand","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Comma-separated list of additional fields. Valid values: `edible_volume`, `edible_volume_display`.","title":"Expand"},"description":"Comma-separated list of additional fields. Valid values: `edible_volume`, `edible_volume_display`."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddIngredientIn"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IngredientOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPBadRequest"}}}},"429":{"description":"Rate limit exceeded. Authenticated requests: 500/minute, 7200/hour. Concurrent limit: 10 requests. Check Retry-After header for reset time.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPRateLimitExceeded"}}}}},"x-llm-hint":"Adding an ingredient requires exactly ONE of: food_id (reference a food) OR source_recipe_id (reference another recipe as nested ingredient). Do not provide both."}},"/v1/recipes/{recipe_id}/ingredients/{ingredient_id}":{"get":{"tags":["recipes"],"summary":"Get Ingredient","description":"Get a single ingredient line from a recipe.","operationId":"get_ingredient_v1_recipes__recipe_id__ingredients__ingredient_id__get","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"recipe_id","in":"path","required":true,"schema":{"type":"string","description":"Recipe ID containing the ingredient","title":"Recipe Id"},"description":"Recipe ID containing the ingredient"},{"name":"ingredient_id","in":"path","required":true,"schema":{"type":"string","description":"Ingredient line ID to retrieve","title":"Ingredient Id"},"description":"Ingredient line ID to retrieve"},{"name":"expand","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Comma-separated list of additional fields. Valid values: `edible_volume`, `edible_volume_display`.","title":"Expand"},"description":"Comma-separated list of additional fields. Valid values: `edible_volume`, `edible_volume_display`."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IngredientOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPBadRequest"}}}},"429":{"description":"Rate limit exceeded. Authenticated requests: 500/minute, 7200/hour. Concurrent limit: 10 requests. Check Retry-After header for reset time.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPRateLimitExceeded"}}}}}},"post":{"tags":["recipes"],"summary":"Edit Ingredient","description":"Update an ingredient line in a recipe.\n\nOnly provided fields are updated; omitted fields are preserved.","operationId":"edit_ingredient_v1_recipes__recipe_id__ingredients__ingredient_id__post","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"recipe_id","in":"path","required":true,"schema":{"type":"string","description":"Recipe ID containing the ingredient","title":"Recipe Id"},"description":"Recipe ID containing the ingredient"},{"name":"ingredient_id","in":"path","required":true,"schema":{"type":"string","description":"Ingredient line ID to update","title":"Ingredient Id"},"description":"Ingredient line ID to update"},{"name":"expand","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Comma-separated list of additional fields. Valid values: `edible_volume`, `edible_volume_display`.","title":"Expand"},"description":"Comma-separated list of additional fields. Valid values: `edible_volume`, `edible_volume_display`."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EditIngredientIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IngredientOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPBadRequest"}}}},"429":{"description":"Rate limit exceeded. Authenticated requests: 500/minute, 7200/hour. Concurrent limit: 10 requests. Check Retry-After header for reset time.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPRateLimitExceeded"}}}}}},"delete":{"tags":["recipes"],"summary":"Remove Ingredient","description":"Remove an ingredient line from a recipe.\n\n**Note:** Request body must be provided (can be empty `{}`).\nReturns 204 No Content on success.","operationId":"remove_ingredient_v1_recipes__recipe_id__ingredients__ingredient_id__delete","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"recipe_id","in":"path","required":true,"schema":{"type":"string","description":"Recipe ID containing the ingredient","title":"Recipe Id"},"description":"Recipe ID containing the ingredient"},{"name":"ingredient_id","in":"path","required":true,"schema":{"type":"string","description":"Ingredient line ID to delete","title":"Ingredient Id"},"description":"Ingredient line ID to delete"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeleteRecipeIn"}}}},"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPBadRequest"}}}},"429":{"description":"Rate limit exceeded. Authenticated requests: 500/minute, 7200/hour. Concurrent limit: 10 requests. Check Retry-After header for reset time.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPRateLimitExceeded"}}}}}}},"/v1/recipes/{recipe_id}/custom_units":{"post":{"tags":["recipes"],"summary":"Add Custom Unit","operationId":"add_custom_unit_v1_recipes__recipe_id__custom_units_post","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"recipe_id","in":"path","required":true,"schema":{"type":"string","description":"Recipe ID to add custom unit to","title":"Recipe Id"},"description":"Recipe ID to add custom unit to"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddRecipeCustomUnitIn"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecipeCustomUnitOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPBadRequest"}}}},"429":{"description":"Rate limit exceeded. Authenticated requests: 500/minute, 7200/hour. Concurrent limit: 10 requests. Check Retry-After header for reset time.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPRateLimitExceeded"}}}}}}},"/v1/recipes/{recipe_id}/custom_units/{custom_unit_id}":{"get":{"tags":["recipes"],"summary":"Get Custom Unit","operationId":"get_custom_unit_v1_recipes__recipe_id__custom_units__custom_unit_id__get","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"recipe_id","in":"path","required":true,"schema":{"type":"string","description":"Recipe ID containing the custom unit","title":"Recipe Id"},"description":"Recipe ID containing the custom unit"},{"name":"custom_unit_id","in":"path","required":true,"schema":{"type":"string","description":"Custom unit ID to retrieve","title":"Custom Unit Id"},"description":"Custom unit ID to retrieve"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecipeCustomUnitOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPBadRequest"}}}},"429":{"description":"Rate limit exceeded. Authenticated requests: 500/minute, 7200/hour. Concurrent limit: 10 requests. Check Retry-After header for reset time.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPRateLimitExceeded"}}}}}},"post":{"tags":["recipes"],"summary":"Edit Custom Unit","operationId":"edit_custom_unit_v1_recipes__recipe_id__custom_units__custom_unit_id__post","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"recipe_id","in":"path","required":true,"schema":{"type":"string","description":"Recipe ID containing the custom unit","title":"Recipe Id"},"description":"Recipe ID containing the custom unit"},{"name":"custom_unit_id","in":"path","required":true,"schema":{"type":"string","description":"Custom unit ID to update","title":"Custom Unit Id"},"description":"Custom unit ID to update"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EditRecipeCustomUnitIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecipeCustomUnitOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPBadRequest"}}}},"429":{"description":"Rate limit exceeded. Authenticated requests: 500/minute, 7200/hour. Concurrent limit: 10 requests. Check Retry-After header for reset time.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPRateLimitExceeded"}}}}}},"delete":{"tags":["recipes"],"summary":"Remove Custom Unit","operationId":"remove_custom_unit_v1_recipes__recipe_id__custom_units__custom_unit_id__delete","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"recipe_id","in":"path","required":true,"schema":{"type":"string","description":"Recipe ID containing the custom unit","title":"Recipe Id"},"description":"Recipe ID containing the custom unit"},{"name":"custom_unit_id","in":"path","required":true,"schema":{"type":"string","description":"Custom unit ID to delete","title":"Custom Unit Id"},"description":"Custom unit ID to delete"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeleteRecipeCustomUnitIn"}}}},"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPBadRequest"}}}},"429":{"description":"Rate limit exceeded. Authenticated requests: 500/minute, 7200/hour. Concurrent limit: 10 requests. Check Retry-After header for reset time.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPRateLimitExceeded"}}}}}}},"/v1/labels":{"get":{"tags":["labels"],"summary":"List Labels","description":"List Nutrition Facts Table labels.\n\nReturns a paginated list of NFT label configurations. Use `recipe_id` to filter labels for a specific recipe.","operationId":"list_labels_v1_labels_get","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"short","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"description":"Returns a condensed response. When `false`, full objects returned but `page_size` capped at 20.","default":true,"title":"Short"},"description":"Returns a condensed response. When `false`, full objects returned but `page_size` capped at 20."},{"name":"recipe_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter to labels for this recipe ID.","title":"Recipe Id"},"description":"Filter to labels for this recipe ID."},{"name":"ids","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by specific label IDs. Comma-separated list. Example: `abc123,def456`.","title":"Ids"},"description":"Filter by specific label IDs. Comma-separated list. Example: `abc123,def456`."},{"name":"page","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"The page number","default":1,"title":"Page"},"description":"The page number"},{"name":"page_size","in":"query","required":false,"schema":{"anyOf":[{"type":"integer","maximum":200},{"type":"null"}],"description":"The number of element per page","default":20,"title":"Page Size"},"description":"The number of element per page"},{"name":"order_by","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"The field name of the element to sort by (Limited)","title":"Order By"},"description":"The field name of the element to sort by (Limited)"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/LabelListOut"},{"$ref":"#/components/schemas/ShortLabelListOut"}],"title":"Response List Labels V1 Labels Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPBadRequest"}}}},"429":{"description":"Rate limit exceeded. Authenticated requests: 500/minute, 7200/hour. Concurrent limit: 10 requests. Check Retry-After header for reset time.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPRateLimitExceeded"}}}}}},"post":{"tags":["labels"],"summary":"Add Label","description":"Create a new Nutrition Facts Table label.\n\n**Required fields:** `recipe_id` and `concrete_type`.\n\n**Defaults:**\n- `concrete_type`: Required - specify 'CAN2016' (Canadian) or 'US' (American). See GET /v1/utils/concrete_types\n- `label_format`: \"standard\" (other formats from GET /v1/utils/label_rules/{concrete_type})\n- `label_language`: \"en\" (for bilingual formats, determines which language appears first)\n- `serving_qty`: \"100\"\n- `serving_unit`: \"g\"","operationId":"add_label_v1_labels_post","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"default_name_lang","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Language for default name. Valid values: `en` (creates 'New label'), `fr` (creates 'Nouvelle etiquette').","default":"en","title":"Default Name Lang"},"description":"Language for default name. Valid values: `en` (creates 'New label'), `fr` (creates 'Nouvelle etiquette')."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddLabelIn"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LabelOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPBadRequest"}}}},"429":{"description":"Rate limit exceeded. Authenticated requests: 500/minute, 7200/hour. Concurrent limit: 10 requests. Check Retry-After header for reset time.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPRateLimitExceeded"}}}}}}},"/v1/labels/batch_remove":{"post":{"tags":["labels"],"summary":"Batch Remove","description":"Delete multiple labels in a single request.\n\nReturns `true` on success. Stops on first error.","operationId":"batch_remove_v1_labels_batch_remove_post","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"ids","in":"query","required":false,"schema":{"type":"string","description":"Label IDs to delete. Comma-separated list. Example: `abc123,def456`.","title":"Ids"},"description":"Label IDs to delete. Comma-separated list. Example: `abc123,def456`."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"boolean","title":"Response Batch Remove V1 Labels Batch Remove Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPBadRequest"}}}},"429":{"description":"Rate limit exceeded. Authenticated requests: 500/minute, 7200/hour. Concurrent limit: 10 requests. Check Retry-After header for reset time.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPRateLimitExceeded"}}}}},"x-llm-hint":"IDs are passed via query parameter 'ids' (comma-separated), NOT in request body. Body should be empty {}."}},"/v1/labels/{label_id}":{"get":{"tags":["labels"],"summary":"Get Label","description":"Get a single label by ID.","operationId":"get_label_v1_labels__label_id__get","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"label_id","in":"path","required":true,"schema":{"type":"string","description":"Label ID to retrieve","title":"Label Id"},"description":"Label ID to retrieve"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LabelOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPBadRequest"}}}},"429":{"description":"Rate limit exceeded. Authenticated requests: 500/minute, 7200/hour. Concurrent limit: 10 requests. Check Retry-After header for reset time.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPRateLimitExceeded"}}}}}},"post":{"tags":["labels"],"summary":"Edit Label","description":"Update a label (full replacement mode).\n\n**Full update:** Sub-entities (`label_additional_recipes`, `supplemented_cautionary_statements`) follow these rules:\n- **Omitting** a sub-entity field: existing data is **preserved**\n- **Sending empty array**: existing items are **deleted**\n- **Sending items**: provided items replace existing items entirely\n\nUse PATCH to merge instead.","operationId":"edit_label_v1_labels__label_id__post","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"label_id","in":"path","required":true,"schema":{"type":"string","description":"Label ID to update","title":"Label Id"},"description":"Label ID to update"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EditLabelIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LabelOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPBadRequest"}}}},"429":{"description":"Rate limit exceeded. Authenticated requests: 500/minute, 7200/hour. Concurrent limit: 10 requests. Check Retry-After header for reset time.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPRateLimitExceeded"}}}}},"x-llm-hint":"POST replaces label_additional_recipes list entirely. For partial updates, use PATCH instead."},"patch":{"tags":["labels"],"summary":"Patch Label","description":"Update a label (merge mode).\n\n**Partial update:** Sub-entities (`label_additional_recipes`, `supplemented_cautionary_statements`) are **merged**.\n- Only provided items are added or updated\n- Existing items not present in the request are left untouched\n\nUse POST to replace sub-entities entirely.","operationId":"patch_label_v1_labels__label_id__patch","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"label_id","in":"path","required":true,"schema":{"type":"string","description":"Label ID to update","title":"Label Id"},"description":"Label ID to update"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EditLabelIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LabelOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPBadRequest"}}}},"429":{"description":"Rate limit exceeded. Authenticated requests: 500/minute, 7200/hour. Concurrent limit: 10 requests. Check Retry-After header for reset time.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPRateLimitExceeded"}}}}},"x-llm-hint":"PATCH merges label_additional_recipes: existing entries not mentioned are retained. For full replacement, use POST instead."},"delete":{"tags":["labels"],"summary":"Remove Label","description":"Delete a label.\n\nReturns 204 No Content on success.","operationId":"remove_label_v1_labels__label_id__delete","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"label_id","in":"path","required":true,"schema":{"type":"string","description":"Label ID to delete","title":"Label Id"},"description":"Label ID to delete"}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPBadRequest"}}}},"429":{"description":"Rate limit exceeded. Authenticated requests: 500/minute, 7200/hour. Concurrent limit: 10 requests. Check Retry-After header for reset time.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPRateLimitExceeded"}}}}}}},"/v1/labels/{label_id}/render.{output_format}":{"get":{"tags":["labels"],"summary":"Render Label","description":"Render a Nutrition Facts Table label.\n\n**Output formats:**\n- `pdf`: PDF document (recommended for printing)\n- `png`: PNG image\n- `jpg`: JPEG image\n- `bmp`: BMP image\n- `eps`: EPS vector format\n- `html`: HTML markup (only format supporting `json=true`)\n\nReturns the rendered label as a binary download with appropriate Content-Type header.","operationId":"render_label_v1_labels__label_id__render__output_format__get","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"label_id","in":"path","required":true,"schema":{"type":"string","description":"Label ID to render","title":"Label Id"},"description":"Label ID to render"},{"name":"output_format","in":"path","required":true,"schema":{"type":"string","description":"Output format: 'pdf', 'png', 'jpg', 'bmp', 'eps', or 'html'","title":"Output Format"},"description":"Output format: 'pdf', 'png', 'jpg', 'bmp', 'eps', or 'html'"},{"name":"json","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"description":"When `true`, return JSON response with content (for HTML only). When `false`, return binary file download.","default":false,"title":"Json"},"description":"When `true`, return JSON response with content (for HTML only). When `false`, return binary file download."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPBadRequest"}}}},"429":{"description":"Rate limit exceeded. Authenticated requests: 500/minute, 7200/hour. Concurrent limit: 10 requests. Check Retry-After header for reset time.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPRateLimitExceeded"}}}}}}},"/v1/labels/{label_id}/measure":{"get":{"tags":["labels"],"summary":"Measure Render Label","description":"Get the dimensions of a rendered label.\n\nReturns width, height, and area in inches. Useful for packaging layout planning.","operationId":"measure_render_label_v1_labels__label_id__measure_get","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"label_id","in":"path","required":true,"schema":{"type":"string","description":"Label ID to measure","title":"Label Id"},"description":"Label ID to measure"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LabelMeasureOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPBadRequest"}}}},"429":{"description":"Rate limit exceeded. Authenticated requests: 500/minute, 7200/hour. Concurrent limit: 10 requests. Check Retry-After header for reset time.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPRateLimitExceeded"}}}}}}},"/v1/labels/{label_id}/label_additional_recipes":{"get":{"tags":["labels"],"summary":"List Label Additional Recipes","description":"List additional recipe columns for a label.\n\nUsed for dual-column NFTs showing 'as packaged' and 'as prepared' values.","operationId":"list_label_additional_recipes_v1_labels__label_id__label_additional_recipes_get","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"label_id","in":"path","required":true,"schema":{"type":"string","description":"Label ID","title":"Label Id"},"description":"Label ID"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LabelAdditionalRecipesListOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPBadRequest"}}}},"429":{"description":"Rate limit exceeded. Authenticated requests: 500/minute, 7200/hour. Concurrent limit: 10 requests. Check Retry-After header for reset time.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPRateLimitExceeded"}}}}}},"post":{"tags":["labels"],"summary":"Add Label Additional Recipe","description":"Add an additional recipe column to a label.","operationId":"add_label_additional_recipe_v1_labels__label_id__label_additional_recipes_post","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"label_id","in":"path","required":true,"schema":{"type":"string","description":"Label ID","title":"Label Id"},"description":"Label ID"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddLabelAdditionalRecipeIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LabelAdditionalRecipesOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPBadRequest"}}}},"429":{"description":"Rate limit exceeded. Authenticated requests: 500/minute, 7200/hour. Concurrent limit: 10 requests. Check Retry-After header for reset time.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPRateLimitExceeded"}}}}}}},"/v1/labels/{label_id}/label_additional_recipes/{label_additional_recipe_id}":{"get":{"tags":["labels"],"summary":"Get Label Additional Recipe","description":"Get a single additional recipe column by ID.","operationId":"get_label_additional_recipe_v1_labels__label_id__label_additional_recipes__label_additional_recipe_id__get","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"label_id","in":"path","required":true,"schema":{"type":"string","description":"Label ID","title":"Label Id"},"description":"Label ID"},{"name":"label_additional_recipe_id","in":"path","required":true,"schema":{"type":"string","description":"Additional recipe ID","title":"Label Additional Recipe Id"},"description":"Additional recipe ID"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LabelAdditionalRecipesOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPBadRequest"}}}},"429":{"description":"Rate limit exceeded. Authenticated requests: 500/minute, 7200/hour. Concurrent limit: 10 requests. Check Retry-After header for reset time.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPRateLimitExceeded"}}}}}},"post":{"tags":["labels"],"summary":"Edit Label Additional Recipe","description":"Update an additional recipe column.","operationId":"edit_label_additional_recipe_v1_labels__label_id__label_additional_recipes__label_additional_recipe_id__post","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"label_id","in":"path","required":true,"schema":{"type":"string","description":"Label ID","title":"Label Id"},"description":"Label ID"},{"name":"label_additional_recipe_id","in":"path","required":true,"schema":{"type":"string","description":"Additional recipe ID to update","title":"Label Additional Recipe Id"},"description":"Additional recipe ID to update"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EditLabelAdditionalRecipeIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LabelAdditionalRecipesOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPBadRequest"}}}},"429":{"description":"Rate limit exceeded. Authenticated requests: 500/minute, 7200/hour. Concurrent limit: 10 requests. Check Retry-After header for reset time.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPRateLimitExceeded"}}}}}},"delete":{"tags":["labels"],"summary":"Remove Label Additional Recipe","description":"Delete an additional recipe column from a label.\n\nReturns 204 No Content on success.","operationId":"remove_label_additional_recipe_v1_labels__label_id__label_additional_recipes__label_additional_recipe_id__delete","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"label_id","in":"path","required":true,"schema":{"type":"string","description":"Label ID","title":"Label Id"},"description":"Label ID"},{"name":"label_additional_recipe_id","in":"path","required":true,"schema":{"type":"string","description":"Additional recipe ID to delete","title":"Label Additional Recipe Id"},"description":"Additional recipe ID to delete"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RemoveLabelAdditionalRecipe"}}}},"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPBadRequest"}}}},"429":{"description":"Rate limit exceeded. Authenticated requests: 500/minute, 7200/hour. Concurrent limit: 10 requests. Check Retry-After header for reset time.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPRateLimitExceeded"}}}}}}},"/v1/fop_labels":{"get":{"tags":["fop_labels"],"summary":"List Fop Labels","description":"List front-of-package (FOP) labels.\n\nFOP labels are nutrition symbols (e.g., Health Canada's magnifying glass symbol) that appear on product packaging. Filter by recipe_id to get FOP labels for a specific recipe, or by ids for specific labels.","operationId":"list_fop_labels_v1_fop_labels_get","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"recipe_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter FOP labels by recipe ID","title":"Recipe Id"},"description":"Filter FOP labels by recipe ID"},{"name":"ids","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by specific FOP label IDs (comma-separated)","title":"Ids"},"description":"Filter by specific FOP label IDs (comma-separated)"},{"name":"page","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"The page number","default":1,"title":"Page"},"description":"The page number"},{"name":"page_size","in":"query","required":false,"schema":{"anyOf":[{"type":"integer","maximum":200},{"type":"null"}],"description":"The number of element per page","default":20,"title":"Page Size"},"description":"The number of element per page"},{"name":"order_by","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"The field name of the element to sort by (Limited)","title":"Order By"},"description":"The field name of the element to sort by (Limited)"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FopLabelListOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPBadRequest"}}}},"429":{"description":"Rate limit exceeded. Authenticated requests: 500/minute, 7200/hour. Concurrent limit: 10 requests. Check Retry-After header for reset time.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPRateLimitExceeded"}}}}}},"post":{"tags":["fop_labels"],"summary":"Add Fop Label","description":"Create a new front-of-package (FOP) label.\n\nRequires recipe_id and concrete_type. The FOP label determines whether a nutrition symbol must appear on packaging based on sodium, sugar, and saturated fat thresholds. Set is_prepackaged_meal=true for prepared meals (different thresholds apply).","operationId":"add_fop_label_v1_fop_labels_post","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"default_name_lang","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Language ('en' or 'fr') for the auto-generated default name","default":"en","title":"Default Name Lang"},"description":"Language ('en' or 'fr') for the auto-generated default name"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddFopLabelIn"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FopLabelOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPBadRequest"}}}},"429":{"description":"Rate limit exceeded. Authenticated requests: 500/minute, 7200/hour. Concurrent limit: 10 requests. Check Retry-After header for reset time.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPRateLimitExceeded"}}}}}}},"/v1/fop_labels/batch_remove":{"post":{"tags":["fop_labels"],"summary":"Batch Remove","description":"Delete multiple FOP labels in a single request.\n\nNote: IDs are passed via query parameter, not request body. Processing stops on the first invalid ID.","operationId":"batch_remove_v1_fop_labels_batch_remove_post","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"ids","in":"query","required":false,"schema":{"type":"string","description":"FOP label IDs to delete (comma-separated). Stops on first error.","title":"Ids"},"description":"FOP label IDs to delete (comma-separated). Stops on first error."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"boolean","title":"Response Batch Remove V1 Fop Labels Batch Remove Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPBadRequest"}}}},"429":{"description":"Rate limit exceeded. Authenticated requests: 500/minute, 7200/hour. Concurrent limit: 10 requests. Check Retry-After header for reset time.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPRateLimitExceeded"}}}}}}},"/v1/fop_labels/{fop_label_id}":{"get":{"tags":["fop_labels"],"summary":"Get Fop Label","description":"Get a single front-of-package label by ID.","operationId":"get_fop_label_v1_fop_labels__fop_label_id__get","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"fop_label_id","in":"path","required":true,"schema":{"type":"string","description":"FOP label ID to retrieve","title":"Fop Label Id"},"description":"FOP label ID to retrieve"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FopLabelOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPBadRequest"}}}},"429":{"description":"Rate limit exceeded. Authenticated requests: 500/minute, 7200/hour. Concurrent limit: 10 requests. Check Retry-After header for reset time.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPRateLimitExceeded"}}}}}},"post":{"tags":["fop_labels"],"summary":"Edit Fop Label","description":"Update a front-of-package label.\n\nAll provided fields are merged with existing values (PATCH-like behavior).","operationId":"edit_fop_label_v1_fop_labels__fop_label_id__post","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"fop_label_id","in":"path","required":true,"schema":{"type":"string","description":"FOP label ID to update","title":"Fop Label Id"},"description":"FOP label ID to update"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EditFopLabelIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FopLabelOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPBadRequest"}}}},"429":{"description":"Rate limit exceeded. Authenticated requests: 500/minute, 7200/hour. Concurrent limit: 10 requests. Check Retry-After header for reset time.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPRateLimitExceeded"}}}}}},"delete":{"tags":["fop_labels"],"summary":"Remove Fop Label","description":"Delete a front-of-package label.","operationId":"remove_fop_label_v1_fop_labels__fop_label_id__delete","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"fop_label_id","in":"path","required":true,"schema":{"type":"string","description":"FOP label ID to delete","title":"Fop Label Id"},"description":"FOP label ID to delete"}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPBadRequest"}}}},"429":{"description":"Rate limit exceeded. Authenticated requests: 500/minute, 7200/hour. Concurrent limit: 10 requests. Check Retry-After header for reset time.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPRateLimitExceeded"}}}}}}},"/v1/fop_labels/{fop_label_id}/render.{output_format}":{"get":{"tags":["fop_labels"],"summary":"Render Fop Label","description":"Render a front-of-package label to an image or document.\n\nReturns binary content with appropriate Content-Type header. Supported formats: pdf, png, jpg, bmp, eps.","operationId":"render_fop_label_v1_fop_labels__fop_label_id__render__output_format__get","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"fop_label_id","in":"path","required":true,"schema":{"type":"string","description":"FOP label ID to render","title":"Fop Label Id"},"description":"FOP label ID to render"},{"name":"output_format","in":"path","required":true,"schema":{"type":"string","description":"Output format: 'pdf', 'png', 'jpg', 'bmp', or 'eps'","title":"Output Format"},"description":"Output format: 'pdf', 'png', 'jpg', 'bmp', or 'eps'"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPBadRequest"}}}},"429":{"description":"Rate limit exceeded. Authenticated requests: 500/minute, 7200/hour. Concurrent limit: 10 requests. Check Retry-After header for reset time.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPRateLimitExceeded"}}}}}}},"/v1/tags/food_tags":{"get":{"tags":["tags[food]"],"summary":"List Food Tags","description":"List all food tags for the current tenant.","operationId":"list_food_tags_v1_tags_food_tags_get","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"page","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"The page number (null returns all)","title":"Page"},"description":"The page number (null returns all)"},{"name":"page_size","in":"query","required":false,"schema":{"anyOf":[{"type":"integer","maximum":200},{"type":"null"}],"description":"The number of element per page","default":20,"title":"Page Size"},"description":"The number of element per page"},{"name":"order_by","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"The field name of the element to sort by (Limited)","title":"Order By"},"description":"The field name of the element to sort by (Limited)"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FoodTagListOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPBadRequest"}}}},"429":{"description":"Rate limit exceeded. Authenticated requests: 500/minute, 7200/hour. Concurrent limit: 10 requests. Check Retry-After header for reset time.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPRateLimitExceeded"}}}}}},"post":{"tags":["tags[food]"],"summary":"Add Food Tag","description":"Create a new food tag.\n\nTags are used to organize and filter foods in list views.","operationId":"add_food_tag_v1_tags_food_tags_post","security":[{"APIKeyHeader":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddFoodTagIn"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FoodTagOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPBadRequest"}}}},"429":{"description":"Rate limit exceeded. Authenticated requests: 500/minute, 7200/hour. Concurrent limit: 10 requests. Check Retry-After header for reset time.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPRateLimitExceeded"}}}}}}},"/v1/tags/food_tags/batch_remove":{"post":{"tags":["tags[food]"],"summary":"Batch Remove","description":"Delete multiple food tags.","operationId":"batch_remove_v1_tags_food_tags_batch_remove_post","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"ids","in":"query","required":false,"schema":{"type":"string","description":"IDs to delete (comma-separated)","title":"Ids"},"description":"IDs to delete (comma-separated)"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"boolean","title":"Response Batch Remove V1 Tags Food Tags Batch Remove Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPBadRequest"}}}},"429":{"description":"Rate limit exceeded. Authenticated requests: 500/minute, 7200/hour. Concurrent limit: 10 requests. Check Retry-After header for reset time.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPRateLimitExceeded"}}}}}}},"/v1/tags/food_tags/batch_merge":{"post":{"tags":["tags[food]"],"summary":"Batch Merge","description":"Merge multiple food tags into one.\n\nAll foods with the merged tags are reassigned to the first tag. Other tags are deleted.","operationId":"batch_merge_v1_tags_food_tags_batch_merge_post","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"ids","in":"query","required":false,"schema":{"type":"string","description":"IDs to merge (comma-separated). First ID becomes the target.","title":"Ids"},"description":"IDs to merge (comma-separated). First ID becomes the target."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FoodTagOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPBadRequest"}}}},"429":{"description":"Rate limit exceeded. Authenticated requests: 500/minute, 7200/hour. Concurrent limit: 10 requests. Check Retry-After header for reset time.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPRateLimitExceeded"}}}}}}},"/v1/tags/food_tags/{food_tag_id}":{"get":{"tags":["tags[food]"],"summary":"Get Food Tag","description":"Get a single food tag by ID.","operationId":"get_food_tag_v1_tags_food_tags__food_tag_id__get","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"food_tag_id","in":"path","required":true,"schema":{"type":"string","description":"Food tag ID to retrieve","title":"Food Tag Id"},"description":"Food tag ID to retrieve"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FoodTagOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPBadRequest"}}}},"429":{"description":"Rate limit exceeded. Authenticated requests: 500/minute, 7200/hour. Concurrent limit: 10 requests. Check Retry-After header for reset time.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPRateLimitExceeded"}}}}}},"post":{"tags":["tags[food]"],"summary":"Edit Food Tag","description":"Update a food tag.","operationId":"edit_food_tag_v1_tags_food_tags__food_tag_id__post","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"food_tag_id","in":"path","required":true,"schema":{"type":"string","description":"Food tag ID to update","title":"Food Tag Id"},"description":"Food tag ID to update"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EditFoodTagIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FoodTagOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPBadRequest"}}}},"429":{"description":"Rate limit exceeded. Authenticated requests: 500/minute, 7200/hour. Concurrent limit: 10 requests. Check Retry-After header for reset time.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPRateLimitExceeded"}}}}}},"delete":{"tags":["tags[food]"],"summary":"Remove Food Tag","description":"Delete a food tag.\n\nFoods with this tag will have the tag removed (not deleted).","operationId":"remove_food_tag_v1_tags_food_tags__food_tag_id__delete","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"food_tag_id","in":"path","required":true,"schema":{"type":"string","description":"Food tag ID to delete","title":"Food Tag Id"},"description":"Food tag ID to delete"}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPBadRequest"}}}},"429":{"description":"Rate limit exceeded. Authenticated requests: 500/minute, 7200/hour. Concurrent limit: 10 requests. Check Retry-After header for reset time.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPRateLimitExceeded"}}}}}}},"/v1/tags/food_associations/{food_id}":{"post":{"tags":["tags[food]"],"summary":"Save Tag Associations","description":"Replace all tag associations for a food.\n\nExisting associations not in the list are removed.","operationId":"save_tag_associations_v1_tags_food_associations__food_id__post","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"food_id","in":"path","required":true,"schema":{"type":"string","description":"Food ID to update tags for","title":"Food Id"},"description":"Food ID to update tags for"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SaveFoodTagAssociationsIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FoodTagListOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPBadRequest"}}}},"429":{"description":"Rate limit exceeded. Authenticated requests: 500/minute, 7200/hour. Concurrent limit: 10 requests. Check Retry-After header for reset time.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPRateLimitExceeded"}}}}}}},"/v1/tags/food_associations/{food_id}/tags":{"get":{"tags":["tags[food]"],"summary":"List Tag Associations","description":"List all tags associated with a food.","operationId":"list_tag_associations_v1_tags_food_associations__food_id__tags_get","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"food_id","in":"path","required":true,"schema":{"type":"string","description":"Food ID to get tags for","title":"Food Id"},"description":"Food ID to get tags for"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FoodTagListOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPBadRequest"}}}},"429":{"description":"Rate limit exceeded. Authenticated requests: 500/minute, 7200/hour. Concurrent limit: 10 requests. Check Retry-After header for reset time.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPRateLimitExceeded"}}}}}},"post":{"tags":["tags[food]"],"summary":"Add Tag Association","description":"Add a tag to a food.","operationId":"add_tag_association_v1_tags_food_associations__food_id__tags_post","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"food_id","in":"path","required":true,"schema":{"type":"string","description":"Food ID to add tag to","title":"Food Id"},"description":"Food ID to add tag to"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddFoodTagAssociationIn"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FoodTagOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPBadRequest"}}}},"429":{"description":"Rate limit exceeded. Authenticated requests: 500/minute, 7200/hour. Concurrent limit: 10 requests. Check Retry-After header for reset time.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPRateLimitExceeded"}}}}}}},"/v1/tags/food_associations/{food_id}/tags/{food_tag_id}":{"delete":{"tags":["tags[food]"],"summary":"Remove Tag Association","description":"Remove a tag from a food.","operationId":"remove_tag_association_v1_tags_food_associations__food_id__tags__food_tag_id__delete","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"food_id","in":"path","required":true,"schema":{"type":"string","description":"Food ID to remove tag from","title":"Food Id"},"description":"Food ID to remove tag from"},{"name":"food_tag_id","in":"path","required":true,"schema":{"type":"string","description":"Tag ID to remove","title":"Food Tag Id"},"description":"Tag ID to remove"}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPBadRequest"}}}},"429":{"description":"Rate limit exceeded. Authenticated requests: 500/minute, 7200/hour. Concurrent limit: 10 requests. Check Retry-After header for reset time.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPRateLimitExceeded"}}}}}}},"/v1/tags/recipe_tags":{"get":{"tags":["tags[recipe]"],"summary":"List Recipe Tags","description":"List all recipe tags for the current tenant.","operationId":"list_recipe_tags_v1_tags_recipe_tags_get","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"page","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"The page number (null returns all)","title":"Page"},"description":"The page number (null returns all)"},{"name":"page_size","in":"query","required":false,"schema":{"anyOf":[{"type":"integer","maximum":200},{"type":"null"}],"description":"The number of element per page","default":20,"title":"Page Size"},"description":"The number of element per page"},{"name":"order_by","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"The field name of the element to sort by (Limited)","title":"Order By"},"description":"The field name of the element to sort by (Limited)"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecipeTagListOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPBadRequest"}}}},"429":{"description":"Rate limit exceeded. Authenticated requests: 500/minute, 7200/hour. Concurrent limit: 10 requests. Check Retry-After header for reset time.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPRateLimitExceeded"}}}}}},"post":{"tags":["tags[recipe]"],"summary":"Add Recipe Tag","description":"Create a new recipe tag.\n\nTags are used to organize and filter recipes in list views.","operationId":"add_recipe_tag_v1_tags_recipe_tags_post","security":[{"APIKeyHeader":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddRecipeTagIn"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecipeTagOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPBadRequest"}}}},"429":{"description":"Rate limit exceeded. Authenticated requests: 500/minute, 7200/hour. Concurrent limit: 10 requests. Check Retry-After header for reset time.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPRateLimitExceeded"}}}}}}},"/v1/tags/recipe_tags/batch_remove":{"post":{"tags":["tags[recipe]"],"summary":"Batch Remove","description":"Delete multiple recipe tags.","operationId":"batch_remove_v1_tags_recipe_tags_batch_remove_post","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"ids","in":"query","required":false,"schema":{"type":"string","description":"IDs to delete (comma-separated)","title":"Ids"},"description":"IDs to delete (comma-separated)"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"boolean","title":"Response Batch Remove V1 Tags Recipe Tags Batch Remove Post"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPBadRequest"}}}},"429":{"description":"Rate limit exceeded. Authenticated requests: 500/minute, 7200/hour. Concurrent limit: 10 requests. Check Retry-After header for reset time.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPRateLimitExceeded"}}}}}}},"/v1/tags/recipe_tags/batch_merge":{"post":{"tags":["tags[recipe]"],"summary":"Batch Merge","description":"Merge multiple recipe tags into one.\n\nAll recipes with the merged tags are reassigned to the first tag. Other tags are deleted.","operationId":"batch_merge_v1_tags_recipe_tags_batch_merge_post","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"ids","in":"query","required":false,"schema":{"type":"string","description":"IDs to merge (comma-separated). First ID becomes the target.","title":"Ids"},"description":"IDs to merge (comma-separated). First ID becomes the target."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecipeTagOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPBadRequest"}}}},"429":{"description":"Rate limit exceeded. Authenticated requests: 500/minute, 7200/hour. Concurrent limit: 10 requests. Check Retry-After header for reset time.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPRateLimitExceeded"}}}}}}},"/v1/tags/recipe_tags/{recipe_tag_id}":{"get":{"tags":["tags[recipe]"],"summary":"Get Recipe Tag","description":"Get a single recipe tag by ID.","operationId":"get_recipe_tag_v1_tags_recipe_tags__recipe_tag_id__get","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"recipe_tag_id","in":"path","required":true,"schema":{"type":"string","description":"Recipe tag ID to retrieve","title":"Recipe Tag Id"},"description":"Recipe tag ID to retrieve"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecipeTagOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPBadRequest"}}}},"429":{"description":"Rate limit exceeded. Authenticated requests: 500/minute, 7200/hour. Concurrent limit: 10 requests. Check Retry-After header for reset time.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPRateLimitExceeded"}}}}}},"post":{"tags":["tags[recipe]"],"summary":"Edit Recipe Tag","description":"Update a recipe tag.","operationId":"edit_recipe_tag_v1_tags_recipe_tags__recipe_tag_id__post","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"recipe_tag_id","in":"path","required":true,"schema":{"type":"string","description":"Recipe tag ID to update","title":"Recipe Tag Id"},"description":"Recipe tag ID to update"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EditRecipeTagIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecipeTagOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPBadRequest"}}}},"429":{"description":"Rate limit exceeded. Authenticated requests: 500/minute, 7200/hour. Concurrent limit: 10 requests. Check Retry-After header for reset time.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPRateLimitExceeded"}}}}}},"delete":{"tags":["tags[recipe]"],"summary":"Remove Recipe Tag","description":"Delete a recipe tag.\n\nRecipes with this tag will have the tag removed (not deleted).","operationId":"remove_recipe_tag_v1_tags_recipe_tags__recipe_tag_id__delete","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"recipe_tag_id","in":"path","required":true,"schema":{"type":"string","description":"Recipe tag ID to delete","title":"Recipe Tag Id"},"description":"Recipe tag ID to delete"}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPBadRequest"}}}},"429":{"description":"Rate limit exceeded. Authenticated requests: 500/minute, 7200/hour. Concurrent limit: 10 requests. Check Retry-After header for reset time.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPRateLimitExceeded"}}}}}}},"/v1/tags/recipe_associations/{recipe_id}":{"post":{"tags":["tags[recipe]"],"summary":"Save Tag Associations","description":"Replace all tag associations for a recipe.\n\nExisting associations not in the list are removed.","operationId":"save_tag_associations_v1_tags_recipe_associations__recipe_id__post","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"recipe_id","in":"path","required":true,"schema":{"type":"string","description":"Recipe ID to update tags for","title":"Recipe Id"},"description":"Recipe ID to update tags for"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SaveRecipeTagAssociationsIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecipeTagListOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPBadRequest"}}}},"429":{"description":"Rate limit exceeded. Authenticated requests: 500/minute, 7200/hour. Concurrent limit: 10 requests. Check Retry-After header for reset time.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPRateLimitExceeded"}}}}}}},"/v1/tags/recipe_associations/{recipe_id}/tags":{"get":{"tags":["tags[recipe]"],"summary":"List Tag Associations","description":"List all tags associated with a recipe.","operationId":"list_tag_associations_v1_tags_recipe_associations__recipe_id__tags_get","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"recipe_id","in":"path","required":true,"schema":{"type":"string","description":"Recipe ID to get tags for","title":"Recipe Id"},"description":"Recipe ID to get tags for"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecipeTagListOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPBadRequest"}}}},"429":{"description":"Rate limit exceeded. Authenticated requests: 500/minute, 7200/hour. Concurrent limit: 10 requests. Check Retry-After header for reset time.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPRateLimitExceeded"}}}}}},"post":{"tags":["tags[recipe]"],"summary":"Add Tag Association","description":"Add a tag to a recipe.","operationId":"add_tag_association_v1_tags_recipe_associations__recipe_id__tags_post","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"recipe_id","in":"path","required":true,"schema":{"type":"string","description":"Recipe ID to add tag to","title":"Recipe Id"},"description":"Recipe ID to add tag to"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddRecipeTagAssociationIn"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecipeTagOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPBadRequest"}}}},"429":{"description":"Rate limit exceeded. Authenticated requests: 500/minute, 7200/hour. Concurrent limit: 10 requests. Check Retry-After header for reset time.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPRateLimitExceeded"}}}}}}},"/v1/tags/recipe_associations/{recipe_id}/tags/{recipe_tag_id}":{"delete":{"tags":["tags[recipe]"],"summary":"Remove Tag Association","description":"Remove a tag from a recipe.","operationId":"remove_tag_association_v1_tags_recipe_associations__recipe_id__tags__recipe_tag_id__delete","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"recipe_id","in":"path","required":true,"schema":{"type":"string","description":"Recipe ID to remove tag from","title":"Recipe Id"},"description":"Recipe ID to remove tag from"},{"name":"recipe_tag_id","in":"path","required":true,"schema":{"type":"string","description":"Tag ID to remove","title":"Recipe Tag Id"},"description":"Tag ID to remove"}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPBadRequest"}}}},"429":{"description":"Rate limit exceeded. Authenticated requests: 500/minute, 7200/hour. Concurrent limit: 10 requests. Check Retry-After header for reset time.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPRateLimitExceeded"}}}}}}},"/v1/invoices/{invoice_id}/render.{output_format}":{"get":{"tags":["invoices"],"summary":"Render Invoice","description":"Render an invoice to PDF or HTML.\n\nReturns binary file by default. Set json=true for JSON response with content.","operationId":"render_invoice_v1_invoices__invoice_id__render__output_format__get","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"invoice_id","in":"path","required":true,"schema":{"type":"string","description":"Invoice ID to render","title":"Invoice Id"},"description":"Invoice ID to render"},{"name":"output_format","in":"path","required":true,"schema":{"type":"string","description":"Output format: pdf, html","title":"Output Format"},"description":"Output format: pdf, html"},{"name":"json","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"description":"Return JSON wrapper instead of raw file","default":false,"title":"Json"},"description":"Return JSON wrapper instead of raw file"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPBadRequest"}}}},"429":{"description":"Rate limit exceeded. Authenticated requests: 500/minute, 7200/hour. Concurrent limit: 10 requests. Check Retry-After header for reset time.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPRateLimitExceeded"}}}}}}},"/v1/utils/allergies":{"get":{"tags":["utils"],"summary":"Get Allergies","description":"List standard allergens recognized by Health Canada and FDA.\n\nReturns the official list of priority allergens that must be declared on Canadian and US food labels. These values are used in the `allergies` and `may_contains` arrays when creating or editing foods (POST/PATCH /v1/foods), and in `extra_allergies` and `extra_may_contains` when editing recipes (POST/PATCH /v1/recipes).\n\nSome allergens have `to_specify: true`, meaning the specific variety must be declared (e.g., \"Fish (salmon)\" rather than just \"Fish\").\n\n**Consuming fields:**\n- `POST /v1/foods` - `allergies[].name_en`, `allergies[].name_fr`, `may_contains[].name_en`, `may_contains[].name_fr`\n- `POST/PATCH /v1/foods/{food_id}` - Same fields\n- `POST/PATCH /v1/recipes/{recipe_id}` - `extra_allergies[].name_en`, `extra_allergies[].name_fr`, `extra_may_contains[].name_en`, `extra_may_contains[].name_fr`\n- `FoodOut.allergies`, `FoodOut.may_contains` - Output schemas\n- `RecipeOut.allergies`, `RecipeOut.may_contains` - Output schemas (aggregated from ingredients + extras)","operationId":"get_allergies_v1_utils_allergies_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/AllergiesInfoOut"},"type":"array","title":"Response Get Allergies V1 Utils Allergies Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPBadRequest"}}}},"429":{"description":"Rate limit exceeded. Authenticated requests: 500/minute, 7200/hour. Concurrent limit: 10 requests. Check Retry-After header for reset time.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPRateLimitExceeded"}}}}}}},"/v1/utils/available_units":{"get":{"tags":["utils"],"summary":"Get Available Units","description":"List all standard units of measure available in the system.\n\nReturns unit keys and their bilingual display names. Use the `key` value when setting unit fields on foods, recipes, labels, and ingredients.\n\n**Consuming fields:**\n- `POST /v1/foods` - `mass_unit` (food base unit)\n- `POST/PATCH /v1/foods/{food_id}/custom_units` - `unit_to` (conversion target)\n- `POST /v1/recipes/{recipe_id}/ingredients` - `unit` (ingredient quantity unit)\n- `POST /v1/labels` - `serving_unit`, `reference_unit`\n- `POST /v1/fop_labels` - `serving_unit`, `reference_unit`\n- `FoodOut.available_units` - Units valid for this food\n- `IngredientOut.available_units` - Units valid for this ingredient\n- `IngredientOut.unit` - Current unit selection\n\nFilter by `volume=false` to get mass-only units, or `mass=false` for volume-only.","operationId":"get_available_units_v1_utils_available_units_get","parameters":[{"name":"volume","in":"query","required":false,"schema":{"type":"boolean","description":"Include volume units (mL, L, cup, etc.)","default":true,"title":"Volume"},"description":"Include volume units (mL, L, cup, etc.)"},{"name":"mass","in":"query","required":false,"schema":{"type":"boolean","description":"Include mass units (g, kg, oz, lb, etc.)","default":true,"title":"Mass"},"description":"Include mass units (g, kg, oz, lb, etc.)"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/UnitOut"},"title":"Response Get Available Units V1 Utils Available Units Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPBadRequest"}}}},"429":{"description":"Rate limit exceeded. Authenticated requests: 500/minute, 7200/hour. Concurrent limit: 10 requests. Check Retry-After header for reset time.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPRateLimitExceeded"}}}}}}},"/v1/utils/yield_units":{"get":{"tags":["utils"],"summary":"Get Yield Units","description":"List units available for recipe yield specification.\n\nReturns the subset of units that can be used for `yield_unit` on recipes. Includes mass units (g, kg, oz, lb) and percentage (%). Volume units are excluded because yield is typically expressed as mass or percentage of original.\n\n**Consuming fields:**\n- `POST /v1/recipes` - `yield_unit` (default: '%')\n- `POST/PATCH /v1/recipes/{recipe_id}` - `yield_unit`\n- `RecipeOut.yield_unit` - Current yield unit","operationId":"get_yield_units_v1_utils_yield_units_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/UnitOut"},"type":"array","title":"Response Get Yield Units V1 Utils Yield Units Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPBadRequest"}}}},"429":{"description":"Rate limit exceeded. Authenticated requests: 500/minute, 7200/hour. Concurrent limit: 10 requests. Check Retry-After header for reset time.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPRateLimitExceeded"}}}}}}},"/v1/utils/concrete_types":{"get":{"tags":["utils"],"summary":"Get Concrete Types","description":"List available regulatory label types.\n\nReturns the regulation identifiers that determine label format, nutrient requirements, and %DV calculations.\n\n**Values:**\n- `CAN` - Canadian (legacy format, pre-2016)\n- `CAN2016` - Canadian 2016+ regulations (current Health Canada standard)\n- `US` - United States FDA format\n\n**Consuming fields:**\n- `POST /v1/labels` - `concrete_type` (required)\n- `POST /v1/fop_labels` - `concrete_type` (required)\n- `LabelOut.concrete_type`, `ShortLabelOut.concrete_type` - Output schemas\n- `FopLabelOut.concrete_type` - Output schema\n- `GET /v1/utils/label_rules/{concrete_type}` - Path parameter\n- `GET /v1/utils/fop_label_rules/{concrete_type}` - Path parameter","operationId":"get_concrete_types_v1_utils_concrete_types_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"type":"string","maxLength":255},"type":"array","title":"Response Get Concrete Types V1 Utils Concrete Types Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPBadRequest"}}}},"429":{"description":"Rate limit exceeded. Authenticated requests: 500/minute, 7200/hour. Concurrent limit: 10 requests. Check Retry-After header for reset time.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPRateLimitExceeded"}}}}}}},"/v1/utils/label_rules/{concrete_type}":{"get":{"tags":["utils"],"summary":"Get Label Rules","description":"Get NFT label configuration rules for a regulation type.\n\nReturns the full rule set for nutrition facts table (NFT) labels under the specified regulation. Includes available label formats, format versions, options with their default values, and regulatory constraints.\n\nUse this to:\n- Discover valid `label_format` values for POST /v1/labels\n- Discover valid `label_format_version` values\n- See available `options` keys and their defaults\n- Understand which nutrients are required vs optional\n\n**Related:**\n- `POST /v1/labels` - Uses these rules when creating labels\n- `GET /v1/labels/{label_id}/render.{format}` - Renders according to these rules","operationId":"get_label_rules_v1_utils_label_rules__concrete_type__get","parameters":[{"name":"concrete_type","in":"path","required":true,"schema":{"type":"string","description":"Regulation type from GET /v1/utils/concrete_types: 'CAN', 'CAN2016', or 'US'","title":"Concrete Type"},"description":"Regulation type from GET /v1/utils/concrete_types: 'CAN', 'CAN2016', or 'US'"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Label Rules V1 Utils Label Rules  Concrete Type  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPBadRequest"}}}},"429":{"description":"Rate limit exceeded. Authenticated requests: 500/minute, 7200/hour. Concurrent limit: 10 requests. Check Retry-After header for reset time.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPRateLimitExceeded"}}}}}}},"/v1/utils/fop_label_rules/{concrete_type}":{"get":{"tags":["utils"],"summary":"Get Fop Label Rules","description":"Get FOP (front-of-package) label configuration rules for a regulation type.\n\nReturns the rule set for front-of-package nutrition symbols under the specified regulation. Includes thresholds for sodium, sugar, and saturated fat that determine whether a warning symbol is required, and format options.\n\nUse this to:\n- Understand FOP symbol thresholds\n- Discover valid `label_format` values for POST /v1/fop_labels\n- See `is_prepackaged_meal` impact on thresholds\n\n**Related:**\n- `POST /v1/fop_labels` - Uses these rules when creating FOP labels\n- `GET /v1/fop_labels/{fop_label_id}/render.{format}` - Renders according to these rules","operationId":"get_fop_label_rules_v1_utils_fop_label_rules__concrete_type__get","parameters":[{"name":"concrete_type","in":"path","required":true,"schema":{"type":"string","description":"Regulation type from GET /v1/utils/concrete_types: 'CAN', 'CAN2016', or 'US'","title":"Concrete Type"},"description":"Regulation type from GET /v1/utils/concrete_types: 'CAN', 'CAN2016', or 'US'"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Fop Label Rules V1 Utils Fop Label Rules  Concrete Type  Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPBadRequest"}}}},"429":{"description":"Rate limit exceeded. Authenticated requests: 500/minute, 7200/hour. Concurrent limit: 10 requests. Check Retry-After header for reset time.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPRateLimitExceeded"}}}}}}},"/v1/utils/nutriments_rules":{"get":{"tags":["utils"],"summary":"Get Nutriments Rules","description":"Get nutrient field definitions and validation rules.\n\nReturns metadata for all nutrient fields in the system, including field keys, display names, units, and validation constraints. Use this to understand:\n- Valid keys for the `nutriments` object when creating/editing foods\n- Units expected for each nutrient (g, mg, mcg, IU, kcal)\n- Display order and grouping for UI rendering\n- Which nutrients are calculated vs manually entered\n\n**Consuming schemas:**\n- `POST /v1/foods` - `nutriments` object keys\n- `POST/PATCH /v1/foods/{food_id}` - `nutriments` object keys\n- `FoodOut.nutriments`, `RecipeOut.nutriments` - Output field names\n- `NutrimentsOut` schema - All 85 nutrient fields","operationId":"get_nutriments_rules_v1_utils_nutriments_rules_get","parameters":[{"name":"former","in":"query","required":false,"schema":{"type":"boolean","description":"If true, include former/deprecated nutrient codes alongside current ones","default":false,"title":"Former"},"description":"If true, include former/deprecated nutrient codes alongside current ones"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Get Nutriments Rules V1 Utils Nutriments Rules Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPBadRequest"}}}},"429":{"description":"Rate limit exceeded. Authenticated requests: 500/minute, 7200/hour. Concurrent limit: 10 requests. Check Retry-After header for reset time.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPRateLimitExceeded"}}}}}}},"/v1/utils/class_names":{"get":{"tags":["utils"],"summary":"Get Class Names","description":"Get ingredient class names for regulatory grouping.\n\nReturns the list of class names used to group ingredients in ingredient lists according to Canadian and US labeling regulations.\n\n**Values:** sugar, spice, seasoning, herb, colour, natural_flavour, artificial_flavour, at_end\n\n**Behavior by regulation:**\n- **CAN/CAN2016:** spice, seasoning, herb, colour, natural_flavour, artificial_flavour, at_end have `end=True` - these ingredients can be grouped at the end of the ingredient list (requires `ingredient_list_at_end=true` on the ingredient). May be renamed to class name (e.g., \"Spices\"). Sugar groups ingredients but stays in weight order (`end=False`).\n- **US:** ALL classes have `end=False` (FDA requires strict descending weight order). Classes only affect naming (e.g., \"natural flavor\"). The `ingredient_list_at_end` field has no effect for US labels.\n\n**Important:** Setting `ingredient_list_at_end=true` on an ingredient only works if:\n1. The ingredient has a `ingredient_list_class_name` set, AND\n2. That class has `end=True` for the label's regulation\n\n**Consuming fields:**\n- `POST /v1/recipes/{recipe_id}/ingredients` - `ingredient_list_class_name`\n- `POST/PATCH /v1/recipes/{recipe_id}/ingredients/{ingredient_id}` - `ingredient_list_class_name`\n- `IngredientOut.ingredient_list_class_name` - Output field","operationId":"get_class_names_v1_utils_class_names_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Get Class Names V1 Utils Class Names Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPBadRequest"}}}},"429":{"description":"Rate limit exceeded. Authenticated requests: 500/minute, 7200/hour. Concurrent limit: 10 requests. Check Retry-After header for reset time.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPRateLimitExceeded"}}}}}}},"/v1/activity-logs":{"get":{"tags":["activity-logs"],"summary":"List Activity Logs","description":"List activity logs. Business+ feature.","operationId":"list_activity_logs_v1_activity_logs_get","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"entity_type","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter: food, recipe, label","title":"Entity Type"},"description":"Filter: food, recipe, label"},{"name":"entity_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by entity ID","title":"Entity Id"},"description":"Filter by entity ID"},{"name":"user_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by user ID","title":"User Id"},"description":"Filter by user ID"},{"name":"action","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Filter by action","title":"Action"},"description":"Filter by action"},{"name":"date_start","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"From date (inclusive)","title":"Date Start"},"description":"From date (inclusive)"},{"name":"date_end","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"description":"To date (exclusive)","title":"Date End"},"description":"To date (exclusive)"},{"name":"page","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"The page number","default":1,"title":"Page"},"description":"The page number"},{"name":"page_size","in":"query","required":false,"schema":{"anyOf":[{"type":"integer","maximum":200},{"type":"null"}],"description":"The number of element per page","default":20,"title":"Page Size"},"description":"The number of element per page"},{"name":"order_by","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"The field name of the element to sort by (Limited)","title":"Order By"},"description":"The field name of the element to sort by (Limited)"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ActivityLogListOut"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPBadRequest"}}}},"429":{"description":"Rate limit exceeded. Authenticated requests: 500/minute, 7200/hour. Concurrent limit: 10 requests. Check Retry-After header for reset time.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPRateLimitExceeded"}}}}}}},"/v1/activity-logs/csv_export":{"post":{"tags":["activity-logs"],"summary":"Csv Export Activity Logs","operationId":"csv_export_activity_logs_v1_activity_logs_csv_export_post","security":[{"APIKeyHeader":[]}],"parameters":[{"name":"entity_type","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Entity Type"}},{"name":"entity_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Entity Id"}},{"name":"user_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"User Id"}},{"name":"action","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Action"}},{"name":"date_start","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Date Start"}},{"name":"date_end","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Date End"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPBadRequest"}}}},"429":{"description":"Rate limit exceeded. Authenticated requests: 500/minute, 7200/hour. Concurrent limit: 10 requests. Check Retry-After header for reset time.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPRateLimitExceeded"}}}}}}},"/health":{"get":{"tags":["misc"],"summary":"Health","operationId":"health_health_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Health Health Get"}}}},"422":{"description":"Validation Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPValidationError"}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPBadRequest"}}}},"429":{"description":"Rate limit exceeded. Authenticated requests: 500/minute, 7200/hour. Concurrent limit: 10 requests. Check Retry-After header for reset time.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HTTPRateLimitExceeded"}}}}}}}},"components":{"schemas":{"ActivityLogListOut":{"properties":{"items":{"items":{"$ref":"#/components/schemas/ActivityLogOut"},"type":"array","title":"Items"},"page_info":{"$ref":"#/components/schemas/PageInfo"}},"type":"object","required":["items","page_info"],"title":"ActivityLogListOut"},"ActivityLogOut":{"properties":{"id":{"type":"integer","title":"Id"},"tenant_id":{"type":"string","title":"Tenant Id"},"user_id":{"type":"string","title":"User Id"},"user_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"User Name"},"current_user_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Current User Name"},"action":{"type":"string","title":"Action"},"entity_type":{"type":"string","title":"Entity Type"},"entity_id":{"type":"string","title":"Entity Id"},"entity_name":{"type":"string","title":"Entity Name"},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["id","tenant_id","user_id","action","entity_type","entity_id","entity_name","created_at"],"title":"ActivityLogOut"},"AddCustomUnitFoodIn":{"properties":{"name_en":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Name En","default":""},"name_fr":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Name Fr","default":""},"rate":{"type":"string","format":"decimal","title":"Rate","default":"1","example":"99.5"},"unit_to":{"type":"string","maxLength":255,"title":"Unit To","default":"g"}},"type":"object","title":"AddCustomUnitFoodIn"},"AddCustomUnitIn":{"properties":{"name_en":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Name En","default":""},"name_fr":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Name Fr","default":""},"rate":{"type":"string","format":"decimal","title":"Rate","default":"1","example":"99.5"},"unit_to":{"type":"string","maxLength":255,"title":"Unit To","default":"g"},"food_version_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Food Version Id"}},"type":"object","title":"AddCustomUnitIn"},"AddCustomUnitRecipeIn":{"properties":{"name_en":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Name En","default":""},"name_fr":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Name Fr","default":""},"rate":{"type":"string","format":"decimal","title":"Rate","default":"1","example":"99.5"},"unit_to":{"type":"string","maxLength":255,"title":"Unit To","default":"g"}},"type":"object","title":"AddCustomUnitRecipeIn"},"AddFoodIn":{"properties":{"name":{"anyOf":[{"type":"string","maxLength":255,"minLength":1},{"type":"null"}],"title":"Name","description":"Display name for the ingredient. If not provided, computed from name_en or name_fr"},"name_en":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Name En","description":"English name of the ingredient"},"name_fr":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Name Fr","description":"French name of the ingredient"},"common_name_en":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Common Name En","description":"English common name (regulatory term)"},"common_name_fr":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Common Name Fr","description":"French common name (regulatory term)"},"public":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Public","description":"Whether the ingredient is publicly visible. Default: false","default":false},"brand":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Brand","description":"Brand name for branded ingredients"},"source":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Source","description":"Internal use"},"mass_quantity":{"type":"string","format":"decimal","title":"Mass Quantity","description":"Base mass quantity for nutriment values. Default: '100'","default":"100","example":"99.5"},"mass_unit":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Mass Unit","description":"Unit for mass_quantity. Default: 'g'. Valid values from GET /v1/utils/available_units","default":"g"},"volume_quantity":{"anyOf":[{"type":"string","format":"decimal","example":"99.5"},{"type":"null"}],"title":"Volume Quantity","description":"Optional volume equivalent of the mass quantity"},"volume_unit":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Volume Unit","description":"Unit for volume_quantity (e.g., 'mL', 'L')"},"custom_units":{"items":{"anyOf":[{"$ref":"#/components/schemas/EditCustomUnitFoodIn"},{"$ref":"#/components/schemas/AddCustomUnitFoodIn"}]},"type":"array","title":"Custom Units","description":"Custom units of measure","default":[]},"refuse_pct":{"anyOf":[{"type":"string","format":"decimal","example":"99.5"},{"type":"null"}],"title":"Refuse Pct","description":"Percentage of ingredient that is waste/refuse (0-100)"},"refuse_description_en":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Refuse Description En","description":"English description of refuse (e.g., 'skin and seeds')"},"refuse_description_fr":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Refuse Description Fr","description":"French description of refuse"},"auto_apply_refuse":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Auto Apply Refuse","description":"Auto-apply refuse percentage when added to recipes"},"ingredient_list_en":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Ingredient List En","description":"English ingredient list text for compound ingredients"},"ingredient_list_fr":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Ingredient List Fr","description":"French ingredient list text for compound ingredients"},"ingredient_list_preserve_case":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Ingredient List Preserve Case","description":"Preserve original case in ingredient list"},"nutriments":{"$ref":"#/components/schemas/NutrimentsIn","description":"Nutritional values. Defaults to all null amounts"},"allergies":{"items":{"$ref":"#/components/schemas/AllergyIn"},"type":"array","title":"Allergies","description":"Allergens present (contains statements). Standard allergens from GET /v1/utils/allergies","default":[]},"may_contains":{"items":{"$ref":"#/components/schemas/MayContainIn"},"type":"array","title":"May Contains","description":"Potential allergens from cross-contamination. Standard allergens from GET /v1/utils/allergies","default":[]},"density_overwrite":{"anyOf":[{"type":"string","format":"decimal","example":"99.5"},{"type":"null"}],"title":"Density Overwrite","description":"Manual density override in g/mL"},"product_code":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Product Code","description":"User-defined identifier (UPC/SKU)"},"irradiated":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Irradiated","description":"Whether ingredient has been irradiated"},"irradiated_fr_feminine":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Irradiated Fr Feminine","description":"French grammar: feminine form"},"irradiated_fr_plural":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Irradiated Fr Plural","description":"French grammar: plural form"},"thawed":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Thawed","description":"Whether ingredient was previously frozen"},"notes_en":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Notes En","description":"Internal English notes"},"notes_fr":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Notes Fr","description":"Internal French notes"}},"type":"object","title":"AddFoodIn","description":"Request body for creating a new ingredient.\nAll fields are optional with sensible defaults."},"AddFoodTagAssociationIn":{"properties":{"food_tag_id":{"type":"string","title":"Food Tag Id","description":"Tag ID to associate"}},"type":"object","required":["food_tag_id"],"title":"AddFoodTagAssociationIn","description":"Request to associate a tag with a food."},"AddFoodTagIn":{"properties":{"name":{"type":"string","maxLength":255,"minLength":1,"title":"Name"},"color":{"anyOf":[{"type":"string","format":"color"},{"type":"null"}],"title":"Color"}},"type":"object","required":["name"],"title":"AddFoodTagIn"},"AddFopLabelIn":{"properties":{"name":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Name","description":"Display name for the FOP label"},"serving_qty":{"type":"string","format":"decimal","title":"Serving Qty","description":"Serving size quantity (default: 100)","default":"100","example":"99.5"},"serving_unit":{"type":"string","maxLength":255,"title":"Serving Unit","description":"Unit for serving (default: 'g')","default":"g"},"reference_qty":{"type":"string","format":"decimal","title":"Reference Qty","description":"Reference amount quantity (default: 100)","default":"100","example":"99.5"},"reference_unit":{"type":"string","maxLength":255,"title":"Reference Unit","description":"Unit for reference amount (default: 'g')","default":"g"},"is_prepackaged_meal":{"type":"boolean","title":"Is Prepackaged Meal","description":"Whether this is a prepackaged meal (default: false)","default":false},"label_format":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Label Format","description":"FOP symbol format (default: '1'): bilingual_horizontal, bilingual_vertical, unilingual_horizontal, unilingual_vertical, supplemented_unilingual, supplemented_bilingual. Full list from GET /v1/utils/fop_label_rules/{concrete_type}","default":"1"},"label_format_version":{"anyOf":[{"type":"string","maxLength":255},{"type":"integer"},{"type":"null"}],"title":"Label Format Version","description":"Version of the label format. Valid values from GET /v1/utils/fop_label_rules/{concrete_type}"},"label_language":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Label Language","description":"Language code: 'en' or 'fr'. For bilingual, use a bilingual label_format. Determines which language appears first"},"recipe_id":{"type":"string","title":"Recipe Id","description":"Recipe ID to associate with this FOP label"},"concrete_type":{"type":"string","maxLength":255,"title":"Concrete Type","description":"Regulation type: 'CAN2016' for Canadian, 'US' for American. See GET /v1/utils/concrete_types"},"specification_type":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Specification Type","description":"Reserved for future use"}},"type":"object","required":["recipe_id","concrete_type"],"title":"AddFopLabelIn","description":"Input for creating a new FOP label. Requires recipe_id and concrete_type."},"AddIngredientIn":{"properties":{"food_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Food Id"},"source_recipe_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Source Recipe Id","description":"Alternative behavior. Add a recipe directly to another recipe."},"quantity":{"anyOf":[{"type":"string","format":"decimal","example":"99.5"},{"type":"null"}],"title":"Quantity"},"unit":{"type":"string","maxLength":255,"title":"Unit"},"order":{"anyOf":[{"type":"integer","minimum":0.0},{"type":"null"}],"title":"Order"},"refuse_pct":{"anyOf":[{"type":"string","format":"decimal","example":"99.5"},{"type":"null"}],"title":"Refuse Pct"},"ingredient_list_display_as_overwrite_en":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Ingredient List Display As Overwrite En"},"ingredient_list_display_as_overwrite_fr":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Ingredient List Display As Overwrite Fr"},"ingredient_list_class_name":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Ingredient List Class Name","description":"Regulatory grouping. Values from GET /v1/utils/class_names. Required for ingredient_list_at_end to work"},"ingredient_list_at_end":{"type":"boolean","title":"Ingredient List At End","description":"Move to end of list. Only works if ingredient_list_class_name is set to a class with end=True for the regulation (CAN/CAN2016: spice, seasoning, herb, colour, flavours, at_end; US: none)","default":false},"ingredient_list_hide_subingredients":{"type":"boolean","title":"Ingredient List Hide Subingredients","default":false},"ingredient_list_merge_subingredients":{"type":"boolean","title":"Ingredient List Merge Subingredients","description":"Merge nested recipe's ingredients into main list. Only applies when using `source_recipe_id`","default":false},"instructions_display_as_overwrite_en":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Instructions Display As Overwrite En","description":"Custom name for cooking instructions (not for regulatory labels)"},"instructions_display_as_overwrite_fr":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Instructions Display As Overwrite Fr","description":"Custom name for cooking instructions (not for regulatory labels)"},"recipe_version_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Recipe Version Id"}},"type":"object","required":["unit"],"title":"AddIngredientIn"},"AddIngredientRecipeIn":{"properties":{"food_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Food Id"},"source_recipe_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Source Recipe Id","description":"Alternative behavior. Add a recipe directly to another recipe."},"quantity":{"anyOf":[{"type":"string","format":"decimal","example":"99.5"},{"type":"null"}],"title":"Quantity"},"unit":{"type":"string","maxLength":255,"title":"Unit"},"order":{"anyOf":[{"type":"integer","minimum":0.0},{"type":"null"}],"title":"Order"},"refuse_pct":{"anyOf":[{"type":"string","format":"decimal","example":"99.5"},{"type":"null"}],"title":"Refuse Pct"},"ingredient_list_display_as_overwrite_en":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Ingredient List Display As Overwrite En"},"ingredient_list_display_as_overwrite_fr":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Ingredient List Display As Overwrite Fr"},"ingredient_list_class_name":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Ingredient List Class Name","description":"Regulatory grouping. Values from GET /v1/utils/class_names. Required for ingredient_list_at_end to work"},"ingredient_list_at_end":{"type":"boolean","title":"Ingredient List At End","description":"Move to end of list. Only works if ingredient_list_class_name is set to a class with end=True for the regulation (CAN/CAN2016: spice, seasoning, herb, colour, flavours, at_end; US: none)","default":false},"ingredient_list_hide_subingredients":{"type":"boolean","title":"Ingredient List Hide Subingredients","default":false},"ingredient_list_merge_subingredients":{"type":"boolean","title":"Ingredient List Merge Subingredients","description":"Merge nested recipe's ingredients into main list. Only applies when using `source_recipe_id`","default":false},"instructions_display_as_overwrite_en":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Instructions Display As Overwrite En","description":"Custom name for cooking instructions (not for regulatory labels)"},"instructions_display_as_overwrite_fr":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Instructions Display As Overwrite Fr","description":"Custom name for cooking instructions (not for regulatory labels)"}},"type":"object","required":["unit"],"title":"AddIngredientRecipeIn"},"AddLabelAdditionalRecipeIn":{"properties":{"recipe_id":{"type":"string","title":"Recipe Id","description":"Recipe for this column's nutrition values"},"serving_qty":{"type":"string","format":"decimal","title":"Serving Qty","description":"Serving quantity (default: 100)","default":"100","example":"99.5"},"serving_unit":{"type":"string","maxLength":255,"title":"Serving Unit","description":"Serving unit (default: g)","default":"g"},"reference_qty":{"type":"string","format":"decimal","title":"Reference Qty","description":"Reference amount (default: 100)","default":"100","example":"99.5"},"reference_unit":{"type":"string","maxLength":255,"title":"Reference Unit","description":"Reference unit (default: g)","default":"g"},"household_serving_en":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Household Serving En","description":"English household measure (e.g., '1 cup prepared')"},"household_serving_fr":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Household Serving Fr","description":"French household measure"},"household_serving_prefix_en":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Household Serving Prefix En","description":"English prefix (default: Per)","default":"Per"},"household_serving_prefix_fr":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Household Serving Prefix Fr","description":"French prefix (default: par)","default":"par"},"is_prepackaged_meal":{"type":"boolean","title":"Is Prepackaged Meal","description":"Whether prepackaged meal (default: false)","default":false},"column_name_en":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Column Name En","description":"English column header (e.g., 'As Prepared')"},"column_name_fr":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Column Name Fr","description":"French column header"},"label_version_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Label Version Id"}},"type":"object","required":["recipe_id"],"title":"AddLabelAdditionalRecipeIn"},"AddLabelAdditionalRecipeLabelIn":{"properties":{"recipe_id":{"type":"string","title":"Recipe Id","description":"Recipe for this column's nutrition values"},"serving_qty":{"type":"string","format":"decimal","title":"Serving Qty","description":"Serving quantity (default: 100)","default":"100","example":"99.5"},"serving_unit":{"type":"string","maxLength":255,"title":"Serving Unit","description":"Serving unit (default: g)","default":"g"},"reference_qty":{"type":"string","format":"decimal","title":"Reference Qty","description":"Reference amount (default: 100)","default":"100","example":"99.5"},"reference_unit":{"type":"string","maxLength":255,"title":"Reference Unit","description":"Reference unit (default: g)","default":"g"},"household_serving_en":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Household Serving En","description":"English household measure (e.g., '1 cup prepared')"},"household_serving_fr":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Household Serving Fr","description":"French household measure"},"household_serving_prefix_en":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Household Serving Prefix En","description":"English prefix (default: Per)","default":"Per"},"household_serving_prefix_fr":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Household Serving Prefix Fr","description":"French prefix (default: par)","default":"par"},"is_prepackaged_meal":{"type":"boolean","title":"Is Prepackaged Meal","description":"Whether prepackaged meal (default: false)","default":false},"column_name_en":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Column Name En","description":"English column header (e.g., 'As Prepared')"},"column_name_fr":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Column Name Fr","description":"French column header"},"label_version_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Label Version Id","description":"Parent label version for optimistic locking"}},"type":"object","required":["recipe_id"],"title":"AddLabelAdditionalRecipeLabelIn"},"AddLabelIn":{"properties":{"name":{"anyOf":[{"type":"string","maxLength":255,"minLength":1},{"type":"null"}],"title":"Name"},"serving_qty":{"type":"string","format":"decimal","title":"Serving Qty","default":"100","example":"99.5"},"serving_unit":{"type":"string","maxLength":255,"title":"Serving Unit","default":"g"},"reference_qty":{"type":"string","format":"decimal","title":"Reference Qty","default":"100","example":"99.5"},"reference_unit":{"type":"string","maxLength":255,"title":"Reference Unit","default":"g"},"household_serving_en":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Household Serving En"},"household_serving_fr":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Household Serving Fr"},"household_serving_prefix_en":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Household Serving Prefix En","default":"Per"},"household_serving_prefix_fr":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Household Serving Prefix Fr","default":"par"},"servings_per_container":{"anyOf":[{"type":"string","format":"decimal","example":"99.5"},{"type":"null"}],"title":"Servings Per Container"},"is_prepackaged_meal":{"type":"boolean","title":"Is Prepackaged Meal","default":false},"label_format":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Label Format","description":"Label layout format (default: standard_bilingual). CAN2016: standard, narrow, standard_bilingual, dual, aggregate, etc. US: standard, simplified, tabular, dual. Full list from GET /v1/utils/label_rules/{concrete_type}","default":"standard_bilingual"},"label_format_version":{"anyOf":[{"type":"string","maxLength":255},{"type":"integer"},{"type":"null"}],"title":"Label Format Version","description":"Format version. Valid values from GET /v1/utils/label_rules/{concrete_type}"},"label_language":{"anyOf":[{"type":"string","maxLength":2},{"type":"null"}],"title":"Label Language"},"show_table":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Show Table"},"show_ingredient_list":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Show Ingredient List"},"ingredient_list_align":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Ingredient List Align","description":"Text alignment. Values from GET /v1/utils/label_rules/{concrete_type}"},"ingredient_list_case":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Ingredient List Case","description":"Case transformation. Values from GET /v1/utils/label_rules/{concrete_type}"},"ingredient_list_border":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Ingredient List Border"},"ingredient_list_use_bullet_sep":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Ingredient List Use Bullet Sep"},"options":{"anyOf":[{"additionalProperties":{"anyOf":[{"type":"boolean"},{"type":"string"},{"type":"null"}]},"type":"object"},{"type":"null"}],"title":"Options","description":"Format-specific options. Valid keys and defaults from GET /v1/utils/label_rules/{concrete_type}"},"table_extra_width":{"anyOf":[{"type":"string","format":"decimal","example":"99.5"},{"type":"null"}],"title":"Table Extra Width"},"column_name_en":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Column Name En","description":"Custom column header for dual-column labels (e.g., 'As Packaged')"},"column_name_fr":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Column Name Fr","description":"French column header for dual-column labels"},"serving_extra_en":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Serving Extra En","description":"Additional text appended after serving size line"},"serving_extra_fr":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Serving Extra Fr","description":"French text appended after serving size line"},"label_additional_recipes":{"anyOf":[{"items":{"anyOf":[{"$ref":"#/components/schemas/EditLabelAdditionalRecipeLabelIn"},{"$ref":"#/components/schemas/AddLabelAdditionalRecipeLabelIn"}]},"type":"array"},{"type":"null"}],"title":"Label Additional Recipes","default":[]},"supplemented_cautionary_statements":{"anyOf":[{"items":{"$ref":"#/components/schemas/SupplementedCautionaryStatementIn"},"type":"array"},{"type":"null"}],"title":"Supplemented Cautionary Statements","default":[]},"recipe_id":{"type":"string","title":"Recipe Id"},"concrete_type":{"type":"string","maxLength":255,"title":"Concrete Type","description":"Regulation type: 'CAN2016' (Canadian) or 'US' (American). See GET /v1/utils/concrete_types"},"specification_type":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Specification Type","description":"Reserved for future use"}},"type":"object","required":["recipe_id","concrete_type"],"title":"AddLabelIn"},"AddRecipeCustomUnitIn":{"properties":{"name_en":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Name En","default":""},"name_fr":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Name Fr","default":""},"rate":{"type":"string","format":"decimal","title":"Rate","default":"1","example":"99.5"},"unit_to":{"type":"string","maxLength":255,"title":"Unit To","default":"g"},"recipe_version_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Recipe Version Id"}},"type":"object","title":"AddRecipeCustomUnitIn"},"AddRecipeIn":{"properties":{"name":{"anyOf":[{"type":"string","maxLength":255,"minLength":1},{"type":"null"}],"title":"Name"},"ingredients":{"items":{"anyOf":[{"$ref":"#/components/schemas/EditIngredientRecipeIn"},{"$ref":"#/components/schemas/AddIngredientRecipeIn"}]},"type":"array","title":"Ingredients","default":[]},"yield_qty":{"type":"string","format":"decimal","title":"Yield Qty","default":"100","example":"99.5"},"yield_unit":{"type":"string","maxLength":255,"title":"Yield Unit","default":"%"},"density_overwrite":{"anyOf":[{"type":"string","format":"decimal","example":"99.5"},{"type":"null"}],"title":"Density Overwrite"},"extra_allergies":{"items":{"$ref":"#/components/schemas/AllergyIn"},"type":"array","title":"Extra Allergies","default":[]},"extra_may_contains":{"items":{"$ref":"#/components/schemas/MayContainIn"},"type":"array","title":"Extra May Contains","default":[]},"ingredient_list_overwrite_en":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Ingredient List Overwrite En"},"ingredient_list_overwrite_fr":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Ingredient List Overwrite Fr"},"instructions_en":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Instructions En"},"instructions_fr":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Instructions Fr"},"notes_en":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Notes En"},"notes_fr":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Notes Fr"},"image_path":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Image Path"},"nutriments_overwrite_qty":{"anyOf":[{"type":"string","format":"decimal","example":"99.5"},{"type":"null"}],"title":"Nutriments Overwrite Qty"},"nutriments_overwrite_unit":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Nutriments Overwrite Unit"},"nutriments_overwrite":{"anyOf":[{"$ref":"#/components/schemas/NutrimentsIn"},{"type":"null"}]},"product_code":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Product Code"},"common_name_en":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Common Name En","description":"It will be used in the ingredient list statement if the recipe is used as an ingredient in another recipe."},"common_name_fr":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Common Name Fr","description":"It will be used in the ingredient list statement if the recipe is used as an ingredient in another recipe."},"synchronized_sort_allergies":{"type":"boolean","title":"Synchronized Sort Allergies","default":false},"custom_units":{"items":{"anyOf":[{"$ref":"#/components/schemas/EditCustomUnitRecipeIn"},{"$ref":"#/components/schemas/AddCustomUnitRecipeIn"}]},"type":"array","title":"Custom Units","description":"Custom units of measure","default":[]}},"type":"object","title":"AddRecipeIn"},"AddRecipeTagAssociationIn":{"properties":{"recipe_tag_id":{"type":"string","title":"Recipe Tag Id","description":"Tag ID to associate"}},"type":"object","required":["recipe_tag_id"],"title":"AddRecipeTagAssociationIn","description":"Request to associate a tag with a recipe."},"AddRecipeTagIn":{"properties":{"name":{"type":"string","maxLength":255,"minLength":1,"title":"Name"},"color":{"anyOf":[{"type":"string","format":"color"},{"type":"null"}],"title":"Color"}},"type":"object","required":["name"],"title":"AddRecipeTagIn"},"AllergenSourceOut":{"properties":{"type":{"type":"string","title":"Type","description":"Type of source: 'food' or 'recipe'"},"id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Id","description":"ID of the food or recipe"},"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name","description":"Name of the food or recipe"}},"type":"object","required":["type"],"title":"AllergenSourceOut"},"AllergiesInfoOut":{"properties":{"name_en":{"type":"string","maxLength":255,"title":"Name En","description":"English name of the allergen"},"name_fr":{"type":"string","maxLength":255,"title":"Name Fr","description":"French name of the allergen"},"to_specify":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"To Specify","description":"If true, requires user to specify details (e.g., type of fish)"}},"type":"object","required":["name_en","name_fr"],"title":"AllergiesInfoOut","description":"Standard allergen option from Health Canada and FDA allergen lists."},"AllergyIn":{"properties":{"name_en":{"type":"string","maxLength":255,"title":"Name En"},"name_fr":{"type":"string","maxLength":255,"title":"Name Fr"}},"type":"object","required":["name_en","name_fr"],"title":"AllergyIn"},"AllergyOut":{"properties":{"name_en":{"type":"string","maxLength":255,"title":"Name En"},"name_fr":{"type":"string","maxLength":255,"title":"Name Fr"},"sources":{"anyOf":[{"items":{"$ref":"#/components/schemas/AllergenSourceOut"},"type":"array"},{"type":"null"}],"title":"Sources","description":"Sources of this allergen (only populated in Recipe)"}},"type":"object","required":["name_en","name_fr"],"title":"AllergyOut"},"Body_add_organization_logo_v1_me_organization_logo_post":{"properties":{"upload_file":{"type":"string","contentMediaType":"application/octet-stream","title":"Upload File","description":"Logo image file. Multipart form field name: `upload_file`"}},"type":"object","required":["upload_file"],"title":"Body_add_organization_logo_v1_me_organization_logo_post"},"Body_add_technical_file_v1_foods__food_id__technical_file_post":{"properties":{"upload_file":{"type":"string","contentMediaType":"application/octet-stream","title":"Upload File","description":"The file to upload. Multipart form field name: `upload_file`"}},"type":"object","required":["upload_file"],"title":"Body_add_technical_file_v1_foods__food_id__technical_file_post"},"CustomUnitOut":{"properties":{"id":{"type":"string","title":"Id","description":"Unique identifier for the custom unit"},"name_en":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Name En","description":"English display name (e.g., 'cup', 'slice')"},"name_fr":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Name Fr","description":"French display name"},"rate":{"type":"string","format":"decimal","title":"Rate","description":"Conversion factor to base unit","example":"99.5"},"unit_to":{"type":"string","title":"Unit To","description":"Base unit to convert to (e.g., 'g', 'mL'). Valid values from GET /v1/utils/available_units"},"food_version_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Food Version Id","description":"Current food version for optimistic locking"}},"type":"object","required":["id","rate","unit_to"],"title":"CustomUnitOut","description":"Custom unit of measure defined for a food."},"DeleteFoodIn":{"properties":{"food_version_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Food Version Id","description":"Optional version ID for optimistic locking"}},"type":"object","title":"DeleteFoodIn","description":"Request body for delete operations (can be empty)."},"DeleteRecipeCustomUnitIn":{"properties":{"recipe_version_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Recipe Version Id","description":"Optional version ID for optimistic locking"}},"type":"object","title":"DeleteRecipeCustomUnitIn"},"DeleteRecipeIn":{"properties":{"recipe_version_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Recipe Version Id","description":"Optional version ID for optimistic locking"}},"type":"object","title":"DeleteRecipeIn","description":"Request body for delete operations (can be empty)."},"EditCustomUnitFoodIn":{"properties":{"id":{"type":"string","title":"Id"},"name_en":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Name En"},"name_fr":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Name Fr"},"rate":{"anyOf":[{"type":"string","format":"decimal","example":"99.5"},{"type":"null"}],"title":"Rate"},"unit_to":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Unit To"}},"type":"object","required":["id"],"title":"EditCustomUnitFoodIn"},"EditCustomUnitIn":{"properties":{"name_en":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Name En"},"name_fr":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Name Fr"},"rate":{"anyOf":[{"type":"string","format":"decimal","example":"99.5"},{"type":"null"}],"title":"Rate"},"unit_to":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Unit To"},"food_version_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Food Version Id"}},"type":"object","title":"EditCustomUnitIn"},"EditCustomUnitRecipeIn":{"properties":{"id":{"type":"string","title":"Id"},"name_en":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Name En"},"name_fr":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Name Fr"},"rate":{"anyOf":[{"type":"string","format":"decimal","example":"99.5"},{"type":"null"}],"title":"Rate"},"unit_to":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Unit To"}},"type":"object","required":["id"],"title":"EditCustomUnitRecipeIn"},"EditFoodIn":{"properties":{"name":{"anyOf":[{"type":"string","maxLength":255,"minLength":1},{"type":"null"}],"title":"Name","description":"Display name for the ingredient. If not provided, computed from name_en or name_fr"},"name_en":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Name En","description":"English name of the ingredient"},"name_fr":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Name Fr","description":"French name of the ingredient"},"common_name_en":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Common Name En","description":"English common name (regulatory term)"},"common_name_fr":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Common Name Fr","description":"French common name (regulatory term)"},"public":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Public","description":"Whether the ingredient is publicly visible"},"brand":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Brand","description":"Brand name for branded ingredients"},"source":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Source","description":"Internal use"},"mass_quantity":{"anyOf":[{"type":"string","format":"decimal","example":"99.5"},{"type":"null"}],"title":"Mass Quantity","description":"Base mass quantity for nutriment values. Must be positive"},"mass_unit":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Mass Unit","description":"Unit for mass_quantity (e.g., 'g', 'kg'). Valid values from GET /v1/utils/available_units"},"volume_quantity":{"anyOf":[{"type":"string","format":"decimal","example":"99.5"},{"type":"null"}],"title":"Volume Quantity","description":"Optional volume equivalent of the mass quantity"},"volume_unit":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Volume Unit","description":"Unit for volume_quantity (e.g., 'mL', 'L')"},"custom_units":{"anyOf":[{"items":{"anyOf":[{"$ref":"#/components/schemas/EditCustomUnitFoodIn"},{"$ref":"#/components/schemas/AddCustomUnitFoodIn"}]},"type":"array"},{"type":"null"}],"title":"Custom Units","description":"Custom units of measure with conversion rates"},"refuse_pct":{"anyOf":[{"type":"string","format":"decimal","example":"99.5"},{"type":"null"}],"title":"Refuse Pct","description":"Percentage of ingredient that is waste/refuse (0-100)"},"refuse_description_en":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Refuse Description En","description":"English description of refuse (e.g., 'skin and seeds')"},"refuse_description_fr":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Refuse Description Fr","description":"French description of refuse"},"auto_apply_refuse":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Auto Apply Refuse","description":"Auto-apply refuse percentage when added to recipes"},"ingredient_list_en":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Ingredient List En","description":"English ingredient list text for compound ingredients"},"ingredient_list_fr":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Ingredient List Fr","description":"French ingredient list text for compound ingredients"},"ingredient_list_preserve_case":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Ingredient List Preserve Case","description":"Preserve original case in ingredient list"},"nutriments":{"anyOf":[{"$ref":"#/components/schemas/NutrimentsIn"},{"type":"null"}],"description":"Nutritional values for the specified mass_quantity"},"allergies":{"anyOf":[{"items":{"$ref":"#/components/schemas/AllergyIn"},"type":"array"},{"type":"null"}],"title":"Allergies","description":"Allergens present (contains statements). Standard allergens from GET /v1/utils/allergies"},"may_contains":{"anyOf":[{"items":{"$ref":"#/components/schemas/MayContainIn"},"type":"array"},{"type":"null"}],"title":"May Contains","description":"Potential allergens from cross-contamination. Standard allergens from GET /v1/utils/allergies"},"density_overwrite":{"anyOf":[{"type":"string","format":"decimal","example":"99.5"},{"type":"null"}],"title":"Density Overwrite","description":"Manual density override in g/mL"},"product_code":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Product Code","description":"User-defined identifier (UPC/SKU)"},"irradiated":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Irradiated","description":"Whether ingredient has been irradiated"},"irradiated_fr_feminine":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Irradiated Fr Feminine","description":"French grammar: feminine form"},"irradiated_fr_plural":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Irradiated Fr Plural","description":"French grammar: plural form"},"thawed":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Thawed","description":"Whether ingredient was previously frozen"},"notes_en":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Notes En","description":"Internal English notes"},"notes_fr":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Notes Fr","description":"Internal French notes"},"version_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Version Id","description":"Optional version ID for optimistic locking. If provided and doesn't match current version, update fails"}},"type":"object","title":"EditFoodIn","description":"Request body for updating an ingredient.\nAll fields are optional. Omitted fields are preserved (not cleared)."},"EditFoodTagIn":{"properties":{"name":{"anyOf":[{"type":"string","maxLength":255,"minLength":1},{"type":"null"}],"title":"Name"},"color":{"anyOf":[{"type":"string","format":"color"},{"type":"null"}],"title":"Color"}},"type":"object","title":"EditFoodTagIn"},"EditFopLabelIn":{"properties":{"name":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Name","description":"Display name for the FOP label"},"serving_qty":{"anyOf":[{"type":"string","format":"decimal","example":"99.5"},{"type":"null"}],"title":"Serving Qty","description":"Serving size quantity"},"serving_unit":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Serving Unit","description":"Unit for serving quantity (e.g., 'g', 'mL')"},"reference_qty":{"anyOf":[{"type":"string","format":"decimal","example":"99.5"},{"type":"null"}],"title":"Reference Qty","description":"Reference amount quantity for calculations"},"reference_unit":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Reference Unit","description":"Unit for reference quantity"},"is_prepackaged_meal":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Prepackaged Meal","description":"True if this is a prepackaged meal (applies different FOP thresholds)"},"label_format":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Label Format","description":"FOP symbol format: bilingual_horizontal, bilingual_vertical, unilingual_horizontal, unilingual_vertical, supplemented_unilingual, supplemented_bilingual. Full list from GET /v1/utils/fop_label_rules/{concrete_type}"},"label_format_version":{"anyOf":[{"type":"string","maxLength":255},{"type":"integer"},{"type":"null"}],"title":"Label Format Version","description":"Version of the label format. Valid values from GET /v1/utils/fop_label_rules/{concrete_type}"},"label_language":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Label Language","description":"Language code: 'en' or 'fr'. For bilingual, use a bilingual label_format. Determines which language appears first"},"version_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Version Id","description":"Expected version for optimistic locking"}},"type":"object","title":"EditFopLabelIn","description":"Input for updating an existing FOP label. All fields optional."},"EditIngredientIn":{"properties":{"quantity":{"anyOf":[{"type":"string","format":"decimal","example":"99.5"},{"type":"null"}],"title":"Quantity"},"unit":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Unit"},"order":{"anyOf":[{"type":"integer","minimum":0.0},{"type":"null"}],"title":"Order"},"refuse_pct":{"anyOf":[{"type":"string","format":"decimal","example":"99.5"},{"type":"null"}],"title":"Refuse Pct"},"ingredient_list_display_as_overwrite_en":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Ingredient List Display As Overwrite En"},"ingredient_list_display_as_overwrite_fr":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Ingredient List Display As Overwrite Fr"},"ingredient_list_class_name":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Ingredient List Class Name","description":"Regulatory grouping. Values from GET /v1/utils/class_names. Required for ingredient_list_at_end to work"},"ingredient_list_at_end":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Ingredient List At End","description":"Move to end of list. Only works if ingredient_list_class_name is set to a class with end=True for the regulation (CAN/CAN2016: spice, seasoning, herb, colour, flavours, at_end; US: none)"},"ingredient_list_hide_subingredients":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Ingredient List Hide Subingredients"},"ingredient_list_preserve_case":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Ingredient List Preserve Case"},"ingredient_list_merge_subingredients":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Ingredient List Merge Subingredients","description":"Merge nested recipe's ingredients into main list. Only applies when using `source_recipe_id`"},"instructions_display_as_overwrite_en":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Instructions Display As Overwrite En","description":"Custom name for cooking instructions (not for regulatory labels)"},"instructions_display_as_overwrite_fr":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Instructions Display As Overwrite Fr","description":"Custom name for cooking instructions (not for regulatory labels)"},"recipe_version_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Recipe Version Id"}},"type":"object","title":"EditIngredientIn"},"EditIngredientRecipeIn":{"properties":{"id":{"type":"string","title":"Id"},"quantity":{"anyOf":[{"type":"string","format":"decimal","example":"99.5"},{"type":"null"}],"title":"Quantity"},"unit":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Unit"},"order":{"anyOf":[{"type":"integer","minimum":0.0},{"type":"null"}],"title":"Order"},"refuse_pct":{"anyOf":[{"type":"string","format":"decimal","example":"99.5"},{"type":"null"}],"title":"Refuse Pct"},"ingredient_list_display_as_overwrite_en":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Ingredient List Display As Overwrite En"},"ingredient_list_display_as_overwrite_fr":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Ingredient List Display As Overwrite Fr"},"ingredient_list_class_name":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Ingredient List Class Name","description":"Regulatory grouping. Values from GET /v1/utils/class_names. Required for ingredient_list_at_end to work"},"ingredient_list_at_end":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Ingredient List At End","description":"Move to end of list. Only works if ingredient_list_class_name is set to a class with end=True for the regulation (CAN/CAN2016: spice, seasoning, herb, colour, flavours, at_end; US: none)"},"ingredient_list_hide_subingredients":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Ingredient List Hide Subingredients"},"ingredient_list_preserve_case":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Ingredient List Preserve Case"},"ingredient_list_merge_subingredients":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Ingredient List Merge Subingredients","description":"Merge nested recipe's ingredients into main list. Only applies when using `source_recipe_id`"},"instructions_display_as_overwrite_en":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Instructions Display As Overwrite En","description":"Custom name for cooking instructions (not for regulatory labels)"},"instructions_display_as_overwrite_fr":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Instructions Display As Overwrite Fr","description":"Custom name for cooking instructions (not for regulatory labels)"}},"type":"object","required":["id"],"title":"EditIngredientRecipeIn"},"EditLabelAdditionalRecipeIn":{"properties":{"recipe_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Recipe Id","description":"Recipe for this column's nutrition values (can be same as main label or different)"},"serving_qty":{"anyOf":[{"type":"string","format":"decimal","example":"99.5"},{"type":"null"}],"title":"Serving Qty","description":"Serving quantity for this column"},"serving_unit":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Serving Unit","description":"Serving unit. Values from GET /v1/utils/available_units"},"reference_qty":{"anyOf":[{"type":"string","format":"decimal","example":"99.5"},{"type":"null"}],"title":"Reference Qty","description":"Reference amount quantity"},"reference_unit":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Reference Unit","description":"Reference amount unit. Values from GET /v1/utils/available_units"},"household_serving_en":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Household Serving En","description":"English household measure (e.g., '1 cup prepared')"},"household_serving_fr":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Household Serving Fr","description":"French household measure"},"household_serving_prefix_en":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Household Serving Prefix En","description":"English prefix (e.g., 'about')"},"household_serving_prefix_fr":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Household Serving Prefix Fr","description":"French prefix"},"is_prepackaged_meal":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Prepackaged Meal","description":"Whether this column represents a prepackaged meal (affects %DV)"},"column_name_en":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Column Name En","description":"English column header (e.g., 'As Prepared')"},"column_name_fr":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Column Name Fr","description":"French column header"},"label_version_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Label Version Id"}},"type":"object","title":"EditLabelAdditionalRecipeIn"},"EditLabelAdditionalRecipeLabelIn":{"properties":{"id":{"type":"string","title":"Id"},"recipe_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Recipe Id","description":"Recipe for this column's nutrition values (can be same as main label or different)"},"serving_qty":{"anyOf":[{"type":"string","format":"decimal","example":"99.5"},{"type":"null"}],"title":"Serving Qty","description":"Serving quantity for this column"},"serving_unit":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Serving Unit","description":"Serving unit. Values from GET /v1/utils/available_units"},"reference_qty":{"anyOf":[{"type":"string","format":"decimal","example":"99.5"},{"type":"null"}],"title":"Reference Qty","description":"Reference amount quantity"},"reference_unit":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Reference Unit","description":"Reference amount unit. Values from GET /v1/utils/available_units"},"household_serving_en":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Household Serving En","description":"English household measure (e.g., '1 cup prepared')"},"household_serving_fr":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Household Serving Fr","description":"French household measure"},"household_serving_prefix_en":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Household Serving Prefix En","description":"English prefix (e.g., 'about')"},"household_serving_prefix_fr":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Household Serving Prefix Fr","description":"French prefix"},"is_prepackaged_meal":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Prepackaged Meal","description":"Whether this column represents a prepackaged meal (affects %DV)"},"column_name_en":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Column Name En","description":"English column header (e.g., 'As Prepared')"},"column_name_fr":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Column Name Fr","description":"French column header"},"label_version_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Label Version Id","description":"Parent label version for optimistic locking"}},"type":"object","required":["id"],"title":"EditLabelAdditionalRecipeLabelIn"},"EditLabelIn":{"properties":{"name":{"anyOf":[{"type":"string","maxLength":255,"minLength":1},{"type":"null"}],"title":"Name"},"serving_qty":{"anyOf":[{"type":"string","format":"decimal","example":"99.5"},{"type":"null"}],"title":"Serving Qty"},"serving_unit":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Serving Unit"},"reference_qty":{"anyOf":[{"type":"string","format":"decimal","example":"99.5"},{"type":"null"}],"title":"Reference Qty"},"reference_unit":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Reference Unit"},"household_serving_en":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Household Serving En"},"household_serving_fr":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Household Serving Fr"},"household_serving_prefix_en":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Household Serving Prefix En"},"household_serving_prefix_fr":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Household Serving Prefix Fr"},"servings_per_container":{"anyOf":[{"type":"string","format":"decimal","example":"99.5"},{"type":"null"}],"title":"Servings Per Container"},"is_prepackaged_meal":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Prepackaged Meal"},"label_format":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Label Format","description":"Label layout format. CAN2016: standard, narrow, standard_bilingual, dual, aggregate, etc. US: standard, simplified, tabular, dual. Full list from GET /v1/utils/label_rules/{concrete_type}"},"label_format_version":{"anyOf":[{"type":"string","maxLength":255},{"type":"integer"},{"type":"null"}],"title":"Label Format Version","description":"Format version. Valid values from GET /v1/utils/label_rules/{concrete_type}"},"label_language":{"anyOf":[{"type":"string","maxLength":2},{"type":"null"}],"title":"Label Language"},"show_table":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Show Table"},"show_ingredient_list":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Show Ingredient List"},"ingredient_list_align":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Ingredient List Align","description":"Text alignment. Values from GET /v1/utils/label_rules/{concrete_type}"},"ingredient_list_case":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Ingredient List Case","description":"Case transformation. Values from GET /v1/utils/label_rules/{concrete_type}"},"ingredient_list_border":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Ingredient List Border"},"ingredient_list_use_bullet_sep":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Ingredient List Use Bullet Sep"},"options":{"anyOf":[{"additionalProperties":{"anyOf":[{"type":"boolean"},{"type":"string"},{"type":"null"}]},"type":"object"},{"type":"null"}],"title":"Options","description":"Format-specific options. Valid keys and defaults from GET /v1/utils/label_rules/{concrete_type}"},"table_extra_width":{"anyOf":[{"type":"string","format":"decimal","example":"99.5"},{"type":"null"}],"title":"Table Extra Width"},"column_name_en":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Column Name En","description":"Custom column header for dual-column labels (e.g., 'As Packaged')"},"column_name_fr":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Column Name Fr","description":"French column header for dual-column labels"},"serving_extra_en":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Serving Extra En","description":"Additional text appended after serving size line"},"serving_extra_fr":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Serving Extra Fr","description":"French text appended after serving size line"},"label_additional_recipes":{"anyOf":[{"items":{"anyOf":[{"$ref":"#/components/schemas/EditLabelAdditionalRecipeLabelIn"},{"$ref":"#/components/schemas/AddLabelAdditionalRecipeLabelIn"}]},"type":"array"},{"type":"null"}],"title":"Label Additional Recipes","description":"Additional recipe columns for dual-column NFTs"},"supplemented_cautionary_statements":{"anyOf":[{"items":{"$ref":"#/components/schemas/SupplementedCautionaryStatementIn"},"type":"array"},{"type":"null"}],"title":"Supplemented Cautionary Statements"},"version_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Version Id"}},"type":"object","title":"EditLabelIn"},"EditRecipeCustomUnitIn":{"properties":{"name_en":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Name En"},"name_fr":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Name Fr"},"rate":{"anyOf":[{"type":"string","format":"decimal","example":"99.5"},{"type":"null"}],"title":"Rate"},"unit_to":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Unit To"},"recipe_version_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Recipe Version Id"}},"type":"object","title":"EditRecipeCustomUnitIn"},"EditRecipeIn":{"properties":{"name":{"anyOf":[{"type":"string","maxLength":255,"minLength":1},{"type":"null"}],"title":"Name"},"ingredients":{"anyOf":[{"items":{"anyOf":[{"$ref":"#/components/schemas/EditIngredientRecipeIn"},{"$ref":"#/components/schemas/AddIngredientRecipeIn"}]},"type":"array"},{"type":"null"}],"title":"Ingredients"},"yield_qty":{"anyOf":[{"type":"string","format":"decimal","example":"99.5"},{"type":"null"}],"title":"Yield Qty"},"yield_unit":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Yield Unit"},"density_overwrite":{"anyOf":[{"type":"string","format":"decimal","example":"99.5"},{"type":"null"}],"title":"Density Overwrite"},"extra_allergies":{"anyOf":[{"items":{"$ref":"#/components/schemas/AllergyIn"},"type":"array"},{"type":"null"}],"title":"Extra Allergies"},"extra_may_contains":{"anyOf":[{"items":{"$ref":"#/components/schemas/MayContainIn"},"type":"array"},{"type":"null"}],"title":"Extra May Contains"},"ingredient_list_overwrite_en":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Ingredient List Overwrite En"},"ingredient_list_overwrite_fr":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Ingredient List Overwrite Fr"},"instructions_en":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Instructions En"},"instructions_fr":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Instructions Fr"},"notes_en":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Notes En"},"notes_fr":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Notes Fr"},"image_path":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Image Path"},"nutriments_overwrite_qty":{"anyOf":[{"type":"string","format":"decimal","example":"99.5"},{"type":"null"}],"title":"Nutriments Overwrite Qty"},"nutriments_overwrite_unit":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Nutriments Overwrite Unit"},"nutriments_overwrite":{"anyOf":[{"$ref":"#/components/schemas/NutrimentsIn"},{"type":"null"}]},"product_code":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Product Code"},"common_name_en":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Common Name En","description":"It will be used in the ingredient list statement if the recipe is used as an ingredient in another recipe."},"common_name_fr":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Common Name Fr","description":"It will be used in the ingredient list statement if the recipe is used as an ingredient in another recipe."},"synchronized_sort_allergies":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Synchronized Sort Allergies"},"custom_units":{"anyOf":[{"items":{"anyOf":[{"$ref":"#/components/schemas/EditCustomUnitRecipeIn"},{"$ref":"#/components/schemas/AddCustomUnitRecipeIn"}]},"type":"array"},{"type":"null"}],"title":"Custom Units","description":"Custom units of measure with conversion rates"},"version_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Version Id"}},"type":"object","title":"EditRecipeIn"},"EditRecipeTagIn":{"properties":{"name":{"anyOf":[{"type":"string","maxLength":255,"minLength":1},{"type":"null"}],"title":"Name"},"color":{"anyOf":[{"type":"string","format":"color"},{"type":"null"}],"title":"Color"}},"type":"object","title":"EditRecipeTagIn"},"EquationOut":{"properties":{"message_en":{"type":"string","title":"Message En","description":"English equation/formula"},"message_fr":{"type":"string","title":"Message Fr","description":"French equation/formula"}},"type":"object","required":["message_en","message_fr"],"title":"EquationOut","description":"Mathematical equation used in validation calculations."},"FoodListOut":{"properties":{"items":{"items":{"$ref":"#/components/schemas/FoodOut"},"type":"array","title":"Items"},"page_info":{"$ref":"#/components/schemas/PageInfo"}},"type":"object","required":["items","page_info"],"title":"FoodListOut"},"FoodOut":{"properties":{"id":{"type":"string","title":"Id","description":"Unique identifier for this ingredient"},"tenant_id":{"type":"string","title":"Tenant Id","description":"Organization ID that owns this ingredient"},"name":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Name","description":"Computed display name. Returns `name_en` if set, otherwise `name_fr`, otherwise 'New ingredient'"},"name_en":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Name En","description":"English name of the ingredient"},"name_fr":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Name Fr","description":"French name of the ingredient"},"common_name_en":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Common Name En","description":"English common name (regulatory term for the ingredient)"},"common_name_fr":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Common Name Fr","description":"French common name (regulatory term for the ingredient)"},"public":{"type":"boolean","title":"Public","description":"Whether this ingredient is publicly visible. User-created ingredients are typically `false`"},"brand":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Brand","description":"Brand name for branded ingredients (common with USDA data)"},"source":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Source","description":"Provenance tracking. Typically null for user-created or database foods, or `ID:{food_id}` if duplicated from another ingredient. To filter by origin, use the `source` query parameter (USER, CNF, USDA) which checks the CNF/USDA fields"},"CNF":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Cnf","description":"Canadian Nutrient File database ID. Present only for CNF-sourced ingredients"},"USDA":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Usda","description":"USDA database ID. Present only for USDA-sourced ingredients"},"dataset_version":{"anyOf":[{"type":"string","maxLength":50},{"type":"null"}],"title":"Dataset Version","description":"Source dataset generation for public database ingredients (e.g., `CNF2026`). Null for user-created ingredients"},"legacy_dataset":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Legacy Dataset","description":"True when this ingredient comes from a legacy dataset generation (e.g., CNF 2016 after the CNF 2026 refresh). Legacy ingredients are hidden from search unless `include_legacy_datasets=true`, but remain fully usable. Null for user-created ingredients, which have no dataset generation"},"mass_quantity":{"type":"string","format":"decimal","title":"Mass Quantity","description":"Base mass quantity for nutriment values. Default: '100'","example":"99.5"},"mass_unit":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Mass Unit","description":"Unit for mass_quantity. Default: 'g'. Valid values from GET /v1/utils/available_units"},"volume_quantity":{"anyOf":[{"type":"string","format":"decimal","example":"99.5"},{"type":"null"}],"title":"Volume Quantity","description":"Optional volume equivalent of the mass quantity"},"volume_unit":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Volume Unit","description":"Unit for volume_quantity, e.g., 'mL'"},"custom_units":{"items":{"$ref":"#/components/schemas/CustomUnitOut"},"type":"array","title":"Custom Units","description":"User-defined units of measure (e.g., 'cup', 'slice') with conversion rates"},"refuse_pct":{"type":"string","format":"decimal","title":"Refuse Pct","description":"Percentage of ingredient that is waste/refuse (0-100). Default: '0'","example":"99.5"},"refuse_description_en":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Refuse Description En","description":"English description of the refuse portion (e.g., 'skin and seeds')"},"refuse_description_fr":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Refuse Description Fr","description":"French description of the refuse portion"},"auto_apply_refuse":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Auto Apply Refuse","description":"When true, automatically apply refuse percentage when this ingredient is added to recipes"},"ingredient_list_en":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Ingredient List En","description":"English ingredient list text for compound ingredients (appears on labels)"},"ingredient_list_fr":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Ingredient List Fr","description":"French ingredient list text for compound ingredients"},"ingredient_list_preserve_case":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Ingredient List Preserve Case","description":"When true, preserve original case in ingredient list instead of applying regulatory formatting"},"nutriments":{"$ref":"#/components/schemas/NutrimentsOut","description":"Nutritional values for the specified mass_quantity"},"nutriments_validation":{"anyOf":[{"$ref":"#/components/schemas/NutrimentsValidationOut"},{"type":"null"}],"description":"Validation results comparing declared vs calculated nutriment values"},"allergies":{"items":{"$ref":"#/components/schemas/AllergyOut"},"type":"array","title":"Allergies","description":"Allergens present in this ingredient (contains statements). Standard allergens from GET /v1/utils/allergies"},"may_contains":{"items":{"$ref":"#/components/schemas/MayContainOut"},"type":"array","title":"May Contains","description":"Potential allergens from cross-contamination (may contain statements). Standard allergens from GET /v1/utils/allergies"},"density_overwrite":{"anyOf":[{"type":"string","format":"decimal","example":"99.5"},{"type":"null"}],"title":"Density Overwrite","description":"Manual density override in g/mL for volume-to-mass conversions"},"product_code":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Product Code","description":"User-defined identifier, typically a UPC barcode or internal SKU. Not validated for uniqueness"},"irradiated":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Irradiated","description":"Whether the ingredient has been irradiated (regulatory disclosure)"},"irradiated_fr_feminine":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Irradiated Fr Feminine","description":"French grammar: use feminine form for 'irradiated' (irradiee vs irradie)"},"irradiated_fr_plural":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Irradiated Fr Plural","description":"French grammar: use plural form for 'irradiated'"},"thawed":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Thawed","description":"Whether the ingredient was previously frozen (regulatory disclosure)"},"notes_en":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Notes En","description":"Internal English notes (not displayed on labels)"},"notes_fr":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Notes Fr","description":"Internal French notes (not displayed on labels)"},"recipe_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Recipe Id","description":"(Legacy) For subrecipes: source recipe ID. Prefer adding recipes directly as ingredients using `source_recipe_id`"},"recipe_version_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Recipe Version Id","description":"(Legacy) For subrecipes: version when last synced"},"recipe_ingredient_list_en":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Recipe Ingredient List En","description":"(Legacy) For subrecipes: auto-generated English ingredient list"},"recipe_ingredient_list_fr":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Recipe Ingredient List Fr","description":"(Legacy) For subrecipes: auto-generated French ingredient list"},"available_units":{"items":{"$ref":"#/components/schemas/UnitOut"},"type":"array","title":"Available Units","description":"All available units for this ingredient: standard units from GET /v1/utils/available_units plus custom_units"},"density":{"anyOf":[{"type":"string","format":"decimal","example":"99.5"},{"type":"null"}],"title":"Density","description":"Computed or overwritten density in g/mL"},"technical_file":{"anyOf":[{"$ref":"#/components/schemas/TechnicalFile"},{"type":"null"}],"description":"Attached specification sheet or reference document"},"nutriments_100g":{"anyOf":[{"$ref":"#/components/schemas/NutrimentsOut"},{"type":"null"}],"description":"Nutriments normalized to 100g. Only present when expand=nutriments_100g is requested"},"nutriments_100g_validation":{"anyOf":[{"$ref":"#/components/schemas/NutrimentsValidationOut"},{"type":"null"}],"description":"Validation for normalized nutriments. Only present when expand=nutriments_100g is requested"},"created_date":{"type":"string","format":"date-time","title":"Created Date","description":"When this ingredient was created"},"updated_date":{"type":"string","format":"date-time","title":"Updated Date","description":"When this ingredient was last modified"},"version_id":{"type":"integer","title":"Version Id","description":"Internal version tracking"},"subversion_id":{"type":"integer","title":"Subversion Id","description":"Internal version tracking"},"tags":{"anyOf":[{"items":{"$ref":"#/components/schemas/FoodTagOut"},"type":"array"},{"type":"null"}],"title":"Tags","description":"Tag associations. Only present when expand=tags is requested"},"warnings":{"anyOf":[{"items":{"$ref":"#/components/schemas/WarningOut"},"type":"array"},{"type":"null"}],"title":"Warnings","description":"Validation warnings (e.g., nutriment sum exceeds portion size)"}},"type":"object","required":["id","tenant_id","public","mass_quantity","custom_units","refuse_pct","nutriments","allergies","may_contains","available_units","created_date","updated_date","version_id","subversion_id"],"title":"FoodOut","description":"Complete ingredient (food) response object.\nIn the UI, foods are called \"Ingredients\"."},"FoodTagListOut":{"properties":{"items":{"items":{"$ref":"#/components/schemas/FoodTagOut"},"type":"array","title":"Items","description":"List of food tag records"},"page_info":{"anyOf":[{"$ref":"#/components/schemas/PageInfo"},{"type":"null"}],"description":"Pagination metadata"}},"type":"object","required":["items"],"title":"FoodTagListOut","description":"Paginated list of food tags."},"FoodTagOut":{"properties":{"id":{"type":"string","title":"Id","description":"Unique tag identifier"},"tenant_id":{"type":"string","title":"Tenant Id","description":"Tenant that owns this tag"},"name":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Name","description":"Display name for the tag"},"color":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Color","description":"Hex color code for visual display (e.g., '#FF5733')"},"created_date":{"type":"string","format":"date-time","title":"Created Date","description":"When the tag was created"},"updated_date":{"type":"string","format":"date-time","title":"Updated Date","description":"When the tag was last modified"}},"type":"object","required":["id","tenant_id","created_date","updated_date"],"title":"FoodTagOut","description":"Tag specifically for organizing foods/ingredients."},"FopLabelListOut":{"properties":{"items":{"items":{"$ref":"#/components/schemas/FopLabelOut"},"type":"array","title":"Items"},"page_info":{"$ref":"#/components/schemas/PageInfo"}},"type":"object","required":["items","page_info"],"title":"FopLabelListOut"},"FopLabelOut":{"properties":{"id":{"type":"string","title":"Id","description":"Unique identifier for the FOP label"},"tenant_id":{"type":"string","title":"Tenant Id","description":"Tenant that owns this FOP label"},"recipe_id":{"type":"string","title":"Recipe Id","description":"Recipe this FOP label is associated with"},"name":{"type":"string","maxLength":255,"title":"Name","description":"Display name for the FOP label"},"serving_qty":{"type":"string","format":"decimal","title":"Serving Qty","description":"Serving size quantity for calculation basis","example":"99.5"},"serving_unit":{"$ref":"#/components/schemas/UnitOut","description":"Unit for serving_qty"},"reference_qty":{"anyOf":[{"type":"string","format":"decimal","example":"99.5"},{"type":"null"}],"title":"Reference Qty","description":"Reference amount quantity (e.g., per 100g)"},"reference_unit":{"$ref":"#/components/schemas/UnitOut","description":"Unit for reference_qty"},"is_prepackaged_meal":{"type":"boolean","title":"Is Prepackaged Meal","description":"Whether this is for a prepackaged meal (affects FOP thresholds)"},"label_format":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Label Format","description":"FOP symbol format: bilingual_horizontal, bilingual_vertical, unilingual_horizontal, unilingual_vertical, supplemented_unilingual, supplemented_bilingual. Full list from GET /v1/utils/fop_label_rules/{concrete_type}"},"label_format_version":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Label Format Version","description":"Version of the label format. Valid values from GET /v1/utils/fop_label_rules/{concrete_type}"},"label_language":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Label Language","description":"Language code: 'en' or 'fr'. For bilingual FOP symbols, use a bilingual label_format (e.g., 'bilingual_horizontal'). Determines which language appears first"},"concrete_type":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Concrete Type","description":"Regulation type: 'CAN2016' for Canadian, 'US' for American. See GET /v1/utils/concrete_types"},"specification_type":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Specification Type","description":"Reserved for future use"},"created_date":{"type":"string","format":"date-time","title":"Created Date","description":"When this FOP label was created"},"updated_date":{"type":"string","format":"date-time","title":"Updated Date","description":"When this FOP label was last modified"},"version_id":{"type":"integer","title":"Version Id","description":"Major version number, incremented on significant changes"},"subversion_id":{"type":"integer","title":"Subversion Id","description":"Minor version number for tracking incremental changes"}},"type":"object","required":["id","tenant_id","recipe_id","name","serving_qty","serving_unit","reference_unit","is_prepackaged_meal","created_date","updated_date","version_id","subversion_id"],"title":"FopLabelOut","description":"Front-of-package (FOP) label output. FOP labels are nutrition symbols displayed on product packaging to quickly communicate nutritional content (e.g., Health Canada's FOP symbol)."},"HTTPBadRequest":{"properties":{"code":{"type":"integer","title":"Error code"},"message_en":{"type":"string","title":"Message EN"},"message_fr":{"type":"string","title":"Message FR"},"type":{"type":"string","title":"Error Type"},"metadata":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Metadata"}},"type":"object","required":["code","message_en","message_fr","type"],"title":"HTTPBadRequest"},"HTTPRateLimitExceeded":{"properties":{"code":{"type":"integer","title":"Error code"},"message_en":{"type":"string","title":"Message EN"},"message_fr":{"type":"string","title":"Message FR"},"type":{"type":"string","title":"Error Type"},"retry_after":{"type":"integer","title":"Retry After (seconds)"},"details":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Rate limit details"}},"type":"object","required":["code","message_en","message_fr","type","retry_after"],"title":"HTTPRateLimitExceeded"},"HTTPValidationError":{"properties":{"code":{"type":"integer","title":"Error code"},"message_en":{"type":"string","title":"Message EN"},"message_fr":{"type":"string","title":"Message FR"},"detail":{"anyOf":[{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array"},{"type":"null"}],"title":"Detail"},"type":{"type":"string","title":"Error Type"}},"type":"object","required":["code","message_en","message_fr","type"],"title":"HTTPValidationError"},"IngredientOut":{"properties":{"id":{"type":"string","title":"Id","description":"Unique identifier for this recipe ingredient line"},"recipe_id":{"type":"string","title":"Recipe Id","description":"ID of the recipe this ingredient belongs to"},"food_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Food Id","description":"ID of the food (ingredient) being referenced. Null if recipe_based=true"},"food_name":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Food Name","description":"Computed name of the referenced food"},"food_name_en":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Food Name En","description":"English name of the referenced food"},"food_name_fr":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Food Name Fr","description":"French name of the referenced food"},"food_common_name_en":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Food Common Name En","description":"English common name of the food"},"food_common_name_fr":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Food Common Name Fr","description":"French common name of the food"},"food_product_code":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Food Product Code","description":"Product code of the referenced food"},"food_refuse_pct":{"type":"string","format":"decimal","title":"Food Refuse Pct","description":"Refuse percentage defined on the food","example":"99.5"},"food_refuse_description_en":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Food Refuse Description En","description":"English refuse description from food"},"food_refuse_description_fr":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Food Refuse Description Fr","description":"French refuse description from food"},"food_auto_apply_refuse":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Food Auto Apply Refuse","description":"Whether food's refuse should auto-apply"},"food_ingredient_list_en":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Food Ingredient List En","description":"Food's English ingredient list (for compound ingredients)"},"food_ingredient_list_fr":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Food Ingredient List Fr","description":"Food's French ingredient list"},"food_irradiated":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Food Irradiated","description":"Whether the food is irradiated"},"food_irradiated_fr_feminine":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Food Irradiated Fr Feminine","description":"French feminine form for irradiated"},"food_irradiated_fr_plural":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Food Irradiated Fr Plural","description":"French plural form for irradiated"},"food_thawed":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Food Thawed","description":"Whether the food was previously frozen"},"food_ingredient_list_preserve_case":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Food Ingredient List Preserve Case","description":"Preserve case in ingredient list"},"food_recipe_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Food Recipe Id","description":"(Legacy) If the food is a subrecipe, the source recipe ID. Subrecipes are legacy; prefer `source_recipe_id`"},"quantity":{"anyOf":[{"type":"string","format":"decimal","example":"99.5"},{"type":"null"}],"title":"Quantity","description":"Amount of this ingredient in the recipe"},"unit":{"$ref":"#/components/schemas/UnitOut","description":"Unit for the quantity. Standard units from GET /v1/utils/available_units or food's custom_units"},"order":{"type":"integer","minimum":0.0,"title":"Order","description":"Sort order within the recipe (0-based)"},"refuse_pct":{"anyOf":[{"type":"string","format":"decimal","example":"99.5"},{"type":"null"}],"title":"Refuse Pct","description":"Override refuse percentage for this ingredient line"},"ingredient_list_display_as_en":{"type":"string","title":"Ingredient List Display As En","description":"How this ingredient appears in English ingredient lists"},"ingredient_list_display_as_fr":{"type":"string","title":"Ingredient List Display As Fr","description":"How this ingredient appears in French ingredient lists"},"ingredient_list_display_as_overwrite_en":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Ingredient List Display As Overwrite En","description":"Manual override for English display name"},"ingredient_list_display_as_overwrite_fr":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Ingredient List Display As Overwrite Fr","description":"Manual override for French display name"},"ingredient_list_class_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Ingredient List Class Name","description":"Regulatory grouping for ingredient list. Values: sugar, spice, seasoning, herb, colour, natural_flavour, artificial_flavour, at_end. Required for `ingredient_list_at_end` to work. Full list from GET /v1/utils/class_names"},"ingredient_list_at_end":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Ingredient List At End","description":"Move this ingredient to end of list. Only works if `ingredient_list_class_name` is set to a class with end-grouping enabled for the label's regulation (CAN/CAN2016: spice, seasoning, herb, colour, natural_flavour, artificial_flavour, at_end; US: none - FDA requires strict weight order)"},"ingredient_list_hide_subingredients":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Ingredient List Hide Subingredients","description":"Hide sub-ingredients in nested recipes"},"ingredient_list_preserve_case":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Ingredient List Preserve Case","description":"Preserve original case instead of regulatory formatting"},"ingredient_list_merge_subingredients":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Ingredient List Merge Subingredients","description":"Merge nested recipe's ingredients into parent list. Only applies when ingredient references a recipe via `source_recipe_id`"},"recipe_based":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Recipe Based","description":"True if this ingredient references another recipe instead of a food"},"recipe_ingredient_list":{"anyOf":[{"additionalProperties":{"additionalProperties":{"type":"string"},"type":"object"},"type":"object"},{"type":"null"}],"title":"Recipe Ingredient List","description":"For recipe-based ingredients: the nested recipe's ingredient list"},"instructions_display_as_en":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Instructions Display As En","description":"How this appears in cooking instructions (not for regulatory labels)"},"instructions_display_as_fr":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Instructions Display As Fr","description":"How this appears in cooking instructions (not for regulatory labels)"},"instructions_display_as_overwrite_en":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Instructions Display As Overwrite En","description":"Custom name for cooking instructions (not for regulatory labels)"},"instructions_display_as_overwrite_fr":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Instructions Display As Overwrite Fr","description":"Custom name for cooking instructions (not for regulatory labels)"},"weight":{"anyOf":[{"$ref":"#/components/schemas/MeasureOut"},{"type":"null"}],"description":"Calculated weight of this ingredient line"},"weight_display":{"anyOf":[{"$ref":"#/components/schemas/MeasureOut"},{"type":"null"}],"description":"Formatted weight for display"},"edible_weight":{"anyOf":[{"$ref":"#/components/schemas/MeasureOut"},{"type":"null"}],"description":"Weight after refuse applied. Only present when expand includes edible volume fields"},"edible_weight_display":{"anyOf":[{"$ref":"#/components/schemas/MeasureOut"},{"type":"null"}],"description":"Formatted edible weight for display"},"edible_weight_pct":{"anyOf":[{"$ref":"#/components/schemas/MeasureOut"},{"type":"null"}],"description":"Edible weight as percentage of total"},"available_units":{"anyOf":[{"items":{"$ref":"#/components/schemas/UnitOut"},"type":"array"},{"type":"null"}],"title":"Available Units","description":"Units available for this ingredient. Standard units from GET /v1/utils/available_units plus food's custom_units"},"nutriments":{"anyOf":[{"$ref":"#/components/schemas/NutrimentsOut"},{"type":"null"}],"description":"Calculated nutriments for this ingredient line. Only present when expand=ingredients.nutriments"},"recipe_version_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Recipe Version Id","description":"Current recipe version for optimistic locking"}},"type":"object","required":["id","recipe_id","food_refuse_pct","unit","order","ingredient_list_display_as_en","ingredient_list_display_as_fr"],"title":"IngredientOut","description":"A line item in a recipe referencing an ingredient (food) or nested recipe with quantity.\nNote: In the UI, 'ingredient' refers to a food entity. In the API, 'ingredient' is a recipe line item."},"LabelAdditionalRecipesListOut":{"properties":{"items":{"items":{"$ref":"#/components/schemas/LabelAdditionalRecipesOut"},"type":"array","title":"Items","description":"List of additional recipe records"}},"type":"object","required":["items"],"title":"LabelAdditionalRecipesListOut","description":"List of additional recipe columns for a label."},"LabelAdditionalRecipesOut":{"properties":{"id":{"type":"string","title":"Id","description":"Unique identifier"},"label_id":{"type":"string","title":"Label Id","description":"Parent label ID"},"recipe_id":{"type":"string","title":"Recipe Id","description":"Recipe used for this column's nutrition values (can be same as main label or different)"},"serving_qty":{"type":"string","format":"decimal","title":"Serving Qty","description":"Serving quantity for this column","example":"99.5"},"serving_unit":{"$ref":"#/components/schemas/UnitOut","description":"Serving unit for this column"},"reference_qty":{"type":"string","format":"decimal","title":"Reference Qty","description":"Reference amount quantity","example":"99.5"},"reference_unit":{"$ref":"#/components/schemas/UnitOut","description":"Reference amount unit"},"household_serving_en":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Household Serving En","description":"English household measure (e.g., '1 cup prepared')"},"household_serving_fr":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Household Serving Fr","description":"French household measure"},"household_serving_prefix_en":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Household Serving Prefix En","description":"English prefix (e.g., 'about')"},"household_serving_prefix_fr":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Household Serving Prefix Fr","description":"French prefix"},"is_prepackaged_meal":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Prepackaged Meal","description":"Whether this column represents a prepackaged meal (affects %DV)"},"column_name_en":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Column Name En","description":"English column header (e.g., 'As Prepared')"},"column_name_fr":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Column Name Fr","description":"French column header"}},"type":"object","required":["id","label_id","recipe_id","serving_qty","serving_unit","reference_qty","reference_unit"],"title":"LabelAdditionalRecipesOut","description":"Additional recipe column for dual-column NFTs.\n\nUsed for labels showing multiple nutrition columns (e.g., 'As Packaged' vs 'As Prepared').\nThe additional recipe provides a second set of nutrition values calculated from a different\nrecipe or the same recipe with different serving size."},"LabelListOut":{"properties":{"items":{"items":{"$ref":"#/components/schemas/LabelOut"},"type":"array","title":"Items"},"page_info":{"$ref":"#/components/schemas/PageInfo"}},"type":"object","required":["items","page_info"],"title":"LabelListOut","description":"Paginated list of full label objects."},"LabelMeasureOut":{"properties":{"width":{"type":"string","format":"decimal","title":"Width","description":"Width in inches","example":"99.5"},"height":{"type":"string","format":"decimal","title":"Height","description":"Height in inches","example":"99.5"},"area":{"type":"string","format":"decimal","title":"Area","description":"Total area in square inches","example":"99.5"},"display_width":{"type":"string","maxLength":255,"title":"Display Width","description":"Formatted width string"},"display_height":{"type":"string","maxLength":255,"title":"Display Height","description":"Formatted height string"},"display_area":{"type":"string","maxLength":255,"title":"Display Area","description":"Formatted area string"}},"type":"object","required":["width","height","area","display_width","display_height","display_area"],"title":"LabelMeasureOut","description":"Dimensions of a rendered label."},"LabelOut":{"properties":{"id":{"type":"string","title":"Id","description":"Unique identifier for this label"},"tenant_id":{"type":"string","title":"Tenant Id","description":"Organization ID that owns this label"},"recipe_id":{"type":"string","title":"Recipe Id","description":"ID of the recipe this label is based on"},"name":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Name","description":"Display name for this label configuration"},"serving_qty":{"type":"string","format":"decimal","title":"Serving Qty","description":"Serving size quantity for nutrient calculations","example":"99.5"},"serving_unit":{"$ref":"#/components/schemas/UnitOut","description":"Unit for serving_qty. Valid values from GET /v1/utils/available_units"},"reference_qty":{"anyOf":[{"type":"string","format":"decimal","example":"99.5"},{"type":"null"}],"title":"Reference Qty","description":"Reference amount for dual-column labels"},"reference_unit":{"$ref":"#/components/schemas/UnitOut","description":"Unit for reference_qty. Valid values from GET /v1/utils/available_units"},"household_serving_en":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Household Serving En","description":"English household serving description (e.g., '1 cup', '2 tbsp')"},"household_serving_fr":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Household Serving Fr","description":"French household serving description"},"household_serving_prefix_en":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Household Serving Prefix En","description":"English prefix for household serving (e.g., 'about')"},"household_serving_prefix_fr":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Household Serving Prefix Fr","description":"French prefix for household serving"},"servings_per_container":{"anyOf":[{"type":"string","format":"decimal","example":"99.5"},{"type":"null"}],"title":"Servings Per Container","description":"Number of servings per package (US labels)"},"is_prepackaged_meal":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Prepackaged Meal","description":"Whether this is a prepackaged meal (affects %DV calculations)"},"label_format":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Label Format","description":"Label layout format. CAN2016: standard, narrow, standard_bilingual, dual, aggregate, linear, etc. US: standard, simplified, tabular, dual, aggregate. Full list from GET /v1/utils/label_rules/{concrete_type}"},"label_format_version":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Label Format Version","description":"Version of the label format template. Valid values from GET /v1/utils/label_rules/{concrete_type}"},"label_language":{"anyOf":[{"type":"string","maxLength":2},{"type":"null"}],"title":"Label Language","description":"Language code: 'en' or 'fr'. For bilingual labels, determines which language appears first (e.g., 'fr' puts French on top)"},"show_table":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Show Table","description":"Whether to display the nutrition facts table"},"show_ingredient_list":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Show Ingredient List","description":"Whether to display the ingredient list"},"ingredient_list_align":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Ingredient List Align","description":"Text alignment for ingredient list. Values from GET /v1/utils/label_rules/{concrete_type}"},"ingredient_list_case":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Ingredient List Case","description":"Case transformation for ingredient list. Values from GET /v1/utils/label_rules/{concrete_type}"},"ingredient_list_border":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Ingredient List Border","description":"Whether to show border around ingredient list"},"ingredient_list_use_bullet_sep":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Ingredient List Use Bullet Sep","description":"Use bullet points as separators instead of commas"},"options":{"anyOf":[{"additionalProperties":{"anyOf":[{"type":"boolean"},{"type":"string"},{"type":"null"}]},"type":"object"},{"type":"null"}],"title":"Options","description":"Format-specific options. Valid keys and defaults from GET /v1/utils/label_rules/{concrete_type}"},"table_extra_width":{"anyOf":[{"type":"string","format":"decimal","example":"99.5"},{"type":"null"}],"title":"Table Extra Width","description":"Additional width in pixels for the NFT table"},"column_name_en":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Column Name En","description":"Custom English column header for dual-column labels (e.g., 'As Packaged')"},"column_name_fr":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Column Name Fr","description":"Custom French column header for dual-column labels"},"serving_extra_en":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Serving Extra En","description":"Additional English text appended after serving size line"},"serving_extra_fr":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Serving Extra Fr","description":"Additional French text appended after serving size line"},"label_additional_recipes":{"items":{"$ref":"#/components/schemas/LabelAdditionalRecipesOut"},"type":"array","title":"Label Additional Recipes","description":"Additional recipe columns for dual-column NFTs (e.g., 'as packaged' vs 'as prepared'). Each entry adds a column with its own recipe and serving size"},"supplemented_cautionary_statements":{"items":{"$ref":"#/components/schemas/LabelSupplementedCautionaryStatementOut"},"type":"array","title":"Supplemented Cautionary Statements","description":"Cautionary statements for supplemented foods"},"concrete_type":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Concrete Type","description":"Regulation type: 'CAN', 'CAN2016', or 'US'. See GET /v1/utils/concrete_types"},"specification_type":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Specification Type","description":"Reserved for future use"},"created_date":{"type":"string","format":"date-time","title":"Created Date","description":"When this label was created"},"updated_date":{"type":"string","format":"date-time","title":"Updated Date","description":"When this label was last modified"},"version_id":{"type":"integer","title":"Version Id","description":"Internal version tracking"},"subversion_id":{"type":"integer","title":"Subversion Id","description":"Internal version tracking"}},"type":"object","required":["id","tenant_id","recipe_id","serving_qty","serving_unit","reference_unit","label_additional_recipes","supplemented_cautionary_statements","created_date","updated_date","version_id","subversion_id"],"title":"LabelOut","description":"Complete Nutrition Facts Table (NFT) label configuration and settings.\nLabels are generated from recipes according to regulatory requirements."},"LabelSupplementedCautionaryStatementOut":{"properties":{"name_en":{"type":"string","maxLength":255,"title":"Name En","description":"English cautionary statement text"},"name_fr":{"type":"string","maxLength":255,"title":"Name Fr","description":"French cautionary statement text"}},"type":"object","required":["name_en","name_fr"],"title":"LabelSupplementedCautionaryStatementOut","description":"Cautionary statement for supplemented foods (Health Canada requirements)."},"MayContainIn":{"properties":{"name_en":{"type":"string","maxLength":255,"title":"Name En"},"name_fr":{"type":"string","maxLength":255,"title":"Name Fr"}},"type":"object","required":["name_en","name_fr"],"title":"MayContainIn"},"MayContainOut":{"properties":{"name_en":{"type":"string","maxLength":255,"title":"Name En"},"name_fr":{"type":"string","maxLength":255,"title":"Name Fr"},"skipping":{"type":"boolean","title":"Only used in a recipe when an allergen is already present in the allergy statement. It will be skipped from the may contain statement."},"sources":{"anyOf":[{"items":{"$ref":"#/components/schemas/AllergenSourceOut"},"type":"array"},{"type":"null"}],"title":"Sources","description":"Sources of this allergen (only populated in Recipe)"}},"type":"object","required":["name_en","name_fr","skipping"],"title":"MayContainOut"},"MeasureOut":{"properties":{"amount":{"anyOf":[{"type":"string","format":"decimal","example":"99.5"},{"type":"null"}],"title":"Amount","description":"Raw numeric value (may be null)"},"amount_round":{"type":"string","format":"decimal","title":"Amount Round","description":"Rounded value for display","example":"99.5"},"unit":{"anyOf":[{"$ref":"#/components/schemas/UnitOut"},{"type":"null"}],"description":"Unit of measure"}},"type":"object","required":["amount_round"],"title":"MeasureOut","description":"A measured quantity with unit."},"MissingNutrientOut":{"properties":{"key":{"type":"string","title":"Key","description":"Nutrient key (e.g., 'protein', 'fat')"},"name_en":{"type":"string","title":"Name En","description":"English nutrient name"},"name_fr":{"type":"string","title":"Name Fr","description":"French nutrient name"}},"type":"object","required":["key","name_en","name_fr"],"title":"MissingNutrientOut","description":"A nutrient required for calculations but not provided."},"NutrimentIn":{"properties":{"amount":{"anyOf":[{"type":"string","format":"decimal","example":"99.5"},{"type":"null"}],"title":"Amount"},"unit":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Unit"}},"type":"object","title":"NutrimentIn"},"NutrimentOut":{"properties":{"amount":{"anyOf":[{"type":"string","format":"decimal","example":"99.5"},{"type":"null"}],"title":"Amount","description":"Raw numeric value (may be null)"},"amount_round":{"type":"string","format":"decimal","title":"Amount Round","description":"Rounded value for display","example":"99.5"},"unit":{"anyOf":[{"$ref":"#/components/schemas/UnitOut"},{"type":"null"}],"description":"Unit of measure"},"name_en":{"type":"string","title":"Name En","description":"English nutrient name"},"name_fr":{"type":"string","title":"Name Fr","description":"French nutrient name"}},"type":"object","required":["amount_round","name_en","name_fr"],"title":"NutrimentOut","description":"A single nutrient value with localized names."},"NutrimentsIn":{"properties":{"calories":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"fat":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"fat_saturated":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"fat_trans":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"cholesterol":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"sodium":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"carbohydrate":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"fibre":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"sugars":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"protein":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"calcium":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"iron":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"potassium":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"vitamin_a_RAE":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"vitamin_c":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"fat_polyunsaturated":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"omega-6":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"omega-3":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"fat_monounsaturated":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"soluble_fibre":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"insoluble_fibre":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"sugar_alcohols":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"starch":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"vitamin_d":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"vitamin_e":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"vitamin_k":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"thiamin":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"riboflavin":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"niacin_NE":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"vitamin_b6":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"folate_DFE":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"vitamin_b12":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"biotin":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"pantothenic_acid":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"choline":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"phosphorus":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"iodide":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"magnesium":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"zinc":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"selenium":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"copper":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"manganese":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"chromium":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"molybdenum":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"chloride":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"polydextrose":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"erythritol":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"caffeine":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"green_tea_extract":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"phosphatidylserine":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"taurine":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"l-alanine":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"l-arginine":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"l-asparagine":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"l-aspartic_acid":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"l-cysteine":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"l-glutamic_acid":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"l-glutamine":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"glycine":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"l-histidine":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"l-isoleucine":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"l-leucine":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"l-lysine":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"l-methionine":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"l-phenylalanine":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"l-proline":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"l-serine":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"l-threonine":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"l-tyrosine":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"l-valine":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"vitamin_a_beta-carotene":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"vitamin_a_retinol":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"moisture":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"ash":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"added_sugars":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"ethyl_alcohol":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"propylene_glycol":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"lycopene":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"polyphenols":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"calories_fat":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"calories_fat_saturated_trans":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]}},"type":"object","title":"NutrimentsIn","description":"dict() needs to have the by_alias=True flag on at all time when handling \nthis model or its parents."},"NutrimentsOut":{"properties":{"calories":{"$ref":"#/components/schemas/NutrimentOut"},"fat":{"$ref":"#/components/schemas/NutrimentOut"},"fat_saturated":{"$ref":"#/components/schemas/NutrimentOut"},"fat_trans":{"$ref":"#/components/schemas/NutrimentOut"},"cholesterol":{"$ref":"#/components/schemas/NutrimentOut"},"sodium":{"$ref":"#/components/schemas/NutrimentOut"},"carbohydrate":{"$ref":"#/components/schemas/NutrimentOut"},"fibre":{"$ref":"#/components/schemas/NutrimentOut"},"sugars":{"$ref":"#/components/schemas/NutrimentOut"},"protein":{"$ref":"#/components/schemas/NutrimentOut"},"calcium":{"$ref":"#/components/schemas/NutrimentOut"},"iron":{"$ref":"#/components/schemas/NutrimentOut"},"potassium":{"$ref":"#/components/schemas/NutrimentOut"},"vitamin_a_RAE":{"$ref":"#/components/schemas/NutrimentOut"},"vitamin_c":{"$ref":"#/components/schemas/NutrimentOut"},"fat_polyunsaturated":{"$ref":"#/components/schemas/NutrimentOut"},"omega-6":{"$ref":"#/components/schemas/NutrimentOut"},"omega-3":{"$ref":"#/components/schemas/NutrimentOut"},"fat_monounsaturated":{"$ref":"#/components/schemas/NutrimentOut"},"soluble_fibre":{"$ref":"#/components/schemas/NutrimentOut"},"insoluble_fibre":{"$ref":"#/components/schemas/NutrimentOut"},"sugar_alcohols":{"$ref":"#/components/schemas/NutrimentOut"},"starch":{"$ref":"#/components/schemas/NutrimentOut"},"vitamin_d":{"$ref":"#/components/schemas/NutrimentOut"},"vitamin_e":{"$ref":"#/components/schemas/NutrimentOut"},"vitamin_k":{"$ref":"#/components/schemas/NutrimentOut"},"thiamin":{"$ref":"#/components/schemas/NutrimentOut"},"riboflavin":{"$ref":"#/components/schemas/NutrimentOut"},"niacin_NE":{"$ref":"#/components/schemas/NutrimentOut"},"vitamin_b6":{"$ref":"#/components/schemas/NutrimentOut"},"folate_DFE":{"$ref":"#/components/schemas/NutrimentOut"},"vitamin_b12":{"$ref":"#/components/schemas/NutrimentOut"},"biotin":{"$ref":"#/components/schemas/NutrimentOut"},"pantothenic_acid":{"$ref":"#/components/schemas/NutrimentOut"},"choline":{"$ref":"#/components/schemas/NutrimentOut"},"phosphorus":{"$ref":"#/components/schemas/NutrimentOut"},"iodide":{"$ref":"#/components/schemas/NutrimentOut"},"magnesium":{"$ref":"#/components/schemas/NutrimentOut"},"zinc":{"$ref":"#/components/schemas/NutrimentOut"},"selenium":{"$ref":"#/components/schemas/NutrimentOut"},"copper":{"$ref":"#/components/schemas/NutrimentOut"},"manganese":{"$ref":"#/components/schemas/NutrimentOut"},"chromium":{"$ref":"#/components/schemas/NutrimentOut"},"molybdenum":{"$ref":"#/components/schemas/NutrimentOut"},"chloride":{"$ref":"#/components/schemas/NutrimentOut"},"polydextrose":{"$ref":"#/components/schemas/NutrimentOut"},"erythritol":{"$ref":"#/components/schemas/NutrimentOut"},"caffeine":{"$ref":"#/components/schemas/NutrimentOut"},"green_tea_extract":{"$ref":"#/components/schemas/NutrimentOut"},"phosphatidylserine":{"$ref":"#/components/schemas/NutrimentOut"},"taurine":{"$ref":"#/components/schemas/NutrimentOut"},"l-alanine":{"$ref":"#/components/schemas/NutrimentOut"},"l-arginine":{"$ref":"#/components/schemas/NutrimentOut"},"l-asparagine":{"$ref":"#/components/schemas/NutrimentOut"},"l-aspartic_acid":{"$ref":"#/components/schemas/NutrimentOut"},"l-cysteine":{"$ref":"#/components/schemas/NutrimentOut"},"l-glutamic_acid":{"$ref":"#/components/schemas/NutrimentOut"},"l-glutamine":{"$ref":"#/components/schemas/NutrimentOut"},"glycine":{"$ref":"#/components/schemas/NutrimentOut"},"l-histidine":{"$ref":"#/components/schemas/NutrimentOut"},"l-isoleucine":{"$ref":"#/components/schemas/NutrimentOut"},"l-leucine":{"$ref":"#/components/schemas/NutrimentOut"},"l-lysine":{"$ref":"#/components/schemas/NutrimentOut"},"l-methionine":{"$ref":"#/components/schemas/NutrimentOut"},"l-phenylalanine":{"$ref":"#/components/schemas/NutrimentOut"},"l-proline":{"$ref":"#/components/schemas/NutrimentOut"},"l-serine":{"$ref":"#/components/schemas/NutrimentOut"},"l-threonine":{"$ref":"#/components/schemas/NutrimentOut"},"l-tyrosine":{"$ref":"#/components/schemas/NutrimentOut"},"l-valine":{"$ref":"#/components/schemas/NutrimentOut"},"vitamin_a_beta-carotene":{"$ref":"#/components/schemas/NutrimentOut"},"vitamin_a_retinol":{"$ref":"#/components/schemas/NutrimentOut"},"moisture":{"$ref":"#/components/schemas/NutrimentOut"},"ash":{"$ref":"#/components/schemas/NutrimentOut"},"added_sugars":{"$ref":"#/components/schemas/NutrimentOut"},"ethyl_alcohol":{"$ref":"#/components/schemas/NutrimentOut"},"propylene_glycol":{"$ref":"#/components/schemas/NutrimentOut"},"lycopene":{"$ref":"#/components/schemas/NutrimentOut"},"polyphenols":{"$ref":"#/components/schemas/NutrimentOut"},"calories_fat":{"$ref":"#/components/schemas/NutrimentOut"},"calories_fat_saturated_trans":{"$ref":"#/components/schemas/NutrimentOut"},"fat_saturated_trans_total":{"$ref":"#/components/schemas/NutrimentOut"},"calories_kJ":{"$ref":"#/components/schemas/NutrimentOut"},"vitamin_a_RAE_total":{"$ref":"#/components/schemas/NutrimentOut"}},"type":"object","required":["calories","fat","fat_saturated","fat_trans","cholesterol","sodium","carbohydrate","fibre","sugars","protein","calcium","iron","potassium","vitamin_a_RAE","vitamin_c","fat_polyunsaturated","omega-6","omega-3","fat_monounsaturated","soluble_fibre","insoluble_fibre","sugar_alcohols","starch","vitamin_d","vitamin_e","vitamin_k","thiamin","riboflavin","niacin_NE","vitamin_b6","folate_DFE","vitamin_b12","biotin","pantothenic_acid","choline","phosphorus","iodide","magnesium","zinc","selenium","copper","manganese","chromium","molybdenum","chloride","polydextrose","erythritol","caffeine","green_tea_extract","phosphatidylserine","taurine","l-alanine","l-arginine","l-asparagine","l-aspartic_acid","l-cysteine","l-glutamic_acid","l-glutamine","glycine","l-histidine","l-isoleucine","l-leucine","l-lysine","l-methionine","l-phenylalanine","l-proline","l-serine","l-threonine","l-tyrosine","l-valine","vitamin_a_beta-carotene","vitamin_a_retinol","moisture","ash","added_sugars","ethyl_alcohol","propylene_glycol","lycopene","polyphenols","calories_fat","calories_fat_saturated_trans","fat_saturated_trans_total","calories_kJ","vitamin_a_RAE_total"],"title":"NutrimentsOut","description":"Complete nutritional profile with ~85 nutrient values. Each field is a NutrimentOut containing amount, unit, and localized names. Units vary by nutrient type: calories (kcal), macros (g), vitamins (mg or mcg), minerals (mg)."},"NutrimentsOverwriteOut":{"properties":{"calories":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"fat":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"fat_saturated":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"fat_trans":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"cholesterol":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"sodium":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"carbohydrate":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"fibre":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"sugars":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"protein":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"calcium":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"iron":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"potassium":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"vitamin_a_RAE":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"vitamin_c":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"fat_polyunsaturated":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"omega-6":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"omega-3":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"fat_monounsaturated":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"soluble_fibre":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"insoluble_fibre":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"sugar_alcohols":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"starch":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"vitamin_d":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"vitamin_e":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"vitamin_k":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"thiamin":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"riboflavin":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"niacin_NE":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"vitamin_b6":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"folate_DFE":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"vitamin_b12":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"biotin":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"pantothenic_acid":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"choline":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"phosphorus":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"iodide":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"magnesium":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"zinc":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"selenium":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"copper":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"manganese":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"chromium":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"molybdenum":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"chloride":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"polydextrose":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"erythritol":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"caffeine":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"green_tea_extract":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"phosphatidylserine":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"taurine":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"l-alanine":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"l-arginine":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"l-asparagine":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"l-aspartic_acid":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"l-cysteine":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"l-glutamic_acid":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"l-glutamine":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"glycine":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"l-histidine":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"l-isoleucine":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"l-leucine":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"l-lysine":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"l-methionine":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"l-phenylalanine":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"l-proline":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"l-serine":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"l-threonine":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"l-tyrosine":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"l-valine":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"vitamin_a_beta-carotene":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"vitamin_a_retinol":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"moisture":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"ash":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"added_sugars":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"ethyl_alcohol":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"propylene_glycol":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"lycopene":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"polyphenols":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"calories_fat":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]},"calories_fat_saturated_trans":{"anyOf":[{"$ref":"#/components/schemas/NutrimentIn"},{"type":"null"}]}},"type":"object","title":"NutrimentsOverwriteOut","description":"Manual nutriment override values. Same structure as NutrimentsIn."},"NutrimentsValidationOut":{"properties":{"nutriments_weight":{"$ref":"#/components/schemas/MeasureOut","description":"Sum of macronutrients: protein + carbs + fat + moisture + ash + alcohol"},"portion_size_g":{"$ref":"#/components/schemas/MeasureOut","description":"Declared portion/serving size in grams"},"calculated_carbohydrate":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Calculated Carbohydrate","description":"Carbohydrate calculated as: 100 - protein - fat - moisture - ash - alcohol"},"declared_carbohydrate":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Declared Carbohydrate","description":"User-declared carbohydrate value"},"carbohydrate_difference":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Carbohydrate Difference","description":"Difference between calculated and declared (acceptable: <5%)"},"carbohydrate_details":{"items":{"$ref":"#/components/schemas/ValidationDetailOut"},"type":"array","title":"Carbohydrate Details","description":"Detailed validation messages"},"calories_declared":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Calories Declared","description":"User-declared calorie value"},"calories_calculated":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Calories Calculated","description":"Calculated using Atwater: protein*4 + carbs*4 + fat*9 + alcohol*7"},"calories_difference":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Calories Difference","description":"Difference between calculated and declared"},"calories_details":{"items":{"$ref":"#/components/schemas/ValidationDetailOut"},"type":"array","title":"Calories Details","description":"Detailed validation messages"},"calories_equation":{"anyOf":[{"$ref":"#/components/schemas/EquationOut"},{"type":"null"}],"description":"The Atwater equation used"},"macronutrients_sum":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Macronutrients Sum","description":"Sum of all macronutrients"},"declared_portion_size":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Declared Portion Size","description":"Declared portion size for comparison"},"macronutrients_difference":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Macronutrients Difference","description":"Difference between sum and portion size"},"macronutrients_details":{"items":{"$ref":"#/components/schemas/ValidationDetailOut"},"type":"array","title":"Macronutrients Details","description":"Detailed validation messages"},"macronutrients_equation":{"anyOf":[{"$ref":"#/components/schemas/EquationOut"},{"type":"null"}],"description":"The sum equation used"},"missing_nutrients":{"items":{"$ref":"#/components/schemas/MissingNutrientOut"},"type":"array","title":"Missing Nutrients","description":"Nutrients needed for validation but not provided"}},"type":"object","required":["nutriments_weight","portion_size_g"],"title":"NutrimentsValidationOut","description":"Validation results for nutritional data consistency.\n\nChecks that declared values match calculated values using standard formulas. Validates: carbohydrate calculation (by difference), calorie calculation (Atwater factors), and macronutrient sum vs portion size."},"PageInfo":{"properties":{"page_size":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Page Size","description":"Number of items per page"},"next_page":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Next Page","description":"Next page number (null if on last page)"},"previous_page":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Previous Page","description":"Previous page number (null if on first page)"},"total":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Total","description":"Total number of items across all pages"},"page":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Page","description":"Current page number (1-indexed)"},"start":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Start","description":"Index of first item on this page"},"end":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"End","description":"Index of last item on this page"},"pages":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Pages","description":"Total number of pages"},"has_next":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Has Next","description":"Whether there are more pages after this one"},"has_previous":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Has Previous","description":"Whether there are pages before this one"}},"type":"object","title":"PageInfo","description":"Pagination metadata for list endpoints."},"PreviewsOut":{"properties":{"allergies_list_en":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Allergies List En","description":"Formatted English allergen statement"},"allergies_list_fr":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Allergies List Fr","description":"Formatted French allergen statement"},"may_contains_list_en":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"May Contains List En","description":"Formatted English 'may contain' statement"},"may_contains_list_fr":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"May Contains List Fr","description":"Formatted French 'may contain' statement"},"ingredient_list_en":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Ingredient List En","description":"Formatted English ingredient list for labels"},"ingredient_list_fr":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Ingredient List Fr","description":"Formatted French ingredient list for labels"}},"type":"object","title":"PreviewsOut","description":"Modern preview format for CAN2016 and US labels. Contains formatted text for label display."},"PreviewsOutLegacy":{"properties":{"allergies_list_en":{"type":"string","title":"Allergies List En","description":"Formatted English allergen statement"},"allergies_list_fr":{"type":"string","title":"Allergies List Fr","description":"Formatted French allergen statement"},"may_contains_list_en":{"type":"string","title":"May Contains List En","description":"Formatted English 'may contain' statement"},"may_contains_list_fr":{"type":"string","title":"May Contains List Fr","description":"Formatted French 'may contain' statement"},"ingredient_list_en":{"additionalProperties":{"type":"string"},"type":"object","title":"Ingredient List En","description":"English ingredient lists by regulation. Keys: 'CAN', 'CAN2016'"},"ingredient_list_fr":{"additionalProperties":{"type":"string"},"type":"object","title":"Ingredient List Fr","description":"French ingredient lists by regulation. Keys: 'CAN', 'CAN2016'"}},"type":"object","required":["allergies_list_en","allergies_list_fr","may_contains_list_en","may_contains_list_fr","ingredient_list_en","ingredient_list_fr"],"title":"PreviewsOutLegacy","description":"Legacy preview format with nested Dict structure. Use previews_CAN2016 or previews_US instead."},"RecipeCustomUnitOut":{"properties":{"id":{"type":"string","title":"Id","description":"Unique identifier for the custom unit"},"name_en":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Name En","description":"English display name (e.g., 'cup', 'slice')"},"name_fr":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Name Fr","description":"French display name"},"rate":{"type":"string","format":"decimal","title":"Rate","description":"Conversion factor to base unit","example":"99.5"},"unit_to":{"type":"string","title":"Unit To","description":"Base unit to convert to (e.g., 'g', 'mL'). Valid values from GET /v1/utils/available_units"},"recipe_version_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Recipe Version Id","description":"Current recipe version for optimistic locking"}},"type":"object","required":["id","rate","unit_to"],"title":"RecipeCustomUnitOut","description":"Custom unit of measure defined for a recipe."},"RecipeListOut":{"properties":{"items":{"items":{"$ref":"#/components/schemas/RecipeOut"},"type":"array","title":"Items"},"page_info":{"$ref":"#/components/schemas/PageInfo"}},"type":"object","required":["items","page_info"],"title":"RecipeListOut"},"RecipeOut":{"properties":{"id":{"type":"string","title":"Id","description":"Unique identifier for this recipe"},"tenant_id":{"type":"string","title":"Tenant Id","description":"Organization ID that owns this recipe"},"name":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Name","description":"Recipe name"},"ingredients":{"items":{"$ref":"#/components/schemas/IngredientOut"},"type":"array","title":"Ingredients","description":"List of ingredients in this recipe with quantities"},"yield_qty":{"anyOf":[{"type":"string","format":"decimal","example":"99.5"},{"type":"null"}],"title":"Yield Qty","description":"Output quantity (e.g., '500' for 500g yield). Default: '100'"},"yield_unit":{"$ref":"#/components/schemas/UnitOut","description":"Unit for yield_qty. Default: '%' (percentage of total weight). Valid values from GET /v1/utils/yield_units"},"density_overwrite":{"anyOf":[{"type":"string","format":"decimal","example":"99.5"},{"type":"null"}],"title":"Density Overwrite","description":"Manual density override in g/mL for volume calculations"},"density":{"anyOf":[{"type":"string","format":"decimal","example":"99.5"},{"type":"null"}],"title":"Density","description":"Computed or overwritten density in g/mL"},"extra_allergies":{"items":{"$ref":"#/components/schemas/AllergyOut"},"type":"array","title":"Extra Allergies","description":"Additional allergens manually added to recipe (not from ingredients). Standard allergens from GET /v1/utils/allergies"},"extra_may_contains":{"items":{"$ref":"#/components/schemas/MayContainOut"},"type":"array","title":"Extra May Contains","description":"Additional 'may contain' allergens manually added. Standard allergens from GET /v1/utils/allergies"},"ingredient_list_overwrite_en":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Ingredient List Overwrite En","description":"Manual override for English ingredient list text"},"ingredient_list_overwrite_fr":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Ingredient List Overwrite Fr","description":"Manual override for French ingredient list text"},"instructions_en":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Instructions En","description":"English preparation instructions (not displayed on labels)"},"instructions_fr":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Instructions Fr","description":"French preparation instructions"},"notes_en":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Notes En","description":"Internal English notes"},"notes_fr":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Notes Fr","description":"Internal French notes"},"image_path":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Image Path","description":"Path to recipe image file"},"nutriments_overwrite_qty":{"anyOf":[{"type":"string","format":"decimal","example":"99.5"},{"type":"null"}],"title":"Nutriments Overwrite Qty","description":"Quantity basis for manual nutriment override"},"nutriments_overwrite_unit":{"anyOf":[{"$ref":"#/components/schemas/UnitOut"},{"type":"null"}],"description":"Unit for nutriments_overwrite_qty"},"nutriments_overwrite":{"anyOf":[{"$ref":"#/components/schemas/NutrimentsOverwriteOut"},{"type":"null"}],"description":"Manual nutriment values that override calculated values. Only present when expand=nutriments_overwrite is requested"},"product_code":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Product Code","description":"User-defined identifier (UPC/SKU)"},"common_name_en":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Common Name En","description":"English common name (regulatory term)"},"common_name_fr":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Common Name Fr","description":"French common name (regulatory term)"},"synchronized_sort_allergies":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Synchronized Sort Allergies","description":"When true, allergens use the same sort order in both English and French statements. When false (default), each language sorts allergens alphabetically in that language"},"custom_units":{"items":{"$ref":"#/components/schemas/RecipeCustomUnitOut"},"type":"array","title":"Custom Units","description":"User-defined units of measure (e.g., 'cup', 'slice') with conversion rates"},"available_units":{"anyOf":[{"items":{"$ref":"#/components/schemas/UnitOut"},"type":"array"},{"type":"null"}],"title":"Available Units","description":"All available units for this recipe"},"ingredient_allergies":{"items":{"$ref":"#/components/schemas/AllergyOut"},"type":"array","title":"Ingredient Allergies","description":"Allergens aggregated from all ingredients. Values from GET /v1/utils/allergies"},"ingredient_may_contains":{"items":{"$ref":"#/components/schemas/MayContainOut"},"type":"array","title":"Ingredient May Contains","description":"'May contain' allergens aggregated from ingredients. Values from GET /v1/utils/allergies"},"allergies":{"items":{"$ref":"#/components/schemas/AllergyOut"},"type":"array","title":"Allergies","description":"Combined allergen list (ingredient_allergies + extra_allergies). Values from GET /v1/utils/allergies"},"may_contains":{"items":{"$ref":"#/components/schemas/MayContainOut"},"type":"array","title":"May Contains","description":"Combined 'may contain' list, excluding items already in allergies. Values from GET /v1/utils/allergies"},"nutriments":{"anyOf":[{"$ref":"#/components/schemas/NutrimentsOut"},{"type":"null"}],"description":"Calculated nutritional values for the entire recipe. Only present when expand=nutriments is requested"},"nutriments_validation":{"anyOf":[{"$ref":"#/components/schemas/NutrimentsValidationOut"},{"type":"null"}],"description":"Validation results for calculated nutriments"},"nutriments_100g":{"anyOf":[{"$ref":"#/components/schemas/NutrimentsOut"},{"type":"null"}],"description":"Nutriments normalized to 100g. Only present when expand=nutriments_100g is requested"},"nutriments_100g_validation":{"anyOf":[{"$ref":"#/components/schemas/NutrimentsValidationOut"},{"type":"null"}],"description":"Validation for normalized nutriments"},"weight":{"anyOf":[{"$ref":"#/components/schemas/MeasureOut"},{"type":"null"}],"description":"Total weight of all ingredients before refuse"},"weight_display":{"anyOf":[{"$ref":"#/components/schemas/MeasureOut"},{"type":"null"}],"description":"Formatted weight for display"},"edible_weight":{"anyOf":[{"$ref":"#/components/schemas/MeasureOut"},{"type":"null"}],"description":"Weight after refuse is applied"},"edible_weight_display":{"anyOf":[{"$ref":"#/components/schemas/MeasureOut"},{"type":"null"}],"description":"Formatted edible weight for display"},"yield_weight":{"anyOf":[{"$ref":"#/components/schemas/MeasureOut"},{"type":"null"}],"description":"Final output weight based on yield settings"},"yield_weight_display":{"anyOf":[{"$ref":"#/components/schemas/MeasureOut"},{"type":"null"}],"description":"Formatted yield weight for display"},"yield_pct":{"anyOf":[{"$ref":"#/components/schemas/MeasureOut"},{"type":"null"}],"description":"Yield as percentage of total ingredient weight"},"previews":{"anyOf":[{"$ref":"#/components/schemas/PreviewsOutLegacy"},{"type":"null"}],"description":"Legacy preview format returning both regulations in nested dict. Deprecated: use previews_CAN2016 or previews_US instead. Only present when expand=previews"},"previews_CAN2016":{"anyOf":[{"$ref":"#/components/schemas/PreviewsOut"},{"type":"null"}],"description":"Ingredient list and allergen statements formatted per Canadian 2016 regulations. Recipes are regulation-agnostic (concrete_type is set on labels), so previews show formatting for each regulation. Only present when expand=previews_CAN2016"},"previews_US":{"anyOf":[{"$ref":"#/components/schemas/PreviewsOut"},{"type":"null"}],"description":"Ingredient list and allergen statements formatted per US FDA regulations. Recipes are regulation-agnostic (concrete_type is set on labels), so previews show formatting for each regulation. Only present when expand=previews_US"},"created_date":{"type":"string","format":"date-time","title":"Created Date","description":"When this recipe was created"},"updated_date":{"type":"string","format":"date-time","title":"Updated Date","description":"When this recipe was last modified"},"version_id":{"type":"integer","title":"Version Id","description":"Internal version tracking"},"subversion_id":{"type":"integer","title":"Subversion Id","description":"Internal version tracking"},"tags":{"anyOf":[{"items":{"$ref":"#/components/schemas/RecipeTagOut"},"type":"array"},{"type":"null"}],"title":"Tags","description":"Tag associations. Only present when expand=tags is requested"},"warnings":{"anyOf":[{"items":{"$ref":"#/components/schemas/WarningOut"},"type":"array"},{"type":"null"}],"title":"Warnings","description":"Validation warnings"}},"type":"object","required":["id","tenant_id","ingredients","yield_unit","extra_allergies","extra_may_contains","custom_units","ingredient_allergies","ingredient_may_contains","allergies","may_contains","created_date","updated_date","version_id","subversion_id"],"title":"RecipeOut","description":"Complete recipe response object."},"RecipeTagListOut":{"properties":{"items":{"items":{"$ref":"#/components/schemas/RecipeTagOut"},"type":"array","title":"Items","description":"List of recipe tag records"},"page_info":{"anyOf":[{"$ref":"#/components/schemas/PageInfo"},{"type":"null"}],"description":"Pagination metadata"}},"type":"object","required":["items"],"title":"RecipeTagListOut","description":"Paginated list of recipe tags."},"RecipeTagOut":{"properties":{"id":{"type":"string","title":"Id","description":"Unique tag identifier"},"tenant_id":{"type":"string","title":"Tenant Id","description":"Tenant that owns this tag"},"name":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Name","description":"Display name for the tag"},"color":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Color","description":"Hex color code for visual display (e.g., '#FF5733')"},"created_date":{"type":"string","format":"date-time","title":"Created Date","description":"When the tag was created"},"updated_date":{"type":"string","format":"date-time","title":"Updated Date","description":"When the tag was last modified"}},"type":"object","required":["id","tenant_id","created_date","updated_date"],"title":"RecipeTagOut","description":"Tag specifically for organizing recipes."},"RemoveLabelAdditionalRecipe":{"properties":{"label_version_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Label Version Id","description":"Optional version ID for optimistic locking"}},"type":"object","title":"RemoveLabelAdditionalRecipe","description":"Request body for delete (can be empty)."},"RemoveTechnicalFileIn":{"properties":{"food_version_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Food Version Id","description":"Optional version ID for optimistic locking"}},"type":"object","title":"RemoveTechnicalFileIn","description":"Request body for delete operations (can be empty)."},"SaveFoodTagAssociationsIn":{"properties":{"tags":{"items":{"type":"string"},"type":"array","title":"Tags","description":"List of tag IDs to associate"}},"type":"object","required":["tags"],"title":"SaveFoodTagAssociationsIn","description":"Request to replace all tag associations for a food."},"SaveRecipeTagAssociationsIn":{"properties":{"tags":{"items":{"type":"string"},"type":"array","title":"Tags","description":"List of tag IDs to associate"}},"type":"object","required":["tags"],"title":"SaveRecipeTagAssociationsIn","description":"Request to replace all tag associations for a recipe."},"ShortFoodListOut":{"properties":{"items":{"items":{"$ref":"#/components/schemas/ShortFoodOut"},"type":"array","title":"Items"},"page_info":{"$ref":"#/components/schemas/PageInfo"}},"type":"object","required":["items","page_info"],"title":"ShortFoodListOut"},"ShortFoodOut":{"properties":{"id":{"type":"string","title":"Id","description":"Unique identifier for this ingredient"},"tenant_id":{"type":"string","title":"Tenant Id","description":"Organization ID that owns this ingredient"},"name":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Name","description":"Computed display name"},"name_en":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Name En","description":"English name"},"name_fr":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Name Fr","description":"French name"},"public":{"type":"boolean","title":"Public","description":"Whether this ingredient is publicly visible"},"brand":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Brand","description":"Brand name (common with USDA data)"},"CNF":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Cnf","description":"Canadian Nutrient File database ID"},"USDA":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Usda","description":"USDA database ID"},"dataset_version":{"anyOf":[{"type":"string","maxLength":50},{"type":"null"}],"title":"Dataset Version","description":"Source dataset generation for public database ingredients (e.g., `CNF2026`). Null for user-created ingredients"},"legacy_dataset":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Legacy Dataset","description":"True when this ingredient comes from a legacy dataset generation. Hidden from search unless `include_legacy_datasets=true`, but remains fully usable. Null for user-created ingredients"},"product_code":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Product Code","description":"User-defined identifier (UPC/SKU)"},"created_date":{"type":"string","format":"date-time","title":"Created Date","description":"When this ingredient was created"},"updated_date":{"type":"string","format":"date-time","title":"Updated Date","description":"When this ingredient was last modified"},"version_id":{"type":"integer","title":"Version Id","description":"Major version number"},"subversion_id":{"type":"integer","title":"Subversion Id","description":"Minor version number"},"tags":{"anyOf":[{"items":{"$ref":"#/components/schemas/FoodTagOut"},"type":"array"},{"type":"null"}],"title":"Tags","description":"Tag associations. Only present when expand=tags is requested"}},"type":"object","required":["id","tenant_id","public","created_date","updated_date","version_id","subversion_id"],"title":"ShortFoodOut","description":"Condensed ingredient response for list endpoints (short=true).\nContains 14 core fields for efficient listing."},"ShortLabelListOut":{"properties":{"items":{"items":{"$ref":"#/components/schemas/ShortLabelOut"},"type":"array","title":"Items"},"page_info":{"$ref":"#/components/schemas/PageInfo"}},"type":"object","required":["items","page_info"],"title":"ShortLabelListOut","description":"Paginated list of condensed label objects."},"ShortLabelOut":{"properties":{"id":{"type":"string","title":"Id","description":"Unique identifier for this label"},"tenant_id":{"type":"string","title":"Tenant Id","description":"Organization ID that owns this label"},"recipe_id":{"type":"string","title":"Recipe Id","description":"ID of the recipe this label is based on"},"name":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Name","description":"Display name for this label"},"serving_qty":{"type":"string","format":"decimal","title":"Serving Qty","description":"Serving size quantity","example":"99.5"},"serving_unit":{"$ref":"#/components/schemas/UnitOut","description":"Unit for serving_qty. Valid values from GET /v1/utils/available_units"},"reference_qty":{"anyOf":[{"type":"string","format":"decimal","example":"99.5"},{"type":"null"}],"title":"Reference Qty","description":"Reference amount for dual-column labels"},"reference_unit":{"$ref":"#/components/schemas/UnitOut","description":"Unit for reference_qty. Valid values from GET /v1/utils/available_units"},"household_serving_en":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Household Serving En","description":"English household serving"},"household_serving_fr":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Household Serving Fr","description":"French household serving"},"household_serving_prefix_en":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Household Serving Prefix En","description":"English prefix"},"household_serving_prefix_fr":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Household Serving Prefix Fr","description":"French prefix"},"label_format":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Label Format","description":"Label format code. Valid values from GET /v1/utils/label_rules/{concrete_type}"},"label_format_version":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Label Format Version","description":"Format version. Valid values from GET /v1/utils/label_rules/{concrete_type}"},"label_language":{"anyOf":[{"type":"string","maxLength":2},{"type":"null"}],"title":"Label Language","description":"Language code: 'en' or 'fr'. For bilingual labels, determines language order"},"concrete_type":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Concrete Type","description":"Regulation type. See GET /v1/utils/concrete_types"},"specification_type":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Specification Type","description":"Reserved for future use"},"created_date":{"type":"string","format":"date-time","title":"Created Date","description":"When created"},"updated_date":{"type":"string","format":"date-time","title":"Updated Date","description":"When last modified"},"version_id":{"type":"integer","title":"Version Id","description":"Internal version tracking"},"subversion_id":{"type":"integer","title":"Subversion Id","description":"Internal version tracking"}},"type":"object","required":["id","tenant_id","recipe_id","serving_qty","serving_unit","reference_unit","created_date","updated_date","version_id","subversion_id"],"title":"ShortLabelOut","description":"Condensed label response for list endpoints (short=true)."},"ShortRecipeListOut":{"properties":{"items":{"items":{"$ref":"#/components/schemas/ShortRecipeOut"},"type":"array","title":"Items"},"page_info":{"$ref":"#/components/schemas/PageInfo"}},"type":"object","required":["items","page_info"],"title":"ShortRecipeListOut"},"ShortRecipeOut":{"properties":{"id":{"type":"string","title":"Id","description":"Unique identifier for this recipe"},"tenant_id":{"type":"string","title":"Tenant Id","description":"Organization ID that owns this recipe"},"name":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Name","description":"Recipe name"},"product_code":{"anyOf":[{"type":"string","maxLength":255},{"type":"null"}],"title":"Product Code","description":"User-defined identifier (UPC/SKU)"},"created_date":{"type":"string","format":"date-time","title":"Created Date","description":"When this recipe was created"},"updated_date":{"type":"string","format":"date-time","title":"Updated Date","description":"When this recipe was last modified"},"version_id":{"type":"integer","title":"Version Id","description":"Internal version tracking"},"subversion_id":{"type":"integer","title":"Subversion Id","description":"Internal version tracking"},"tags":{"anyOf":[{"items":{"$ref":"#/components/schemas/RecipeTagOut"},"type":"array"},{"type":"null"}],"title":"Tags","description":"Tag associations. Only present when expand=tags is requested"}},"type":"object","required":["id","tenant_id","created_date","updated_date","version_id","subversion_id"],"title":"ShortRecipeOut","description":"Condensed recipe response for list endpoints (short=true). Contains 8 core fields."},"SupplementedCautionaryStatementIn":{"properties":{"name_en":{"type":"string","maxLength":255,"title":"Name En"},"name_fr":{"type":"string","maxLength":255,"title":"Name Fr"}},"type":"object","required":["name_en","name_fr"],"title":"SupplementedCautionaryStatementIn"},"TechnicalFile":{"properties":{"id":{"type":"string","title":"Id","description":"Unique identifier for the technical file"},"filename":{"type":"string","title":"Filename","description":"Original filename of the uploaded document"},"created_date":{"type":"string","format":"date-time","title":"Created Date","description":"When the file was uploaded"},"updated_date":{"type":"string","format":"date-time","title":"Updated Date","description":"When the file was last modified"}},"type":"object","required":["id","filename","created_date","updated_date"],"title":"TechnicalFile","description":"Specification sheet or reference document attached to an ingredient."},"TechnicalFileOut":{"properties":{"id":{"type":"string","title":"Id","description":"Unique identifier for the technical file"},"filename":{"type":"string","title":"Filename","description":"Original filename of the uploaded document"},"created_date":{"type":"string","format":"date-time","title":"Created Date","description":"When the file was uploaded"},"updated_date":{"type":"string","format":"date-time","title":"Updated Date","description":"When the file was last modified"}},"type":"object","required":["id","filename","created_date","updated_date"],"title":"TechnicalFileOut","description":"Technical file metadata returned after upload."},"UnitOut":{"properties":{"key":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Key","description":"Unit key identifier (e.g., 'g', 'mg', 'mcg', 'kcal')"},"name_en":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name En","description":"English display name"},"name_fr":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name Fr","description":"French display name"}},"type":"object","title":"UnitOut","description":"Unit of measure reference."},"ValidationDetailOut":{"properties":{"type":{"type":"string","title":"Type","description":"Detail type: 'info', 'warning', or 'error'"},"message_en":{"type":"string","title":"Message En","description":"English explanation"},"message_fr":{"type":"string","title":"Message Fr","description":"French explanation"}},"type":"object","required":["type","message_en","message_fr"],"title":"ValidationDetailOut","description":"Detail item from nutriment validation."},"ValidationError":{"properties":{"loc":{"items":{"type":"string"},"type":"array","title":"Location"},"message_en":{"type":"string","title":"Message EN"},"message_fr":{"type":"string","title":"Message FR"},"type":{"type":"string","title":"Error Type"}},"type":"object","required":["loc","message_en","message_fr","type"],"title":"ValidationError"},"WarningOut":{"properties":{"code":{"type":"string","title":"Code","description":"Error/warning code (e.g., 'W001', 'E001')"},"message_en":{"type":"string","title":"Message En","description":"English message text"},"message_fr":{"type":"string","title":"Message Fr","description":"French message text"},"severity":{"type":"string","title":"Severity","description":"Severity level: 'INFO', 'WARNING', or 'CRITICAL'"},"type":{"type":"string","title":"Type","description":"Error type identifier"},"metadata":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Metadata","description":"Additional context (field names, values, etc.)"}},"type":"object","required":["code","message_en","message_fr","severity","type"],"title":"WarningOut","description":"Warning or error message from validation."}},"securitySchemes":{"APIKeyHeader":{"type":"apiKey","in":"header","name":"Authorization"}}},"tags":[{"name":"foods","description":"Ingredients (called `foods` in the API). An ingredient is a nutritional entity with its own nutriment data, allergens, and metadata. Ingredients are either tenant-created (custom) or from public databases (CNF, USDA). Use the `source` query parameter to filter by origin. Related: recipes, tags."},{"name":"recipes","description":"Recipes are collections of ingredients with quantities, used to calculate aggregate nutritional values. A recipe can contain other recipes as ingredients (nested recipes). Recipes support yield configuration for serving size calculations, and can have their calculated nutriments overwritten manually. Related: foods, labels, tags."},{"name":"labels","description":"Nutrition Facts Tables (NFT). Labels are generated from recipes according to regulatory requirements (CAN2016 for Canadian 2016 regulations, US for United States). Labels can include additional recipes for multi-component products. Related: recipes, fop_labels."},{"name":"fop_labels","description":"Front of Package (FOP) nutrition symbols. These are simplified nutrition indicators displayed on product packaging, generated according to regulatory requirements. Related: labels, recipes."},{"name":"me","description":"Current user and organization settings. These endpoints manage the authenticated user's profile, organization details, and account preferences. Note: Most /me endpoints require session authentication and do not accept API key authentication."},{"name":"tags","description":"Tags for organizing ingredients and recipes with custom metadata. Use tags to track workflow status (e.g., 'incomplete', 'to review'), categorize items (e.g., 'imported', 'seasonal'), or any custom grouping. Separate tag systems exist for foods (food_tags) and recipes (recipe_tags). Tags are color-coded and can be used to filter list endpoints."},{"name":"session","description":"Authentication and session management. Includes login, logout, registration, password reset, and session token operations."},{"name":"users","description":"User management within a tenant organization. Manage team members, roles, and permissions."},{"name":"utils","description":"Utility endpoints providing form data, validation rules, and reference data for the API. Includes allergen lists, unit definitions, and regulatory rule sets."}]}