Appearance
Item Configurator
Some menu items use a configurator — a guided, multi-step "build your own" flow (e.g. build-a-pizza, custom platters) instead of a flat list of modifier groups. The configurator endpoints return the step definitions for an item and validate a customer's in-progress build before it is added to the cart.
These endpoints are public (no authentication required). Items that do not have a configurator return 404 — fall back to the standard option groups returned by GET .../items/{item}.
Get Item Configurator
Fetch the configurator template (ordered steps + resolved option groups) for an item.
GET /v1/ecommerce/items/{item}/configuratorAuthentication: None (Public)
Rate Limit: 100/min per IP
Path Parameters
| Parameter | Type | Description |
|---|---|---|
item | string | Menu item ID (e.g. itm_00000a1B2c3D4e5) |
Response
json
{
"status": "success",
"data": {
"id": "cfg_00000a1B2c3D4e5",
"menu_item_id": "itm_00000a1B2c3D4e5",
"name": "Build Your Pizza",
"status": "active",
"steps": [
{
"step_number": 1,
"name": "Select Size",
"type": "single_select",
"option_group_id": "opg_size123",
"required": true,
"ui_hint": "size_picker",
"help_text": "Choose your pizza size"
},
{
"step_number": 2,
"name": "Add Toppings",
"type": "multi_select",
"option_group_id": "opg_toppings456",
"required": false,
"ui_hint": "checkbox_grid",
"help_text": "Select as many as you like"
},
{
"step_number": 3,
"name": "Special Instructions",
"type": "text_input",
"option_group_id": null,
"required": false,
"max_length": 500,
"price_impact": 0,
"ui_hint": "textarea",
"help_text": "Any notes for the kitchen?"
}
],
"option_groups": [
{
"option_group_id": "opg_size123",
"name": "Pizza Size",
"selection_type": "single",
"pricing_type": "per_modifier",
"modifiers": [
{
"modifier_id": "mod_small",
"name": "Small (10\")",
"description": "Feeds 1-2 people",
"price_adjustment": 0.00,
"is_default": true,
"sort_order": 1
},
{
"modifier_id": "mod_large",
"name": "Large (14\")",
"description": "Feeds 3-4 people",
"price_adjustment": 5.00,
"is_default": false,
"sort_order": 2
}
]
},
{
"option_group_id": "opg_toppings456",
"name": "Toppings",
"selection_type": "multiple",
"pricing_type": "per_modifier",
"modifiers": [
{
"modifier_id": "mod_pepperoni",
"name": "Pepperoni",
"price_adjustment": 1.50,
"is_default": false,
"sort_order": 1
}
]
}
]
}
}Step Fields
| Field | Type | Description |
|---|---|---|
step_number | integer | 1-indexed execution order |
name | string | Display name for the step |
type | string | single_select, multi_select, text_input, or image_upload |
option_group_id | string | null | Option group resolved in option_groups (select steps only) |
required | boolean | Whether the step must be completed before checkout |
max_length | integer | null | Max characters for text_input steps |
price_impact | number | null | Flat price added when a non-select step is completed |
ui_hint | string | null | Rendering hint (e.g. size_picker, checkbox_grid, textarea) |
help_text | string | null | Instructional copy shown to the customer |
The option_groups array contains the same option-group / modifier shape used elsewhere in the Menus API. See Menus → Item Details.
Validate Configuration
Validate a customer's in-progress build and compute its price impact before adding it to the cart. Use this to drive inline validation in your UI; the canonical price is always re-computed server-side at POST /orders/calculate.
POST /v1/ecommerce/items/{item}/configurator/validateAuthentication: None (Public)
Rate Limit: 100/min per IP
Request Body
json
{
"selections": [
{ "step_number": 1, "type": "single_select", "value": "mod_large" },
{ "step_number": 2, "type": "multi_select", "value": ["mod_pepperoni"] },
{ "step_number": 3, "type": "text_input", "value": "Light cheese" }
]
}| Field | Type | Required | Description |
|---|---|---|---|
selections | array | Yes | At least one selection |
selections[].step_number | integer | Yes | Must match a step in the template |
selections[].type | string | Yes | The step type (single_select, multi_select, text_input, image_upload) |
selections[].value | mixed | Yes | single_select: a modifier ID string · multi_select: an array of modifier ID strings · text_input/image_upload: a string |
Response
json
{
"status": "success",
"data": {
"valid": true,
"errors": [],
"price_impact": 6.50
}
}| Field | Type | Description |
|---|---|---|
valid | boolean | true when all required steps are present and within constraints |
errors | array | Human-readable constraint violations (empty when valid), e.g. "Step 1 (Select Size) is required." |
price_impact | number | Total price added by the current selections, rounded to 2 decimals |
Errors
| Status | Condition |
|---|---|
404 | Item not found, or the item has no configurator |
422 | Malformed request body (e.g. missing selections) |
Changelog
| Date | Change |
|---|---|
| 2026-06-17 | Initial publication. |