Skip to content

Webhooks API Enterprise

Configure webhooks to receive real-time notifications when events occur in your Controlinfra organization.

Endpoints Summary

MethodEndpointDescription
GET/api/webhooksList webhooks
POST/api/webhooksCreate a webhook
PUT/api/webhooks/:idUpdate a webhook
DELETE/api/webhooks/:idDelete a webhook
POST/api/webhooks/:id/testSend a test event

Authentication

All endpoints require a Bearer token in the Authorization header.

Authorization: Bearer <your-api-token>

List Webhooks

GET /api/webhooks

Returns all webhooks for the current organization.

Example:

bash
curl -X GET "https://api.controlinfra.com/api/webhooks" \
  -H "Authorization: Bearer YOUR_TOKEN"

Response:

json
{
  "webhooks": [
    {
      "_id": "666a1b2c3d4e5f6a7b8c9d0e",
      "url": "https://example.com/hooks/controlinfra",
      "events": ["scan.completed", "drift.detected"],
      "active": true,
      "secret": "whsec_••••••••",
      "lastDelivery": {
        "status": 200,
        "timestamp": "2025-01-15T10:30:00Z"
      },
      "createdAt": "2025-01-01T00:00:00Z"
    }
  ]
}

Create a Webhook

POST /api/webhooks

Request Body:

FieldTypeRequiredDescription
urlstringYesWebhook endpoint URL (must be HTTPS)
eventsstring[]YesEvents to subscribe to
secretstringNoShared secret for payload signing
activebooleanNoWhether the webhook is active (default: true)

Available Events

EventDescription
scan.startedA drift scan has started
scan.completedA drift scan completed
scan.failedA drift scan failed
drift.detectedNew drift was detected
drift.resolvedA drift was resolved
guardrail.violatedA guardrail was violated
guardrail.bypassedA guardrail was bypassed (break-glass)
watch.drift_detectedDrift Watch detected drift
member.invitedA member was invited
member.removedA member was removed

Example:

bash
curl -X POST "https://api.controlinfra.com/api/webhooks" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "url": "https://example.com/hooks/controlinfra",
    "events": ["scan.completed", "drift.detected", "guardrail.violated"],
    "secret": "my-webhook-secret"
  }'

Response: 201 Created

json
{
  "_id": "666a1b2c3d4e5f6a7b8c9d0e",
  "url": "https://example.com/hooks/controlinfra",
  "events": ["scan.completed", "drift.detected", "guardrail.violated"],
  "active": true,
  "createdAt": "2025-01-15T10:00:00Z"
}

Update a Webhook

PUT /api/webhooks/:id

Request Body:

FieldTypeDescription
urlstringWebhook endpoint URL
eventsstring[]Events to subscribe to
secretstringShared secret for payload signing
activebooleanEnable or disable the webhook

Example:

bash
curl -X PUT "https://api.controlinfra.com/api/webhooks/666a1b2c3d4e5f6a7b8c9d0e" \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "events": ["scan.completed", "drift.detected"],
    "active": false
  }'

Delete a Webhook

DELETE /api/webhooks/:id

Example:

bash
curl -X DELETE "https://api.controlinfra.com/api/webhooks/666a1b2c3d4e5f6a7b8c9d0e" \
  -H "Authorization: Bearer YOUR_TOKEN"

Response: 204 No Content


Test a Webhook

POST /api/webhooks/:id/test

Sends a test event to the webhook URL to verify connectivity.

Example:

bash
curl -X POST "https://api.controlinfra.com/api/webhooks/666a1b2c3d4e5f6a7b8c9d0e/test" \
  -H "Authorization: Bearer YOUR_TOKEN"

Response:

json
{
  "success": true,
  "statusCode": 200,
  "responseTime": 245,
  "message": "Test event delivered successfully"
}

Error Response:

json
{
  "success": false,
  "statusCode": 500,
  "error": "Connection timed out",
  "message": "Failed to deliver test event"
}

Webhook Payload Format

All webhook deliveries include the following structure:

json
{
  "id": "evt_abc123def456",
  "event": "drift.detected",
  "timestamp": "2025-01-15T10:30:00Z",
  "organization": {
    "id": "663e...",
    "name": "My Org"
  },
  "data": {
    // Event-specific data
  }
}

Payload Signing

If a secret is configured, each delivery includes a X-Controlinfra-Signature header:

X-Controlinfra-Signature: sha256=abc123def456...

Verify the signature by computing HMAC-SHA256 of the raw request body using your secret:

javascript
const crypto = require('crypto');

function verifySignature(payload, signature, secret) {
  const expected = 'sha256=' + crypto
    .createHmac('sha256', secret)
    .update(payload)
    .digest('hex');
  return crypto.timingSafeEqual(
    Buffer.from(signature),
    Buffer.from(expected)
  );
}

Retry Policy

Failed deliveries (non-2xx responses or timeouts) are retried:

AttemptDelay
1st retry1 minute
2nd retry5 minutes
3rd retry30 minutes
4th retry2 hours

After 4 failed retries, the delivery is marked as failed. Webhooks with repeated failures are automatically deactivated after 10 consecutive failures.