> For the complete documentation index, see [llms.txt](https://mobile-calendar.gitbook.io/v1/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://mobile-calendar.gitbook.io/v1/rest-api/meals.md).

# Meals

Meal service hours (breakfast/lunch/dinner) and board plan price list — for meals reports combined with reservations.

## Get meal service hours (breakfast/lunch/dinner) and board plan price list

> Account-level meals configuration: serving hours of the three meal services (\`mealTimes.breakfast/lunch/dinner\`, HH:MM) and the price list of the 9 board plans (\`plans\`, per person per day of stay, adult/child, in \`currency\`). Plan \`code\` equals the \`meal\` field of reservations (GET /reservations) — but codes are historical, so ALWAYS read the plan's \`meals\` array instead of guessing from the name (\`DINNER\` = lunch only, \`SUPPER\` = dinner only; \`HB\` = breakfast + lunch in this system). Pricing rule: when a reservation is priced by a rate plan, meals are already INCLUDED in the rate's price (the rate's own board is the numeric \`meals\` field of GET /rates — same ids as \`plans\[].id\` here); the price list below is charged automatically only for reservations WITHOUT a rate plan. The reservation's \`meal\` field always says what board the guest has, regardless of how it was priced — use it for meal reports. How to build a meals report for a date range (same rules as the panel): for each day D take reservations with \`meal\` other than OV that stay that day (\`arrival\` <= D < \`departure\`, plus the departure day D = \`departure\`); for every service in the plan's \`meals\` add the reservation's \`adultsPortion\`/\`childrenPortion\` (NOT \`adults\`/\`children\` — portions can differ from occupancy), EXCEPT: on the departure day skip a service when the reservation's \`checkOut\` time is before the service's \`from\` (guest leaves before it starts), and on the arrival day skip a service when \`checkIn\` is after the service's \`to\` (guest arrives after it ends); treat a missing \`from\` as 00:00 and a missing \`to\` as 23:59. Count a group reservation once per group (rows sharing \`groupId\` carry the portions of the whole group). Required scope: \`meals.read\`.

```json
{"openapi":"3.0.0","info":{"title":"Public REST API v1 – mobile-calendar.com","version":"1.0.0"},"tags":[{"name":"meals","description":"Meal service hours (breakfast/lunch/dinner) and board plan price list — for meals reports combined with reservations."}],"servers":[{"url":"https://api.mobile-calendar.com/v1/public","description":"Production"}],"security":[{"bearerAuth":[]}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","description":"Pass the token in header: Authorization: Bearer <JWT>","bearerFormat":"JWT","scheme":"bearer"}},"schemas":{"MealsResponse":{"required":["data"],"properties":{"data":{"required":["configured","currency","mealTimes","plans","bookingEngineSales","lastEdit"],"properties":{"configured":{"description":"false = the account never saved the meals configuration (hours null, all prices 0).","type":"boolean"},"currency":{"description":"Account currency of the plan prices.","type":"string"},"mealTimes":{"description":"Serving hours of the three meal services.","required":["breakfast","lunch","dinner"],"properties":{"breakfast":{"$ref":"#/components/schemas/MealTime"},"lunch":{"$ref":"#/components/schemas/MealTime"},"dinner":{"$ref":"#/components/schemas/MealTime"}},"type":"object"},"plans":{"description":"All 9 board plans (always returned, also unpriced ones).","type":"array","items":{"$ref":"#/components/schemas/MealPlan"}},"bookingEngineSales":{"description":"How meals are sold in the online booking engine (guest widget).","required":["saleMode","defaultPlanCodes"],"properties":{"saleMode":{"type":"string","enum":["NONE","MANDATORY","INCLUDED_IN_PRICE","OPTIONAL","ON_SITE"]},"defaultPlanCodes":{"description":"Plans offered to guests in the booking engine.","type":"array","items":{"type":"string"}}},"type":"object"},"lastEdit":{"type":"string","format":"date-time","nullable":true}},"type":"object"},"meta":{"properties":{"plansWithPrices":{"description":"How many plans have a non-zero adult or child price.","type":"integer"}},"type":"object"}},"type":"object"},"MealTime":{"description":"Serving hours of one meal (HH:MM, property local time). Both may be null when the hotel did not configure them — when computing reports treat a missing `from` as 00:00 and a missing `to` as 23:59 (this is what the panel report does).","required":["from","to"],"properties":{"from":{"description":"Serving starts (HH:MM); null = not configured.","type":"string","nullable":true},"to":{"description":"Serving ends (HH:MM); null = not configured.","type":"string","nullable":true}},"type":"object"},"MealPlan":{"description":"One board plan. `code` is EXACTLY the value of the `meal` field of reservations (GET /reservations), `id` is the numeric `meals` field of rate plans (GET /rates). Plan codes are historical — do not guess the included meals from the code name (`DINNER` = lunch only, `SUPPER` = dinner only); always use the `meals` array. Prices apply only to reservations priced WITHOUT a rate plan — a rate plan already includes its board in the rate price.","required":["id","code","name","meals","priceAdult","priceChildren"],"properties":{"id":{"description":"Numeric plan id (panel internal).","type":"integer"},"code":{"description":"Plan code — matches `meal` on reservations.","type":"string","enum":["OV","BB","HB","FB","AI","DINNER","BREAKFAST_SUPPER","DINNER_SUPPER","SUPPER"]},"name":{"type":"string"},"meals":{"description":"Which meal services the plan includes (keys of `mealTimes`). Empty for OV (no meals).","type":"array","items":{"type":"string","enum":["breakfast","lunch","dinner"]}},"priceAdult":{"description":"Price per ADULT per day of stay, in `currency`. 0 = not priced.","type":"number","format":"float"},"priceChildren":{"description":"Price per CHILD per day of stay, in `currency`. 0 = not priced.","type":"number","format":"float"}},"type":"object"},"ApiProblem401":{"description":"Missing authentication or invalid credentials.","allOf":[{"$ref":"#/components/schemas/ApiProblemBase"},{"properties":{"type":{"description":"401 Unauthorized","type":"string","format":"uri"},"title":{"type":"string"},"status":{"type":"integer"},"detail":{"type":"string"},"instance":{"type":"string"}},"type":"object"}]},"ApiProblemBase":{"description":"RFC 7807 Problem Details (base schema).","required":["type","title","status","detail","instance"],"properties":{"type":{"description":"RFC 7807 base — DO NOT use directly in endpoints.\nIn endpoints reference ApiProblem400/401/403/409/422/429/500.","type":"string","format":"uri"},"title":{"type":"string"},"status":{"type":"integer"},"detail":{"type":"string"},"instance":{"type":"string"}},"type":"object"},"ApiProblem403":{"description":"Authenticated user but no access.","allOf":[{"$ref":"#/components/schemas/ApiProblemBase"},{"properties":{"type":{"description":"403 Forbidden","type":"string","format":"uri"},"title":{"type":"string"},"status":{"type":"integer"},"detail":{"type":"string"},"instance":{"type":"string"}},"type":"object"}]}}},"paths":{"/meals":{"get":{"tags":["meals"],"summary":"Get meal service hours (breakfast/lunch/dinner) and board plan price list","description":"Account-level meals configuration: serving hours of the three meal services (`mealTimes.breakfast/lunch/dinner`, HH:MM) and the price list of the 9 board plans (`plans`, per person per day of stay, adult/child, in `currency`). Plan `code` equals the `meal` field of reservations (GET /reservations) — but codes are historical, so ALWAYS read the plan's `meals` array instead of guessing from the name (`DINNER` = lunch only, `SUPPER` = dinner only; `HB` = breakfast + lunch in this system). Pricing rule: when a reservation is priced by a rate plan, meals are already INCLUDED in the rate's price (the rate's own board is the numeric `meals` field of GET /rates — same ids as `plans[].id` here); the price list below is charged automatically only for reservations WITHOUT a rate plan. The reservation's `meal` field always says what board the guest has, regardless of how it was priced — use it for meal reports. How to build a meals report for a date range (same rules as the panel): for each day D take reservations with `meal` other than OV that stay that day (`arrival` <= D < `departure`, plus the departure day D = `departure`); for every service in the plan's `meals` add the reservation's `adultsPortion`/`childrenPortion` (NOT `adults`/`children` — portions can differ from occupancy), EXCEPT: on the departure day skip a service when the reservation's `checkOut` time is before the service's `from` (guest leaves before it starts), and on the arrival day skip a service when `checkIn` is after the service's `to` (guest arrives after it ends); treat a missing `from` as 00:00 and a missing `to` as 23:59. Count a group reservation once per group (rows sharing `groupId` carry the portions of the whole group). Required scope: `meals.read`.","operationId":"getMeals","responses":{"200":{"description":"Meals configuration","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MealsResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiProblem401"}}}},"403":{"description":"Insufficient scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiProblem403"}}}}}}}}}
```
