This section documents the weekly menu endpoints of the MiseOS API.
Weekly menus are planned by head chefs and sous chefs. A menu is created for a specific ISO week and year, then filled with slots (day + station + optional dish).
A menu slot represents a station assignment for a specific day and can optionally reference a dish from the dish bank.
Menus can be translated to multiple languages and later published for public access.
Only published menus are visible to guests.
Guests can only view published menus. Management can also view drafts.
Weekly menu lifecycle#
stateDiagram-v2
[*] --> DRAFT : menu created
DRAFT --> PUBLISHED : publish
PUBLISHED --> [*] : menu visible to guests
A menu is initially created in the DRAFT state and can be modified by management until it is published. Once published, the menu becomes visible to guests and kitchen staff without draft access.
Weekly Menus Endpoints#
| Method | URL | Auth |
|---|---|---|
GET | /weekly-menus | HEAD_CHEF, SOUS_CHEF |
GET | /weekly-menus/current | ANYONE |
GET | /weekly-menus/by-week | KITCHEN_STAFF, ANYONE |
GET | /weekly-menus/{id} | HEAD_CHEF, SOUS_CHEF |
POST | /weekly-menus | HEAD_CHEF, SOUS_CHEF |
DELETE | /weekly-menus/{id} | HEAD_CHEF, SOUS_CHEF |
POST | /weekly-menus/{id}/slots | HEAD_CHEF, SOUS_CHEF |
PUT | /weekly-menus/{id}/slots/{slotId} | HEAD_CHEF, SOUS_CHEF |
DELETE | /weekly-menus/{id}/slots/{slotId} | HEAD_CHEF, SOUS_CHEF |
POST | /weekly-menus/{id}/slots/{slotId}/translate | HEAD_CHEF, SOUS_CHEF |
POST | /weekly-menus/{id}/translate | HEAD_CHEF, SOUS_CHEF |
POST | /weekly-menus/{id}/publish | HEAD_CHEF, SOUS_CHEF |
Role-based visibility (
GET /weekly-menus/by-week)
- Guests and line cooks only see
PUBLISHEDmenus- Head chefs and sous chefs can see both
DRAFTandPUBLISHED
WeeklyMenu response object#
{
"menuId": 1,
"weekNumber": 20,
"year": 2026,
"menuStatus": "DRAFT",
"publishedAt": null,
"menuCreatedBy": {
"id": 1,
"firstName": "Gordon",
"lastName": "Ramsay"
},
"menuSlots": [
{
"menuSlotId": 1,
"dayOfWeek": "MONDAY",
"station": { "id": 1, "name": "Cold Kitchen" },
"menuDish": {
"id": 1,
"nameDA": "Røget Laks",
"nameEN": "Smoked Salmon",
"descriptionDA": "Laks med dildcreme",
"descriptionEN": "Salmon with dill cream",
"hasTranslation": true,
"allergens": []
}
}
],
"numberOfSlots": 1
}Status values: DRAFT | PUBLISHED
Day values: MONDAY | TUESDAY | WEDNESDAY | THURSDAY | FRIDAY
WeeklyMenuOverview response object#
Returned by GET /weekly-menus (lightweight list).
{
"id": 1,
"weekNumber": 20,
"year": 2026,
"menuStatus": "DRAFT",
"slotCount": 8,
"publishedAt": null
}GET /weekly-menus#
Returns weekly menu overviews. Supports optional filtering.
Query parameters
| Parameter | Type | Description |
|---|---|---|
status | String | Filter by DRAFT or PUBLISHED |
year | Integer | Filter by year |
week | Integer | Filter by ISO week number |
Example Request#
curl -H "Authorization: Bearer <token>" \
"https://miseos.corral.dk/api/v1/weekly-menus?status=PUBLISHED&year=2026&week=20"Response 200 — array of WeeklyMenuOverview objects.
GET /weekly-menus/current#
Returns the published menu for the current ISO week.
Example Request#
curl https://miseos.corral.dk/api/v1/weekly-menus/currentResponse 200 — WeeklyMenu object.
Errors
| Status | Cause |
|---|---|
404 | No published menu found for current week |
GET /weekly-menus/by-week#
Returns menu by week and year.
Query parameters
| Parameter | Type | Description |
|---|---|---|
week | Integer | ISO week number (required) |
year | Integer | Year (required) |
Example Request#
curl "https://miseos.corral.dk/api/v1/weekly-menus/by-week?week=20&year=2026"Response 200 — WeeklyMenu object.
Errors
| Status | Cause |
|---|---|
400 | Missing/invalid week or year |
404 | No menu found for requested week/year |
GET /weekly-menus/{id}#
Returns a specific weekly menu by ID.
Example Request#
curl -H "Authorization: Bearer <token>" \
https://miseos.corral.dk/api/v1/weekly-menus/5Response 200 — WeeklyMenu object.
Errors
| Status | Cause |
|---|---|
400 | Invalid ID |
404 | Menu not found |
POST /weekly-menus#
Creates a new draft menu for a specific week and year.
Request body
{
"week": 20,
"year": 2026
}Response 201 — created WeeklyMenu object.
Errors
| Status | Cause |
|---|---|
400 | Invalid week/year |
409 | Menu for that week/year already exists |
DELETE /weekly-menus/{id}#
Deletes a weekly menu.
Domain rule validation is applied by the menu entity/service (for example who can delete and menu state).
Response 204 — no content.
Errors
| Status | Cause |
|---|---|
400 | Invalid ID or delete not allowed by domain rules |
404 | Menu not found |
409 | Conflict with current menu state/business rules |
POST /weekly-menus/{id}/slots#
Adds a slot to a menu (dayOfWeek + stationId + optional dishId).
Each menu can contain multiple slots across days and stations.
Request body
{
"dayOfWeek": "MONDAY",
"stationId": 1,
"dishId": 1
}dishId is optional. If omitted/null, an empty slot is created.
Response 201 — updated WeeklyMenu object.
Errors
| Status | Cause |
|---|---|
400 | Invalid input or dish/station mismatch |
404 | Menu, station, or dish not found |
409 | Dish is inactive |
PUT /weekly-menus/{id}/slots/{slotId}#
Updates a slot dish assignment.
Request body
{
"dishId": 2
}Set dishId to null to clear the slot.
Response 200 — updated WeeklyMenu object.
Errors
| Status | Cause |
|---|---|
400 | Invalid input |
404 | Menu, slot, or dish not found |
409 | Dish is inactive |
DELETE /weekly-menus/{id}/slots/{slotId}#
Removes a slot from the menu.
Response 200 — updated WeeklyMenu object.
Errors
| Status | Cause |
|---|---|
400 | Invalid ID |
404 | Menu or slot not found |
POST /weekly-menus/{id}/slots/{slotId}/translate#
Translates the dish in a single slot.
If an unsupported or missing language code is provided, the API defaults to English (EN).
Query parameters
| Parameter | Type | Description |
|---|---|---|
lang | String | Target language code. Supported values: DA, EN, ES, IT, PT, FR, DE, PL, NL |
Example Request#
curl -X POST \
-H "Authorization: Bearer <token>" \
"https://miseos.corral.dk/api/v1/weekly-menus/5/slots/20/translate?lang=EN"Response 200 — updated WeeklyMenu object.
Errors
| Status | Cause |
|---|---|
400 | Missing/invalid lang |
404 | Menu or slot not found |
409 | Slot has no dish to translate |
POST /weekly-menus/{id}/translate#
Translates all dishes in the menu in one batch operation.
If an unsupported or missing language code is provided, the API defaults to English (EN).
Query parameters
| Parameter | Type | Description |
|---|---|---|
lang | String | Target language code. Supported values: DA, EN, ES, IT, PT, FR, DE, PL, NL |
Example Request#
curl -X POST \
-H "Authorization: Bearer <token>" \
"https://miseos.corral.dk/api/v1/weekly-menus/5/translate?lang=EN"Response 200 — updated WeeklyMenu object.
Errors
| Status | Cause |
|---|---|
400 | Missing/invalid lang |
404 | Menu not found |
502 | Translation provider error |
POST /weekly-menus/{id}/publish#
Publishes a weekly menu.
Publish validation includes:
- Menu must not be empty
- All assigned dishes must have translations
Response 200 — updated WeeklyMenu object with menuStatus: PUBLISHED.
Errors
| Status | Cause |
|---|---|
400 | Invalid ID |
404 | Menu not found |
409 | Menu is empty or has untranslated dishes |