¿Nuevo en Fire spark?
Lee la introducción a la API de integraciones para autenticación, webhooks y
el modelo completo de integración.
Dónde encaja la sincronización de menús
Tu sistema operativo es dueño de ítems, precios y disponibilidad. Fire spark queda en el medio y publica menús compuestos hacia canales propios y agregadores. Cuando un cliente pide, losid de línea del menú compuesto aparecen en el payload del pedido y en el ticket del POS tras order.status.changed. Mantén los ids externos de producto estables entre la sync de menú y el traspaso a cocina.
Prerrequisitos
Crea tiendas, canales y tipos de fulfillment en el dashboard de Fire spark antes del primer upsert de menú. Cada recurso usa el mismoid externo que empleas en tu POS o RMS.
1
Obtén un access token
Autentica con OAuth 2.0 client credentials. Los endpoints de menú requieren
menus:read y menus:write. Ver
Token.2
Confirma opciones de fulfillment
Verifica que delivery, pickup, dine-in y cualquier tipo custom existan en el
dashboard. Ver List fulfillment.
3
Confirma tiendas
Verifica cada ubicación del comercio y sus ids externos. Las tiendas llevan
disponibilidad por canal y reglas locales. Ver List
stores.
4
Confirma canales
Verifica los canales configurados — app, web, kiosco, agregadores y más. Ver
List channels.
Cómo funciona la composición de menús
Un menú compuesto es el catálogo que ve el cliente para un contexto de venta. Fire spark acota cada menú a una tripleta tienda + canal + fulfillment. Puedes añadir horarios para que la misma tripleta muestre categorías distintas en desayuno vs almuerzo.
Actualizas el POS una vez. Tu integración decide cuántos menús compuestos enviar y qué categorías e ítems incluye cada uno.
Para el contexto de por qué los menús se componen por contexto, ver
Menús. Para disponibilidad de categorías por canal y
tienda, ver Categorías.
Bloques del catálogo
Cada menú compuesto se arma con cuatro tipos de entidad que envías en la misma solicitud.Productos
Un producto es cualquier cosa que puede salir en un ticket: un burger suelto, un combo o una opción modificadora como “Cola”. Envía productos en el arrayproducts de nivel superior en Upsert menus. Cada producto necesita un id externo estable — el mismo valor que tu cocina espera en pedidos inyectados.
Categorías
Las categorías organizan productos para navegar. Cada categoría listaitems — productos y categorías anidadas visibles en esa sección de este menú.
Puedes ocultar una categoría en un canal y mantenerla en otro componiendo menús distintos — sin duplicar maestros de ítem en el POS.
Subcategorías anidadas
El payload de menu sync modela subcategorías como un árbol por referencias, no con un campoparent_id. Declara todas las categorías en el array plano categories[] y arma el árbol con entradas type: "CATEGORY" en items del padre.
Orden de display. El orden en cada array es el orden de display:
Puedes mezclar entradas
CATEGORY y PRODUCT en el mismo items; el orden del array define cómo aparecen juntas en la UI.
Convención recomendada: coloca productos en categorías hoja y usa categorías intermedias solo para navegar. La validación no lo exige, pero evita pantallas donde el cliente ve subcategorías y productos al mismo nivel sin quererlo.
Límite de profundidad: hasta 3 niveles contando la raíz vinculada al menú — raíz (1) → subcategoría (2) → sub-subcategoría (3). Más profundo falla la validación.
Ver el payload completo en Subcategorías anidadas.
Al leer un menú compuesto con List menus,
categories[] incluye solo las categorías raíz de category_ids. Los ids de
subcategoría aparecen en items del padre con type: "CATEGORY" — para
resolver nombre y productos de cada hija, conserva el payload de sync o navega
el árbol desde la raíz en tu integración.Grupos de modificadores y modificadores
La personalización se modela en dos capas:
Los modificadores son productos. Cada entrada en
modifier_ids del grupo es el id externo de otro producto en el mismo payload. Eso implica:
- Una bebida vendida suelta y como modificador de combo comparte un registro de producto.
- Cuando haces 86 de agua sin gas en el POS, pon
availability.statusenOUT_OF_STOCKen ese producto — el modificador desaparece de todos los grupos que lo referencian. - Los tickets de cocina usan ids de producto reales, no notas en texto libre.
pricing.modifier_group_ids. Define reglas de selección en el grupo:
Precio por modificador, cantidad por defecto, tipo de display (
RADIO, CHECKBOX, QUANTITY) y reglas de cobro viven en el producto modificador bajo pricing.modifiers — una entrada por cada modifier_group_id donde ese producto aparece como opción. image_url en esa entrada es opcional y reemplaza la imagen del producto solo dentro de ese grupo. Si la omites, se usa la imagen del producto.
Las imágenes de productos, categorías, variantes y modificadores se copian a almacenamiento público (/storage/v1/object/public/multimedia/...). Las respuestas sirven /storage/v1/render/image/public/...?quality=80. Agrega width, height y resize (cover, contain o fill) en esa URL cuando necesites un tamaño concreto.
Consulta Tipos de display de modificadores para las reglas de cantidad que determinan cada display_type, los errores de validación y ejemplos.
Defaults primero, override solo donde haga falta
Si omites el alcance, Fire spark asume cualquiera. Puedes publicar un menú base y añadir upserts más acotados solo donde tu operación difiere — en lugar de una llamada API por cada combinación de tienda, canal y horario.
Añade
fulfillment_id, store_id, channel_id, brand_id o entradas de horario solo cuando un contexto concreto necesite algo distinto al baseline. Los upserts más específicos aplican solo a ese contexto; no eliminan el default en los contextos que no tocaste.
Orden sugerido de sync (si usas un baseline):
- Envía un default a nivel comercio —
PUT /menussin query params, omitefulfillment_iden cada entrada de menú y usa"schedules": null. Incluye el catálogo completo de productos. - Envía overrides — repite el upsert con
?store_id=…,?channel_id=…,fulfillment_ido un arrayschedulessolo donde el catálogo, precio u horarios difieran del baseline.
Flujo de sincronización
1
Elige el contexto de venta
Decide si este upsert es el default del comercio (omite
store_id,
channel_id y fulfillment_id) o un override acotado para una tienda,
canal y/o tipo de fulfillment. Ver Upsert
menus para los query params.2
Arma el payload
Envía entidades compartidas (
products, categories, modifier_groups)
más hasta 10 entradas en menus. Cada menú referencia category_ids y un
fulfillment_id.3
Haz upsert del menú
Llama
PUT /menus para el baseline, o añade ?store_id=… y/o
?channel_id=… para overrides. Usa "style": "DEFAULT" en canales propios,
o "style": "UBER_EATS" para formato Uber Eats Menu API v2. Ver Upsert
menus.4
Verifica el resultado
Lee menús compuestos con List
menus. Usa
el mismo
store_id y channel_id del upsert. Confirma fulfillment_id,
horarios e ids de producto contra tu mapeo POS.5
Envía cambios incrementales
Para actualizaciones de un ítem — precio, 86, overrides por canal — usa
Update product en lugar de
reenviar el menú completo.
Varios canales, tiendas y modos de fulfillment
Cada menú compuesto se identifica por contexto:fulfillment_id, store_id, channel_id o brand_id, esa dimensión es todas. Aprovéchalo: un upsert baseline con el catálogo completo y overrides solo donde haga falta.
Overrides por ítem entre contextos
Cuando un producto necesita precio o disponibilidad distinta por canal, tienda o tipo de fulfillment sin reemplazar menús enteros, llama a Update product con?store_id=…, ?channel_id=…, ?fulfillment_id=… y/o ?menu_id=… cuando varios menús comparten el mismo scope. El body usa la misma forma de producto de menú que Upsert menus — pricing y availability en el nivel superior, no un objeto channels anidado.
Así piensa el equipo comercial: publica el producto base una vez y luego envía un update acotado con ?store_id y ?channel_id para que la Cola cueste $0 en el combo de la app en downtown, mientras el catálogo default mantiene otro precio.
Las ediciones desde el dashboard o usando nuestro API de sincronización persisten en upserts normales. Para sobrescribir estos cambios, envía x-force: true en Upsert menus. Para preparar una sincronización sin publicarla aún, envía x-publish: false y publícala desde el dashboard cuando esté lista.
Horarios
Los horarios restringen cuándo un menú o entidad individual es pedible.
Usa
null o omite schedules cuando el menú está disponible todo el día — Fire spark lo interpreta como 24 horas, todos los días. Define un array schedules solo cuando la pedibilidad se limita a días o franjas concretas.
Cuando envías un array schedules, Fire spark valida la forma semanal completa:
Los tiempos en
start_time y end_time usan strings ISO (por ejemplo 11:00:00). Usa closed: true cuando el periodo es una ventana cerrada (start_time / end_time pueden omitirse). Usa fechas null como fallback siempre activo; define start_date / end_date para una ventana más específica. Un array periods vacío significa cerrado todo el día.
Varios menús en el mismo sync pueden tener franjas horarias solapadas. Get menu devuelve en data todos los menús compuestos cuyo horario coincide con la hora actual. Cuando ninguno está en horario, devuelve el o los menús cuya próxima ventana comienza antes. Los menús con schedules: null se consideran siempre activos.
Patrones comunes:
- Default siempre activo — Omite horarios (
null) en el menú baseline; añade overrides con horario solo para dayparts que difieren. - Menús por daypart — Ids de menú separados para desayuno y almuerzo en la misma tienda + canal + fulfillment, cada uno con su horario y
category_ids. - Ventanas cerradas — Mantén horas abiertas en un día y añade un periodo con
closed: true(opcionalmente constart_date/end_date) para un feriado o bloqueo de mantenimiento. - Categorías estacionales — Mantén el menú siempre activo; programa
availabilityde la categoría o producto. - 86 temporal — Prefiere
availability.status: OUT_OF_STOCKconout_of_stock_untilpara pausas de ítem sin reconstruir horarios.
Reglas de validación
Fire spark valida el payload completo de Upsert menus antes de encolar un sync. Estas reglas aplican al estiloDEFAULT.
Productos
Categorías
Anidamiento (ver Subcategorías anidadas):
Definiciones de menú
Grupos de modificadores
Recomendaciones
Cuando un sync define varios menús, Fire spark compone cada menú desde el catálogo compartido y conserva solo las recomendaciones cuyo
target_product_id es alcanzable en ese menú — las mismas reglas de composición que products y modifier_groups.
Labels y tags
Los productos y categorías aceptanlabels y tags opcionales. Omite cualquiera de los dos en syncs existentes — Fire spark usa [] y {} por defecto y no rechaza payloads que los dejen fuera.
Estilos de sync
Upsert menus acepta una unión discriminada porstyle:
- DEFAULT
- UBER_EATS
Formato nativo Fire spark para canales propios (app, web, kiosco, call
center). Usa nombres de campo
products, categories, modifier_groups y
objetos name localizados por locale (por ejemplo en_us).Ideal cuando controlas la UI del cliente con la
Storefront API o un front end propio.Sync completa vs actualizaciones incrementales
Mapea ids de vuelta a tu POS
Usa ids externos para mapeo entre sistemas. Usa campos
*_uid solo al referenciar recursos Fire spark en otras llamadas API.
Endpoints relacionados
Upsert menus
Crear o actualizar menús compuestos
List menus
Leer menús para reconciliación
Update product
Enviar cambios por ítem
Order webhooks
Recibir pedidos con los mismos ids de producto
List stores
Leer ids externos de tienda antes que menús
List fulfillment
Leer ids externos de fulfillment antes que menús
Payloads de ejemplo
Payloads listos para copiar en escenarios comunes de sync de menú:Menú simple
3 productos, 1 categoría, 1 grupo de modificadores
Subcategorías anidadas
Categoría raíz con dos subcategorías
Multi horario
2 menús daypart, sin grupos de modificadores
Modificadores multinivel
3 niveles de grupos anidados
Overrides de grupos
Overrides de precio, min y max
Horario de producto
Disponibilidad happy hour en un producto
Recomendaciones de producto
Upsell a combo, cross-sell de acompañamiento y downsell a producto suelto