Webhook Integration
Send detection events to your own endpoints for custom processing, SIEM integration, or automation workflows.
Use Cases
Section titled “Use Cases”- Forward events to your SIEM (Splunk, Elastic, etc.)
- Trigger custom automation workflows
- Send to incident management (PagerDuty, Opsgenie)
- Log to your own database
- Integrate with internal security tools
- Build custom dashboards
Creating a Webhook
Section titled “Creating a Webhook”-
Go to Integrations → Webhooks
-
Click Add Webhook
-
Configure:
Field Description Name Friendly name for the webhook URL Your endpoint URL (HTTPS required) Secret Auto-generated for signature verification -
Configure triggers:
Trigger Description On Detection Every new detection On High Risk Only high-scoring detections (70+) On Rule Enforced When an integration blocks an IP -
Click Create
Webhook Payload
Section titled “Webhook Payload”Your endpoint receives JSON payloads via POST request:
{ "event_type": "detection.created", "timestamp": "2025-01-15T10:30:00Z", "detection": { "id": "det_abc123", "source": "decoy_link", "source_name": "Admin Backup Trap", "ip_address": "192.168.1.100", "user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)...", "request_path": "/admin/backup.zip", "request_method": "GET", "threat_score": 85, "threat_level": "CRITICAL", "bot_score": 92, "mitre_tactic": { "id": "TA0043", "name": "Reconnaissance" }, "mitre_technique": { "id": "T1595", "name": "Active Scanning" }, "geoip": { "country": "US", "country_code": "US", "city": "New York", "region": "NY", "latitude": 40.7128, "longitude": -74.0060, "asn": 12345, "org": "Example ISP" }, "is_vpn": false, "is_proxy": false, "is_tor": false, "is_datacenter": true }, "organization_id": "org_xyz789", "property_id": "prop_def456"}Event Types
Section titled “Event Types”| Event Type | Description |
|---|---|
detection.created | New detection recorded |
detection.high_risk | High-risk detection (score >= 70) |
integration.ip_blocked | IP was blocked by an integration |
integration.ip_unblocked | IP was unblocked |
Request Headers
Section titled “Request Headers”Every webhook request includes these headers:
| Header | Description |
|---|---|
Content-Type | application/json |
X-WebDecoy-Signature | HMAC signature for verification |
X-WebDecoy-Event | Event type (e.g., detection.created) |
X-WebDecoy-Delivery | Unique delivery ID |
User-Agent | WebDecoy-Webhook/1.0 |
Signature Verification
Section titled “Signature Verification”Verify webhooks are from WebDecoy using the signature header:
X-WebDecoy-Signature: sha256=abc123def456...Verification in Node.js
Section titled “Verification in Node.js”const crypto = require('crypto');
function verifyWebhookSignature(payload, signature, secret) { const expected = crypto .createHmac('sha256', secret) .update(payload, 'utf8') .digest('hex');
return `sha256=${expected}` === signature;}
// Express middlewareapp.post('/webhook', express.raw({ type: 'application/json' }), (req, res) => { const signature = req.headers['x-webdecoy-signature']; const payload = req.body.toString();
if (!verifyWebhookSignature(payload, signature, process.env.WEBHOOK_SECRET)) { return res.status(401).send('Invalid signature'); }
const event = JSON.parse(payload); // Process event...
res.status(200).send('OK');});Verification in Python
Section titled “Verification in Python”import hmacimport hashlib
def verify_webhook_signature(payload: bytes, signature: str, secret: str) -> bool: expected = hmac.new( secret.encode('utf-8'), payload, hashlib.sha256 ).hexdigest()
return f'sha256={expected}' == signature
# Flask example@app.route('/webhook', methods=['POST'])def webhook(): signature = request.headers.get('X-WebDecoy-Signature') payload = request.get_data()
if not verify_webhook_signature(payload, signature, WEBHOOK_SECRET): return 'Invalid signature', 401
event = request.get_json() # Process event...
return 'OK', 200Verification in Go
Section titled “Verification in Go”package main
import ( "crypto/hmac" "crypto/sha256" "encoding/hex" "fmt" "io" "net/http")
func verifySignature(payload []byte, signature, secret string) bool { mac := hmac.New(sha256.New, []byte(secret)) mac.Write(payload) expected := "sha256=" + hex.EncodeToString(mac.Sum(nil)) return hmac.Equal([]byte(expected), []byte(signature))}
func webhookHandler(w http.ResponseWriter, r *http.Request) { payload, _ := io.ReadAll(r.Body) signature := r.Header.Get("X-WebDecoy-Signature")
if !verifySignature(payload, signature, webhookSecret) { http.Error(w, "Invalid signature", http.StatusUnauthorized) return }
// Process event... w.WriteHeader(http.StatusOK)}Retry Policy
Section titled “Retry Policy”WebDecoy retries failed webhook deliveries:
| Attempt | Delay |
|---|---|
| 1 | Immediate |
| 2 | 1 minute |
| 3 | 5 minutes |
| 4 | 30 minutes |
| 5 | 2 hours |
Success criteria: HTTP 2xx response within 30 seconds
After 5 failed attempts, the delivery is marked as failed and no further retries are attempted.
Best Practices
Section titled “Best Practices”- ✅ Verify signatures in production
- ✅ Return 200 quickly - process events asynchronously
- ✅ Handle duplicates - use delivery ID for deduplication
- ✅ Log failures for debugging
- ✅ Use HTTPS (required)
Don’ts
Section titled “Don’ts”- ❌ Process events synchronously (causes timeouts)
- ❌ Skip signature verification
- ❌ Return errors for events you want to ignore
- ❌ Expose webhook URL publicly
Recommended Architecture
Section titled “Recommended Architecture”WebDecoy Webhook │ ▼Your Webhook Endpoint │ ├── Verify signature ├── Return 200 immediately └── Queue event for processing │ ▼ Background Worker │ ├── Process event ├── Forward to SIEM └── Trigger automationTesting Webhooks
Section titled “Testing Webhooks”Test from WebDecoy
Section titled “Test from WebDecoy”- Go to Integrations → Webhooks
- Find your webhook
- Click Test
- A test event is sent to your endpoint
- View delivery status and response
Local Development
Section titled “Local Development”Use a tunneling service to test locally:
# Using ngrokngrok http 3000
# Your webhook URL becomes:# https://abc123.ngrok.io/webhookTroubleshooting
Section titled “Troubleshooting”Webhook Not Receiving Events
Section titled “Webhook Not Receiving Events”- Verify webhook is enabled
- Check URL is correct and accessible
- Ensure HTTPS is used
- Check trigger settings match expected events
- View delivery logs in WebDecoy
Signature Verification Failing
Section titled “Signature Verification Failing”- Ensure you’re using the raw request body (not parsed JSON)
- Check secret matches exactly (no extra whitespace)
- Verify encoding is UTF-8
- Check signature header name is correct
Timeouts
Section titled “Timeouts”- Return 200 before processing
- Move heavy processing to background jobs
- Increase endpoint timeout if possible
Next Steps
Section titled “Next Steps”- Cloudflare - Automatic IP blocking
- Slack - Real-time notifications
- Overview - All integrations