Skip to main content

Menu Schema

This document describes the menu data structure used in menu push and pull operations.

Store Menu (Root Object)

interface StoreMenu {
reference: string; // Reference ID for tracking
store: {
merchant_supplied_id: string; // Store ID
provider_type: string; // Platform identifier
};
open_hours: StoreOpenHour[]; // Business hours
special_hours: StoreSpecialHour[]; // Holiday/special hours
menu: Menu; // Menu content
}

interface Menu {
name: string; // Menu name (displayed in portal and sent to platforms)
subtitle: string; // Menu subtitle/description
merchant_supplied_id: string; // Unique menu ID
active: boolean; // Whether menu is active
categories: Category[]; // Menu categories
}

Category

interface Category {
merchant_supplied_id: string; // Unique category ID
name: string; // Category name (e.g., "Appetizers")
subtitle: string; // Category description (customer-facing on platforms)
sort_id?: number; // Display order (lower = first)
active?: boolean; // Whether category is active (default: true)
items: Item[]; // Items in this category
}

Item

interface Item {
merchant_supplied_id: string; // Unique item ID
name: string; // Item name
description?: string; // Item description
original_image_url: string; // Item image URL
price: number; // Base price in cents
base_price?: number; // Alternative base price
tax_rate?: string; // Tax rate (e.g., "0.08875")
is_alcohol?: boolean; // Contains alcohol
is_bike_friendly?: boolean; // Safe for bike delivery
sort_id?: number; // Display order
active?: boolean; // Whether item is active (default: true)
operation_context?: string[]; // Operating contexts
item_special_hours?: ItemSpecialHour[]; // Time-based availability
extras: ItemExtra[]; // Modifier groups
}

Item Extra (Modifier Group)

interface ItemExtra {
merchant_supplied_id: string; // Modifier group ID
name: string; // Group name (e.g., "Choose Size")
description?: string; // Group description
sort_id?: number; // Display order
active?: boolean; // Whether group is active

// Quantity constraints
min_num_options?: number; // Minimum options to select
max_num_options?: number; // Maximum options to select
num_free_options?: number; // Free options before charging
min_option_choice_quantity?: number; // Min quantity per option
max_option_choice_quantity?: number; // Max quantity per option
min_aggregate_options_quantity?: number; // Min total across all options
max_aggregate_options_quantity?: number; // Max total across all options

options: ItemExtraOption[]; // Available options
}

Item Extra Option (Modifier)

interface ItemExtraOption {
merchant_supplied_id: string; // Modifier ID
name: string; // Modifier name (e.g., "Extra Cheese")
description?: string; // Modifier description
price: number; // Price in cents
base_price?: number; // Alternative base price
tax_rate?: string; // Tax rate
default?: boolean; // Pre-selected option
sort_id?: number; // Display order
active?: boolean; // Whether option is active
operation_context?: string[]; // Operating contexts
item_extra_option_special_hours?: ItemSpecialHour[];
quantity_info?: {
default_quantity?: number; // Default quantity
charge_above?: number; // Free quantity threshold
};
extras?: ItemExtra[]; // Nested modifier groups
}

Store Open Hours

interface StoreOpenHour {
day_index: DayOfWeek; // Day of week
start_time: string; // HH:MM:SS format
end_time: string; // HH:MM:SS format
}

type DayOfWeek = 'MON' | 'TUE' | 'WED' | 'THU' | 'FRI' | 'SAT' | 'SUN';

Store Special Hours

interface StoreSpecialHour {
date: string; // YYYY-MM-DD format
closed: boolean; // true = closed all day
start_time: string; // HH:MM:SS (if not closed)
end_time: string; // HH:MM:SS (if not closed)
}

Item Special Hours

interface ItemSpecialHour {
day_index: DayOfWeek; // Day of week
start_time: string; // HH:MM:SS format
end_time: string; // HH:MM:SS format
start_date: string; // Start date (ISO 8601)
end_date: string; // End date (ISO 8601)
}

Example Menu

{
"reference": "store-123-main-menu",
"store": {
"merchant_supplied_id": "store-123",
"provider_type": "your_platform"
},
"open_hours": [
{ "day_index": "MON", "start_time": "11:00:00", "end_time": "22:00:00" },
{ "day_index": "TUE", "start_time": "11:00:00", "end_time": "22:00:00" },
{ "day_index": "WED", "start_time": "11:00:00", "end_time": "22:00:00" },
{ "day_index": "THU", "start_time": "11:00:00", "end_time": "22:00:00" },
{ "day_index": "FRI", "start_time": "11:00:00", "end_time": "23:00:00" },
{ "day_index": "SAT", "start_time": "10:00:00", "end_time": "23:00:00" },
{ "day_index": "SUN", "start_time": "10:00:00", "end_time": "21:00:00" }
],
"special_hours": [
{ "date": "2024-12-25", "closed": true, "start_time": "", "end_time": "" }
],
"menu": {
"name": "Main Menu",
"subtitle": "Fresh ingredients, made to order",
"merchant_supplied_id": "main-menu-001",
"active": true,
"categories": [
{
"merchant_supplied_id": "cat-appetizers",
"name": "Appetizers",
"subtitle": "Start your meal right",
"sort_id": 1,
"active": true,
"items": [
{
"merchant_supplied_id": "item-wings-001",
"name": "Buffalo Wings",
"description": "Crispy wings tossed in spicy buffalo sauce",
"original_image_url": "https://cdn.example.com/wings.jpg",
"price": 1299,
"tax_rate": "0.08875",
"is_alcohol": false,
"sort_id": 1,
"active": true,
"extras": [
{
"merchant_supplied_id": "mod-wing-count",
"name": "How Many?",
"min_num_options": 1,
"max_num_options": 1,
"options": [
{
"merchant_supplied_id": "opt-6-wings",
"name": "6 Wings",
"price": 0,
"default": true
},
{
"merchant_supplied_id": "opt-12-wings",
"name": "12 Wings",
"price": 699
}
]
},
{
"merchant_supplied_id": "mod-wing-sauce",
"name": "Choose Sauce",
"min_num_options": 1,
"max_num_options": 2,
"options": [
{
"merchant_supplied_id": "opt-buffalo",
"name": "Buffalo",
"price": 0,
"default": true
},
{
"merchant_supplied_id": "opt-bbq",
"name": "BBQ",
"price": 0
}
]
}
]
}
]
}
]
}
}

Field Notes

Unique IDs

All merchant_supplied_id values must be unique within their scope:

  • Menu IDs: Unique per store
  • Category IDs: Unique per menu
  • Item IDs: Unique per menu
  • Modifier group IDs: Unique per item
  • Modifier option IDs: Unique per group

Pricing

All prices are in cents (e.g., 1299 = $12.99).

The price field is required; base_price is an optional alternative that may be used in specific pricing scenarios.

Availability

The active field controls visibility:

  • true (default): Item/category/option is available
  • false: Item/category/option is hidden

For real-time 86ing (items running out), use the Item Availability webhook rather than republishing the entire menu.

Modifier Group Constraints

FieldDescription
min_num_optionsMinimum number of options customer must select
max_num_optionsMaximum number of options customer can select
num_free_optionsNumber of options included free before additional charges
min_option_choice_quantityMinimum quantity per individual option
max_option_choice_quantityMaximum quantity per individual option
min_aggregate_options_quantityMinimum total quantity across all selected options
max_aggregate_options_quantityMaximum total quantity across all selected options

Quantity Info (for Modifier Options)

The quantity_info object on modifier options controls quantity behavior:

  • default_quantity: Pre-selected quantity for this option
  • charge_above: Number of free units before charging (e.g., "first 2 toppings free")

Special Hours

  • Store Open Hours: Regular weekly schedule
  • Store Special Hours: Override schedule for specific dates (holidays, special events)
  • Item Special Hours: Time-based availability for specific items (e.g., "Breakfast Burrito" only available 6am-11am)

Tax Rate

The tax_rate field is a string representing a decimal tax rate (e.g., "0.08875" = 8.875% tax). This is used for tax calculation at the item level.

Operation Context

The operation_context field is an array of strings that can be used to control when items or options are available based on operational conditions (configured during integration).