recommendations array to define upsell, cross-sell, and downsell targets once per sync. Attach them in two places:
pricing.recommendationson a line item — suggest other catalog products on the parent (combo upgrade, side item, downsell).pricing.modifiers[].recommendationson a modifier option — pre-select modifier quantities when you surface a premium customization preset.
default_quantity. That value is independent from default_quantity on the same pricing.modifiers entry.
The type values below are illustrative for this payload. Your catalog can map UPSELL, CROSS_SELL, and DOWNSELL differently.
What this example includes
| Layer | Where it lives | Behavior |
|---|---|---|
| Upsell to combo | upsell-meal-combo on burger | Suggests upgrading the standalone burger to meal-combo |
| Cross-sell side | cross-sell-fries on burger | Suggests adding fries as a separate item |
| Downsell to single | downsell-burger on meal-combo | Suggests burger when the customer opened the combo |
| Pre-selected side | burger.pricing.recommendations[] | Pre-selects 1 unit of fries on the burger line |
| Drink default | cola.pricing.modifiers[] | default_quantity: 1 inside the combo drink group |
| Premium preset | extra-cheese.pricing.modifiers[].recommendations | Pre-selects 2× extra cheese for a premium toppings preset |
| Premium preset | bacon.pricing.modifiers[].recommendations | Pre-selects 1× bacon for the same preset flow |
Request
Define recommendations in the shared catalog. Link line-item suggestions frompricing.recommendations on the parent product. For premium modifier configurations, link presets from pricing.modifiers[].recommendations on each modifier option — each recommendation_id must exist in the catalog and its target_product_id must match the modifier product.
curl --request PUT \
--url 'https://firespark.cloud/api/integrations/v1/menus?fulfillment_id=delivery&store_id=downtown&channel_id=app&brand_id=0001' \
-H "Authorization: Bearer ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d @product-recommendations.json
product-recommendations.json
{
"style": "DEFAULT",
"recommendations": [
{
"id": "upsell-meal-combo",
"type": "UPSELL",
"title": { "en_us": "Make it a combo" },
"description": { "en_us": "Add a drink and save on the meal." },
"target_product_id": "meal-combo",
"metadata": {}
},
{
"id": "cross-sell-fries",
"type": "CROSS_SELL",
"title": { "en_us": "Add fries" },
"description": { "en_us": "Side of seasoned fries." },
"target_product_id": "fries",
"metadata": {}
},
{
"id": "downsell-burger",
"type": "DOWNSELL",
"title": { "en_us": "Burger only" },
"description": { "en_us": "Skip the drink if you only want the main." },
"target_product_id": "burger",
"metadata": {}
},
{
"id": "premium-double-cheese",
"type": "CROSS_SELL",
"title": { "en_us": "Double cheese" },
"description": { "en_us": "Premium topping preset." },
"target_product_id": "extra-cheese",
"metadata": {}
},
{
"id": "premium-add-bacon",
"type": "CROSS_SELL",
"title": { "en_us": "Add bacon" },
"description": { "en_us": "Premium topping preset." },
"target_product_id": "bacon",
"metadata": {}
}
],
"products": [
{
"id": "burger",
"name": { "en_us": "Classic burger" },
"description": { "en_us": "Angus beef patty." },
"image_url": null,
"bundled_items": [],
"pricing": {
"minimum_quantity": 1,
"maximum_quantity": 10,
"is_tax_inclusive": true,
"tax_rate": 0.15,
"price": 12.99,
"anchor_price": 14.99,
"anchor_price_percentage": 0.13,
"modifier_group_ids": ["premium-toppings"],
"modifiers": [],
"recommendations_ids": ["upsell-meal-combo", "cross-sell-fries"],
"recommendations": [
{
"recommendation_id": "upsell-meal-combo",
"default_quantity": 0
},
{
"recommendation_id": "cross-sell-fries",
"default_quantity": 1
}
]
},
"availability": {
"status": "AVAILABLE",
"schedules": null,
"out_of_stock_until": null
},
"metadata": {}
},
{
"id": "fries",
"name": { "en_us": "Fries" },
"description": { "en_us": "Crispy side." },
"image_url": null,
"bundled_items": [],
"pricing": {
"minimum_quantity": 0,
"maximum_quantity": 5,
"is_tax_inclusive": true,
"tax_rate": 0.15,
"price": 3.99,
"anchor_price": 3.99,
"anchor_price_percentage": 0,
"modifier_group_ids": [],
"modifiers": [],
"recommendations_ids": [],
"recommendations": []
},
"availability": {
"status": "AVAILABLE",
"schedules": null,
"out_of_stock_until": null
},
"metadata": {}
},
{
"id": "extra-cheese",
"name": { "en_us": "Extra cheese" },
"description": { "en_us": "Premium topping." },
"image_url": null,
"bundled_items": [],
"pricing": {
"minimum_quantity": 0,
"maximum_quantity": 3,
"is_tax_inclusive": true,
"tax_rate": 0.15,
"price": 1.5,
"anchor_price": 1.5,
"anchor_price_percentage": 0,
"modifier_group_ids": ["premium-toppings"],
"modifiers": [
{
"modifier_group_id": "premium-toppings",
"minimum_quantity": 0,
"maximum_quantity": 3,
"is_tax_inclusive": true,
"tax_rate": 0.15,
"price": 1.5,
"anchor_price": 1.5,
"anchor_price_percentage": 0,
"default_quantity": 0,
"charge_above_quantity": null,
"display_type": "QUANTITY",
"recommendations": [
{
"recommendation_id": "premium-double-cheese",
"default_quantity": 2
}
]
}
],
"recommendations_ids": [],
"recommendations": []
},
"availability": {
"status": "AVAILABLE",
"schedules": null,
"out_of_stock_until": null
},
"metadata": {}
},
{
"id": "bacon",
"name": { "en_us": "Bacon" },
"description": { "en_us": "Premium topping." },
"image_url": null,
"bundled_items": [],
"pricing": {
"minimum_quantity": 0,
"maximum_quantity": 3,
"is_tax_inclusive": true,
"tax_rate": 0.15,
"price": 2,
"anchor_price": 2,
"anchor_price_percentage": 0,
"modifier_group_ids": ["premium-toppings"],
"modifiers": [
{
"modifier_group_id": "premium-toppings",
"minimum_quantity": 0,
"maximum_quantity": 3,
"is_tax_inclusive": true,
"tax_rate": 0.15,
"price": 2,
"anchor_price": 2,
"anchor_price_percentage": 0,
"default_quantity": 0,
"charge_above_quantity": null,
"display_type": "QUANTITY",
"recommendations": [
{
"recommendation_id": "premium-add-bacon",
"default_quantity": 1
}
]
}
],
"recommendations_ids": [],
"recommendations": []
},
"availability": {
"status": "AVAILABLE",
"schedules": null,
"out_of_stock_until": null
},
"metadata": {}
},
{
"id": "meal-combo",
"name": { "en_us": "Burger meal combo" },
"description": { "en_us": "Classic burger plus one drink." },
"image_url": null,
"bundled_items": [],
"pricing": {
"minimum_quantity": 1,
"maximum_quantity": 5,
"is_tax_inclusive": true,
"tax_rate": 0.15,
"price": 15.99,
"anchor_price": 17.99,
"anchor_price_percentage": 0.11,
"modifier_group_ids": ["choose-drink"],
"modifiers": [],
"recommendations_ids": ["downsell-burger"],
"recommendations": [
{
"recommendation_id": "downsell-burger",
"default_quantity": 0
}
]
},
"availability": {
"status": "AVAILABLE",
"schedules": null,
"out_of_stock_until": null
},
"metadata": {}
},
{
"id": "cola",
"name": { "en_us": "Cola" },
"description": { "en_us": "Fountain drink." },
"image_url": null,
"bundled_items": [],
"pricing": {
"minimum_quantity": 0,
"maximum_quantity": 3,
"is_tax_inclusive": true,
"tax_rate": 0.15,
"price": 0,
"anchor_price": 2.5,
"anchor_price_percentage": 0,
"modifier_group_ids": ["choose-drink"],
"modifiers": [
{
"modifier_group_id": "choose-drink",
"minimum_quantity": 0,
"maximum_quantity": 1,
"is_tax_inclusive": true,
"tax_rate": 0.15,
"price": 0,
"anchor_price": 0,
"anchor_price_percentage": 0,
"default_quantity": 1,
"charge_above_quantity": null,
"display_type": "RADIO",
"recommendations_ids": [],
"recommendations": []
}
],
"recommendations_ids": [],
"recommendations": []
},
"availability": {
"status": "AVAILABLE",
"schedules": null,
"out_of_stock_until": null
},
"metadata": {}
},
{
"id": "sprite",
"name": { "en_us": "Sprite" },
"description": { "en_us": "Fountain drink." },
"image_url": null,
"bundled_items": [],
"pricing": {
"minimum_quantity": 0,
"maximum_quantity": 3,
"is_tax_inclusive": true,
"tax_rate": 0.15,
"price": 0,
"anchor_price": 2.5,
"anchor_price_percentage": 0,
"modifier_group_ids": ["choose-drink"],
"modifiers": [
{
"modifier_group_id": "choose-drink",
"minimum_quantity": 0,
"maximum_quantity": 1,
"is_tax_inclusive": true,
"tax_rate": 0.15,
"price": 0,
"anchor_price": 0,
"anchor_price_percentage": 0,
"default_quantity": 0,
"charge_above_quantity": null,
"display_type": "RADIO",
"recommendations_ids": [],
"recommendations": []
}
],
"recommendations_ids": [],
"recommendations": []
},
"availability": {
"status": "AVAILABLE",
"schedules": null,
"out_of_stock_until": null
},
"metadata": {}
}
],
"categories": [
{
"id": "mains",
"name": { "en_us": "Mains" },
"description": null,
"items": [
{ "type": "PRODUCT", "id": "burger" },
{ "type": "PRODUCT", "id": "meal-combo" },
{ "type": "PRODUCT", "id": "fries" }
],
"availability": {
"status": "ACTIVE",
"schedules": null,
"inactive_until": null
},
"metadata": {}
}
],
"modifier_groups": [
{
"id": "premium-toppings",
"title": { "en_us": "Premium toppings" },
"description": null,
"display_type": "LIST",
"modifier_ids": ["extra-cheese", "bacon"],
"minimum_quantity": 0,
"maximum_quantity": 3,
"charge_above_quantity": null,
"metadata": {}
},
{
"id": "choose-drink",
"title": { "en_us": "Choose a drink" },
"description": null,
"display_type": "LIST",
"modifier_ids": ["cola", "sprite"],
"minimum_quantity": 1,
"maximum_quantity": 1,
"charge_above_quantity": null,
"metadata": {}
}
],
"menus": [
{
"id": "all-day",
"name": { "en_us": "All day" },
"description": null,
"schedules": null,
"category_ids": ["mains"],
"status": "ACTIVE",
"metadata": {}
}
]
}
Uber Eats style
Sendrecommendations on a full UBER_EATS payload the same way as items, categories, and modifier_groups. Use title.translations instead of name, and keep target_product_id aligned with an items[].id. Fire spark maps the array to the DEFAULT catalog during sync.
"recommendations": [
{
"id": "upsell-meal-combo",
"type": "UPSELL",
"title": { "translations": { "en_us": "Make it a combo" } },
"target_product_id": "meal-combo",
"metadata": {}
},
{
"id": "cross-sell-fries",
"type": "CROSS_SELL",
"title": { "translations": { "en_us": "Add fries" } },
"target_product_id": "fries",
"metadata": {}
},
{
"id": "downsell-burger",
"type": "DOWNSELL",
"title": { "translations": { "en_us": "Burger only" } },
"target_product_id": "burger",
"metadata": {}
}
]
pricing.recommendations pre-selects other products on the parent line.
pricing.modifiers[].recommendations pre-selects quantities inside a modifier
group — use it to ship ready-made premium configurations. default_quantity
on the same modifier entry still controls the baseline when no preset is
applied.Related
Modifier group overrides
Per-group pricing and default quantities on modifier products
Menu sync guide
Full validation rules for recommendations