← Developers
Level 3: events API

Webhooks

Outbound webhooks are emitted for threat.detected, config.published, config.failed, list.updated, feed.polled and device.registered. Each delivery is signed with HMAC-SHA256 over the raw body, sent in X-Securd-Signature as sha256=<hex>. Delivery is attempted three times with backoff.

Configuration and reference code for Webhooks

Python receiver

receiver.py
# receiver.py (FastAPI). Verify X-Securd-Signature before trusting the body.
import hmac, hashlib, os
from fastapi import FastAPI, Request, HTTPException

app = FastAPI()
SECRET = os.environ["SECURD_WEBHOOK_SECRET"]

def verify(raw: bytes, header: str) -> bool:
    expected = "sha256=" + hmac.new(SECRET.encode(), raw, hashlib.sha256).hexdigest()
    return hmac.compare_digest(expected, header or "")

@app.post("/securd/events")
async def securd_events(request: Request):
    raw = await request.body()
    if not verify(raw, request.headers.get("X-Securd-Signature", "")):
        raise HTTPException(status_code=401)
    event = await request.json()
    # Envelope: {"event": ..., "timestamp": ..., "data": {...}}
    # event["event"] is one of:
    # threat.detected, config.published, config.failed,
    # list.updated, feed.polled, device.registered
    print(event["event"], event["data"])
    return {"ok": True}

Node receiver

receiver.ts
// receiver.ts (Express). Verify X-Securd-Signature before trusting the body.
import express from "express";
import { createHmac, timingSafeEqual } from "node:crypto";

const app = express();
const SECRET = process.env.SECURD_WEBHOOK_SECRET!;

app.post("/securd/events", express.raw({ type: "*/*" }), (req, res) => {
  const expected = "sha256=" + createHmac("sha256", SECRET).update(req.body).digest("hex");
  const given = String(req.header("X-Securd-Signature") ?? "");
  const ok = expected.length === given.length && timingSafeEqual(Buffer.from(expected), Buffer.from(given));
  if (!ok) return res.sendStatus(401);
  const event = JSON.parse(req.body.toString("utf8"));
  console.log(event.event, event);
  res.json({ ok: true });
});

app.listen(8080);

Register the endpoint

register.sh
curl -s https://control.securd.com/api/v1/gateway/webhooks \
  -H "Authorization: Bearer $TOKEN" -H "X-Tenant-UUID: $TENANT" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "soc-events",
    "url": "https://hooks.example.com/securd/events",
    "events": ["threat.detected", "list.updated", "config.failed"]
  }'

Chat-based review

Post threat.detected to a channel with the policy, hostname and categories, with an action that calls the approve or block endpoint. This places the review queue in the tool the team already monitors.

Evaluate Agent DNS with your own agent traffic

Deploy on a single policy in learning mode and review the recorded destinations with your team.