Edit a meal plan
Changes a meal plan made in the dashboard or through the API. days replaces every day (same shape as when creating). Send expectedUpdatedAt to avoid overwriting someone else’s newer edit. PDF plans cannot be edited.
Requires the meal_plans:write permission.
/meal-plans/{meal_plan_id}AuthorizationToken Bearer (API Key) · headerobligatorioAlmendra API key, bound to one professional account. Send it as Authorization: Bearer YOUR_API_KEY.
meal_plans:writemeal_plan_idstringobligatorioMeal plan ID
expectedUpdatedAtstring<date-time>The plan's updatedAt when you read it. If it changed since (someone edited it in the dashboard), the edit answers 409 instead of overwriting.
application/jsonnamestringstartDatestring<date>First day, in the account's time zone. Defaults to the day after the patient's last plan ends, or tomorrow.
endDatestring<date>Last day (defaults to 6 days after startDate). daily and text plans last whole weeks. When editing, a new startDate alone keeps the plan's length.
objectivestringindicationsstring[]Recommendations shown with the plan (defaults to the patient's previous plan's)
daysMealPlanDayInput[]Mostrar propiedadesOcultar propiedades
MealPlanDayInputweekdaystringdaily plans: the day of the week (each at most once). Weekdays left out are free days.
mondaytuesdaywednesdaythursdayfridaysaturdaysundaynamestringflexible and exchange plans: the model day name (defaults to "Día Modelo 1", "Día Modelo 2"… in the account's language)
isFreeDaybooleanA day without a menu (daily plans)
targetsMealPlanDayTargetsRequired unless isFreeDay
Mostrar propiedadesOcultar propiedades
caloriesKcalnumberobligatorioproteinGnumberobligatoriocarbsGnumberobligatoriofatGnumberobligatoriomealsMealPlanMealInput[]Mostrar propiedadesOcultar propiedades
MealPlanMealInputnamestringobligatoriotimestring24-hour HH:MM
commentstringcaloriesPercentagenumberShare of the day's calories this meal targets
proteinTargetGnumbercarbsTargetGnumberfatTargetGnumberoptionsobject[]daily and flexible plans. Each option is one item of the meal; in flexible plans its foods are alternatives the patient picks one of, in daily plans the patient app shows the first food of each option.
Mostrar propiedadesOcultar propiedades
objectnamestringfoodsIngredientInput[]obligatorioMostrar propiedadesOcultar propiedades
IngredientInputfoodstringobligatorioFood ID (GET /foods)
quantitynumberobligatoriounitstringGrams (g, the default) or one of the food's measures (measures[].description in GET /foods/{food_id}).
exchangesobject[]exchange plans: portions per group
Mostrar propiedadesOcultar propiedades
objectgroupstringobligatorioExchange group: an id from GET /exchange-groups or a built-in group code of the account's exchange system (e.g. CENAN-01, SMAE-06)
quantitynumberobligatorioexcludedFoodsstring[]Meal plan edited
_idstringobligatorionamestringobligatoriopatientstringobligatorioPatient ID
typestringobligatoriodaily: a menu per day; flexible: the same options every day; exchange: portions per exchange group; text: meals written as free text (meals[].text); pdf: an uploaded PDF (pdfUrl).
dailyflexibleexchangetextpdfstartDatestring<date-time>endDatestring<date-time>sentbooleanobligatorioFinished and visible to the patient in the Almendra app
objectivestringpdfUrlstringcreatedAtstring<date-time>obligatorioupdatedAtstring<date-time>obligatorioSend it back as expectedUpdatedAt when editing to avoid overwriting newer changes
indicationsstring[]obligatorioRecommendations shown to the patient with the plan
daysMealPlanDay[]obligatorioMostrar propiedadesOcultar propiedades
MealPlanDaynamestringobligatorioisFreeDaybooleanobligatoriocaloriesKcalnumberproteinGnumbercarbsGnumberfatGnumbermealsMealPlanMeal[]obligatorioMostrar propiedadesOcultar propiedades
MealPlanMealnamestringobligatoriotimestringcommentstringtextstringtext plans: the meal written as free text by the professional
caloriesPercentagenumberShare of the day's calories this meal targets (0–100)
proteinTargetGnumbercarbsTargetGnumberfatTargetGnumberoptionsMealPlanOption[]obligatorioAlternatives the patient can choose from for this meal
Mostrar propiedadesOcultar propiedades
MealPlanOptionnamestringfoodsMealPlanFood[]obligatorioMostrar propiedadesOcultar propiedades
MealPlanFoodfoodstringobligatorioFood or recipe ID
foodNamestringobligatorioquantitynumberobligatoriounitstringobligatorioexchangesMealPlanExchange[]obligatorioExchange portions (exchange meal plans)
Mostrar propiedadesOcultar propiedades
MealPlanExchangegroupstringobligatorioExchange group: the id of a stored group (GET /exchange-groups) or a built-in group code
quantitynumberobligatorioexcludedFoodsstring[]obligatorioFood IDs of the group the patient should not pick
Invalid path parameter, query parameter or request body
successbooleanobligatoriofalsemessagestringobligatorioSame as error.message.
errorobjectobligatorioMostrar propiedadesOcultar propiedades
statusintegerobligatorioHTTP status code of the response.
codestringobligatorioMachine-readable error code, stable across versions; branch on this rather than on message.
bad_requestunauthorizedforbiddennot_foundmethod_not_allowedconflictpayload_too_largeunsupported_media_typeunprocessable_entityrate_limitedinternal_errornot_implementedbad_gatewayservice_unavailablegateway_timeoutmessagestringobligatorioHuman-readable explanation of what went wrong.
Missing or invalid API key
successbooleanobligatoriofalsemessagestringobligatorioSame as error.message.
errorobjectobligatorioMostrar propiedadesOcultar propiedades
statusintegerobligatorioHTTP status code of the response.
codestringobligatorioMachine-readable error code, stable across versions; branch on this rather than on message.
bad_requestunauthorizedforbiddennot_foundmethod_not_allowedconflictpayload_too_largeunsupported_media_typeunprocessable_entityrate_limitedinternal_errornot_implementedbad_gatewayservice_unavailablegateway_timeoutmessagestringobligatorioHuman-readable explanation of what went wrong.
The account behind the API key has no active paid plan, or the key lacks the permission this operation needs
successbooleanobligatoriofalsemessagestringobligatorioSame as error.message.
errorobjectobligatorioMostrar propiedadesOcultar propiedades
statusintegerobligatorioHTTP status code of the response.
codestringobligatorioMachine-readable error code, stable across versions; branch on this rather than on message.
bad_requestunauthorizedforbiddennot_foundmethod_not_allowedconflictpayload_too_largeunsupported_media_typeunprocessable_entityrate_limitedinternal_errornot_implementedbad_gatewayservice_unavailablegateway_timeoutmessagestringobligatorioHuman-readable explanation of what went wrong.
Meal plan, food or exchange group not found
successbooleanobligatoriofalsemessagestringobligatorioSame as error.message.
errorobjectobligatorioMostrar propiedadesOcultar propiedades
statusintegerobligatorioHTTP status code of the response.
codestringobligatorioMachine-readable error code, stable across versions; branch on this rather than on message.
bad_requestunauthorizedforbiddennot_foundmethod_not_allowedconflictpayload_too_largeunsupported_media_typeunprocessable_entityrate_limitedinternal_errornot_implementedbad_gatewayservice_unavailablegateway_timeoutmessagestringobligatorioHuman-readable explanation of what went wrong.
The plan changed after expectedUpdatedAt, or it is a PDF plan
successbooleanobligatoriofalsemessagestringobligatorioSame as error.message.
errorobjectobligatorioMostrar propiedadesOcultar propiedades
statusintegerobligatorioHTTP status code of the response.
codestringobligatorioMachine-readable error code, stable across versions; branch on this rather than on message.
bad_requestunauthorizedforbiddennot_foundmethod_not_allowedconflictpayload_too_largeunsupported_media_typeunprocessable_entityrate_limitedinternal_errornot_implementedbad_gatewayservice_unavailablegateway_timeoutmessagestringobligatorioHuman-readable explanation of what went wrong.
Request body sent without Content-Type: application/json
successbooleanobligatoriofalsemessagestringobligatorioSame as error.message.
errorobjectobligatorioMostrar propiedadesOcultar propiedades
statusintegerobligatorioHTTP status code of the response.
codestringobligatorioMachine-readable error code, stable across versions; branch on this rather than on message.
bad_requestunauthorizedforbiddennot_foundmethod_not_allowedconflictpayload_too_largeunsupported_media_typeunprocessable_entityrate_limitedinternal_errornot_implementedbad_gatewayservice_unavailablegateway_timeoutmessagestringobligatorioHuman-readable explanation of what went wrong.
Rate limit exceeded (600 requests per 60 seconds); retry after Retry-After seconds
successbooleanobligatoriofalsemessagestringobligatorioSame as error.message.
errorobjectobligatorioMostrar propiedadesOcultar propiedades
statusintegerobligatorioHTTP status code of the response.
codestringobligatorioMachine-readable error code, stable across versions; branch on this rather than on message.
bad_requestunauthorizedforbiddennot_foundmethod_not_allowedconflictpayload_too_largeunsupported_media_typeunprocessable_entityrate_limitedinternal_errornot_implementedbad_gatewayservice_unavailablegateway_timeoutmessagestringobligatorioHuman-readable explanation of what went wrong.
Unexpected server error
successbooleanobligatoriofalsemessagestringobligatorioSame as error.message.
errorobjectobligatorioMostrar propiedadesOcultar propiedades
statusintegerobligatorioHTTP status code of the response.
codestringobligatorioMachine-readable error code, stable across versions; branch on this rather than on message.
bad_requestunauthorizedforbiddennot_foundmethod_not_allowedconflictpayload_too_largeunsupported_media_typeunprocessable_entityrate_limitedinternal_errornot_implementedbad_gatewayservice_unavailablegateway_timeoutmessagestringobligatorioHuman-readable explanation of what went wrong.