SendGrid → HookGet
SendGrid calls HookGet; the request is verified at the door and becomes normalised events on the same pipeline as everything else you deliver.
In short
- Verifies SendGrid’s ECDSA P-256 signature: timestamp + raw body, exactly as their libraries do — plus a 10-minute replay window they do not enforce.
- One SendGrid POST carries many events; each becomes its own normalised event.
- The recipient address stays in the raw payload — it is PII and never becomes a groupable attribute.
sg_event_idis the idempotency key, so SendGrid retries never duplicate.
What it produces
| SendGrid sends | Becomes | Data |
|---|---|---|
| processed | email.queued | — |
| delivered | email.delivered | — |
| open / click | email.opened / email.clicked | — |
| bounce / dropped | email.bounced / email.dropped | bounce_type |
| spamreport | email.complained | — |
| unsubscribe, group_unsubscribe | email.unsubscribed | asm_group_id |
Set up
# In SendGrid: Settings → Mail Settings → Event Webhook → enable "Signed Event Webhook"
# Copy the VERIFICATION KEY (a base64 public key), then:
curl -X POST https://api.hookget.com/v1/sources \
-H "authorization: Bearer $HOOKGET_KEY" \
-d '{"provider":"sendgrid","secret":"<the verification key>"}'
# → point the Event Webhook URL at the returned ingest path
Stated plainly
The "secret" you store is SendGrid’s public key — only SendGrid holds the private half, which is exactly what makes the signature worth verifying. SendGrid’s own tooling enforces no replay window; we add a 10-minute one, so a captured request cannot be replayed later.
Questions
Why do I paste a key from SendGrid instead of pasting yours into SendGrid?
Because SendGrid signs with its own key pair. Verification needs their public key on our side; there is nothing of ours to paste into theirs.
Does one email produce several events?
Yes — queued, delivered, opened, clicked each arrive separately, sharing the same
sg_message_id as their entity, so you can follow one message across its life.