El ciclo
Compatibilidad hacia adelante: pueden aparecer estados nuevos del lado Xenda (por
ejemplo, etapas de logística). Tratá cualquier estado que no reconozcas como
informativo — nunca como error.
Reglas
- Aceptación implícita: mandar
listo,asignadooentregadosobre un pedidopendientelo acepta y lo mueve en un solo evento — no hace falta elaceptadoprevio. Queda auditado en el historial como aceptación implícita. - Transiciones válidas:
aceptado/rechazadosolo desdependiente;listodesdeen_preparacion;asignadodesdeen_preparacionolisto;entregadodesde cualquier estado en curso;canceladodesde cualquier estado previo al cierre. Una transición inválida devuelve400con el estado actual en el mensaje (invalid_transition: ... (current: entregado)) — útil si tu panel quedó desactualizado respecto del pedido. - Idempotencia: cada cambio de estado lleva
event_idúnico. Reintentar con el mismoevent_iddevuelveduplicate: truecon el estado vigente, sin re-aplicar. Un evento rechazado (por ejemplo, sinmotivo) no consume suevent_id: podés corregir el payload y reintentar con el mismo id, y esta vez se aplica. occurred_at: cuándo ocurrió la acción en tu sistema (el cajero aceptó a las 20:15 aunque el request salga 20:16).
Cómo distinguir los errores. Todos vienen con un
message legible; esto es lo que
significa cada código:400— el pedido o el payload no permiten esa acción: transición inválida (invalid_transition: ... (current: entregado)), falta un campo, o elmotivoes obligatorio. No reintentar igual: corregí y volvé a mandar (podés reusar el mismoevent_id).403con el mensaje empezando enrate_limited:— superaste el límite de requests por minuto de tu key. El mensaje incluye en cuántos segundos reintentar. Es temporal: reintentá, no es un problema de credenciales.403conInvalid API key— la key es incorrecta, fue revocada, o estás pegándole a un endpoint que no corresponde a su alcance.404— el pedido no existe o no pertenece a tu sucursal.
403 como “credenciales inválidas”, separá el caso del
rate limit por el prefijo del mensaje.Cierres que no salen de tu POS
Los estados los mueve tu POS, pero un pedido puede cerrarse sin que vos lo pidas:- El cliente lo cancela desde WhatsApp mientras está
pendiente. - El local lo cierra desde la plataforma Xenda: puede marcarlo
entregadoo cancelarlo. Es lo único que el local puede hacer ahí con una sucursal conectada a un POS; aceptar, rechazar y los pasos intermedios son siempre de tu sistema. - Un tiempo automático del local lo cierra, si el local lo activó (más abajo).
GET /v1/orders?status=cancelado (y entregado) además del de
pendiente, o tratar el 400 de invalid_transition como señal de que el pedido ya se
cerró y refrescar su estado. El mensaje trae el estado actual:
invalid_transition: ... (current: entregado).
El motivo le llega al cliente final
Cuando tu POS rechaza o cancela, el texto del motivo es el insumo con el que el
bot le explica al cliente por WhatsApp qué pasó. Escribilo pensando en esa persona:
Tiempos automáticos del local
Cada local puede activar dos tiempos automáticos desde su configuración en Xenda. Vienen apagados: una sucursal nueva no cancela ni cierra nada por su cuenta.
Si el local los activa, para tu POS significa:
- Un pedido puede desaparecer de
?status=pendienteentre un poll y el siguiente. Podés consultarlo con?status=canceladosi necesitás el detalle. - Un evento que llegue después del cierre (por ejemplo
asignadosobre un pedido que ya se cerró solo) recibe400coninvalid_transition. - Aceptar rápido es parte de la experiencia: mientras antes llegue tu
aceptado, antes recibe el cliente su confirmación.
En el sandbox los dos tiempos están apagados, para que puedas probar con calma. En
una sucursal real, si tu flujo no emite
entregado, conviene acordar con el local y con
Xenda cómo se cierran los pedidos antes de salir a producción.
