Nouvelles tentatives et livraison

Comment Certivant renouvelle les livraisons de webhooks en échec — calendrier exact d'espacement, règle de délai d'attente de 10 secondes, reprise des événements épuisés, et modèle de gestionnaire rapide pour rester dans le budget.

Certivant est conçu pour livrer chaque événement au moins une fois. Si votre point de terminaison est brièvement indisponible — un déploiement, un incident de base de données, une panne de 30 secondes — les nouvelles tentatives garantissent que l'événement finit tout de même par passer. Cette page décrit le comportement exact afin que vous puissiez anticiper.

La politique de nouvelle tentative en bref

Valeur
Nombre maximal de tentatives de livraison5 (y compris la première)
Calendrier des nouvelles tentatives5s, 30s, 5min, 1h, 24h, chacun avec une gigue de ±10 %
Retry-AfterRespecté sur toute tentative échouée (secondes ou date HTTP, plafonné à 24 h) : la tentative suivante n'a jamais lieu plus tôt que ce que vous avez demandé
Délai d'attente par tentative10 secondes
Critère de succèsCode HTTP 200–299
Critères d'échecCode >= 300, délai dépassé, erreur de connexion, échec DNS
Fenêtre totale de livraisonEnviron 25 heures à partir de la première tentative

Après la cinquième tentative échouée, l'événement est marqué comme épuisé. Il ne sera plus renouvelé automatiquement. Un courriel est alors envoyé au propriétaire de l'organisation pour l'avertir que les webhooks échouent.

La chronologie

gantt
  title Webhook delivery attempts
  dateFormat X
  axisFormat %s
  section Attempts
  Attempt 1 (immediate) :a1, 0, 1s
  Attempt 2 (+5s)       :a2, 5, 1s
  Attempt 3 (+30s)      :a3, 35, 1s
  Attempt 4 (+5min)     :a4, 335, 1s
  Attempt 5 (+1h)       :a5, 3935, 1s
  Attempt 6 (+24h)      :a6, 90335, 1s

Le compteur démarre lorsque l'événement est généré. Si votre point de terminaison est opérationnel dès la première tentative, vous ne voyez jamais de nouvelles tentatives. S'il reste indisponible pendant les 25 heures complètes, l'événement est épuisé.

Une brève interruption transitoire (un déploiement, un basculement de base de données, tout ce qui dure moins d'une minute) est entièrement absorbée par le calendrier : votre point de terminaison recevra la tentative suivante environ 5 secondes plus tard et réussira.

Ce qui est considéré comme un succès

Certivant considère votre point de terminaison comme opérationnel lorsque :

  • Le code HTTP est 2xx (200, 201, 204, etc.).
  • La réponse arrive dans les 10 secondes suivant l'envoi de la requête.

Tout le reste constitue un échec de livraison :

  • Redirections 3xx — Certivant ne suit pas les redirections. Indiquez directement la destination finale dans l'URL du webhook.
  • 4xx (y compris 401 et 404) — Certivant renouvelle quand même, au cas où le problème serait transitoire (vérification d'authentification au démarrage à froid, route pas encore déployée). La plupart des intégrations doivent examiner tout code 4xx, car il indique généralement une mauvaise configuration de votre côté.
  • 5xx — erreur serveur. Nouvelle tentative standard.
  • Connexion refusée, échec DNS, erreur de négociation TLS — même comportement de nouvelle tentative.
  • Aucune réponse dans les 10 secondes — Certivant interrompt la requête et la compte comme un échec. Les nouvelles tentatives se poursuivent.

Concevoir un gestionnaire rapide

Vous disposez d'un budget de 10 secondes. Effectuez le strict minimum de façon synchrone :

app.post("/webhooks/certivant", async (c) => {
  const rawBody = await c.req.text();

  // 1. Verify signature
  if (!verifyCertivantSignature(rawBody, c.req.header("X-Certivant-Signature-V2"), SECRET)) {
    return c.json({ error: "Invalid signature" }, 401);
  }

  // 2. Persist to queue (single DB write, fast)
  const eventId = c.req.header("X-Certivant-Event-Id")!;
  await db.webhookEventQueue.create({
    data: { id: eventId, payload: rawBody },
  });

  // 3. Acknowledge immediately
  return c.json({ received: true }, 200);
});

// Process the queue asynchronously
async function workerLoop() {
  while (true) {
    const event = await db.webhookEventQueue.findFirst({ where: { processedAt: null } });
    if (!event) { await sleep(1000); continue; }
    try {
      await handleEvent(JSON.parse(event.payload));
      await db.webhookEventQueue.update({ where: { id: event.id }, data: { processedAt: new Date() } });
    } catch (err) {
      // Bounded retry on your side; surface after N attempts
    }
  }
}

Ce modèle dissocie l'accusé de réception (qui doit être rapide) de la logique métier (qui peut être lente ou renouvelée indépendamment). Vos services en aval (envoi de courriels de bienvenue, création de comptes, etc.) peuvent échouer sans que Certivant ne renouvelle l'envoi.

Lorsque votre point de terminaison est réellement indisponible

Si vous devez être indisponible pendant une période prolongée (maintenance, migration), les nouvelles tentatives vous couvrent encore pendant environ 25 heures. Au-delà :

  • Les événements épuisés restent consultables via GET /api/v1/kyc/requests/:id — l'état actuel est toujours disponible sur la demande elle-même. Parcourez les demandes créées pendant votre indisponibilité et synchronisez l'état manuellement.
  • Le propriétaire de l'organisation reçoit un courriel lorsqu'un événement est épuisé. Le courriel contient l'identifiant de la demande, pour faciliter la recherche.
  • L'état de livraison des webhooks (livré / en échec / épuisé), le nombre de tentatives, le dernier code de réponse et la prochaine nouvelle tentative prévue sont visibles dans le tableau de bord, à KYC → Paramètres → Webhooks → Journal des livraisons. Chaque événement en échec ou épuisé dispose d'un bouton Réessayer maintenant (ainsi que d'une nouvelle tentative groupée).

Renvoyer un événement épuisé

Depuis le journal des livraisons, Réessayer maintenant renvoie immédiatement un événement en échec ou épuisé, signé avec le secret actuel, et réinitialise son compteur de tentatives. Il n'existe aucun point de terminaison public (accessible par clé d'API) pour relancer un événement unique. Autres options :

  1. Récupérer l'état via l'API. GET /api/v1/kyc/requests/:id renvoie toujours l'état actuel, y compris la décision finale. C'est la bonne solution pour rattraper un retard après une indisponibilité.
  2. Demander au support de rejouer les événements si un grand lot vous manque. Indiquez les identifiants de demandes ou la fenêtre temporelle : le support peut réémettre les événements pour vous.

Interaction avec la limite de débit

La livraison des webhooks ne compte pas dans la limite de débit de votre clé d'API : ce sont des systèmes distincts. Vous pouvez recevoir des centaines de webhooks par minute tout en effectuant des centaines d'appels API par minute avec la même clé, et aucun de ces deux budgets n'affecte l'autre.

Retour sur l'idempotence

Comme les nouvelles tentatives existent, un même événement logique arrivera parfois deux fois. Voir Événements → Idempotence pour le modèle de déduplication recommandé à l'aide de X-KYC-Event-Id.

Suggestions de supervision

Une intégration de webhooks saine présente :

  • Un temps de réponse médian du point de terminaison webhook inférieur à 500 ms. S'il augmente, vous risquez d'atteindre le délai d'attente de 10 secondes sous charge.
  • Zéro réponse 4xx et 5xx depuis l'URL du webhook en fonctionnement normal. Configurez une alerte sur l'un ou l'autre.
  • Une table de journal d'idempotence que vous pouvez interroger pour confirmer que chaque webhook a été traité au moins une fois.

Si vous recevez des courriels d'événements épuisés, les causes les plus fréquentes sont : (a) l'URL du webhook est incorrecte (faute de frappe dans le tableau de bord), (b) votre point de terminaison exige une authentification que Certivant ne fournit pas (l'URL doit accepter des POST non authentifiés — l'en-tête de signature sert d'authentification), (c) votre point de terminaison répond systématiquement en plus de 10 secondes. Examinez chacune de ces pistes.