Skip to main content
Menu items represent individual dishes or products that customers can order.
id
string (uuid)
Unique identifier for the item
category_id
string (uuid)
ID of the parent category
branch_id
string (uuid)
ID of the branch this item belongs to
organization_id
string (uuid)
ID of the parent organization
name
string
Item name (1-255 characters)
description
string
Item description (max 1000 characters)
price
integer
Price in cents (min: 0). Example: 2500 = S/. 25.00
image_url
string
Optional item image URL
is_available
boolean
Current availability status (default: true)
sort_order
integer
Display order within category (default: 0)
preparation_time_min
integer
Estimated preparation time in minutes (1-120)

List Menu Items

GET /menu/items

Retrieve all menu items for the current branch, optionally filtered by category
Required Permission: menu:read Query Parameters:
categoryId
string (uuid)
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
    }
  ]
}

Create Menu Item

POST /menu/items

Create a new menu item
Required Permission: menu:create Body Parameters:
categoryId
string (uuid)
required
ID of the category this item belongs to
name
string
required
Item name (1-255 characters)
description
string
Item description (max 1000 characters)
price
integer
required
Price in cents (min: 0). Example: 2500 for S/. 25.00
imageUrl
string
URL to item image (must be valid URL)
isAvailable
boolean
default:"true"
Whether item is currently available
sortOrder
integer
default:"0"
Display order within category (min: 0)
preparationTimeMin
integer
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"
  }
}

Update Menu Item

PATCH /menu/items/:id

Update an existing menu item. All fields are optional.
Required Permission: menu:update Path Parameters:
id
string (uuid)
required
Menu item ID
Body Parameters (all optional):
categoryId
string (uuid)
Move item to a different category
name
string
Item name (1-255 characters)
description
string
Item description (max 1000 characters)
price
integer
Price in cents (min: 0)
imageUrl
string
URL to item image
isAvailable
boolean
Whether item is currently available
sortOrder
integer
Display order within category (min: 0)
preparationTimeMin
integer
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 Item

DELETE /menu/items/:id

Delete a menu item
Required Permission: menu:delete Path Parameters:
id
string (uuid)
required
Menu item ID
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:
id
string (uuid)
required
Menu item ID
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
        }
      ]
    }
  ]
}

POST /menu/items/:id/modifier-groups

Associate a modifier group with a menu item
Required Permission: menu:update Path Parameters:
id
string (uuid)
required
Menu item ID
Body Parameters:
groupId
string (uuid)
required
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"
  }
}

DELETE /menu/items/:id/modifier-groups/:groupId

Remove a modifier group association from a menu item
Required Permission: menu:update Path Parameters:
id
string (uuid)
required
Menu item ID
groupId
string (uuid)
required
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.

Build docs developers (and LLMs) love