Subscribe to updates
Get an email whenever a new entry lands here — new events, breaking changes and API reference updates. One click to unsubscribe.
Subscribe21 October 2026 — Import and export the catalog
The backoffice has a new screen, Import & export (Operation → Import & export): download a copy of a vendor’s catalog, edit it outside the backoffice and import it again, reviewing every change before it is written.- Import & export — new manual. Two formats: Full backup (JSON), with categories, modifiers, price lists, products and menus, to keep a copy or move the catalog to another environment; and Editable spreadsheet (Excel), with categories, products and prices in flat rows, to change many at once.
- Review first — importing never writes right away: the file is analyzed, you review what would be created, updated and deleted, and only then apply it. Before applying, Fire saves a backup of the current data.
- Merge and Replace — Merge creates and updates and deletes nothing. Replace leaves the data exactly as in the file and deletes what is not in it; it is reserved for platform administrators, who can also Undo an applied import.
- Affected combinations — the detail lists the store × channel × Fulfillment Type combinations that use a menu or price list that changes.
Importing does not synchronize: the changes reach stores and channels only when you synchronize from Menu assignment.
13 October 2026 — API keys guide and sale prices in the backoffice
A new guide covers API keys end to end: where to create one, what vendor scope means, and which scope each endpoint needs.- API keys — create keys under Developers → API Management with Create API Key: pick a name, the scopes and an optional expiration. Select a vendor in the dashboard before you create the key: with All vendors selected the key has no vendor binding, and endpoints that require one answer
403. - Scopes — every scope in the dashboard, mapped to the endpoints it unlocks, including
cash-management:writeandkiosks:write. - Managing keys — you can edit a key’s scopes without changing its secret; name, description and expiration are fixed once created, and there is no built-in rotation (create a new key, switch, then revoke the old one).
- Header — send the key in
x-api-key.Authorization: Bearer pk_live_...still works as a legacy alias; if you send both,x-api-keywins. - List menus and Get menu now link to the guide for the
menu:readscope and the vendor binding.
- Price lists — sale prices now live here, next to the price, and also apply inside combos. How far a sale reaches, and why a suggested price is only a struck price, never charged.
- Menus — a menu no longer has a fulfillment type of its own: it takes the one from the assignment row. Three lenses (day, fulfillment type, prices) and the new Overrides tab.
- Menu assignment — sale prices travel with Sync, batches drop from 50 to 20 rows, and price edits saved from the preview only reach aggregators, not POS or Kiosk.
- Modifier groups — adding a group to a product copies it: later edits to the group don’t reach products that already have it. Different questions per fulfillment type.
- Products — combos have no price of their own: the customer pays the sum of the options picked. The “from” reference price, sales inside a combo and prices by fulfillment type.
6 October 2026 — New endpoint: list a store’s terminals
You can now read which devices a store has and what state they are in: POS registers, self-service kiosks and KDS kitchen displays.GET /external/stores/{storeId}/terminals— returns each terminal’stype,statusandlastSeenAt, and itsexternalId(for kiosks, the device ID on the QR screen). By default it returns active and suspended terminals; ask for revoked ones withstatus=REVOKED. Filter bytypeand trim the response withfields. Uses thestore:readscope you already have for the store endpoints.
5 October 2026 — The partial day report in receipt printing
Print the day close accepts"partial": true to print
how the day is going so far without closing it (X report): same template as the close, with a
PARCIAL — NO ES CIERRE band and the cut time.
- Only the store’s open day; any other date responds
409 PRINT_DAY_NOT_OPEN. - The response carries
subject.partial: true, andfreshness.asOfis the cut time. - Without
partial, the endpoint behaves exactly as before.
30 September 2026 — The store fiscal block has the same shape in every country
Thefiscal block in List stores and
Get store is no longer Brazil-specific. secondaryGovIdType,
secondaryGovIdNumber and metadata are always present, null when the store doesn’t have
them, same as store.storeFiscalConfig in order.completed.
- Colombia:
metadatacarriesclaveTecnica,rangoFacturacionandrangoNotaCredito(the DIAN numbering ranges). - Ecuador, Chile, Argentina, Venezuela: the three keys are present, as
null. They used to be absent. - Brazil: unchanged.
order.cancelled, order.invoiced, order.reversed) carry the same block as
order.completed: in Colombia, the cancellation includes the ranges used to issue the credit note.
28 September 2026 — External API menu endpoints documented
Two endpoints join the External API, alongside Get store and List stores: reading a store’s menus by API key, the query-side counterpart to themenu.updated webhook.
- List menus — which ternas (store × channel × fulfillment type) of a store currently have a generated menu, without the menu body.
- Get menu — the last generated menu of one terna, in the same shape as
menu.updated, with asyncblock telling you whether it reached the channel.
Design is closed but not implemented yet — there is nothing to call today. This entry exists so you can build against the contract ahead of the release.
25 September 2026 — Cash handed over and change in the order events
The two cash fields ofpayments.paymentMethods[] in the events that carry the V4 order snapshot (order.opened, order.completed, order.invoiced, order.cancelled, order.reversed). The event versions do not change.
customerCashAmountis a number and carries the real amount. Until 24 September 2026 it always travelled as the string"0", even on cash payments. Now it is the cash the customer handed over: for a22.9bill paid with a50note,50;0on methods that are not cash.changeAmountis listed — the change the till gave back, as a number:27.1in the example above,0on methods that are not cash,nullwhen the till did not send it. It already travelled in the events; it was missing from the reference.- If your consumer checked that
customerCashAmountis a string, it now fails. Read it as a number. Events of orders injected before 24 September still carry"0", so a replay of an older order does too.
23 September 2026 — Catalog Agent user manual
New manual for anyone managing the catalog with the Catalog Agent, the AI chat that proposes product tags and applies them only with human approval.- Catalog Agent — how to chat or upload a file to tag products, which decisions the agent asks for (mode, new terms, aliases), and why an approval can come back partial when someone edits the product in the meantime.
16 September 2026 — cStat is emitted again, inside countryData
This supersedes what a later entry says. On 15 September we announced that cStat was no longer emitted. Consumers asked for it back — without it a cancellation does not say whether the authority accepted it — so it returns. Only cStat: docType, dataAutorizacao and sefazCancellation stay out.
- Brazil:
authority.countryData.cStat. The code the authority resolved this document with:100on an authorization,135on a cancellation. It is the authority’s own vocabulary, so it travels besidechaveAcessoandprotocolo, not at the root of the block. - A cancellation carries its own code, not the invoice’s.
order.reversedreads135— the cancellation event registered at SEFAZ — while theorder.invoicedthat preceded it keeps100. Verified end to end in staging. - It travels as the provider sends it,
numberorstring. We do not normalise a type the authority did not choose. - Through the fiscal callback it already worked: anything inside
documentthat is not canonical reachescountryDatauntouched. SendcStatthere and it arrives — no change was needed on your side. mensagemSefazstays out. Only the code comes back.- Rejections still emit no event. A
rejecteddocument stores its code but fires neitherorder.invoicednororder.reversed, socStatdoes not reach you for that case.
15 September 2026 — KDS bump printing, zoom, and Android Fire Agent
Kitchen print is now a store rule (comanda and/or fiscal on one station). Tablets need their own Fire Agent. Zoom and the operator reprint printer are separate from that rule.- Print on bump — By screen or By station, documents and fiscal timing. Arm the queue on the KDS screen. A dashboard alert fires if the print station has no active screen.
- Screen actions — station/ticket zoom (timer double-tap, default key Q). If the printer fails after a fiscal-ready bump, the ticket shows Queued: printer failed.
- Operator board — Operator fiscal printer on the supervisor PC (not the kitchen queue).
- Android installation — APK on the KDS tablet.
kds-agent.fire.restmust resolve to127.0.0.1. Token and printer name must match fire-kds. - Stations / Routing — station item-type veto is gone. Categories live only in the routing strategy.
15 September 2026 — Cancellation dates and rejected documents
Two fixes to what the fiscal callback stores, and therefore to whatorder.invoiced and order.reversed carry. The event versions do not change.
- A cancellation keeps the invoice’s dates.
authority.issuedAtandauthority.authorizedAtnow stay as the invoice had them, even when thecancelledcallback sends its own. Before, they took the cancellation’s time whilecompensates.issuedAtstill pointed at the invoice, so the same block told two stories. Useauthority.cancelledAtfor when the document was annulled. - A negative outcome stores no receipt data. On
rejected,deniedanderror, Fire ignoresdocumentNumber,providerDocId,issuedAt,authorizedAt, the amounts,pdfUrl,xmlUrlandgraphiceven if the provider sends them;documentType,docSubtype, the country’sdocumentkeys,failure,providerandmetadataare kept. A rejected document used to read like an authorized one, with a number and anauthorizedAton it. A document that already had receipt data keeps it.
15 September 2026 — Structured fiscal block and new fiscal event versions
The fiscal block of the three fiscal events is now what Fire stores on the order, with one shape for every country: the authority’s verdict inauthority, plus the document’s journey and what it replaces. Two new guides explain the whole cycle.
- Breaking — the fiscal block of
order.invoiced,order.cancelledandorder.reversedis structured. Canonical fields move intoauthority(documentType,documentNumber,issuedAt,cancelledAt…), amounts intoauthority.amounts, and the authority’s own identifiers (chaveAcesso,claveAcceso,cufe,protocolo…) intoauthority.countryData.dataAutorizacaobecomesauthority.authorizedAt;docType,cStatandsefazCancellationare no longer emitted. Every previous path has exactly one new path: see Path changes. - Breaking — on a cancellation the block moves from
cancellation.metadata.fiscaltocancellation.fiscal, andcancellation.metadatais no longer emitted. When the order had no authorized document, thefiscalkey is absent — before it wasnull, so a check for=== nullstops matching. - Breaking — the fiscal callback moved every canonical field out of
documentto the root (documentType,docSubtype,documentNumber,issuedAt,authorizedAt,cancelledAt,authorizationMode,providerDocId,totalAmount,taxAmount,currencyCode,pdfUrl,xmlUrl,graphic);documentnow holds only the country’s identifiers. Renames:countryCode→country,docType→documentType(SALE_INVOICEorCREDIT_NOTE, the only two accepted),error→failure(withscopeanddetails),providerSpecific→metadata,emittedAt→issuedAt. A sender using the previous names receives400naming the field — fordocType, onauthorizedandcancelled. In EcuadornumeroAutorizacionis retired: the authorized identifier isclaveAcceso.cnpjEmitenteis not part of the contract. order.cancelledcarries the fiscal block in every country with an authorized document; before it was Brazil only.historyandcompensates—order.invoicedandorder.reversedcarry every stop of the document’s journey, oldest first.compensatespoints at the document the current one replaces, so it is filled onorder.reversedandnullonorder.invoiced.authority.providerIdentityandauthority.providerMetadata— the callback’sproviderandmetadatanow reach the order and the events, with the same names as in the fiscal numbering.nullwhen not sent; PlugNotas (Brazil) never sends them.- How fiscal works in Fire — the two acts (numbering and authorization), the two blocks on the order, and the two ways a document reaches Fire.
- From the callback to the events — which event fires for each callback and where every field lands.
In Brazil
authority.authorizedAt carries the SEFAZ date with a conventional midnight time, so it can read earlier than issuedAt. Use issuedAt for the moment of the sale.
Not backwards compatible for the fiscal block; the rest of the order snapshot is unchanged. The previous versions stay available from each event’s version tabs.
Updated in EN / ES / PT.
4 September 2026 — Coupons on order lines
Orders can now arrive with coupons.order.completed carries who financed each discount, on the line and on the order.
orderLines[].rewardId— the coupon’s redemption code, ornull. Selected modifiers carry it too: on a combo the discount usually sits on the modifiers, not on the container. Two shapes are both valid and neither is a bug:nullwith a discount (a catalog markdown, no coupon), and a code withdiscountValue: "0"(the coupon changed the list price instead of discounting it).data.marketing.coupons[]— was reserved for future use; now carries{ rewardId, name, metadata }per coupon.metadata.scopeisproduct,orderorshipping, andmetadata.amountis the money it took off. A coupon withscope: "order"appears only here: its amount reaches the lines already spread across them, and nothing links the slices back to it.
value in a coupon’s metadata is the rule’s nominal figure — a percentage, or points — not currency. The money is always amount. And baseValue: null means the list price is unknown, which is not the same as zero.
Backwards compatible: both fields are additions on the existing shape, and
rewardId is null on every channel that does not send coupons.
Updated in EN / ES / PT.
3 September 2026 — KDS Fire credentials, ticket rows, and station categories
Kitchen print and cancel need the right Fire host and key. Ticket cards can now sit on one to three rows. Products get a routing category and a kitchen thumbnail.- Fire API credentials — account default vs vendor override. The base URL is the Fire host only; fire-kds appends print and cancel paths.
- Station categories — codes used as
item_typein routing, plus product thumbs on the category view. - KDS Fire credentials (technical) — vendor row → account default → env. Print reads
FISCAL_PRINT_*only. Cancel may fall back toFIRE_*. - Screen actions — Ticket rows (1–3) reserve space for notes. If Fire rejects a cancel, the operator sees the rejection and the policy detail; the job stays failed.
3 September 2026 — The catalog: products, categories and modifier groups
Three new manuals for the screens that feed everything else. A menu invents nothing — it picks from the catalog — so this is where the work actually starts.- Products — the four types, the switches that decide whether something sells, price, modifiers, combos and suggestions.
- Categories — the blocks customers browse with, their schedule, and channel exclusivity.
- Modifier Groups — the questions asked at order time, and the options that answer them.
- Modifier options are catalog products. To offer extra cheese there has to be an extra cheese product; its price is read from that product, never typed on the group.
- You only set two numbers on a group: minimum and maximum. Required/optional and single/multiple are derived from them, so a group cannot contradict itself.
- Channel exclusivity cascades. Marking a category exclusive takes it and its products out of the Golden Menu.
- A combo has no pricing tab, and its listed price is a calculated reference, not what you charge. The real price comes from the destination’s price list.
The pricing tab is country-dependent: in Brazil it is simplified to the final price plus the
fiscal category (NCM). Product variants are planned but have no screen yet.
3 September 2026 — Menus: building the menu and getting it to the channel
Two new manuals for the pair of screens that decide what is sold and where: the Golden Menu and the custom menus that inherit from it, and the matrix that puts each menu into each store, channel and fulfillment type.- Menus — Golden and custom, inheritance, the create dialog, the Structure and Overrides tabs, and the price and day lenses.
- Menu assignment — the store x channel x fulfillment matrix, bulk assignment, Sync and its warnings, and the sync preview.
- The fulfillment type is chosen once and cannot be changed. It is the only field on the menu with no way back: getting it wrong means creating the menu again.
- Saving a menu does not publish it — there is no publish button in the editor. The menu reaches a channel only when somebody syncs the corresponding row on the assignment screen.
- Sync flattens the menu fresh, with no versioning. It sends the menu and the price list exactly as they are saved at that second; an earlier state cannot be republished.
- A row can end up Synced and still have dropped products. A product with no price in the assigned list is left out of the payload rather than published at zero, and only the warnings chip says so.
Aggregator channels receive their events, but their outcome is not yet reflected in the sync
status on this screen. The menu History tab is also still empty.
2 September 2026 — Out of stock: turning products off during service
New manual for the Out of stock screen: taking a product off sale in one store when the kitchen runs out, without editing the menu and without anyone having to undo it later.- Out of stock — the turn-off dialog, scope by channel, the mandatory reason, restoring, and the Audit tab.
- A turn-off never outlives the store’s closing time. The ceiling is the end of the store’s business day, not a fixed number of hours: a product turned off today is selling again when the store opens tomorrow.
- Scope is a channel and fulfillment type pair. A product can be turned off for the kiosk while it keeps selling at the till.
- As a combo option, the product stays selectable. If it is also sold inside modifier groups, the dialog names them and the turn-off records them, but channel availability is per product — there is nowhere to put an option in either contract.
- The reason is mandatory and immutable. Changing the expiry moves the time only — the reason stays as the record of why the product was turned off.
- Publishing the menu closes the turn-off — but only if it covered the whole scope. A store-wide turn-off survives a publication that reached one channel, because the others really are still out of sale. The outcome is Replaced by a sync.
- A turn-off is saved even when the channel is not notified. Notifying is reported separately from saving, and turn-offs whose notification did not land are counted in the header and flagged on their row.
The turn-off does propagate to the sales channels:
products/listing per product for X-Mart
channels, and product.availability_changed
per channel for the aggregators — in all three directions (turning off, restoring, expiring). The
row stays as Fire’s operational record — what stopped being sold, when and why — and never enters
the menu snapshot: that separation is deliberate, not a pending stage. What does not propagate are
products sold only as a modifier option: neither contract has anywhere to put them.15 August 2026 — The fiscal block: country identifiers, voiding and provider
fiscalRepresentation drops its fixed per-country fields and now carries the order’s
current document, with the previous ones in history.
- Breaking —
sequential,serieandclaveAccesoare no longer fields of the block. The authority identifiers now live incountryData, in the vocabulary of the country that numbered:claveAcceso,establecimiento,puntoEmision,secuencialandambientein Ecuador;numeroControl,numeroFacturaandseriein Venezuela. Iterate the keys, do not index them: a channel readingcountryData.claveAccesooutright works in Ecuador and breaks with the first country added. The fields that mean the same everywhere —documentNumber,issuedAt,authorizationMode,numberingStatus— did not move. historyandcompensates— when a cancellation numbers, the credit note becomes the top document,compensatespoints at the invoice it voids, and the whole invoice moves down intohistory. Everyhistoryentry has the same keys as the block above, so they read the same.environment— which environment Fire numbered in:SANDBOXorPRODUCTION. It is ours, not the authority’s; the authority’s still travels insidecountryDatawith its own code.providerCode,providerIdentityandproviderMetadata— these used to be a single object mixing three things.providerCodeis our adapter identifier;providerIdentityis the provider’s block (name,version,reference) and has a shape;providerMetadatais an opaque bag and you should not program against its keys. The numbering endpoint’s response now returns exactly the same three fields, under the same names.
If your reconciliation assumes
documentNumber is always the sale’s, revisit it: after a
cancellation the number on top is the credit note’s. What the customer walked away with is
not lost — it is in history — but you have to go there for it.order.opened,
order.completed,
order.cancelled,
order.invoiced,
order.reversed, in the
endpoint reference and in the
Integrating fiscalization guide.
Updated in EN / ES / PT.
13 August 2026 — Fiscal numbering now travels in every order event
Orders numbered by the Fiscal Gateway before injection now carry those identifiers in every event of the order, so you no longer need a second call to print or reconcile.-
data.fiscalRepresentation— series, sequential, document number, access key and the QR (graphic), exactly as printed at the till. The key always travels: it arrives asnullwhen numbering was not attempted — aggregators, countries without fiscal representation, or numbering turned off — and carries the block when it was. Branch on the value (if (data.fiscalRepresentation)), not on the key’s presence. Carrying the block means numbering was attempted, not that it succeeded:numberingStatustells you how the attempt ended andfailurewhy, when it did not end well — a charged sale left with no fiscal receipt arrives withnullidentifiers and the reason infailure. Carrying the block does not mean the document is authorized: the authority’s verdict stays inlastKnown.fiscal.status. The block itself never changes, even after the authority authorizes or rejects. -
data.lastKnown.fiscal.sourceEvent— now reports real provenance instead of deriving it from the status. Aprocessingseeded at injection used to be reported asfiscal.callbackeven though no callback had occurred; it now saysorder.injected. Account for the new value if you branch on this field. -
Documented on
order.opened,order.completed,order.invoicedandorder.cancelled.
11 August 2026 — BOH API: qty_base derived server-side with item_unit_id
On purchase order lines (POST /procurement/orders, add-lines, and line update), qty_base is now optional when the line references item_unit_id — not only unit_code. The server derives qty_base = qty × factor_to_base from the referenced unit, so external integrators referencing a purchase unit by UUID no longer need to know or recompute its conversion factor.
If you send an explicit qty_base anyway, BOH validates it against the derived value (tolerance 0.001) and returns purchase_order_qty_base_mismatch (422) on disagreement — same behavior as unit_code. If item_unit_id doesn’t resolve to an active unit and qty_base was omitted, the response is now the typed error item_unit_not_found (404).
Updated in EN / ES / PT.
11 August 2026 — BOH API: store resolution by fiscal ID in purchase orders (Phase 19)
tax_id is now a first-class field on BOH stores (RUC, CNPJ, CUIT, NIT, RUT, RFC, or any fiscal code up to 64 characters). It is optional, not unique, and accepted in POST /identity/stores and PATCH /identity/stores/{id}.
When creating a purchase order via the API you can now identify the receiving store with any of three mutually exclusive fields:
store_id— existing UUID (unchanged).external_store_id— cross-system external identifier.store_tax_id(new) — fiscal identifier. Returns422withpurchase_order_store_tax_id_ambiguousif multiple active stores share the value (e.g. Ecuador RUC shared across branches) — usestore_idorexternal_store_idin that case.
11 August 2026 — BOH API reference restructured: one page per endpoint
The BOH API tab has been fully restructured into individual endpoint pages. Each endpoint now has its own menu entry showing the HTTP method (GET, POST, PATCH, DELETE), interactive request/response examples, and a Try it button to test the endpoint directly from the docs.
The new structure covers all 63 endpoints across 6 sections: Identity, Catalog, Recipes, Operations, Procurement, and Webhooks.
Updated in EN / ES / PT.
11 August 2026 — BOH API: purchase orders — supplier SKU resolution and external_user_id
Two additions to the purchase orders reference:supplier_sku on lines — a third item identifier for ERP integration. Instead of item_id or external_item_id, send supplier_sku (case-insensitive) and BOH resolves the item directly from the order’s supplier catalog, deriving base_unit_id automatically. Error: purchase_order_supplier_sku_not_found (404).
external_user_id on create — the caller’s user identifier is now accepted when creating a purchase order and stored as actor_external_user_id. Previously the field was silently ignored.
Updated in EN / ES / PT.
10 August 2026 — KDS manuals: device pairing, operator board, line strike, and display defaults
New and updated KDS user manuals covering recent fire-kds product work: Pair a kitchen device — new guide. Enroll kitchen TVs with a 6-digit code from KDS → All Stores, manage paired terminals, and understand device vs email sign-out. Operator board — new guide. Supervisor list/detail with live timers, filters, collect codes, and cancel / ready / dispatch overrides. Screen actions — line strike before bump, dispatch waiting for assembly, new-order alert, and richer display settings (store defaults, customer name by channel/fulfillment). Order display — fulfillment filters (e.g. hide delivery from the turnero). Overview — store-level KDS options (display defaults, line strike, cancellation reasons) and links to the new guides. Updated in EN / ES / PT.7 August 2026 — BOH API: operations, identity, bulk sync, and procurement endpoints
The BOH API reference now covers the full set of endpoints needed to build a complete integration: Identity — new section. Discover your account context (GET /identity/me), list vendors, and fully manage stores and suppliers (create, update, archive/unarchive).
Catalog: Bulk sync — new section. Three bulk PUT endpoints:
PUT /catalog/units— upsert units bycode + unit_group_code; global units are skipped safely.PUT /identity/suppliers— upsert suppliers byexternal_supplier_id.PUT /catalog/classifications/assignments— replace all classification assignments for an item or store atomically.
- Goods receipts (create, list, get) — supports
external_store_idandexternal_supplier_idso you don’t need to pre-fetch UUIDs. - Stock counts (create, list) —
FULLorPARTIALscope, witharea_breakdownfor collaborative field-count sessions. - Waste events (create, list) — lines by item, item tag, or subrecipe snapshot.
- Transfers (create, list) — atomic debit/credit between stores.
- Production batches (create, list, get) — records recipe execution with actual output and optional ingredient overrides.
- Tracking transactions (get status, list) — poll any async write via its
tracking_id.
POST /procurement/orders with idempotency key, list/get, submit, confirm, add/update/remove lines, cancel, close, and fulfillment status), plus PUT /procurement/par-levels to upsert stock targets per item/store and GET /procurement/suggested-order to retrieve recommended reorder quantities. Purchase orders also support ERP integration via external identifiers: external_supplier_id, external_item_id, and unit_code resolve internal records server-side (no BOH UUIDs needed), external_reference tags the order with your document code (filterable on the list endpoint), and lines accept informational amounts (tax_amount, delivery_amount, total_amount, markup_amount).
Updated in EN / ES / PT.
7 August 2026 — BOH manuals: channel-scoped recipe lines, collaborative counts, account currency
Three updates to the BOH user manuals reflecting recent product changes: Recipes — channel-scoped lines (Phase 16) The “Service complements” model has been replaced by channel-scoped lines on a single recipe. Each recipe line now has an optionalservice_codes field:
- Lines without
service_codesare general and always apply. - Lines with
service_codes: ["DELIVERY"]only apply when the order’s channel matches. - A single published recipe per product and store replaces the old BASE + COMPLEMENT pair.
7 August 2026 — Price lists: new user manual
Price lists let you run different prices per channel, location or campaign without maintaining each one by hand. The manual is now available: Price lists.- Connected lists — a list can follow a base list. Change the price once and it reaches all
of them; any product that needs its own price sets one and stops following, just for that
product. Formulas like
=P*1.15stay live: when the base moves, the list recalculates itself. - Contextual prices — the same product can be worth a different amount inside a combo. Those prices used to be buried in each combo’s configuration; they’re now visible and editable from the product row, with the percentage against the standalone price.
- Bulk edit with commercial rounding — apply a percentage or amount to many products at once,
reaching the prices inside combos too, and round to
.99,.90or a whole number so you don’t end up selling at 13.42. - Comparison mode — overlay another list as a reference to see, product by product, where the two diverge.
- Blast radius before saving — a summary of which connected lists receive the change and, more importantly, which one gets nothing because every product you touched has its own price there.
- Connecting an existing list — a list that was born as a copy and drifted can be connected to a base list. Whatever matches the base starts following it, whatever has its own price stays put: no price moves at the moment you connect.
Time-based pricing (day-parting) is not available yet, and this phase works on the final
price with taxes included — net price and reference price come later. The manual states both
limits explicitly.
6 August 2026 — Component health heartbeats for kiosks, KDS and POS
Kiosks, KDS stations and POS terminals can now report that they are alive, and Fire’s availability dashboard reads the fleet from those beats. The endpoint isPOST /external/component-health and needs an API key
with the component-health:write scope.
- Component health — one beat per cycle with
componentType,componentId,storeIdandstatus. OptionalsentAt,offlineSince,degradedReason,appVersionand a free-formdetails. Answers204 No Content. X-Heartbeat-Interval— every204carries the cadence in force, in seconds. Adopt it on the next cycle: that is how the interval is reconfigured without shipping a release.- A
componentIdmust be stable — if it changes between reboots, Fire sees a different component: the old one is retired after 7 days and the new one starts with no history. degradedReasonuses a shared vocabulary —printer_down,pinpad_down,backend_unreachable,queue_backlog,peripheral_other. Thedetailskeys forkds_stationare still to be agreed with the KDS team.
status accepts only online and degraded. There is no down: a device cannot declare
itself dead — Fire infers the outage from the missing heartbeat, after two missed intervals.4 August 2026 — New assignedAt field on menu and product events
menu.updated v2 and product.updated now carry assignedAt on every category and product.
categories[n].assignedAtandproducts[n].additionalInfo.assignedAt— the date the entity joined the menu, ISO 8601 UTC, no milliseconds. It’s membership data, not edit data: untouched by price, name, image, or order edits; gets a new value when an item is removed from the menu and re-added. Full edge cases inmenu.updated→ Menu assignment date. Not carried byproduct.price_updatedorproduct.availability_changed— they only ship their delta.menu.updated/product.updatedusetaxInfo(nottaxesInfo),type: PRODUCTOfor standard items, andmodifierGroups[n].type: RADIOfor single-select groups (CHECKBOXfor multiple).storeIdis the store’s internal UUID (stores.id), not thestore_number— same convention acrossmenu.updated,product.updated,product.price_updated, andproduct.availability_changed.product.price_updated’spriceInfodoesn’t share a shape with the catalogpriceInfoinmenu.updated/product.updated— it’s the sale price just saved with its discount, not catalog pricing.
channelReferenceName means the fulfillment (delivery, pickup) in menu.updated’s list.stores[n].channels[n], but the sales channel (iFood, Rappi) in the same field name on product.updated, product.price_updated, and product.availability_changed. Same key, two different things depending on the event.4 August 2026 — Subscribe to the changelog by email
You can now get an email whenever a new entry lands on this page. Subscribe from the button at the top — Buttondown handles the list, so no address is ever stored in the docs, and one click unsubscribes you from any email.- One email per entry, in all three languages — English, Español and Português arrive stacked in the same message, so there is nothing to pick.
- Only a new entry sends — correcting a typo in something already published never re-sends it.
2 August 2026 — order.opened and the deferred-payment blocks
Each event advances on its own version line — there is no global contract number:
Every addition is backward-compatible (new blocks on an existing shape). Nothing here
changes a field you already read, and the previous contract of each event stays online
behind its version tab.
- New event
order.opened— fires when an order is injected already open: it exists, the kitchen can start, nobody has paid yet. Carries the same V4 snapshot asorder.completed. It does not fire for orders injected asCOMPLETEDorCANCELLED. This event has no v0 — it was born at v1. data.policy.deferredPayment— added to all four order events (order.opened,order.completed,order.invoiced,order.cancelled). Says whether the order may be cooked, invoiced or dispatched before payment. Resolved once at injection and stamped immutably; every later event echoes the same value.data.lastKnown— added to the same four events. Advisory snapshot of kitchen and fiscal state. Never gate an irreversible action on it — it may benullor stale, and Fire itself ignores it and re-reads from source before issuing anything.
On
order.opened, payments.paymentMethods[] is what the POS declared, not what
was charged — transactionStatus is PENDING and transactionId is usually empty.
Fire overwrites the array with the real tenders when the charge settles, and emits
order.completed. Reading the declared method as settlement evidence is the most
common mistake with this event.22 July 2026 — BOH user manuals
Added a BOH section to the User manuals tab covering back-of-house inventory administration from the Fire backoffice:- Overview and concepts — how catalog, recipes, procurement, movements, counts and reports fit together; the stock flow; map of the BOH menu.
- Stores and suppliers — BOH stores linked to Restaurant OS and supplier records with item-supplier links (price, purchase unit, SKU).
- Catalog — unit groups and units, items, interchangeable item tags (FIFO / FEFO / priority / highest stock), classifications.
- Recipes — sales, production and subrecipes; draft → published → archived lifecycle; channel-scoped lines; sale simulator.
- Procurement — receiving schedules, purchase order lifecycle, par levels and suggested orders.
- Receipts and returns — goods receipts (stock entry, PO linking, over-receiving) and supplier returns.
- Waste and internal consumption — waste reasons catalog, waste events, internal consumption.
- Transfers and production — transfers between stores and production batches with yield.
- Stock counts — inventory areas, full/partial counts, and the mobile counting app.
- Reports — usage, waste, production yield, and balance at a date.
13 July 2026 — Cancel Order: cancellationType field
Added optional cancellationType (string) to the Cancel Order request body. When provided, the cancellation reason ID or code from the catalog is persisted on the order and reported to the payment gateway. Updated in EN / ES / PT.
3 July 2026 — Inject Order: combo discount distribution
Added a new Combo discounts section to the Inject Order reference. When aCOMBO product has a container price of 0, the combo’s discountsValue must not be placed on the container line (this produces negative totals). Instead, distribute the discount proportionally across the selectedModifiers:
discount_i = ROUND(D × (base_i / B), 2)— proportional share per modifier- Every modifier must keep
subtotalIncludeDiscounts >= 0andtotal >= 0after the discount - The COMBO container must have all price fields at
0 SUM(modifier.totalPrice.discountsValue)must equal the combo’s total discount
29 June 2026 — KDS user manuals
Added a KDS section to the User manuals tab covering both operator and backoffice administration:- Overview and concepts — how stores, stations, screens, routing, devices and printing fit together; two station types (production vs convergence); kitchen patterns (assembly-only, KITCHEN, multi-station).
- Set up a store — apply a template (blueprint wizard) or configure from scratch; step-by-step order.
- Stations — fields, optional station rules by channel / service / item type, step-by-step creation.
- Screens — device identifier, create and assign stations, screen ↔ station relationship.
- Routing — decision layers (routing → rules → distribution → convergence), distribution modes, multi-station example.
- Peripherals, printing and validation — keyboard layouts, ready-pickup printing (one screen per store), order cancellation, go-live checklist and reference routes.
- Screen actions — bump, hold/unhold, undo, cancel, pagination, settings menu and keyboard shortcuts.
- Order display — customer-facing waitlist screen (preparing / ready areas, hero on ready, auto-pagination).
22 June 2026 — New guide: Products structure · Menu publication updated
New guide: Products structure
New Products structure page in the Guides tab — covers theCOMBO type and modifier overrides:
- COMBO type —
priceInfo.priceis always0; usepriceInfo.referencePriceas the product header price. - Reference price — sum of (cheapest option ×
minOptions) across every required modifier group (minOptions ≥ 1). - Modifier overrides —
productModifiers[n].overridessets a different price for an option inside a specific combo; takes precedence over the option’s base price inproducts[]. - Delta pricing — required groups show
+R$ Xabove the baseline; optional groups show the full add-on price.
Menu publication guide
- Removed the
menus.syncsection — that event no longer exists. - Fixed the payload format:
eventis now a nested object (id,type,executionId,createdAt), not top-level fields. - The signature verification step now specifies that the signing secret is obtained under Aggregator integrations in the Fire dashboard.
- Added a menu structure section describing
list,categories,products(type table), andmodifierGroups.
15 June 2026 — order.completed — new payment method fields
Added 4 fields to payments.paymentMethods[n] in the order.completed event. All fields are nullable and already live in production.
idAuth(string | null) — Authorization ID from the payment processor (e.g. SiTefIdAuth). Distinct fromauthorizationCode.receiptCustomer(string | null) — Full customer-facing receipt text; may be multi-line.receiptMerchant(string | null) — Full merchant-facing receipt text; may be multi-line.acquirer.cnpj(string | null) — Tax ID (CNPJ) of the payment acquirer — Brazil only.
15 June 2026 — Payment method details fields
Added 5 optional fields topayments.paymentMethods[n] in Inject Order:
id_auth(string | null) — NFCE authorization number (SiTef 952 / IdAuth).receipt_customer(string | null) — Customer receipt copy: printed receipt text for the cardholder (SiTef 121 / ReceiptCustomer).receipt_merchant(string | null) — Merchant receipt copy: printed receipt text for the store (SiTef 122 / ReceiptMerchant).acquirer.cnpj(string) — Acquirer CNPJ for NFCE (SiTef 950 / CNPJAuth).acquireritself is now documented as nullable — sendnullfor methods without an acquirer.card.media(string) — Card read method:CHIP,MAGNETIC,NFC,MANUAL(SiTef 2090 / Media).cardis now documented as nullable — sendnullfor non-card methods.
14 June 2026 — Aggregator order-status webhook
- New inbound webhook
POST /v1/webhooks/aggregators/order-status— your delivery aggregator (Rappi / Uber / Didi / iFood / PedidosYa / Glovo…) POSTs the order’s delivery status as it advances (courier_assigned→on_route→delivered…). Fire mirrors the latest status ontoorders.aggregatorand logs every event. - Status is passthrough — no enum is imposed; the aggregator’s own labels are stored verbatim, and the current status is the one with the latest
occurredAt(no anti-regression gate). Friendly translated labels are resolved at display time from the channel catalog. - Flexible order resolution — send
orderId(Fire UUID) and/orexternalOrderId(your reference, matched onmetadata.order_id); at least one is required, both vendor-scoped. If both are sent and resolve to different orders →409. - No Fire-emitted
eventIdto echo — an aggregator status is a spontaneous external event (Fire is not the source of truth here). Idempotency is keyed on(channelCode, providerEventId)+status;channelCodemust equal the order’smetadata.channel.code. - Auth: vendor-scoped API key with the new
webhooks:aggregatorscope. Async202+ queue, same envelope as the fiscal / KDS callbacks. - Documented in EN / ES / PT.
12 June 2026 — Aggregator discounts in Inject Order
Documented how to send aggregator platform discounts (iFood, Rappi, UberEats, etc.) in the Inject Order endpoint.- Aggregator discounts are a payment method, not a discount row. When an aggregator applies a promotional discount to the customer, the store receives the full amount and the aggregator reimburses the difference — model it as an extra entry in
payments.paymentMethods[]withpaymentMethodCode: "AGGREGATOR_DISCOUNT",transactionType: "BENEFIT",processorset to the aggregator name, andcard: null. payments.discounts[]stays empty for aggregator discounts — that array is only for store-absorbed promos/coupons.- New balance rule documented:
SUM(paymentMethods[].totalBill)must equal products + extra charges + shipping. - New request example with an iFood order (BRL 38.69 CREDIT + BRL 1.00 AGGREGATOR_DISCOUNT = BRL 39.69 gross).
- Updated in EN / ES / PT.
11 June 2026 — Underscore nomenclature + lean day-close payload
- Naming (breaking) —
store.day-closed→store.business_day_closedandorder.status-updated→order.status_updated(underscore nomenclature). Update yourevent.typeswitch. store.business_day_closedis now a thin payload — close identity (businessDayId,businessDayDate,timezone,status), timing (openedAt/closedAt),closedBy, and a minimalstore(uid,code,externalId,countryCode,timezone,currencyCode). Removed from the event:sales,metrics,summary,byChannel,byPaymentMethod,forceClosedOrders,closureStats,cancelledOrders,metadata— query them bybusinessDayIdwhen needed.snapshotIdrenamed tobusinessDayId(same value).- Documented in EN / ES / PT.
10 June 2026 — Canonical order events + kitchen event
Fiscal events drop the country from the name and become canonical order events — still the v1 contract, only theevent.type changes:
fiscal.authorized.br→order.invoicedandfiscal.cancelled.br→order.reversed. If your integration dispatches onevent.type, update your switch — the payload shape does not change.- They now fire for all countries: Brazil (SEFAZ via your fiscal provider) and CO/EC/CL/AR/VE via the generic fiscal callback. The country travels in
fiscal.countryCode. - New event
order.status_updated— the KDS advances the order in the kitchen (preparing→ready→dispatched), with akitchenblock and the full journey inhistory. - Fire is the source of truth — inbound webhooks (fiscal callback, KDS statuses) now validate that
eventIdreferences an event Fire emitted for that order; otherwise they respond400before the202. Always echo theevent.idof an envelope you received. - Documented in EN / ES / PT.
9 June 2026 — Event contract v1
The order/fiscal/day-close event contract is now officially v1. All additions are backward-compatible (new optional fields); the previous shape is preserved as v0 (deprecated, historical) — switch with the version selector at the top of each event page.- Discounts — order- and product-level discounts now travel as a structured
Discountobject (priority,typeFIXED/PERCENTAGE,value,net_price,discount_value,net_price_after_discount) inpayments.discounts,payments.totals[].discounts,orderLines[].price.unitPrice/totalPrice[].discountsandorderLines[].lineTotals[].discounts. - Granular taxes —
taxes[]now carries the BR tax-reform taxesIBS_UF,IBS_MUN,CBSalongsideICMS/PIS/COFINS, each with reformmetadata(cClassTrib,reducao,rateNominal,rateEffective) in addition tocst/cBenef. The breakdown is uniform across countries — LATAM carries its localIVAin the sametaxes[]shape; only SEFAZ emission (metadata.fiscal,fiscal.*.br) is BR-only. itemType— full enum documented:PRODUCT/COMBO/MODIFIER/PACKAGING, with the meaning of each.fulfillment.delivery.deliveryConfirmationCode— aggregator delivery/pickup confirmation code (e.g. iFood / Rappi).payments.shippingCost/extraCharges— documented as PriceBlock rows (same shape astotals[]).- store.business_day_closed —
salesnow includesproduct_discounts,gross_before_discounts,shipping,extra_charges,total_charged, andtaxes_by_type(per-tax breakdown with anOTHERreconciliation bucket). (Superseded 11 June — these aggregates are no longer embedded in the event; the day-close payload is now thin. See the entry at the top.) - order.cancelled / order.invoiced / order.reversed — carry the v1 order snapshot (they reference
order.completed/order.cancelled). - All of the above documented in EN / ES / PT with updated examples.
8 June 2026
- menu.updated:
productModifiers[n].overrides[]added — allows setting a different price for a specific modifier option when it belongs to a particular product. Each override targets oneproductIdand provides its ownpriceInfo.priceandpriceInfo.salePrice. EN/ES/PT updated.
5 June 2026
-
menus.sync: page removed — Fire sends a single
menu.updatedevent per menu; batch sync is no longer a separate event. -
menu.updated:
event.timezonefield removed from the payload.data.groupIdadded — a UUID that identifies the synchronization batch; multiple events emitted together share the same value, allowing downstream systems to correlate them. Category and productschedulesarrays now include full 7-day examples showing different time windows per category (e.g. Burgers 11:00–23:00, Breakfast 07:00–11:00).standardTimefield on products documented:trueinherits menu-level schedules,falsemeans the product has its ownschedulesarray. EN/ES/PT updated. -
Inject order:
typeis now required on everyorder.products[]item, everyselectedModifiers[]item, and everypayments.extraCharges[]item. Accepted values:COMBO(product with non-empty modifier groups),PRODUCT(simple sellable product or sellable modifier option),MODIFIER(pure modifier option),PACKAGING(packing-cost item). Payloads that omittypeare invalid. Request examples updated in EN/ES/PT. -
Inject order:
shippingMethod.delivery.additionalInfo.deliveryConfirmationCodedocumented as an optional string for delivery verification codes.
1 June 2026
- Inject order: new Amounts and price bands and Shipping and discounts sections; three reconciled request examples (simple delivery, line discount + shipping, multi-product + order discount); emphasis on
payments.shippingCost[],payments.discounts[], and productdiscountsValue(EN/ES/PT).
27 May 2026
- menus.sync: payload example completed (categories, products, modifier groups, schedules);
data.menus[]replaced withdata.menu(one menu per event); EN/ES/PT pages in webhook reference. - menu.updated: general structure aligned with
menus.sync— catalog fields (list,categories,products,modifierGroups,scheduledActivities) nested underdata.menu; field tables and delete example updated. - Menu publication guide (EN/ES/PT): examples and processing steps updated for
data.menu. - Inject order: optional
commentfield documented onorder.products[]; request example updated (replacesproductComment). - menu.updated / menus.sync: modifier option
productIdvalues must exist inproducts; example includesprod_size_smallandprod_size_large. - menu.updated: main payload example indentation fixed under
data.menu. - Menu webhooks (
menu.updated,menus.sync, product.updated):data.countrydocumented and exemplified as ISO 3166-1 alpha-2 (e.g.EC,BR,CO) instead of a numeric country ID.
26 May 2026
- Added User manuals as a top-level navigation tab.
- Added FIRE POS V2 manuals for Linking, Cashiers, and Authorization codes in English, Spanish, and Portuguese.
- Added subtle placeholder images for pending POS screenshots so the guides keep their final visual structure while captures are prepared.
- Inject order: removed
order.stockfrom the request body (not part of the contract). 200 response example updated to the real envelope (data,isArray,status,method,pathname,duration,traceId). - Login (playground):
authMethod: none, absolute staging URL in theapi:frontmatter, defaultContent-Typeand defaultgrant_typeto avoid Missing required fields when using Try it. - Inject order: product line
pricedocumented with full price band fields andtaxes[](name,rate,amount, optionalmetadata). - Inject order:
payments.shippingCost[]andpayments.discounts[]documented as the same price-band rows astotals[]; request example updated with sample shipping and discount lines. - Cancel order: API reference updated to the aggregator route
POST /api/v4/integrations/sales/aggregator/orders/{order_uid}/refund, with refund/cancellation request fields and standard response envelope; moved under Inject order in the API reference.
11 May 2026
- New Changelog tab (last in the nav) with this page.
- Removed the List sales channels page and its sidebar entry (all locales).
- API reference intro: copy adjusted; removed the sales channels card.
- Inject order: documented the
Authorizationheader (EN). ES & PT: path, headers, and body updated to the current aggregator contract (channel/service objects, device and operator fields, examples). - Login (ES & PT): aligned with
POST /api/authentication/loginand the client-credentials response (accessToken). - Spanish homepage (
/es/): content updated. - Configuration: new Aggregator integrations guide (Fire dashboard: webhook endpoints and test events).

