> ## Documentation Index
> Fetch the complete documentation index at: https://docs.fire.rest/llms.txt
> Use this file to discover all available pages before exploring further.

# Changelog

> Recent documentation and API reference updates.

<div style={{border: '1px solid rgb(128 128 128 / 0.25)', borderRadius: '0.75rem', padding: '1.25rem', marginBottom: '2.5rem'}}>
  <div style={{fontWeight: 600, fontSize: '1rem'}}>Subscribe to updates</div>
  <div style={{fontSize: '0.875rem', opacity: 0.8, marginTop: '0.25rem'}}>Get an email whenever a new entry lands here — new events, breaking changes and API reference updates. One click to unsubscribe.</div>
  <a href="https://buttondown.com/fire-docs" target="_blank" rel="noopener" style={{display: 'inline-block', marginTop: '0.875rem', padding: '0.5rem 1.25rem', borderRadius: '0.5rem', background: '#E6293D', color: '#fff', fontSize: '0.875rem', fontWeight: 600, textDecoration: 'none'}}>Subscribe</a>
</div>

## 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`, `serie` and `claveAcceso` are no longer fields of the block.
  The authority identifiers now live in **`countryData`**, in the vocabulary of the country
  that numbered: `claveAcceso`, `establecimiento`, `puntoEmision`, `secuencial` and `ambiente`
  in Ecuador; `numeroControl`, `numeroFactura` and `serie` in Venezuela. **Iterate the keys, do
  not index them**: a channel reading `countryData.claveAcceso` outright works in Ecuador and
  breaks with the first country added. The fields that mean the same everywhere
  —`documentNumber`, `issuedAt`, `authorizationMode`, `numberingStatus`— did not move.
* **`history`** and **`compensates`** — when a cancellation numbers, the credit note becomes
  the top document, `compensates` points at the invoice it voids, and the whole invoice moves
  down into `history`. Every `history` entry has **the same keys** as the block above, so they
  read the same.
* **`environment`** — which environment Fire numbered in: `SANDBOX` or `PRODUCTION`. It is
  ours, not the authority's; the authority's still travels inside `countryData` with its own
  code.
* **`providerCode`, `providerIdentity` and `providerMetadata`** — these used to be a single
  object mixing three things. `providerCode` is our adapter identifier; `providerIdentity` is
  the provider's block (`name`, `version`, `reference`) and **has a shape**; `providerMetadata`
  is 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.

<Note>
  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.
</Note>

Documented on [`order.opened`](/en/events/order-opened),
[`order.completed`](/en/events/order-completed),
[`order.cancelled`](/en/events/order-cancelled),
[`order.invoiced`](/en/events/order-invoiced),
[`order.reversed`](/en/events/order-reversed), in the
[endpoint reference](/en/api-reference/fiscal-documents) and in the
[Integrating fiscalization](/en/guides/fiscal-integration) 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
  as `null` when 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**:
  `numberingStatus` tells you how the attempt ended and `failure` why, when it did not end
  well — a charged sale left **with no fiscal receipt** arrives with `null` identifiers and
  the reason in `failure`. Carrying the block does **not** mean the document is authorized:
  the authority's verdict stays in `lastKnown.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. A `processing` seeded at injection used to be reported as
  `fiscal.callback` even though no callback had occurred; it now says `order.injected`.
  Account for the new value if you branch on this field.
* Documented on [`order.opened`](/en/events/order-opened),
  [`order.completed`](/en/events/order-completed),
  [`order.invoiced`](/en/events/order-invoiced) and
  [`order.cancelled`](/en/events/order-cancelled).

Updated in **EN / ES / PT**.

## 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. Returns `422` with `purchase_order_store_tax_id_ambiguous` if multiple active stores share the value (e.g. Ecuador RUC shared across branches) — use `store_id` or `external_store_id` in that case.

Combined with [Phase 17–18 ERP fields](/en/boh-api/procurement/orders-create), ERPs can now create purchase orders using only external identifiers — no internal UUIDs needed.

Updated in **EN / ES / PT**.

***

## 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](/en/boh-api/procurement#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](/en/manuals/kds/device-pairing)** — 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](/en/manuals/kds/operator-board)** — new guide. Supervisor list/detail with live timers, filters, collect codes, and cancel / ready / dispatch overrides.

**[Screen actions](/en/manuals/kds/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](/en/manuals/kds/waitlist)** — fulfillment filters (e.g. hide delivery from the turnero).

**[Overview](/en/manuals/kds/admin-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](/en/boh-api/introduction) reference now covers the full set of endpoints needed to build a complete integration:

**[Identity](/en/boh-api/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](/en/boh-api/catalog-sync)** — new section. Three bulk `PUT` endpoints:

* `PUT /catalog/units` — upsert units by `code + unit_group_code`; global units are skipped safely.
* `PUT /identity/suppliers` — upsert suppliers by `external_supplier_id`.
* `PUT /catalog/classifications/assignments` — replace all classification assignments for an item or store atomically.

**[Operations](/en/boh-api/operations)** — new section. Covers all inventory movement types:

* Goods receipts (create, list, get) — supports `external_store_id` and `external_supplier_id` so you don't need to pre-fetch UUIDs.
* Stock counts (create, list) — `FULL` or `PARTIAL` scope, with `area_breakdown` for 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`.

**[Procurement](/en/boh-api/procurement)** — new section. Full purchase-order lifecycle (`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 optional `service_codes` field:

* Lines without `service_codes` are **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.

Updated: [Recipes — Channel-scoped lines](/en/manuals/boh/recipes#channel-scoped-lines).

**Stock counts — collaborative field-count sessions**

New section documenting **field-count sessions**: multiple devices can count different inventory areas of the same store simultaneously. Each device claims an exclusive area, counts it, and marks it ready. The admin device finalizes the session, which creates a normal stock count.

Updated: [Stock counts — Collaborative counting sessions](/en/manuals/boh/stock-counts#collaborative-counting-sessions).

**Catalog — account currency**

New section documenting the **account currency** setting. Each BOH account now has a default ISO 4217 currency (set in Account & access → Account settings) used across procurement costs, supplier item prices, and reports.

Updated: [Catalog — Account currency](/en/manuals/boh/catalog#account-currency).

Updated in **EN / ES / PT**.

***

## 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](/en/manuals/backoffice/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.15` stay 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`, `.90` or 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.

<Note>
  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.
</Note>

***

## 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 is
[`POST /external/component-health`](/en/api-reference/component-health) and needs an API key
with the `component-health:write` scope.

* **[Component health](/en/api-reference/component-health)** — one beat per cycle with
  `componentType`, `componentId`, `storeId` and `status`. Optional `sentAt`, `offlineSince`,
  `degradedReason`, `appVersion` and a free-form `details`. Answers `204 No Content`.
* **`X-Heartbeat-Interval`** — every `204` carries the cadence in force, in seconds. Adopt it
  on the next cycle: that is how the interval is reconfigured without shipping a release.
* **A `componentId` must 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.
* **`degradedReason` uses a shared vocabulary** — `printer_down`, `pinpad_down`,
  `backend_unreachable`, `queue_backlog`, `peripheral_other`. The `details` keys for
  `kds_station` are still to be agreed with the KDS team.

<Note>
  `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.
</Note>

## 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].assignedAt`** and **`products[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 in [`menu.updated` → Menu assignment date](/en/webhook-reference/menu-updated-v2#menu-assignment-date). Not carried by [`product.price_updated`](/en/webhook-reference/product-price-updated) or [`product.availability_changed`](/en/webhook-reference/product-availability-changed) — they only ship their delta.
* **[`menu.updated`](/en/webhook-reference/menu-updated-v2) / [`product.updated`](/en/webhook-reference/product-updated) use `taxInfo`** (not `taxesInfo`), **`type: PRODUCTO`** for standard items, and **`modifierGroups[n].type: RADIO`** for single-select groups (`CHECKBOX` for multiple).
* **`storeId` is the store's internal UUID** (`stores.id`), not the `store_number` — same convention across `menu.updated`, `product.updated`, `product.price_updated`, and `product.availability_changed`.
* **`product.price_updated`'s `priceInfo` doesn't share a shape with the catalog `priceInfo`** in `menu.updated` / `product.updated` — it's the sale price just saved with its discount, not catalog pricing.

<Note>
  `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.
</Note>

Updated in **EN / ES / PT**.

## 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.

Updated in **EN / ES / PT**.

## 2 August 2026 — `order.opened` and the deferred-payment blocks

Each event advances on **its own version line** — there is no global contract number:

| Event                                           | Version                           |
| ----------------------------------------------- | --------------------------------- |
| [`order.opened`](/en/events/order-opened)       | **v1** (new event, first version) |
| [`order.completed`](/en/events/order-completed) | v1 → **v1.1**                     |
| [`order.invoiced`](/en/events/order-invoiced)   | v1 → **v1.1**                     |
| [`order.cancelled`](/en/events/order-cancelled) | v2 → **v2.1**                     |

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`](/en/events/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 as `order.completed`. It does **not** fire for orders
  injected as `COMPLETED` or `CANCELLED`. 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 be `null` or
  stale, and Fire itself ignores it and re-reads from source before issuing anything.

<Note>
  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.
</Note>

Updated in **EN / ES / PT**.

## 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](/en/manuals/boh/admin-overview)** — how catalog, recipes, procurement, movements, counts and reports fit together; the stock flow; map of the BOH menu.
* **[Stores and suppliers](/en/manuals/boh/stores-suppliers)** — BOH stores linked to Restaurant OS and supplier records with item-supplier links (price, purchase unit, SKU).
* **[Catalog](/en/manuals/boh/catalog)** — unit groups and units, items, interchangeable item tags (FIFO / FEFO / priority / highest stock), classifications.
* **[Recipes](/en/manuals/boh/recipes)** — sales, production and subrecipes; draft → published → archived lifecycle; channel-scoped lines; sale simulator.
* **[Procurement](/en/manuals/boh/procurement)** — receiving schedules, purchase order lifecycle, par levels and suggested orders.
* **[Receipts and returns](/en/manuals/boh/goods-receipts-returns)** — goods receipts (stock entry, PO linking, over-receiving) and supplier returns.
* **[Waste and internal consumption](/en/manuals/boh/waste-consumption)** — waste reasons catalog, waste events, internal consumption.
* **[Transfers and production](/en/manuals/boh/transfers-production)** — transfers between stores and production batches with yield.
* **[Stock counts](/en/manuals/boh/stock-counts)** — inventory areas, full/partial counts, and the mobile counting app.
* **[Reports](/en/manuals/boh/reports)** — usage, waste, production yield, and balance at a date.

All 10 pages published in **EN / ES / PT**.

***

## 13 July 2026 — Cancel Order: `cancellationType` field

Added optional `cancellationType` (`string`) to the [Cancel Order](/en/api-reference/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](/en/api-reference/orders#combo-discounts) section to the Inject Order reference.

When a `COMBO` 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 >= 0` and `total >= 0` after the discount
* The COMBO container must have all price fields at `0`
* `SUM(modifier.totalPrice.discountsValue)` must equal the combo's total discount

Includes a before/after JSON example (BRL 17.94 discount over a 7-item combo, base BRL 89.68) and a full breakdown table. Updated in **EN / ES / PT**.

## 29 June 2026 — KDS user manuals

Added a **KDS** section to the User manuals tab covering both operator and backoffice administration:

* **[Overview and concepts](/en/manuals/kds/admin-overview)** — 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](/en/manuals/kds/store-setup)** — apply a template (blueprint wizard) or configure from scratch; step-by-step order.
* **[Stations](/en/manuals/kds/stations)** — fields, optional station rules by channel / service / item type, step-by-step creation.
* **[Screens](/en/manuals/kds/screens)** — device identifier, create and assign stations, screen ↔ station relationship.
* **[Routing](/en/manuals/kds/routing)** — decision layers (routing → rules → distribution → convergence), distribution modes, multi-station example.
* **[Peripherals, printing and validation](/en/manuals/kds/peripherals-printing)** — keyboard layouts, ready-pickup printing (one screen per store), order cancellation, go-live checklist and reference routes.
* **[Screen actions](/en/manuals/kds/screen-actions)** — bump, hold/unhold, undo, cancel, pagination, settings menu and keyboard shortcuts.
* **[Order display](/en/manuals/kds/waitlist)** — customer-facing waitlist screen (preparing / ready areas, hero on ready, auto-pagination).

All 8 pages published in **EN / ES / PT**.

## 22 June 2026 — New guide: Products structure · Menu publication updated

### New guide: Products structure

New [Products structure](/en/guides/combo-products) page in the Guides tab — covers the `COMBO` type and modifier overrides:

* **COMBO type** — `priceInfo.price` is always `0`; use `priceInfo.referencePrice` as the product header price.
* **Reference price** — sum of (cheapest option × `minOptions`) across every required modifier group (`minOptions ≥ 1`).
* **Modifier overrides** — `productModifiers[n].overrides` sets a different price for an option inside a specific combo; takes precedence over the option's base price in `products[]`.
* **Delta pricing** — required groups show `+R$ X` above the baseline; optional groups show the full add-on price.

### Menu publication guide

* Removed the `menus.sync` section — that event no longer exists.
* Fixed the payload format: `event` is 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), and `modifierGroups`.

Updated in **EN / ES / PT**.

## 15 June 2026 — `order.completed` — new payment method fields

Added 4 fields to `payments.paymentMethods[n]` in the [`order.completed`](/en/events/order-completed) event. All fields are nullable and already live in production.

* **`idAuth`** (`string | null`) — Authorization ID from the payment processor (e.g. SiTef `IdAuth`). Distinct from `authorizationCode`.
* **`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.

Updated in **EN / ES / PT**.

## 15 June 2026 — Payment method details fields

Added 5 optional fields to `payments.paymentMethods[n]` in [Inject Order](/en/api-reference/orders):

* **`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). `acquirer` itself is now documented as nullable — send `null` for methods without an acquirer.
* **`card.media`** (`string`) — Card read method: `CHIP`, `MAGNETIC`, `NFC`, `MANUAL` (SiTef 2090 / Media). `card` is now documented as nullable — send `null` for non-card methods.

All fields are optional and already implemented in the validator. Updated in **EN / ES / PT**.

## 14 June 2026 — Aggregator order-status webhook

* **New inbound webhook [`POST /v1/webhooks/aggregators/order-status`](/en/api-reference/aggregator-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 onto `orders.aggregator` and 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/or** `externalOrderId` (your reference, matched on `metadata.order_id`); at least one is required, both vendor-scoped. If both are sent and resolve to **different** orders → `409`.
* **No Fire-emitted `eventId` to echo** — an aggregator status is a spontaneous external event (Fire is not the source of truth here). Idempotency is keyed on `(channelCode, providerEventId)` + `status`; `channelCode` must equal the order's `metadata.channel.code`.
* **Auth**: vendor-scoped API key with the new **`webhooks:aggregator`** scope. Async `202` + 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](/en/api-reference/orders) 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[]` with `paymentMethodCode: "AGGREGATOR_DISCOUNT"`, `transactionType: "BENEFIT"`, `processor` set to the aggregator name, and `card: 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](/en/api-reference/orders#aggregator-discounts) 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_closed`** and `order.status-updated` → **`order.status_updated`** (underscore nomenclature). Update your `event.type` switch.
* **[`store.business_day_closed`](/en/events/store-day-closed) is now a thin payload** — close identity (`businessDayId`, `businessDayDate`, `timezone`, `status`), timing (`openedAt`/`closedAt`), `closedBy`, and a **minimal `store`** (`uid`, `code`, `externalId`, `countryCode`, `timezone`, `currencyCode`). **Removed from the event**: `sales`, `metrics`, `summary`, `byChannel`, `byPaymentMethod`, `forceClosedOrders`, `closureStats`, `cancelledOrders`, `metadata` — query them by `businessDayId` when needed. **`snapshotId` renamed to `businessDayId`** (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 the `event.type` changes:

* **`fiscal.authorized.br` → [`order.invoiced`](/en/events/order-invoiced)** and **`fiscal.cancelled.br` → [`order.reversed`](/en/events/order-reversed)**. If your integration dispatches on `event.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](/en/api-reference/fiscal-callback). The country travels in `fiscal.countryCode`.
* **New event [`order.status_updated`](/en/events/order-status-updated)** — the KDS advances the order in the kitchen (`preparing` → `ready` → `dispatched`), with a `kitchen` block and the full journey in `history`.
* **Fire is the source of truth** — inbound webhooks ([fiscal callback](/en/api-reference/fiscal-callback), [KDS statuses](/en/api-reference/kds-order-status)) now **validate that `eventId` references an event Fire emitted for that order**; otherwise they respond `400` before the `202`. Always echo the `event.id` of 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 **`Discount`** object (`priority`, `type` `FIXED`/`PERCENTAGE`, `value`, `net_price`, `discount_value`, `net_price_after_discount`) in `payments.discounts`, `payments.totals[].discounts`, `orderLines[].price.unitPrice/totalPrice[].discounts` and `orderLines[].lineTotals[].discounts`.
* **Granular taxes** — `taxes[]` now carries the BR tax-reform taxes `IBS_UF`, `IBS_MUN`, `CBS` alongside `ICMS`/`PIS`/`COFINS`, each with reform `metadata` (`cClassTrib`, `reducao`, `rateNominal`, `rateEffective`) in addition to `cst`/`cBenef`. The breakdown is **uniform across countries** — LATAM carries its local `IVA` in the same `taxes[]` 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 as `totals[]`).
* **store.business\_day\_closed** — `sales` now includes `product_discounts`, `gross_before_discounts`, `shipping`, `extra_charges`, `total_charged`, and `taxes_by_type` (per-tax breakdown with an `OTHER` reconciliation 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 one `productId` and provides its own `priceInfo.price` and `priceInfo.salePrice`. EN/ES/PT updated.

## 5 June 2026

* **menus.sync**: page removed — Fire sends a single `menu.updated` event per menu; batch sync is no longer a separate event.

* **menu.updated**: `event.timezone` field removed from the payload. `data.groupId` added — a UUID that identifies the synchronization batch; multiple events emitted together share the same value, allowing downstream systems to correlate them. Category and product `schedules` arrays now include full 7-day examples showing different time windows per category (e.g. Burgers 11:00–23:00, Breakfast 07:00–11:00). `standardTime` field on products documented: `true` inherits menu-level schedules, `false` means the product has its own `schedules` array. EN/ES/PT updated.

* **Inject order**: `type` is now **required** on every `order.products[]` item, every `selectedModifiers[]` item, and every `payments.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 omit `type` are invalid. Request examples updated in EN/ES/PT.

* **Inject order**: `shippingMethod.delivery.additionalInfo.deliveryConfirmationCode` documented 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 product `discountsValue` (EN/ES/PT).

## 27 May 2026

* **menus.sync**: payload example completed (categories, products, modifier groups, schedules); `data.menus[]` replaced with `data.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 under `data.menu`; field tables and delete example updated.
* **Menu publication** guide (EN/ES/PT): examples and processing steps updated for `data.menu`.
* **Inject order**: optional `comment` field documented on `order.products[]`; request example updated (replaces `productComment`).
* **menu.updated** / **menus.sync**: modifier option `productId` values must exist in `products`; example includes `prod_size_small` and `prod_size_large`.
* **menu.updated**: main payload example indentation fixed under `data.menu`.
* **Menu webhooks** (`menu.updated`, `menus.sync`, **product.updated**): `data.country` documented 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.stock` from 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 the `api:` frontmatter, default `Content-Type` and default `grant_type` to avoid *Missing required fields* when using **Try it**.
* **Inject order**: product line `price` documented with full **price band** fields and `taxes[]` (`name`, `rate`, `amount`, optional `metadata`).
* **Inject order**: `payments.shippingCost[]` and `payments.discounts[]` documented as the same price-band rows as `totals[]`; 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 `Authorization` header (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/login` and the client-credentials response (`accessToken`).
* **Spanish homepage** (`/es/`): content updated.
* **Configuration**: new **Aggregator integrations** guide (Fire dashboard: webhook endpoints and test events).
