Saltar al contenido principal
Suscríbete a las actualizaciones
Recibe un correo cada vez que se publica una entrada nueva — eventos nuevos, cambios incompatibles y actualizaciones de la referencia de API. Puedes darte de baja con un clic.
Suscribirme
El backoffice tiene una pantalla nueva, Importar y exportar (Operación → Importar y exportar): descarga una copia del catálogo de un vendor, edítala fuera del backoffice y vuelve a importarla, revisando cada cambio antes de que se escriba.
  • Importar y exportar — manual nuevo. Dos formatos: Respaldo completo (JSON), con categorías, modificadores, listas de precios, productos y menús, para guardar una copia o llevar el catálogo a otro ambiente; y Planilla editable (Excel), con categorías, productos y precios en filas planas, para cambiar muchos a la vez.
  • Primero se revisa — importar nunca escribe de inmediato: se analiza el archivo, revisas qué se crearía, actualizaría y eliminaría, y solo entonces lo aplicas. Antes de aplicar, Fire guarda un respaldo de los datos actuales.
  • Combinar y Reemplazar — Combinar crea y actualiza, y no elimina nada. Reemplazar deja los datos exactamente como están en el archivo y elimina lo que no está en él; está reservado a administradores de la plataforma, que también pueden Deshacer una importación aplicada.
  • Ternas afectadas — el detalle lista las combinaciones de tienda × canal × Tipo de Fulfillment que usan un menú o una lista de precios que cambia.
Importar no sincroniza: los cambios llegan a las tiendas y a los canales solo cuando sincronizas desde Asignación de menús.
Actualizado en EN / ES / PT.

13 de octubre de 2026 — Guía de API keys y precios de oferta en el backoffice

Una guía nueva cubre las API keys de principio a fin: dónde crear una, qué significa el vendor scope y qué scope necesita cada endpoint.
  • API keys — las keys se crean en Developers → API Management con Create API Key: eliges un nombre, los scopes y una expiración opcional. Selecciona un vendor en el dashboard antes de crear la key: con All vendors seleccionado la key queda sin vínculo de vendor, y los endpoints que lo exigen responden 403.
  • Scopes — todos los scopes del dashboard, con los endpoints que habilita cada uno, incluidos cash-management:write y kiosks:write.
  • Administrar keys — puedes editar los scopes de una key sin cambiar su secreto; el nombre, la descripción y la expiración quedan fijos al crearla, y no hay rotación integrada (crea una key nueva, cambia y luego revoca la anterior).
  • Header — envía la key en x-api-key. Authorization: Bearer pk_live_... sigue funcionando como alias legacy; si envías ambos, gana x-api-key.
  • Listar menús y Obtener menú ahora enlazan a la guía para el scope menu:read y el vínculo de vendor.
Los manuales del backoffice para el catálogo se reescribieron en torno a los precios de oferta y los precios por tipo de entrega:
  • Listas de precios — las ofertas ahora viven aquí, junto al precio, y también aplican dentro de los combos. Hasta dónde llega una oferta y por qué un precio sugerido es solo un precio tachado que nunca se cobra.
  • Menús — un menú ya no tiene tipo de entrega propio: toma el de la fila de asignación. Tres lentes (día, tipo de entrega, precios) y la nueva pestaña Overrides.
  • Asignación de menús — los precios de oferta viajan con Sync, las tandas bajan de 50 a 20 filas y los cambios de precio guardados desde la vista previa solo llegan a los agregadores, no a POS ni Kiosco.
  • Grupos de modificadores — agregar un grupo a un producto lo copia: los cambios posteriores al grupo no llegan a los productos que ya lo tienen. Preguntas distintas por tipo de entrega.
  • Productos — los combos no tienen precio propio: el cliente paga la suma de las opciones que elige. El precio de referencia “desde”, las ofertas dentro de un combo y los precios por tipo de entrega.
Actualizado en EN / ES / PT.

6 de octubre de 2026 — Nuevo endpoint: listar las terminales de una tienda

Ya puedes consultar qué equipos tiene una tienda y en qué estado están: cajas POS, kioscos de autoservicio y pantallas de cocina KDS.
  • GET /external/stores/{storeId}/terminals — devuelve el type, el status y el lastSeenAt de cada terminal, y su externalId (en kioscos, el device ID de la pantalla QR). Por defecto trae las terminales activas y suspendidas; las revocadas se piden con status=REVOKED. Se filtra por type y se acota la respuesta con fields. Usa el scope store:read que ya tienes para los endpoints de tiendas.

5 de octubre de 2026 — El parcial del día en la impresión de tirilla

Imprimir el cierre de día acepta "partial": true para imprimir cómo va el día hasta ahora sin cerrarlo (corte X): misma plantilla que el cierre, con una banda PARCIAL — NO ES CIERRE y la hora del corte.
  • Solo el día abierto de la tienda; otra fecha responde 409 PRINT_DAY_NOT_OPEN.
  • La respuesta trae subject.partial: true, y freshness.asOf es la hora del corte.
  • Sin partial, el endpoint se comporta igual que antes.
Actualizado en EN / ES / PT.

30 de septiembre de 2026 — El bloque fiscal de las tiendas tiene la misma forma en todos los países

El bloque fiscal de Listar tiendas y Obtener tienda deja de ser específico de Brasil. secondaryGovIdType, secondaryGovIdNumber y metadata vienen siempre, en null cuando la tienda no los tiene, igual que store.storeFiscalConfig en order.completed.
  • Colombia: metadata trae claveTecnica, rangoFacturacion y rangoNotaCredito (los rangos de la DIAN).
  • Ecuador, Chile, Argentina, Venezuela: las tres claves aparecen, en null. Antes no venían.
  • Brasil: sin cambios.
Los eventos de orden (order.cancelled, order.invoiced, order.reversed) llevan el mismo bloque que order.completed: en Colombia, la cancelación trae los rangos con los que se emite la nota de crédito.

28 de septiembre de 2026 — Endpoints de menús de la External API documentados

Dos endpoints se suman a la External API, junto a Obtener tienda y Listar tiendas: leer los menús de una tienda por API key, la versión por consulta del webhook menu.updated.
  • Listar menús — qué ternas (tienda × canal × tipo de fulfillment) de una tienda tienen hoy un menú generado, sin el menú.
  • Obtener menú — el último menú generado de una terna, con el mismo shape que menu.updated, con un bloque sync que dice si llegó al canal.
El diseño está cerrado pero todavía no está implementado — no hay nada para llamar hoy. Esta entrada existe para que puedas construir contra el contrato antes del release.
Actualizado en EN / ES / PT.

25 de septiembre de 2026 — Efectivo entregado y vuelto en los eventos de la orden

Los dos campos de efectivo de payments.paymentMethods[] en los eventos que llevan el snapshot V4 de la orden (order.opened, order.completed, order.invoiced, order.cancelled, order.reversed). Las versiones de los eventos no cambian.
  • customerCashAmount es un número y trae el monto real. Hasta el 24 de septiembre de 2026 viajaba siempre como el texto "0", incluso en pagos en efectivo. Ahora es el efectivo que entregó el cliente: para una cuenta de 22.9 pagada con un billete de 50, 50; 0 en los medios que no son efectivo.
  • changeAmount figura en la referencia — el vuelto que entregó la caja, como número: 27.1 en el ejemplo anterior, 0 en los medios que no son efectivo, null si la caja no lo mandó. Ya viajaba en los eventos; faltaba en la referencia.
  • Si tu consumidor validaba que customerCashAmount fuera texto, ahora falla. Leelo como número. Los eventos de órdenes inyectadas antes del 24 de septiembre siguen trayendo "0", así que un reenvío de una orden vieja también.
Actualizado en EN / ES / PT. Nuevo manual para quien opera el catálogo con el Agente de catálogo, el chat con inteligencia artificial que propone etiquetas de producto y las aplica solo con aprobación humana.
  • Agente de catálogo — cómo conversar o subir un archivo para etiquetar productos, qué decisiones pide el agente (modo, términos nuevos, alias) y por qué una aprobación puede terminar parcial cuando alguien edita el producto en el medio.
Actualizado en EN / ES / PT.

16 de septiembre de 2026 — cStat vuelve a emitirse, dentro de countryData

Esto corrige lo que dice una entrada posterior. El 15 de septiembre anunciamos que cStat ya no se emitía. Los consumidores lo pidieron de vuelta —sin él una anulación no dice si el ente la aceptó— así que vuelve. Solo cStat: docType, dataAutorizacao y sefazCancellation siguen afuera.
  • Brasil: authority.countryData.cStat. El código con el que el ente resolvió este documento: 100 en una autorización, 135 en una anulación. Es vocabulario del ente, así que viaja al lado de chaveAcesso y protocolo, no en la raíz del bloque.
  • La anulación lleva su propio código, no el de la factura. El order.reversed trae 135 —el evento de cancelación registrado en SEFAZ— mientras el order.invoiced que lo precedió conserva 100. Verificado de punta a punta en staging.
  • Viaja tal cual lo manda el proveedor, number o string. No normalizamos un tipo que el ente no eligió.
  • Por el callback fiscal ya funcionaba: todo lo que va dentro de document y no es canónico llega a countryData sin tocarse. Mandá cStat ahí y llega — no hubo que cambiar nada de tu lado.
  • mensagemSefaz sigue afuera. Vuelve solo el código.
  • Los rechazos siguen sin emitir evento. Un documento rejected guarda su código pero no dispara order.invoiced ni order.reversed, así que para ese caso cStat no te llega.
Actualizado en EN / ES / PT.

15 de septiembre de 2026 — Impresión al enviar del KDS, zoom y Agente Fire Android

La impresión de cocina ahora es una regla de tienda (comanda y/o fiscal en una estación). Las tablets necesitan su propio Agente Fire. El zoom y la reimpresión del operador son otra impresora.
  • Impresión al enviar — By screen o By station, documentos y timing fiscal. Arma la cola en la pantalla KDS. El dashboard avisa si la estación de impresión no tiene pantalla activa.
  • Acciones en pantalla — zoom de estación/ticket (doble toque al temporizador, tecla Q). Si la impresora falla con el fiscal listo, el ticket muestra Queued: printer failed.
  • Tablero de operador — Operator fiscal printer en el PC del supervisor (no la cola de cocina).
  • Instalación en Android — APK en la tablet del KDS. kds-agent.fire.rest debe resolver a 127.0.0.1. El token y el nombre de impresora deben coincidir con fire-kds.
  • Estaciones / Ruteo — el veto de item type en la estación desapareció. Las categorías viven solo en la estrategia de ruteo.
Actualizado en EN / ES / PT.

15 de septiembre de 2026 — Fechas de la anulación y rechazos

Dos correcciones sobre lo que guarda el callback fiscal y, por lo tanto, sobre lo que llevan order.invoiced y order.reversed. Las versiones de los eventos no cambian.
  • La anulación conserva las fechas de la factura. authority.issuedAt y authority.authorizedAt se mantienen como los tenía la factura, aunque el callback cancelled mande los suyos. Antes tomaban la hora de la anulación mientras compensates.issuedAt seguía apuntando a la factura, así que el mismo bloque contaba dos historias. Para saber cuándo se anuló el documento, usa authority.cancelledAt.
  • Un resultado negativo no guarda datos de comprobante. En rejected, denied y error, Fire ignora documentNumber, providerDocId, issuedAt, authorizedAt, los importes, pdfUrl, xmlUrl y graphic aunque el proveedor los mande; se guardan documentType, docSubtype, las claves del país en document, failure, provider y metadata. Un documento rechazado se leía igual que uno autorizado, con número y con authorizedAt. Un documento que ya tenía datos de comprobante los conserva.
Actualizado en EN / ES / PT.

15 de septiembre de 2026 — Bloque fiscal estructurado y eventos fiscales nuevos

El bloque fiscal de los tres eventos fiscales ahora es lo que Fire guarda en la orden, con una sola forma para todos los países: el veredicto del ente en authority, más el recorrido del documento y a cuál reemplaza. Dos guías nuevas explican el ciclo completo.
  • Breaking — el bloque fiscal de order.invoiced, order.cancelled y order.reversed es estructurado. Los campos canónicos pasan a authority (documentType, documentNumber, issuedAt, cancelledAt…), los importes a authority.amounts y los identificadores del ente (chaveAcesso, claveAcceso, cufe, protocolo…) a authority.countryData. dataAutorizacao pasa a ser authority.authorizedAt; docType, cStat y sefazCancellation ya no se emiten. Cada ruta anterior tiene exactamente una ruta nueva: ver Rutas que cambian.
  • Breaking — en una anulación el bloque pasa de cancellation.metadata.fiscal a cancellation.fiscal, y cancellation.metadata ya no se emite. Si la orden no tenía documento autorizado, la clave fiscal no está — antes venía null, así que una comparación con === null deja de cumplirse.
  • Breaking — el callback fiscal sacó todos los campos canónicos de document a la raíz (documentType, docSubtype, documentNumber, issuedAt, authorizedAt, cancelledAt, authorizationMode, providerDocId, totalAmount, taxAmount, currencyCode, pdfUrl, xmlUrl, graphic); document ahora lleva solo los identificadores del país. Renombres: countryCode → country, docType → documentType (SALE_INVOICE o CREDIT_NOTE, los únicos dos aceptados), error → failure (con scope y details), providerSpecific → metadata, emittedAt → issuedAt. Un emisor con los nombres anteriores recibe 400 con el campo — en el caso de docType, en authorized y cancelled. En Ecuador se retira numeroAutorizacion: el identificador autorizado es claveAcceso. cnpjEmitente no es parte del contrato.
  • order.cancelled lleva el bloque fiscal en todos los países con documento autorizado; antes era solo Brasil.
  • history y compensates — order.invoiced y order.reversed llevan cada parada del recorrido del documento, de la más vieja a la más nueva. compensates apunta al documento que el vigente reemplaza: viene lleno en order.reversed y en null en order.invoiced.
  • authority.providerIdentity y authority.providerMetadata — el provider y el metadata del callback ahora llegan a la orden y a los eventos, con los mismos nombres que en la numeración fiscal. null si no se mandan; PlugNotas (Brasil) nunca los manda.
  • Cómo funciona lo fiscal en Fire — los dos actos (numerar y autorizar), los dos bloques de la orden y los dos caminos por los que un documento llega a Fire.
  • Del callback a los eventos — qué evento sale por cada callback y dónde cae cada campo.
Los flujos y handlers que leen las rutas anteriores — fiscal.chaveAcesso, fiscal.protocolo, cancellation.metadata.fiscal.* — leen undefined en las versiones nuevas, sin error. Actualízalos antes de depender de estos eventos.
En Brasil authority.authorizedAt trae la fecha de la SEFAZ con una hora convencional de medianoche, así que puede quedar antes que issuedAt. Para el momento de la venta usa issuedAt.
No es retrocompatible en el bloque fiscal; el resto del snapshot de la orden no cambia. Las versiones anteriores siguen disponibles desde las pestañas de versión de cada evento. Actualizado en EN / ES / PT.

4 de septiembre de 2026 — Cupones en las líneas de la orden

Las órdenes ya pueden llegar con cupones. order.completed lleva quién financió cada descuento, en la línea y en la orden.
  • orderLines[].rewardId — el código de canje del cupón, o null. Los modificadores seleccionados también lo llevan: en un combo el descuento suele estar en los modificadores, no en el contenedor. Hay dos formas válidas y ninguna es un error: null con descuento (una rebaja de catálogo, sin cupón) y un código con discountValue: "0" (el cupón cambió el precio de lista en vez de descontar).
  • data.marketing.coupons[] — estaba reservado para uso futuro; ahora lleva { rewardId, name, metadata } por cupón. metadata.scope es product, order o shipping, y metadata.amount es la plata que descontó. Un cupón con scope: "order" aparece solo acá: su monto llega a las líneas ya repartido entre ellas y nada une las porciones con él.
En órdenes de kiosco totals.discountValue es el total de todos los niveles — el cupón de orden y los descuentos de línea juntos, porque el origen reparte el cupón de orden dentro de las líneas antes de enviar. Sumarlo con la suma de orderLines[].discountValue cuenta la misma plata dos veces. Usá uno u otro, no los dos.
El value de un cupón es el valor nominal de la regla — un porcentaje, o puntos —, no moneda. La plata siempre está en amount. Y baseValue: null significa que no se conoce el precio de lista, que no es lo mismo que cero. Retrocompatible: los dos campos son agregados sobre la forma existente, y rewardId llega en null en todo canal que no manda cupones. Actualizado en EN / ES / PT.

3 de septiembre de 2026 — Credenciales Fire del KDS, filas de comandas y categorías de estación

La impresión y la cancelación de cocina necesitan el host y la key correctos de Fire. Las tarjetas pueden ocupar de una a tres filas. Los productos reciben una categoría de ruteo y una miniatura de cocina.
  • Credenciales Fire API — default de cuenta frente a override por vendor. La base URL es solo el host de Fire; fire-kds agrega las rutas de print y cancel.
  • Categorías de estación — códigos usados como item_type en el ruteo, más miniaturas de producto en la vista de la categoría.
  • Credenciales Fire del KDS (técnico) — fila de vendor → default de cuenta → env. Print solo lee FISCAL_PRINT_*. Cancel puede caer a FIRE_*.
  • Acciones en pantalla — Filas de comandas (1–3) reservan espacio para notas. Si Fire rechaza un cancel, el operador ve el rechazo y el detalle de policy; el trabajo queda fallido.
Actualizado en EN / ES / PT.

3 de septiembre de 2026 — El catálogo: productos, categorías y grupos de modificadores

Tres manuales nuevos para las pantallas que alimentan todo lo demás. Un menú no inventa nada —elige del catálogo—, así que el trabajo empieza de verdad aquí.
  • Productos — los cuatro tipos, los interruptores que deciden si algo se vende, el precio, los modificadores, los combos y las sugerencias.
  • Categorías — los bloques con los que el cliente recorre la carta, su horario y la exclusividad de canal.
  • Grupos de modificadores — las preguntas que se hacen al pedir, y las opciones que las responden.
  • Las opciones de un modificador son productos del catálogo. Para ofrecer queso extra tiene que existir un producto queso extra; su precio se lee de ese producto, nunca se escribe en el grupo.
  • En un grupo solo se ponen dos números: mínimo y máximo. Obligatorio/opcional y única/múltiple se deducen de ellos, así que un grupo no puede contradecirse.
  • La exclusividad de canal se hereda. Marcar una categoría como exclusiva la saca del Golden Menu junto con sus productos.
  • Un combo no tiene pestaña de precio, y el precio que muestra el listado es una referencia calculada, no lo que cobras. El precio real sale de la lista de precios del destino.
La pestaña de precios depende del país: en Brasil está simplificada al precio final más la categoría fiscal (NCM). Las variantes de producto están previstas pero todavía no tienen pantalla.
Actualizado en EN / ES / PT.

3 de septiembre de 2026 — Menús: armar la carta y hacerla llegar al canal

Dos manuales nuevos para el par de pantallas que deciden qué se vende y dónde: el menú Golden y los menús custom que heredan de él, y la matriz que pone cada menú en cada tienda, canal y tipo de fulfillment.
  • Menús — Golden y custom, la herencia, el diálogo de creación, las pestañas Structure y Overrides, y las lentes de precio y de día.
  • Asignación de menús — la matriz tienda x canal x fulfillment, la asignación masiva, el Sync y sus advertencias, y la previsualización.
  • El tipo de fulfillment se elige una vez y no se puede cambiar. Es el único campo del menú sin vuelta atrás: equivocarse significa crear el menú de nuevo.
  • Guardar un menú no lo publica — en el editor no hay botón de publicar. El menú llega a un canal recién cuando alguien sincroniza la fila correspondiente en la pantalla de asignaciones.
  • El Sync aplasta el menú fresco, sin versionado. Manda el menú y la lista de precios tal como están guardados en ese segundo; no se puede republicar un estado anterior.
  • Una fila puede quedar en Synced y aun así haber perdido productos. Un producto sin precio en la lista asignada queda fuera del envío en vez de publicarse en cero, y lo único que lo dice es el chip de advertencias.
Los canales agregadores reciben sus eventos, pero su resultado todavía no se refleja en el estado de sincronización de esta pantalla. La pestaña History del menú también sigue vacía.
Actualizado en EN / ES / PT.

2 de septiembre de 2026 — Agotados: apagar productos durante el servicio

Manual nuevo de la pantalla Agotados: sacar un producto de la venta en una tienda cuando se acaba en cocina, sin editar el menú y sin que nadie tenga que deshacerlo después.
  • Agotados — el diálogo de apagado, el alcance por canal, el motivo obligatorio, la restauración y la pestaña de auditoría.
  • Un apagado nunca sobrevive al cierre de la tienda. El techo es el fin de la jornada operativa, no una cantidad fija de horas: un producto apagado hoy amanece vendiéndose mañana.
  • El alcance es un par de canal y tipo de entrega. Un producto puede quedar apagado en el kiosco y seguir vendiéndose en caja.
  • Como opción de un combo, el producto se sigue pudiendo elegir. Si se vende dentro de grupos de modificadores, el diálogo los nombra y el apagado los registra, pero lo que reciben los canales es disponibilidad por producto: una opción no tiene dónde entrar ahí.
  • El motivo es obligatorio y no se edita. Cambiar la vigencia mueve solo la hora — el motivo queda como el registro de por qué se apagó el producto.
  • Publicar el menú cierra el apagado, pero solo si cubrió todo su alcance. Un apagado de toda la tienda sobrevive a una publicación que llegó a un canal, porque en los otros el producto sigue fuera de venta de verdad. El desenlace es Pisado por un sync.
  • El apagado queda guardado aunque el canal no se entere. Avisar se informa aparte de guardar, y los apagados cuyo aviso no llegó se cuentan en la cabecera y quedan marcados en su fila.
El apagado sí se propaga a los canales de venta: products/listing por producto para los canales X-Mart y product.availability_changed por canal para los agregadores, en las tres direcciones (apagar, restaurar, vencer). La fila queda como registro operativo de Fire —qué se dejó de vender, cuándo y por qué— y nunca entra al snapshot del menú: esa separación es deliberada, no una etapa pendiente. Lo que no se propaga son los productos que se venden solo como opción de modificador: ninguno de los dos contratos tiene dónde ponerlos.
Actualizado en EN / ES / PT.

15 de agosto de 2026 — El bloque fiscal: identificadores por país, anulación y proveedor

fiscalRepresentation deja de tener campos fijos por país y pasa a llevar el documento vigente de la orden, con los anteriores en history.
  • Breaking — sequential, serie y claveAcceso ya no son campos del bloque. Los identificadores del ente viven ahora en countryData, con el vocabulario del país que numeró: claveAcceso, establecimiento, puntoEmision, secuencial y ambiente en Ecuador; numeroControl, numeroFactura y serie en Venezuela. Recorré las claves, no las indexes: un canal que lea countryData.claveAcceso directo funciona en Ecuador y se rompe con el primer país que entre. Los campos que significan lo mismo en todo país —documentNumber, issuedAt, authorizationMode, numberingStatus— no se movieron.
  • history y compensates — cuando una anulación numera, la nota de crédito pasa a ser el documento de arriba, compensates apunta a la factura que anula, y la factura entera baja a history. Cada entrada de history tiene las mismas claves que el bloque de arriba, así que se leen igual.
  • environment — en qué ambiente numeró Fire: SANDBOX o PRODUCTION. Es nuestro, no del ente; el del ente sigue viajando dentro de countryData con su propio código.
  • providerCode, providerIdentity y providerMetadata — antes eran un solo objeto que mezclaba tres cosas. providerCode es nuestro identificador de adaptador; providerIdentity es el bloque del proveedor (name, version, reference) y tiene forma; providerMetadata es una bolsa opaca y no hay que programar contra sus claves. La respuesta del endpoint de numeración devuelve ahora exactamente los mismos tres campos, con los mismos nombres.
Si tu conciliación asume que documentNumber es siempre el de la venta, revisala: después de una anulación el número de arriba es el de la nota de crédito. Lo que el cliente se llevó impreso no se pierde —está en history— pero hay que ir a buscarlo ahí.
Documentado en order.opened, order.completed, order.cancelled, order.invoiced, order.reversed, en la referencia del endpoint y en la guía Integrar un punto de venta. Actualizado en EN / ES / PT.

13 de agosto de 2026 — La numeración fiscal ahora viaja en todos los eventos de la orden

Las órdenes que el Fiscal Gateway numeró antes de inyectarse ahora llevan esos identificadores en todos sus eventos, así que ya no hace falta una segunda llamada para imprimir o conciliar.
  • data.fiscalRepresentation — serie, secuencial, número de documento, clave de acceso y el QR (graphic), tal como se imprimieron en la caja. La clave viaja siempre: llega en null cuando no se intentó numerar —agregadores, países sin representación fiscal, o numeración desactivada— y con el bloque cuando sí. Ramificá por valor (if (data.fiscalRepresentation)), no por presencia de la clave. Que traiga bloque significa que se intentó numerar, no que se numeró: numberingStatus dice cómo terminó el intento y failure por qué, cuando no terminó bien — una venta cobrada que quedó sin comprobante fiscal llega con los identificadores en null y el motivo en failure. Que traiga bloque no significa que el comprobante esté autorizado: el veredicto del ente sigue en lastKnown.fiscal.status. El bloque no cambia nunca, ni siquiera después de que el ente autorice o rechace.
  • data.lastKnown.fiscal.sourceEvent — ahora informa la procedencia real en vez de deducirla del estado. Un processing sembrado al inyectar se reportaba como fiscal.callback sin que ningún callback hubiera ocurrido; ahora dice order.injected. Contemplá el valor nuevo si ramificás por este campo.
  • Documentado en order.opened, order.completed, order.invoiced y order.cancelled.
Actualizado en EN / ES / PT.

11 de agosto de 2026 — BOH API: qty_base derivado en el servidor con item_unit_id

En las líneas de órdenes de compra (POST /procurement/orders, add-lines y actualización de línea), qty_base ahora es opcional cuando la línea referencia item_unit_id — no solo unit_code. El servidor deriva qty_base = qty × factor_to_base desde la unidad referenciada, así que los integradores externos que referencian una unidad de compra por UUID ya no necesitan conocer ni recalcular su factor de conversión. Si de todos modos envías un qty_base explícito, BOH lo valida contra el valor derivado (tolerancia 0.001) y devuelve purchase_order_qty_base_mismatch (422) si no coincide — mismo comportamiento que unit_code. Si item_unit_id no resuelve a una unidad activa y se omitió qty_base, la respuesta ahora es el error tipado item_unit_not_found (404). Actualizado en EN / ES / PT.

11 de agosto de 2026 — BOH API: resolución de establecimiento por ID fiscal en órdenes de compra (Fase 19)

tax_id es ahora un campo de primera clase en los establecimientos de BOH (RUC, CNPJ, CUIT, NIT, RUT, RFC u otro código fiscal de hasta 64 caracteres). Es opcional, no único, y se acepta en POST /identity/stores y PATCH /identity/stores/{id}. Al crear una orden de compra por API puedes identificar el establecimiento receptor con cualquiera de estos tres campos mutuamente exclusivos:
  • store_id — UUID interno (sin cambios).
  • external_store_id — identificador cruzado externo.
  • store_tax_id (nuevo) — identificador fiscal. Devuelve 422 con purchase_order_store_tax_id_ambiguous si varios establecimientos activos comparten el mismo valor (p. ej. RUC de Ecuador compartido entre sucursales) — en ese caso usa store_id o external_store_id.
Combinado con los campos ERP de las Fases 17–18, los ERPs pueden crear órdenes de compra sin conocer ningún UUID interno. Actualizado en EN / ES / PT.

11 de agosto de 2026 — BOH API restructurada: un endpoint por página

La pestaña de BOH API fue completamente restructurada en páginas individuales por endpoint. Cada endpoint tiene ahora su propia entrada en el menú mostrando el método HTTP (GET, POST, PATCH, DELETE), ejemplos interactivos de request/response, y un botón Pruébalo para probar el endpoint directamente desde la documentación. La nueva estructura cubre los 63 endpoints en 6 secciones: Identidad, Catálogo, Recetas, Operaciones, Compras y Webhooks. Actualizado en EN / ES / PT.

11 de agosto de 2026 — BOH API: órdenes de compra — resolución por supplier_sku y external_user_id

Dos adiciones a la referencia de órdenes de compra: supplier_sku en líneas — un tercer identificador de ítem para integración con ERPs. En lugar de item_id o external_item_id, envía supplier_sku (sin distinguir mayúsculas) y BOH resuelve el ítem directamente desde el catálogo del proveedor de la orden, derivando base_unit_id automáticamente. Error: purchase_order_supplier_sku_not_found (404). external_user_id al crear — el identificador de usuario del llamador ahora se acepta al crear una orden de compra y se guarda como actor_external_user_id. Antes el campo era ignorado silenciosamente. Actualizado en EN / ES / PT.

10 de agosto de 2026 — Manuales KDS: emparejamiento, tablero de operador, tache de líneas y defaults de display

Manuales KDS nuevos y actualizados con el trabajo reciente de fire-kds: Emparejar un dispositivo — guía nueva. Enrolar TVs de cocina con código de 6 dígitos desde KDS → Todas las tiendas, administrar terminales emparejados y entender el cierre de sesión de dispositivo vs correo. Tablero de operador — guía nueva. Listado/detalle de supervisor con temporizadores en vivo, filtros, códigos de recolección y sobrescrituras cancelar / listo / despachar. Acciones en pantalla — tache de líneas antes del bump, despacho esperando armado, alerta de pedido nuevo y ajustes de display más ricos (defaults de tienda, nombre del cliente por canal/fulfillment). Turnero — filtros de fulfillment (ej. ocultar delivery del turnero). Descripción general — opciones KDS a nivel de tienda (defaults de display, line strike, motivos de cancelación) y enlaces a las guías nuevas. Actualizado en EN / ES / PT.

7 de agosto de 2026 — BOH API: operaciones, identidad, sincronización masiva y endpoints de compras

La referencia de la BOH API ahora cubre el conjunto completo de endpoints para construir una integración completa: Identidad — nueva sección. Descubre el contexto de tu cuenta (GET /identity/me), lista vendors y administra establecimientos y proveedores (crear, actualizar, archivar/desarchivar). Catálogo: Sync masivo — nueva sección. Tres endpoints PUT de sincronización masiva:
  • PUT /catalog/units — upsert de unidades por code + unit_group_code; las unidades globales se omiten sin error.
  • PUT /identity/suppliers — upsert de proveedores por external_supplier_id.
  • PUT /catalog/classifications/assignments — reemplaza todas las asignaciones de clasificación de un ítem o establecimiento de forma atómica.
Operaciones — nueva sección. Cubre todos los tipos de movimiento de inventario:
  • Recepciones de mercancía (crear, listar, obtener) — soporta external_store_id y external_supplier_id para no necesitar UUIDs previos.
  • Conteos de inventario (crear, listar) — alcance FULL o PARTIAL, con area_breakdown para sesiones de conteo colaborativo por áreas.
  • Mermas (crear, listar) — líneas por ítem, tag de ítems o snapshot de subreceta.
  • Transferencias (crear, listar) — débito/crédito atómico entre establecimientos.
  • Lotes de producción (crear, listar, obtener) — registra ejecuciones de receta con output real y overrides de ingredientes opcionales.
  • Seguimiento de transacciones (estado, listar) — consulta cualquier escritura asíncrona por su tracking_id.
Compras — nueva sección. Ciclo de vida completo de órdenes de compra (POST /procurement/orders con clave de idempotencia, listar/obtener, enviar, confirmar, añadir/actualizar/eliminar líneas, cancelar, cerrar y estado de cumplimiento), además de PUT /procurement/par-levels para upsert de objetivos de stock por ítem/establecimiento y GET /procurement/suggested-order para obtener cantidades de reorden sugeridas. Las órdenes de compra también soportan integración con ERPs mediante identificadores externos: external_supplier_id, external_item_id y unit_code resuelven los registros internos del lado del servidor (sin necesidad de UUIDs de BOH), external_reference etiqueta la orden con tu código de documento (filtrable en el listado) y las líneas aceptan montos informativos (tax_amount, delivery_amount, total_amount, markup_amount). Actualizado en EN / ES / PT.

7 de agosto de 2026 — Manuales BOH: líneas por canal, conteos colaborativos, moneda de cuenta

Tres actualizaciones en los manuales de usuario BOH que reflejan cambios recientes en el producto: Recetas — líneas con alcance por canal (Fase 16) El modelo de “complementos por servicio” fue reemplazado por líneas con alcance por canal en una única receta. Cada línea ahora tiene un campo opcional service_codes:
  • Líneas sin service_codes son generales y siempre aplican.
  • Líneas con service_codes: ["DELIVERY"] solo aplican cuando el canal de la orden coincide.
  • Una única receta publicada por producto y tienda reemplaza el par BASE + COMPLEMENT anterior.
Actualizado: Recetas — Líneas con alcance por canal. Conteos — sesiones de conteo colaborativo Nueva sección que documenta las sesiones de conteo en campo: varios dispositivos pueden contar diferentes áreas de inventario de la misma tienda al mismo tiempo. Cada dispositivo reclama un área exclusiva, cuenta y la marca como lista. El dispositivo administrador finaliza la sesión, lo que crea un conteo normal. Actualizado: Conteos — Sesiones de conteo colaborativo. Catálogo — moneda de la cuenta Nueva sección que documenta la configuración de moneda de la cuenta. Cada cuenta BOH ahora tiene una moneda ISO 4217 predeterminada (configurada en Cuenta y accesos → Configuración de cuenta) que se usa en costos de abastecimiento, precios de ítems de proveedor y reportes. Actualizado: Catálogo — Moneda de la cuenta. Actualizado en EN / ES / PT.

7 de agosto de 2026 — Listas de precios: nuevo manual de usuario

Las listas de precios permiten manejar precios distintos por canal, local o campaña sin mantener cada uno a mano. El manual ya está disponible: Listas de precios.
  • Listas conectadas — una lista puede seguir a una lista base. Cambias el precio una vez y llega a todas; el producto que necesita un precio propio lo fija y deja de seguirla, solo para ese producto. Las fórmulas tipo =P*1.15 quedan vivas: cuando la base se mueve, la lista se recalcula sola.
  • Precios por contexto — el mismo producto puede valer distinto dentro de un combo. Esos precios vivían escondidos en la configuración de cada combo; ahora se ven y se editan desde la fila del producto, con el porcentaje contra el precio suelto.
  • Edición masiva con redondeo comercial — aplica un porcentaje o un monto a muchos productos de una vez, alcanzando también los precios dentro de combos, y redondea a .99, .90 o número entero para no terminar vendiendo a 13,42.
  • Modo comparación — superpone otra lista como referencia para ver, producto por producto, dónde se separan las dos.
  • Alcance antes de guardar — un resumen de qué listas conectadas reciben el cambio y, sobre todo, cuál no recibe nada porque todos los productos que tocaste tienen precio propio ahí.
  • Conectar una lista existente — una lista que nació como copia y quedó desactualizada puede conectarse a una lista base. Lo que coincide con la base pasa a seguirla, lo que tiene precio propio se queda como está: al conectar no se mueve ningún precio.
Los precios por horario (day-parting) todavía no están disponibles, y esta fase trabaja sobre el precio final con impuestos incluidos — el precio neto y el de referencia vienen después. El manual deja los dos límites explícitos.

6 de agosto de 2026 — Latidos de salud de kioscos, KDS y cajas

Los kioscos, las pantallas KDS y las cajas POS ya pueden reportar que están vivos, y el tablero de disponibilidad de Fire lee la flota a partir de esos latidos. El endpoint es POST /external/component-health y necesita una API key con el scope component-health:write.
  • Salud de componentes — un latido por ciclo con componentType, componentId, storeId y status. Opcionales: sentAt, offlineSince, degradedReason, appVersion y un details libre. Responde 204 No Content.
  • X-Heartbeat-Interval — cada 204 trae la cadencia vigente, en segundos. Adoptala en el próximo ciclo: así se reconfigura el intervalo sin publicar una release.
  • El componentId tiene que ser estable — si cambia entre reinicios, para Fire es otro componente: el viejo se da de baja a los 7 días y el nuevo arranca sin historia.
  • degradedReason usa un vocabulario común — printer_down, pinpad_down, backend_unreachable, queue_backlog, peripheral_other. Las claves de details para kds_station todavía están por acordar con el equipo de KDS.
status solo acepta online y degraded. No existe down: un equipo no puede declararse muerto — Fire infiere la caída por la ausencia de latido, tras dos intervalos perdidos.

4 de agosto de 2026 — Nuevo campo assignedAt en eventos de menú y producto

menu.updated v2 y product.updated ahora llevan assignedAt en cada categoría y producto.
  • categories[n].assignedAt y products[n].additionalInfo.assignedAt — fecha en que la entidad entró al menú, ISO 8601 UTC, sin milisegundos. Es un dato de membresía, no de edición: no cambia con ediciones de precio, nombre, imagen u orden; sí cambia (fecha nueva) cuando el ítem se quita del menú y se vuelve a agregar. Casos borde completos en menu.updated → Fecha de incorporación al menú. No viaja en product.price_updated ni en product.availability_changed — esos eventos solo transmiten su delta.
  • menu.updated / product.updated usan taxInfo (no taxesInfo), type: PRODUCTO para ítems estándar y modifierGroups[n].type: RADIO para grupos de selección única (CHECKBOX para múltiple).
  • storeId es el UUID interno de la tienda (stores.id), no el store_number — misma convención en menu.updated, product.updated, product.price_updated y product.availability_changed.
  • El priceInfo de product.price_updated no comparte forma con el priceInfo de catálogo de menu.updated / product.updated — es el precio de venta recién guardado con su descuento, no precios de catálogo.
channelReferenceName significa el fulfillment (delivery, pickup) en list.stores[n].channels[n] de menu.updated, pero el canal de ventas (iFood, Rappi) en el mismo nombre de campo de product.updated, product.price_updated y product.availability_changed. Misma clave, dos cosas distintas según el evento.
Actualizado en EN / ES / PT.

4 de agosto de 2026 — Suscripción por correo al registro de cambios

Ya puedes recibir un correo cada vez que se publica una entrada nueva en esta página. Suscríbete desde el botón de arriba — la lista la gestiona Buttondown, así que ninguna dirección se guarda en la documentación, y un clic en cualquier correo te da de baja.
  • Un correo por entrada, en los tres idiomas — English, Español y Português llegan juntos en el mismo mensaje, así que no hay nada que elegir.
  • Solo envía una entrada nueva — corregir una errata en algo ya publicado nunca lo reenvía.
Actualizado en EN / ES / PT.

2 de agosto de 2026 — order.opened y los bloques de pago diferido

Cada evento avanza en su propia línea de versión — no hay un número de contrato global: Todo lo agregado es retrocompatible (bloques nuevos sobre un shape existente). Nada de esto cambia un campo que ya estés leyendo, y el contrato anterior de cada evento sigue publicado detrás de su pestaña de versión.
  • Nuevo evento order.opened — se dispara cuando una orden se inyecta ya abierta: existe, la cocina puede arrancar, nadie pagó todavía. Lleva el mismo snapshot V4 que order.completed. No se dispara para órdenes inyectadas como COMPLETED o CANCELLED. Este evento no tiene v0 — nació en v1.
  • data.policy.deferredPayment — agregado a los cuatro eventos de orden (order.opened, order.completed, order.invoiced, order.cancelled). Dice si la orden puede cocinarse, facturarse o despacharse antes del pago. Se resuelve una vez al inyectar y se estampa inmutable; todos los eventos posteriores repiten el mismo valor.
  • data.lastKnown — agregado a esos mismos cuatro eventos. Foto orientativa del estado de cocina y fiscal. Nunca condiciones una acción irreversible a este campo — puede venir null o viejo, y el propio Fire lo ignora y relee de la fuente antes de emitir nada.
En order.opened, payments.paymentMethods[] es lo que el POS declaró, no lo que se cobró — transactionStatus viene en PENDING y transactionId normalmente vacío. Fire sobreescribe el arreglo con los tenders reales cuando entra el cobro, y emite order.completed. Leer el medio declarado como evidencia de cobro es el error más común con este evento.
Actualizado en EN / ES / PT.

22 de julio de 2026 — Manuales de usuario BOH

Añadida la sección BOH en la pestaña Manuales de usuario, cubriendo la administración del inventario back-of-house desde el Fire backoffice:
  • Descripción general y conceptos — cómo encajan catálogo, recetas, abastecimiento, movimientos, conteos y reportes; el flujo de stock; mapa del menú BOH.
  • Tiendas y proveedores — tiendas BOH vinculadas a Restaurant OS y proveedores con vínculos ítem–proveedor (precio, unidad de compra, SKU).
  • Catálogo — grupos de unidad y unidades, ítems, etiquetas de ítems intercambiables (FIFO / FEFO / prioridad / mayor stock), clasificaciones.
  • Recetas — recetas de venta, producción y subrecetas; ciclo borrador → publicada → archivada; líneas por canal; simulador de venta.
  • Abastecimiento — programaciones de recepción, ciclo de vida de las órdenes de compra, niveles par y pedido sugerido.
  • Recepciones y devoluciones — recepciones de mercancía (entrada de stock, vínculo a OC, sobre-recepción) y devoluciones a proveedor.
  • Mermas y consumos internos — catálogo de razones de merma, eventos de merma, consumos internos.
  • Transferencias y producción — transferencias entre tiendas y lotes de producción con rendimiento.
  • Conteos — áreas de inventario, conteos completos/parciales y la app móvil de conteo.
  • Reportes — usos y consumos, mermas, rendimiento de producción y balance a fecha.
Las 10 páginas publicadas en EN / ES / PT.

13 de julio de 2026 — Cancelar orden: campo cancellationType

Añadido el campo opcional cancellationType (string) al body de Cancelar orden. Cuando se envía, el ID o código del motivo de cancelación del catálogo se persiste en la orden y se reporta al gateway de pago. Actualizado en EN / ES / PT.

3 de julio de 2026 — Inyectar orden: distribución de descuento en combo

Añadida la sección Descuentos de combo en la referencia de Inyectar orden. Cuando un producto COMBO tiene precio contenedor 0, el discountsValue del combo no debe colocarse en la línea del contenedor (produce totales negativos). En su lugar, hay que distribuirlo proporcionalmente entre los selectedModifiers:
  • discount_i = ROUND(D × (base_i / B), 2) — parte proporcional por modificador
  • Cada modificador debe mantener subtotalIncludeDiscounts >= 0 y total >= 0 tras el descuento
  • El contenedor COMBO debe tener todos los campos de precio en 0
  • SUM(modifier.totalPrice.discountsValue) debe igualar el descuento total del combo
Incluye ejemplo JSON antes/después (descuento BRL 17,94 en un combo de 7 ítems, base BRL 89,68) y tabla de desglose completo. Actualizado en EN / ES / PT.

29 de junio de 2026 — Manuales de usuario KDS

Añadida la sección KDS en la pestaña Manuales de usuario, cubriendo tanto el uso por parte del operador como la administración desde el backoffice:
  • Descripción general y conceptos — cómo encajan tiendas, estaciones, pantallas, enrutamiento, dispositivos e impresión; dos tipos de estación (producción vs convergencia); patrones de cocina (solo ensamblaje, KITCHEN, multi-estación).
  • Configurar una tienda — aplicar una plantilla (asistente de blueprint) o configurar desde cero; orden recomendado de pasos.
  • Estaciones — campos, reglas opcionales por canal / servicio / tipo de ítem, creación paso a paso.
  • Pantallas — identificador de dispositivo, crear y asignar estaciones, relación pantalla ↔ estación.
  • Enrutamiento — capas de decisión (enrutamiento → reglas → distribución → convergencia), modos de distribución, ejemplo multi-estación.
  • Periféricos, impresión y validación — teclados, impresión de recogida (una pantalla por tienda), cancelación de órdenes, checklist de go-live y rutas de referencia.
  • Acciones en pantalla — avanzar, retener/liberar, deshacer, cancelar, paginación, menú de configuración y atajos de teclado.
  • Pantalla de espera — pantalla para clientes (áreas en preparación / listo, destaque al pasar a listo, paginación automática).
Las 8 páginas publicadas en EN / ES / PT.

22 de junio de 2026 — Nueva guía: Estructura de productos · Publicación de menús actualizada

Nueva guía: Estructura de productos

Nueva página Estructura de productos en la pestaña Guías — cubre el tipo COMBO y los overrides de modificadores:
  • Tipo COMBO — priceInfo.price es siempre 0; usar priceInfo.referencePrice como precio de encabezado del producto.
  • Precio de referencia — suma de (opción más barata × minOptions) en cada grupo de modificadores obligatorio (minOptions ≥ 1).
  • Overrides de modificadores — productModifiers[n].overrides define un precio diferente para una opción dentro de un combo específico; tiene precedencia sobre el precio base del producto en products[].
  • Precios delta — grupos obligatorios muestran +R$ X respecto al baseline; grupos opcionales muestran el precio completo del add-on.

Guía de publicación de menús

  • Eliminada la sección menus.sync — ese evento ya no existe.
  • Corregido el formato del payload: event es ahora un objeto anidado (id, type, executionId, createdAt), no campos al nivel raíz.
  • El paso de verificación de firma ahora especifica que el signing secret se obtiene en Integraciones de agregadores en el dashboard de Fire.
  • Añadida sección de estructura del menú con descripción de list, categories, products (tabla de tipos) y modifierGroups.
Actualizado en EN / ES / PT.

15 de junio de 2026 — order.completed — nuevos campos de método de pago

Añadidos 4 campos a payments.paymentMethods[n] en el evento order.completed. Todos son nullable y ya están en producción.
  • idAuth (string | null) — ID de autorización del procesador de pago (ej. SiTef IdAuth). Distinto de authorizationCode.
  • receiptCustomer (string | null) — Texto completo del comprobante para el cliente; puede ser multilínea.
  • receiptMerchant (string | null) — Texto completo del comprobante para el comercio; puede ser multilínea.
  • acquirer.cnpj (string | null) — CNPJ de la credenciadora de pago — solo Brasil.
Actualizado en EN / ES / PT.

15 de junio de 2026 — Campos de detalle de método de pago

Añadidos 5 campos opcionales a payments.paymentMethods[n] en Inyectar orden:
  • id_auth (string | null) — Número de autorización NFCE (SiTef 952 / IdAuth).
  • receipt_customer (string | null) — Vía del cliente: texto del comprobante impreso para el portador (SiTef 121 / ReceiptCustomer).
  • receipt_merchant (string | null) — Vía del comercio: texto del comprobante impreso para el establecimiento (SiTef 122 / ReceiptMerchant).
  • acquirer.cnpj (string) — CNPJ de la credenciadora para NFCE (SiTef 950 / CNPJAuth). acquirer queda documentado como nullable — enviar null para métodos sin credenciadora.
  • card.media (string) — Tipo de lectura de la tarjeta: CHIP, MAGNETIC, NFC, MANUAL (SiTef 2090 / Media). card queda documentado como nullable — enviar null para métodos sin tarjeta.
Todos los campos son opcionales y ya están implementados en el validador. Actualizado en EN / ES / PT.

14 de junio de 2026 — Webhook de estado de orden de agregador

  • Nuevo webhook entrante POST /v1/webhooks/aggregators/order-status — tu agregador de delivery (Rappi / Uber / Didi / iFood / PedidosYa / Glovo…) hace POST con el estado de entrega de la orden a medida que avanza (courier_assigned → on_route → delivered…). Fire refleja el último estado en orders.aggregator y registra cada evento.
  • El estado es passthrough — no se impone ningún enum; las etiquetas propias del agregador se guardan tal cual, y el estado actual es el del occurredAt más reciente (sin compuerta anti-regresión). Las etiquetas amigables y traducidas se resuelven al momento de mostrar desde el catálogo del canal.
  • Correlación flexible de la orden — envía orderId (UUID de Fire) y/o externalOrderId (tu referencia, comparada contra metadata.order_id); al menos uno es requerido, ambos vendor-scoped. Si envías ambos y correlacionan a órdenes distintas → 409.
  • No hay un eventId emitido por Fire para ecoar — un estado de agregador es un evento externo espontáneo (Fire no es la fuente de verdad aquí). La idempotencia se llavea por (channelCode, providerEventId) + status; channelCode debe ser igual al metadata.channel.code de la orden.
  • Auth: API key vendor-scoped con el nuevo scope webhooks:aggregator. 202 async + cola, mismo envelope que los callbacks fiscal / KDS.
  • Documentado en EN / ES / PT.

12 de junio de 2026 — Descuentos del agregador en Inyectar orden

Documentado cómo enviar descuentos promocionales del agregador (iFood, Rappi, UberEats, etc.) en el endpoint Inyectar orden.
  • Los descuentos del agregador son un método de pago, no una fila de descuento. Cuando el agregador aplica un descuento al cliente, el local recibe el importe completo y el agregador reembolsa la diferencia — modélalo como una entrada extra en payments.paymentMethods[] con paymentMethodCode: "AGGREGATOR_DISCOUNT", transactionType: "BENEFIT", processor con el nombre del agregador y card: null.
  • payments.discounts[] queda vacío para descuentos del agregador — ese array es solo para promos/cupones que absorbe el local.
  • Nueva regla de balance documentada: SUM(paymentMethods[].totalBill) debe ser igual a productos + cargos extra + envío.
  • Nuevo ejemplo de request con una orden de iFood (BRL 38.69 CREDIT + BRL 1.00 AGGREGATOR_DISCOUNT = BRL 39.69 bruto).
  • Actualizado en EN / ES / PT.

11 de junio de 2026 — Nomenclatura underscore + payload thin de cierre de día

  • Nombres (breaking) — store.day-closed → store.business_day_closed y order.status-updated → order.status_updated (nomenclatura underscore). Actualiza tu switch de event.type.
  • store.business_day_closed ahora es un payload thin — identidad del cierre (businessDayId, businessDayDate, timezone, status), timing (openedAt/closedAt), closedBy y una store mínima (uid, code, externalId, countryCode, timezone, currencyCode). Removido del evento: sales, metrics, summary, byChannel, byPaymentMethod, forceClosedOrders, closureStats, cancelledOrders, metadata — consúltalos por businessDayId cuando los necesites. snapshotId renombrado a businessDayId (mismo valor).
  • Documentado en EN / ES / PT.

10 de junio de 2026 — Eventos canónicos de orden + evento de cocina

Los eventos fiscales pierden el país del nombre y pasan a ser canónicos de orden — sigue siendo el contrato v1, solo cambia el event.type:
  • fiscal.authorized.br → order.invoiced y fiscal.cancelled.br → order.reversed. Si tu integración despacha por event.type, actualiza el switch — el payload no cambia de forma.
  • Ahora disparan para todos los países: Brasil (SEFAZ vía tu proveedor fiscal) y CO/EC/CL/AR/VE vía el callback fiscal genérico. El país viaja en fiscal.countryCode.
  • Nuevo evento order.status_updated — el KDS avanza la orden en cocina (preparing → ready → dispatched), con bloque kitchen y el recorrido completo en history.
  • Fire es la fuente de verdad — los webhooks entrantes (callback fiscal, estados KDS) ahora validan que eventId referencie un evento emitido por Fire para esa orden; si no, responden 400 antes del 202. Ecoa siempre el event.id de un envelope que recibiste.
  • Documentado en EN / ES / PT.

9 de junio de 2026 — Contrato de eventos v1

El contrato de eventos de orden/fiscal/cierre es ahora oficialmente v1. Todas las adiciones son retrocompatibles (campos opcionales nuevos); la forma anterior se preserva como v0 (deprecada, histórica) — cambia con el selector de versión arriba de cada página de evento.
  • Descuentos — descuentos de orden y de producto viajan como objeto Discount (priority, type FIXED/PERCENTAGE, value, net_price, discount_value, net_price_after_discount) en payments.discounts, payments.totals[].discounts y orderLines[].price.*[].discounts + lineTotals[].discounts.
  • Impuestos granulares — taxes[] ahora lleva los impuestos de la reforma BR IBS_UF, IBS_MUN, CBS junto a ICMS/PIS/COFINS, con metadata de reforma (cClassTrib, reducao, rateNominal, rateEffective). El desglose es uniforme en todos los países — LATAM lleva su IVA local en el mismo taxes[]; solo la emisión SEFAZ (metadata.fiscal, fiscal.*.br) es BR-only.
  • itemType — enum completo: PRODUCT / COMBO / MODIFIER / PACKAGING.
  • fulfillment.delivery.deliveryConfirmationCode — código de confirmación del agregador (ej. iFood / Rappi).
  • store.business_day_closed — sales ahora incluye product_discounts, gross_before_discounts, shipping, extra_charges, total_charged y taxes_by_type. (Superado el 11 de junio — estos agregados ya no van embebidos en el evento; el payload de cierre ahora es thin. Ver la entrada de arriba.)
  • order.cancelled / order.invoiced / order.reversed — llevan el snapshot v1 de orden.
  • Documentado en EN / ES / PT con ejemplos actualizados.

8 de junio de 2026

  • menu.updated: añadido productModifiers[n].overrides[] — permite definir un precio diferente para una opción específica de modificador cuando pertenece a un producto concreto. Cada override apunta a un productId y proporciona su propio priceInfo.price y priceInfo.salePrice. Actualizado EN/ES/PT.

5 de junio de 2026

  • menus.sync: página eliminada — Fire envía un único evento menu.updated por menú; la sincronización en lote ya no es un evento separado.
  • menu.updated: campo event.timezone eliminado del payload. Añadido data.groupId — UUID que identifica el batch de sincronización; varios eventos emitidos juntos comparten el mismo valor, lo que permite correlacionarlos en sistemas externos. Los arrays schedules de categorías y productos ahora incluyen ejemplos completos de 7 días con distintas ventanas de horario por categoría (p. ej. Hamburguesas 11:00–23:00, Desayunos 07:00–11:00). Campo standardTime en productos documentado: true hereda los horarios del menú, false significa que el producto tiene su propio array schedules. Actualizado EN/ES/PT.
  • Inyectar orden: el campo type es ahora obligatorio en cada ítem de order.products[], en cada ítem de selectedModifiers[] y en cada ítem de payments.extraCharges[]. Valores aceptados: COMBO (producto con grupos de modificadores no vacíos), PRODUCT (producto simple vendible o opción vendible dentro de modificadores), MODIFIER (opción de modificador puro), PACKAGING (ítem de empaque). Los payloads que omitan type son inválidos. Ejemplos de petición actualizados en EN/ES/PT.
  • Inyectar orden: documentado shippingMethod.delivery.additionalInfo.deliveryConfirmationCode como string opcional para enviar el código de confirmación de entrega.

1 de junio de 2026

  • Inyectar orden: secciones Montos y tramos de precio y Envío y descuentos; tres ejemplos de petición conciliados (entrega simple, descuento en línea + envío, varios productos + descuento de orden); énfasis en payments.shippingCost[], payments.discounts[] y discountsValue por producto (EN/ES/PT).

27 de mayo de 2026

  • menus.sync: ejemplo de payload completo (categorías, productos, grupos de modificadores, horarios); data.menus[] reemplazado por data.menu (un menú por evento); páginas EN/ES/PT en webhook reference.
  • menu.updated: estructura general alineada con menus.sync — campos del catálogo (list, categories, products, modifierGroups, scheduledActivities) anidados bajo data.menu; tablas de campos y ejemplo de borrado actualizados.
  • Guía Publicación de menú (EN/ES/PT): ejemplos y pasos de procesamiento actualizados para data.menu.
  • Inyectar orden: campo opcional comment documentado en order.products[]; ejemplo de petición actualizado (sustituye productComment).
  • menu.updated / menus.sync: los productId de las opciones de modificador deben existir en products; el ejemplo incluye prod_size_small y prod_size_large.
  • menu.updated: corregida la indentación del ejemplo principal del payload bajo data.menu.
  • Webhooks de menú (menu.updated, menus.sync, product.updated): data.country documentado y ejemplificado como ISO 3166-1 alpha-2 (p. ej. EC, BR, CO) en lugar de un ID numérico de país.

26 de mayo de 2026

  • Agregada la pestaña Manuales de usuario como sección principal de la navegación.
  • Agregados manuales de FIRE POS V2 para Vinculación, Cajeros y Códigos de autorización en inglés, español y portugués.
  • Agregadas imágenes placeholder sutiles para las capturas pendientes de POS, manteniendo la estructura visual final de las guías mientras se preparan las capturas.
  • Inyectar orden: eliminado el campo order.stock del cuerpo (no aplica al contrato). Ejemplo de respuesta 200 actualizado al sobre real (data, isArray, status, method, pathname, duration, traceId).
  • Login (playground): authMethod: none, URL absoluta de staging en el frontmatter api:, cabecera Content-Type con valor por defecto y grant_type por defecto para evitar el error Missing required fields al usar Probar.
  • Inyectar orden: price de línea de producto documentado con todos los campos del tramo de precio y taxes[] (name, rate, amount, metadata opcional).
  • Inyectar orden: payments.shippingCost[] y payments.discounts[] documentados como las mismas filas de tramo de precio que totals[]; ejemplo de petición actualizado con líneas de envío y descuento.
  • Cancelar orden: referencia API actualizada a la ruta de agregador POST /api/v4/integrations/sales/aggregator/orders/{order_uid}/refund, con campos de cancelación/reembolso y sobre estándar de respuesta; movida debajo de Inyectar orden en la referencia API.

11 de mayo de 2026

  • Nueva pestaña Cambios al final de la navegación y esta página inicial.
  • Eliminada la página de canales de venta (listado) y su entrada en la navegación (todos los idiomas).
  • Intro de la API: texto ajustado; retirada la tarjeta de canales de venta.
  • Inyectar orden: documentada la cabecera Authorization (EN). ES y PT: ruta, cabeceras y cuerpo actualizados al contrato actual de integración (objetos de canal/servicio, dispositivo, operador, ejemplos).
  • Login (ES y PT): alineado con POST /api/authentication/login y respuesta accessToken (client credentials).
  • Inicio en español (/es/): contenido revisado.
  • Configuración: nueva guía Integraciones de agregadores (panel Fire: endpoints de webhook y eventos de prueba).