> ## Documentation Index
> Fetch the complete documentation index at: https://firespark.cloud/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Product recommendations

> Catalog-level recommendations with per-product default quantities and modifier-level defaults.

Use the top-level `recommendations` array to define upsell, cross-sell, and downsell targets once per sync. Attach them in two places:

* **`pricing.recommendations` on a line item** — suggest other catalog products on the parent (combo upgrade, side item, downsell).
* **`pricing.modifiers[].recommendations` on a modifier option** — pre-select modifier quantities when you surface a premium customization preset.

Each linked entry can set its own `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             |

```mermaid theme={null}
flowchart TB
    BURGER["burger"] --> UP["upsell-meal-combo"]
    UP --> COMBO["meal-combo"]
    BURGER --> XS["cross-sell-fries"]
    XS --> FRIES["fries"]
    BURGER --> G2["premium-toppings"]
    G2 --> CHEESE["extra-cheese · recommendations in modifiers"]
    G2 --> BACON["bacon · recommendations in modifiers"]
    COMBO --> DN["downsell-burger"]
    DN --> BURGER
    COMBO --> G1["choose-drink"]
    G1 --> COLA["cola · default_quantity 1 in group"]
```

## Request

Define recommendations in the shared catalog. Link line-item suggestions from `pricing.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.

```bash theme={null}
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
```

```json product-recommendations.json theme={null}
{
  "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

Send `recommendations` 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.

```json theme={null}
"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": {}
  }
]
```

Add this array to a complete Uber Eats menu payload such as [Simple menu](/docs/integrations-api/examples/menu-sync/simple-menu).

<Tip>
  `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.
</Tip>

## Related

<CardGroup cols={2}>
  <Card title="Modifier group overrides" icon="sliders" href="/docs/integrations-api/examples/menu-sync/modifier-group-overrides">
    Per-group pricing and default quantities on modifier products
  </Card>

  <Card title="Menu sync guide" icon="book" href="/docs/integrations-api/guides/menu-sync#validation-rules">
    Full validation rules for recommendations
  </Card>
</CardGroup>
