Menu items represent individual dishes or products that customers can order.
Unique identifier for the item
ID of the parent category
ID of the branch this item belongs to
ID of the parent organization
Item name (1-255 characters)
Item description (max 1000 characters)
Price in cents (min: 0). Example: 2500 = S/. 25.00
Current availability status (default: true)
Display order within category (default: 0)
Estimated preparation time in minutes (1-120)
GET /menu/items Retrieve all menu items for the current branch, optionally filtered by category
Required Permission: menu:read
Query Parameters:
Filter items by category ID
Request (all items):
curl https://api.restai.com/v1/menu/items \
-H "Authorization: Bearer <token>"
Request (filtered by category):
curl "https://api.restai.com/v1/menu/items?categoryId=a1b2c3d4-e5f6-4a5b-8c9d-0e1f2a3b4c5d" \
-H "Authorization: Bearer <token>"
Response:
{
"success" : true ,
"data" : [
{
"id" : "e5f6a7b8-c9d0-8e9f-2a3b-4c5d6e7f8a9b" ,
"category_id" : "a1b2c3d4-e5f6-4a5b-8c9d-0e1f2a3b4c5d" ,
"branch_id" : "550e8400-e29b-41d4-a716-446655440000" ,
"organization_id" : "123e4567-e89b-12d3-a456-426614174000" ,
"name" : "Tequeños" ,
"description" : "6 unidades de tequeños rellenos de queso, servidos con salsas" ,
"price" : 1800 ,
"image_url" : "https://example.com/images/tequenos.jpg" ,
"is_available" : true ,
"sort_order" : 0 ,
"preparation_time_min" : 10
},
{
"id" : "f6a7b8c9-d0e1-9f0a-3b4c-5d6e7f8a9b0c" ,
"category_id" : "a1b2c3d4-e5f6-4a5b-8c9d-0e1f2a3b4c5d" ,
"branch_id" : "550e8400-e29b-41d4-a716-446655440000" ,
"organization_id" : "123e4567-e89b-12d3-a456-426614174000" ,
"name" : "Causa Limeña" ,
"description" : "Causa rellena de pollo, palta y mayonesa" ,
"price" : 2200 ,
"image_url" : "https://example.com/images/causa.jpg" ,
"is_available" : true ,
"sort_order" : 1 ,
"preparation_time_min" : 15
}
]
}
POST /menu/items Create a new menu item
Required Permission: menu:create
Body Parameters:
ID of the category this item belongs to
Item name (1-255 characters)
Item description (max 1000 characters)
Price in cents (min: 0). Example: 2500 for S/. 25.00
URL to item image (must be valid URL)
Whether item is currently available
Display order within category (min: 0)
Estimated preparation time in minutes (1-120)
Request:
curl -X POST https://api.restai.com/v1/menu/items \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"categoryId": "b2c3d4e5-f6a7-5b6c-9d0e-1f2a3b4c5d6e",
"name": "Lomo Saltado",
"description": "Trozos de lomo salteados con cebolla, tomate y papas fritas, acompañado de arroz",
"price": 3200,
"imageUrl": "https://example.com/images/lomo-saltado.jpg",
"isAvailable": true,
"sortOrder": 0,
"preparationTimeMin": 20
}'
Response (201 Created):
{
"success" : true ,
"data" : {
"id" : "a7b8c9d0-e1f2-0a1b-4c5d-6e7f8a9b0c1d" ,
"category_id" : "b2c3d4e5-f6a7-5b6c-9d0e-1f2a3b4c5d6e" ,
"branch_id" : "550e8400-e29b-41d4-a716-446655440000" ,
"organization_id" : "123e4567-e89b-12d3-a456-426614174000" ,
"name" : "Lomo Saltado" ,
"description" : "Trozos de lomo salteados con cebolla, tomate y papas fritas, acompañado de arroz" ,
"price" : 3200 ,
"image_url" : "https://example.com/images/lomo-saltado.jpg" ,
"is_available" : true ,
"sort_order" : 0 ,
"preparation_time_min" : 20
}
}
Error Response:
// 404 Not Found - Category doesn't exist
{
"success" : false ,
"error" : {
"code" : "NOT_FOUND" ,
"message" : "Categoría no encontrada"
}
}
PATCH /menu/items/:id Update an existing menu item. All fields are optional.
Required Permission: menu:update
Path Parameters:
Body Parameters (all optional):
Move item to a different category
Item name (1-255 characters)
Item description (max 1000 characters)
Whether item is currently available
Display order within category (min: 0)
Estimated preparation time in minutes (1-120)
Request:
curl -X PATCH https://api.restai.com/v1/menu/items/a7b8c9d0-e1f2-0a1b-4c5d-6e7f8a9b0c1d \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"price": 3500,
"isAvailable": false,
"preparationTimeMin": 25
}'
Response:
{
"success" : true ,
"data" : {
"id" : "a7b8c9d0-e1f2-0a1b-4c5d-6e7f8a9b0c1d" ,
"category_id" : "b2c3d4e5-f6a7-5b6c-9d0e-1f2a3b4c5d6e" ,
"branch_id" : "550e8400-e29b-41d4-a716-446655440000" ,
"organization_id" : "123e4567-e89b-12d3-a456-426614174000" ,
"name" : "Lomo Saltado" ,
"description" : "Trozos de lomo salteados con cebolla, tomate y papas fritas, acompañado de arroz" ,
"price" : 3500 ,
"image_url" : "https://example.com/images/lomo-saltado.jpg" ,
"is_available" : false ,
"sort_order" : 0 ,
"preparation_time_min" : 25
}
}
DELETE /menu/items/:id Delete a menu item
Required Permission: menu:delete
Path Parameters:
Request:
curl -X DELETE https://api.restai.com/v1/menu/items/a7b8c9d0-e1f2-0a1b-4c5d-6e7f8a9b0c1d \
-H "Authorization: Bearer <token>"
Response:
{
"success" : true ,
"data" : {
"message" : "Item eliminado"
}
}
Get Item Modifier Groups
GET /menu/items/:id/modifier-groups Retrieve all modifier groups linked to a menu item
Required Permission: menu:read
Path Parameters:
Request:
curl https://api.restai.com/v1/menu/items/a7b8c9d0-e1f2-0a1b-4c5d-6e7f8a9b0c1d/modifier-groups \
-H "Authorization: Bearer <token>"
Response:
{
"success" : true ,
"data" : [
{
"id" : "mod-group-001" ,
"branch_id" : "550e8400-e29b-41d4-a716-446655440000" ,
"organization_id" : "123e4567-e89b-12d3-a456-426614174000" ,
"name" : "Punto de Cocción" ,
"min_selections" : 1 ,
"max_selections" : 1 ,
"is_required" : true ,
"modifiers" : [
{
"id" : "mod-001" ,
"group_id" : "mod-group-001" ,
"name" : "Término Medio" ,
"price" : 0 ,
"is_available" : true
},
{
"id" : "mod-002" ,
"group_id" : "mod-group-001" ,
"name" : "Bien Cocido" ,
"price" : 0 ,
"is_available" : true
}
]
}
]
}
Link Modifier Group to Item
POST /menu/items/:id/modifier-groups Associate a modifier group with a menu item
Required Permission: menu:update
Path Parameters:
Body Parameters:
Modifier group ID to link
Request:
curl -X POST https://api.restai.com/v1/menu/items/a7b8c9d0-e1f2-0a1b-4c5d-6e7f8a9b0c1d/modifier-groups \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"groupId": "mod-group-002"
}'
Response (201 Created):
{
"success" : true ,
"data" : {
"message" : "Grupo de modificadores vinculado"
}
}
Error Response:
// 404 Not Found
{
"success" : false ,
"error" : {
"code" : "NOT_FOUND" ,
"message" : "Item o grupo no encontrado"
}
}
Unlink Modifier Group from Item
DELETE /menu/items/:id/modifier-groups/:groupId Remove a modifier group association from a menu item
Required Permission: menu:update
Path Parameters:
Modifier group ID to unlink
Request:
curl -X DELETE https://api.restai.com/v1/menu/items/a7b8c9d0-e1f2-0a1b-4c5d-6e7f8a9b0c1d/modifier-groups/mod-group-002 \
-H "Authorization: Bearer <token>"
Response:
{
"success" : true ,
"data" : {
"message" : "Grupo desvinculado"
}
}
Price Management
Prices are stored as integers in cents:
// Converting to cents for API
const priceInSoles = 25.50 ;
const priceInCents = Math . round ( priceInSoles * 100 ); // 2550
// Converting from API for display
const apiPrice = 2550 ;
const displayPrice = apiPrice / 100 ; // 25.50
Always use integer arithmetic for prices to avoid floating-point precision errors. Store prices in cents in the database and convert to decimal only for display.
Availability Management
Quickly toggle item availability:
# Mark item as unavailable (out of stock)
curl -X PATCH https://api.restai.com/v1/menu/items/{id} \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{ "isAvailable": false }'
# Mark item as available again
curl -X PATCH https://api.restai.com/v1/menu/items/{id} \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{ "isAvailable": true }'
Use the availability flag instead of deleting items when temporarily out of stock. This preserves order history and item configuration.