Skip to Content
WebhooksExemplos

Exemplos de webhooks

Esta página oferece exemplos completos e prontos para produção para receber e processar webhooks Ignite em várias linguagens de programação.

Exemplos completos de servidor

// 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(); }

Entregas de webhook

Cada tentativa de entrega de webhook é registada. Se uma entrega falhar, o sistema volta a tentar automaticamente.

Estado da entrega

EstadoDescrição
successO evento foi entregue com sucesso (resposta HTTP 2xx)
failedA entrega falhou (timeout, HTTP 4xx/5xx, erro de rede)

Informação da entrega

Cada registo de entrega contém:

CampoDescrição
responseCodeCódigo de estado HTTP devolvido pelo teu endpoint
responseBodyCorpo da resposta do teu endpoint (truncado para respostas grandes)
errorMessageMensagem de erro se a entrega falhou
deliveredAtTimestamp da tentativa de entrega
attemptNumberQual foi esta tentativa (incrementa com novas tentativas)
nextRetryAtQuando será feita a próxima nova tentativa (se aplicável)

Comportamento de novas tentativas

  • As entregas falhadas são automaticamente repetidas
  • Se nextRetryAt estiver definido, fica agendada uma nova tentativa
  • Se nextRetryAt não estiver definido, não haverá mais novas tentativas

Boas práticas

Seguir estas boas práticas garante um processamento fiável dos webhooks e ajuda a depurar problemas.

Tempo de resposta

O teu endpoint tem de responder no prazo de 30 segundos. Para operações longas, confirma o webhook de imediato e processa de forma assíncrona:

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 }

Segurança

  • Mantém os segredos seguros — Nunca exponhas o signing secret em código client-side ou em controlo de versões
  • Usa HTTPS — Usa sempre endpoints HTTPS em produção
  • Valida tudo — Verifica sempre as assinaturas antes de processar
  • Limite de pedidos — Considera implementar rate limiting no teu endpoint

Fiabilidade

  • Idempotência — Guarda e verifica o X-Webhook-Delivery-Id para tratar entregas duplicadas
  • Logging — Regista todos os pedidos de webhook para depuração
  • Monitorização — Configura alertas para falhas no processamento de webhooks
  • Tratamento de erros — Devolve códigos de estado HTTP adequados para que as novas tentativas funcionem corretamente

Códigos de estado HTTP

CódigoSignificado
200-299Sucesso — evento processado
4xxErro do cliente — será repetido
5xxErro do servidor — será repetido

Resolução de problemas

Não recebes eventos

  1. Verifica se a subscrição de webhook está Ativa
  2. Confirma que os tipos de evento corretos estão selecionados
  3. Garante que os eventos ocorrem no workspace correto
  4. Consulta os logs do servidor à procura de pedidos recebidos

A verificação da assinatura falha

  1. Confirma que estás a usar o signing secret correto (não um token de API)
  2. Garante que o corpo do pedido não é alterado antes da verificação
  3. Verifica que a serialização JSON coincide (compacta, sem espaços extra)
  4. Confirma que o formato do cabeçalho de assinatura é analisado corretamente: t=timestamp,v1=signature

Erros de timeout

  1. Responde no prazo de 30 segundos
  2. Move operações longas para processamento em segundo plano
  3. Devolve 200 de imediato e processa de forma assíncrona

Eventos duplicados

  1. Implementa idempotência com X-Webhook-Delivery-Id
  2. Verifica attemptNumber para novas tentativas
  3. Guarda os IDs de entrega processados numa base de dados