Webhooks
Receive real-time HTTP notifications when events occur in Datix xAgents. Build event-driven integrations and automate workflows.
🔔 What Are Webhooks?
Webhooks are HTTP POST requests sent to your server when specific events occur:
- Real-time notifications: No polling required
- Event-driven: React to user actions and system events
- Flexible: Trigger any custom logic
- Secure: Signed with secret key for verification
📡 Available Events
Query Events
query.started- Query execution beginsquery.completed- Query successfully finishedquery.failed- Query encountered an error
Template Events
template.created- New template createdtemplate.executed- Template run completedtemplate.scheduled- Scheduled template run completed
Agent Events
agent.created- New agent createdagent.updated- Agent configuration changedagent.assigned- Agent assigned to user
User Events
user.created- New user registereduser.login- User logged inuser.role_changed- User role updated
System Events
data_source.connected- Database connection successfuldata_source.failed- Database connection failedusage.limit_reached- Monthly usage limit reached
⚙️ Setting Up Webhooks
1. Create Webhook Endpoint
Create an endpoint in your application to receive webhook POST requests:
Node.js/Express Example:
const express = require('express');
const crypto = require('crypto');
app.post('/webhooks/datixxagents', express.json(), (req, res) => {
// Verify webhook signature
const signature = req.headers['x-datixxagents-signature'];
const payload = JSON.stringify(req.body);
const expectedSignature = crypto
.createHmac('sha256', process.env.WEBHOOK_SECRET)
.update(payload)
.digest('hex');
if (signature !== expectedSignature) {
return res.status(401).send('Invalid signature');
}
// Handle the event
const event = req.body;
console.log('Received event:', event.type);
// Process based on event type
switch (event.type) {
case 'query.completed':
handleQueryCompleted(event.data);
break;
case 'template.executed':
handleTemplateExecuted(event.data);
break;
// ... handle other events
}
res.status(200).send('OK');
});
2. Register Webhook in Datix xAgents
- Navigate to Settings → Webhooks
- Click "Add Webhook"
- Enter your endpoint URL
- Select events to subscribe to
- Save to generate secret key
3. Test Webhook
Click "Send Test Event" to verify your endpoint is working.
📦 Webhook Payload Format
Standard Structure
{
"id": "evt_abc123",
"type": "query.completed",
"created_at": "2024-12-15T10:30:00Z",
"data": {
// Event-specific data
}
}
Example: query.completed
{
"id": "evt_abc123",
"type": "query.completed",
"created_at": "2024-12-15T10:30:00Z",
"data": {
"query_id": "query_xyz789",
"question": "Show me total revenue for Q4",
"agent_id": "agent_abc123",
"user_id": "user_456",
"execution_time": 2.3,
"row_count": 1,
"status": "success"
}
}
Example: template.executed
{
"id": "evt_def456",
"type": "template.executed",
"created_at": "2024-12-15T08:00:00Z",
"data": {
"template_id": "tpl_789",
"template_name": "Daily Sales Summary",
"execution_id": "exec_012",
"parameters": {
"date": "2024-12-15"
},
"status": "success",
"row_count": 25
}
}
🔐 Security
Signature Verification
All webhooks include a signature for verification:
Header:
X-DatixXAgents-Signature: sha256=abc123...
Verification (Python):
import hmac
import hashlib
def verify_webhook(payload, signature, secret):
expected_signature = hmac.new(
secret.encode(),
payload.encode(),
hashlib.sha256
).hexdigest()
return hmac.compare_digest(
f"sha256={expected_signature}",
signature
)
Verification (JavaScript):
const crypto = require('crypto');
function verifyWebhook(payload, signature, secret) {
const expectedSignature = crypto
.createHmac('sha256', secret)
.update(payload)
.digest('hex');
return signature === `sha256=${expectedSignature}`;
}
Best Practices
✅ Verify Signatures
Always validate webhook signatures
✅ Use HTTPS
Only accept webhooks over HTTPS
✅ Store Secret Securely
Keep webhook secret in environment variables
✅ Respond Quickly
Return 200 OK within 5 seconds
✅ Process Async
Handle heavy processing in background
✅ Log Events
Keep audit trail of webhooks received
🔄 Retry Logic
Retry Behavior
If your endpoint returns non-200 status or times out:
- Retry 1: After 1 minute
- Retry 2: After 5 minutes
- Retry 3: After 15 minutes
- Final: After 1 hour
After 5 consecutive failures, webhook will be automatically disabled. Re-enable in Settings → Webhooks.
Idempotency
Use the id field to handle duplicate deliveries:
const processedEvents = new Set();
app.post('/webhooks/datix-xagents', (req, res) => {
const eventId = req.body.id;
if (processedEvents.has(eventId)) {
return res.status(200).send('Already processed');
}
// Process event
handleEvent(req.body);
// Mark as processed
processedEvents.add(eventId);
res.status(200).send('OK');
});
🎯 Use Cases
1. Slack Notifications
Send query results to Slack channel:
app.post('/webhooks/datix-xagents', async (req, res) => {
const event = req.body;
if (event.type === 'query.completed') {
const { question, execution_time, row_count } = event.data;
await sendSlackMessage({
channel: '#data-insights',
text: `✅ Query completed: "${question}"`,
attachments: [{
fields: [
{ title: 'Execution Time', value: `${execution_time}s` },
{ title: 'Rows Returned', value: row_count }
]
}]
});
}
res.status(200).send('OK');
});
2. Database Logging
Log all queries to database:
app.post('/webhooks/datix-xagents', async (req, res) => {
const event = req.body;
if (event.type === 'query.completed') {
await db.queries.create({
query_id: event.data.query_id,
user_id: event.data.user_id,
question: event.data.question,
execution_time: event.data.execution_time,
timestamp: event.created_at
});
}
res.status(200).send('OK');
});
3. Custom Analytics
Track usage in analytics platform:
app.post('/webhooks/datix-xagents', (req, res) => {
const event = req.body;
if (event.type === 'query.completed') {
analytics.track({
userId: event.data.user_id,
event: 'Query Executed',
properties: {
agent: event.data.agent_id,
executionTime: event.data.execution_time,
rowCount: event.data.row_count
}
});
}
res.status(200).send('OK');
});
4. Error Monitoring
Alert when queries fail:
app.post('/webhooks/datix-xagents', async (req, res) => {
const event = req.body;
if (event.type === 'query.failed') {
await sentry.captureException(new Error('Query failed'), {
extra: {
query_id: event.data.query_id,
question: event.data.question,
error: event.data.error_message
}
});
}
res.status(200).send('OK');
});
🔧 Managing Webhooks
List Webhooks
GET /api/webhooks
Create Webhook
POST /api/webhooks
{
"url": "https://myapp.com/webhooks/datix-xagents",
"events": ["query.completed", "template.executed"],
"description": "Production webhook"
}
Update Webhook
PATCH /api/webhooks/{webhook_id}
{
"enabled": true,
"events": ["query.completed", "query.failed"]
}
Delete Webhook
DELETE /api/webhooks/{webhook_id}
Test Webhook
POST /api/webhooks/{webhook_id}/test
📊 Monitoring
Webhook Dashboard
View in Settings → Webhooks:
- Total deliveries
- Success rate
- Recent failures
- Average response time
Delivery Logs
Each webhook delivery is logged with:
- Timestamp
- Event type
- HTTP status code
- Response time
- Retry count
⚠️ Troubleshooting
Webhook Not Receiving Events
- Verify webhook is enabled
- Check URL is correct and accessible
- Ensure endpoint returns 200 OK
- Check firewall allows Datix xAgents IPs
- Review delivery logs for errors
Signature Verification Failing
- Verify you're using correct secret
- Check payload isn't modified before verification
- Ensure you're hashing the raw body
Timeouts
- Respond with 200 OK immediately
- Process heavy logic asynchronously
- Increase server resources if needed