Upsert menus
Create or update composed menus from your POS or RMS in Fire spark.
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.
menus:write scope. See
Token to obtain a token.Headers
Query parameters
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 onstyle. Fire spark validates each variant against a different schema.
"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 usePUT with scope query parameters (fulfillment_id, store_id, channel_id, brand_id).
- Default
- Uber Eats
name, pricing, items, and so on).Request body
- Default
- Uber Eats
Menu fields
Each object inmenus accepts these writable fields:products
products
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: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. |categories
categories
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:availability object:modifier_groups
modifier_groups
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 {}. |recommendations
recommendations
pricing
pricing
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: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. |Response
The endpoint returns asynchronously. Fire spark starts a background menu sync and responds immediately.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:
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
Bearer authentication header of the form Bearer <token>, where <token> is your auth token.
Headers
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.
1 - 64^[a-zA-Z0-9_-]+$When true or 1, menu changes in the dashboard and via API will be overwritten; otherwise, existing changes persist.
true, false, 1, 0 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.
true, false, 1, 0 Query Parameters
External fulfillment identifier used to scope the upsert. Omit or pass ANY for all fulfillment types.
1 - 64^[a-zA-Z0-9_-]+$External store identifier used to scope the upsert.
1 - 64^[a-zA-Z0-9_-]+$External channel identifier used to scope the upsert.
1 - 64^[a-zA-Z0-9_-]+$Scope the upsert to menus for this brand. Omit or pass ANY for the merchant-wide default.
1 - 64^[a-zA-Z0-9_-]+$Body
Composed menu payload. Use style DEFAULT or UBER_EATS.
Response
Ok