Create a meal plan
Creates a complete meal plan for a patient: daily (a menu per weekday), flexible (model days of options) or exchange (model days of portions per exchange group). Foods and recipes come from GET /foods and GET /recipes; quantities are in grams unless unit names one of the food’s measures. The plan is a draft the professional can review in the dashboard; set send: true to send it to the patient right away.
Requires the meal_plans:write permission.
/meal-plansAuthorizationToken Bearer (API Key) · headerobligatorioAlmendra API key, bound to one professional account. Send it as Authorization: Bearer YOUR_API_KEY.
meal_plans:writeapplication/jsonpatient_idstringobligatorioPatient the plan is for
namestringobligatoriotypestringobligatoriodaily: a menu for each day of the week; flexible: 1 to 7 model days of options the patient chooses from; exchange: 1 to 7 model days of portions per exchange group.
dailyflexibleexchangestartDatestring<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[]obligatorioMostrar 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[]sendbooleanFinish it and send it to the patient right away (same as POST /meal-plans/{meal_plan_id}/send). Otherwise it stays a draft in the dashboard.
Meal plan created
_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.
Patient, 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.
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.