Skip to main content
Crea o actualiza menús compuestos para el comercio autenticado. Envía las entidades del catálogo una sola vez en el nivel superior y referencia hasta 10 definiciones de menú en la misma solicitud. Cada menú en menus se empareja por id. Si no existe un menú con ese id para el comercio, Fire spark lo crea. Si ya existe, Fire spark actualiza los campos editables indicados abajo. Los campos omitidos conservan su valor actual en una actualización. Acota el upsert con parámetros de consulta opcionales. Fire spark resuelve el contexto de organización y comercio desde tu access token.
Requiere un access token con el scope menus:write. Consulta Token para obtener un token.
Los valores de id del menú son inmutables. No puedes cambiar el id de un menú existente mediante este endpoint — envía el mismo id que usas en tu POS o RMS en cada sincronización.

Headers

Parámetros de consulta

Omite los parámetros de scope para un default opcional a nivel comercio — útil cuando aún no se eligió tienda, canal o fulfillment. Añade fulfillment_id, store_id, channel_id y/o brand_id para sobreescribir ese default en un contexto concreto. Omite un parámetro de scope o envía __ANY__ para persistir el wildcard en esa dimensión. Consulta Sincronización de menús para el flujo baseline y overrides recomendado.

Estilos de sync

El cuerpo de la solicitud es una unión discriminada por style. Fire spark valida cada variante con un esquema distinto. Envía "style": "DEFAULT" o "style": "UBER_EATS" en el nivel superior. En ambos estilos se envían las entidades del catálogo y hasta 10 definiciones de menú en la misma solicitud.

Request

Alterna entre DEFAULT y UBER_EATS en el panel de ejemplos de solicitud para ver ambas formas de payload. Ambas llamadas usan PUT con parámetros de scope (fulfillment_id, store_id, channel_id, brand_id).
Payload nativo de Fire spark. Productos, categorías y grupos de modificadores usan nombres de campo de Fire spark (name, pricing, items, etc.).

Cuerpo de la solicitud

Campos del menú

Cada objeto en menus acepta estos campos editables:
Cada producto en el cuerpo de la solicitud:| id | Sí | string | Identificador externo del producto. | | name | Sí | object | Nombre visible localizado por locale (por ejemplo en_us). | | description | No | object | null | Descripción localizada. null si se omite. | | image_url | No | string | URL de imagen del producto. JPG, PNG o WebP. Fire spark la copia a almacenamiento público y la sirve como URL de render para que agregues width, height y resize. null si se omite. | | bundled_items | No | array | Ítems incluidos en un bundle o combo. Por defecto []. | | pricing | Sí | object | Precio, impuestos, límites de cantidad y configuración de modificadores. Ver pricing. | | availability | Sí | object | Disponibilidad del producto. Ver campos abajo. | | labels | No | string[] | Etiquetas cortas para filtros y selección rápida en el Dashboard. Como máximo 64 cadenas (1–128 caracteres cada una). Por defecto []. | | tags | No | object | Tags clave/valor para reglas personalizadas avanzadas. Los valores pueden ser boolean, string o number. Por defecto {}. Ver Reglas personalizadas. | | metadata | No | object | Metadatos del partner. Por defecto {}. |Cada objeto availability:Cada entrada de bundled_items:| id | Sí | string | Identificador externo del producto incluido. | | refund_price | Sí | number | Monto de reembolso si el cliente quita este ítem del bundle. ≥ 0. | | included_quantity | Sí | number | Unidades incluidas por defecto. ≥ 0. |
Ejemplo de producto
Cada categoría en el cuerpo de la solicitud:| id | Sí | string | Identificador externo de la categoría. | | name | Sí | object | Nombre visible localizado por locale. | | description | No | object | null | Descripción localizada. null si se omite. | | image_url | No | string | URL de imagen de la categoría. Debe ser JPG, PNG o WebP. null si se omite. | | items | Sí | array | Entradas ordenadas de la categoría. Al menos 1 entrada. Como máximo 1000. | | availability | Sí | object | Disponibilidad de la categoría. Ver campos abajo. | | labels | No | string[] | Etiquetas cortas para filtros y selección rápida en el Dashboard. Como máximo 64 cadenas (1–128 caracteres cada una). Por defecto []. | | tags | No | object | Tags clave/valor para reglas personalizadas avanzadas. Los valores pueden ser boolean, string o number. Por defecto {}. Ver Reglas personalizadas. | | metadata | No | object | Metadatos del partner. Por defecto {}. |Cada entrada en items:Cada objeto availability:
Ejemplo de categoría
Cada grupo de modificadores en el cuerpo de la solicitud:| id | Sí | string | Identificador externo del grupo de modificadores. Referenciado desde pricing.modifier_group_ids. | | title | Sí | object | Título localizado del grupo por locale. | | description | No | object | null | Descripción localizada. null si se omite. | | display_type | No | string | GRID o LIST. | | modifier_ids | Sí | array | UUIDs de productos modificadores en este grupo. 1–100 entradas. Un grupo de una sola opción es válido. | | minimum_quantity | Sí | number | Selecciones mínimas requeridas. ≥ 0. | | maximum_quantity | Sí | number | Selecciones máximas permitidas. 0–1,000,000. | | charge_above_quantity | No | number | Selecciones gratuitas antes de cobrar adicionales. Opcional. | | metadata | No | object | Metadatos del partner. Por defecto {}. |
Ejemplo de grupo de modificadores
Cada recomendación en el catálogo de nivel superior:
Ejemplo de recomendación
Cada grupo de variantes:Cada entrada en variants:
Example variant group
Precio de producto en el cuerpo de la solicitud:| minimum_quantity | No | number | Unidades mínimas por pedido. ≥ 0. Por defecto 0. | | maximum_quantity | No | number | Unidades máximas por pedido. 0–1,000,000. Por defecto 1000000. | | is_tax_inclusive | Sí | boolean | Si price incluye impuestos. | | tax_rate | Sí | number | Tasa de impuesto como decimal (por ejemplo 0.15 para 15%). 0–1. | | price | Sí | number | Precio de lista. ≥ 0. | | anchor_price | No | number | Precio de referencia para tachado o comparación. ≥ 0. | | anchor_price_percentage | No | number | Descuento mostrado respecto a anchor_price. 0–1. | | starting_price | No | number | null | Precio “Desde” de referencia. Si lo omites, Fire spark calcula durante el sync el precio más bajo que cumple todos los modificadores obligatorios. Envía null para no mostrarlo nunca. ≥ 0. | | modifiers | No | array | Overrides de precio y selección por grupo. Por defecto []. | | modifier_group_ids | No | array | Identificadores externos de grupos de modificadores del producto. Por defecto []. | | variant_group_ids | No | array | Grupos de variantes que se preguntan en este producto base. Cada id debe existir en variant_groups y aparecer una vez. Un producto con grupos de variantes no puede tener modifier_group_ids. Por defecto []. Mira Variantes. | | variants | No | array | Cuando este producto es una variante: una entrada por base, cada una { "product_id": id de la base, "variant_group_option_ids": [...] } con exactamente una opción de cada grupo de la base. Por defecto []. | | recommendations_ids | No | array | IDs de recomendaciones a mostrar en este producto. Cada id debe existir en recommendations de nivel superior. Por defecto []. | | recommendations | No | array | Configuración de visualización por recomendación en este producto. Por defecto []. |Cada objeto en recommendations (dentro de pricing) vincula una recomendación del catálogo al producto padre:Cada objeto en modifiers configura un grupo de modificadores referenciado en modifier_group_ids. Acepta los mismos campos de precio que el producto padre, más campos específicos del modificador:| modifier_group_id | Sí | string | Identificador externo del grupo de modificadores. Debe coincidir con un grupo en modifier_group_ids. | | minimum_quantity | No | number | Unidades mínimas por pedido para modificadores de este grupo. ≥ 0. Por defecto 0. | | maximum_quantity | No | number | Unidades máximas por pedido para modificadores de este grupo. 0–1,000,000. | | is_tax_inclusive | Sí | boolean | Si price incluye impuestos para modificadores de este grupo. | | tax_rate | Sí | number | Tasa de impuesto como decimal (por ejemplo 0.15 para 15%). 0–1. | | price | Sí | number | Precio de lista para modificadores de este grupo. ≥ 0. | | anchor_price | No | number | Precio de referencia para tachado o comparación. ≥ 0. | | anchor_price_percentage | No | number | Descuento mostrado respecto a anchor_price. 0–1. | | default_quantity | Sí | number | Cantidad preseleccionada para modificadores de este grupo. ≥ 0. | | charge_above_quantity | No | number | Selecciones gratuitas antes de cobrar adicionales. Opcional. | | display_type | No | string | Cómo se muestran los modificadores en la UI: RADIO, CHECKBOX o QUANTITY. Opcional. | | image_url | No | string | Imagen de este producto solo en este grupo de modificadores. JPG, PNG o WebP. Omítela para conservar la imagen del producto. Se copia a almacenamiento público igual que las imágenes de producto. |
Ejemplo de entrada en modifiers

Response

El endpoint responde de forma asíncrona. Fire spark inicia una sincronización de menú en segundo plano y responde de inmediato. Trata 202 como éxito: el catálogo ya se está procesando. Reintenta solo cuando el sync actual termine o falle. Trata 409 como éxito al reenviar un release que ya completó. Si el sync previo para ese release y scope está en FAILED o CANCELLED, reenvía el mismo x-release-id.

Límites de tasa

GET y PUT /api/integrations/v1/menus comparten un límite de 30 solicitudes por 10 segundos por comercio. La clave es el merchant_id de tu access token. Envía una solicitud a la vez por comercio — espera la respuesta antes de iniciar la siguiente. No paralelices upserts ni lecturas de menú para el mismo comercio. Cada respuesta incluye headers de rate limit para saber cuándo puedes emitir la siguiente solicitud: Si superas el límite, la API responde 429 Too Many Requests. Espera Retry-After segundos (o X-RateLimit-Reset) antes de enviar otra solicitud para ese comercio.

Respuestas de error

| Estado | Descripción | | ------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --- | | 400 | Error de validación — valores inválidos, campos requeridos ausentes o forma semanal inválida. El cuerpo es { "error": "Invalid fields", "details": { "<path>": "<message>" } }. Ver Reglas de validación. | | 401 | Access token ausente o inválido. | | 403 | El token no incluye el scope menus:write. | | 409 | La tienda, canal o fulfillment referenciados no existen para este comercio, o ya existe un sync para el mismo release y scope. | | 429 | Límite de tasa excedido — espera Retry-After / X-RateLimit-Reset antes de reintentar. Ver Límites de tasa. | |