This describes internal KDS functionality. Only the 6 core KDS endpoints (tickets, expo, bump, recall, void, priority) are exposed through the API gateway.
KDS Routing Rules
Routing rules map menu items to stations, defining where each item should be prepared and how long it takes.
Create Routing Rule
Permissions Required: manager, owner, tenant_admin
POST /api/v1/kds/routing
Authorization: Bearer {access_token}
Content-Type: application/json
{
"location_id": "550e8400-e29b-41d4-a716-446655440000",
"menu_item_id": "item-burger-123",
"station_id": "station-grill-456",
"prep_time_seconds": 480,
"priority_boost": 0
}
| Field | Type | Required | Description |
|---|---|---|---|
location_id | UUID | Yes | Location this rule applies to |
menu_item_id | UUID | Yes | Menu item to route |
station_id | UUID | Yes | Target station |
prep_time_seconds | integer | Yes | Default prep time for this item |
priority_boost | integer | No | Priority boost (0 = normal) |
Response (201 Created)
{
"id": "rule-abc123",
"tenant_id": "tenant-xyz",
"location_id": "550e8400-e29b-41d4-a716-446655440000",
"menu_item_id": "item-burger-123",
"station_id": "station-grill-456",
"prep_time_seconds": 480,
"priority_boost": 0,
"created_at": "2026-01-23T12:00:00Z",
"updated_at": "2026-01-23T12:00:00Z"
}
Bulk Create Routing Rules
Create multiple routing rules in a single request.
Permissions Required: manager, owner, tenant_admin
POST /api/v1/kds/routing/bulk
Authorization: Bearer {access_token}
Content-Type: application/json
{
"rules": [
{
"location_id": "loc-123",
"menu_item_id": "burger",
"station_id": "grill",
"prep_time_seconds": 480
},
{
"location_id": "loc-123",
"menu_item_id": "fries",
"station_id": "fry",
"prep_time_seconds": 300
},
{
"location_id": "loc-123",
"menu_item_id": "caesar-salad",
"station_id": "salad",
"prep_time_seconds": 180
}
]
}
Response
{
"count": 3
}
List Routing Rules
GET /api/v1/kds/routing?location_id={location_id}
Authorization: Bearer {access_token}
Response
[
{
"id": "rule-001",
"tenant_id": "tenant-xyz",
"location_id": "loc-123",
"menu_item_id": "item-burger",
"station_id": "station-grill",
"prep_time_seconds": 480,
"priority_boost": 0,
"created_at": "2026-01-23T12:00:00Z",
"updated_at": "2026-01-23T12:00:00Z"
}
]
Delete Routing Rule
Permissions Required: manager, owner, tenant_admin
DELETE /api/v1/kds/routing/{rule_id}
Authorization: Bearer {access_token}
Response: 204 No Content
Order Routing
Route Order to KDS
Route an order to appropriate kitchen stations based on routing rules. This endpoint:
- Fetches order items
- Looks up routing rules for each menu item
- Creates tickets grouped by station
- Calls AI service for prep time prediction
- Applies course-based holding logic
POST /api/v1/kds/route-order
Authorization: Bearer {access_token}
Content-Type: application/json
{
"order_id": "order-12345",
"location_id": "loc-xyz789",
"order_reference": "Table 7",
"order_channel": "dine_in",
"customer_name": null,
"server_name": "Sarah",
"items": [
{
"menu_item_id": "item-burger",
"name": "Classic Burger",
"quantity": 2,
"modifiers": [
{
"modifier_id": "mod-cheese",
"name": "Cheddar",
"quantity": 1
}
],
"special_instructions": "Extra pickles",
"seat_number": 1,
"course": 2
}
],
"priority": "normal",
"target_time": "2026-01-23T12:30:00Z",
"metadata": {}
}
Response (201 Created)
{
"order_id": "order-12345",
"tickets_created": [
{
"id": "ticket-abc",
"station_id": "station-grill",
"status": "pending",
"items": ["..."],
"estimated_prep_time": 480
}
],
"unrouted_items": []
}
AI Prep Time Prediction
When routing orders, the system calls the Python AI service to predict prep times:
// Internal request to Python AI service
{
"tenant_id": "tenant-xyz",
"items": [
{"name": "Classic Burger", "quantity": 2, "category": "Burgers"}
],
"order_source": "dine_in",
"current_load": 0.65
}
The AI considers:
- Menu item historical prep times
- Current station load percentage
- Order source (dine-in vs takeout vs delivery)
- Time of day patterns
If AI service is unavailable, falls back to 600 seconds (10 min) default.
Course-Based Holding
Tickets for courses > 1 are created with held status until explicitly fired:
- Course 1 items:
pendingstatus (immediate) - Course 2+ items:
heldstatus (wait for fire command) - Exception:
urgentpriority overrides hold