Documentation Index
Fetch the complete documentation index at: https://docs.tuteliq.ai/llms.txt
Use this file to discover all available pages before exploring further.
Webhooks let you receive push notifications when safety events occur, so you can act on critical incidents without polling the API.
Registering a Webhook
curl -X POST https://api.tuteliq.ai/webhooks \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://yourapp.com/tuteliq/webhook",
"events": ["safety.critical", "safety.high"],
"description": "Production safety alerts"
}'
Response:
{
"id": "wh_abc123",
"url": "https://yourapp.com/tuteliq/webhook",
"events": ["safety.critical", "safety.high"],
"secret": "whsec_9f8a7b6c5d4e3f2a1b...",
"status": "active",
"created_at": "2026-02-16T10:00:00Z"
}
Store the secret value immediately. It is only returned once at creation time and is required to verify incoming webhook signatures.
Event Types
| Event | Description |
|---|
safety.critical | A critical-severity safety alert was triggered |
safety.high | A high-severity safety alert was triggered |
safety.medium | A medium-severity safety alert was triggered |
batch.completed | A batch analysis job has finished processing |
batch.failed | A batch analysis job has failed |
voice.alert | A safety alert was detected during voice streaming |
report.ready | A scheduled compliance report is ready |
Webhook Payload
Every webhook delivery is an HTTP POST with a JSON body:
{
"id": "evt_xyz789",
"type": "safety.critical",
"created_at": "2026-02-16T12:34:56Z",
"data": {
"analysis_id": "an_456def",
"category": "grooming",
"severity": "critical",
"risk_score": 0.96,
"summary": "High-confidence grooming pattern detected in text input.",
"input_preview": "hey sweetie, this is our little secret..."
}
}
Signature Verification
Every webhook request includes an X-Tuteliq-Signature header containing an HMAC-SHA256 signature of the raw request body, computed with your webhook secret.
Always verify this signature before processing the payload.
import crypto from "node:crypto";
function verifyWebhookSignature(rawBody, signatureHeader, secret) {
const expected = crypto
.createHmac("sha256", secret)
.update(rawBody, "utf-8")
.digest("hex");
return crypto.timingSafeEqual(
Buffer.from(signatureHeader),
Buffer.from(expected)
);
}
// Express / Fastify example
app.post("/tuteliq/webhook", (req, res) => {
const signature = req.headers["x-tuteliq-signature"];
const rawBody = req.rawBody; // ensure your framework preserves the raw body
if (!verifyWebhookSignature(rawBody, signature, process.env.TUTELIQ_WEBHOOK_SECRET)) {
return res.status(401).send("Invalid signature");
}
const event = JSON.parse(rawBody);
switch (event.type) {
case "safety.critical":
// Escalate immediately — alert moderators, pause user, etc.
handleCriticalAlert(event.data);
break;
case "safety.high":
handleHighAlert(event.data);
break;
case "batch.completed":
handleBatchComplete(event.data);
break;
}
res.status(200).send("OK");
});
Always use a constant-time comparison function (such as crypto.timingSafeEqual or hmac.compare_digest) to prevent timing attacks.
Retry Policy
If your endpoint returns a non-2xx status code or does not respond within 10 seconds, Tuteliq will retry the delivery:
| Attempt | Delay |
|---|
| 1st retry | 30 seconds |
| 2nd retry | 5 minutes |
| 3rd retry | 30 minutes |
After three failed retries, the event is marked as failed. You can view and replay failed deliveries from the dashboard or via the API.
Managing Webhooks
List Webhooks
curl https://api.tuteliq.ai/webhooks \
-H "Authorization: Bearer YOUR_API_KEY"
Update Events
curl -X PATCH https://api.tuteliq.ai/webhooks/wh_abc123 \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "events": ["safety.critical", "safety.high", "batch.completed"] }'
Test Delivery
Send a test event to your endpoint to verify it is reachable and correctly validating signatures:
curl -X POST https://api.tuteliq.ai/webhooks/wh_abc123/test \
-H "Authorization: Bearer YOUR_API_KEY"
The test event will have "type": "webhook.test" and does not represent a real safety incident.
Regenerate Secret
If your webhook secret has been compromised, regenerate it immediately:
curl -X POST https://api.tuteliq.ai/webhooks/wh_abc123/secret/rotate \
-H "Authorization: Bearer YOUR_API_KEY"
Rotating the secret invalidates the previous one immediately. Update your verification logic before or right after regeneration to avoid rejecting legitimate deliveries.
Delete a Webhook
curl -X DELETE https://api.tuteliq.ai/webhooks/wh_abc123 \
-H "Authorization: Bearer YOUR_API_KEY"