← ClaudeAtlas

webhookslisted

Webhook patterns for sending and receiving. Signature verification, retry logic, idempotency, payload design, and webhook infrastructure. Covers Stripe, GitHub, Slack webhook consumption and custom webhook dispatch. USE WHEN: user mentions "webhook", "webhook endpoint", "webhook signature", "event callback", "HTTP callback", "webhook retry", "webhook dispatch" DO NOT USE FOR: WebSocket real-time - use `socket-io` or `sse`; message queues - use messaging skills
claude-dev-suite/claude-dev-suite · ★ 33 · AI & Automation · score 80
Install: claude install-skill claude-dev-suite/claude-dev-suite
# Webhooks ## Receiving Webhooks ### Express (with signature verification) ```typescript app.post('/webhooks/stripe', express.raw({ type: 'application/json' }), (req, res) => { const signature = req.headers['stripe-signature']!; const event = stripe.webhooks.constructEvent(req.body, signature, WEBHOOK_SECRET); // Idempotency: check if already processed const existing = await db.webhookEvent.findUnique({ where: { eventId: event.id } }); if (existing) return res.json({ received: true }); // Process switch (event.type) { case 'checkout.session.completed': await fulfillOrder(event.data.object); break; } // Mark as processed await db.webhookEvent.create({ data: { eventId: event.id, type: event.type } }); res.json({ received: true }); }); ``` ### Generic HMAC Verification ```typescript import { createHmac, timingSafeEqual } from 'crypto'; function verifyWebhookSignature(payload: string, signature: string, secret: string): boolean { const expected = createHmac('sha256', secret).update(payload).digest('hex'); return timingSafeEqual(Buffer.from(signature), Buffer.from(`sha256=${expected}`)); } app.post('/webhooks/github', express.raw({ type: '*/*' }), (req, res) => { const sig = req.headers['x-hub-signature-256'] as string; if (!verifyWebhookSignature(req.body.toString(), sig, GITHUB_SECRET)) { return res.status(401).json({ error: 'Invalid signature' }); } // Process event... res.status(200).json({ received: true }); })