Category Object
Categories organize menu items into groups like “Appetizers”, “Main Courses”, “Desserts”, etc.
Unique identifier for the category
ID of the branch this category belongs to
ID of the parent organization
Category name (1-255 characters)
Optional description (max 500 characters)
Optional category image URL
Display order (default: 0, lower numbers appear first)
Whether the category is visible to customers (default: true)
List Categories
GET /menu/categories
Retrieve all categories for the current branch
Required Permission: menu:read
Request:
curl https://api.restai.com/v1/menu/categories \
-H "Authorization: Bearer <token>"
Response:
{
"success": true,
"data": [
{
"id": "a1b2c3d4-e5f6-4a5b-8c9d-0e1f2a3b4c5d",
"branch_id": "550e8400-e29b-41d4-a716-446655440000",
"organization_id": "123e4567-e89b-12d3-a456-426614174000",
"name": "Entradas",
"description": "Deliciosos aperitivos para comenzar tu comida",
"image_url": "https://example.com/images/entradas.jpg",
"sort_order": 0,
"is_active": true
},
{
"id": "b2c3d4e5-f6a7-5b6c-9d0e-1f2a3b4c5d6e",
"branch_id": "550e8400-e29b-41d4-a716-446655440000",
"organization_id": "123e4567-e89b-12d3-a456-426614174000",
"name": "Platos Principales",
"description": "Nuestros mejores platos",
"image_url": "https://example.com/images/principales.jpg",
"sort_order": 1,
"is_active": true
},
{
"id": "c3d4e5f6-a7b8-6c7d-0e1f-2a3b4c5d6e7f",
"branch_id": "550e8400-e29b-41d4-a716-446655440000",
"organization_id": "123e4567-e89b-12d3-a456-426614174000",
"name": "Postres",
"description": "Dulces delicias",
"image_url": null,
"sort_order": 2,
"is_active": true
}
]
}
Create Category
POST /menu/categories
Create a new menu category
Required Permission: menu:create
Body Parameters:
Category name (1-255 characters)
Category description (max 500 characters)
URL to category image (must be valid URL)
Whether category is visible to customers
Request:
curl -X POST https://api.restai.com/v1/menu/categories \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"name": "Bebidas",
"description": "Refrescantes bebidas frías y calientes",
"imageUrl": "https://example.com/images/bebidas.jpg",
"sortOrder": 3,
"isActive": true
}'
Response (201 Created):
{
"success": true,
"data": {
"id": "d4e5f6a7-b8c9-7d8e-1f2a-3b4c5d6e7f8a",
"branch_id": "550e8400-e29b-41d4-a716-446655440000",
"organization_id": "123e4567-e89b-12d3-a456-426614174000",
"name": "Bebidas",
"description": "Refrescantes bebidas frías y calientes",
"image_url": "https://example.com/images/bebidas.jpg",
"sort_order": 3,
"is_active": true
}
}
Update Category
PATCH /menu/categories/:id
Update an existing category. All fields are optional.
Required Permission: menu:update
Path Parameters:
Body Parameters (all optional):
Category name (1-255 characters)
Category description (max 500 characters)
Whether category is visible to customers
Request:
curl -X PATCH https://api.restai.com/v1/menu/categories/d4e5f6a7-b8c9-7d8e-1f2a-3b4c5d6e7f8a \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"name": "Bebidas y Jugos",
"isActive": false
}'
Response:
{
"success": true,
"data": {
"id": "d4e5f6a7-b8c9-7d8e-1f2a-3b4c5d6e7f8a",
"branch_id": "550e8400-e29b-41d4-a716-446655440000",
"organization_id": "123e4567-e89b-12d3-a456-426614174000",
"name": "Bebidas y Jugos",
"description": "Refrescantes bebidas frías y calientes",
"image_url": "https://example.com/images/bebidas.jpg",
"sort_order": 3,
"is_active": false
}
}
Error Response:
// 404 Not Found
{
"success": false,
"error": {
"code": "NOT_FOUND",
"message": "Categoría no encontrada"
}
}
Delete Category
DELETE /menu/categories/:id
Delete a category and all its menu items
Required Permission: menu:delete
Path Parameters:
Request:
curl -X DELETE https://api.restai.com/v1/menu/categories/d4e5f6a7-b8c9-7d8e-1f2a-3b4c5d6e7f8a \
-H "Authorization: Bearer <token>"
Response:
{
"success": true,
"data": {
"message": "Categoría eliminada"
}
}
Deleting a category will cascade delete all menu items in that category due to foreign key constraints. This action cannot be undone.
Sort Order
Use the sort_order field to control the display order of categories:
[
{ "name": "Entradas", "sort_order": 0 },
{ "name": "Platos Principales", "sort_order": 1 },
{ "name": "Postres", "sort_order": 2 },
{ "name": "Bebidas", "sort_order": 3 }
]
Use increments of 10 or 100 for sort_order (0, 10, 20 or 0, 100, 200) to make it easier to insert new categories between existing ones.
Active/Inactive Categories
Use the is_active flag to temporarily hide categories without deleting them:
# Hide category from customers
curl -X PATCH https://api.restai.com/v1/menu/categories/{id} \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{ "isActive": false }'
# Show category again
curl -X PATCH https://api.restai.com/v1/menu/categories/{id} \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{ "isActive": true }'
Inactive categories and their items won’t appear in customer-facing interfaces, but remain accessible via the admin API.
Best Practices
- Keep names concise: Category names should be short and clear (e.g., “Entradas”, not “Entradas y Aperitivos Variados”)
- Use descriptions for detail: Put longer explanations in the description field
- Optimize images: Use compressed, web-optimized images for faster loading
- Logical ordering: Order categories in the sequence customers typically order (starters → mains → desserts → drinks)
- Consistent naming: Use consistent capitalization and language across all categories