Catalog Object Examples
Item Family containing Items
In the example below, the Appetizer Platter Item Family has 3 Item's (otherwise known as variations). Each size being priced accordingly.
{
"category": [
{
"provider_id": "starters_provider_id",
"name": "Starters",
"item_family_ids": ["platter_provider_id"]
}
],
"item_family": [
{
"provider_id": "platter_provider_id",
"name": "c",
"description": "Appetizer Platter",
"is_active": true,
"modifier_group_ids": [],
"item_ids": [
"small_platter_provider_id",
"large_platter_provider_id",
"party_platter_provider_id"
],
"images": []
}
],
"item": [
{
"provider_id": "small_platter_provider_id",
"name": "Small Platter",
"is_active": true,
"price_amount": 500,
"price_currency": "usd"
},
{
"provider_id": "large_platter_provider_id",
"name": "Large Platter",
"is_active": true,
"price_amount": 800,
"price_currency": "usd"
},
{
"provider_id": "party_platter_provider_id",
"name": "Party Platter",
"is_active": true,
"price_amount": 2000,
"price_currency": "usd"
}
],
"modifier_group": [],
"modifier": [],
"menu": []
}
Item Family with no Items
In the example below, the BLT Sandwich Item Family does not have any variations. Requiring the price_amount and price_currency to be set at the item family level.
{
"category": [
{
"provider_id": "sandwiches_provider_id",
"name": "Sandwiches",
"item_family_ids": ["blt_provider_id"]
}
],
"item_family": [
{
"provider_id": "blt_provider_id",
"name": "BLT Sandwich",
"description": "BLT Sandwich",
"is_active": true,
"price_amount": 1000,
"price_currency": "usd",
"modifier_group_ids": [],
"item_ids": [],
"images": []
}
],
"item": [],
"modifier_group": [],
"modifier": [],
"menu": []
}
86'd Item Family
In the example below, the BLT Sandwich item family has been marked as 86'd by populating is_active with a value of false.
{
"category": [
{
"provider_id": "sandwiches_provider_id",
"name": "Sandwiches",
"item_family_ids": ["blt_provider_id"]
}
],
"item_family": [
{
"provider_id": "blt_provider_id",
"name": "BLT Sandwich",
"description": "BLT Sandwich",
"is_active": false,
"modifier_group_ids": [],
"item_ids": [],
"images": []
}
],
"item": [],
"modifier_group": [],
"modifier": [],
"menu": []
}
Modifier Group with Rules
In the example below, the Fries modifier group will only allow one modifier option to be selected (maximum_unique_modifiers_allowed = 1) while having no requirement of a selection (minimum_unique_modifiers_allowed = 0)
{
"category": [
{
"provider_id": "all_cheeseburgers_provider_id",
"name": "All Cheeseburgers",
"item_family_ids": ["cheeseburger_provider_id"]
}
],
"item_family": [
{
"provider_id": "cheeseburger_provider_id",
"name": "Cheeseburger",
"description": "Cheeseburger",
"is_active": true,
"modifier_group_ids": ["fries_mg_provider_id"],
"item_ids": [],
"images": []
}
],
"item": [],
"modifier_group": [
{
"provider_id": "fries_mg_provider_id",
"name": "Add Fries",
"is_active": true,
"modifier_ids": [
"small_fries_provider_id",
"med_fries_provider_id",
"large_fries_provider_id"
],
"rules": {
"amount_of_modifiers_free": 0,
"minimum_unique_modifiers_allowed": 0,
"maximum_unique_modifiers_allowed": 1
}
}
],
"modifier": [
{
"provider_id": "small_fries_provider_id",
"name": "Small Fry",
"is_active": true,
"price_amount": 250,
"price_currency": "usd",
"modifier_group_ids": []
},
{
"provider_id": "med_fries_provider_id",
"name": "Medium Fry",
"is_active": true,
"price_amount": 350,
"price_currency": "usd",
"modifier_group_ids": []
},
{
"provider_id": "large_fries_provider_id",
"name": "Large Fry",
"is_active": true,
"price_amount": 450,
"price_currency": "usd",
"modifier_group_ids": []
}
],
"menu": []
}
Modifier Group with Rules - No Maximum
In the example below, the Cheese Slice modifier group will allow infinite modifier options to be selected (maximum_unique_modifiers_allowed = null) while having no requirement of a selection (minimum_unique_modifiers_allowed = 0)
{
"category": [
{
"provider_id": "all_cheeseburgers_provider_id",
"name": "All Cheeseburgers",
"item_family_ids": ["cheeseburger_provider_id"]
}
],
"item_family": [
{
"provider_id": "cheeseburger_provider_id",
"name": "Cheeseburger",
"description": "Cheeseburger",
"is_active": true,
"modifier_group_ids": ["cheese_mg_provider_id"],
"item_ids": [],
"images": []
}
],
"item": [],
"modifier_group": [
{
"provider_id": "cheese_mg_provider_id",
"name": "Cheese Slice",
"is_active": true,
"modifier_ids": [
"cheddar_provider_id",
"colby_provider_id",
"parm_provider_id",
"jalapeno_provider_id",
"swiss_provider_id"
],
"rules": {
"minimum_unique_modifiers_allowed": 0
}
}
],
"modifier": [
{
"provider_id": "small_fries_provider_id",
"name": "Small Fry",
"is_active": true,
"price_amount": 250,
"price_currency": "usd",
"modifier_group_ids": []
},
{
"provider_id": "med_fries_provider_id",
"name": "Medium Fry",
"is_active": true,
"price_amount": 350,
"price_currency": "usd",
"modifier_group_ids": []
},
{
"provider_id": "large_fries_provider_id",
"name": "Large Fry",
"is_active": true,
"price_amount": 450,
"price_currency": "usd",
"modifier_group_ids": []
}
],
"menu": []
}
Modifier Group with Rules - Multiple Selection
The Cheese Slice modifier group below sets selection_type: "multiple". With multiple, minimum_unique_modifiers_allowed and maximum_unique_modifiers_allowed validate the total quantity of selections, not the count of distinct options — despite their names, repeating the same modifier is allowed and counts toward these limits. Here, up to 2 total selections are allowed (maximum_unique_modifiers_allowed = 2) with no minimum required (minimum_unique_modifiers_allowed = 0), so a customer could pick "Cheddar" twice, or "Cheddar" once and "Swiss" once — either satisfies the rule. (Contrast this with selection_type: "single" in the first example above, where each selection must be a different modifier.)
{
"category": [
{
"provider_id": "all_cheeseburgers_provider_id",
"name": "All Cheeseburgers",
"item_family_ids": ["cheeseburger_provider_id"]
}
],
"item_family": [
{
"provider_id": "cheeseburger_provider_id",
"name": "Cheeseburger",
"description": "Cheeseburger",
"is_active": true,
"modifier_group_ids": ["cheese_mg_provider_id"],
"item_ids": [],
"images": []
}
],
"item": [],
"modifier_group": [
{
"provider_id": "cheese_mg_provider_id",
"name": "Cheese Slice",
"is_active": true,
"modifier_ids": [
"cheddar_provider_id",
"colby_provider_id",
"parm_provider_id",
"jalapeno_provider_id",
"swiss_provider_id"
],
"rules": {
"minimum_unique_modifiers_allowed": 0,
"maximum_unique_modifiers_allowed": 2,
"selection_type": "multiple"
}
}
],
"modifier": [
{
"provider_id": "small_fries_provider_id",
"name": "Small Fry",
"is_active": true,
"price_amount": 250,
"price_currency": "usd",
"modifier_group_ids": []
},
{
"provider_id": "med_fries_provider_id",
"name": "Medium Fry",
"is_active": true,
"price_amount": 350,
"price_currency": "usd",
"modifier_group_ids": []
},
{
"provider_id": "large_fries_provider_id",
"name": "Large Fry",
"is_active": true,
"price_amount": 450,
"price_currency": "usd",
"modifier_group_ids": []
}
],
"menu": []
}
Modifier Group with Item Family Rule Overrides
In the example below, it will allow 1 free modifier from the Fries modifier group and have the Large Fry modifier selected by default for the Cheeseburger combo item family only.
{
"category": [
{
"provider_id": "all_cheeseburgers_provider_id",
"name": "All Cheeseburgers",
"item_family_ids": ["cheeseburger_provider_id"]
}
],
"item_family": [
{
"provider_id": "cheeseburger_combo_provider_id",
"name": "Cheeseburger Combo",
"description": "Cheeseburger with Fries",
"is_active": true,
"modifier_group_ids": ["fries_mg_provider_id"],
"item_ids": ["regular_cheeseburger"],
"images": [],
"modifier_group_rules": {
"fries_mg_provider_id": {
"amount_of_modifiers_free": 1,
"default_modifier_quantities": {
"large_fries_provider_id": 1
}
}
}
}
],
"item": [],
"modifier_group": [
{
"provider_id": "fries_mg_provider_id",
"name": "Add Fries",
"is_active": true,
"modifier_ids": [
"small_fries_provider_id",
"med_fries_provider_id",
"large_fries_provider_id"
],
"rules": {
"amount_of_modifiers_free": 0,
"minimum_unique_modifiers_allowed": 0,
"maximum_unique_modifiers_allowed": 1
}
}
],
"modifier": [
{
"provider_id": "small_fries_provider_id",
"name": "Small Fry",
"is_active": true,
"price_amount": 250,
"price_currency": "usd",
"modifier_group_ids": []
},
{
"provider_id": "med_fries_provider_id",
"name": "Medium Fry",
"is_active": true,
"price_amount": 350,
"price_currency": "usd",
"modifier_group_ids": []
},
{
"provider_id": "large_fries_provider_id",
"name": "Large Fry",
"is_active": true,
"price_amount": 450,
"price_currency": "usd",
"modifier_group_ids": []
}
],
"menu": []
}
Item Family with Item Priced Modifiers
In the example below, it uses a similar pattern to the Combo with group overrides, however the selected modifiers will be priced according to the item selected on platforms that support it. For platforms without support they will be priced according to the normal modifier.price_amount.
{
"category": [
{
"provider_id": "all_cheeseburgers_provider_id",
"name": "All Cheeseburgers",
"item_family_ids": ["cheeseburger_provider_id"]
}
],
"item_family": [
{
"provider_id": "cheeseburger_combo_provider_id",
"name": "Cheeseburger Combo",
"description": "Cheeseburger with Fries",
"is_active": true,
"modifier_group_ids": ["fries_mg_provider_id"],
"item_ids": [
"jr_cheeseburger_combo",
"reg_cheeseburger_combo",
"lg_cheeseburger_combo"
],
"images": [],
"modifier_group_rules": {
"fries_mg_provider_id": {
"amount_of_modifiers_free": 1,
"default_modifier_quantities": {
"large_fries_provider_id": 1
}
}
}
}
],
"item": [
{
"provider_id": "jr_cheeseburger_combo",
"name": "Junior Combo",
"is_active": true,
"price_amount": 500,
"price_currency": "usd",
"modifier_overrides": {
"french_fries": {
"price_amount": 100
}
}
},
{
"provider_id": "reg_cheeseburger_combo",
"name": "Regular Combo",
"is_active": true,
"price_amount": 750,
"price_currency": "usd",
"modifier_overrides": {
"french_fries": {
"price_amount": 200
}
}
},
{
"provider_id": "lg_cheeseburger_combo",
"name": "Large Combo",
"is_active": true,
"price_amount": 1000,
"price_currency": "usd",
"modifier_overrides": {
"french_fries": {
"price_amount": 300
}
}
}
],
"modifier_group": [
{
"provider_id": "fries_mg_provider_id",
"name": "Add Fries",
"is_active": true,
"modifier_ids": ["french_fries"],
"rules": {
"amount_of_modifiers_free": 0,
"minimum_unique_modifiers_allowed": 0,
"maximum_unique_modifiers_allowed": 1
}
}
],
"modifier": [
{
"provider_id": "french_fries",
"name": "French Fries",
"is_active": true,
"price_amount": 100,
"price_currency": "usd",
"modifier_group_ids": []
}
],
"menu": []
}
Nested Modifiers
In the example below, the Appetizer Platter Item Family has modifier groups which contain modifiers that have their own modifiers. Defining these nested modifiers is approached the same way as with item families, with a modifier_group_ids array. Similarly, they may have per-modifier override rules that can be set with the modifier_group_rules field, which can be seen in the Spread Options Modifier Group below.
Two override mechanisms are especially useful in nested trees, and each has a dedicated example following this one:
- Modifier → nested Modifier Group rule overrides — a parent modifier can override the rules of a modifier group nested beneath it with
modifier_group_rules(keyed by the nestedmodifier_group_id). See Modifier-Level Rule Overrides on Nested Modifier Groups. - Item → Modifier price overrides — an item variation can override the price of any modifier in its family's tree (including a nested one) with
modifier_overrides(keyed by themodifier_id). See Item-Level Price Overrides on Nested Modifiers.
For a full combo meal built this way (choose an entrée, side, and drink, each with its own follow-up choices), see Combo Meal with Nested Modifiers. For an optional "make it a combo" upgrade nested three levels deep, see Combo Opt-In with Three Levels of Nesting.
Appetizer Platter
--> Platter Options (Modifier Group)
--> Chips (Modifier)
--> Salsa (Modifier Group)
--> Mild (Modifier)
--> Hot (Modifier)
--> Bread (Modifier)
--> Spreads (Modifier Group)
--> Jam (Modifier)
--> Butter (Modifier)
{
"category": [
{
"provider_id": "appetizers_provider_id",
"name": "Appetizers",
"item_family_ids": ["platter_provider_id"]
}
],
"item_family": [
{
"provider_id": "platter_provider_id",
"name": "Appetizer Platter",
"description": "Appetizer Platter",
"is_active": true,
"modifier_group_ids": ["platter_mg_provider_id"],
"item_ids": ["small_platter_provider_id", "large_platter_provider_id"],
"images": []
}
],
"item": [
{
"provider_id": "small_platter_provider_id",
"name": "Small Platter",
"is_active": true,
"price_amount": 500,
"price_currency": "usd"
},
{
"provider_id": "large_platter_provider_id",
"name": "Large Platter",
"is_active": true,
"price_amount": 800,
"price_currency": "usd"
}
],
"modifier_group": [
{
"provider_id": "platter_mg_provider_id",
"name": "Platter Options",
"is_active": true,
"modifier_ids": ["chips_platter", "bread_platter"],
"rules": {
"amount_of_modifiers_free": 0,
"minimum_unique_modifiers_allowed": 1,
"maximum_unique_modifiers_allowed": 1
}
},
{
"provider_id": "salsa_mg_provider_id",
"name": "Add Salsa",
"is_active": true,
"modifier_ids": ["mild_provider_id", "hot_provider_id"],
"rules": {
"selection_type": "multiple",
"amount_of_modifiers_free": 1,
"minimum_unique_modifiers_allowed": 0,
"maximum_unique_modifiers_allowed": 2
}
},
{
"provider_id": "spreads_mg_provider_id",
"name": "Spread Options",
"is_active": true,
"modifier_ids": ["berry_jam_provider_id", "butter_provider_id"],
"rules": {
"selection_type": "multiple",
"amount_of_modifiers_free": 1,
"minimum_unique_modifiers_allowed": 0,
"maximum_unique_modifiers_allowed": 2
}
}
],
"modifier": [
{
"provider_id": "chips_platter",
"name": "Chips and Salsa",
"is_active": true,
"price_amount": 0,
"price_currency": "usd",
"modifier_group_ids": ["salsa_mg_provider_id"]
},
{
"provider_id": "bread_platter",
"name": "Bread",
"is_active": true,
"price_amount": 0,
"price_currency": "usd",
"modifier_group_ids": ["spreads_mg_provider_id"],
"modifier_group_rules": {
"spreads_mg_provider_id": {
"minimum_unique_modifiers_allowed": 1
}
}
},
{
"provider_id": "mild_provider_id",
"name": "Mild Salsa",
"is_active": true,
"price_amount": 200,
"price_currency": "usd",
"modifier_group_ids": []
},
{
"provider_id": "hot_provider_id",
"name": "Hot Salsa",
"is_active": true,
"price_amount": 250,
"price_currency": "usd",
"modifier_group_ids": []
},
{
"provider_id": "berry_jam_provider_id",
"name": "Berry Jam",
"is_active": true,
"price_amount": 250,
"price_currency": "usd",
"modifier_group_ids": []
},
{
"provider_id": "butter_provider_id",
"name": "Butter",
"is_active": true,
"price_amount": 200,
"price_currency": "usd",
"modifier_group_ids": []
}
]
}
Modifier-Level Rule Overrides on Nested Modifier Groups
Just as an Item Family can override the rules of a Modifier Group attached to it (see Modifier Group with Item Family Rule Overrides), a Modifier can override the rules of a Modifier Group nested beneath it. This is done with the same modifier_group_rules field, keyed by the nested modifier_group_id, and accepting any subset of a modifier group's rules (selection_type, minimum_unique_modifiers_allowed, maximum_unique_modifiers_allowed, amount_of_modifiers_free, default_modifier_quantities).
The override only applies to the nested group when it is reached through that specific parent modifier. The group's base rules continue to apply everywhere else it is attached, so a single shared modifier group can behave differently under different parents.
In the example below, the shared Toppings modifier group has base rules allowing up to 2 toppings with 1 free. When reached through the Regular Fries modifier it keeps those base rules, but the Loaded Fries modifier overrides the same group to allow up to 4 toppings with 3 free.
Combo Meal
--> Side Choice (Modifier Group)
--> Regular Fries (Modifier)
--> Toppings (Modifier Group) [base rules: max 2, 1 free]
--> Loaded Fries (Modifier)
--> Toppings (Modifier Group) [overridden: max 4, 3 free]
{
"category": [
{
"provider_id": "combos_provider_id",
"name": "Combos",
"item_family_ids": ["combo_meal_provider_id"]
}
],
"item_family": [
{
"provider_id": "combo_meal_provider_id",
"name": "Combo Meal",
"description": "Entrée with a side",
"is_active": true,
"price_amount": 900,
"price_currency": "usd",
"modifier_group_ids": ["side_choice_mg_provider_id"],
"item_ids": [],
"images": []
}
],
"item": [],
"modifier_group": [
{
"provider_id": "side_choice_mg_provider_id",
"name": "Side Choice",
"is_active": true,
"modifier_ids": [
"regular_fries_provider_id",
"loaded_fries_provider_id"
],
"rules": {
"amount_of_modifiers_free": 1,
"minimum_unique_modifiers_allowed": 1,
"maximum_unique_modifiers_allowed": 1
}
},
{
"provider_id": "toppings_mg_provider_id",
"name": "Toppings",
"is_active": true,
"modifier_ids": [
"cheese_topping_provider_id",
"bacon_topping_provider_id",
"onion_topping_provider_id",
"jalapeno_topping_provider_id"
],
"rules": {
"selection_type": "multiple",
"amount_of_modifiers_free": 1,
"minimum_unique_modifiers_allowed": 0,
"maximum_unique_modifiers_allowed": 2
}
}
],
"modifier": [
{
"provider_id": "regular_fries_provider_id",
"name": "Regular Fries",
"is_active": true,
"price_amount": 0,
"price_currency": "usd",
"modifier_group_ids": ["toppings_mg_provider_id"]
},
{
"provider_id": "loaded_fries_provider_id",
"name": "Loaded Fries",
"is_active": true,
"price_amount": 200,
"price_currency": "usd",
"modifier_group_ids": ["toppings_mg_provider_id"],
"modifier_group_rules": {
"toppings_mg_provider_id": {
"amount_of_modifiers_free": 3,
"maximum_unique_modifiers_allowed": 4
}
}
},
{
"provider_id": "cheese_topping_provider_id",
"name": "Cheese",
"is_active": true,
"price_amount": 100,
"price_currency": "usd",
"modifier_group_ids": []
},
{
"provider_id": "bacon_topping_provider_id",
"name": "Bacon",
"is_active": true,
"price_amount": 150,
"price_currency": "usd",
"modifier_group_ids": []
},
{
"provider_id": "onion_topping_provider_id",
"name": "Grilled Onions",
"is_active": true,
"price_amount": 100,
"price_currency": "usd",
"modifier_group_ids": []
},
{
"provider_id": "jalapeno_topping_provider_id",
"name": "Jalapeños",
"is_active": true,
"price_amount": 100,
"price_currency": "usd",
"modifier_group_ids": []
}
],
"menu": []
}
Item-Level Price Overrides on Nested Modifiers
An Item variation can override the price of a specific modifier anywhere in its family's modifier tree — including a nested modifier — using modifier_overrides, keyed by the modifier_id. This lets the same modifier cost a different amount depending on which item variation is selected. On platforms without support for item-priced modifiers, the modifier is priced according to its own modifier.price_amount instead.
NOTE: This applies only to the few DSP platforms that support item-priced modifiers (e.g. Grubhub).
In the example below, the Extra Mozzarella modifier is nested two levels deep (Pizza → Crust Add-ons → Stuffed Crust → Cheese Filling → Extra Mozzarella). Its base price is 250, but the Small variation overrides it to 200 and the Large variation overrides it to 300.
Pizza
--> Small (Item) [Extra Mozzarella priced 200]
--> Large (Item) [Extra Mozzarella priced 300]
--> Crust Add-ons (Modifier Group)
--> Stuffed Crust (Modifier)
--> Cheese Filling (Modifier Group)
--> Extra Mozzarella (Modifier) [base price 250]
{
"category": [
{
"provider_id": "pizzas_provider_id",
"name": "Pizzas",
"item_family_ids": ["pizza_provider_id"]
}
],
"item_family": [
{
"provider_id": "pizza_provider_id",
"name": "Pizza",
"description": "Hand-tossed pizza",
"is_active": true,
"modifier_group_ids": ["crust_addons_mg_provider_id"],
"item_ids": [
"small_pizza_provider_id",
"large_pizza_provider_id"
],
"images": []
}
],
"item": [
{
"provider_id": "small_pizza_provider_id",
"name": "Small",
"is_active": true,
"price_amount": 1200,
"price_currency": "usd",
"modifier_overrides": {
"extra_mozzarella_provider_id": {
"price_amount": 200,
"price_currency": "usd"
}
}
},
{
"provider_id": "large_pizza_provider_id",
"name": "Large",
"is_active": true,
"price_amount": 1800,
"price_currency": "usd",
"modifier_overrides": {
"extra_mozzarella_provider_id": {
"price_amount": 300,
"price_currency": "usd"
}
}
}
],
"modifier_group": [
{
"provider_id": "crust_addons_mg_provider_id",
"name": "Crust Add-ons",
"is_active": true,
"modifier_ids": ["stuffed_crust_provider_id"],
"rules": {
"amount_of_modifiers_free": 0,
"minimum_unique_modifiers_allowed": 0,
"maximum_unique_modifiers_allowed": 1
}
},
{
"provider_id": "cheese_filling_mg_provider_id",
"name": "Cheese Filling",
"is_active": true,
"modifier_ids": ["extra_mozzarella_provider_id"],
"rules": {
"amount_of_modifiers_free": 0,
"minimum_unique_modifiers_allowed": 0,
"maximum_unique_modifiers_allowed": 1
}
}
],
"modifier": [
{
"provider_id": "stuffed_crust_provider_id",
"name": "Stuffed Crust",
"is_active": true,
"price_amount": 250,
"price_currency": "usd",
"modifier_group_ids": ["cheese_filling_mg_provider_id"]
},
{
"provider_id": "extra_mozzarella_provider_id",
"name": "Extra Mozzarella",
"is_active": true,
"price_amount": 250,
"price_currency": "usd",
"modifier_group_ids": []
}
],
"menu": []
}
Combo Meal with Nested Modifiers
A combo is modeled as one Item Family whose "steps" (choose an entrée, choose a side, choose a drink) are each a Modifier Group. Any choice inside a step can carry its own nested Modifier Groups for the follow-up questions that only apply to that choice, such as toppings for a burger or a size for a drink.
In the example below, the Burger Combo:
- Has two combo sizes modeled as Items (
Regular ComboandLarge Combo), because the size changes the price of the whole combo. See Item Family containing Items. - Requires exactly one entrée, one side, and one drink (
minimum_unique_modifiers_allowedandmaximum_unique_modifiers_allowedboth1). - Prices included choices at
0and premium choices as an upcharge (Crispy Chicken Sandwich+$1.00,Onion Rings+$0.75). - Asks a different follow-up question depending on the entrée: the
Cheeseburgeropens optionalBurger Toppings, while theCrispy Chicken Sandwichopens a requiredChicken Stylechoice. - Reuses one
Drink SizeModifier Group under every drink, withMediumselected by default (default_modifier_quantities) andLargeas an upcharge.
With these prices, a Large Combo with a Crispy Chicken Sandwich, Onion Rings, and a Large Lemonade totals 1299 + 100 + 75 + 75 = 1549.
A "pick one" step left at minimum_unique_modifiers_allowed: 0 lets the customer check out a combo without that component. Set the minimum to 1 on every required step, including nested ones such as Chicken Style and Drink Size.
Burger Combo (Item Family)
--> Regular Combo (Item)
--> Large Combo (Item)
--> Choose Your Entrée (Modifier Group) [required, pick 1]
--> Cheeseburger (Modifier)
--> Burger Toppings (Modifier Group) [optional, up to 3]
--> Bacon (Modifier)
--> Grilled Onions (Modifier)
--> Jalapeños (Modifier)
--> Crispy Chicken Sandwich (Modifier)
--> Chicken Style (Modifier Group) [required, pick 1]
--> Classic (Modifier)
--> Spicy (Modifier)
--> Choose Your Side (Modifier Group) [required, pick 1]
--> Fries (Modifier)
--> Onion Rings (Modifier)
--> Choose Your Drink (Modifier Group) [required, pick 1]
--> Cola (Modifier)
--> Drink Size (Modifier Group) [required, pick 1, Medium by default]
--> Medium (Modifier)
--> Large (Modifier)
--> Lemonade (Modifier)
--> Drink Size (Modifier Group) [same shared group]
{
"category": [
{
"provider_id": "combos_provider_id",
"name": "Combos",
"item_family_ids": ["burger_combo_provider_id"]
}
],
"item_family": [
{
"provider_id": "burger_combo_provider_id",
"name": "Burger Combo",
"description": "Choose an entrée, a side, and a drink",
"is_active": true,
"modifier_group_ids": [
"entree_mg_provider_id",
"side_mg_provider_id",
"drink_mg_provider_id"
],
"item_ids": [
"regular_combo_provider_id",
"large_combo_provider_id"
],
"images": []
}
],
"item": [
{
"provider_id": "regular_combo_provider_id",
"name": "Regular Combo",
"is_active": true,
"price_amount": 1099,
"price_currency": "usd"
},
{
"provider_id": "large_combo_provider_id",
"name": "Large Combo",
"is_active": true,
"price_amount": 1299,
"price_currency": "usd"
}
],
"modifier_group": [
{
"provider_id": "entree_mg_provider_id",
"name": "Choose Your Entrée",
"is_active": true,
"modifier_ids": [
"cheeseburger_entree_provider_id",
"chicken_sandwich_entree_provider_id"
],
"rules": {
"amount_of_modifiers_free": 0,
"minimum_unique_modifiers_allowed": 1,
"maximum_unique_modifiers_allowed": 1
}
},
{
"provider_id": "burger_toppings_mg_provider_id",
"name": "Burger Toppings",
"is_active": true,
"modifier_ids": [
"bacon_provider_id",
"grilled_onions_provider_id",
"jalapenos_provider_id"
],
"rules": {
"amount_of_modifiers_free": 0,
"minimum_unique_modifiers_allowed": 0,
"maximum_unique_modifiers_allowed": 3
}
},
{
"provider_id": "chicken_style_mg_provider_id",
"name": "Chicken Style",
"is_active": true,
"modifier_ids": [
"classic_chicken_provider_id",
"spicy_chicken_provider_id"
],
"rules": {
"amount_of_modifiers_free": 0,
"minimum_unique_modifiers_allowed": 1,
"maximum_unique_modifiers_allowed": 1
}
},
{
"provider_id": "side_mg_provider_id",
"name": "Choose Your Side",
"is_active": true,
"modifier_ids": ["fries_side_provider_id", "onion_rings_side_provider_id"],
"rules": {
"amount_of_modifiers_free": 0,
"minimum_unique_modifiers_allowed": 1,
"maximum_unique_modifiers_allowed": 1
}
},
{
"provider_id": "drink_mg_provider_id",
"name": "Choose Your Drink",
"is_active": true,
"modifier_ids": ["cola_provider_id", "lemonade_provider_id"],
"rules": {
"amount_of_modifiers_free": 0,
"minimum_unique_modifiers_allowed": 1,
"maximum_unique_modifiers_allowed": 1
}
},
{
"provider_id": "drink_size_mg_provider_id",
"name": "Drink Size",
"is_active": true,
"modifier_ids": ["medium_drink_provider_id", "large_drink_provider_id"],
"rules": {
"amount_of_modifiers_free": 0,
"minimum_unique_modifiers_allowed": 1,
"maximum_unique_modifiers_allowed": 1,
"default_modifier_quantities": {
"medium_drink_provider_id": 1
}
}
}
],
"modifier": [
{
"provider_id": "cheeseburger_entree_provider_id",
"name": "Cheeseburger",
"is_active": true,
"price_amount": 0,
"price_currency": "usd",
"modifier_group_ids": ["burger_toppings_mg_provider_id"]
},
{
"provider_id": "chicken_sandwich_entree_provider_id",
"name": "Crispy Chicken Sandwich",
"is_active": true,
"price_amount": 100,
"price_currency": "usd",
"modifier_group_ids": ["chicken_style_mg_provider_id"]
},
{
"provider_id": "bacon_provider_id",
"name": "Bacon",
"is_active": true,
"price_amount": 150,
"price_currency": "usd",
"modifier_group_ids": []
},
{
"provider_id": "grilled_onions_provider_id",
"name": "Grilled Onions",
"is_active": true,
"price_amount": 50,
"price_currency": "usd",
"modifier_group_ids": []
},
{
"provider_id": "jalapenos_provider_id",
"name": "Jalapeños",
"is_active": true,
"price_amount": 50,
"price_currency": "usd",
"modifier_group_ids": []
},
{
"provider_id": "classic_chicken_provider_id",
"name": "Classic",
"is_active": true,
"price_amount": 0,
"price_currency": "usd",
"modifier_group_ids": []
},
{
"provider_id": "spicy_chicken_provider_id",
"name": "Spicy",
"is_active": true,
"price_amount": 0,
"price_currency": "usd",
"modifier_group_ids": []
},
{
"provider_id": "fries_side_provider_id",
"name": "Fries",
"is_active": true,
"price_amount": 0,
"price_currency": "usd",
"modifier_group_ids": []
},
{
"provider_id": "onion_rings_side_provider_id",
"name": "Onion Rings",
"is_active": true,
"price_amount": 75,
"price_currency": "usd",
"modifier_group_ids": []
},
{
"provider_id": "cola_provider_id",
"name": "Cola",
"is_active": true,
"price_amount": 0,
"price_currency": "usd",
"modifier_group_ids": ["drink_size_mg_provider_id"]
},
{
"provider_id": "lemonade_provider_id",
"name": "Lemonade",
"is_active": true,
"price_amount": 0,
"price_currency": "usd",
"modifier_group_ids": ["drink_size_mg_provider_id"]
},
{
"provider_id": "medium_drink_provider_id",
"name": "Medium",
"is_active": true,
"price_amount": 0,
"price_currency": "usd",
"modifier_group_ids": []
},
{
"provider_id": "large_drink_provider_id",
"name": "Large",
"is_active": true,
"price_amount": 75,
"price_currency": "usd",
"modifier_group_ids": []
}
],
"menu": []
}
Combo Opt-In with Three Levels of Nesting
A combo does not have to be its own Item Family. In the example below, a plain Cheeseburger offers a Make It a Combo? Modifier Group, and only the Make It a Combo modifier opens the side and drink steps. Nesting continues as deep as needed: the Loaded Fries modifier opens its own required Fry Sauce group, and Fountain Soda opens a required Soda Flavor group. Every level is linked the same way: a Modifier's modifier_group_ids points at the Modifier Groups beneath it, and each Modifier Group's modifier_ids points at its options.
Just the Burgeris selected by default (default_modifier_quantities) and has no nested groups, so a customer who keeps it is never asked about sides or drinks.Make It a Comboadds 350 and opens two groups,Choose Your SideandChoose Your Drink.Loaded Friesadds 150 and opensFry Sauce, whereGarlic AioliandChipotle Mayoadd 50 each.
With these prices, a Double as a combo with Loaded Fries, Garlic Aioli, and a Fountain Soda in Cola totals 1199 + 350 + 150 + 50 = 1749.
Cheeseburger (Item Family)
--> Single (Item)
--> Double (Item)
--> Make It a Combo? (Modifier Group) [required, pick 1, Just the Burger by default]
--> Just the Burger (Modifier)
--> Make It a Combo (Modifier)
--> Choose Your Side (Modifier Group) [required, pick 1]
--> Regular Fries (Modifier)
--> Loaded Fries (Modifier)
--> Fry Sauce (Modifier Group) [required, pick 1]
--> Cheese Sauce (Modifier)
--> Garlic Aioli (Modifier)
--> Chipotle Mayo (Modifier)
--> Choose Your Drink (Modifier Group) [required, pick 1]
--> Fountain Soda (Modifier)
--> Soda Flavor (Modifier Group) [required, pick 1]
--> Cola (Modifier)
--> Lemon-Lime (Modifier)
--> Bottled Water (Modifier)
{
"category": [
{
"provider_id": "burgers_provider_id",
"name": "Burgers",
"item_family_ids": ["cheeseburger_provider_id"]
}
],
"item_family": [
{
"provider_id": "cheeseburger_provider_id",
"name": "Cheeseburger",
"description": "Cheeseburger, optionally as a combo",
"is_active": true,
"modifier_group_ids": ["make_combo_mg_provider_id"],
"item_ids": [
"single_cheeseburger_provider_id",
"double_cheeseburger_provider_id"
],
"images": []
}
],
"item": [
{
"provider_id": "single_cheeseburger_provider_id",
"name": "Single",
"is_active": true,
"price_amount": 899,
"price_currency": "usd"
},
{
"provider_id": "double_cheeseburger_provider_id",
"name": "Double",
"is_active": true,
"price_amount": 1199,
"price_currency": "usd"
}
],
"modifier_group": [
{
"provider_id": "make_combo_mg_provider_id",
"name": "Make It a Combo?",
"is_active": true,
"modifier_ids": ["burger_only_provider_id", "make_combo_provider_id"],
"rules": {
"amount_of_modifiers_free": 0,
"minimum_unique_modifiers_allowed": 1,
"maximum_unique_modifiers_allowed": 1,
"default_modifier_quantities": {
"burger_only_provider_id": 1
}
}
},
{
"provider_id": "combo_side_mg_provider_id",
"name": "Choose Your Side",
"is_active": true,
"modifier_ids": ["regular_fries_provider_id", "loaded_fries_provider_id"],
"rules": {
"amount_of_modifiers_free": 0,
"minimum_unique_modifiers_allowed": 1,
"maximum_unique_modifiers_allowed": 1
}
},
{
"provider_id": "fry_sauce_mg_provider_id",
"name": "Fry Sauce",
"is_active": true,
"modifier_ids": [
"cheese_sauce_provider_id",
"garlic_aioli_provider_id",
"chipotle_mayo_provider_id"
],
"rules": {
"amount_of_modifiers_free": 0,
"minimum_unique_modifiers_allowed": 1,
"maximum_unique_modifiers_allowed": 1
}
},
{
"provider_id": "combo_drink_mg_provider_id",
"name": "Choose Your Drink",
"is_active": true,
"modifier_ids": ["fountain_soda_provider_id", "bottled_water_provider_id"],
"rules": {
"amount_of_modifiers_free": 0,
"minimum_unique_modifiers_allowed": 1,
"maximum_unique_modifiers_allowed": 1
}
},
{
"provider_id": "soda_flavor_mg_provider_id",
"name": "Soda Flavor",
"is_active": true,
"modifier_ids": ["cola_flavor_provider_id", "lemon_lime_flavor_provider_id"],
"rules": {
"amount_of_modifiers_free": 0,
"minimum_unique_modifiers_allowed": 1,
"maximum_unique_modifiers_allowed": 1
}
}
],
"modifier": [
{
"provider_id": "burger_only_provider_id",
"name": "Just the Burger",
"is_active": true,
"price_amount": 0,
"price_currency": "usd",
"modifier_group_ids": []
},
{
"provider_id": "make_combo_provider_id",
"name": "Make It a Combo",
"is_active": true,
"price_amount": 350,
"price_currency": "usd",
"modifier_group_ids": [
"combo_side_mg_provider_id",
"combo_drink_mg_provider_id"
]
},
{
"provider_id": "regular_fries_provider_id",
"name": "Regular Fries",
"is_active": true,
"price_amount": 0,
"price_currency": "usd",
"modifier_group_ids": []
},
{
"provider_id": "loaded_fries_provider_id",
"name": "Loaded Fries",
"is_active": true,
"price_amount": 150,
"price_currency": "usd",
"modifier_group_ids": ["fry_sauce_mg_provider_id"]
},
{
"provider_id": "cheese_sauce_provider_id",
"name": "Cheese Sauce",
"is_active": true,
"price_amount": 0,
"price_currency": "usd",
"modifier_group_ids": []
},
{
"provider_id": "garlic_aioli_provider_id",
"name": "Garlic Aioli",
"is_active": true,
"price_amount": 50,
"price_currency": "usd",
"modifier_group_ids": []
},
{
"provider_id": "chipotle_mayo_provider_id",
"name": "Chipotle Mayo",
"is_active": true,
"price_amount": 50,
"price_currency": "usd",
"modifier_group_ids": []
},
{
"provider_id": "fountain_soda_provider_id",
"name": "Fountain Soda",
"is_active": true,
"price_amount": 0,
"price_currency": "usd",
"modifier_group_ids": ["soda_flavor_mg_provider_id"]
},
{
"provider_id": "bottled_water_provider_id",
"name": "Bottled Water",
"is_active": true,
"price_amount": 0,
"price_currency": "usd",
"modifier_group_ids": []
},
{
"provider_id": "cola_flavor_provider_id",
"name": "Cola",
"is_active": true,
"price_amount": 0,
"price_currency": "usd",
"modifier_group_ids": []
},
{
"provider_id": "lemon_lime_flavor_provider_id",
"name": "Lemon-Lime",
"is_active": true,
"price_amount": 0,
"price_currency": "usd",
"modifier_group_ids": []
}
],
"menu": []
}
Menu with Schedule
In the example below the menu is scheduled to open at 10AM and close at 8PM, in the location's timezone provided via Get Locations
{
"category": [
{
"provider_id": "sandwiches_provider_id",
"name": "Sandwiches",
"item_family_ids": ["blt_provider_id"]
}
],
"item_family": [
{
"provider_id": "blt_provider_id",
"name": "BLT Sandwich",
"description": "BLT Sandwich",
"is_active": true,
"price_amount": 1000,
"modifier_group_ids": [],
"item_ids": [],
"images": []
}
],
"item": [],
"modifier_group": [],
"modifier": [],
"menu": [
{
"provider_id": "lunch_and_dinner_provider_id",
"name": "Lunch & Dinner",
"category_ids": ["sandwiches_provider_id"],
"schedule": {
"monday": ["10:00-20:00"],
"tuesday": ["10:00-20:00"],
"wednesday": ["10:00-20:00"],
"thursday": ["10:00-20:00"],
"friday": ["10:00-20:00"],
"saturday": [],
"sunday": []
}
}
]
}
Menu with Overnight schedule
When a service window crosses midnight, use a single range where the end time is earlier on the clock than the start time (the end is on the following calendar day). For example, late-night hours from 11:30 PM to 2:00 AM are sent as 11:30-02:00 in the location's timezone from Get Locations. List that range on the day the window starts (here, Friday night into Saturday morning).
{
"category": [
{
"provider_id": "sandwiches_provider_id",
"name": "Sandwiches",
"item_family_ids": ["blt_provider_id"]
}
],
"item_family": [
{
"provider_id": "blt_provider_id",
"name": "BLT Sandwich",
"description": "BLT Sandwich",
"is_active": true,
"price_amount": 1000,
"modifier_group_ids": [],
"item_ids": [],
"images": []
}
],
"item": [],
"modifier_group": [],
"modifier": [],
"menu": [
{
"provider_id": "late_night_provider_id",
"name": "Late Night",
"category_ids": ["sandwiches_provider_id"],
"schedule": {
"monday": [],
"tuesday": [],
"wednesday": [],
"thursday": [],
"friday": ["11:30-02:00"],
"saturday": [],
"sunday": []
}
}
]
}
Menu with Prep Time Adjusted Schedule
In the example below the menu is scheduled to open at 10AM and close at 8PM minus location's configured prep time provided via Get Locations
{
"category": [
{
"provider_id": "sandwiches_provider_id",
"name": "Sandwiches",
"item_family_ids": ["blt_provider_id"]
}
],
"item_family": [
{
"provider_id": "blt_provider_id",
"name": "BLT Sandwich",
"description": "BLT Sandwich",
"is_active": true,
"price_amount": 1000,
"modifier_group_ids": [],
"item_ids": [],
"images": []
}
],
"item": [],
"modifier_group": [],
"modifier": [],
"menu": [
{
"provider_id": "lunch_and_dinner_provider_id",
"name": "Lunch & Dinner",
"category_ids": ["sandwiches_provider_id"],
"should_adjust_for_prep_time": true,
"schedule": {
"monday": ["10:00-20:00"],
"tuesday": ["10:00-20:00"],
"wednesday": ["10:00-20:00"],
"thursday": ["10:00-20:00"],
"friday": ["10:00-20:00"],
"saturday": [],
"sunday": []
}
}
]
}
Category with Schedule
Categories can carry their own availability hours, independent of the menus they belong to. In the example below the "Lunch" category is available 11AM–3PM on weekdays and closed on weekends, in the location's timezone provided via Get Locations. The "All Day" category has no schedule, so it stays available for the full menu window.
{
"category": [
{
"provider_id": "lunch_provider_id",
"name": "Lunch",
"item_family_ids": ["blt_provider_id"],
"schedule": {
"monday": ["11:00-15:00"],
"tuesday": ["11:00-15:00"],
"wednesday": ["11:00-15:00"],
"thursday": ["11:00-15:00"],
"friday": ["11:00-15:00"],
"saturday": [],
"sunday": []
}
},
{
"provider_id": "all_day_provider_id",
"name": "All Day",
"item_family_ids": ["fries_provider_id"]
}
],
"item_family": [
{
"provider_id": "blt_provider_id",
"name": "BLT Sandwich",
"description": "BLT Sandwich",
"is_active": true,
"price_amount": 1000,
"modifier_group_ids": [],
"item_ids": [],
"images": []
},
{
"provider_id": "fries_provider_id",
"name": "Fries",
"is_active": true,
"price_amount": 400,
"modifier_group_ids": [],
"item_ids": [],
"images": []
}
],
"item": [],
"modifier_group": [],
"modifier": [],
"menu": [
{
"provider_id": "main_menu_provider_id",
"name": "Main Menu",
"category_ids": ["lunch_provider_id", "all_day_provider_id"],
"schedule": {
"monday": ["08:00-22:00"],
"tuesday": ["08:00-22:00"],
"wednesday": ["08:00-22:00"],
"thursday": ["08:00-22:00"],
"friday": ["08:00-22:00"],
"saturday": ["08:00-22:00"],
"sunday": ["08:00-22:00"]
}
}
]
}
Category with Split and Overnight Schedule
A category schedule accepts multiple ranges per day for split availability, and a range whose end time is earlier on the clock than its start crosses midnight. In the example below the "Snacks" category is available 07:15–14:30 and again 15:30–22:00 on weekdays, and on Friday it also serves a late-night window from 11:30 PM to 2:00 AM Saturday — listed on Friday, the day the window starts.
{
"category": [
{
"provider_id": "snacks_provider_id",
"name": "Snacks",
"item_family_ids": ["fries_provider_id"],
"schedule": {
"monday": ["07:15-14:30", "15:30-22:00"],
"tuesday": ["07:15-14:30", "15:30-22:00"],
"wednesday": ["07:15-14:30", "15:30-22:00"],
"thursday": ["07:15-14:30", "15:30-22:00"],
"friday": ["07:15-14:30", "15:30-22:00", "23:30-02:00"],
"saturday": [],
"sunday": []
}
}
],
"item_family": [
{
"provider_id": "fries_provider_id",
"name": "Fries",
"is_active": true,
"price_amount": 400,
"modifier_group_ids": [],
"item_ids": [],
"images": []
}
],
"item": [],
"modifier_group": [],
"modifier": [],
"menu": []
}
Category with Menu-Specific Schedule
A category shared across menus can carry different hours in each one via menu_overrides, keyed by the menu's provider_id. In the example below the "Sides" category runs 11AM–10PM by default, but serves breakfast hours inside the "Breakfast" menu. The "Dinner" menu has no override, so it uses the base schedule.
This works in any catalog — a global catalog is not required to scope category hours per menu. See Category Availability Hours.
{
"category": [
{
"provider_id": "sides_provider_id",
"name": "Sides",
"item_family_ids": ["fries_provider_id"],
"schedule": {
"monday": ["11:00-22:00"],
"tuesday": ["11:00-22:00"],
"wednesday": ["11:00-22:00"],
"thursday": ["11:00-22:00"],
"friday": ["11:00-22:00"],
"saturday": ["11:00-22:00"],
"sunday": ["11:00-22:00"]
},
"menu_overrides": [
{
"provider_menu_id": "breakfast_provider_id",
"override": {
"schedule": {
"monday": ["06:00-11:00"],
"tuesday": ["06:00-11:00"],
"wednesday": ["06:00-11:00"],
"thursday": ["06:00-11:00"],
"friday": ["06:00-11:00"],
"saturday": ["07:00-12:00"],
"sunday": ["07:00-12:00"]
}
}
}
]
}
],
"item_family": [
{
"provider_id": "fries_provider_id",
"name": "Fries",
"is_active": true,
"price_amount": 400,
"modifier_group_ids": [],
"item_ids": [],
"images": []
}
],
"item": [],
"modifier_group": [],
"modifier": [],
"menu": [
{
"provider_id": "breakfast_provider_id",
"name": "Breakfast",
"category_ids": ["sides_provider_id"],
"schedule": {
"monday": ["06:00-11:00"],
"tuesday": ["06:00-11:00"],
"wednesday": ["06:00-11:00"],
"thursday": ["06:00-11:00"],
"friday": ["06:00-11:00"],
"saturday": ["07:00-12:00"],
"sunday": ["07:00-12:00"]
}
},
{
"provider_id": "dinner_provider_id",
"name": "Dinner",
"category_ids": ["sides_provider_id"],
"schedule": {
"monday": ["17:00-22:00"],
"tuesday": ["17:00-22:00"],
"wednesday": ["17:00-22:00"],
"thursday": ["17:00-22:00"],
"friday": ["17:00-22:00"],
"saturday": ["17:00-22:00"],
"sunday": ["17:00-22:00"]
}
}
]
}
Nested Categories
In the example below, there is a parent category "Coffee" with sub-categories "Lattes" and "Cappuccinos". Note that DSP support varies for nested categories, so the examples below may be flattened into "Coffee - Lattes" and "Coffee - Cappuccinos" on some platforms.
{
"category": [
{
"provider_id": "coffee_provider_id",
"name": "Coffee",
"item_family_ids": [],
"category_ids": ["lattes_provider_id", "cappuccinos_provider_id"]
},
{
"provider_id": "lattes_provider_id",
"name": "Lattes",
"item_family_ids": ["latte_provider_id"]
},
{
"provider_id": "cappuccinos_provider_id",
"name": "Cappuccinos",
"item_family_ids": ["cappuccino_provider_id"]
}
],
"item_family": [
{
"provider_id": "latte_provider_id",
"name": "Latte",
"description": "Latte",
"is_active": true,
"price_amount": 500,
"price_currency": "usd",
"images": []
},
{
"provider_id": "cappuccino_provider_id",
"name": "Cappuccino",
"description": "Cappuccino",
"is_active": true,
"price_amount": 500,
"price_currency": "usd",
"images": []
}
],
"item": [],
"modifier_group": [],
"modifier": []
}
DSP Specific Markups
In the example below, the BLT Sandwich has distinct price markups for Doordash and Uber Eats. The standard price_amount property will be applied to any DSPs not present in the list.
DSP price overrides are supported for Item Families, Items, and Modifiers. API Spec
NOTE: Markups from the POS will always override those set within the UI
{
"category": [
{
"provider_id": "sandwiches_provider_id",
"name": "Sandwiches",
"item_family_ids": ["blt_provider_id"]
}
],
"item_family": [
{
"provider_id": "blt_provider_id",
"name": "BLT Sandwich",
"description": "BLT Sandwich",
"is_active": true,
"price_amount": 1000,
"price_currency": "usd",
"dsp_price_amount_overrides": [
{
"dsp": "doordash",
"price_amount": 1200
},
{
"dsp": "uber",
"price_amount": 1100
}
],
"modifier_group_ids": [],
"item_ids": [],
"images": []
}
],
"item": [],
"modifier_group": [],
"modifier": [],
"menu": []
}