Skip to content

Webhooks

Redact can notify your systems in real time when leakage is detected in an LLM response. Instead of discovering leakage events in the vault days later, your security team or SIEM receives an HTTP callback the moment it happens.


Supported Events

Event Trigger
leakage.detected A real PII value was found in the LLM response and scrubbed before returning to the agent

Payload Format

{
  "event": "leakage.detected",
  "workspace_id": "a1b2c3d4e5f6...",
  "leaked_count": 3,
  "timestamp": "2026-05-22T10:30:00"
}
Field Type Description
event string Always "leakage.detected"
workspace_id string The workspace where leakage was detected
leaked_count integer Number of real values found in the LLM response
timestamp string ISO 8601 UTC timestamp of the detection

HMAC Signature Verification

If you configure a webhook secret, every request includes an X-Xybern-Signature header:

X-Xybern-Signature: sha256=a3f9c2b1d4e8f7...

The signature is HMAC-SHA256(secret, request_body). Verify it on your server to confirm the request came from Xybern:

import hmac
import hashlib
from flask import Flask, request, abort

app = Flask(__name__)
WEBHOOK_SECRET = "your-webhook-secret"

@app.route("/hook", methods=["POST"])
def handle_webhook():
    sig_header = request.headers.get("X-Xybern-Signature", "")
    expected = "sha256=" + hmac.new(
        WEBHOOK_SECRET.encode(),
        request.data,
        hashlib.sha256,
    ).hexdigest()

    if not hmac.compare_digest(sig_header, expected):
        abort(403)

    payload = request.get_json()
    print(f"Leakage detected: {payload['leaked_count']} values in workspace {payload['workspace_id']}")
    return "", 200
const crypto = require("crypto");
const express = require("express");

const app = express();
const WEBHOOK_SECRET = "your-webhook-secret";

app.post("/hook", express.raw({ type: "application/json" }), (req, res) => {
  const sig = req.headers["x-xybern-signature"] || "";
  const expected = "sha256=" + crypto
    .createHmac("sha256", WEBHOOK_SECRET)
    .update(req.body)
    .digest("hex");

  if (!crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(expected))) {
    return res.status(403).send("Invalid signature");
  }

  const payload = JSON.parse(req.body);
  console.log(`Leakage: ${payload.leaked_count} values in ${payload.workspace_id}`);
  res.status(200).send("ok");
});

Creating a Webhook

Via Dashboard

  1. Go to the Webhooks tab in the Redact dashboard
  2. Click Add Webhook
  3. Enter your endpoint URL
  4. Optionally enter a secret (recommended for production)
  5. Click Add Webhook

The webhook is active immediately.

Via API

curl -X POST https://www.xybern.com/api/redact/{workspace_id}/webhooks \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://your-server.com/redact-hook",
    "secret": "your-webhook-secret",
    "events": ["leakage.detected"]
  }'

Response:

{
  "ok": true,
  "webhook": {
    "id": "wh_a1b2c3...",
    "url": "https://your-server.com/redact-hook",
    "has_secret": true,
    "events": ["leakage.detected"],
    "is_active": true,
    "created_at": "2026-05-22T10:00:00"
  }
}

Managing Webhooks

List

GET /api/redact/{workspace_id}/webhooks

Disable / Enable

PATCH /api/redact/{workspace_id}/webhooks/{webhook_id}
Content-Type: application/json

{ "is_active": false }

Delete

DELETE /api/redact/{workspace_id}/webhooks/{webhook_id}

Delivery Behaviour

  • Webhooks are fired fire-and-forget in a background thread. They do not block the proxy response.
  • Timeout: 10 seconds per delivery attempt.
  • No retries. If your endpoint is down, the delivery is lost. Use the vault to audit missed events retrospectively.
  • Redact sends Content-Type: application/json and User-Agent: Xybern-Redact/4.0.

Routing to SIEM or PagerDuty

Point the webhook URL at a relay service (Zapier, Make, Pipedream) to fan out to Slack, PagerDuty, Splunk, or any SIEM without custom code on your side.