Webhooks
Webhooks deliver real-time event notifications to your server via HTTP POST. Cortex signs every delivery so you can verify authenticity.
Base path: /api/webhooks
All endpoints require Authorization: Bearer <token>.
Events
| Event | Triggered when |
|---|---|
task.created | A new kanban task is created |
task.completed | A task reaches done status |
task.status_changed | A task moves to any new status |
agent.spawned | An agent execution starts |
agent.completed | An agent execution finishes successfully |
agent.failed | An agent execution ends in error |
Payload Verification
Every delivery includes these HTTP headers:
| Header | Description |
|---|---|
X-Cortex-Signature | sha256=<hmac> — HMAC-SHA256 of the raw body using your webhook secret |
X-Cortex-Event | Event name (e.g. task.created) |
X-Cortex-Delivery | Unique delivery ID |
X-Cortex-Timestamp | Unix timestamp of delivery |
Verification example (Node.js):
import crypto from 'crypto';
function verify(secret: string, rawBody: string, signature: string): boolean {
const expected = 'sha256=' + crypto
.createHmac('sha256', secret)
.update(rawBody)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(expected),
Buffer.from(signature)
);
}Replay protection
Always validate X-Cortex-Timestamp and reject deliveries older than 5 minutes to prevent replay attacks.
Register Webhook
POST /api/webhooks/registerRequest body:
{
"url": "https://your-server.com/hooks/cortex",
"events": ["task.created", "task.completed", "agent.failed"],
"secret": "your-signing-secret"
}| Field | Type | Required | Description |
|---|---|---|---|
url | string | Yes | HTTPS URL that will receive POST deliveries |
events | string[] | Yes | One or more event names to subscribe to |
secret | string | No | Shared secret for HMAC signing (recommended) |
Response: 201 Created
{
"success": true,
"data": {
"id": "wh_01J...",
"url": "https://your-server.com/hooks/cortex",
"events": ["task.created", "task.completed", "agent.failed"],
"active": true,
"createdAt": "2026-04-03T12:00:00Z"
}
}curl:
curl -X POST "https://api.cortex.acrobi.com/api/webhooks/register" \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"url": "https://your-server.com/hooks/cortex",
"events": ["task.created", "agent.completed"],
"secret": "your-signing-secret"
}'List Webhooks
GET /api/webhooksResponse:
{
"success": true,
"data": [
{
"id": "wh_01J...",
"url": "https://your-server.com/hooks/cortex",
"events": ["task.created", "agent.completed"],
"active": true,
"lastDeliveryAt": "2026-04-03T11:58:00Z",
"createdAt": "2026-04-03T12:00:00Z"
}
]
}Get Webhook
GET /api/webhooks/:idResponse: Full webhook object (secret is never returned).
Delete Webhook
DELETE /api/webhooks/:idResponse:
{ "success": true }Send Test Payload
Sends a synthetic test delivery to the registered URL. Useful for verifying your server can receive and verify webhooks.
POST /api/webhooks/:id/testRequest body:
{
"event": "task.created"
}Response: 200 OK
{
"success": true,
"data": {
"deliveryId": "dlv_01J...",
"httpStatus": 200,
"responseBody": "ok",
"durationMs": 89
}
}curl:
curl -X POST "https://api.cortex.acrobi.com/api/webhooks/wh_01J.../test" \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{"event": "task.created"}'Delivery History
GET /api/webhooks/:id/deliveriesReturns recent delivery attempts with status and response.
Query parameters: limit (default 20), offset
Response:
{
"success": true,
"data": [
{
"id": "dlv_01J...",
"event": "task.completed",
"httpStatus": 200,
"durationMs": 112,
"deliveredAt": "2026-04-03T11:58:00Z",
"redelivery": false
},
{
"id": "dlv_00J...",
"event": "agent.failed",
"httpStatus": 500,
"durationMs": 3021,
"deliveredAt": "2026-04-03T11:42:00Z",
"redelivery": false,
"error": "Connection refused"
}
],
"pagination": { "limit": 20, "offset": 0, "total": 48 }
}Automatic retries
Failed deliveries (non-2xx or timeout) are retried up to 3 times with exponential backoff: 5 min, 30 min, 2 hours.
Example Payload
task.status_changed delivery body:
{
"event": "task.status_changed",
"deliveryId": "dlv_01J...",
"timestamp": "2026-04-03T12:01:00Z",
"data": {
"task": {
"id": "tk_01J...",
"title": "Add rate limiting",
"previousStatus": "in_progress",
"status": "qa_review",
"assignedAgent": "qa-tester",
"projectId": "proj_01J..."
}
}
}