Skip to content

Webhook Integration

Send detection events to your own endpoints for custom processing, SIEM integration, or automation workflows.

  • 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
  1. Go to Integrations → Webhooks

  2. Click Add Webhook

  3. Configure:

    FieldDescription
    NameFriendly name for the webhook
    URLYour endpoint URL (HTTPS required)
    SecretAuto-generated for signature verification
  4. Configure triggers:

    TriggerDescription
    On DetectionEvery new detection
    On High RiskOnly high-scoring detections (70+)
    On Rule EnforcedWhen an integration blocks an IP
  5. Click Create

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 TypeDescription
detection.createdNew detection recorded
detection.high_riskHigh-risk detection (score >= 70)
integration.ip_blockedIP was blocked by an integration
integration.ip_unblockedIP was unblocked

Every webhook request includes these headers:

HeaderDescription
Content-Typeapplication/json
X-WebDecoy-SignatureHMAC signature for verification
X-WebDecoy-EventEvent type (e.g., detection.created)
X-WebDecoy-DeliveryUnique delivery ID
User-AgentWebDecoy-Webhook/1.0

Verify webhooks are from WebDecoy using the signature header:

X-WebDecoy-Signature: sha256=abc123def456...
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 middleware
app.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');
});
import hmac
import 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', 200
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)
}

WebDecoy retries failed webhook deliveries:

AttemptDelay
1Immediate
21 minute
35 minutes
430 minutes
52 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.

  • Verify signatures in production
  • Return 200 quickly - process events asynchronously
  • Handle duplicates - use delivery ID for deduplication
  • Log failures for debugging
  • Use HTTPS (required)
  • ❌ Process events synchronously (causes timeouts)
  • ❌ Skip signature verification
  • ❌ Return errors for events you want to ignore
  • ❌ Expose webhook URL publicly
WebDecoy Webhook
Your Webhook Endpoint
├── Verify signature
├── Return 200 immediately
└── Queue event for processing
Background Worker
├── Process event
├── Forward to SIEM
└── Trigger automation
  1. Go to Integrations → Webhooks
  2. Find your webhook
  3. Click Test
  4. A test event is sent to your endpoint
  5. View delivery status and response

Use a tunneling service to test locally:

Terminal window
# Using ngrok
ngrok http 3000
# Your webhook URL becomes:
# https://abc123.ngrok.io/webhook
  1. Verify webhook is enabled
  2. Check URL is correct and accessible
  3. Ensure HTTPS is used
  4. Check trigger settings match expected events
  5. View delivery logs in WebDecoy
  1. Ensure you’re using the raw request body (not parsed JSON)
  2. Check secret matches exactly (no extra whitespace)
  3. Verify encoding is UTF-8
  4. Check signature header name is correct
  1. Return 200 before processing
  2. Move heavy processing to background jobs
  3. Increase endpoint timeout if possible