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:

    Field Description
    Name Friendly name for the webhook
    URL Your endpoint URL (HTTPS required)
    Secret Auto-generated for signature verification
  4. 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
  5. Click Create

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 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

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

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)
}

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.

  • 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