Webhooks Guide¶
Overview¶
Webhooks allow you to receive HTTP callbacks when events occur in your workspace. Use webhooks to integrate Centrali with external services and automate workflows.
What are Webhooks?¶
When an event occurs (e.g., record created, function completed), Centrali sends an HTTP POST request to your configured endpoint with event details.
Creating a Webhook¶
curl -X POST https://api.centrali.io/workspace/my-workspace/api/v1/webhooks \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "Order Notifications",
"url": "https://your-app.com/webhooks/centrali",
"events": ["record.created", "record.updated"],
"filters": {
"structure": "orders"
}
}'
Webhook Events¶
Available event types:
record.created- New record createdrecord.updated- Record updatedrecord.deleted- Record deletedfunction.completed- Function execution completedfunction.failed- Function execution failedtrigger.fired- Trigger activated
Event Payload¶
Example webhook payload for record.created:
{
"event": "record.created",
"workspace": "my-workspace",
"timestamp": "2025-01-15T10:30:00Z",
"data": {
"structure": "orders",
"recordId": "rec_abc123",
"record": {
"id": "rec_abc123",
"customer": "John Doe",
"total": 99.99,
"status": "pending"
}
}
}
Webhook Security¶
Signature Verification¶
All webhook requests include a signature header for verification:
Verify the signature in your endpoint:
const crypto = require('crypto');
function verifyWebhook(payload, signature, secret) {
const hash = crypto
.createHmac('sha256', secret)
.update(JSON.stringify(payload))
.digest('hex');
return `sha256=${hash}` === signature;
}
app.post('/webhooks/centrali', (req, res) => {
const signature = req.headers['x-centrali-signature'];
const isValid = verifyWebhook(req.body, signature, 'your-webhook-secret');
if (!isValid) {
return res.status(401).send('Invalid signature');
}
// Process webhook
console.log('Event:', req.body.event);
res.status(200).send('OK');
});
Setting Webhook Secret¶
curl -X PATCH https://api.centrali.io/workspace/my-workspace/api/v1/webhooks/webhook_123 \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"secret": "your-webhook-secret"
}'
Filtering Events¶
By Structure¶
Only receive events for specific structures:
By Query¶
Filter events using query syntax:
Retry Behavior¶
If your endpoint returns a non-2xx status: - Centrali retries up to 3 times - Exponential backoff: 1s, 5s, 15s - After 3 failures, webhook is marked as failed
View failed deliveries:
curl -X GET https://api.centrali.io/workspace/my-workspace/api/v1/webhooks/webhook_123/failures \
-H "Authorization: Bearer YOUR_TOKEN"
Testing Webhooks¶
Send a test event:
curl -X POST https://api.centrali.io/workspace/my-workspace/api/v1/webhooks/webhook_123/test \
-H "Authorization: Bearer YOUR_TOKEN"
Managing Webhooks¶
List Webhooks¶
curl -X GET https://api.centrali.io/workspace/my-workspace/api/v1/webhooks \
-H "Authorization: Bearer YOUR_TOKEN"
Update Webhook¶
curl -X PATCH https://api.centrali.io/workspace/my-workspace/api/v1/webhooks/webhook_123 \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"url": "https://new-endpoint.com/webhooks",
"enabled": true
}'
Delete Webhook¶
curl -X DELETE https://api.centrali.io/workspace/my-workspace/api/v1/webhooks/webhook_123 \
-H "Authorization: Bearer YOUR_TOKEN"
Best Practices¶
Endpoint Implementation¶
- Respond quickly: Return 200 OK immediately, process async
- Verify signatures: Always validate webhook signatures
- Handle idempotency: Same event may be delivered multiple times
- Log events: Keep audit trail of received webhooks
- Monitor failures: Set up alerts for webhook failures
Example Implementation¶
const express = require('express');
const app = express();
app.post('/webhooks/centrali', async (req, res) => {
// 1. Verify signature
const signature = req.headers['x-centrali-signature'];
if (!verifyWebhook(req.body, signature, process.env.WEBHOOK_SECRET)) {
return res.status(401).send('Invalid signature');
}
// 2. Respond immediately
res.status(200).send('OK');
// 3. Process async
try {
await processWebhook(req.body);
} catch (error) {
console.error('Webhook processing failed:', error);
}
});
async function processWebhook(event) {
switch (event.event) {
case 'record.created':
await handleRecordCreated(event.data);
break;
case 'function.completed':
await handleFunctionCompleted(event.data);
break;
}
}
Common Use Cases¶
Slack Notifications¶
async function handleRecordCreated(data) {
await fetch('https://hooks.slack.com/services/YOUR/WEBHOOK/URL', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
text: `New ${data.structure} created: ${data.recordId}`
})
});
}
Email Notifications¶
async function handleFunctionFailed(data) {
await sendgrid.send({
to: 'admin@example.com',
from: 'alerts@example.com',
subject: 'Function Failed',
text: `Function ${data.functionId} failed: ${data.error}`
});
}
External System Sync¶
async function handleRecordCreated(data) {
// Sync to external CRM
await crm.createContact({
id: data.recordId,
...data.record
});
}
Troubleshooting¶
Webhook Not Firing¶
- Verify webhook is enabled
- Check event filters match your data
- Confirm structure name is correct
- View webhook logs for errors
Signature Validation Failing¶
- Ensure using raw request body (not parsed JSON)
- Verify secret matches configured value
- Check signature header name is correct
- Use UTF-8 encoding for hash calculation
High Failure Rate¶
- Check endpoint is publicly accessible
- Verify SSL certificate is valid
- Ensure endpoint responds within 30 seconds
- Review error logs for your endpoint
Related Documentation¶
- Compute Functions - Alternative to webhooks
- Triggers - Event-driven functions
- Notifications - WebSocket notifications