This section documents the dish bank endpoints of the MiseOS API.
The dish bank contains all approved dishes that can be reused when planning weekly menus.
Dishes typically originate from approved dish suggestions, but head chefs and sous chefs can also create dishes manually when needed.
Each dish stores:
- Danish and optional English names and descriptions
- associated allergens
- the originating week and year
- the kitchen station responsible for the dish
Only active dishes can be used when building weekly menus or ingredient requests.
Dish lifecycle#
flowchart LR
Suggestion["Dish Suggestion"] -->|Approved| Dish["Dish created in dish bank"]
Dish -->|Used in| Menu["Weekly Menu"]
Dish -->|Deactivate| Inactive["Inactive Dish"]
Endpoints#
| Method | URL | Auth |
|---|---|---|
GET | /dishes | HEAD_CHEF, SOUS_CHEF |
GET | /dishes/search | KITCHEN_STAFF |
GET | /dishes/available | HEAD_CHEF, SOUS_CHEF |
GET | /dishes/grouped | HEAD_CHEF, SOUS_CHEF |
GET | /dishes/{id} | KITCHEN_STAFF |
POST | /dishes | HEAD_CHEF, SOUS_CHEF |
PUT | /dishes/{id} | HEAD_CHEF, SOUS_CHEF |
PATCH | /dishes/{id}/activate | HEAD_CHEF, SOUS_CHEF |
PATCH | /dishes/{id}/deactivate | HEAD_CHEF, SOUS_CHEF |
DELETE | /dishes/{id} | HEAD_CHEF, SOUS_CHEF |
Response objects#
The dish API returns several response structures depending on the endpoint.
Dish response object#
Represents a complete dish from the dish bank.
Used by: GET /dishes, GET /dishes/{id}, POST /dishes, PUT /dishes/{id}, PATCH /dishes/{id}/activate, PATCH /dishes/{id}/deactivate
{
"id": 1,
"nameDA": "Røget Laks",
"nameEN": "Smoked Salmon",
"descriptionDA": "Laks med dildcreme og rugbrødschips",
"descriptionEN": "Salmon with dill cream and rye bread chips",
"station": { "id": 1, "name": "Cold Kitchen" },
"createdBy": { "id": 1, "firstName": "Gordon", "lastName": "Ramsay" },
"allergens": [
{ "id": 1, "nameDA": "Gluten", "nameEN": "Gluten", "displayNumber": 1 },
{ "id": 4, "nameDA": "Fisk", "nameEN": "Fish", "displayNumber": 4 }
],
"active": true,
"originWeek": 7,
"originYear": 2026,
"hasTranslations": true,
"createdAt": "2026-02-15 12:00",
"updatedAt": "2026-02-20 15:30"
}DishOption response object#
A lightweight representation used when selecting dishes for menus or browsing grouped lists.
Used by: GET /dishes/grouped, GET /dishes/available
{
"dishId": 1,
"dishName": "Røget Laks",
"dishDescription": "Laks med dildcreme og rugbrødschips",
"stationName": "Cold Kitchen",
"isActive": true
}AvailableDishes response object#
Represents dishes available for building a specific weekly menu. Separates dishes created in the requested week (thisWeekDishes) from dishes already in the bank from previous weeks (fromDishBank).
Used by: GET /dishes/available
{
"week": 20,
"year": 2026,
"thisWeekDishes": {
"Cold Kitchen": [
{
"dishId": 1,
"dishName": "Røget Laks",
"dishDescription": "Laks med dildcreme og rugbrødschips",
"stationName": "Cold Kitchen",
"isActive": true
}
]
},
"fromDishBank": {
"Hot Kitchen": [
{
"dishId": 2,
"dishName": "Bøf Bearnaise",
"dishDescription": "Oksemørbrad med hjemmelavet bearnaise",
"stationName": "Hot Kitchen",
"isActive": true
},
{
"dishId": 5,
"dishName": "Stegt Flæsk",
"dishDescription": "Med persillesovs og kartofler",
"stationName": "Hot Kitchen",
"isActive": true
}
],
"Pastry": [
{
"dishId": 9,
"dishName": "Chokolademousse",
"dishDescription": "Mørk chokolade med flødeskum",
"stationName": "Pastry",
"isActive": true
}
]
}
}GET /dishes#
Returns all dishes with optional filters. Only accessible to head chefs and sous chefs — for management and menu planning. Line cooks use GET /dishes/search.
Query parameters
| Parameter | Type | Description |
|---|---|---|
stationId | Long | Filter by station |
active | Boolean | Filter by active status |
Example request
curl -H "Authorization: Bearer <token>" \
"https://miseos.corral.dk/api/v1/dishes?stationId=1&active=true"Response 200 — array of dish objects.
[
{
"id": 1,
"nameDA": "Røget Laks",
"nameEN": "Smoked Salmon",
"descriptionDA": "Laks med dildcreme og rugbrødschips",
"descriptionEN": "Salmon with dill cream and rye bread chips",
"station": { "id": 1, "name": "Cold Kitchen" },
"createdBy": { "id": 1, "firstName": "Gordon", "lastName": "Ramsay" },
"allergens": [
{ "id": 1, "nameDA": "Gluten", "nameEN": "Gluten", "displayNumber": 1 },
{ "id": 4, "nameDA": "Fisk", "nameEN": "Fish", "displayNumber": 4 }
],
"active": true,
"originWeek": 7,
"originYear": 2026,
"hasTranslations": true,
"createdAt": "2026-02-15 12:00",
"updatedAt": "2026-02-20 15:30"
},
{
"id": 2,
"nameDA": "Bøf Bearnaise",
"nameEN": "Beef Bearnaise",
"descriptionDA": "Oksemørbrad med hjemmelavet bearnaise",
"descriptionEN": "Beef tenderloin with homemade bearnaise",
"station": { "id": 2, "name": "Hot Kitchen" },
"createdBy": { "id": 1, "firstName": "Gordon", "lastName": "Ramsay" },
"allergens": [
{ "id": 2, "nameDA": "Æg", "nameEN": "Eggs", "displayNumber": 2 },
{ "id": 7, "nameDA": "Mælk", "nameEN": "Milk", "displayNumber": 7 }
],
"active": true,
"originWeek": 6,
"originYear": 2026,
"hasTranslations": true,
"createdAt": "2026-02-10 12:00",
"updatedAt": "2026-02-18 15:30"
}
]GET /dishes/search#
Searches dishes by name in both Danish and English. Returns partial matches. Available to all kitchen staff.
Query parameters
| Parameter | Type | Description |
|---|---|---|
query | String | Search term — minimum 2 characters |
Example request
curl -H "Authorization: Bearer <token>" \
"https://miseos.corral.dk/api/v1/dishes/search?query=laks"Response 200 — array of dish objects.
Errors
| Status | Cause |
|---|---|
400 | Query is blank or fewer than 2 characters |
GET /dishes/available#
Returns dishes available for a specific week’s menu, grouped by station. Separates new dishes from that week from the existing dish bank.
Query parameters
| Parameter | Type | Description |
|---|---|---|
week | Integer | ISO week number (required) |
year | Integer | Year (required) |
Example request
curl -H "Authorization: Bearer <token>" \
"https://miseos.corral.dk/api/v1/dishes/available?week=20&year=2026"Response 200 — AvailableDishes object.
GET /dishes/grouped#
Returns all active dishes grouped by station name. Intended for menu planning — a complete overview of what is available per station.
Example request
curl -H "Authorization: Bearer <token>" \
"https://miseos.corral.dk/api/v1/dishes/grouped"Response 200
{
"Cold Kitchen": [
{
"dishId": 1,
"dishName": "Røget Laks",
"dishDescription": "Laks med dildcreme og rugbrødschips",
"stationName": "Cold Kitchen",
"isActive": true
},
{
"dishId": 4,
"dishName": "Roastbeef",
"dishDescription": "Roastbeef med remoulade og sprøde løg",
"stationName": "Cold Kitchen",
"isActive": true
}
],
"Hot Kitchen": [
{
"dishId": 2,
"dishName": "Bøf Bearnaise",
"dishDescription": "Oksemørbrad med hjemmelavet bearnaise",
"stationName": "Hot Kitchen",
"isActive": true
},
{
"dishId": 3,
"dishName": "Tarteletter",
"dishDescription": "Høns i asparges",
"stationName": "Hot Kitchen",
"isActive": true
},
{
"dishId": 5,
"dishName": "Stegt Flæsk",
"dishDescription": "Med persillesovs og kartofler",
"stationName": "Hot Kitchen",
"isActive": true
}
],
"Pastry": [
{
"dishId": 9,
"dishName": "Chokolademousse",
"dishDescription": "Mørk chokolade med flødeskum",
"stationName": "Pastry",
"isActive": true
}
]
}GET /dishes/{id}#
Returns a single dish by ID. Available to all kitchen staff.
Example request
curl -H "Authorization: Bearer <token>" \
"https://miseos.corral.dk/api/v1/dishes/1"Response 200 — dish object.
Errors
| Status | Cause |
|---|---|
400 | ID is not a positive number |
404 | Dish not found |
POST /dishes#
Creates a new dish manually. The dish is assigned the current week and year as its origin and is active by default.
Example request
curl -X POST \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"nameDA": "Grillet Kylling",
"descriptionDA": "Serveret med citron og timian",
"stationId": 2,
"allergenIds": [1, 3]
}' \
"https://miseos.corral.dk/api/v1/dishes"Request body
{
"nameDA": "Grillet Kylling",
"descriptionDA": "Serveret med citron og timian",
"stationId": 2,
"allergenIds": [1, 3]
}allergenIds is optional — omit or send an empty array for a dish with no allergens.
Response 201 — created dish object.
Errors
| Status | Cause |
|---|---|
404 | Station not found |
PUT /dishes/{id}#
Updates a dish. English fields are optional — set to null if no translation exists yet.
Example request
curl -X PUT \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"nameDA": "Grillet Kylling",
"descriptionDA": "Serveret med citron og timian",
"nameEN": "Grilled Chicken",
"descriptionEN": "Served with lemon and thyme",
"allergenIds": [1]
}' \
"https://miseos.corral.dk/api/v1/dishes/7"Request body
{
"nameDA": "Grillet Kylling",
"descriptionDA": "Serveret med citron og timian",
"nameEN": "Grilled Chicken",
"descriptionEN": "Served with lemon and thyme",
"allergenIds": [1]
}Response 200 — updated dish object.
Errors
| Status | Cause |
|---|---|
404 | Dish not found |
PATCH /dishes/{id}/activate#
Reactivates a previously deactivated dish. The dish becomes available again for menus and ingredient requests.
Example request
curl -X PATCH \
-H "Authorization: Bearer <token>" \
"https://miseos.corral.dk/api/v1/dishes/6/activate"Response 200 — updated dish object with active: true.
PATCH /dishes/{id}/deactivate#
Deactivates a dish. Deactivated dishes cannot be added to menus or ingredient requests but remain in the system for historical reference. Prefer deactivation over deletion when the dish has been used in menus.
Example request
curl -X PATCH \
-H "Authorization: Bearer <token>" \
"https://miseos.corral.dk/api/v1/dishes/6/deactivate"Response 200 — updated dish object with active: false.
DELETE /dishes/{id}#
Permanently deletes a dish. Fails if the dish is used in any weekly menu — use deactivate instead.
Example request
curl -X DELETE \
-H "Authorization: Bearer <token>" \
"https://miseos.corral.dk/api/v1/dishes/10"Response 204 — no content.
Errors
| Status | Cause |
|---|---|
404 | Dish not found |
409 | Dish is used in one or more weekly menus |