Skip to content

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 created
  • record.updated - Record updated
  • record.deleted - Record deleted
  • function.completed - Function execution completed
  • function.failed - Function execution failed
  • trigger.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:

X-Centrali-Signature: sha256=abc123...

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:

{
  "filters": {
    "structure": "orders"
  }
}

By Query

Filter events using query syntax:

{
  "filters": {
    "structure": "orders",
    "query": "total > 100"
  }
}

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

  1. Respond quickly: Return 200 OK immediately, process async
  2. Verify signatures: Always validate webhook signatures
  3. Handle idempotency: Same event may be delivered multiple times
  4. Log events: Keep audit trail of received webhooks
  5. 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