openapi: 3.2.0 info: title: SparkyFitness Nutrition & Meals API version: 1.0.0 description: API documentation for the SparkyFitness application, providing a comprehensive guide to all available endpoints. Have caution using the API directly, as improper use may lead to data loss or corruption. Also note that the API is subject to change without notice due to heavy development, so always refer to the latest documentation for up-to-date information. It might have flaw and due to vite/nginx internal proxy actual end point accessed via front end URL might be different than hitting them directly on the server. contact: name: SparkyFitness Support servers: - url: https://{host}/api description: Self-hosted SparkyFitness instance (the operator supplies the host). The upstream spec declares the relative base "/api". variables: host: default: sparkyfitness.example.com description: Hostname of your own SparkyFitness deployment. SparkyFitness is self-hosted; there is no vendor-operated API host. security: - apiKeyAuth: [] tags: - name: Nutrition & Meals description: Food database, diary logging, meal planning, and nutritional preferences. paths: /custom-nutrients: post: summary: Create a new custom nutrient tags: - Nutrition & Meals description: Creates a new custom nutrient for the authenticated user. security: - apiKeyAuth: [] requestBody: required: true content: application/json: schema: type: object required: - name - unit properties: name: type: string description: The name of the custom nutrient. unit: type: string description: The unit of measurement for the custom nutrient. aliases: type: array items: type: string description: Alternate nutrient names online food providers may use for this nutrient. responses: '201': description: The new custom nutrient was created successfully. content: application/json: schema: $ref: '#/components/schemas/CustomNutrient' '401': description: Unauthorized, authentication token is missing or invalid. '500': description: Failed to create custom nutrient. get: summary: Retrieve all custom nutrients tags: - Nutrition & Meals description: Retrieves all custom nutrients available to the authenticated user. security: - apiKeyAuth: [] responses: '200': description: A list of custom nutrients. content: application/json: schema: type: array items: $ref: '#/components/schemas/CustomNutrient' '401': description: Unauthorized, authentication token is missing or invalid. '500': description: Failed to fetch custom nutrients. /custom-nutrients/from-catalog: post: summary: Find-or-create custom nutrients from the canonical micronutrient catalog tags: - Nutrition & Meals description: 'Ensures the authenticated user has a custom nutrient for each supplied canonical catalog id, seeded with the catalog''s name, unit, aliases and Daily Value. Idempotent: ids the user already has (matched by name or alias) are skipped, as are catalog entries that are already first-class nutrient columns. ' security: - apiKeyAuth: [] requestBody: required: true content: application/json: schema: type: object required: - catalogIds properties: catalogIds: type: array items: type: string description: Canonical micronutrient catalog ids (e.g. "vitamin_d", "magnesium"). responses: '200': description: The user's custom nutrients after seeding. content: application/json: schema: type: object properties: resolved: type: array description: Each requested catalog id mapped to the nutrient key to store against. items: type: object properties: catalogId: type: string name: type: string description: The custom nutrient's actual name (may pre-date the catalog). fixedField: type: string description: Set when the nutrient is a built-in column rather than a custom nutrient. created: type: array items: $ref: '#/components/schemas/CustomNutrient' nutrients: type: array items: $ref: '#/components/schemas/CustomNutrient' '400': description: catalogIds must be an array of strings. '401': description: Unauthorized, authentication token is missing or invalid. '500': description: Failed to seed custom nutrients. /custom-nutrients/{id}: get: summary: Retrieve a single custom nutrient by ID tags: - Nutrition & Meals description: Retrieves a single custom nutrient by its ID. security: - apiKeyAuth: [] parameters: - in: path name: id required: true schema: type: string format: uuid description: The ID of the custom nutrient to retrieve. responses: '200': description: The requested custom nutrient. content: application/json: schema: $ref: '#/components/schemas/CustomNutrient' '401': description: Unauthorized, authentication token is missing or invalid. '404': description: Custom nutrient not found. '500': description: Failed to fetch custom nutrient. put: summary: Update a custom nutrient tags: - Nutrition & Meals description: Updates an existing custom nutrient. security: - apiKeyAuth: [] parameters: - in: path name: id required: true schema: type: string format: uuid description: The ID of the custom nutrient to update. requestBody: required: true content: application/json: schema: type: object properties: name: type: string description: The new name for the custom nutrient. unit: type: string description: The new unit of measurement for the custom nutrient. aliases: type: array items: type: string description: Alternate nutrient names online food providers may use for this nutrient. responses: '200': description: The custom nutrient was updated successfully. content: application/json: schema: $ref: '#/components/schemas/CustomNutrient' '401': description: Unauthorized, authentication token is missing or invalid. '404': description: Custom nutrient not found or unauthorized. '500': description: Failed to update custom nutrient. delete: summary: Delete a custom nutrient tags: - Nutrition & Meals description: Deletes a specific custom nutrient and performs cascading cleanup. security: - apiKeyAuth: [] parameters: - in: path name: id required: true schema: type: string format: uuid description: The ID of the custom nutrient to delete. - in: query name: deleteAllHistory schema: type: boolean description: Whether to also remove the nutrient data from past diary entries and goals. responses: '200': description: Custom nutrient deleted successfully. '401': description: Unauthorized, authentication token is missing or invalid. '404': description: Custom nutrient not found or unauthorized. '500': description: Failed to delete custom nutrient. /favorites: get: summary: List the user's favorite (starred) foods and meals tags: - Nutrition & Meals responses: '200': description: The user's favorite foods and meals. /favorites/{type}/{id}: post: summary: Star a food or meal as a favorite tags: - Nutrition & Meals delete: summary: Remove a food or meal from favorites tags: - Nutrition & Meals /foods/search: get: summary: Search for foods (AI-dedicated) tags: - Nutrition & Meals description: Searches for foods based on a name query. This endpoint is dedicated for AI-powered searches. parameters: - in: query name: name schema: type: string required: true description: The name of the food to search for. - in: query name: exactMatch schema: type: boolean description: If true, performs an exact match search. - in: query name: broadMatch schema: type: boolean description: If true, performs a broad match search. - in: query name: checkCustom schema: type: boolean description: If true, includes custom foods in the search. responses: '200': description: A list of foods matching the search criteria. content: application/json: schema: type: array items: $ref: '#/components/schemas/Food' '400': description: Invalid request parameters. /foods: get: summary: Search for foods tags: - Nutrition & Meals description: Searches for foods based on various criteria. parameters: - in: query name: name schema: type: string description: The name of the food to search for. - in: query name: exactMatch schema: type: boolean description: If true, performs an exact match search. - in: query name: broadMatch schema: type: boolean description: If true, performs a broad match search. - in: query name: checkCustom schema: type: boolean description: If true, includes custom foods in the search. - in: query name: limit schema: type: integer description: The maximum number of results to return. - in: query name: mealType schema: type: string description: The type of meal to filter by. responses: '200': description: A list of foods matching the search criteria. content: application/json: schema: type: array items: $ref: '#/components/schemas/Food' '400': description: Invalid request parameters. post: summary: Create a new food tags: - Nutrition & Meals description: Creates a new food item. requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/Food' responses: '201': description: The food was created successfully. content: application/json: schema: $ref: '#/components/schemas/Food' '403': description: User does not have permission to create a food. /foods/foods-paginated: get: summary: Get foods with pagination tags: - Nutrition & Meals description: Retrieves a paginated list of foods. parameters: - in: query name: searchTerm schema: type: string description: The term to search for. - in: query name: foodFilter schema: type: string description: The filter to apply to the food list. - in: query name: currentPage schema: type: integer description: The current page number. - in: query name: itemsPerPage schema: type: integer description: The number of items to return per page. - in: query name: sortBy schema: type: string description: The field to sort by. responses: '200': description: A paginated list of foods. content: application/json: schema: type: object properties: foods: type: array items: $ref: '#/components/schemas/Food' totalCount: type: integer /foods/food-variants: post: summary: Create a new food variant tags: - Nutrition & Meals description: Creates a new variant for a food item. requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/FoodVariant' responses: '201': description: The food variant was created successfully. content: application/json: schema: $ref: '#/components/schemas/FoodVariant' '403': description: User does not have permission to create a food variant. '404': description: Food not found. get: summary: Get food variants by food ID tags: - Nutrition & Meals description: Retrieves all variants for a specific food item. parameters: - in: query name: food_id schema: type: string format: uuid required: true description: The ID of the food to retrieve variants for. responses: '200': description: A list of food variants. content: application/json: schema: type: array items: $ref: '#/components/schemas/FoodVariant' '400': description: Food ID is required. /foods/food-variants/bulk: post: summary: Bulk create food variants tags: - Nutrition & Meals description: Creates multiple food variants in a single request. requestBody: required: true content: application/json: schema: type: array items: $ref: '#/components/schemas/FoodVariant' responses: '201': description: The food variants were created successfully. content: application/json: schema: type: array items: $ref: '#/components/schemas/FoodVariant' '403': description: User does not have permission to create food variants. /foods/food-variants/{id}: get: summary: Get a food variant by ID tags: - Nutrition & Meals description: Retrieves a specific food variant by its ID. parameters: - in: path name: id schema: type: string format: uuid required: true description: The ID of the food variant to retrieve. responses: '200': description: The requested food variant. content: application/json: schema: $ref: '#/components/schemas/FoodVariant' '400': description: Food Variant ID is required. '403': description: User does not have permission to access this resource. '404': description: Food variant not found. put: summary: Update a food variant tags: - Nutrition & Meals description: Updates an existing food variant. parameters: - in: path name: id schema: type: string format: uuid required: true description: The ID of the food variant to update. requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/FoodVariant' responses: '200': description: The updated food variant. content: application/json: schema: $ref: '#/components/schemas/FoodVariant' '400': description: Food Variant ID and Food ID are required. '403': description: User does not have permission to update this food variant. '404': description: Food variant not found. delete: summary: Delete a food variant tags: - Nutrition & Meals description: Deletes a specific food variant. parameters: - in: path name: id schema: type: string format: uuid required: true description: The ID of the food variant to delete. responses: '200': description: Food variant deleted successfully. '400': description: Food Variant ID is required. '403': description: User does not have permission to delete this food variant. '404': description: Food variant not found. /foods/barcode/{barcode}: get: summary: Look up a food by barcode tags: - Nutrition & Meals description: Checks the local database first, then queries an external barcode provider (USDA, FatSecret, YAZIO, or OpenFoodFacts). The provider can be specified via the providerId query parameter or the user's default_barcode_provider_id preference. If the chosen provider returns no results, OpenFoodFacts is tried as a fallback. parameters: - in: path name: barcode schema: type: string required: true description: The barcode to look up (8-14 digits). - in: query name: providerId schema: type: string format: uuid description: Optional external data provider ID to use for barcode lookup (e.g. a USDA provider). Falls back to the user's default barcode provider preference if not specified. responses: '200': description: Barcode lookup result. content: application/json: schema: type: object properties: source: type: string enum: - local - openfoodfacts - usda - fatsecret - yazio - not_found food: $ref: '#/components/schemas/Food' '400': description: Invalid barcode format. /foods/{foodId}: get: summary: Get a food by ID tags: - Nutrition & Meals description: Retrieves a specific food item by its ID. parameters: - in: path name: foodId schema: type: string format: uuid required: true description: The ID of the food to retrieve. responses: '200': description: The requested food item. content: application/json: schema: $ref: '#/components/schemas/Food' '400': description: Food ID is required. '403': description: User does not have permission to access this resource. '404': description: Food not found. /foods/{id}: put: summary: Update a food tags: - Nutrition & Meals description: Updates an existing food item. parameters: - in: path name: id schema: type: string format: uuid required: true description: The ID of the food to update. requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/Food' responses: '200': description: The updated food item. content: application/json: schema: $ref: '#/components/schemas/Food' '400': description: Food ID is required. '403': description: User does not have permission to update this food. '404': description: Food not found or not authorized to update. delete: summary: Delete a food tags: - Nutrition & Meals description: Deletes a specific food item. parameters: - in: path name: id schema: type: string format: uuid required: true description: The ID of the food to delete. - in: query name: forceDelete schema: type: boolean description: If true, forces deletion even if there are dependencies. responses: '200': description: Food deleted successfully. '400': description: Food ID is required. '403': description: User does not have permission to delete this food. '404': description: Food not found. /foods/{id}/deletion-impact: get: summary: Get food deletion impact tags: - Nutrition & Meals description: Retrieves the impact of deleting a specific food item. parameters: - in: path name: id schema: type: string format: uuid required: true description: The ID of the food to check. responses: '200': description: The deletion impact report. '400': description: Food ID is required. '403': description: User does not have permission to access this resource. '404': description: Food not found. /foods/import-from-csv: post: summary: Import foods from CSV tags: - Nutrition & Meals description: Imports a list of foods from a CSV file. requestBody: required: true content: application/json: schema: type: object properties: foods: type: array items: $ref: '#/components/schemas/Food' responses: '200': description: Food data imported successfully. '400': description: Food data is required. /foods/needs-review: get: summary: Get foods needing review tags: - Nutrition & Meals description: Retrieves a list of foods that need to be reviewed. responses: '200': description: A list of foods needing review. content: application/json: schema: type: array items: $ref: '#/components/schemas/Food' /foods/update-snapshot: post: summary: Update food entries snapshot tags: - Nutrition & Meals description: Updates the snapshot of food entries. requestBody: required: true content: application/json: schema: type: object properties: foodId: type: string format: uuid variantId: type: string format: uuid syncImages: type: boolean default: true description: 'When true (the default), past entries are forced onto the food''s current photos, replacing photos the user set on individual diary entries; the replaced files are unlinked. When false, nutrition is rewritten and every entry keeps the photo it is showing. ' responses: '200': description: The result of the snapshot update. '400': description: foodId is required. /food-entry-meals: post: summary: Create a new FoodEntryMeal tags: - Nutrition & Meals description: Creates a new food entry meal for the authenticated user. requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/FoodEntryMeal' responses: '201': description: The FoodEntryMeal was created successfully. content: application/json: schema: $ref: '#/components/schemas/FoodEntryMeal' '403': description: User does not have permission to create a food entry meal. /food-entry-meals/by-date/{date}: get: summary: Get FoodEntryMeals by date tags: - Nutrition & Meals description: Retrieves a list of all food entry meals for a specific date. parameters: - in: path name: date required: true schema: type: string format: date description: The date to retrieve food entry meals for (YYYY-MM-DD). responses: '200': description: A list of food entry meals for the specified date. content: application/json: schema: type: array items: $ref: '#/components/schemas/FoodEntryMeal' '403': description: User does not have permission to access this resource. /food-entry-meals/{id}: get: summary: Get a specific FoodEntryMeal with its components tags: - Nutrition & Meals description: Retrieves a specific food entry meal by its ID, including its associated food components. parameters: - in: path name: id required: true schema: type: string format: uuid description: The ID of the food entry meal to retrieve. responses: '200': description: The requested FoodEntryMeal with components. content: application/json: schema: $ref: '#/components/schemas/FoodEntryMeal' '403': description: User does not have permission to access this resource. '404': description: FoodEntryMeal not found. put: summary: Update an existing FoodEntryMeal tags: - Nutrition & Meals description: Updates an existing food entry meal with new information. parameters: - in: path name: id required: true schema: type: string format: uuid description: The ID of the food entry meal to update. requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/FoodEntryMeal' responses: '200': description: The FoodEntryMeal was updated successfully. content: application/json: schema: $ref: '#/components/schemas/FoodEntryMeal' '403': description: User does not have permission to update this food entry meal. '404': description: FoodEntryMeal not found. delete: summary: Delete a FoodEntryMeal tags: - Nutrition & Meals description: Deletes a specific food entry meal. parameters: - in: path name: id required: true schema: type: string format: uuid description: The ID of the food entry meal to delete. responses: '204': description: FoodEntryMeal deleted successfully. '403': description: User does not have permission to delete this food entry meal. '404': description: FoodEntryMeal not found. /food-entry-meals/{id}/image: post: summary: Set a logged meal's override photo tags: - Nutrition & Meals description: 'Attaches a photo to this diary entry only. It never modifies the meal template''s own images; entries without an override fall back to those. ' requestBody: content: multipart/form-data: schema: type: object properties: images: description: 'Repeated file parts for newly uploaded photos, plus a JSON string field of the same name holding the desired final order. Entries in that array are either existing image paths being kept, or `__new__` placeholders marking where the n-th uploaded file belongs. ' type: array items: type: string format: binary responses: '200': description: The updated logged meal. '400': description: No image supplied. '404': description: FoodEntryMeal not found. delete: summary: Clear a logged meal's override photo tags: - Nutrition & Meals description: 'Removes the entry-specific photo so the entry falls back to the meal template''s own image. The template is never modified. ' responses: '200': description: The updated logged meal. '404': description: FoodEntryMeal not found. /food-entries/export/csv: get: summary: Export all food entries as CSV tags: - Nutrition & Meals security: - apiKeyAuth: [] responses: '200': description: A CSV stream of all food entries content: text/csv: schema: type: string /food-entries/import-from-csv: post: summary: Import diary log entries from CSV tags: - Nutrition & Meals description: 'Bulk-creates diary log entries (food_entries) from CSV rows, distinct from /foods/import-from-csv which only imports food-library master data. Unmatched foods are auto-created from the row''s own nutrient columns; a row with no match and no nutrients is a per-row error. ' requestBody: required: true content: application/json: schema: type: object properties: entries: type: array items: type: object scope: type: object properties: family: type: boolean public: type: boolean responses: '200': description: Per-row import results (processed/errors/skipped). '400': description: Entries are required. /food-entries: post: summary: Create a new food entry tags: - Nutrition & Meals description: Adds a new food entry to the user's diary for a specific meal and date. requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/FoodEntry' responses: '201': description: The food entry was created successfully. content: application/json: schema: $ref: '#/components/schemas/FoodEntry' '400': description: Invalid request body. '403': description: User does not have permission to create a food entry. get: summary: Get food entries by selected date tags: - Nutrition & Meals description: Retrieves a list of all food entries for a specific date, passed as a query parameter. parameters: - in: query name: selectedDate required: true schema: type: string format: date description: The date to retrieve food entries for (YYYY-MM-DD). responses: '200': description: A list of food entries for the specified date. content: application/json: schema: type: array items: $ref: '#/components/schemas/FoodEntry' '400': description: Selected date parameter is missing. '403': description: User does not have permission to access this resource. /food-entries/copy: post: summary: Copy food entries from one meal to another tags: - Nutrition & Meals description: Copies all food entries from a source meal on a specific date to a target meal on another date. requestBody: required: true content: application/json: schema: type: object required: - sourceDate - sourceMealType - targetDate - targetMealType properties: sourceDate: type: string format: date sourceMealType: type: string targetDate: type: string format: date targetMealType: type: string responses: '201': description: The food entries were copied successfully. '400': description: Invalid request body. '403': description: User does not have permission to copy food entries. /food-entries/copy-from-user: post: summary: Copy food entries from a family member's diary to the active user's diary tags: - Nutrition & Meals requestBody: required: true content: application/json: schema: type: object required: - familyUserId - sourceDate - sourceMealType - targetDate - targetMealType properties: familyUserId: type: string format: uuid sourceDate: type: string format: date sourceMealType: type: string targetDate: type: string format: date targetMealType: type: string responses: '201': description: Successfully copied entries '400': description: Missing fields '403': description: Forbidden /food-entries/copy-reviewed-from-user: post: summary: Copy an unchanged reviewed family meal into the authenticated user's diary tags: - Nutrition & Meals description: 'Preserves logged composite meal containers. The submitted entry IDs and source fingerprints are an optimistic-concurrency snapshot; any added, removed, or changed source row returns 409 and writes nothing. ' requestBody: required: true content: application/json: schema: type: object additionalProperties: false required: - familyUserId - sourceDate - sourceMealType - targetDate - targetMealType - entries properties: familyUserId: type: string format: uuid sourceDate: type: string format: date sourceMealType: type: string targetDate: type: string format: date targetMealType: type: string format: uuid entries: type: array minItems: 1 maxItems: 100 items: type: object additionalProperties: false required: - entryId - sourceFingerprint properties: entryId: type: string format: uuid sourceFingerprint: type: string description: Exact reviewed source-row snapshot. responses: '201': description: The reviewed meal was copied successfully. '400': description: Invalid request body. '403': description: Forbidden. '409': description: The reviewed source meal changed before it could be copied. /food-entries/copy-selected-from-user: post: summary: Copy selected food entries from a family member's diary tags: - Nutrition & Meals requestBody: required: true content: application/json: schema: type: object additionalProperties: false required: - familyUserId - sourceDate - targetDate - targetMealType - entries properties: familyUserId: type: string format: uuid sourceDate: type: string format: date targetDate: type: string format: date targetMealType: type: string format: uuid entries: type: array minItems: 1 maxItems: 100 items: type: object additionalProperties: false required: - entryId - quantity - sourceFingerprint properties: entryId: type: string format: uuid quantity: type: number exclusiveMinimum: 0 sourceFingerprint: type: string description: Exact reviewed source-row snapshot. responses: '201': description: The selected food entries were copied successfully. '400': description: Invalid request body. '403': description: Forbidden. '409': description: A selected source entry changed after it was reviewed. /food-entries/copy-to-user: post: summary: Copy food entries from the active user's diary to a family member's diary tags: - Nutrition & Meals requestBody: required: true content: application/json: schema: type: object required: - familyUserId - sourceDate - sourceMealType - targetDate - targetMealType properties: familyUserId: type: string format: uuid sourceDate: type: string format: date sourceMealType: type: string targetDate: type: string format: date targetMealType: type: string responses: '201': description: Successfully copied entries '400': description: Missing fields '403': description: Forbidden /food-entries/copy-yesterday: post: summary: Copy food entries from yesterday's meal tags: - Nutrition & Meals description: Copies all food entries from a specific meal on the previous day to the same meal on a target date. requestBody: required: true content: application/json: schema: type: object required: - mealType - targetDate properties: mealType: type: string targetDate: type: string format: date responses: '201': description: The food entries were copied successfully. '400': description: Invalid request body. '403': description: User does not have permission to copy food entries. /food-entries/copy-all: post: summary: Copy all food entries from one day to another tags: - Nutrition & Meals description: Copies every food entry across all meal slots from a source date to a target date. requestBody: required: true content: application/json: schema: type: object required: - sourceDate - targetDate properties: sourceDate: type: string format: date targetDate: type: string format: date responses: '201': description: All food entries were copied successfully. '400': description: sourceDate and targetDate are required. '403': description: User does not have permission. /food-entries/copy-all-yesterday: post: summary: Copy all food entries from yesterday tags: - Nutrition & Meals description: Copies every food entry from the previous day to a target date. requestBody: required: true content: application/json: schema: type: object required: - targetDate properties: targetDate: type: string format: date responses: '201': description: All food entries were copied successfully. '400': description: targetDate is required. /food-entries/{id}: put: summary: Update a food entry tags: - Nutrition & Meals description: Updates an existing food entry with new information. parameters: - in: path name: id required: true schema: type: string format: uuid description: The ID of the food entry to update. requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/FoodEntry' responses: '200': description: The food entry was updated successfully. content: application/json: schema: $ref: '#/components/schemas/FoodEntry' '400': description: Invalid request body or food entry ID. '403': description: User does not have permission to update this food entry. '404': description: Food entry not found. delete: summary: Delete a food entry tags: - Nutrition & Meals description: Deletes a food entry from the user's diary. parameters: - in: path name: id required: true schema: type: string format: uuid description: The ID of the food entry to delete. responses: '200': description: The food entry was deleted successfully. '400': description: Invalid food entry ID. '403': description: User does not have permission to delete this food entry. '404': description: Food entry not found. /food-entries/by-date/{date}: get: summary: Get all food entries for a specific date tags: - Nutrition & Meals description: Retrieves a list of all food entries logged by the user for a given date. parameters: - in: path name: date required: true schema: type: string format: date description: The date to retrieve food entries for (YYYY-MM-DD). responses: '200': description: A list of food entries for the specified date. content: application/json: schema: type: array items: $ref: '#/components/schemas/FoodEntry' '400': description: Date parameter is missing. '403': description: User does not have permission to access this resource. /food-entries/range/{startDate}/{endDate}: get: summary: Get food entries within a date range tags: - Nutrition & Meals description: Retrieves a list of all food entries logged by the user between a start and end date. parameters: - in: path name: startDate required: true schema: type: string format: date description: The start date of the range (YYYY-MM-DD). - in: path name: endDate required: true schema: type: string format: date description: The end date of the range (YYYY-MM-DD). responses: '200': description: A list of food entries for the specified date range. content: application/json: schema: type: array items: $ref: '#/components/schemas/FoodEntry' '400': description: Start or end date parameters are missing. '403': description: User does not have permission to access this resource. /food-entries/nutrition/today: get: summary: Get daily nutrition summary tags: - Nutrition & Meals description: Retrieves a summary of the user's nutritional intake for a specific date. parameters: - in: query name: date required: true schema: type: string format: date description: The date to retrieve the nutrition summary for (YYYY-MM-DD). responses: '200': description: The daily nutrition summary. content: application/json: schema: $ref: '#/components/schemas/NutritionSummary' '400': description: Date parameter is missing. '403': description: User does not have permission to access this resource. '404': description: Nutrition summary not found for this date. /food-entries/{id}/image: post: summary: Set the per-entry override photo for a diary entry tags: - Nutrition & Meals description: 'Uploads a photo that applies only to this diary entry. It never changes the underlying food''s or meal''s own images; entries without an override fall back to those at display time. ' requestBody: required: true content: multipart/form-data: schema: type: object properties: images: description: 'Repeated file parts for newly uploaded photos, plus a JSON string field of the same name holding the desired final order. Entries in that array are either existing image paths being kept, or `__new__` placeholders marking where the n-th uploaded file belongs. ' type: array items: type: string format: binary responses: '200': description: The updated food entry. '400': description: No image supplied. '403': description: User does not have permission to manage this diary. delete: summary: Clear a diary entry's override photo tags: - Nutrition & Meals description: 'Removes the entry-specific photo so the entry falls back to the parent food''s or meal''s own image. The parent is never modified. ' responses: '200': description: The updated food entry. /foods/food-entries/{date}: get: summary: Get food entries by date (re-routed) tags: - Nutrition & Meals description: This endpoint re-routes requests to the foodEntryRoutes for retrieving food entries by date. parameters: - in: path name: date schema: type: string format: date required: true description: The date to retrieve food entries for (YYYY-MM-DD). responses: '200': description: A list of food entries for the specified date. '400': description: Invalid date parameter. /meal-plan-templates: post: summary: Create a new meal plan template tags: - Nutrition & Meals description: Creates a new meal plan template for the authenticated user. requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/MealPlanTemplate' responses: '201': description: The meal plan template was created successfully. content: application/json: schema: $ref: '#/components/schemas/MealPlanTemplate' '403': description: User does not have permission to create a meal plan template. get: summary: Get all meal plan templates for a user tags: - Nutrition & Meals description: Retrieves all meal plan templates owned by the authenticated user. responses: '200': description: A list of meal plan templates. content: application/json: schema: type: array items: $ref: '#/components/schemas/MealPlanTemplate' '403': description: User does not have permission to access this resource. /meal-plan-templates/{id}: put: summary: Update a meal plan template tags: - Nutrition & Meals description: Updates an existing meal plan template. parameters: - in: path name: id required: true schema: type: string format: uuid description: The ID of the meal plan template to update. requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/MealPlanTemplate' responses: '200': description: The meal plan template was updated successfully. content: application/json: schema: $ref: '#/components/schemas/MealPlanTemplate' '403': description: User does not have permission to update this meal plan template. '404': description: Meal plan template not found. delete: summary: Delete a meal plan template tags: - Nutrition & Meals description: Deletes a specific meal plan template. parameters: - in: path name: id required: true schema: type: string format: uuid description: The ID of the meal plan template to delete. responses: '204': description: Meal plan template deleted successfully. '403': description: User does not have permission to delete this meal plan template. '404': description: Meal plan template not found. /meal-plan-templates/{id}/duplicate: post: summary: Duplicate a meal plan template tags: - Nutrition & Meals description: Clones an existing meal plan template and its assignments. parameters: - in: path name: id required: true schema: type: string format: uuid description: The ID of the meal plan template to duplicate. responses: '201': description: The meal plan template was duplicated successfully. content: application/json: schema: $ref: '#/components/schemas/MealPlanTemplate' /meals/plan: post: summary: Create a new meal plan entry tags: - Nutrition & Meals description: Creates a new meal plan entry for the authenticated user. requestBody: required: true content: application/json: schema: type: object properties: meal_plan_template_id: type: string format: uuid description: The ID of the meal plan template to use. plan_date: type: string format: date description: The date for which the meal plan is created. meals: type: array items: type: object properties: meal_type: type: string description: The type of meal (e.g., "Breakfast"). food_ids: type: array items: type: string format: uuid description: List of food IDs included in this meal. required: - meal_plan_template_id - plan_date - meals responses: '201': description: The meal plan entry was created successfully. '400': description: Invalid request body. '403': description: User does not have permission to create a meal plan entry. get: summary: Get meal plan entries for a specific date or date range tags: - Nutrition & Meals description: Retrieves meal plan entries for the authenticated user within a specified date range. parameters: - in: query name: startDate schema: type: string format: date required: true description: The start date of the range (YYYY-MM-DD). - in: query name: endDate schema: type: string format: date required: true description: The end date of the range (YYYY-MM-DD). responses: '200': description: A list of meal plan entries. '400': description: startDate and endDate are required. '403': description: User does not have permission to access this resource. /meals/plan/{id}: put: summary: Update a meal plan entry tags: - Nutrition & Meals description: Updates an existing meal plan entry. parameters: - in: path name: id required: true schema: type: string format: uuid description: The ID of the meal plan entry to update. requestBody: required: true content: application/json: schema: type: object properties: meal_plan_template_id: type: string format: uuid description: The ID of the meal plan template to use. plan_date: type: string format: date description: The date for which the meal plan is created. meals: type: array items: type: object properties: meal_type: type: string description: The type of meal (e.g., "Breakfast"). food_ids: type: array items: type: string format: uuid description: List of food IDs included in this meal. required: - meal_plan_template_id - plan_date - meals responses: '200': description: The meal plan entry was updated successfully. '403': description: User does not have permission to update this meal plan entry. '404': description: Meal plan entry not found. delete: summary: Delete a meal plan entry tags: - Nutrition & Meals description: Deletes a specific meal plan entry. parameters: - in: path name: id required: true schema: type: string format: uuid description: The ID of the meal plan entry to delete. responses: '200': description: Meal plan entry deleted successfully. '403': description: User does not have permission to delete this meal plan entry. '404': description: Meal plan entry not found. /meals: post: summary: Create a new meal template tags: - Nutrition & Meals description: Creates a new meal template for the authenticated user. requestBody: required: true content: application/json: schema: type: object properties: name: type: string description: The name of the meal. description: type: string description: A description of the meal. is_public: type: boolean description: Whether the meal is publicly visible. serving_size: type: number description: Quantity of one serving in serving_unit (e.g. 250 for 250 ml). Forced to 1 when serving_unit is 'serving'. serving_unit: type: string description: Unit of measurement for one serving (e.g. ml, g, cup, serving). total_servings: type: number description: How many servings the recipe yields. Full recipe quantity = serving_size × total_servings. foods: type: array description: 'The meal''s flat ingredient list. Each item is either a food (item_type "food", default) or a reusable sub-meal (item_type "meal"). A linked meal''s quantity/unit scale its full recipe (serving_size × total_servings) the same way a food''s quantity scales its serving_size. Linking a meal that would create a cycle, exceed the max nesting depth, or that the caller cannot access is rejected with a 400. ' items: type: object properties: item_type: type: string enum: - food - meal default: food description: Discriminates a food ingredient from a linked sub-meal. food_id: type: string format: uuid description: Required when item_type is "food". child_meal_id: type: string format: uuid description: Required when item_type is "meal"; the linked sub-meal's id. quantity: type: number unit: type: string required: - quantity - unit required: - name - foods responses: '201': description: The meal was created successfully. '400': description: Validation error (e.g. serving_size/total_servings not positive, ambiguous or inaccessible ingredient, cycle, or nesting depth exceeded). '403': description: User does not have permission to create a meal. get: summary: Get all meal templates for the user tags: - Nutrition & Meals description: Retrieves all meal templates owned by the authenticated user, and public ones. parameters: - in: query name: filter schema: type: string description: Filter meals (e.g., "public", "private"). - in: query name: search schema: type: string description: Search term for meal names. responses: '200': description: A list of meal templates. '403': description: User does not have permission to access this resource. /meals/recent: get: summary: Get recently logged meal templates tags: - Nutrition & Meals description: Retrieves meal templates recently logged by the authenticated user. parameters: - in: query name: limit schema: type: integer default: 3 minimum: 1 maximum: 20 description: The maximum number of recent meals to return. responses: '200': description: A list of recently logged meal templates. '403': description: User does not have permission to access this resource. /meals/top: get: summary: Get most frequently logged meal templates tags: - Nutrition & Meals description: Retrieves the meal templates the authenticated user logs most often, ranked by usage count. parameters: - in: query name: limit schema: type: integer default: 3 minimum: 1 maximum: 20 description: The maximum number of top meals to return. responses: '200': description: A list of the most frequently logged meal templates. '403': description: User does not have permission to access this resource. /meals/search: get: summary: Search for meal templates tags: - Nutrition & Meals description: Searches for meal templates based on a search term. parameters: - in: query name: searchTerm schema: type: string required: true description: The term to search for. responses: '200': description: A list of meal templates matching the search term. '400': description: Search term is required. /meals/{id}: get: summary: Get a specific meal template by ID tags: - Nutrition & Meals description: Retrieves a specific meal template by its ID. parameters: - in: path name: id required: true schema: type: string format: uuid description: The ID of the meal template to retrieve. responses: '200': description: 'The requested meal template. Each entry in `foods` carries `item_type` ("food" or "meal"). Food rows have `food_id`, `food_name`, `variant_id`, and a nutrition snapshot. Linked-meal rows have `child_meal_id`, `child_meal_name`, `child_meal_serving_unit`, `child_meal_total_servings`, and the same nutrition fields populated with the sub-meal''s *resolved* full-recipe totals (recursively aggregated through any further nested sub-meals) so external tools can compute a scaled contribution the same way as for a food row: value × quantity / serving_size. ' '403': description: User does not have permission to access this resource. '404': description: Meal not found. put: summary: Update an existing meal template tags: - Nutrition & Meals description: Updates an existing meal template. parameters: - in: path name: id required: true schema: type: string format: uuid description: The ID of the meal template to update. requestBody: required: true content: application/json: schema: type: object properties: name: type: string description: The name of the meal. description: type: string description: A description of the meal. is_public: type: boolean description: Whether the meal is publicly visible. serving_size: type: number description: Quantity of one serving in serving_unit. Forced to 1 when serving_unit is 'serving'. serving_unit: type: string description: Unit of measurement for one serving (e.g. ml, g, cup, serving). total_servings: type: number description: How many servings the recipe yields. Full recipe quantity = serving_size × total_servings. foods: type: array description: 'The meal''s flat ingredient list. Each item is either a food (item_type "food", default) or a reusable sub-meal (item_type "meal"). Linking a meal that would create a cycle, exceed the max nesting depth, or that the caller cannot access is rejected with a 400. ' items: type: object properties: item_type: type: string enum: - food - meal default: food description: Discriminates a food ingredient from a linked sub-meal. food_id: type: string format: uuid description: Required when item_type is "food". child_meal_id: type: string format: uuid description: Required when item_type is "meal"; the linked sub-meal's id. quantity: type: number unit: type: string required: - quantity - unit required: - name - foods responses: '200': description: The meal template was updated successfully. '400': description: Validation error (e.g. serving_size/total_servings not positive, ambiguous or inaccessible ingredient, cycle, or nesting depth exceeded). '403': description: User does not have permission to update this meal. '404': description: Meal not found. delete: summary: Delete a meal template tags: - Nutrition & Meals description: Deletes a specific meal template. parameters: - in: path name: id required: true schema: type: string format: uuid description: The ID of the meal template to delete. responses: '200': description: Meal deleted successfully. '403': description: User does not have permission to delete this meal. '404': description: Meal not found. /meals/{id}/deletion-impact: get: summary: Get the deletion impact for a meal tags: - Nutrition & Meals description: Retrieves the impact of deleting a specific meal template. parameters: - in: path name: id required: true schema: type: string format: uuid description: The ID of the meal to check. responses: '200': description: The deletion impact report. '403': description: User does not have permission to access this resource. '404': description: Meal not found. /meals/plan/{id}/log-to-diary: post: summary: Log a specific meal plan entry to the food diary tags: - Nutrition & Meals description: Logs a specific meal plan entry to the user's food diary for a target date. parameters: - in: path name: id required: true schema: type: string format: uuid description: The ID of the meal plan entry to log. requestBody: required: true content: application/json: schema: type: object properties: target_date: type: string format: date description: The date to log the meal plan entry to. required: - target_date responses: '201': description: The food entries were created successfully. '403': description: User does not have permission to perform this action. '404': description: Meal plan entry or associated meal template not found. /meals/plan/log-day-to-diary: post: summary: Log all meal plan entries for a specific day to the food diary tags: - Nutrition & Meals description: Logs all meal plan entries for a given plan date to the user's food diary for a target date. requestBody: required: true content: application/json: schema: type: object properties: plan_date: type: string format: date description: The date of the meal plan to log. target_date: type: string format: date description: The date to log the meal plan entries to. required: - plan_date - target_date responses: '201': description: The food entries were created successfully. '400': description: plan_date is required. '403': description: User does not have permission to perform this action. /meals/needs-review: get: summary: Get meals needing review tags: - Nutrition & Meals description: Retrieves a list of meals that need to be reviewed. responses: '200': description: A list of meals needing review. '403': description: User does not have permission to access this resource. /meals/update-snapshot: post: summary: Update meal entries snapshot tags: - Nutrition & Meals description: Updates the snapshot of meal entries. requestBody: required: true content: application/json: schema: type: object properties: mealId: type: string format: uuid description: The ID of the meal to update the snapshot for. required: - mealId responses: '200': description: The result of the snapshot update. '400': description: mealId is required. '403': description: User does not have permission to perform this action. /meals/create-meal-from-diary: post: summary: Create a meal from diary entries tags: - Nutrition & Meals description: Creates a new meal template from existing food diary entries for a specific date and meal type. requestBody: required: true content: application/json: schema: type: object properties: date: type: string format: date description: The date of the diary entries to use. mealType: type: string description: The meal type of the diary entries to use. mealName: type: string description: A name for the new meal template. description: type: string description: A description for the new meal template. isPublic: type: boolean description: Whether the new meal template should be publicly visible. required: - date - mealType responses: '201': description: The new meal template was created successfully. '400': description: Date and mealType are required, or no food entries found, or cannot create meal. '403': description: User does not have permission to perform this action. /meal-types: get: summary: Retrieve all meal types tags: - Nutrition & Meals description: Retrieves all meal types available to the user, including system defaults and custom meal types. security: - bearerAuth: [] responses: '200': description: A list of meal types. content: application/json: schema: type: array items: $ref: '#/components/schemas/MealType' '401': description: Unauthorized, authentication token is missing or invalid. '500': description: Failed to fetch meal types. post: summary: Create a new custom meal type tags: - Nutrition & Meals description: Creates a new custom meal type for the authenticated user. security: - bearerAuth: [] requestBody: required: true content: application/json: schema: type: object required: - name properties: name: type: string description: The name of the new meal type (e.g., "Pre-Workout"). sort_order: type: - integer - 'null' description: The sort order for the meal type. default_time: type: - string - 'null' description: Default time of day (HH:MM, 24h) used to prefill diary entry times for this meal. responses: '201': description: The new meal type was created successfully. content: application/json: schema: $ref: '#/components/schemas/MealType' '400': description: Invalid request body, name is required. '401': description: Unauthorized, authentication token is missing or invalid. '409': description: A meal type with the given name already exists. '500': description: Failed to create meal type. /meal-types/{id}: get: summary: Retrieve a single meal type by ID tags: - Nutrition & Meals description: Retrieves a single meal type by its ID. security: - bearerAuth: [] parameters: - in: path name: id required: true schema: type: string format: uuid description: The ID of the meal type to retrieve. responses: '200': description: The requested meal type. content: application/json: schema: $ref: '#/components/schemas/MealType' '401': description: Unauthorized, authentication token is missing or invalid. '404': description: Meal type not found. '500': description: Failed to fetch meal type. put: summary: Update a meal type tags: - Nutrition & Meals description: Updates an existing custom meal type. System default meal types cannot be updated. security: - bearerAuth: [] parameters: - in: path name: id required: true schema: type: string format: uuid description: The ID of the meal type to update. requestBody: required: true content: application/json: schema: type: object properties: name: type: string description: The new name for the meal type. sort_order: type: - integer - 'null' description: The new sort order for the meal type. is_visible: type: boolean description: Whether this meal type is visible in the diary view. show_in_quick_log: type: boolean description: Whether this meal type appears in the quick food log menu. default_time: type: - string - 'null' description: Per-user default time of day (HH:MM, 24h) used to prefill diary entry times. Null clears it. responses: '200': description: The meal type was updated successfully. content: application/json: schema: $ref: '#/components/schemas/MealType' '401': description: Unauthorized, authentication token is missing or invalid. '403': description: Forbidden, system default meal types cannot be updated. '404': description: Meal type not found. '500': description: Failed to update meal type. delete: summary: Delete a custom meal type tags: - Nutrition & Meals description: Deletes a custom meal type. System default meal types cannot be deleted. security: - bearerAuth: [] parameters: - in: path name: id required: true schema: type: string format: uuid description: The ID of the meal type to delete. responses: '200': description: Meal type deleted successfully. '401': description: Unauthorized, authentication token is missing or invalid. '403': description: Forbidden, system default meal types cannot be deleted. '404': description: Meal type not found or cannot be deleted. '409': description: Conflict, meal type contains food entries and cannot be deleted. '500': description: Failed to delete meal type. /preferences/nutrient-display: get: summary: Get all nutrient display preferences for the logged-in user tags: - Nutrition & Meals description: Retrieves all nutrient display preferences for the authenticated user. security: - apiKeyAuth: [] responses: '200': description: A list of nutrient display preferences. content: application/json: schema: type: array items: $ref: '#/components/schemas/NutrientDisplayPreference' '401': description: Unauthorized, authentication token is missing or invalid. '500': description: Failed to fetch nutrient display preferences. /preferences/nutrient-display/{viewGroup}/{platform}: put: summary: Upsert a nutrient display preference tags: - Nutrition & Meals description: Creates or updates a nutrient display preference for a specific view group and platform for the authenticated user. security: - apiKeyAuth: [] parameters: - in: path name: viewGroup required: true schema: type: string description: The group for which the preference applies (e.g., "daily", "meal"). - in: path name: platform required: true schema: type: string description: The platform for which the preference applies (e.g., "web", "mobile"). requestBody: required: true content: application/json: schema: type: object required: - visible_nutrients properties: visible_nutrients: type: array items: type: string description: An array of nutrient names that should be visible. responses: '200': description: The nutrient display preference was upserted successfully. content: application/json: schema: $ref: '#/components/schemas/NutrientDisplayPreference' '401': description: Unauthorized, authentication token is missing or invalid. '500': description: Failed to upsert nutrient display preference. delete: summary: Reset a nutrient display preference to default tags: - Nutrition & Meals description: Resets a specific nutrient display preference to its default settings for the authenticated user. security: - apiKeyAuth: [] parameters: - in: path name: viewGroup required: true schema: type: string description: The group for which the preference applies (e.g., "daily", "meal"). - in: path name: platform required: true schema: type: string description: The platform for which the preference applies (e.g., "web", "mobile"). responses: '200': description: The nutrient display preference was reset successfully. content: application/json: schema: $ref: '#/components/schemas/NutrientDisplayPreference' '401': description: Unauthorized, authentication token is missing or invalid. '500': description: Failed to reset nutrient display preference. /nutrient-goal-preferences: get: summary: Get effective goal-direction preferences for every nutrient tags: - Nutrition & Meals description: Returns a map of nutrient key -> effective goal direction (user override merged with built-in defaults) for all predefined nutrients and the user's custom nutrients. security: - apiKeyAuth: [] responses: '200': description: Map of nutrient key to NutrientGoalPreference. content: application/json: schema: type: object additionalProperties: $ref: '#/components/schemas/NutrientGoalPreference' '401': description: Unauthorized. /nutrient-goal-preferences/{nutrientKey}: put: summary: Set a nutrient's goal-direction override tags: - Nutrition & Meals description: Upserts the authenticated user's goal-direction override for a single nutrient (predefined or custom). security: - apiKeyAuth: [] parameters: - in: path name: nutrientKey required: true schema: type: string requestBody: required: true content: application/json: schema: type: object required: - goalType properties: goalType: type: string enum: - minimum - maximum - target targetMin: type: number targetMax: type: number responses: '200': description: The upserted preference. '400': description: Invalid goalType or missing/invalid target band. '401': description: Unauthorized. delete: summary: Reset a nutrient's goal direction to its built-in default tags: - Nutrition & Meals security: - apiKeyAuth: [] parameters: - in: path name: nutrientKey required: true schema: type: string responses: '200': description: The resolved built-in default after resetting. '401': description: Unauthorized. components: schemas: FoodVariant: type: object properties: id: type: string format: uuid description: The unique identifier for the food variant. food_id: type: string format: uuid description: The ID of the food this variant belongs to. serving_size: type: string description: The serving size of the variant (e.g., "1 cup"). data: type: object description: Nutritional data for this specific variant. required: - id - food_id - serving_size - data MealType: type: object properties: id: type: string format: uuid description: The unique identifier for the meal type. user_id: type: string format: uuid description: The ID of the user who owns the meal type (null for system defaults). name: type: string description: The name of the meal type (e.g., "Breakfast", "Lunch"). sort_order: type: integer description: The order in which meal types should be displayed. is_system_default: type: boolean description: Indicates if this is a system default meal type. created_at: type: string format: date-time description: The date and time when the meal type was created. updated_at: type: string format: date-time description: The date and time when the meal type was last updated. required: - id - name - sort_order - is_system_default NutrientDisplayPreference: type: object properties: user_id: type: string format: uuid description: The ID of the user who owns the preference. view_group: type: string description: The group for which the preference applies (e.g., "daily", "meal"). platform: type: string description: The platform for which the preference applies (e.g., "web", "mobile"). visible_nutrients: type: array items: type: string description: An array of nutrient names that should be visible. created_at: type: string format: date-time description: The date and time when the preference was created. updated_at: type: string format: date-time description: The date and time when the preference was last updated. required: - user_id - view_group - platform - visible_nutrients CustomNutrient: type: object properties: id: type: string format: uuid description: The unique identifier for the custom nutrient. user_id: type: string format: uuid description: The ID of the user who owns the custom nutrient. name: type: string description: The name of the custom nutrient. unit: type: string description: The unit of measurement for the custom nutrient. aliases: type: array items: type: string description: Alternate nutrient names online food providers may use, matched (case-insensitively) on import. created_at: type: string format: date-time description: The date and time when the custom nutrient was created. updated_at: type: string format: date-time description: The date and time when the custom nutrient was last updated. required: - id - user_id - name - unit FoodEntry: type: object required: - user_id - meal_type_id - quantity - unit - entry_date - food_name - calories properties: id: type: string format: uuid description: The unique identifier for the food entry. user_id: type: string format: uuid description: The ID of the user who owns this food entry. food_id: type: string format: uuid description: The ID of the food, if this entry is linked to a food in the database. meal_id: type: string format: uuid description: The ID of the meal, if this entry is part of a meal. meal_type_id: type: string format: uuid description: The ID of the meal type (e.g., breakfast, lunch, dinner). quantity: type: number description: The quantity of the food consumed. unit: type: string description: The unit of measurement for the quantity (e.g., grams, oz, serving). entry_date: type: string format: date description: The date the food was consumed. entry_time: type: string description: The wall-clock local time of day the food was eaten (e.g., HH:MM). Nullable. variant_id: type: string format: uuid description: The ID of the food variant, if applicable. food_entry_meal_id: type: string format: uuid description: The ID of the food entry meal, if this entry is part of a larger meal entry. food_name: type: string description: The name of the food. brand_name: type: string description: The brand name of the food. serving_size: type: number description: The size of a single serving. serving_unit: type: string description: The unit for the serving size. calories: type: number description: The number of calories. protein: type: number carbs: type: number fat: type: number saturated_fat: type: number polyunsaturated_fat: type: number monounsaturated_fat: type: number trans_fat: type: number cholesterol: type: number sodium: type: number potassium: type: number dietary_fiber: type: number sugars: type: number vitamin_a: type: number vitamin_c: type: number calcium: type: number iron: type: number glycemic_index: type: number custom_nutrients: type: object description: A JSON object for storing custom nutrient data. FoodEntryMeal: type: object properties: id: type: string format: uuid description: The unique identifier for the food entry meal. user_id: type: string format: uuid description: The ID of the user who owns the food entry meal. meal_template_id: type: string format: uuid description: The ID of the meal template used for this entry, if any. meal_type: type: string description: The type of meal (e.g., "Breakfast", "Lunch", "Dinner"). meal_type_id: type: string format: uuid description: The ID of the meal type. entry_date: type: string format: date description: The date of the food entry meal (YYYY-MM-DD). name: type: string description: The name of the food entry meal. description: type: string description: A description of the food entry meal. foods: type: array items: type: object properties: food_id: type: string format: uuid description: The ID of the food item. quantity: type: number description: The quantity of the food item. unit: type: string description: The unit of measurement for the food item. required: - food_id - quantity - unit description: A list of food items included in the meal. quantity: type: number description: The total quantity of the meal. unit: type: string description: The unit of measurement for the meal. created_at: type: string format: date-time description: The date and time when the food entry meal was created. updated_at: type: string format: date-time description: The date and time when the food entry meal was last updated. required: - user_id - meal_type - entry_date - name - foods - quantity - unit MealPlanTemplate: type: object properties: id: type: string format: uuid description: The unique identifier for the meal plan template. user_id: type: string format: uuid description: The ID of the user who owns the meal plan template. name: type: string description: The name of the meal plan template. description: type: string description: A description of the meal plan template. day_presets: type: array items: type: object properties: day_of_week: type: string enum: - monday - tuesday - wednesday - thursday - friday - saturday - sunday description: The day of the week for this preset. meal_day_preset_id: type: string format: uuid description: The ID of the meal day preset to use for this day. required: - day_of_week - meal_day_preset_id description: The meal day presets assigned to each day of the week. created_at: type: string format: date-time description: The date and time when the meal plan template was created. updated_at: type: string format: date-time description: The date and time when the meal plan template was last updated. required: - user_id - name - day_presets NutrientGoalPreference: type: object properties: goalType: type: string enum: - minimum - maximum - target description: How progress toward this nutrient's goal should be interpreted. targetMin: type: - number - 'null' description: Lower bound of the acceptable band (only when goalType is "target"). targetMax: type: - number - 'null' description: Upper bound of the acceptable band (only when goalType is "target"). Food: type: object properties: id: type: string format: uuid description: The unique identifier for the food. user_id: type: string format: uuid description: The ID of the user who owns the food. name: type: string description: The name of the food. default_variant: $ref: '#/components/schemas/FoodVariant' description: The default nutritional variant for this food. is_public: type: boolean description: Indicates if the food is publicly available. brand: type: string description: The brand name of the food. barcode: type: string description: The barcode of the food. provider_type: type: string description: The type of provider (e.g., "mealie"). provider_external_id: type: string description: The external ID from the provider. is_custom: type: boolean description: Indicates if the food is a custom entry created by the user. shared_with_public: type: boolean description: Indicates if the food is shared with the public. is_quick_food: type: boolean description: Indicates if the food is marked for quick access. created_at: type: string format: date-time description: The date and time when the food was created. updated_at: type: string format: date-time description: The date and time when the food was last updated. required: - id - user_id - name NutritionSummary: type: object properties: total_calories: type: number description: Total calories consumed total_protein: type: number description: Total protein consumed in grams total_carbs: type: number description: Total carbohydrates consumed in grams total_fat: type: number description: Total fat consumed in grams total_dietary_fiber: type: number description: Total dietary fiber consumed in grams total_custom_nutrients: type: object additionalProperties: type: number description: Aggregated custom nutrients values securitySchemes: apiKeyAuth: type: apiKey in: header name: x-api-key description: API key authentication via x-api-key header. x-provenance: generated: '2026-08-27' method: derived source: https://github.com/CodeWithCJ/SparkyFitness — assembled from the project's own swagger-jsdoc configuration (SparkyFitnessServer/config/swagger.ts) and the 419 @swagger JSDoc blocks in SparkyFitnessServer/routes/**, using the same scan paths and the same cookieAuth->apiKeyAuth post-processing the server applies. This is the identical document a running instance serves at GET /api/api-docs/json (Swagger UI at /api/api-docs/swagger, ReDoc at /api/api-docs/redoc). note: 'Not fetched from a live host: SparkyFitness is self-hosted and the project operates no public instance, so the contract can only be read from the source that generates it. Upstream sets no operationIds; paths+methods are the stable identifiers.' upstream_version: server package.json 1.6.4 (release v1.6.4, 2026-08-27)