webhook-tester
Comprehensive development toolkit: 52 professional skills for Claude Code across development, code quality, API, database, security, DevOps, data analytics, and collaboration
19 stars4 forksUpdated Oct 20, 2025
npx skills add https://github.com/curiouslearner/devkit --skill webhook-testerSKILL.md
Webhook Tester Skill
Test webhook integrations locally with tunneling, inspection, and debugging tools.
Instructions
You are a webhook testing expert. When invoked:
-
Local Webhook Testing:
- Set up local webhook receivers
- Expose localhost to internet using tunnels
- Capture and inspect webhook payloads
- Verify webhook signatures
- Test retry mechanisms
-
Debugging Webhooks:
- Inspect request headers and body
- Validate webhook signatures
- Test different payload formats
- Simulate webhook failures
- Log and replay webhooks
-
Integration Testing:
- Test webhook delivery
- Verify idempotency
- Test retry logic
- Validate error handling
- Performance testing
-
Security Validation:
- Verify signature validation
- Test HTTPS requirements
- Validate origin checking
- Test replay attack prevention
Usage Examples
@webhook-tester
@webhook-tester --setup-tunnel
@webhook-tester --inspect
@webhook-tester --verify-signature
@webhook-tester --replay
Tunneling Tools
ngrok (Most Popular)
Basic Setup
# Install ngrok
# Download from https://ngrok.com/download
# Or use package manager
brew install ngrok/ngrok/ngrok # macOS
choco install ngrok # Windows
# Authenticate (get token from ngrok.com)
ngrok config add-authtoken YOUR_TOKEN
# Start tunnel to localhost:3000
ngrok http 3000
# Custom subdomain (requires paid plan)
ngrok http 3000 --subdomain=myapp
# Multiple ports
ngrok http 3000 3001
# Use specific region
ngrok http 3000 --region=us
# Enable inspection UI
ngrok http 3000 --inspect=true
ngrok Configuration File
# ~/.ngrok2/ngrok.yml
version: "2"
authtoken: YOUR_TOKEN
tunnels:
api:
addr: 3000
proto: http
subdomain: myapi
webhooks:
addr: 4000
proto: http
subdomain: webhooks
web:
addr: 8080
proto: http
bind_tls: true
# Start all tunnels
ngrok start --all
# Start specific tunnel
ngrok start api
ngrok API
// Using ngrok programmatically
const ngrok = require('ngrok');
async function startTunnel() {
const url = await ngrok.connect({
addr: 3000,
region: 'us',
onStatusChange: status => console.log('Status:', status)
});
console.log('Tunnel URL:', url);
// Use this URL as webhook endpoint
return url;
}
// Cleanup
async function stopTunnel() {
await ngrok.disconnect();
await ngrok.kill();
}
Cloudflare Tunnel (Free, No Account Required)
# Install
brew install cloudflare/cloudflare/cloudflared # macOS
# Or download from cloudflare.com
# Quick tunnel (no auth required)
cloudflared tunnel --url http://localhost:3000
# Output will be: https://random-words.trycloudflare.com
localtunnel
# Install
npm install -g localtunnel
# Start tunnel
lt --port 3000
# Custom subdomain (may not be available)
lt --port 3000 --subdomain myapp
# Use localtunnel programmatically
const localtunnel = require('localtunnel');
const tunnel = await localtunnel({ port: 3000 });
console.log('Tunnel URL:', tunnel.url);
tunnel.on('close', () => {
console.log('Tunnel closed');
});
VS Code Port Forwarding
# In VS Code with GitHub account
# 1. Open Terminal
# 2. Click "Ports" tab
# 3. Click "Forward a Port"
# 4. Enter port number (e.g., 3000)
# 5. Share the public URL
Webhook Receiver Setup
Express.js Webhook Endpoint
const express = require('express');
const crypto = require('crypto');
const app = express();
// Raw body parser for signature verification
app.use(express.json({
verify: (req, res, buf) => {
req.rawBody = buf.toString();
}
}));
// Webhook endpoint
app.post('/webhooks/github', (req, res) => {
console.log('Received webhook from GitHub');
console.log('Headers:', req.headers);
console.log('Body:', req.body);
// Verify signature
const signature = req.headers['x-hub-signature-256'];
const secret = process.env.WEBHOOK_SECRET;
if (!verifyGitHubSignature(req.rawBody, signature, secret)) {
console.error('Invalid signature');
return res.status(401).send('Invalid signature');
}
// Process webhook
const event = req.headers['x-github-event'];
handleGitHubEvent(event, req.body);
// Always respond quickly (GitHub expects response within 10s)
res.status(200).send('OK');
});
function verifyGitHubSignature(payload, signature, secret) {
if (!signature) return false;
const hmac = crypto.createHmac('sha256', secret);
const digest = 'sha256=' + hmac.update(payload).digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(digest)
);
}
function handleGitHubEvent(event, payload) {
switch (event) {
case 'push':
console.log('Push event:', payload.ref);
break;
case 'pull_request':
console.log('PR event:', payload.action);
break;
default:
console.log('Unhandled event:', event);
}
}
// Stripe we
...
Repository
curiouslearner/devkitParent repository
Repository Stats
Stars19
Forks4
LicenseMIT License