Patterns
Mécanisme de replay des webhooks
Endpoint /replay et déduplication par event_id
Un webhook peut échouer côté receveur (5xx, timeout, déploiement en cours). Le pattern replay expose un endpoint `POST /api/v1/webhooks/{id}/replay` qui retransmet un événement précis (par `event_id`) ou une plage temporelle. Côté receveur, la déduplication est obligatoire : stocker chaque `event_id` reçu dans une table `processed_webhook_events` avec un index unique, ou utiliser Redis avec `SETNX event:{id} 1 EX 86400`. Sans déduplication, un replay double-facture, double-comptabilise, double-déclenche un workflow. Le pattern complet : retry automatique en backoff exponentiel (5 tentatives sur 24h) → si toutes échouent, l'événement est marqué `failed` et l'utilisateur peut déclencher un replay manuel via le dashboard ou l'API. Les logs de delivery sont conservés 30 jours via `GET /api/v1/webhooks/{id}/logs`.
À retenir
- Endpoint `POST /api/v1/webhooks/{id}/replay` avec event_id ou range
- Déduplication obligatoire côté receveur (table SQL ou Redis SETNX)
- Retry automatique 5x sur 24h en backoff exponentiel avant 'failed'
- Logs de delivery conservés 30j via `GET /webhooks/{id}/logs`
- Replay manuel disponible dans le dashboard Scell.io
Exemple de code
// Receveur webhook avec déduplication Redis
import { createClient } from 'redis';
const redis = createClient();
async function handleWebhook(req: Request, res: Response) {
const eventId = req.body.event_id;
const isFirstTime = await redis.set(
`webhook:event:${eventId}`,
'1',
{ NX: true, EX: 86400 } // 24h dedup window
);
if (!isFirstTime) return res.status(200).send('duplicate ignored');
// Traiter l'événement (idempotent par construction)
await processEvent(req.body);
return res.status(200).send('ok');
}