hookdeck/webhook-skills

sendgrid-webhooks

Receive and verify SendGrid webhooks. Use when setting up SendGrid webhook handlers, debugging signature verification, or handling email delivery events.

First seen Feb 5, 2026

Installation

$ npx skills add hookdeck/webhook-skills --skill sendgrid-webhooks

Similar popular skills

Related neighbors and high-traction skills in the same topics — useful to compare before installing.

Also in this package

Other skills from hookdeck/webhook-skills · top by installs.

npx skills add hookdeck/webhook-skills

Browse all from hookdeck/webhook-skills

More details

Agent compatibility

Declared targets from SKILL.md / docs. Unmarked agents are not listed — the skill may still install via the CLI.

Claude Code Not declared
Cursor Not declared
Codex Not declared
GitHub Copilot Not declared
Windsurf Not declared
Gemini CLI Not declared
Cline Not declared
OpenCode Not declared

Repository health

Stars 84
License LICENSE
Default branch main
Open issues 6
Status Active

Skill metadata

Parsed from SKILL.md frontmatter.

Version0.1.0
LicenseMIT
More metadata
author
hookdeck
version
0.1.0
repository
https://github.com/hookdeck/webhook-skills

Package contents

Files included with this skill beyond the listing page.

  • skill md SKILL.md 4,992 B
  • docs SUMMARY.md 178 B

History

  1. First seen on skills.sh
  2. First recorded snapshot · 239 installs

SKILL.md

SendGrid Webhooks

When to Use This Skill

  • Setting up SendGrid webhook handlers for email delivery tracking
  • Debugging ECDSA signature verification failures
  • Processing email events (bounce, delivered, open, click, spam report)
  • Implementing email engagement analytics

Essential Code

Signature Verification (Manual)

SendGrid uses ECDSA (Elliptic Curve Digital Signature Algorithm) with public key verification.

// Node.js manual verification
const crypto = require('crypto');

function verifySignature(publicKey, payload, signature, timestamp) {
  // Decode the base64 signature
  const decodedSignature = Buffer.from(signature, 'base64');

  // Create the signed content
  const signedContent = timestamp + payload;

  // Create verifier
  const verifier = crypto.createVerify('sha256');
  verifier.update(signedContent);

  // Add PEM headers if not present
  let pemKey = publicKey;
  if (!pemKey.includes('BEGIN PUBLIC KEY')) {
    pemKey = `-----BEGIN PUBLIC KEY-----\n${publicKey}\n-----END PUBLIC KEY-----`;
  }

  // Verify the signature
  return verifier.verify(pemKey, decodedSignature);
}

// Express middleware
app.post('/webhooks/sendgrid', express.raw({ type: 'application/json' }), (req, res) => {
  const signature = req.get('X-Twilio-Email-Event-Webhook-Signature');
  const timestamp = req.get('X-Twilio-Email-Event-Webhook-Timestamp');

  if (!signature || !timestamp) {
    return res.status(400).send('Missing signature headers');
  }

  const publicKey = process.env.SENDGRID_WEBHOOK_VERIFICATION_KEY;
  const payload = req.body.toString();

  if (!verifySignature(publicKey, payload, signature, timestamp)) {
    return res.status(400).send('Invalid signature');
  }

  // Process events
  const events = JSON.parse(payload);
  console.log(`Received ${events.length} events`);

  res.sendStatus(200);
});

Using SendGrid SDK

const { EventWebhook } = require('@sendgrid/eventwebhook');

const verifyWebhook = new EventWebhook();
const publicKey = process.env.SENDGRID_WEBHOOK_VERIFICATION_KEY;

app.post('/webhooks/sendgrid', express.raw({ type: 'application/json' }), (req, res) => {
  const signature = req.get('X-Twilio-Email-Event-Webhook-Signature');
  const timestamp = req.get('X-Twilio-Email-Event-Webhook-Timestamp');

  const isValid = verifyWebhook.verifySignature(
    publicKey,
    req.body,
    signature,
    timestamp
  );

  if (!isValid) {
    return res.status(400).send('Invalid signature');
  }

  // Process webhook
  res.sendStatus(200);
});

Common Event Types

Event Description Use Cases
processed Message has been received and is ready to be delivered Track email processing
delivered Message successfully delivered to recipient Delivery confirmation
bounce Message permanently rejected (includes type='blocked' for blocked messages) Update contact lists, handle failures
deferred Temporary delivery failure Monitor delays
open Recipient opened the email Engagement tracking
click Recipient clicked a link Link tracking, CTR analysis
spam report Email marked as spam List hygiene, sender reputation
unsubscribe Recipient unsubscribed Update subscription status
group unsubscribe Recipient unsubscribed from a group Update group subscription preferences
group resubscribe Recipient resubscribed to a group Update group subscription preferences

Environment Variables

# Your SendGrid webhook verification key (public key)
SENDGRID_WEBHOOK_VERIFICATION_KEY="MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE..."

Local Development

For local webhook testing, use Hookdeck CLI:

npx hookdeck-cli listen 3000 sendgrid --path /webhooks/sendgrid

No account required. Provides local tunnel + web UI for inspecting requests.

Resources

  • [overview.md](references/overview.md) - What SendGrid webhooks are, common event types
  • [setup.md](references/setup.md) - Configure webhooks in SendGrid dashboard, get verification key
  • [verification.md](references/verification.md) - ECDSA signature verification details and gotchas
  • [examples/](examples/) - Complete implementations for Express, Next.js, and FastAPI

Related Skills

  • webhook-handler-patterns - Cross-cutting patterns (idempotency, retries, framework guides)
  • hookdeck-event-gateway - Webhook infrastructure that replaces your queue — guaranteed delivery, automatic retries, replay, rate limiting, and observability for your webhook handlers