Webhooks API Enterprise
Configure webhooks to receive real-time notifications when events occur in your Controlinfra organization.
Endpoints Summary
| Method | Endpoint | Description |
|---|---|---|
GET | /api/webhooks | List webhooks |
POST | /api/webhooks | Create a webhook |
PUT | /api/webhooks/:id | Update a webhook |
DELETE | /api/webhooks/:id | Delete a webhook |
POST | /api/webhooks/:id/test | Send a test event |
Authentication
All endpoints require a Bearer token in the Authorization header.
Authorization: Bearer <your-api-token>List Webhooks
GET /api/webhooksReturns all webhooks for the current organization.
Example:
curl -X GET "https://api.controlinfra.com/api/webhooks" \
-H "Authorization: Bearer YOUR_TOKEN"Response:
{
"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/webhooksRequest Body:
| Field | Type | Required | Description |
|---|---|---|---|
url | string | Yes | Webhook endpoint URL (must be HTTPS) |
events | string[] | Yes | Events to subscribe to |
secret | string | No | Shared secret for payload signing |
active | boolean | No | Whether the webhook is active (default: true) |
Available Events
| Event | Description |
|---|---|
scan.started | A drift scan has started |
scan.completed | A drift scan completed |
scan.failed | A drift scan failed |
drift.detected | New drift was detected |
drift.resolved | A drift was resolved |
guardrail.violated | A guardrail was violated |
guardrail.bypassed | A guardrail was bypassed (break-glass) |
watch.drift_detected | Drift Watch detected drift |
member.invited | A member was invited |
member.removed | A member was removed |
Example:
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
{
"_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/:idRequest Body:
| Field | Type | Description |
|---|---|---|
url | string | Webhook endpoint URL |
events | string[] | Events to subscribe to |
secret | string | Shared secret for payload signing |
active | boolean | Enable or disable the webhook |
Example:
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/:idExample:
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/testSends a test event to the webhook URL to verify connectivity.
Example:
curl -X POST "https://api.controlinfra.com/api/webhooks/666a1b2c3d4e5f6a7b8c9d0e/test" \
-H "Authorization: Bearer YOUR_TOKEN"Response:
{
"success": true,
"statusCode": 200,
"responseTime": 245,
"message": "Test event delivered successfully"
}Error Response:
{
"success": false,
"statusCode": 500,
"error": "Connection timed out",
"message": "Failed to deliver test event"
}Webhook Payload Format
All webhook deliveries include the following structure:
{
"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:
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:
| Attempt | Delay |
|---|---|
| 1st retry | 1 minute |
| 2nd retry | 5 minutes |
| 3rd retry | 30 minutes |
| 4th retry | 2 hours |
After 4 failed retries, the delivery is marked as failed. Webhooks with repeated failures are automatically deactivated after 10 consecutive failures.