Saltar al contenido principal
POST
/
api
/
v1
/
webhooks
/
kds
/
order-status
Estado de orden KDS
curl --request POST \
  --url https://app.fire.rest/api/v1/webhooks/kds/order-status \
  --header 'Content-Type: application/json' \
  --header 'x-api-key: <x-api-key>' \
  --data '
{
  "eventType": "<string>",
  "providerEventId": "<string>",
  "occurredAt": "<string>",
  "orderId": "<string>",
  "eventId": "<string>",
  "stationName": "<string>",
  "metadata": {}
}
'
{
  "received": true,
  "duplicate": false,
  "eventId": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
  "webhookEventId": "9e6c8af8-af80-4967-9422-c096ab43c0e7",
  "status": "queued",
  "firstReceivedAt": "2026-05-26T18:30:00.512Z",
  "message": "Event accepted and queued for processing."
}
Este endpoint es entrante — tu Sistema de Pantallas de Cocina (KDS) le hace POST cada vez que una orden avanza en la cocina: la cocina empezó a prepararla, quedó lista para entrega, o fue despachada (entregada / retirada). Fire autentica la solicitud, la correlaciona con la orden, aplica idempotencia y una compuerta anti-regresión, y registra el evento en su log de eventos KDS para observabilidad.
Este endpoint es asíncrono. Fire autentica, corre el guard de source-of-truth + tenancy, deduplica y encola el evento — luego responde 202 Accepted con un webhookEventId (típicamente en menos de 100 ms). El evento se registra un instante después en un worker en segundo plano (normalmente en ~2 segundos). Para verificar el resultado, consultá GET /v1/webhooks/events/{webhookEventId}. Los problemas corregibles por el cliente (payload inválido, eventId equivocado, tenant equivocado) se rechazan síncronamente con 4xx antes del 202.
Un evento de dispatch, varios reportes de estado. A diferencia del callback fiscal — donde cada acción lleva su propio eventId — el KDS reporta todo el recorrido (preparingreadydispatched) contra un eventId: el que Fire emitió al despachar la orden a tu device. Se distinguen por eventType, no por eventId. Ver Idempotencia y el recorrido.

Tipos de evento

El ciclo de vida del KDS tiene un orden estricto — una orden se prepara antes de estar lista, y está lista antes de ser despachada:
eventTypeSignificadoRank
order.preparingLa cocina comenzó a preparar la orden1
order.readyLa orden está preparada y lista para entrega / retiro2
order.dispatchedLa orden salió de la cocina (entregada o retirada) — terminal3
Los valores son minúscula, con punto (order.preparing, no ORDER_PREPARING).

Autenticación

Este endpoint requiere una API key vendor-scoped con el scope webhooks:kds (binding de cuenta + vendor). Fire valida que la orden pertenezca a esa cuenta y vendor. Las keys sin el scope, o sin binding de vendor, se rechazan con 403 Forbidden.
x-api-key
string
requerido
Tu API key vendor-scoped de Fire con scope webhooks:kds. Generá una desde Developers → Gestión de API para la cuenta/vendor cuyas órdenes reportará esta key.
Authorization
string
Bearer <token> opcional — aceptado como alternativa legacy a x-api-key. Enviá uno u otro.

Cuerpo de la solicitud

eventType
string
requerido
El evento de ciclo de vida del KDS. order.preparing, order.ready u order.dispatched (minúscula, con punto).
providerEventId
string
requerido
El id propio de tu KDS para esta entrega. Se guarda para auditoría/forense — no es la llave de idempotencia. Fire deduplica por (orderId, eventId, eventType), así que podés enviar un providerEventId nuevo en cada reintento. Usá el id de evento nativo de tu KDS si lo tenés; si no, un UUID.
occurredAt
string
requerido
Timestamp ISO 8601 UTC de cuándo ocurrió el evento en el KDS — no cuándo se envió.
orderId
string
requerido
UUID de la orden en Fire. Coincide con data.orderId de los eventos de orden. Fire correlaciona el evento con esta orden; debe existir previamente.
eventId
string
requerido
UUID de correlación — el event.id del envelope que Fire emitió al despachar la orden a tu device. Ecoalo exacto; nunca lo inventes.
  • Chequeo de fuente de verdad. Un eventId que no referencie un evento de Fire para esa orden se rechaza con 400 antes del 202.
  • Un eventId para todo el recorrido. Enviá el mismo eventId para preparing, ready y dispatched de ese dispatch — se distinguen por eventType. (Cada dispatch a un device distinto lleva su propio eventId, así que dos devices nunca colisionan.)
stationName
string
Estación del KDS de origen, opcional (ej. Cocina caliente, Despacho 1). Se guarda para observabilidad.
metadata
object
Bolsa libre opcional de campos extra. Se guarda tal cual, sin validar.

Ejemplos

Los tres reportes del mismo dispatch comparten un eventId (el del dispatch) y difieren solo en eventType y providerEventId:
order.preparing
{
  "eventType": "order.preparing",
  "providerEventId": "evt_2026-05-26_000122",
  "occurredAt": "2026-05-26T18:28:00.000Z",
  "orderId": "9f1c0e8a-1234-4abc-9def-0123456789ab",
  "eventId": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
  "stationName": "Cocina caliente"
}
order.ready
{
  "eventType": "order.ready",
  "providerEventId": "evt_2026-05-26_000123",
  "occurredAt": "2026-05-26T18:30:00.000Z",
  "orderId": "9f1c0e8a-1234-4abc-9def-0123456789ab",
  "eventId": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
  "stationName": "Cocina caliente"
}
order.dispatched
{
  "eventType": "order.dispatched",
  "providerEventId": "evt_2026-05-26_000124",
  "occurredAt": "2026-05-26T18:42:11.000Z",
  "orderId": "9f1c0e8a-1234-4abc-9def-0123456789ab",
  "eventId": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
  "stationName": "Cocina caliente"
}

Respuesta

En éxito el endpoint responde 202 Accepted — el evento fue autenticado, validado, deduplicado y encolado. Un 202 no significa que el evento ya se registró; eso ocurre de forma asíncrona. Usá el endpoint de estado para confirmar. El body trae dos ids distintos: eventId es el id que vos enviaste (echo), webhookEventId es el id de Fire para el registro encolado. Misma forma que el callback fiscal.
received
boolean
Siempre true cuando la solicitud fue aceptada y encolada.
duplicate
boolean
true cuando esta tripla exacta (orderId, eventId, eventType) ya se ingresó — se devuelve el registro existente y no se re-encola nada. false para un reporte nuevo (incluido un eventType distinto del mismo dispatch — eso es un paso nuevo, no un duplicado).
eventId
string
Echo del eventId que enviaste (el event.id del dispatch).
webhookEventId
string
El id de Fire para el registro encolado. Pasalo a GET /v1/webhooks/events/{webhookEventId} para consultar el resultado. En un duplicado es el mismo id que se devolvió la primera vez.
status
string
Estado actual en la cola — queuedprocessingprocessed (y retry / failed / dead / ignored).
firstReceivedAt
string
Timestamp ISO 8601 UTC de cuándo Fire recibió por primera vez este reporte. Estable entre reintentos.
message
string
Resumen legible.
{
  "received": true,
  "duplicate": false,
  "eventId": "7c9e6679-7425-40de-944b-e07fc1f90ae7",
  "webhookEventId": "9e6c8af8-af80-4967-9422-c096ab43c0e7",
  "status": "queued",
  "firstReceivedAt": "2026-05-26T18:30:00.512Z",
  "message": "Event accepted and queued for processing."
}

Verificar el resultado

Como el procesamiento es asíncrono, el 202 solo confirma que el evento fue encolado. Para ver si se registró, consultá el endpoint de estado con el webhookEventId que devolvió el 202:
GET https://app.fire.rest/api/v1/webhooks/events/{webhookEventId}
x-api-key: <tu key webhooks:kds>
status
string
Ciclo de vida de la cola: queuedprocessingprocessed (listo) · failed / dead (se rindió tras reintentos) · retry (esperando el próximo intento) · ignored (manejado, sin acción — ej. un duplicado o un evento no-avanzante).
attempts
number
Intentos de procesamiento hasta ahora.
result
object | null
En éxito, el resultado del worker — ej. { "kind": "recorded" } (avanzó la orden) o { "kind": "ignored" } (no-avanzante).
error
object | null
{ "message": "…" } cuando el último intento falló; null si no.
Se devuelve 404 para ids desconocidos — o ids de otro tenant — sin filtrar existencia. Autenticá con la misma key webhooks:kds que usaste para el evento.

Idempotencia y el recorrido

Fire deduplica por la tripla (orderId, eventId, eventType)no por providerEventId (que podés regenerar libremente). Esto es lo que hace funcionar el recorrido:
EscenarioResultado
preparing, luego ready, luego dispatchedmismo eventId, distinto eventTypecada uno es un paso nuevo202 duplicate:false. El mismo eventId es esperado, no un conflicto
El mismo reporte reenviado — misma (orderId, eventId, eventType)202 duplicate:true — registro existente devuelto, no reprocesado
eventId no emitido por Fire para ese orderId400
Orden/evento fuera de la cuenta + vendor de tu API key403
Auth store momentáneamente inalcanzable503 — transitorio, reintentá
Esta es la diferencia clave con el callback fiscal. Allá, un eventId lleva exactamente una acción, así que reusarlo para otro eventType es un conflicto (409). Acá, un eventId de dispatch lleva legítimamente todo el recorrido (preparingreadydispatched) — el eventType es lo que distingue los pasos. Devices distintos reciben eventIds de dispatch distintos, así que sus reportes nunca colisionan.

Anti-regresión

El estado de la orden nunca debe retroceder. Fire rastrea la etapa máxima alcanzada por la orden (order.dispatched > order.ready > order.preparing) y compara cada evento entrante contra ella:
  • Un evento que avanza la orden (ej. order.ready después de order.preparing) se registra como el nuevo estado.
  • Un evento que no avanza — una regresión (ej. order.preparing que llega después de order.ready) o una repetición del mismo estado — igual se registra para observabilidad, pero marcado como no-avanzante con un motivo, y no retrocede la orden.
Esto hace el endpoint seguro ante entregas fuera de orden o tardías: enviá los eventos en cualquier orden y Fire mantiene la orden en su etapa más avanzada.

Relacionado

Inyectar orden

El endpoint de inyección que crea la orden que referencia este evento.

Callback fiscal

El webhook entrante hermano — mismo modelo async + idempotencia + correlación.

Autenticación

Cómo funcionan las API keys, scopes y el binding de partner y vendor.