This endpoint requires a valid JWT Bearer token. Accessible via the API gateway at /v1/commerce/*.
Bar & Beverage API
Manage bar operations, drink orders, tab management, pour tracking, and beverage inventory.
All endpoints require a valid Bearer token. See Authentication for details.
Overview
| Attribute | Value |
|---|---|
| Base Path | /api/v1/bar |
| Authentication | Bearer Token |
| Required Roles | bartender, server, pos_staff, restaurant_staff, restaurant_manager, tenant_admin, platform_admin, system_admin, super_admin |
Tab Management
Open Tab
Open a new bar tab.
POST /api/v1/bar/tabs
Request Body
{
"location_id": "loc_123",
"customer_name": "John D.",
"seat_number": "B5",
"card_on_file": {
"payment_method_id": "pm_abc123",
"preauth_amount": 100.00
},
"bartender_id": "emp_001"
}
Response
{
"tab_id": "tab_xyz",
"tab_number": "T-042",
"customer_name": "John D.",
"seat_number": "B5",
"status": "open",
"preauth_amount": 100.00,
"preauth_id": "pi_abc",
"bartender": {
"id": "emp_001",
"name": "Mike"
},
"opened_at": "2026-01-24T21:00:00Z"
}
Get Tab
Retrieve tab details.
GET /api/v1/bar/tabs/{tab_id}
Response
{
"tab_id": "tab_xyz",
"tab_number": "T-042",
"customer_name": "John D.",
"seat_number": "B5",
"status": "open",
"items": [
{
"id": "item_001",
"name": "Old Fashioned",
"quantity": 1,
"price": 14.00,
"modifiers": ["Bulleit Bourbon"],
"added_at": "2026-01-24T21:05:00Z"
},
{
"id": "item_002",
"name": "IPA Draft",
"quantity": 2,
"price": 8.00,
"added_at": "2026-01-24T21:15:00Z"
}
],
"subtotal": 30.00,
"tax": 2.70,
"total": 32.70,
"preauth_amount": 100.00,
"opened_at": "2026-01-24T21:00:00Z"
}
List Open Tabs
Get all open tabs.
GET /api/v1/bar/tabs
Query Parameters
| Parameter | Type | Description |
|---|---|---|
location_id | uuid | Filter by location |
status | string | open, pending_close, closed |
bartender_id | string | Filter by bartender |
Add to Tab
Add items to an open tab.
POST /api/v1/bar/tabs/{tab_id}/items
Request Body
{
"menu_item_id": "drink_001",
"quantity": 1,
"modifiers": [
{"modifier_id": "mod_premium", "name": "Bulleit Bourbon"}
],
"notes": "Light ice"
}
Transfer Tab
Transfer tab to different seat or bartender.
POST /api/v1/bar/tabs/{tab_id}/transfer
Request Body
{
"new_seat": "B8",
"new_bartender_id": "emp_002",
"reason": "Customer moved"
}
Split Tab
Split tab into multiple checks.
POST /api/v1/bar/tabs/{tab_id}/split
Request Body
{
"split_type": "by_items",
"splits": [
{
"customer_name": "John",
"item_ids": ["item_001", "item_002"]
},
{
"customer_name": "Jane",
"item_ids": ["item_003", "item_004"]
}
]
}
Close Tab
Close and settle a tab.
POST /api/v1/bar/tabs/{tab_id}/close
Request Body
{
"payment_method": "card_on_file",
"tip_amount": 6.00,
"print_receipt": true
}
Response
{
"tab_id": "tab_xyz",
"status": "closed",
"subtotal": 30.00,
"tax": 2.70,
"tip": 6.00,
"total_charged": 38.70,
"payment_id": "pay_xyz",
"receipt_url": "https://...",
"closed_at": "2026-01-24T23:30:00Z"
}
Drink Orders
Send to Bar
Send drink orders to bar station.
POST /api/v1/bar/orders
Request Body
{
"order_id": "ord_abc",
"table_number": "T12",
"server_id": "emp_005",
"items": [
{
"menu_item_id": "drink_001",
"name": "Margarita",
"quantity": 2,
"modifiers": ["No Salt"],
"seat_numbers": [1, 2]
}
],
"priority": "normal"
}
Get Bar Queue
View pending drink orders.
GET /api/v1/bar/queue
Response
{
"data": [
{
"id": "barorder_001",
"order_id": "ord_abc",
"table_number": "T12",
"server_name": "Sarah",
"status": "making",
"items": [
{
"name": "Margarita",
"quantity": 2,
"modifiers": ["No Salt"],
"status": "making"
}
],
"elapsed_seconds": 120,
"created_at": "2026-01-24T21:30:00Z"
}
],
"summary": {
"pending": 3,
"making": 2,
"ready": 1
}
}
Update Order Status
Progress drink order.
PATCH /api/v1/bar/orders/{order_id}/status
Request Body
{
"status": "ready"
}
Order Status Values
| Status | Description |
|---|---|
pending | Waiting to make |
making | Being prepared |
ready | Ready for pickup |
delivered | Given to server |
Pour Tracking
Record Pour
Log a pour from a bottle.
POST /api/v1/bar/pours
Request Body
{
"bottle_id": "bottle_001",
"drink_id": "drink_001",
"pour_size_oz": 2.0,
"bartender_id": "emp_001",
"tab_id": "tab_xyz"
}
Get Pour Data
Retrieve pour history.
GET /api/v1/bar/pours
Query Parameters
| Parameter | Type | Description |
|---|---|---|
location_id | uuid | Filter by location |
bottle_id | string | Specific bottle |
bartender_id | string | Filter by bartender |
start_time | datetime | Period start |
end_time | datetime | Period end |
Response
{
"data": [
{
"id": "pour_001",
"bottle_id": "bottle_001",
"bottle_name": "Grey Goose Vodka",
"pour_size_oz": 1.5,
"drink_name": "Vodka Soda",
"bartender_name": "Mike",
"tab_number": "T-042",
"timestamp": "2026-01-24T21:45:00Z"
}
],
"summary": {
"total_pours": 45,
"total_oz": 67.5,
"total_revenue": 585.00
}
}
Bottle Inventory
List Bottles
Get bar bottle inventory.
GET /api/v1/bar/bottles
Response
{
"data": [
{
"id": "bottle_001",
"name": "Grey Goose Vodka",
"category": "vodka",
"size_ml": 750,
"remaining_ml": 450,
"remaining_percent": 60,
"cost": 35.00,
"status": "active",
"opened_at": "2026-01-20T18:00:00Z",
"location": "Well 1"
}
]
}
Add Bottle
Add new bottle to inventory.
POST /api/v1/bar/bottles
Request Body
{
"product_id": "prod_vodka_001",
"location_id": "loc_123",
"bar_location": "Well 1",
"cost": 35.00
}
Update Bottle Level
Record bottle level.
PATCH /api/v1/bar/bottles/{bottle_id}
Request Body
{
"remaining_ml": 300,
"notes": "End of shift count"
}
Mark Empty
Mark bottle as empty.
POST /api/v1/bar/bottles/{bottle_id}/empty
Recipes
List Recipes
Get drink recipes.
GET /api/v1/bar/recipes
Response
{
"data": [
{
"id": "recipe_001",
"name": "Old Fashioned",
"category": "whiskey_cocktails",
"ingredients": [
{"item": "Bourbon", "amount_oz": 2.0, "required": true},
{"item": "Simple Syrup", "amount_oz": 0.25, "required": true},
{"item": "Angostura Bitters", "dashes": 2, "required": true},
{"item": "Orange Peel", "amount": "1", "required": false}
],
"instructions": [
"Add simple syrup and bitters to glass",
"Add ice and bourbon",
"Stir gently",
"Express orange peel and garnish"
],
"glassware": "rocks",
"cost": 3.50,
"menu_price": 14.00,
"image_url": "https://..."
}
]
}
Create Recipe
Add a new drink recipe.
POST /api/v1/bar/recipes
Analytics
Get Bar Analytics
GET /api/v1/bar/analytics
Query Parameters
| Parameter | Type | Description |
|---|---|---|
location_id | uuid | Restaurant location |
start_date | date | Analysis start |
end_date | date | Analysis end |
Response
{
"period": {
"start": "2026-01-24",
"end": "2026-01-24"
},
"sales": {
"total_revenue": 3250.00,
"total_drinks": 185,
"avg_drink_price": 17.57,
"tabs_opened": 42,
"avg_tab_total": 77.38
},
"top_drinks": [
{"name": "Margarita", "count": 28, "revenue": 392.00},
{"name": "Old Fashioned", "count": 22, "revenue": 308.00},
{"name": "IPA Draft", "count": 45, "revenue": 360.00}
],
"by_category": [
{"category": "cocktails", "count": 85, "revenue": 1190.00},
{"category": "beer", "count": 62, "revenue": 496.00},
{"category": "wine", "count": 38, "revenue": 456.00}
],
"by_hour": [
{"hour": 17, "count": 25, "revenue": 350.00},
{"hour": 18, "count": 42, "revenue": 588.00},
{"hour": 21, "count": 55, "revenue": 935.00}
],
"pour_cost": {
"total_pour_cost": 780.00,
"pour_cost_percent": 24.0
},
"bartender_performance": [
{
"bartender_id": "emp_001",
"name": "Mike",
"drinks_made": 95,
"revenue": 1650.00,
"avg_make_time_seconds": 120
}
]
}
Age Verification
Age verification is required by law before serving alcohol. All age check records are audit-logged and non-deletable. Failure to verify age may result in legal liability.
Log Age Check
Record age verification.
POST /api/v1/bar/age-verification
Request Body
{
"tab_id": "tab_xyz",
"method": "id_scan",
"date_of_birth": "1990-05-15",
"verified": true,
"employee_id": "emp_001"
}
Webhooks
| Event | Description |
|---|---|
bar.tab_opened | New tab opened |
bar.tab_closed | Tab settled |
bar.order_received | Drink order sent to bar |
bar.order_ready | Drinks ready |
bar.low_inventory | Bottle inventory low |
bar.high_tab_alert | Tab exceeds threshold |
Error Responses
| Status | Code | Description |
|---|---|---|
| 400 | tab_already_closed | Tab is closed |
| 400 | preauth_declined | Card preauth failed |
| 400 | age_not_verified | Age verification required |
| 404 | tab_not_found | Tab ID not found |
| 409 | insufficient_preauth | Tab exceeds preauth |
Related Documentation
- Bar Operations Guide - Manager guide
- Orders API - Order management
- Inventory API - Inventory tracking