Guía: recibir actualizaciones en tiempo real
Un endpoint que verifica, deduplica, encola y responde en milisegundos. Todo lo demás lo haces después.
1 · Crea el webhook
curl -X POST https://wearetransfers.com/api/v1/webhooks \
-H "Authorization: Bearer $WAT_API_KEY" \
-H "Content-Type: application/json" \
-d '{"url":"https://tu-dominio.com/hooks/wat","events":["*"],"description":"Todo, para el tablero de operaciones"}'Guarda el secret de la respuesta: no se vuelve a mostrar.
2 · El receptor
La regla de oro: verificar → deduplicar → encolar → 200. Nada de llamar a tu base de datos de negocio dentro de la petición.
import express from 'express';
import { verificarWebhook } from './wat-firma.js'; // ver Firmas
const app = express();
app.post('/hooks/wat', express.raw({ type: 'application/json', limit: '1mb' }), async (req, res) => {
const raw = req.body.toString('utf8');
if (!verificarWebhook({ secret: process.env.WAT_WEBHOOK_SECRET, headers: req.headers, rawBody: raw })) return res.status(401).end();
const eventId = req.headers['x-wat-event-id'];
if (await cola.yaVisto(eventId)) return res.status(200).end(); // reintento de algo ya recibido
await cola.encolar({ eventId, tipo: req.headers['x-wat-event'], cuerpo: raw }); // Redis, SQS, tabla… lo que uses
res.status(200).end();
});| Si tu receptor… | WAT… |
|---|---|
| responde 2xx | lo da por entregado. Aunque después falle tu procesamiento: por eso encolas antes de responder. |
| tarda más de 10 s | corta y reintenta. Cada reintento llega con el mismo X-WAT-Event-Id. |
| responde 5xx o 429 | reintenta con espera exponencial hasta 8 veces. |
| responde 4xx | reintenta 3 veces y lo da por muerto. Un 401 sostenido suele ser un secreto mal configurado. |
| redirige | no sigue la redirección: cuenta como fallo. |
3 · Procesar
En el consumidor de la cola, parsea el cuerpo y actúa por type. data ya es la reserva completa (según tus scopes): en la mayoría de los casos no hace falta volver a llamar a la API. Si dos eventos de la misma reserva llegan desordenados, el created_at del cuerpo dice cuál es más nuevo; ante la duda, GET /v1/bookings/{id} devuelve el estado actual.
Las entregas se hacen en lotes y en paralelo: dos eventos de la misma reserva con segundos de diferencia pueden llegar en orden inverso. Diseña el consumidor para que aplicar un evento viejo después de uno nuevo no rompa nada (idempotencia por estado, no por transición).
4 · Vigila
GET /v1/webhooks/{id}/deliverieses tu registro:failedconlast_errordice qué pasa antes de que se acumulen 100 fallos y el webhook se apague.- Si se apagó: arregla, y
PATCHcon{ "active": true }. - Para lo que se perdió, reconcilia con GET /events.