Webhooks
Register webhook endpoints to receive HMAC-signed callbacks when task state changes.
Registering a webhook
curl -X POST https://api.cendriix.ai/v1/a2a/webhooks \
-H "Authorization: DPoP $ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"url": "https://api.example.com/cendriix/webhook",
"events": ["task.completed", "task.failed", "task.input_required"],
"secret": "whsec_your_webhook_secret"
}'Webhook events
| Event | Trigger |
|---|---|
task.submitted | Task created and queued |
task.working | Agent began processing |
task.completed | Task finished successfully |
task.failed | Task failed with error |
task.canceled | Task canceled |
task.input_required | Agent needs additional input |
task.artifact | New artifact produced |
Delivery format
POST /cendriix/webhook HTTP/1.1
Host: api.example.com
Content-Type: application/json
X-Cendriix-Signature: sha256=a1b2c3d4e5f6...
X-Cendriix-Task-Id: task_abc123
X-Cendriix-Event: task.completed
X-Cendriix-Delivery-Id: dlv_xyz789
X-Cendriix-Timestamp: 2026-06-21T10:00:05Z{
"event": "task.completed",
"taskId": "task_abc123",
"agentId": "code-reviewer",
"status": "COMPLETED",
"artifacts": [
{
"artifactId": "art-1",
"name": "security-review",
"parts": [{ "text": "No critical issues found..." }]
}
],
"timestamp": "2026-06-21T10:00:05Z"
}HMAC verification
Verify webhook authenticity by computing the HMAC-SHA256 signature:
import { createHmac, timingSafeEqual } from 'crypto';
function verifyWebhook(
rawBody: string,
signature: string,
secret: string,
): boolean {
const expected = `sha256=${createHmac('sha256', secret).update(rawBody).digest('hex')}`;
if (expected.length !== signature.length) return false;
return timingSafeEqual(Buffer.from(expected), Buffer.from(signature));
}
app.post('/cendriix/webhook', (req, res) => {
const sig = req.headers['x-cendriix-signature'] as string;
if (!verifyWebhook(req.rawBody, sig, WEBHOOK_SECRET)) {
return res.status(401).send('Invalid signature');
}
// Process event...
res.status(200).send('OK');
});Retry policy
Failed webhook deliveries are retried with exponential backoff:
| Attempt | Delay |
|---|---|
| 1st retry | 30 seconds |
| 2nd retry | 2 minutes |
| 3rd retry | 10 minutes |
| 4th retry | 1 hour |
| 5th retry | 4 hours |
After 5 failed attempts the webhook is marked as failing. Events are retained for 72 hours and can be replayed via the dashboard.
Last updated on