Skip to Content
WebhooksExemples

Exemples de webhooks

Cette page propose des exemples complets, prêts pour la production, pour recevoir et traiter les webhooks Ignite dans différents langages de programmation.

Exemples serveur complets

// pages/api/webhook.ts import { createHmac, timingSafeEqual } from "crypto"; import { NextApiRequest, NextApiResponse } from "next"; // Disable body parser to access raw body for signature verification export const config = { api: { bodyParser: false, }, }; interface ThumbnailFormat { url: string; fileSize: number; } interface ThumbnailVariant { name: string; width: number; height: number; formats: { jpeg: ThumbnailFormat; webp: ThumbnailFormat; }; } interface VideoWebhookData { id: string; status: "COMPLETE" | "PROCESSING" | "NO_FILE" | "FAILED"; title: string; src?: { thumbnails?: ThumbnailVariant[]; thumbnailUrl?: string; // deprecated — use src.thumbnails instead mp4?: Array<{ name: string; url: string; width: number; height: number }>; }; // ... other video properties } async function getRawBody(req: NextApiRequest): Promise<string> { const chunks: Buffer[] = []; for await (const chunk of req) { chunks.push(typeof chunk === "string" ? Buffer.from(chunk) : chunk); } return Buffer.concat(chunks).toString("utf-8"); } function isValidSignature( rawBody: string, signatureHeader: string | string[] | undefined, secret: string ): boolean { try { if (typeof signatureHeader !== "string") { return false; } const time = signatureHeader.match(/t=(\d+)/)?.[1]; const token = signatureHeader.match(/v1=(\w+)/)?.[1]; if (!time || !token) { return false; } const signedPayload = `${time}.${rawBody}`; const hmac = createHmac("sha256", secret); const calculatedSignature = hmac.update(signedPayload).digest("hex"); return timingSafeEqual( Buffer.from(token), Buffer.from(calculatedSignature) ); } catch { return false; } } export default async function handler( req: NextApiRequest, res: NextApiResponse ) { if (req.method !== "POST") { return res.status(405).end(); } const rawBody = await getRawBody(req); if ( !isValidSignature( rawBody, req.headers["x-webhook-signature"], process.env.WEBHOOK_SIGNING_SECRET! ) ) { console.error("Invalid webhook signature"); return res.status(403).end(); } const eventType = req.headers["x-webhook-event"]; const deliveryId = req.headers["x-webhook-delivery-id"]; const video = JSON.parse(rawBody) as VideoWebhookData; // Process based on event type switch (eventType) { case "video.created": console.log("New video created:", video.id, video.title); // await handleVideoCreated(video); break; case "video.updated": console.log("Video updated:", video.id, video.title); if (video.status === "COMPLETE") { // Video processing finished - update your database // await db.updateVideo(video.id, { // thumbnails: video.src?.thumbnails, // thumbnail: video.src?.thumbnails?.[0]?.formats.jpeg.url, // sizes: video.src?.mp4, // }); } break; case "video.deleted": console.log("Video deleted:", video.id); // await handleVideoDeleted(video); break; } return res.status(204).end(); }

Livraisons webhook

Chaque tentative de livraison d’un webhook est journalisée. Si une livraison échoue, le système retente automatiquement.

Statut de livraison

StatutDescription
successÉvénement livré avec succès (réponse HTTP 2xx)
failedÉchec de la livraison (délai dépassé, HTTP 4xx/5xx, erreur réseau)

Informations de livraison

Chaque enregistrement de livraison contient :

ChampDescription
responseCodeCode de statut HTTP renvoyé par ton endpoint
responseBodyCorps de la réponse de ton endpoint (tronqué si trop volumineux)
errorMessageMessage d’erreur en cas d’échec de livraison
deliveredAtHorodatage de la tentative de livraison
attemptNumberNuméro de la tentative (s’incrémente aux nouvelles tentatives)
nextRetryAtDate de la prochaine tentative (le cas échéant)

Comportement des nouvelles tentatives

  • Les livraisons en échec sont automatiquement retentées
  • Si nextRetryAt est défini, une nouvelle tentative est planifiée
  • Si nextRetryAt n’est pas défini, aucune nouvelle tentative n’aura lieu

Bonnes pratiques

Suivre ces bonnes pratiques assure un traitement fiable des webhooks et facilite le débogage.

Temps de réponse

Ton endpoint doit répondre dans les 30 secondes. Pour des opérations longues, accuse réception immédiatement du webhook et traite en arrière-plan :

app.post('/webhook', async (req, res) => { // Immediately acknowledge receipt res.status(200).json({ received: true }); // Process asynchronously (don't await) processWebhookAsync(req.body).catch(console.error); }); async function processWebhookAsync(video) { // Long-running operations here }

Sécurité

  • Secrets — N’expose jamais ton secret de signature dans le code client ni dans le contrôle de version
  • HTTPS — Utilise toujours des endpoints HTTPS en production
  • Validation — Vérifie toujours les signatures avant traitement
  • Limitation de débit — Envisage une limitation de débit sur ton endpoint

Fiabilité

  • Idempotence — Stocke et vérifie X-Webhook-Delivery-Id pour gérer les livraisons en double
  • Journaux — Journalise toutes les requêtes webhook pour le débogage
  • Surveillance — Configure des alertes en cas d’échec du traitement
  • Gestion d’erreurs — Renvoie des codes HTTP appropriés pour que les nouvelles tentatives fonctionnent

Codes de statut HTTP

CodeSignification
200-299Succès — événement traité
4xxErreur client — nouvelle tentative prévue
5xxErreur serveur — nouvelle tentative prévue

Dépannage

Aucun événement reçu

  1. Vérifie que l’abonnement webhook est actif
  2. Vérifie que les bons types d’événements sont sélectionnés
  3. Assure-toi que les événements se produisent dans le bon espace de travail
  4. Consulte les journaux de ton serveur pour les requêtes entrantes

Échec de la vérification de signature

  1. Vérifie que tu utilises le bon secret de signature (pas un jeton d’API)
  2. Assure-toi que le corps de la requête n’est pas modifié avant la vérification
  3. Vérifie que la sérialisation JSON correspond (compacte, sans espace superflu)
  4. Vérifie que le format de l’en-tête de signature est correctement analysé : t=timestamp,v1=signature

Erreurs de délai dépassé

  1. Réponds dans les 30 secondes
  2. Déplace les opérations longues vers un traitement en arrière-plan
  3. Renvoie 200 immédiatement, traite de façon asynchrone

Événements en double

  1. Implémente l’idempotence avec X-Webhook-Delivery-Id
  2. Consulte attemptNumber pour les nouvelles tentatives
  3. Stocke les ID de livraison traités en base de données