Webhooks
CohesionXL sends real-time HTTP POST notifications when key events occur. Use webhooks to keep external systems in sync with your planning data.
Supported Events
| Event | Description |
|-------|-------------|
| initiative.created | A new initiative was created |
| initiative.updated | An initiative's fields were modified |
| initiative.status_changed | An initiative moved to a new lifecycle stage |
| scenario.created | A new scenario was created |
| scenario.reconciled | A scenario was reconciled into the active plan |
| approval.requested | An approval request was submitted |
| approval.completed | An approval chain was fully resolved |
| forecast.completed | A Monte Carlo simulation finished |
| capacity.alert | A capacity constraint violation was detected |
Registering a Webhook
curl -X POST https://api.cohesionxl.com/v1/webhooks \
-H "Authorization: Bearer {token}" \
-H "Content-Type: application/json" \
-d '{
"url": "https://your-app.com/webhooks/cohesionxl",
"events": ["initiative.status_changed", "approval.completed"],
"secret": "your_webhook_secret"
}'
Response:
{
"id": "whk_abc123",
"url": "https://your-app.com/webhooks/cohesionxl",
"events": ["initiative.status_changed", "approval.completed"],
"active": true,
"created_at": "2025-01-15T10:00:00Z"
}
Payload Format
All webhook payloads follow the same envelope structure:
{
"id": "evt_xyz789",
"type": "initiative.status_changed",
"timestamp": "2025-01-15T10:30:00Z",
"organization_id": "org_123",
"data": {
"initiative_id": "init_456",
"previous_status": "APPROVED",
"new_status": "IN_PROGRESS",
"changed_by": "user_789"
}
}
Verifying Signatures
Every webhook request includes an X-CohesionXL-Signature header containing an HMAC-SHA256 signature of the request body, computed using your webhook secret.
import crypto from "crypto";
function verifyWebhook(body: string, signature: string, secret: string): boolean {
const expected = crypto
.createHmac("sha256", secret)
.update(body)
.digest("hex");
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expected)
);
}
Retry Policy
Failed deliveries (non-2xx responses or timeouts) are retried with exponential backoff:
- Attempt 1: Immediate
- Attempt 2: 1 minute
- Attempt 3: 5 minutes
- Attempt 4: 30 minutes
- Attempt 5: 2 hours
After 5 failed attempts, the webhook is marked as failing and an alert is sent to organization admins.