Skip to main content
Authenticated API

This endpoint requires a valid JWT Bearer token. Accessible via the API gateway at /v1/commerce/*.

Seating Optimization API

Intelligent table assignment, wait time estimation, turn time prediction, and seating analytics powered by AI.

Authentication Required

All endpoints require a valid Bearer token. See Authentication for details.

Overview

AttributeValue
Base Path/api/v1/seating
AuthenticationBearer Token
Required Rolespos_staff, host, server, bartender, cashier, chef, kitchen, manager, restaurant_manager, tenant_admin, platform_admin, system_admin, super_admin

Table Assignment

AI-Powered Optimization

The seating engine uses machine learning to optimize table assignments based on party size, customer history, reservation patterns, and real-time floor status. Confidence scores above 0.85 indicate a strong match. Always review the reasoning.factors_considered field to understand assignment logic.

Get Optimal Assignment

Get AI-recommended table assignment for a party.

POST /api/v1/seating/assign

Request Body

{
"location_id": "loc_123",
"party_size": 4,
"preferences": {
"seating_area": "patio",
"accessibility": false,
"booth_preferred": true,
"quiet_area": false
},
"reservation_id": "res_456",
"customer_id": "cust_789"
}

Response

{
"recommendation": {
"table_id": "table_12",
"table_name": "Patio 12",
"capacity": 4,
"area": "patio",
"type": "booth",
"confidence": 0.92
},
"alternatives": [
{
"table_id": "table_14",
"table_name": "Patio 14",
"capacity": 6,
"area": "patio",
"type": "table",
"confidence": 0.85,
"note": "Larger table, may affect turn time"
},
{
"table_id": "table_08",
"table_name": "Indoor 8",
"capacity": 4,
"area": "main",
"type": "booth",
"confidence": 0.78,
"note": "Indoor option if patio unavailable"
}
],
"reasoning": {
"factors_considered": [
"Party size match",
"Preference for patio seating",
"Preference for booth",
"Customer history (prefers window view)",
"Current table availability",
"Expected turn time optimization"
],
"customer_insights": {
"visit_count": 12,
"usual_table_preference": "patio",
"avg_party_size": 3.5,
"avg_spend": 145.00
}
}
}

Confirm Assignment

Confirm a table assignment.

POST /api/v1/seating/assign/confirm

Request Body

{
"location_id": "loc_123",
"table_id": "table_12",
"party_size": 4,
"reservation_id": "res_456",
"notes": "Window seat requested"
}

Response

{
"assignment_id": "assign_001",
"table_id": "table_12",
"status": "seated",
"seated_at": "2026-01-24T19:30:00Z",
"predicted_clear_time": "2026-01-24T21:00:00Z",
"server_assigned": {
"id": "emp_001",
"name": "Sarah"
}
}

Turn Time Prediction

Predict Turn Time

Predict how long a table will be occupied.

POST /api/v1/seating/turn-time/predict

Request Body

{
"location_id": "loc_123",
"table_id": "table_12",
"party_size": 4,
"meal_period": "dinner",
"day_of_week": "saturday",
"reservation_type": "special_occasion",
"customer_id": "cust_789"
}

Response

{
"prediction": {
"expected_duration_minutes": 95,
"range": {
"min_minutes": 75,
"max_minutes": 120
},
"confidence": 0.85
},
"factors": [
{
"factor": "party_size",
"impact": "+10 min",
"detail": "4-top averages 10 min longer than 2-top"
},
{
"factor": "day_of_week",
"impact": "+15 min",
"detail": "Saturday dinners run 15% longer"
},
{
"factor": "reservation_type",
"impact": "+20 min",
"detail": "Special occasions tend to linger"
},
{
"factor": "customer_history",
"impact": "-5 min",
"detail": "This customer typically dines efficiently"
}
],
"historical_comparison": {
"similar_parties_avg_minutes": 92,
"this_table_avg_minutes": 88,
"this_time_slot_avg_minutes": 95
}
}

Get Turn Time Analytics

GET /api/v1/seating/turn-time/analytics

Query Parameters

ParameterTypeDescription
location_iduuidFilter by location
periodstringtoday, week, month
areastringFilter by seating area

Response

{
"location_id": "loc_123",
"period": "week",
"summary": {
"avg_turn_time_minutes": 72,
"target_turn_time_minutes": 65,
"total_turns": 845,
"turns_per_table_avg": 4.2
},
"by_meal_period": [
{
"period": "lunch",
"avg_minutes": 48,
"turns": 320,
"target": 45
},
{
"period": "dinner",
"avg_minutes": 88,
"turns": 525,
"target": 75
}
],
"by_party_size": [
{"size": 2, "avg_minutes": 62},
{"size": 4, "avg_minutes": 78},
{"size": 6, "avg_minutes": 95}
],
"by_day": [
{"day": "monday", "avg_minutes": 65},
{"day": "friday", "avg_minutes": 82},
{"day": "saturday", "avg_minutes": 92}
],
"improvement_opportunities": [
{
"area": "dessert_timing",
"potential_savings_minutes": 8,
"suggestion": "Proactive dessert menu presentation"
},
{
"area": "check_delivery",
"potential_savings_minutes": 5,
"suggestion": "Offer check with dessert on busy nights"
}
]
}

Wait Time Estimation

Estimate Wait Time

Get accurate wait time estimate for walk-ins.

POST /api/v1/seating/wait-time/estimate

Request Body

{
"location_id": "loc_123",
"party_size": 4,
"preferences": {
"seating_area": "any",
"willing_to_split": false
}
}

Response

{
"estimate": {
"wait_time_minutes": 25,
"range": {
"min_minutes": 15,
"max_minutes": 40
},
"confidence": 0.82
},
"position_in_queue": 3,
"parties_ahead": [
{"size": 2, "wait_time_remaining_minutes": 5},
{"size": 6, "wait_time_remaining_minutes": 15},
{"size": 4, "wait_time_remaining_minutes": 20}
],
"available_tables": {
"matching_4_top": 0,
"larger_available": 1,
"note": "6-top available now if willing to take larger table"
},
"expected_turnover": [
{"table_id": "table_05", "size": 4, "expected_available_minutes": 15},
{"table_id": "table_12", "size": 4, "expected_available_minutes": 25}
],
"alternatives": {
"bar_seating": {
"available": true,
"wait_minutes": 0,
"note": "Immediate bar seating for 4"
},
"patio_different": {
"wait_minutes": 10,
"note": "High-top on patio in 10 minutes"
}
}
}

Add to Waitlist

POST /api/v1/seating/waitlist

Request Body

{
"location_id": "loc_123",
"party_size": 4,
"customer_name": "Smith",
"phone": "+15551234567",
"preferences": {
"seating_area": "patio",
"notifications": "sms"
},
"quoted_wait_minutes": 25
}

Response

{
"waitlist_id": "wait_001",
"position": 4,
"estimated_wait_minutes": 25,
"notification_method": "sms",
"confirmation_sent": true,
"tracking_url": "https://wait.example.com/w/wait_001"
}

Get Waitlist

GET /api/v1/seating/waitlist

Query Parameters

ParameterTypeDescription
location_iduuidFilter by location
statusstringwaiting, notified, seated, removed

Update Waitlist Entry

PATCH /api/v1/seating/waitlist/{waitlist_id}

Request Body

{
"status": "notified",
"notification_sent_at": "2026-01-24T19:55:00Z"
}

RevPASH Analytics

Calculate RevPASH

Calculate Revenue Per Available Seat Hour.

POST /api/v1/seating/revpash/calculate

Request Body

{
"location_id": "loc_123",
"period": {
"start": "2026-01-24T11:00:00Z",
"end": "2026-01-24T22:00:00Z"
}
}

Response

{
"revpash": {
"value": 28.50,
"currency": "USD",
"unit": "per_seat_hour"
},
"components": {
"total_revenue": 12540.00,
"total_seats": 80,
"operating_hours": 11,
"seat_hours_available": 880,
"seat_hours_utilized": 612,
"utilization_rate": 0.695
},
"by_hour": [
{"hour": "11:00", "revpash": 15.20, "utilization": 0.45},
{"hour": "12:00", "revpash": 42.80, "utilization": 0.92},
{"hour": "13:00", "revpash": 38.50, "utilization": 0.88},
{"hour": "18:00", "revpash": 52.30, "utilization": 0.98},
{"hour": "19:00", "revpash": 55.00, "utilization": 1.00}
],
"by_area": [
{"area": "main", "revpash": 32.40, "seats": 50},
{"area": "patio", "revpash": 28.80, "seats": 20},
{"area": "bar", "revpash": 18.50, "seats": 10}
],
"comparison": {
"vs_yesterday": 5.2,
"vs_last_week": -2.1,
"vs_target": 8.5
},
"optimization_opportunities": [
{
"opportunity": "off_peak_promotion",
"potential_increase": 12,
"detail": "3-5pm shows 40% seat utilization - consider happy hour promo"
},
{
"opportunity": "turn_time_improvement",
"potential_increase": 8,
"detail": "Reducing average turn time by 10 min could add 1 extra turn"
}
]
}

Get RevPASH Report

GET /api/v1/seating/revpash/report

Query Parameters

ParameterTypeDescription
location_iduuidFilter by location
start_datedatePeriod start
end_datedatePeriod end
granularitystringhour, day, week

No-Show Prediction

Predict No-Show Probability

POST /api/v1/seating/no-show/predict

Request Body

{
"reservation_id": "res_456",
"customer_id": "cust_789",
"party_size": 6,
"reservation_time": "2026-01-25T19:00:00Z",
"booking_lead_time_hours": 72
}

Response

{
"reservation_id": "res_456",
"no_show_probability": 0.15,
"risk_level": "moderate",
"factors": [
{
"factor": "party_size",
"impact": "+5%",
"detail": "Larger parties (6+) have higher no-show rate"
},
{
"factor": "lead_time",
"impact": "+3%",
"detail": "Bookings 72+ hours out have higher no-show rate"
},
{
"factor": "customer_history",
"impact": "-8%",
"detail": "Customer has 0 no-shows in 12 visits"
},
{
"factor": "day_of_week",
"impact": "+2%",
"detail": "Saturday nights have slightly higher no-show rate"
}
],
"recommendations": [
{
"action": "confirmation_call",
"timing": "24 hours before",
"reason": "Large party with moderate risk"
},
{
"action": "overbook_slight",
"detail": "Consider accepting 1 additional 2-top reservation"
}
],
"historical_stats": {
"similar_reservations_no_show_rate": 0.12,
"location_avg_no_show_rate": 0.08,
"this_customer_no_show_rate": 0.00
}
}

Get No-Show Analytics

GET /api/v1/seating/no-show/analytics

Query Parameters

ParameterTypeDescription
location_iduuidFilter by location
periodstringweek, month, quarter

Response

{
"location_id": "loc_123",
"period": "month",
"summary": {
"total_reservations": 1250,
"no_shows": 85,
"no_show_rate": 0.068,
"estimated_lost_revenue": 12750.00
},
"by_party_size": [
{"size": "1-2", "no_show_rate": 0.04},
{"size": "3-4", "no_show_rate": 0.06},
{"size": "5-6", "no_show_rate": 0.09},
{"size": "7+", "no_show_rate": 0.14}
],
"by_day_of_week": [
{"day": "friday", "no_show_rate": 0.08},
{"day": "saturday", "no_show_rate": 0.09},
{"day": "sunday", "no_show_rate": 0.05}
],
"by_booking_source": [
{"source": "website", "no_show_rate": 0.05},
{"source": "phone", "no_show_rate": 0.04},
{"source": "third_party", "no_show_rate": 0.12}
],
"mitigation_effectiveness": {
"confirmation_calls": {
"reservations_confirmed": 320,
"no_show_rate_after": 0.02
},
"deposit_required": {
"reservations_with_deposit": 85,
"no_show_rate_after": 0.01
}
}
}

Floor Plan

Get Floor Plan Status

GET /api/v1/seating/floor-plan

Query Parameters

ParameterTypeDescription
location_iduuidFilter by location

Response

{
"location_id": "loc_123",
"areas": [
{
"id": "area_main",
"name": "Main Dining",
"tables": [
{
"id": "table_01",
"name": "Table 1",
"capacity": 4,
"type": "booth",
"status": "occupied",
"party_size": 3,
"seated_at": "2026-01-24T19:15:00Z",
"estimated_clear": "2026-01-24T20:45:00Z",
"server_id": "emp_001",
"position": {"x": 100, "y": 150}
},
{
"id": "table_02",
"name": "Table 2",
"capacity": 2,
"type": "table",
"status": "available",
"position": {"x": 200, "y": 150}
}
]
}
],
"summary": {
"total_tables": 25,
"occupied": 18,
"available": 5,
"reserved": 2,
"total_capacity": 92,
"current_covers": 65
}
}

Table Status Values

StatusDescription
availableReady to seat
occupiedCurrently in use
reservedReserved for upcoming party
cleaningBeing bussed/cleaned
blockedTemporarily unavailable

Webhooks

EventDescription
seating.table_seatedParty seated at table
seating.table_clearedTable cleared and available
seating.waitlist_readyWaitlist party ready to seat
seating.no_show_detectedReservation marked as no-show
seating.turn_time_exceededTable exceeding expected turn

Error Responses

StatusCodeDescription
400invalid_party_sizeParty size exceeds capacity
400table_unavailableTable not available
404table_not_foundTable ID not found
409already_seatedReservation already seated