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 (80+) 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": "detection", "timestamp": "2026-07-15T10:30:00Z", "detection": { "id": "det_abc123", "decoy_id": "decoy_uuid", "organization_id": "org_xyz789", "ip_address": "192.168.1.100", "user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)...", "bot_score": 92, "timestamp": "2026-07-15T10:30:00Z", "rules_enforced": true, "source": "decoy_link" }, "metadata": {}}The payload is deliberately compact — fetch the full enriched detection
(geo, signals, MITRE mapping, threat category) from
GET /organizations/{org}/detections/{id} using the detection.id.
Event Types
Section titled “Event Types”| Event | Description |
|---|---|
detection | New detection recorded |
high_risk_detection | High-risk detection (score ≥ 80) |
rule_enforced | A response action enforced against the detection (details in metadata) |
test | Sent by the Test button when configuring the webhook |
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) |
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)}Delivery Semantics
Section titled “Delivery Semantics”Each event is delivered once — there are currently no automatic retries. Your endpoint must respond within 10 seconds; a non-2xx response or a timeout is recorded as a failed delivery (visible on the webhook’s stats in the dashboard). Design your handler to return 200 immediately and process asynchronously.
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