Skip to main content
PUT
Creates or updates composed menus for the authenticated merchant. Send catalog entities once at the top level, then reference them from up to 10 menu definitions in the same request. Each menu in menus is matched by id. When no menu exists with that id for the merchant, Fire spark creates it. When one already exists, Fire spark updates the writable fields below. Omitted fields keep their current values on update. Scope the upsert with optional query parameters. Fire spark resolves organization and merchant context from your access token.
Requires an access token with the menus:write scope. See Token to obtain a token.
Menu id values are immutable. You cannot change an existing menu’s id through this endpoint — send the same id you use in your POS or RMS on every sync.

Headers

Query parameters

Omit scope query parameters for an optional merchant-wide default — useful when store, channel, or fulfillment is not chosen yet. Add fulfillment_id, store_id, channel_id, and/or brand_id to override that default for a specific selling context. Omit a scope parameter or pass __ANY__ to store the wildcard for that dimension. See Menu sync for the recommended baseline-and-override workflow.

Sync styles

The request body is a discriminated union on style. Fire spark validates each variant against a different schema. Send "style": "DEFAULT" or "style": "UBER_EATS" at the top level. Shared catalog entities and up to 10 menu definitions are sent in the same request for both styles.

Request

Switch between DEFAULT and UBER_EATS in the request examples panel to see both payload shapes. Both calls use PUT with scope query parameters (fulfillment_id, store_id, channel_id, brand_id).
Fire spark native payload. Products, categories, and modifier groups use Fire spark field names (name, pricing, items, and so on).

Request body

Each object in menus accepts these writable fields:
Each product in the request body:| id | Yes | string | External product identifier. | | 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. | | metadata | No | object | Partner-specific metadata. Defaults to {}. |Each availability object:Each bundled_items entry:| 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. |
Example product
Each category in the request body:| id | Yes | string | External category identifier. | | name | Yes | object | Localized display name keyed by locale. | | description | No | object | null | Localized description. null when omitted. | | items | Yes | array | Ordered category entries. At least 1 entry. At most 1000. | | availability | Yes | object | Category 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. | | metadata | No | object | Partner-specific metadata. Defaults to {}. |Each entry in items:Each availability object:
Example category
Each modifier group in the request body:| id | Yes | string | External modifier group identifier. Referenced from pricing.modifier_group_ids. | | title | Yes | object | Localized group title keyed by locale. | | description | No | object | null | Localized description. null when omitted. | | display_type | No | string | GRID or LIST. | | modifier_ids | Yes | array | Product UUIDs for modifiers in this group. At least 2 entries. | | minimum_quantity | Yes | number | Minimum selections required. ≥ 0. | | maximum_quantity | Yes | number | Maximum selections allowed. 0–1,000,000. | | charge_above_quantity | No | number | Number of free selections before additional charges apply. Optional. | | metadata | No | object | Partner-specific metadata. Defaults to {}. |
Example modifier group
Each recommendation in the top-level catalog:
Example recommendation
Product pricing in the request body:| 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 []. | | recommendations_ids | No | array | Recommendation ids to surface on this product. Each id must exist in top-level recommendations. Defaults to []. | | recommendations | No | array | Per-recommendation display settings on this product. Defaults to []. |Each object in recommendations (inside pricing) links one catalog recommendation to the parent product: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:| 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. |
Example modifiers entry

Response

The endpoint returns asynchronously. Fire spark starts a background menu sync and responds immediately. Treat 202 as success: the catalog is already being processed. Retry only after the current sync finishes or fails. Treat 409 as success when replaying a release that already completed successfully. If the prior sync for that release and scope FAILED or was CANCELLED, send the same x-release-id again.

Rate limits

GET and PUT /api/integrations/v1/menus share a limit of 10 requests per 10 seconds per merchant. The limit key is the merchant_id from your access token. Send one request at a time per merchant — wait for each response before starting the next. Do not parallelize menu upserts or reads for the same merchant. Every response includes rate limit headers so you know when you can send the next request: When you exceed the limit, the API returns 429 Too Many Requests. Wait Retry-After seconds (or X-RateLimit-Reset) before sending another request for that merchant.

Error responses

| Status | Description | | ------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --- | | 400 | Validation error — invalid field values, missing required fields, or invalid weekly schedule shape. See Validation rules. | | 401 | Missing or invalid access token. | | 403 | Token does not include the menus:write scope. | | 409 | Referenced store, channel, or fulfillment does not exist for this merchant, or a sync already exists for this release and scope. | | 429 | Rate limit exceeded — wait for Retry-After / X-RateLimit-Reset before retrying. See Rate limits. | |

Authorizations

Authorization
string
header
required

Bearer authentication header of the form Bearer <token>, where <token> is your auth token.

Headers

x-release-id
string

Optional release identifier for this sync. Alphanumeric characters, _, and - only. 1–64 characters. When omitted, Fire spark generates a value like v2026-07-10-21h. Reuse the same value across scopes in a multi-scope rollout. Each scope accepts a given release only once while a sync is processing or after it succeeds; failed or cancelled syncs do not block retries.

Required string length: 1 - 64
Pattern: ^[a-zA-Z0-9_-]+$
x-force
enum<string>

When true or 1, menu changes in the dashboard and via API will be overwritten; otherwise, existing changes persist.

Available options:
true,
false,
1,
0
x-publish
enum<string>
default:true

Defaults to true. When false or 0, the sync pauses before publishing so you can review and publish from the dashboard. With x-force true, the pause happens before override pruning as well.

Available options:
true,
false,
1,
0

Query Parameters

fulfillment_id
string

External fulfillment identifier used to scope the upsert. Omit or pass ANY for all fulfillment types.

Required string length: 1 - 64
Pattern: ^[a-zA-Z0-9_-]+$
store_id
string

External store identifier used to scope the upsert.

Required string length: 1 - 64
Pattern: ^[a-zA-Z0-9_-]+$
channel_id
string

External channel identifier used to scope the upsert.

Required string length: 1 - 64
Pattern: ^[a-zA-Z0-9_-]+$
brand_id
string

Scope the upsert to menus for this brand. Omit or pass ANY for the merchant-wide default.

Required string length: 1 - 64
Pattern: ^[a-zA-Z0-9_-]+$

Body

application/json

Composed menu payload. Use style DEFAULT or UBER_EATS.

style
enum<string>
required
Available options:
DEFAULT
products
object[]
required
Required array length: 1 - 1000 elements
categories
object[]
required
Required array length: 1 - 100 elements
menus
object[]
required
Required array length: 1 - 10 elements
modifier_groups
object[] | null
Maximum array length: 100

Response

200 - application/json

Ok

data
object[]