Webhooks Guide: Testing, Debugging & Best Practices
Complete guide to configuring webhook providers, testing webhooks, verifying signatures, and debugging issues.
#How It Works
FetchHook acts as a mailbox for webhooks. Configure providers to send to your webhook URL, FetchHook stores them, then fetch on demand using your API key.
- **Provision**: Get webhook URL and API key
- **Configure**: Point providers to your webhook URL
- **Receive**: Services send webhooks, FetchHook stores them
- **Fetch**: Pull webhooks using API whenever ready
- **Process**: Handle webhook data in your application
#Configure Stripe
Go to Stripe Dashboard → Developers → Webhooks → Add endpoint. Paste your FetchHook webhook URL, select events, and save the webhook signing secret.
Stripe Configuration
# Your FetchHook webhook URL
https://webhook.fetchhook.app/{SOURCE_ID}
# Select events (examples):
- payment_intent.succeeded
- charge.succeeded
- customer.created
# Save the webhook signing secret for verification#Configure GitHub
Go to Repository → Settings → Webhooks → Add webhook. Paste your webhook URL, set content type to JSON, choose events, and copy the secret token.
GitHub Configuration
# Your FetchHook webhook URL
https://webhook.fetchhook.app/{SOURCE_ID}
# Content type: application/json
# Events (examples):
- push
- pull_request
- issues
- release
# Copy the secret token for signature verification#Testing Webhooks
Send test webhooks using cURL or provider test modes before going live.
Send Test Webhook
curl -X POST https://webhook.fetchhook.app/{SOURCE_ID} \
-H "Content-Type: application/json" \
-d '{
"event": "test.webhook",
"timestamp": "2024-01-15T14:30:00Z",
"data": {"message": "Hello from test!"}
}'
# Then fetch to verify
curl https://api.fetchhook.app/api/v1/{SOURCE_ID} \
-H "Authorization: Bearer {YOUR_API_KEY}"#Verify Stripe Signature
Always verify webhook signatures to ensure requests are authentic. FetchHook preserves all headers including signatures.
Stripe Signature Verification
import stripe
import hmac
import hashlib
def verify_stripe_signature(payload, sig_header, secret):
elements = sig_header.split(',')
timestamp = elements[0].split('=')[1]
signature = elements[1].split('=')[1]
signed_payload = f"{timestamp}.{payload}"
expected = hmac.new(
secret.encode(),
signed_payload.encode(),
hashlib.sha256
).hexdigest()
return hmac.compare_digest(expected, signature)
# Usage with FetchHook
webhook = fetch_webhooks()[0]
sig_header = webhook['headers']['stripe-signature']
payload = json.dumps(webhook['payload'])
if verify_stripe_signature(payload, sig_header, STRIPE_WEBHOOK_SECRET):
print("✓ Signature valid!")
else:
print("✗ Invalid signature")#Verify GitHub Signature
GitHub uses HMAC SHA-256 signatures. Verify before processing to prevent spoofing.
GitHub Signature Verification
const crypto = require('crypto');
function verifyGitHubSignature(payload, signature, secret) {
const hmac = crypto.createHmac('sha256', secret);
const digest = 'sha256=' + hmac.update(payload).digest('hex');
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(digest)
);
}
// Usage with FetchHook
const webhook = webhooks[0];
const signature = webhook.headers['x-hub-signature-256'];
const payload = JSON.stringify(webhook.payload);
if (verifyGitHubSignature(payload, signature, GITHUB_SECRET)) {
console.log('✓ Signature valid!');
}#Debugging Webhooks
Check webhook delivery in provider dashboards, inspect headers preserved by FetchHook, and validate JSON payloads.
Inspect Headers
webhook = fetch_webhooks()[0]
print("Headers received:")
for header, value in webhook['headers'].items():
print(f" {header}: {value}")
# Common headers:
# - content-type: Should be application/json
# - user-agent: Identifies sender
# - *-signature: For verification
# - x-request-id: Unique identifierAgent Protocol Instruction