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:
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¶
- Go to the Webhooks tab in the Redact dashboard
- Click Add Webhook
- Enter your endpoint URL
- Optionally enter a secret (recommended for production)
- 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¶
Disable / Enable¶
PATCH /api/redact/{workspace_id}/webhooks/{webhook_id}
Content-Type: application/json
{ "is_active": false }
Delete¶
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/jsonandUser-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.