GET https://api.fire.rest/api/v1/fire/external/stores/550e8400-e29b-41d4-a716-446655440000/menu?channel=KIOSK&fulfillmentType=DINE_IN
x-api-key: <tu_api_key>
{
"success": true,
"data": {
"menu": {
"list": {
"listId": "812-KIOSK-DINE_IN",
"listName": "KIOSK - Store 812",
"storeId": "aa11bb22-0000-4000-8000-000000000002",
"storeName": "Quicentro",
"channelId": "cc33dd44-0000-4000-8000-000000000009",
"channelReferenceName": "DINE_IN",
"timezone": "America/Guayaquil"
},
"categories": [
{
"productCategoryId": "cat_001",
"name": "Burgers",
"assignedAt": "2026-09-20T12:00:00Z",
"productListing": [ { "productId": "prod_001", "position": 1 } ]
}
],
"products": [
{
"productId": "prod_001",
"name": "Classic Burger",
"type": "PRODUCTO",
"active": true,
"priceInfo": { "price": 4.5 },
"productModifiers": [ { "modifierId": "mod_001", "position": 1 } ]
},
{
"productId": "prod_size_small",
"name": "Small",
"type": "MODIFIER",
"active": true,
"priceInfo": { "price": 0 },
"productModifiers": []
},
{
"productId": "prod_size_large",
"name": "Large",
"type": "MODIFIER",
"active": true,
"priceInfo": { "price": 0.5 },
"productModifiers": []
}
],
"modifierGroups": [
{
"modifierId": "mod_001",
"modifier": "Choose your size",
"minOptions": 1,
"maxOptions": 1,
"type": "RADIO",
"modifierOptions": [
{ "optionId": "opt_001", "productId": "prod_size_small", "name": "Small", "position": 1 },
{ "optionId": "opt_002", "productId": "prod_size_large", "name": "Large", "position": 2 }
]
}
]
},
"sync": {
"status": "FAILED",
"generatedAt": "2026-09-29T09:00:00Z",
"syncedAt": "2026-09-28T10:00:04Z"
}
}
}
{
"success": false,
"error": "VALIDATION_ERROR",
"message": "channel and fulfillmentType are required"
}
{
"success": false,
"error": "UNAUTHORIZED",
"message": "Invalid or missing API key"
}
{
"success": false,
"error": "FORBIDDEN",
"message": "API key does not have required scope: menu:read"
}
{
"success": false,
"error": "NOT_FOUND",
"message": "Store not found"
}
{
"success": false,
"error": "MENU_NOT_AVAILABLE",
"message": "This terna has no menu available"
}
API
Obtener menú
Lee el último menú generado de una terna de tienda (canal × tipo de fulfillment), con su estado de sincronización.
GET
/
api
/
v1
/
fire
/
external
/
stores
/
{storeId}
/
menu
GET https://api.fire.rest/api/v1/fire/external/stores/550e8400-e29b-41d4-a716-446655440000/menu?channel=KIOSK&fulfillmentType=DINE_IN
x-api-key: <tu_api_key>
{
"success": true,
"data": {
"menu": {
"list": {
"listId": "812-KIOSK-DINE_IN",
"listName": "KIOSK - Store 812",
"storeId": "aa11bb22-0000-4000-8000-000000000002",
"storeName": "Quicentro",
"channelId": "cc33dd44-0000-4000-8000-000000000009",
"channelReferenceName": "DINE_IN",
"timezone": "America/Guayaquil"
},
"categories": [
{
"productCategoryId": "cat_001",
"name": "Burgers",
"assignedAt": "2026-09-20T12:00:00Z",
"productListing": [ { "productId": "prod_001", "position": 1 } ]
}
],
"products": [
{
"productId": "prod_001",
"name": "Classic Burger",
"type": "PRODUCTO",
"active": true,
"priceInfo": { "price": 4.5 },
"productModifiers": [ { "modifierId": "mod_001", "position": 1 } ]
},
{
"productId": "prod_size_small",
"name": "Small",
"type": "MODIFIER",
"active": true,
"priceInfo": { "price": 0 },
"productModifiers": []
},
{
"productId": "prod_size_large",
"name": "Large",
"type": "MODIFIER",
"active": true,
"priceInfo": { "price": 0.5 },
"productModifiers": []
}
],
"modifierGroups": [
{
"modifierId": "mod_001",
"modifier": "Choose your size",
"minOptions": 1,
"maxOptions": 1,
"type": "RADIO",
"modifierOptions": [
{ "optionId": "opt_001", "productId": "prod_size_small", "name": "Small", "position": 1 },
{ "optionId": "opt_002", "productId": "prod_size_large", "name": "Large", "position": 2 }
]
}
]
},
"sync": {
"status": "FAILED",
"generatedAt": "2026-09-29T09:00:00Z",
"syncedAt": "2026-09-28T10:00:04Z"
}
}
}
{
"success": false,
"error": "VALIDATION_ERROR",
"message": "channel and fulfillmentType are required"
}
{
"success": false,
"error": "UNAUTHORIZED",
"message": "Invalid or missing API key"
}
{
"success": false,
"error": "FORBIDDEN",
"message": "API key does not have required scope: menu:read"
}
{
"success": false,
"error": "NOT_FOUND",
"message": "Store not found"
}
{
"success": false,
"error": "MENU_NOT_AVAILABLE",
"message": "This terna has no menu available"
}
Próximamente. El diseño está cerrado pero este endpoint todavía no está implementado. Esta
página describe el contrato acordado para que los integradores puedan planificar antes del
release.
menu.updated. Usá
Listar menús para descubrir qué ternas de una tienda tienen hoy uno.
Autenticación
string
requerido
Tu API key de Fire con scope
menu:read. La key debe ser vendor-scoped (binding account +
vendor) — las keys sin vendorId se rechazan con 403.Path params
string
requerido
UUID de la tienda (
stores.id).Query params
No existe una terna por defecto — Fire nunca adivina una por tu cuenta. Los dos parámetros son
obligatorios; si falta alguno, la respuesta es
400.string
requerido
Código del canal de venta (ej.
KIOSK). Se compara sin distinguir mayúsculas.string
requerido
Código del tipo de fulfillment (ej.
DINE_IN, TAKEAWAY). Se compara sin distinguir mayúsculas.Petición
GET https://api.fire.rest/api/v1/fire/external/stores/550e8400-e29b-41d4-a716-446655440000/menu?channel=KIOSK&fulfillmentType=DINE_IN
x-api-key: <tu_api_key>
Respuesta
object
Mismo shape que
data.menu en el webhook menu.updated
— list, categories, products, modifierGroups — con el mismo enriquecimiento que hoy reciben
los agregadores (ids internos en list.storeId / list.channelId, categories[].assignedAt). Ver
esa página para la referencia completa de campos.Mostrar brechas conocidas
Mostrar brechas conocidas
productModifiers[] y modifierGroups[].modifierOptions[] todavía no llevan active ni
assignedAt — la misma brecha que tiene hoy el payload del webhook. Este endpoint devuelve
exactamente lo que se emite; la brecha se cierra del lado del emisor, y esta respuesta hereda
el arreglo.Mismo shape también para canales tipo X-MART.
KIOSK (authType: XMART_LOGIN — ver
channel.updated) es uno de ellos: su payload guardado
lleva además el número de tienda y el id externo del canal, ya plegados en el list de arriba.object
Mostrar sync
Mostrar sync
string
SYNCED | FAILED | PENDING — el último intento de envío de esta versión del menú.string
Timestamp ISO 8601 de esta versión del menú.
string | null
Timestamp ISO 8601 de la última entrega exitosa.
null si nunca sincronizó. Ver Semántica de syncedAt.{
"success": true,
"data": {
"menu": {
"list": {
"listId": "812-KIOSK-DINE_IN",
"listName": "KIOSK - Store 812",
"storeId": "aa11bb22-0000-4000-8000-000000000002",
"storeName": "Quicentro",
"channelId": "cc33dd44-0000-4000-8000-000000000009",
"channelReferenceName": "DINE_IN",
"timezone": "America/Guayaquil"
},
"categories": [
{
"productCategoryId": "cat_001",
"name": "Burgers",
"assignedAt": "2026-09-20T12:00:00Z",
"productListing": [ { "productId": "prod_001", "position": 1 } ]
}
],
"products": [
{
"productId": "prod_001",
"name": "Classic Burger",
"type": "PRODUCTO",
"active": true,
"priceInfo": { "price": 4.5 },
"productModifiers": [ { "modifierId": "mod_001", "position": 1 } ]
},
{
"productId": "prod_size_small",
"name": "Small",
"type": "MODIFIER",
"active": true,
"priceInfo": { "price": 0 },
"productModifiers": []
},
{
"productId": "prod_size_large",
"name": "Large",
"type": "MODIFIER",
"active": true,
"priceInfo": { "price": 0.5 },
"productModifiers": []
}
],
"modifierGroups": [
{
"modifierId": "mod_001",
"modifier": "Choose your size",
"minOptions": 1,
"maxOptions": 1,
"type": "RADIO",
"modifierOptions": [
{ "optionId": "opt_001", "productId": "prod_size_small", "name": "Small", "position": 1 },
{ "optionId": "opt_002", "productId": "prod_size_large", "name": "Large", "position": 2 }
]
}
]
},
"sync": {
"status": "FAILED",
"generatedAt": "2026-09-29T09:00:00Z",
"syncedAt": "2026-09-28T10:00:04Z"
}
}
}
{
"success": false,
"error": "VALIDATION_ERROR",
"message": "channel and fulfillmentType are required"
}
{
"success": false,
"error": "UNAUTHORIZED",
"message": "Invalid or missing API key"
}
{
"success": false,
"error": "FORBIDDEN",
"message": "API key does not have required scope: menu:read"
}
{
"success": false,
"error": "NOT_FOUND",
"message": "Store not found"
}
{
"success": false,
"error": "MENU_NOT_AVAILABLE",
"message": "This terna has no menu available"
}
Notas
El último menú generado, aunque nunca haya sincronizado
Fire guarda el payload del menú antes de enviarlo, y cada intento sobrescribe el anterior. Este endpoint devuelve esa última versión sin importar si el envío llegó al canal — el bloquesync te
dice si llegó.
Ejemplo: el lunes KIOSK/DINE_IN sincroniza bien. El martes suben los precios y el envío falla.
El GET del miércoles devuelve la versión del martes con sync.status: FAILED y sync.syncedAt
todavía apuntando al lunes.
Los agotados se recalculan al leer
Elactive del payload guardado refleja el estado de agotado al momento de generar el menú. Un
producto marcado como agotado después llega al canal por su propio webhook, no reescribiendo el
menú guardado. Este endpoint recalcula active contra el estado de agotado al momento de la
consulta, tanto en products[].active como en los productos-opción de combos.
Ejemplo, en los dos sentidos: el menú se genera a las 10:00 con un producto agotado. A las 11:00
vence el apagado y el webhook lo reactiva en el canal. Un GET a las 11:05 lo muestra activo, igual
que el canal — no agotado, que es lo único que mostraría el payload guardado por sí solo.
Semántica de syncedAt
sync.syncedAt significa “última entrega exitosa”, de forma consistente en todos los tipos de
canal, incluidos los de X-MART. Un envío fallido nunca lo avanza.
Terna sin menú — 404 MENU_NOT_AVAILABLE
Si la terna existe pero no tiene menú o lista de precios asignados, la respuesta es 404 MENU_NOT_AVAILABLE — distinto del 404 que se usa cuando la tienda en sí no existe o pertenece a
otro tenant. La tienda ya se valida contra tu key antes de esta verificación, así que esta respuesta
nunca filtra datos de otro tenant.
Envío vacío — también 404 MENU_NOT_AVAILABLE
Cuando el aplastado produce cero productos vendibles, el envío falla sin llegar nunca al canal —
pero el payload guardado igual queda con products: []. Este endpoint trata ese caso igual que una
terna sin menú: 404 MENU_NOT_AVAILABLE, en vez de un 200 con un menú vacío. Un menú vacío acá
sería indistinguible de “esta tienda no vende nada”, que no es lo que pasó — el menú nunca llegó al
canal. Listar menús igual muestra la terna, con syncStatus: FAILED, para que el problema se vea.
Relacionado
Listar menús
Descubrí qué ternas de una tienda tienen un menú generado.
menu.updated
El webhook que este endpoint refleja — referencia completa de campos para
data.menu.Obtener tienda
Lee una tienda puntual por id.

