SendGrid: como funciona a entrega de webhooks

O SendGrid assina com ECDSA P-256, não com HMAC, num cabeçalho x-twilio-email. O formato verificado e um verificador Web Crypto.

Comportamento de entrega

Lido na documentação do próprio provedor, verificado pela última vez em 2026-08-06. Onde o provedor não informa um número, esta tabela também não traz nenhum.

Prazo de respostanão publicado pelo provedor
Novas tentativasnão publicado pelo provedor
Desistenão publicado pelo provedor

Assinatura

Verificada com um verificador funcional, comprovado por uma suíte de testes, e não lida na documentação. Última verificação em 2026-08-20.

AlgoritmoECDSA P-256
Payload assinado{timestamp}{body}
Codificaçãobase64
Cabeçalhox-twilio-email-event-webhook-signature
Tolerâncianenhuma exigida

Verifique a assinatura

O corpo bruto da requisição, byte a byte, antes de qualquer parsing de JSON. Todos os esquemas desta página quebram no momento em que um framework serializa o payload de novo.

// ECDSA P-256 over "{timestamp}{body}", signature and key both base64.
const b64 = (s) => Uint8Array.from(atob(s), (c) => c.charCodeAt(0));

const key = await crypto.subtle.importKey(
  "spki",
  b64(verificationKey), // Mail Settings → Signed Event Webhook
  { name: "ECDSA", namedCurve: "P-256" },
  false,
  ["verify"],
);
const ts = req.headers["x-twilio-email-event-webhook-timestamp"];
const valid = await crypto.subtle.verify(
  { name: "ECDSA", hash: "SHA-256" },
  key,
  b64(req.headers["x-twilio-email-event-webhook-signature"]),
  new TextEncoder().encode(ts + rawBody),
);

Armadilhas

Os cabeçalhos dizem x-twilio-email porque a Twilio é dona do SendGrid; o esquema é do próprio SendGrid e não tem nada em comum com o HMAC-SHA1 da Twilio. Um verificador que se guia só pelo prefixo do cabeçalho escolhe o algoritmo errado.

Leia também

O AnyHook fica entre SendGrid e seus endpoints: responde em cerca de um segundo, tenta de novo segundo um cronograma próprio quando seu servidor está fora do ar e guarda cada evento disponível para replay. Troque uma URL e mantenha seu código.

Como funciona →