What is signed
SendGrid's signed event webhook is opt-in. When you enable it in the webhook's security settings and save, SendGrid generates a key pair and shows you the public key. Each request then carries a signature header and a timestamp header. The signature is an ECDSA signature, base64 encoded, over a SHA-256 hash of the timestamp text followed by the payload exactly as received. You verify it with the public key, and SendGrid's own libraries for several languages provide helpers.
- Without enabling it, the endpoint receives unsigned requests that anyone could imitate.
- Turning the option off and saving deletes the key pair.
- The test button before saving does not exercise signature verification because no key exists yet.
Why the raw body matters
The documentation says the payload must be used in its raw bytes form, and that converting it to a JSON string may remove characters used when the signature was generated. In practice, many web frameworks parse JSON before your handler runs, and re-encoding the parsed object does not reproduce the original bytes: spacing, key order and escaping can differ. Verification then fails on genuine events, and developers who cannot see why switch the check off.
- Read the raw body before any parser touches it.
- Verify first, then parse.
- Keep the timestamp exactly as received, as text.
What a good endpoint does with a failure
A request that fails verification should return an error and change nothing: no database write, no flag on any address, no queued job. A request that passes should be stored once by event ID. The reply should be a 2xx only after the event is safely stored, because SendGrid retries unsuccessful deliveries for up to a rolling day and a quick but false success would lose the event.
- The pages read describe the timestamp as part of the signed content but give no replay window, so whether to refuse very old timestamps is a choice to agree and test; deduplicating on the event ID is the documented defence against repeats.
- Log that a request was rejected, without logging the full body.
- Alert if rejections suddenly rise; it can mean a rotated key or a changed proxy.
- Rotate by disabling and re-enabling signing, then updating the stored public key.
A test you can run
Create a small set of test requests signed with a key pair you generate for the test, not the production key: one genuine, one with a single byte changed in the body, one with the timestamp altered and one with no signature. Expect the first to be accepted and the others rejected with no database change. This proves your handling of bytes and failure, which the dashboard's test button cannot show.
How the paid outcome is accepted
The SendGrid outcome includes this check: a request with a wrong signature or altered body is rejected and the address flag is unchanged. The fixed £395 price is untested and payment follows the agreed checks and your sign-off. You hold the public key and every production credential; none is needed for the first enquiry.
Sources and limits
- SendGrid: Event Webhook security features Checked 2026-10-11.
- Signatures arrive in a signature header and a timestamp header and use ECDSA over a SHA-256 hash of the timestamp followed by the raw payload bytes.
- Signing is opt-in; the key pair is generated when it is enabled and saved.
- Converting the raw bytes to a JSON string may remove characters used in the signature.