Authenticated API
This endpoint requires a valid JWT Bearer token. Accessible via the API gateway at /v1/commerce/*.
Modifiers API
Manage menu item modifiers, customization options, modifier groups, and pricing rules.
Authentication Required
All endpoints require a valid Bearer token with menu:read or menu:write scopes. See Authentication for details.
Overview
| Attribute | Value |
|---|---|
| Base Path | /api/v1/modifiers |
| Authentication | Bearer Token |
| Required Roles | pos_staff, server, restaurant_staff, restaurant_manager, kitchen, host, tenant_admin, platform_admin, system_admin, super_admin |
Modifier Groups
List Modifier Groups
GET /api/v1/modifiers/groups
Query Parameters
| Parameter | Type | Description |
|---|---|---|
location_id | uuid | Filter by location |
status | string | active, inactive |
type | string | single, multiple, nested |
Response
{
"modifier_groups": [
{
"id": "modgrp_001",
"name": "Steak Temperature",
"display_name": "How would you like it cooked?",
"type": "single",
"required": true,
"min_selections": 1,
"max_selections": 1,
"modifiers": [
{"id": "mod_001", "name": "Rare", "price": 0},
{"id": "mod_002", "name": "Medium Rare", "price": 0, "default": true},
{"id": "mod_003", "name": "Medium", "price": 0},
{"id": "mod_004", "name": "Medium Well", "price": 0},
{"id": "mod_005", "name": "Well Done", "price": 0}
],
"applies_to_items": 5,
"status": "active"
},
{
"id": "modgrp_002",
"name": "Pizza Toppings",
"display_name": "Add Extra Toppings",
"type": "multiple",
"required": false,
"min_selections": 0,
"max_selections": 10,
"pricing_type": "per_modifier",
"modifiers": [
{"id": "mod_010", "name": "Pepperoni", "price": 2.00},
{"id": "mod_011", "name": "Mushrooms", "price": 1.50},
{"id": "mod_012", "name": "Extra Cheese", "price": 2.50},
{"id": "mod_013", "name": "Jalapeños", "price": 1.00}
],
"applies_to_items": 8,
"status": "active"
},
{
"id": "modgrp_003",
"name": "Burger Build",
"display_name": "Build Your Burger",
"type": "nested",
"required": true,
"sub_groups": [
{
"id": "subgrp_001",
"name": "Patty",
"required": true,
"max_selections": 1
},
{
"id": "subgrp_002",
"name": "Cheese",
"required": false,
"max_selections": 2
},
{
"id": "subgrp_003",
"name": "Toppings",
"required": false,
"max_selections": 10
}
],
"status": "active"
}
],
"total": 15
}
Create Modifier Group
POST /api/v1/modifiers/groups
Request Body
{
"name": "Side Choice",
"display_name": "Choose Your Side",
"type": "single",
"required": true,
"min_selections": 1,
"max_selections": 1,
"modifiers": [
{"name": "French Fries", "price": 0, "default": true},
{"name": "Sweet Potato Fries", "price": 1.50},
{"name": "Side Salad", "price": 0},
{"name": "Onion Rings", "price": 2.00},
{"name": "Coleslaw", "price": 0}
],
"display_order": 1,
"locations": ["loc_123"]
}
Response
{
"id": "modgrp_004",
"name": "Side Choice",
"status": "active",
"modifiers_created": 5,
"created_at": "2026-01-24T19:30:00Z"
}
Get Modifier Group
GET /api/v1/modifiers/groups/{group_id}
Response
{
"id": "modgrp_002",
"name": "Pizza Toppings",
"display_name": "Add Extra Toppings",
"description": "Customize your pizza with additional toppings",
"type": "multiple",
"required": false,
"min_selections": 0,
"max_selections": 10,
"pricing_type": "per_modifier",
"free_modifiers": 0,
"modifiers": [
{
"id": "mod_010",
"name": "Pepperoni",
"price": 2.00,
"calories": 140,
"allergens": [],
"available": true,
"display_order": 1
},
{
"id": "mod_011",
"name": "Mushrooms",
"price": 1.50,
"calories": 20,
"allergens": [],
"dietary": ["vegetarian", "vegan"],
"available": true,
"display_order": 2
},
{
"id": "mod_012",
"name": "Extra Cheese",
"price": 2.50,
"calories": 110,
"allergens": ["dairy"],
"dietary": ["vegetarian"],
"available": true,
"display_order": 3
}
],
"applies_to": [
{"item_id": "item_001", "item_name": "Margherita Pizza"},
{"item_id": "item_002", "item_name": "Pepperoni Pizza"}
],
"locations": ["loc_123", "loc_456"],
"status": "active",
"created_at": "2025-06-01T00:00:00Z",
"updated_at": "2026-01-20T00:00:00Z"
}
Update Modifier Group
PUT /api/v1/modifiers/groups/{group_id}
Delete Modifier Group
Deleting Modifier Groups
Deleting a modifier group will remove it from all associated menu items. This cannot be undone. Check the applies_to field before deleting to understand which items will be affected.
DELETE /api/v1/modifiers/groups/{group_id}
Modifiers
List Modifiers
GET /api/v1/modifiers
Query Parameters
| Parameter | Type | Description |
|---|---|---|
group_id | uuid | Filter by group |
available | boolean | Filter by availability |
search | string | Search modifier name |
Response
{
"modifiers": [
{
"id": "mod_010",
"group_id": "modgrp_002",
"group_name": "Pizza Toppings",
"name": "Pepperoni",
"price": 2.00,
"available": true,
"usage_count_30d": 1250
}
],
"total": 85
}
Create Modifier
POST /api/v1/modifiers
Request Body
{
"group_id": "modgrp_002",
"name": "Bacon",
"price": 2.50,
"calories": 180,
"allergens": [],
"dietary": [],
"description": "Crispy bacon strips",
"available": true,
"display_order": 10,
"sku": "TOP-BACON"
}
Get Modifier
GET /api/v1/modifiers/{modifier_id}
Response
{
"id": "mod_010",
"group_id": "modgrp_002",
"name": "Pepperoni",
"display_name": "Pepperoni",
"description": "Classic pepperoni slices",
"price": 2.00,
"cost": 0.45,
"calories": 140,
"allergens": [],
"dietary": [],
"nutrition": {
"fat": 12,
"protein": 6,
"carbs": 1,
"sodium": 480
},
"available": true,
"availability_schedule": null,
"inventory_tracking": {
"enabled": true,
"current_quantity": 500,
"low_threshold": 100
},
"image_url": "https://...",
"display_order": 1,
"sku": "TOP-PEPP",
"external_ids": {
"pos_id": "12345"
},
"usage": {
"count_30d": 1250,
"revenue_30d": 2500.00
},
"created_at": "2025-06-01T00:00:00Z"
}
Update Modifier
PUT /api/v1/modifiers/{modifier_id}
Update Modifier Availability
PATCH /api/v1/modifiers/{modifier_id}/availability
Request Body
{
"available": false,
"reason": "out_of_stock",
"restore_at": "2026-01-25T08:00:00Z"
}
Delete Modifier
DELETE /api/v1/modifiers/{modifier_id}
Item Modifier Assignments
Get Item Modifiers
GET /api/v1/modifiers/items/{item_id}
Response
{
"item_id": "item_001",
"item_name": "Ribeye Steak",
"modifier_groups": [
{
"group_id": "modgrp_001",
"name": "Steak Temperature",
"required": true,
"display_order": 1,
"overrides": null
},
{
"group_id": "modgrp_004",
"name": "Side Choice",
"required": true,
"display_order": 2,
"overrides": {
"excluded_modifiers": ["mod_025"],
"price_adjustments": [
{"modifier_id": "mod_022", "price": 3.00}
]
}
},
{
"group_id": "modgrp_005",
"name": "Add-Ons",
"required": false,
"display_order": 3,
"overrides": null
}
]
}
Assign Modifier Groups to Item
POST /api/v1/modifiers/items/{item_id}/groups
Request Body
{
"assignments": [
{
"group_id": "modgrp_001",
"required": true,
"display_order": 1
},
{
"group_id": "modgrp_004",
"required": true,
"display_order": 2,
"overrides": {
"excluded_modifiers": ["mod_025"],
"price_adjustments": [
{"modifier_id": "mod_022", "price": 3.00}
]
}
}
]
}
Remove Modifier Group from Item
DELETE /api/v1/modifiers/items/{item_id}/groups/{group_id}
Pricing Rules
Get Pricing Rules
GET /api/v1/modifiers/pricing-rules
Response
{
"rules": [
{
"id": "rule_001",
"name": "Free First Topping",
"type": "free_quantity",
"applies_to": {
"group_ids": ["modgrp_002"]
},
"conditions": {
"free_count": 1
},
"status": "active"
},
{
"id": "rule_002",
"name": "Premium Upcharge",
"type": "size_based",
"applies_to": {
"group_ids": ["modgrp_002"]
},
"conditions": {
"size_multipliers": {
"small": 1.0,
"medium": 1.5,
"large": 2.0
}
},
"status": "active"
},
{
"id": "rule_003",
"name": "Half/Half Pricing",
"type": "portion_based",
"applies_to": {
"item_categories": ["pizza"]
},
"conditions": {
"half_price_multiplier": 0.5
},
"status": "active"
}
]
}
Create Pricing Rule
POST /api/v1/modifiers/pricing-rules
Request Body
{
"name": "Buy 2 Get 1 Free Toppings",
"type": "quantity_discount",
"applies_to": {
"group_ids": ["modgrp_002"]
},
"conditions": {
"buy_quantity": 2,
"free_quantity": 1
},
"locations": ["loc_123"]
}
Bulk Operations
Bulk Update Availability
POST /api/v1/modifiers/bulk/availability
Request Body
{
"updates": [
{"modifier_id": "mod_010", "available": false},
{"modifier_id": "mod_011", "available": false},
{"modifier_id": "mod_012", "available": true}
],
"reason": "inventory_adjustment"
}
Bulk Update Prices
POST /api/v1/modifiers/bulk/prices
Request Body
{
"updates": [
{"modifier_id": "mod_010", "price": 2.50},
{"modifier_id": "mod_011", "price": 2.00}
],
"effective_date": "2026-02-01"
}
Copy Modifier Group
POST /api/v1/modifiers/groups/{group_id}/copy
Request Body
{
"new_name": "Pizza Toppings (Downtown)",
"target_locations": ["loc_456"],
"include_pricing_rules": true
}
Webhooks
| Event | Description |
|---|---|
modifier.created | New modifier created |
modifier.updated | Modifier updated |
modifier.availability_changed | Availability changed |
modifier_group.created | New group created |
modifier_group.updated | Group updated |
Error Responses
| Status | Code | Description |
|---|---|---|
| 400 | invalid_selection | Selection violates min/max rules |
| 400 | modifier_unavailable | Modifier not available |
| 404 | modifier_not_found | Modifier ID not found |
| 404 | group_not_found | Group ID not found |
| 409 | modifier_in_use | Cannot delete modifier in use |
Related Documentation
- Menus API - Menu management
- Orders API - Order processing
- Inventory API - Inventory tracking