Configuración de webhooks
Recibe actualizaciones en tiempo real sobre tus envíos mediante webhooks.
¿Qué son los webhooks?
Los webhooks son mensajes automáticos que atoship envía a tu servidor cuando ocurre un evento:
- Etiqueta creada
- Paquete enviado
- Cambio en el estado de entrega
- Incidencia detectada
Ventajas:
- Actualizaciones en tiempo real (sin necesidad de consultar continuamente)
- Activación de flujos de trabajo automatizados
- Actualización instantánea de tus sistemas
- Mejor experiencia para el cliente
Eventos disponibles
Eventos de envío
| Evento | Se activa cuando | Caso de uso |
|---|---|---|
| shipment.created | Se compra una etiqueta | Actualizar inventario |
| shipment.cancelled | Se anula una etiqueta | Restaurar inventario |
| shipment.delivered | Se entrega el paquete | Enviar solicitud de reseña |
| shipment.returned | Se recibe una devolución | Procesar reembolso |
| shipment.exception | Problema de entrega | Avisar a atención al cliente |
Eventos de seguimiento
| Evento | Se activa cuando | Caso de uso |
|---|---|---|
| tracking.in_transit | Primer escaneo del transportista | Notificar al cliente |
| tracking.out_for_delivery | Va en el camión de reparto | Aviso el mismo día |
| tracking.delivered | Entrega confirmada | Cerrar el pedido |
| tracking.failed_attempt | Intento de entrega fallido | Avisar al cliente |
| tracking.exception | Se produjo una incidencia | Investigar |
Eventos de pedido
| Evento | Se activa cuando | Caso de uso |
|---|---|---|
| order.imported | El pedido se sincroniza | Iniciar la preparación |
| order.updated | El pedido se modifica | Actualizar registros |
| order.cancelled | El pedido se cancela | Detener la preparación |
Eventos de cuenta
| Evento | Se activa cuando | Caso de uso |
|---|---|---|
| balance.low | El saldo de la billetera baja del umbral | Aviso para recargar fondos |
| billing.adjustment | Ajuste del transportista | Revisar el cargo |
Guía de configuración
Paso 1: Crear el endpoint
Tu endpoint debe:
- Aceptar solicitudes POST
- Usar HTTPS (obligatorio en producción)
- Devolver un estado 200 en menos de 5 segundos
- Gestionar los reintentos de forma idempotente
Ejemplo de endpoint (Node.js/Express):
const express = require('express');
const app = express();
app.post('/webhooks/atoship', express.json(), (req, res) => {
// Acknowledge immediately
res.status(200).send('OK');
// Process asynchronously
processWebhook(req.body).catch(console.error);
});
async function processWebhook(event) {
switch (event.type) {
case 'shipment.delivered':
await markOrderDelivered(event.data.order_id);
await sendDeliveryEmail(event.data);
break;
case 'tracking.exception':
await alertCustomerService(event.data);
break;
// Handle other events...
}
}
Paso 2: Registrar el webhook
- Ve a Configuración > Webhooks
- Haz clic en Agregar endpoint de webhook
- Ingresa tu URL: https://yoursite.com/webhooks/atoship
- Selecciona los eventos que quieres recibir
- Haz clic en Guardar
Paso 3: Copiar el secreto del webhook
Después de guardar:
- Haz clic en tu webhook
- Copia el secreto de firma (Signing Secret)
- Guárdalo de forma segura (en una variable de entorno)
Paso 4: Verificar las firmas
IMPORTANTE: Verifica siempre las firmas de los webhooks para evitar suplantaciones.
const crypto = require('crypto');
function verifySignature(payload, signature, secret) {
const expectedSig = crypto
.createHmac('sha256', secret)
.update(JSON.stringify(payload))
.digest('hex');
// Use timing-safe comparison
return crypto.timingSafeEqual(
Buffer.from(signature, 'hex'),
Buffer.from(expectedSig, 'hex')
);
}
app.post('/webhooks/atoship', express.json(), (req, res) => {
const signature = req.headers['x-atoship-signature'];
const secret = process.env.ATOSHIP_WEBHOOK_SECRET;
if (!verifySignature(req.body, signature, secret)) {
console.error('Invalid webhook signature');
return res.status(401).send('Invalid signature');
}
// Signature valid, process event
res.status(200).send('OK');
processWebhook(req.body);
});
Estructura del payload del evento
Formato estándar
{
"id": "evt_1234567890abcdef",
"type": "shipment.delivered",
"created_at": "2024-01-15T10:30:00Z",
"data": {
"shipment_id": "shp_abc123",
"tracking_number": "9400111899223456789012",
"carrier": "USPS",
"service": "Priority Mail",
"order_id": "order_xyz789",
"order_reference": "ORD-12345",
"delivered_at": "2024-01-15T10:28:00Z",
"delivery_location": "Front door",
"signed_by": "RESIDENT"
},
"metadata": {
"organization_id": "org_xxxxx",
"attempt": 1
}
}
Lógica de reintentos
Reintentos automáticos
Si tu endpoint devuelve un estado distinto de 2xx o agota el tiempo de espera:
| Intento | Retraso |
|---|---|
| 1 | Inmediato |
| 2 | 1 minuto |
| 3 | 5 minutos |
| 4 | 30 minutos |
| 5 | 2 horas |
| 6 | 6 horas |
Tras 6 fallos, el webhook se marca como fallido.
Cómo gestionar los reintentos
La idempotencia es fundamental:
const processedEvents = new Map(); // Use Redis in production
async function processWebhook(event) {
// Check if already processed
if (processedEvents.has(event.id)) {
console.log('Event ' + event.id + ' already processed, skipping');
return;
}
// Mark as processing
processedEvents.set(event.id, { status: 'processing', timestamp: Date.now() });
try {
// Process event
await handleEvent(event);
processedEvents.set(event.id, { status: 'completed', timestamp: Date.now() });
} catch (error) {
processedEvents.set(event.id, { status: 'failed', error: error.message });
throw error; // Let retry happen
}
}
Probar los webhooks
Enviar un evento de prueba
- Ve a Configuración > Webhooks
- Haz clic en tu endpoint
- Haz clic en Enviar evento de prueba
- Selecciona el tipo de evento
- Revisa la respuesta
Desarrollo local
Usa ngrok para hacer pruebas en local:
# Install ngrok
npm install -g ngrok
# Expose local port
ngrok http 3000
# Use provided URL
# https://abc123.ngrok.io/webhooks/atoship
Registros de webhooks
Consulta los intentos de entrega:
- Ve a la configuración del webhook
- Haz clic en Registros de entrega (Delivery Logs)
- Consulta los detalles de la solicitud y la respuesta
- Reintenta las entregas fallidas
Buenas prácticas
Tiempo de respuesta
Devuelve el estado 200 rápidamente:
// Good - Acknowledge immediately, process async
app.post('/webhooks', (req, res) => {
res.status(200).send('OK');
queue.add('process-webhook', req.body);
});
// Bad - Blocking response
app.post('/webhooks', async (req, res) => {
await processWebhook(req.body); // May timeout
res.status(200).send('OK');
});
Monitoreo
Supervisa el estado de tus webhooks:
- Tasa de entregas exitosas
- Tiempo de respuesta promedio
- Tipos de eventos fallidos
- Frecuencia de reintentos
Solución de problemas
No recibo webhooks
Comprueba:
- Que la URL del endpoint sea correcta
- Que HTTPS esté habilitado
- Que el firewall permita las IP de atoship
- Que estés suscrito a los eventos
- Que el webhook esté habilitado
Falla la verificación de la firma
Causas comunes:
- Usar el JSON ya procesado en lugar del cuerpo sin procesar (raw body)
- Secreto del webhook incorrecto
- Diferencia de codificación
Errores de tiempo de espera
Si el webhook agota el tiempo de espera:
- Responde de inmediato con un estado 200
- Procesa la lógica de forma asíncrona
- Usa una cola de mensajes
- Revisa el rendimiento del servidor
¿Necesitas ayuda?
- Documentación de la API: Referencia completa de webhooks
- Chat para desarrolladores: Soporte técnico
- Correo electrónico: [email protected]
- Soporte: Crea un ticket en /dashboard/support