Reciba eventos en tiempo real de Superroute — pedidos, cambios de estado, actualizaciones de seguimiento. Con cargas firmadas, reintentos automáticos y depurador integrado.
Un webhook es una solicitud HTTP POST que Superroute envía a una URL configurada por usted cada vez que ocurre algo — se crea un pedido, se completa una entrega, se registra un evento de seguimiento. Usted construye un endpoint receptor; nosotros le entregamos el evento.
Cómo funciona la entrega
Los eventos se ponen en cola y se envían de forma asíncrona. Cada solicitud lleva una firma HMAC-SHA256 para que pueda verificar su origen. Las entregas fallidas (no 2xx o tiempo de espera) se reintentan con retroceso exponencial hasta 5 veces.
Modelo de seguridad
Usted configura un secreto compartido en la página de ajustes. Cada webhook saliente se firma con ese secreto. Su receptor recalcula la firma y la compara — si coinciden, la carga es genuina y no ha sido alterada.
Catálogo de Eventos
Hay ocho tipos de eventos salientes disponibles. Cada uno tiene su propio campo URL en la página de ajustes — puede suscribirse a cualquier subconjunto.
pedido.creado
Se dispara cuando se crea un pedido de entrega local (Delivery / Pickup / P2P) por cualquier vía: formulario web, API REST/GraphQL, sincronización con plataforma de e-commerce, reglas automáticas, filas importadas, etc. Excluye los pedidos label-service y otros tipos que no son de entrega. Se omite en el flujo por lotes cuando el mismo destinatario tiene también order_create_async_postback_url configurado. Configure con order_create_webhook_url.
Se dispara en cada transición de estado del pedido — recogido, en tránsito, entregado, excepción, cancelado. Configure con order_status_change_webhook_url.
Se dispara en cada evento del ciclo de vida del seguimiento de un paquete (información enviada, inicio de entrega, entrega exitosa, no entregado, etc.). Configure con tracking_event_webhook_url. Los eventos de entrega y de recogida también incluyen la prueba de entrega: proof_files y proof_files_detail (file_id, type, url, full_url, URL de descarga firmada). Las fotos subidas después del evento llegan como pod.files_updated. Cada archivo incluye además el contexto de su evento: tracking_event_id, tracking_event_status_id, tracking_event_key, service_type (1 = delivery / 2 = pickup) y service_status (1 = success / 2 = failed); en archivos antiguos sin evento registrado son null.
Ejemplos de Carga
{
"id": 90001,
"order_id": 1001,
"order_ref": "REF-001",
"location_id": 12,
"location_name": "Toronto Depot",
"tracking_event_type": "D",
"tracking_event_status_id": 500,
"tracking_event_key": "deliver_success",
"otep_status": "delivered",
"proof_files": [
"storage/2026-07-20/1001_S_Ab3kQ9xYzLm4Np.jpeg",
"storage/2026-07-20/1001_P_Cd7rT2wVuKe8Hs.jpeg"
],
"proof_files_detail": [
{
"file_id": 234567,
"type": 1,
"url": "storage/2026-07-20/1001_S_Ab3kQ9xYzLm4Np.jpeg",
"full_url": "https://api.superroute.ca/storage/2026-07-20/1001_S_Ab3kQ9xYzLm4Np.jpeg",
"signed_url": "https://api.superroute.ca/files/pod/234567?expires=1784748600&signature=8f2c1d...",
"signed_url_expires_at": 1784748600,
"tracking_event_id": 90001,
"tracking_event_status_id": 500,
"tracking_event_key": "deliver_success",
"service_type": 1,
"service_status": 1
},
{
"file_id": 234568,
"type": 2,
"url": "storage/2026-07-20/1001_P_Cd7rT2wVuKe8Hs.jpeg",
"full_url": "https://api.superroute.ca/storage/2026-07-20/1001_P_Cd7rT2wVuKe8Hs.jpeg",
"signed_url": "https://api.superroute.ca/files/pod/234568?expires=1784748600&signature=41ba90...",
"signed_url_expires_at": 1784748600,
"tracking_event_id": 90001,
"tracking_event_status_id": 500,
"tracking_event_key": "deliver_success",
"service_type": 1,
"service_status": 1
}
],
"description": {
"en": "Your parcel has been delivered successfully. Thank you!",
"fr": "Votre colis a été livré avec succès. Merci !",
"chs": "您的包裹已成功送达,感谢您的使用!",
"cht": "您的包裹已成功送達,感謝您的使用!",
"es": "Tu paquete ha sido entregado con éxito. ¡Gracias!",
"de": "Ihr Paket wurde erfolgreich zugestellt. Vielen Dank!",
"nl": "Uw pakket is succesvol afgeleverd, bedankt voor uw gebruik!",
"pt": "Seu pacote foi entregue com sucesso. Obrigado!",
"it": "Il tuo pacco è stato consegnato con successo. Grazie!",
"sr": "Vaš paket je uspešno dostavljen, hvala vam što koristite naše usluge!",
"hu": "Csomagja sikeresen kiszállításra került, köszönjük hogy használta szolgáltatásunkat!",
"pl": "Twoja paczka została dostarczona pomyślnie. Dziękujemy!",
"sk": "Váš balík bol úspešne doručený. Ďakujeme!",
"cs": "Váš balík byl úspěšně doručen. Děkujeme!"
},
"tracking_number": [
"SR000000001"
],
"external_tracking_number": [
"1Z999AA10123456784"
]
}
orden.create_async
Se dispara una vez tras finalizar una importación masiva de pedidos. La carga contiene el array de resultados por fila. Configure con order_create_async_postback_url.
Se dispara cuando una foto de entrega o firma se añade, se reemplaza o se elimina (action: added / updated / removed) — un envío por archivo, sin más sondeo de adjuntos. Se activa configurando pod_files_webhook_url. Cada archivo incluye además el contexto de su evento: tracking_event_id, tracking_event_status_id, tracking_event_key, service_type (1 = delivery / 2 = pickup) y service_status (1 = success / 2 = failed); en archivos antiguos sin evento registrado son null.
Se dispara cuando un pedido se elimina permanentemente, para que su sistema pueda reflejar la eliminación. Se activa configurando order_deleted_webhook_url.
Se dispara cuando un intento de cancelación es rechazado (por ejemplo, el pedido ya está en reparto), para que su equipo de operaciones pueda supervisar las cancelaciones fallidas sin consultar la API. Se activa configurando order_cancel_failed_webhook_url.
Ejemplos de Carga
{
"result": false,
"code": "ORDER_ALREADY_IN_DELIVERY",
"message": "Order can no longer be cancelled at its current status",
"http_status": 409,
"submitted": {
"order_id": 1001,
"tracking_number": "SR000000001",
"external_tracking_number": null
}
}
Asiento del tablero de rutas cambiado
Se dispara cuando un asiento del tablero de rutas cambia de manos o el tablero cambia de estado — el campo action indica qué ocurrió (claimed, standby, pooled, promoted, withdrawn, vetoed, replaced, assigned, awarded, lost, displaced, settled, board_opened, board_closed, board_cancelled). Solo a nivel de empresa. Suscripción mediante route_board_webhook_url.
Un canal de webhooks independiente para proveedors de entrega externos integrados con taquillas inteligentes. Los eventos se entregan al endpoint configurado para su cuenta de proveedor, y cada endpoint puede suscribirse a cualquier subconjunto de tipos de evento.
partner_locker.delivery.doors_opened
Puertas Abiertas — Se dispara en el momento en que se abren las puertas de los casilleros para un intento de entrega — tanto si el repartidor usó la pantalla del casillero con el código de acceso como la API de apertura remota — incluidas las reaperturas por reasignación. El bloque opening lista cada compartimento abierto con su grid_id, el número de puerta de hardware compartment_number y el pickup_locker_number (número secuencial de visualización contado de arriba abajo por columna y luego de izquierda a derecha). Cada compartimento incluye además pickup_locker_code: la etiqueta "{shelf_code}-{pickup_locker_number}" a la que se envía al destinatario; null cuando el compartimento no tiene número de recogida. La carga útil también incluye pickup_code: el código de recogida del destinatario, asignado en el momento en que se abren las puertas; sigue siendo el mismo código después de que el repartidor confirme el depósito, y solo puede usarse para recoger una vez confirmado el depósito.
Entregado en la taquilla — Se dispara cuando se confirma un depósito y los paquetes están en la taquilla. La carga incluye el código de recogida del destinatario. Cada compartimento incluye además pickup_locker_code: la etiqueta "{shelf_code}-{pickup_locker_number}" a la que se envía al destinatario; null cuando el compartimento no tiene número de recogida. Para puertas abiertas mediante la API de apertura remota, la plataforma liquida el depósito en cuanto la taquilla informa de que todas las puertas abiertas están cerradas, por lo que este evento se dispara sin llamada a confirm; confirmed_by indica la vía de liquidación: courier_terminal, partner_api, door_close, timeout_door_closed o console.
Reapertura de corrección — Se dispara cuando los compartimentos ocupados se reabren dentro de la ventana de corrección para corregir una colocación errónea — desde la pantalla de la taquilla o mediante la API. El bloque correction enumera los compartimentos reabiertos. Cada compartimento incluye además pickup_locker_code: la etiqueta "{shelf_code}-{pickup_locker_number}" a la que se envía al destinatario; null cuando el compartimento no tiene número de recogida.
partner_locker_delivery.event_type_code_rotated — Se dispara cuando el socio renueva el código de entrega o el código de recogida de una entrega. El bloque rotation indica qué código se sustituyó, cuándo y si se reenvió la notificación al destinatario; el código nuevo nunca viaja en un webhook, solo se revela en la respuesta directa de la API de renovación.
Firma y Verificación: Los webhooks de taquillas de proveedors usan su propio esquema de firma: X-Webhook-Signature es base64(HMAC-SHA256(secreto, marca de tiempo + "\n" + id de entrega + "\n" + cuerpo sin procesar)), donde la marca de tiempo y el id de entrega provienen de las cabeceras X-Webhook-Timestamp y X-Webhook-Delivery-Id. Verifique también X-Webhook-Content-Digest (SHA-256 del cuerpo) y rechace marcas de tiempo obsoletas. X-Webhook-Id se mantiene estable entre reintentos — úselo para la idempotencia.
Cómo Configurar: Los endpoints se gestionan en Entrega de terceros → Taquilla de proveedors → Configuración, un endpoint por proveedor, con una lista de eventos seleccionable. Las entregas fallidas se reintentan con retroceso exponencial hasta 7 veces antes de pasar a la lista de fallidos; los eventos fallidos pueden reenviarse manualmente desde la página de eventos.
Eventos de sandbox (taquillas simuladas): Las entregas creadas contra taquillas simuladas emiten los mismos eventos de webhook que producción, firmados con el mismo secreto, para que pueda desarrollar con tráfico realista. Los eventos de sandbox se marcan de tres formas: la carga incluye "livemode": false, el event_id empieza por PLE-MOCK- y la solicitud lleva la cabecera X-Webhook-Test: 1. Si el endpoint tiene configurada una URL de sandbox, los eventos de sandbox se envían allí en lugar de a la URL de producción; en caso contrario recurren a la URL de producción, siempre marcados. El interruptor «Entregar eventos de sandbox» detiene por completo la entrega de sandbox.
Eventos de entrega de terceros
Webhooks de entrega de paquetes enviados a los proveedores de entrega externos (mensajerías). Cubren el ciclo de vida de las asignaciones de entrega, de modo que la mensajería ya no necesita sondear en busca de nuevos trabajos. Esta categoría es independiente de los eventos de taquilla inteligente de más abajo: cada proveedor configura por categoría un endpoint, un secreto de firma y una suscripción de eventos independientes — en su propio portal de proveedor o a través del operador de la plataforma.
delivery.assignment.created
Asignación creada — Se dispara cuando un pedido se asigna al proveedor — por una regla automática o manualmente. La carga útil incluye el número de asignación, los identificadores del pedido y los números de seguimiento de los paquetes.
Asignación cancelada — Se dispara cuando la plataforma retira una asignación al proveedor. El campo reason distingue entre cancelled (la asignación se canceló en el transportista), fallback_to_self_delivery (la plataforma recuperó el pedido para entregarlo por sus propios medios) y reassigned (el pedido se trasladó a otro proveedor).
Entrega parcial — Se activa cuando parte de un envío ha sido entregada mientras otros paquetes siguen en curso. El array packages incluye el resultado de cada bulto y legs enumera los pedidos externos registrados con el transportista: uno por paquete cuando el transportista no admite envíos de varios bultos.
Firma y Verificación: Los webhooks de entrega de terceros usan el mismo esquema de firma que los webhooks de taquillas de proveedors: X-Webhook-Signature es base64(HMAC-SHA256(secret, timestamp + "\n" + delivery id + "\n" + raw body)), donde el timestamp y el delivery id se toman de las cabeceras X-Webhook-Timestamp y X-Webhook-Delivery-Id. Verifique también X-Webhook-Content-Digest (SHA-256 del cuerpo) y rechace marcas de tiempo obsoletas. X-Webhook-Id se mantiene estable entre reintentos — úselo para la idempotencia.
Cómo Configurar: Los proveedores configuran este endpoint por sí mismos en el portal del proveedor (Configuración de Webhooks), o lo hace el operador de la plataforma en Entrega de terceros → Proveedores → Webhooks. Un endpoint por proveedor con una lista de eventos seleccionable. El secreto de firma puede generarse automáticamente o establecerse con un valor personalizado, y puede consultarse en la página de configuración. Las entregas fallidas se reintentan con retroceso exponencial hasta 7 veces antes de pasar a la lista de fallidos; los eventos fallidos pueden reenviarse manualmente. Desde la página de configuración se puede enviar en cualquier momento un evento de prueba (mock) firmado: las solicitudes de prueba llevan la cabecera X-Webhook-Test: 1 y "test": true dentro de los datos del payload.
Eventos del ciclo de vida del pedido
Eventos detallados y opcionales junto al webhook clásico order.status_change (que no cambia): a quién se asignó, si el conductor aceptó, cuándo se recogió el paquete, cuándo está en camino, entregado o fallido, además de los cambios de turno de los conductores y sus posiciones limitadas por frecuencia. No se envía nada hasta que configure las URL siguientes.
order.assigned
Se asignó un conductor al pedido (manualmente, por planificación de rutas o por asignación automática). data.source = auto_assign cuando lo hizo el orquestador.
Una posición del conductor procedente de la app o del rastreador, limitada por conductor mediante driver_location_min_interval_sec (60 s por defecto). Se envía solo a driver_location_webhook_url.
Cómo Configurar: Ajustes → Webhooks (o GET/PUT /api/v1/webhook-settings, GraphQL webhookSettingsUpdate): order_lifecycle_webhook_url recibe todos los eventos order.* y driver.on_duty_changed; order_lifecycle_events los limita a una lista separada por comas; driver_location_webhook_url y driver_location_min_interval_sec controlan driver.location_update. Se pueden indicar varias URL separadas por comas. Las entregas aparecen en el registro de entregas de webhooks con reference_type order / driver.
Firma y Verificación: Firmado exactamente igual que cualquier otro webhook saliente de su cuenta: cabecera Signature heredada más X-Webhook-Id / X-Webhook-Timestamp / X-Webhook-Signature-V2 con su webhook_sign_secret. Los reintentos reutilizan el mismo event_id: deduplique a partir de él.
Eventos de pedidos en dispositivos
Eventos opcionales para los paquetes que gestionan sus taquillas inteligentes, quioscos y buzones inteligentes: un paquete depositado en una máquina, retirado, sacado por el personal o que ha superado su plazo de retirada, y las incidencias abiertas o resueltas sobre él. Solo aditivo: ningún webhook existente cambia y no se envía nada hasta que configure device_order_webhook_url.
device_order.stored
Se depositó un paquete en la máquina y espera a la siguiente persona (destinatario, mensajero u operador, véase data.device_order.next_actor). due_at es la fecha límite de retirada.
Se abrió una incidencia sobre la gestión (por ejemplo door_left_open, deposit_unverified, item_missing, overdue). data.exception incluye id, type, severity y status.
Ejemplos de Carga: data.device_order: id, kind, status, next_actor, device_type, device_id, device_name, grid_code, reference_number, order_id, external_order_id, due_at, overdue_at, stored_at, ended_at, removal_reason (horas en ISO 8601, null mientras no se alcancen). Los eventos de incidencia añaden data.exception: id, type, severity, status, resolution_action. El código de retirada nunca se incluye. event_id es DOE-<id del evento del registro> y no cambia en los reintentos.
Cómo Configurar: Ajustes → Webhooks (o GET/PUT /api/v1/webhook-settings): device_order_webhook_url recibe todos los eventos device_order.*; device_order_events lo limita a una lista separada por comas. Se pueden indicar varias URL separadas por comas. Las entregas aparecen en el registro de entregas de webhooks con reference_type device_order.
Firma y Verificación: Firmado exactamente igual que cualquier otro webhook saliente de su cuenta: cabecera Signature heredada más X-Webhook-Id / X-Webhook-Timestamp / X-Webhook-Signature-V2 con su webhook_sign_secret. Los reintentos reutilizan el mismo event_id: deduplique a partir de él.
Los paquetes que un transportista asociado entrega en sus taquillas con su propia cuenta no se envían por este canal; el socio los recibe a través de sus webhooks de taquillas del proveedor.
Cómo Configurar
Puede configurar webhooks en dos niveles: a nivel de negocio (cubre todo) o por cliente (anula para esa subcuenta B2B específica).
1. Llegar a los ajustes
Inicie sesión y vaya a Ajustes → API y Webhooks. Las anulaciones por cliente están en la página de detalle del cliente.
2. Establecer el secreto de firma
Elija cualquier cadena de al menos 16 caracteres, idealmente 32+ bytes aleatorios. Su receptor lo usará para verificar firmas.
3. Establezca las URLs de eventos deseadas
Rellene solo las URLs de los eventos que le interesan. Deje el resto en blanco para omitirlos.
webhook_sign_secretUsted configura un secreto compartido en la página de ajustes. Cada webhook saliente se firma con ese secreto. Su receptor recalcula la firma y la compara — si coinciden, la carga es genuina y no ha sido alterada.
order_create_webhook_urlSe dispara cuando se crea un pedido de entrega local (Delivery / Pickup / P2P) por cualquier vía: formulario web, API REST/GraphQL, sincronización con plataforma de e-commerce, reglas automáticas, filas importadas, etc. Excluye los pedidos label-service y otros tipos que no son de entrega. Se omite en el flujo por lotes cuando el mismo destinatario tiene también order_create_async_postback_url configurado. Configure con order_create_webhook_url.
order_status_change_webhook_urlSe dispara en cada transición de estado del pedido — recogido, en tránsito, entregado, excepción, cancelado. Configure con order_status_change_webhook_url.
seguimiento_event_webhook_urlSe dispara en cada evento del ciclo de vida del seguimiento de un paquete (información enviada, inicio de entrega, entrega exitosa, no entregado, etc.). Configure con tracking_event_webhook_url. Los eventos de entrega y de recogida también incluyen la prueba de entrega: proof_files y proof_files_detail (file_id, type, url, full_url, URL de descarga firmada). Las fotos subidas después del evento llegan como pod.files_updated. Cada archivo incluye además el contexto de su evento: tracking_event_id, tracking_event_status_id, tracking_event_key, service_type (1 = delivery / 2 = pickup) y service_status (1 = success / 2 = failed); en archivos antiguos sin evento registrado son null.
order_create_async_postback_urlSe dispara una vez tras finalizar una importación masiva de pedidos. La carga contiene el array de resultados por fila. Configure con order_create_async_postback_url.
pod_files_webhook_urlSe dispara cuando una foto de entrega o firma se añade, se reemplaza o se elimina (action: added / updated / removed) — un envío por archivo, sin más sondeo de adjuntos. Se activa configurando pod_files_webhook_url. Cada archivo incluye además el contexto de su evento: tracking_event_id, tracking_event_status_id, tracking_event_key, service_type (1 = delivery / 2 = pickup) y service_status (1 = success / 2 = failed); en archivos antiguos sin evento registrado son null.
order_deleted_webhook_urlSe dispara cuando un pedido se elimina permanentemente, para que su sistema pueda reflejar la eliminación. Se activa configurando order_deleted_webhook_url.
order_cancel_failed_webhook_urlSe dispara cuando un intento de cancelación es rechazado (por ejemplo, el pedido ya está en reparto), para que su equipo de operaciones pueda supervisar las cancelaciones fallidas sin consultar la API. Se activa configurando order_cancel_failed_webhook_url.
route_board_webhook_urlSe dispara cuando un asiento del tablero de rutas cambia de manos o el tablero cambia de estado — el campo action indica qué ocurrió (claimed, standby, pooled, promoted, withdrawn, vetoed, replaced, assigned, awarded, lost, displaced, settled, board_opened, board_closed, board_cancelled). Solo a nivel de empresa. Suscripción mediante route_board_webhook_url.
device_order_webhook_urlEventos opcionales para los paquetes que gestionan sus taquillas inteligentes, quioscos y buzones inteligentes: un paquete depositado en una máquina, retirado, sacado por el personal o que ha superado su plazo de retirada, y las incidencias abiertas o resueltas sobre él. Solo aditivo: ningún webhook existente cambia y no se envía nada hasta que configure device_order_webhook_url.
Cada webhook saliente lleva una firma HMAC-SHA256 codificada en hexadecimal en el encabezado. Su receptor debe recalcular la firma sobre el cuerpo crudo con el secreto compartido y rechazar la solicitud si no coincide.
Algoritmo
HMAC-SHA256 (hex)
Nombre del encabezado
Signature
Pasos de verificación
Lea el cuerpo crudo antes de que el parsing o el middleware lo modifique.
Calcule hash_hmac('sha256', rawBody, sharedSecret) y codifique en hexadecimal.
Compare con el encabezado Signature en tiempo constante (hash_equals en PHP, crypto.timingSafeEqual en Node).
Responda 2xx solo si las firmas coinciden. De lo contrario 401.
func handleWebhook(w http.ResponseWriter, r *http.Request) {
body, _ := io.ReadAll(r.Body)
received := r.Header.Get("Signature")
mac := hmac.New(sha256.New, []byte(sharedSecret))
mac.Write(body)
expected := hex.EncodeToString(mac.Sum(nil))
if !hmac.Equal([]byte(received), []byte(expected)) {
w.WriteHeader(401); return
}
// ... handle event ...
w.WriteHeader(200)
w.Write([]byte("ok"))
}
require 'openssl'
require 'rack/utils'
post '/webhooks/superroute' do
raw = request.body.read
received = request.env['HTTP_SIGNATURE'] || ''
expected = OpenSSL::HMAC.hexdigest('sha256', shared_secret, raw)
halt 401 unless Rack::Utils.secure_compare(received, expected)
payload = JSON.parse(raw)
# ... handle event ...
status 200
'ok'
end
Reintentos y Fiabilidad
Su endpoint debería responder con 2xx rápidamente. Si devuelve otra cosa, supera el tiempo de espera o no es accesible, se reintenta la entrega.
Intentos máximos
5 (inicial + 4 reintentos)
Tiempo de espera por intento
3 segundos
Retroceso
Exponencial — aproximadamente 10s, 100s, 1000s, 10000s
Diseñe para idempotencia. Como una entrega puede reintentarse, su receptor puede ver el mismo evento varias veces. Use el ID del pedido/seguimiento como clave de deduplicación — almacene los IDs procesados al menos 24 horas.
Respuesta recomendada. Confirme rápido (HTTP 200) y procese de forma asíncrona. Evite trabajo lento de forma síncrona dentro del handler del webhook — alcanzará el timeout de 3 segundos.
Verificador de Firma
Pegue una carga que recibió de nosotros junto con el valor del encabezado Signature y su secreto — esta herramienta recalcula la firma en su navegador (nada sale de esta página) y le dice si coincide.
Enviar Webhook de Prueba
Dispare un webhook real y correctamente firmado desde nuestro servidor a una URL que proporcione. Úselo para probar que su receptor es accesible, que analiza la carga correctamente y que su lógica de verificación de firma funciona.
Entregas Recientes de Webhook
Vea los intentos de entrega de webhook más recientes en su cuenta — tanto eventos reales de producción como pruebas enviadas desde esta página. Pegue su Bearer token para cargar.
Tiempo
Evento
URL
Estado
HTTP
Intento
Tiempo (ms)
¿Prueba?
Acciones
Aún no se han encontrado entregas de webhook.
Buenas Prácticas
Confirme rápido (HTTP 200) y procese el trabajo de forma asíncrona para no superar el timeout de 3 segundos.
Verifique siempre la firma antes de confiar en la carga.
Trate los eventos como at-least-once — deduplique por número de pedido/seguimiento.
Use endpoints HTTPS con un certificado válido.
Registre las solicitudes entrantes para poder reproducirlas si su handler tiene un bug.