> ## 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.

# Update product

> Update a product inside a composed menu from your POS or RMS.

Updates a single product within a composed menu. Use this endpoint when your POS or RMS pushes item-level changes — pricing, availability, or bundled items — without replacing the entire menu payload.

The request body uses the same **menu product** shape as products in [Upsert menus](/docs/integrations-api/menus/put). Send only the fields you want to change; omitted fields keep their current values.

<Note>
  Requires an access token with the `menus:write` scope. See
  [Token](/docs/integrations-api/oauth/token/post) to obtain a token.
</Note>

## Path parameters

| Parameter | Description                                                                               |
| --------- | ----------------------------------------------------------------------------------------- |
| `id`      | External product identifier. Alphanumeric characters, `_`, and `-` only. 1–64 characters. |

## Query parameters

| Parameter        | Required | Description                                                                                                                                                                                                                                                       |
| ---------------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `brand_id`       | No       | External brand identifier. Omit or pass `__ANY__` for the merchant-wide default. When set, scope the update to menus for this brand only.                                                                                                                         |
| `store_id`       | No       | External store identifier. Scope the update to menus for this store. Omit or pass `__ANY__` for the merchant-wide default.                                                                                                                                        |
| `channel_id`     | No       | External channel identifier. Scope the update to menus for this channel. Omit or pass `__ANY__` for all channels.                                                                                                                                                 |
| `fulfillment_id` | No       | External fulfillment identifier. When set, scope the update to menus for that fulfillment type only. Omit to update the product in every fulfillment type within the resolved store and channel scope. See [List fulfillment](/docs/integrations-api/fulfillment/get). |
| `menu_id`        | No       | External menu identifier. Scope the update to one composed menu when several menus share the same store, channel, and fulfillment scope — for example lunch and dinner schedules. Omit to update the product in every matching menu.                              |

Combine scope query parameters when a product needs different `pricing` or `availability` in one selling context — the same pattern as scoped menu upserts. Each composed menu is keyed by `fulfillment_id + store_id + channel_id + brand_id + menu.id`; see [Menu sync](/docs/integrations-api/guides/menu-sync#multiple-channels-stores-and-fulfillment-modes).

## Request body

Same shape as a product in the `products` array on [Upsert menus](/docs/integrations-api/menus/put). Every field is optional on update; omitted fields keep their current values. The product `id` is set in the path parameter — omit it from the request body.

<AccordionGroup>
  <Accordion title="products">
    Each product in the request body:

    | Field           | Required | Type           | Description                                                                                                                                                      |
    | --------------- | -------- | -------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- |
    | `id`            | Yes      | string         | External product identifier. Set via the path parameter — omit from the request body.                                                                            |
    | `name`          | Yes      | object         | Localized display name keyed by locale (for example `en_us`).                                                                                                    |
    | `description`   | No       | object \| null | Localized description. `null` when omitted.                                                                                                                      |
    | `image_url`     | No       | string         | Product image URL. `null` when omitted.                                                                                                                          |
    | `bundled_items` | No       | array          | Items included in a bundle or combo. Defaults to `[]`.                                                                                                           |
    | `pricing`       | Yes      | object         | Price, tax, quantity limits, and modifier configuration. See **pricing**.                                                                                        |
    | `availability`  | Yes      | object         | Product availability. See fields below.                                                                                                                          |
    | `labels`        | No       | string\[]      | Short labels for Dashboard filters and quick selection. At most 64 strings (1–128 characters each). Defaults to `[]`.                                            |
    | `tags`          | No       | object         | Key/value tags for advanced custom rules. Values may be boolean, string, or number. Defaults to `{}`. See [Custom rules](/docs/integrations-api/guides/custom-rules). |
    | `metadata`      | No       | object         | Partner-specific metadata. Defaults to `{}`.                                                                                                                     |

    Each `availability` object:

    | Field                | Required | Type          | Description                                                                                      |
    | -------------------- | -------- | ------------- | ------------------------------------------------------------------------------------------------ |
    | `status`             | Yes      | string        | `AVAILABLE`, `UNAVAILABLE`, or `OUT_OF_STOCK`.                                                   |
    | `schedules`          | No       | array \| null | Schedule entries with `day_of_week` and `periods`. `null` when there is no schedule restriction. |
    | `out_of_stock_until` | No       | string        | Optional ISO 8601 datetime when the product returns to stock.                                    |

    Each `bundled_items` entry:

    | Field               | Required | Type   | Description                                                             |
    | ------------------- | -------- | ------ | ----------------------------------------------------------------------- |
    | `id`                | Yes      | string | External identifier of the bundled product.                             |
    | `refund_price`      | Yes      | number | Refund amount when the customer removes this item from the bundle. ≥ 0. |
    | `included_quantity` | Yes      | number | Units included by default. ≥ 0.                                         |

    ```json Example product theme={null}
    {
      "id": "burger-classic",
      "name": { "en_us": "Classic burger" },
      "description": { "en_us": "Angus beef patty with lettuce and tomato." },
      "image_url": "https://cdn.example.com/burger-classic.jpg",
      "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,
        "modifiers": [],
        "modifier_group_ids": ["choose-drink"]
      },
      "availability": {
        "status": "AVAILABLE",
        "schedules": null,
        "out_of_stock_until": null
      },
      "metadata": {}
    }
    ```
  </Accordion>

  <Accordion title="pricing">
    Product pricing in the request body:

    | Field                     | Required | Type    | Description                                                                     |
    | ------------------------- | -------- | ------- | ------------------------------------------------------------------------------- |
    | `minimum_quantity`        | Yes      | number  | Minimum units per order. ≥ 0.                                                   |
    | `maximum_quantity`        | Yes      | number  | Maximum units per order. 0–1,000,000.                                           |
    | `is_tax_inclusive`        | Yes      | boolean | Whether `price` includes tax.                                                   |
    | `tax_rate`                | Yes      | number  | Tax rate as a decimal (for example `0.15` for 15%). 0–1.                        |
    | `price`                   | Yes      | number  | List price. ≥ 0.                                                                |
    | `anchor_price`            | Yes      | number  | Reference price for strikethrough or comparison. ≥ 0.                           |
    | `anchor_price_percentage` | Yes      | number  | Discount shown relative to `anchor_price`. 0–1.                                 |
    | `modifiers`               | No       | array   | Per-group pricing and selection overrides. Defaults to `[]`.                    |
    | `modifier_group_ids`      | No       | array   | External modifier group identifiers attached to this product. Defaults to `[]`. |

    Each object in `modifiers` configures one modifier group referenced in `modifier_group_ids`. It accepts the same pricing fields as the parent product, plus modifier-specific fields:

    | Field                     | Required | Type    | Description                                                                     |
    | ------------------------- | -------- | ------- | ------------------------------------------------------------------------------- |
    | `modifier_group_id`       | Yes      | string  | External modifier group identifier. Must match a group in `modifier_group_ids`. |
    | `minimum_quantity`        | Yes      | number  | Minimum units per order for modifiers in this group. ≥ 0.                       |
    | `maximum_quantity`        | Yes      | number  | Maximum units per order for modifiers in this group. 0–1,000,000.               |
    | `is_tax_inclusive`        | Yes      | boolean | Whether `price` includes tax for modifiers in this group.                       |
    | `tax_rate`                | Yes      | number  | Tax rate as a decimal (for example `0.15` for 15%). 0–1.                        |
    | `price`                   | Yes      | number  | List price for modifiers in this group. ≥ 0.                                    |
    | `anchor_price`            | Yes      | number  | Reference price for strikethrough or comparison. ≥ 0.                           |
    | `anchor_price_percentage` | Yes      | number  | Discount shown relative to `anchor_price`. 0–1.                                 |
    | `default_quantity`        | Yes      | number  | Pre-selected quantity for modifiers in this group. ≥ 0.                         |
    | `charge_above_quantity`   | No       | number  | Free selections before charges apply. Optional.                                 |
    | `display_type`            | No       | string  | How modifiers render in the UI: `RADIO`, `CHECKBOX`, or `QUANTITY`. Optional.   |

    ```json Example modifiers entry theme={null}
    {
      "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": 0,
      "display_type": "RADIO"
    }
    ```
  </Accordion>
</AccordionGroup>

## Response

Returns the updated product in `data` — the same shape as a product in [List menus](/docs/integrations-api/menus/get), including `id`, `name`, `pricing`, `availability`, `bundled_items`, and `metadata`.

## Error responses

| Status | Description                                     |
| ------ | ----------------------------------------------- |
| `400`  | Validation error.                               |
| `401`  | Missing or invalid access token.                |
| `403`  | Token does not include the `menus:write` scope. |
| `404`  | No product with this `id` exists in the menu.   |


## OpenAPI

````yaml PUT /menus/products/{id}
openapi: 3.0.1
info:
  title: Fire spark Integrations API
  description: POS and RMS integration endpoints for Fire spark.
  version: 1.0.0
servers:
  - url: https://firespark.cloud/api/integrations/v1
security:
  - bearerAuth: []
paths:
  /menus/products/{id}:
    put:
      summary: Update product
      parameters:
        - in: path
          name: id
          required: true
          schema:
            type: string
            minLength: 1
            maxLength: 64
            pattern: ^[a-zA-Z0-9_-]+$
          description: External product identifier.
        - in: query
          name: fulfillment_id
          required: false
          schema:
            type: string
            minLength: 1
            maxLength: 64
            pattern: ^[a-zA-Z0-9_-]+$
          description: External fulfillment identifier. Omit for all fulfillment types.
        - in: query
          name: store_id
          required: false
          schema:
            type: string
            minLength: 1
            maxLength: 64
            pattern: ^[a-zA-Z0-9_-]+$
          description: External store identifier.
        - in: query
          name: channel_id
          required: false
          schema:
            type: string
            minLength: 1
            maxLength: 64
            pattern: ^[a-zA-Z0-9_-]+$
          description: External channel identifier.
        - in: query
          name: brand_id
          required: false
          schema:
            type: string
            minLength: 1
            maxLength: 64
            pattern: ^[a-zA-Z0-9_-]+$
          description: >-
            External brand identifier. Alphanumeric characters, _, and - only.
            1–64 characters.
        - in: query
          name: menu_id
          required: false
          schema:
            type: string
            minLength: 1
            maxLength: 64
            pattern: ^[a-zA-Z0-9_-]+$
          description: >-
            External menu identifier. Omit to update every matching menu in the
            scope.
      requestBody:
        required: true
        description: Product fields to create or update.
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/MenuProductPatchBody'
      responses:
        '200':
          description: Ok
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    $ref: '#/components/schemas/MenuProductUpsert'
components:
  schemas:
    MenuProductPatchBody:
      type: object
      description: >-
        Partial menu product update. Same fields as MenuProductUpsert except id
        (from path).
      properties:
        name:
          $ref: '#/components/schemas/MultiLanguageText'
        description:
          allOf:
            - $ref: '#/components/schemas/MultiLanguageText'
          nullable: true
        image_url:
          type: string
          format: uri
          nullable: true
        cms_template_id:
          type: string
          format: uuid
          nullable: true
        status:
          type: string
          enum:
            - ACTIVE
            - INACTIVE
        bundled_items:
          type: array
          items:
            type: object
        pricing:
          type: object
        availability:
          type: object
        metadata:
          type: object
          additionalProperties: true
    MenuProductUpsert:
      type: object
      required:
        - id
        - name
        - status
        - pricing
        - availability
      properties:
        id:
          type: string
          minLength: 1
          maxLength: 64
          pattern: ^[a-zA-Z0-9_-]+$
        name:
          $ref: '#/components/schemas/MultiLanguageText'
        description:
          allOf:
            - $ref: '#/components/schemas/MultiLanguageText'
          nullable: true
        image_url:
          type: string
          format: uri
          nullable: true
        cms_template_id:
          type: string
          format: uuid
          nullable: true
        status:
          type: string
          enum:
            - ACTIVE
            - INACTIVE
        bundled_items:
          type: array
          items:
            type: object
        pricing:
          type: object
        availability:
          type: object
        labels:
          type: array
          items:
            type: string
            minLength: 1
            maxLength: 128
          maxItems: 64
          default: []
        tags:
          type: object
          additionalProperties:
            oneOf:
              - type: boolean
              - type: string
              - type: number
          default: {}
        metadata:
          type: object
          additionalProperties: true
    MultiLanguageText:
      type: object
      additionalProperties:
        type: string
      example:
        en_us: Example
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer

````