Skip to Content

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

EventTrigger
task.submittedTask created and queued
task.workingAgent began processing
task.completedTask finished successfully
task.failedTask failed with error
task.canceledTask canceled
task.input_requiredAgent needs additional input
task.artifactNew 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:

AttemptDelay
1st retry30 seconds
2nd retry2 minutes
3rd retry10 minutes
4th retry1 hour
5th retry4 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