Boas práticas de webhooks
Responda rápido, processe depois
Seção intitulada “Responda rápido, processe depois”Verifique a assinatura, enfileire o evento (linha no banco de dados, fila, job em segundo plano) e retorne 2xx imediatamente. O SpacePost espera no máximo 15 segundos, e um handler lento vira novas tentativas e duplicatas.
Seja idempotente
Seção intitulada “Seja idempotente”A entrega é feita pelo menos uma vez. Guarde o webhook-id de cada entrega processada (uma constraint de unicidade basta) e ignore as repetidas.
const inserted = await db.insert(processedWebhooks).values({ id: webhookId }).onConflictDoNothing().returning();if (inserted.length === 0) return new Response("duplicate", { status: 200 });Sempre verifique as assinaturas
Seção intitulada “Sempre verifique as assinaturas”Use o corpo bruto, rejeite horários com mais de 5 minutos de diferença, compare as assinaturas em tempo constante (o SDK e as bibliotecas já fazem isso). Veja Verificar assinaturas.
Não confie na ordem
Seção intitulada “Não confie na ordem”Os eventos podem chegar fora de ordem, principalmente depois de novas tentativas. Compare o created_at do payload com o que você tem armazenado e aplique apenas as mudanças que fazem o estado avançar. O próprio last_event do SpacePost segue a mesma regra.
Aja sobre os eventos que importam
Seção intitulada “Aja sobre os eventos que importam”| Evento | Ação típica |
|---|---|
email.bounced |
Marque o endereço como inválido no seu banco de dados; pare de enviar para ele. |
email.complained |
Cancele imediatamente a inscrição do usuário em e-mails não essenciais. |
email.delivery_delayed |
Em geral, nada; alerte se for um e-mail crítico em termos de tempo (redefinição de senha). |
email.failed |
Registre data.failed.reason em log, alerte e, se possível, tente de novo com uma correção. |
email.suppressed |
Um destinatário estava na sua lista de supressão; mostre isso na sua interface de administração. |
Assine apenas os eventos que você trata. Menos eventos significam menos tráfego e menos falhas.
Proteja o endpoint
Seção intitulada “Proteja o endpoint”- Sirva por HTTPS com um certificado válido.
- Não registre segredos nem payloads completos com dados pessoais em logs.
- Use um caminho dedicado, sem outro comportamento, e retorne um corpo genérico.
- Guarde o
signing_secretem um gerenciador de segredos, não no controle de versão.
Monitore
Seção intitulada “Monitore”Acompanhe o log de entregas no painel ou crie alertas para falhas repetidas: se o seu endpoint ficar fora do ar por mais de cerca de 27 horas, todas as novas tentativas se esgotam, e depois disso você precisa fazer o reenvio manualmente.