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

# order.status_updated

> El estado de cocina de una orden cambió — el KDS reportó preparing, ready, dispatched o cancelled.

<Note>
  Evento nuevo (junio 2026). Nace directamente en **v1** — no existe forma v0.
</Note>

`order.status_updated` dispara cuando el **KDS** (Kitchen Display System) reporta un cambio de estado en cocina: empezó a prepararse (`preparing`), está lista (`ready`), fue despachada (`dispatched`) o fue cancelada en cocina (`cancelled`).

Para los tres estados de avance, Fire aplica un **gate anti-regresión** (un estado nunca retrocede: `dispatched` no vuelve a `ready`) y solo emite este evento cuando el estado genuinamente avanza. `cancelled` es la excepción — bypasea el gate y puede llegar desde cualquier estado de cocina. Por eso recibes **un evento por cambio real**, sin duplicados ni retrocesos.

## Condición de disparo

Fire emite `order.status_updated` cuando se cumple **cualquiera** de las siguientes condiciones:

* El KDS reportó un estado de **avance** (`preparing`, `ready` o `dispatched`) que pasa el gate anti-regresión (`preparing` → `ready` → `dispatched`)
* El KDS reportó `cancelled` para la orden (sin restricción anti-regresión — puede llegar desde cualquier estado de cocina)

En ambos casos, el reporte debe referenciar un evento que Fire emitió para esa orden (validación de origen).

|                        |                                                                                         |
| ---------------------- | --------------------------------------------------------------------------------------- |
| Cobertura              | **Todos los países**                                                                    |
| Estados                | `preparing` → `ready` → `dispatched` (monotónico); `cancelled` (desde cualquier estado) |
| Llave de idempotencia  | `event.id`                                                                              |
| Dispara más de una vez | Una vez por cambio de estado (máx. 4 por orden); reintentos comparten `event.id`        |
| Origen del dato        | `kitchen.source` — solo `kds` hoy; el campo queda abierto a futuras fuentes             |

## Qué hay en `data`

Es un **payload liviano (thin)** — a diferencia de `order.completed`, **no** arrastra la orden completa. Lleva lo necesario para actuar sobre un cambio de estado: la **identidad** de la orden, refs mínimas de **canal / tienda**, el **tipo de fulfillment**, y el bloque **`kitchen`** (el avance + el recorrido). A propósito omite `orderLines`, `payments`, `taxes`, `client`, `device` y la dirección de delivery — eso ya lo recibiste en [`order.completed`](/es/events/order-completed); matcheá por `orderId` / `externalOrderId` y aplicá el cambio.

```json theme={null}
{
  "event": {
    "id": "7f3c2a1b-9d4e-4f6a-8b2c-1e5d3a7f9c0b",
    "type": "order.status_updated",
    "createdAt": "2026-06-10T18:24:31.000Z"
  },
  "data": {
    "orderId": "443bb714-fb69-4538-9ecb-de0acad7b88f",
    "orderCode": "OC-br-001",
    "externalOrderId": "f3bf9fa1-baa8-4050-9e37-4e6d905ee308",
    "businessDayDate": "2026-05-25",
    "status": "COMPLETED",
    "channel": { "code": "99", "uid": "6bac8d41-..." },
    "store": {
      "code": "BR-SP-001",
      "name": "Lab Store BR",
      "account": { "uid": "100", "name": "Sandbox" },
      "vendor":  { "uid": "100.2.1", "name": "Deli Burger BR" }
    },
    "fulfillment": { "service": { "code": "DELIVERY" } },
    "kitchen": {
      "status": "ready",
      "previousStatus": "preparing",
      "rank": 2,
      "occurredAt": "2026-06-10T18:24:29.000Z",
      "stationName": "Cocina caliente",
      "providerEventId": "kds-evt-8842",
      "kdsEventLogId": "1a2b3c4d-...",
      "source": "kds",
      "history": [
        { "status": "preparing", "rank": 1, "occurredAt": "2026-06-10T18:12:02.000Z", "stationName": "Cocina caliente" },
        { "status": "ready",     "rank": 2, "occurredAt": "2026-06-10T18:24:29.000Z", "stationName": "Cocina caliente" }
      ]
    }
  }
}
```

### Identidad y contexto

<ResponseField name="orderId" type="string">UUID de la orden en Fire — matcheá contra el `order.completed` que recibiste.</ResponseField>
<ResponseField name="orderCode" type="string">Código legible de la orden.</ResponseField>
<ResponseField name="externalOrderId" type="string">El id de la orden **en el canal/agregador** — usalo para matchear de su lado.</ResponseField>
<ResponseField name="status" type="string">Estado de negocio de la orden (`COMPLETED` / `CANCELLED`). Contexto — el recorrido de cocina es paralelo.</ResponseField>

<ResponseField name="channel" type="object">
  `code` (canónico, siempre presente — ej. `99`) y `uid`. El nombre legible del canal sale de tu catálogo de channels, no de este evento.
</ResponseField>

<ResponseField name="store" type="object">
  Ref mínima de tienda: `code`, `name`, más `account { uid, name }` y `vendor { uid, name }`.
</ResponseField>

<ResponseField name="fulfillment" type="object">
  `service.code` — `DELIVERY` o `PICKUP`. Le da sentido al status (un `ready` para delivery vs pickup).
</ResponseField>

### El bloque `kitchen`

<ResponseField name="kitchen" type="object">
  El avance que disparó el evento + el recorrido completo. Distinto del bloque `kds` (datos estáticos de la orden capturados al inyectarse).

  <Expandable title="kitchen">
    <ResponseField name="status" type="string">
      Estado que disparó el evento: `preparing` | `ready` | `dispatched` | `cancelled`.
    </ResponseField>

    <ResponseField name="previousStatus" type="string | null">
      Estado anterior. `null` en el primer avance.
    </ResponseField>

    <ResponseField name="rank" type="number">
      Secuencia del recorrido: `preparing`=1 \< `ready`=2 \< `dispatched`=3. **Los webhooks no llegan ordenados** — usá esto para detectar eventos viejos/desordenados (ignorá un `rank` menor al último que aplicaste).
    </ResponseField>

    <ResponseField name="occurredAt" type="string">
      ISO 8601 — cuándo ocurrió en el KDS (reloj del cliente).
    </ResponseField>

    <ResponseField name="stationName" type="string | null">
      Estación que reportó, si el KDS la envía.
    </ResponseField>

    <ResponseField name="providerEventId" type="string">
      Llave de dedup del reporte entrante del KDS.
    </ResponseField>

    <ResponseField name="kdsEventLogId" type="string">
      El id del recibo de Fire para el evento KDS entrante (cross-audit).
    </ResponseField>

    <ResponseField name="source" type="string">
      Quién reportó. Solo `kds` hoy.
    </ResponseField>

    <ResponseField name="history" type="array">
      Recorrido completo hasta ahora — una entrada por hito (`status`, `rank`, `occurredAt`, `stationName`), ordenado por rank. Te permite reconstruir todo el camino desde un solo evento y reconciliar si llegan desordenados.
    </ResponseField>
  </Expandable>
</ResponseField>

## Casos de uso típicos

* **Tracking de orden para el cliente** — "tu pedido está listo" o "tu pedido fue cancelado" en app o pantalla de retiro
* **Notificar al agregador** — avisar a iFood/Rappi/99food que la orden está lista para el repartidor o que fue cancelada en cocina
* **Métricas de cocina** — tiempos preparing→ready por tienda/estación a partir de `history`
* **Flujo de cancelación** — disparar limpieza downstream (liberar repartidor, reembolso, alerta a ops) cuando `kitchen.status = "cancelled"`

## Lo que NO hace

* **No cambia el estado de la orden** — excepto en la cancelación. Para los estados de avance (`preparing`, `ready`, `dispatched`), `data.status` sigue siendo `"COMPLETED"`. Cuando `kitchen.status = "cancelled"`, `data.status` será `"CANCELLED"`.
* **No retrocede** para estados de avance. Si el KDS reporta `ready` después de `dispatched`, Fire lo descarta (gate anti-regresión) y no emite nada. `cancelled` está exento de esta regla.
* **No reemplaza a `order.completed`.** Suscríbete a ambos: `order.completed` para el hecho de negocio, `order.status_updated` para el progreso físico.
