You enabled Signed Event Webhook Requests, copied the key from the dashboard, and your verification code never passes. The usual reason is structural: almost every webhook provider signs with HMAC-SHA256 and a shared secret, so that's what most verifier snippets assume — but SendGrid signs with ECDSA, an asymmetric algorithm. SendGrid keeps a private key, you get the public Verification Key, and no HMAC routine can ever reproduce the signature no matter which key you feed it.
With signing enabled (Settings → Mail Settings → Signed Event Webhook Requests — SendGrid generates the key pair for you), every event POST carries two extra headers:
| Header | Contents |
|---|---|
X-Twilio-Email-Event-Webhook-Signature | base64, DER-encoded ECDSA signature (a SEQUENCE of the two integers r, s) |
X-Twilio-Email-Event-Webhook-Timestamp | timestamp string that was prepended to the payload before signing |
The signed content is timestamp + raw body — SHA-256
hashed, then signed with the private half of a P-256
(prime256v1 / secp256r1) key. Your Verification Key is the
public half, shipped as base64-encoded DER (SPKI) — without PEM framing.
@sendgrid/eventwebhook for Node,
sendgrid-go's helpers/eventwebhook, and equivalents in the
other SendGrid SDKs) wrap this correctly.-----BEGIN PUBLIC KEY----- / -----END PUBLIC KEY----- lines;
and if you rotate the key in the dashboard, deliveries signed with the old key stop
verifying immediately.timestamp + body, concatenated with no separator. Verifying the body alone
fails even with the right key and perfect bytes.crypto.verify accepts DER natively, but
WebCrypto (crypto.subtle.verify) wants the raw 64-byte
r||s (P1363) form — you must convert, or every valid signature reads as
invalid.Because the Verification Key is public, you can safely paste it into tools — there's nothing to leak. Two fast paths:
A useful corollary of signing timestamp + body (and not the URL):
relayed and replayed deliveries keep verifying, because Hookden
re-delivers the original bytes and headers unchanged.
Note the same ECDSA mechanism is available for the Inbound Parse webhook's signature verification — the checks above apply there too.
Related: Mailgun (the other email provider with a scheme HMAC testers can't handle), Stripe signature verification failed (timestamp-prefixed HMAC — what most snippets assume), and a realistic SendGrid event payload you can open in a live bin.
No signup needed. Or from your terminal: curl https://hookden.pages.dev/new
← All guides · Signature debugger · Payload examples · Docs · Hookden vs webhook.site