En lugar de consultar el estado en bucle, registra tu URL y suscribe las guías que te interesan. Cuando el estado cambia, la plataforma envía un POST JSON firmado con HMAC-SHA256 (formato tipo Stripe), con reintentos automáticos y deduplicación por ID de evento. Recibes cada hito del envío: despacho, llegada a la agencia destino, salida a reparto y entrega. Tu endpoint solo tiene que validar la firma y responder 200.
Qué resuelve un webhook
La alternativa es preguntar cada pocos segundos por cada guía. Un webhook invierte eso: registras tu URL una vez, suscribes las guías que te interesan y recibes un POST cuando algo cambia de verdad.
Es la diferencia entre enterarte de una entrega en el momento y enterarte la próxima vez que alguien consulte.
Qué estados recibes
Cada evento tracking.status_changed trae el estado tal cual lo informa Shalom en status (por ejemplo "Registrado", "En origen", "En tránsito", "En destino", "Demora de envíos" o "Entregado") y su equivalente normalizado en statusCode (UNKNOWN, REGISTERED, EN_ORIGIN, IN_TRANSIT, AT_DESTINATION, OUT_FOR_DELIVERY, DELIVERED). El estado anterior viaja en previousStatus y previousStatusCode.
statusCode es el que conviene usar para decidir flujos: status es el texto del espejo y puede cambiar de redacción si Shalom la ajusta. El payload suma statusAt (fecha del hito en ISO UTC), delayed y delayAt (si Shalom reporta demora) y mirrorMessage, que repite el texto del espejo por compatibilidad.
Una guía recién creada avisa hasta tres veces antes de moverse: Registrado (REGISTERED) → En origen (EN_ORIGIN) → En tránsito (IN_TRANSIT). Mientras se mueve se consulta cada 30 minutos; sin cambios, cada 2 horas, y esperando recojo en destino, cada 3 horas hasta que la entregan. Entre las 22:00 y las 06:00 (hora de Lima) no se consulta: un cambio de la noche se avisa desde las 06:00. Una guía con 20 días sin movimiento, o devuelta o anulada, deja de vigilarse; vuelve a suscribirla para reactivarla. Más detalle en el tema Optimizaciones del tracking.
Estados que informa Shalom
El espejo de Shalom publica estos textos (campo statuses.message); la API los replica tal cual y agrega el código normalizado. Es la lista completa de estados que puede recibir tu integración.
Registrado → statusCode REGISTERED: la guía existe en el sistema pero todavía no fue recepcionada en la agencia de origen.
En origen → statusCode EN_ORIGIN: recepcionada en la agencia de origen (Shalom la muestra como "Tu envío ha sido recepcionado").
En tránsito → statusCode IN_TRANSIT: despachada hacia la agencia destino.
En destino → statusCode AT_DESTINATION: llegó a la agencia destino y está lista para recojo.
Demora de envíos → el statusCode no cambia: es un aviso (delayed en true, con delayAt) y el hito real sigue siendo el último alcanzado.
Entregado → statusCode DELIVERED: entregada al destinatario.
Demora de envíos es el único caso donde status y el hito no coinciden: Shalom mantiene ese título incluso después de entregar la guía, así que la entrega se informa igual con statusCode DELIVERED (y delayed en true). Si Shalom no encuentra la orden, status llega en null y statusCode mantiene el último hito conocido.
Verifica siempre la firma
PUT /webhooks devuelve un secreto con el que se firma cada envío. Comprueba esa firma antes de procesar nada: sin eso, cualquiera que conozca tu URL puede inyectarte eventos falsos.
Si el secreto se filtró, vuelve a llamar a PUT /webhooks con rotateSecret en true y actualiza tu verificación.
Suscribir guías una por una
POST /tracking/subscriptions se hace por guía, con su orderNumber y su orderCode. Si tu tienda registra muchos envíos, suscribe justo después de crear cada guía, en el mismo flujo.
Responde rápido y de forma idempotente
Contesta con un 2xx en cuanto recibas y procesa el evento después. Si tu endpoint tarda o falla, el sistema reintenta, así que guarda un identificador del evento para no aplicar dos veces el mismo cambio de estado.
Cuándo seguir usando polling
Si solo necesitas el estado cuando el cliente abre la pantalla de seguimiento, una consulta puntual por API es más simple que montar un endpoint público. El webhook tiene sentido cuando algo tiene que pasar sin que nadie esté mirando.