This section documents the ingredient request endpoints of the MiseOS API.
Kitchen staff can submit ingredient requests for upcoming delivery dates. Head chefs and sous chefs can review requests and approve or reject them. Approved requests are later aggregated into shopping lists.
Ingredient request workflow#
stateDiagram-v2 [*] --> PENDING : Staff submits request PENDING --> APPROVED : Head/Sous chef approves PENDING --> REJECTED : Head/Sous chef rejects PENDING --> DELETED : Owner or Head/Sous deletes APPROVED --> [*] REJECTED --> [*] DELETED --> [*]
The diagram illustrates the lifecycle of an ingredient request, starting from submission (PENDING) to either approval, rejection, or deletion. Only pending requests can be approved or rejected, and only pending requests can be deleted by the owner or Head/Sous chefs.
Endpoints#
| Method | URL | Auth |
|---|---|---|
GET | /ingredient-requests | KITCHEN_STAFF |
GET | /ingredient-requests/{id} | KITCHEN_STAFF |
POST | /ingredient-requests | KITCHEN_STAFF |
PUT | /ingredient-requests/{id} | KITCHEN_STAFF |
DELETE | /ingredient-requests/{id} | KITCHEN_STAFF |
PATCH | /ingredient-requests/{id}/approve | HEAD_CHEF, SOUS_CHEF |
PATCH | /ingredient-requests/{id}/reject | HEAD_CHEF, SOUS_CHEF |
Visibility rule:
- Head chefs and sous chefs can see all requests
- Other kitchen staff only see their own requests
Ingredient Request response object#
The ingredient request object has the following structure:
{
"id": 1,
"name": "Frisk Dild",
"quantity": 10.0,
"unit": "BUNCH",
"preferredSupplier": "Grønttorvet",
"note": "Til laksen",
"status": "PENDING",
"requestType": "DISH_SPECIFIC",
"deliveryDate": "2026-04-01",
"requestedBy": { "id": 2, "firstName": "Claire", "lastName": "Smyth" },
"dish": { "id": 1, "dishNameDA": "Røget Laks", "dishNameEN": "Smoked Salmon" },
"reviewedAt": null,
"createdAt": "2026-03-27 10:00",
"updatedAt": null
}Status values: PENDING | APPROVED | REJECTED
Request type values: DISH_SPECIFIC | GENERAL_STOCK
Unit values: KG | G | L | ML | PCS | BUNCH | SIDES | BOX | BOTTLE | CAN
GET /ingredient-requests#
Returns ingredient requests with optional filters.
Query parameters
| Parameter | Type | Description |
|---|---|---|
status | String | Filter by request status |
deliveryDate | LocalDate | Filter by delivery date (yyyy-MM-dd) |
requestType | String | Filter by request type |
stationId | Long | Filter by station |
Response 200 — array of ingredient request objects.
Errors
| Status | Cause |
|---|---|
400 | Invalid query value (status, requestType, date format, stationId) |
GET /ingredient-requests/{id}#
Returns a single ingredient request.
Response 200 — ingredient request object.
Errors
| Status | Cause |
|---|---|
403 | User is not owner and not management |
404 | Request not found |
POST /ingredient-requests#
Creates a new ingredient request.
Validation rules:
deliveryDatecannot be in the pastdeliveryDatecannot be more than 30 days aheaddishIdis required forDISH_SPECIFIC- For non-management users, dish must belong to user’s station
- Dish must be active
Request body
{
"name": "Frisk Dild",
"quantity": 10.0,
"unit": "BUNCH",
"preferredSupplier": "Grønttorvet",
"note": "Til laksen",
"requestType": "DISH_SPECIFIC",
"deliveryDate": "2026-04-01",
"dishId": 1
}Response 201 — created ingredient request object.
Errors
| Status | Cause |
|---|---|
400 | Invalid payload, invalid date window, or missing required fields |
403 | Dish belongs to different station |
404 | Dish/user not found |
PUT /ingredient-requests/{id}#
Updates an existing request.
Rules:
- Owner or management can update
- Business rule validation is applied in domain/service layer
- Payload updates request content fields (not review action)
Request body
{
"name": "Frisk Dild",
"quantity": 8.0,
"unit": "BUNCH",
"preferredSupplier": "Grønttorvet",
"note": "Opdateret mængde",
"requestType": "DISH_SPECIFIC",
"deliveryDate": "2026-04-01",
"dishId": 1
}Response 200 — updated ingredient request object.
Errors
| Status | Cause |
|---|---|
400 | Invalid payload or date validation failure |
403 | User is not owner and not management |
404 | Request or dish not found |
409 | Request cannot be modified in current state |
DELETE /ingredient-requests/{id}#
Deletes an ingredient request.
Rules:
- Owner or management can delete
- Domain rules for deletable state are enforced
Response 204 — no content.
Errors
| Status | Cause |
|---|---|
403 | User is not owner and not management |
404 | Request not found |
409 | Request cannot be deleted in current state |
PATCH /ingredient-requests/{id}/approve#
Approves a request.
Optional payload can adjust approved quantity/note before approval.
Request body (optional)
{
"quantity": 8.0,
"note": "Reduceret mængde godkendt"
}If body is omitted, current values are kept.
Response 200 — updated ingredient request object (status: APPROVED).
Errors
| Status | Cause |
|---|---|
404 | Request not found |
409 | Request is not in approvable state |
PATCH /ingredient-requests/{id}/reject#
Rejects a request.
Response 200 — updated ingredient request object (status: REJECTED).
Errors
| Status | Cause |
|---|---|
404 | Request not found |
409 | Request is not in rejectable state |
Notifications#
These endpoints trigger WebSocket notifications:
POST /ingredient-requests→ admin pending count broadcastPATCH /ingredient-requests/{id}/approve→ direct staff notification + pending count updatePATCH /ingredient-requests/{id}/reject→ direct staff notification + pending count updateDELETE /ingredient-requests/{id}(if deleted) → pending count update