Audit — Inbound sources
3- inbound_source.created
- inbound_source.rotated
- inbound_source.deleted
Telos fans out every state change as a webhook event. Subscribers receive a signed POST per matching event with exponential-backoff retries; terminal failures land in a dead-letter queue with Sentry alerts so you never silently lose a delivery.
Subscriptions are managed inside the app at Configurations → Webhooks by leadership and admin users. Each subscription stores a URL, shared secret, and the list of event types you want delivered. A Send test action exercises the full delivery path against your endpoint.
A REST endpoint for programmatic subscription management is on the roadmap. Today, subscription CRUD is in-app only.
Every event uses the same envelope. The payload object varies by event type. The id is unique per event and is safe to use for idempotent processing on your side.
{
"id": "01H8X3F4S0Z9KMQ4N6PYZR7C5A",
"eventType": "opportunity.status_changed",
"entityType": "opportunity",
"entityId": "8c2c9d8e-1234-4abc-9def-1234567890ab",
"payload": {
"previousStatus": "shaping",
"newStatus": "validated",
"title": "Reduce onboarding drop-off"
},
"createdAt": "2026-05-18T14:23:11.842Z"
}Each delivery includes an X-Telos-Signature header containing the HMAC-SHA256 hex digest of the raw request body, keyed by your subscription secret. Verify before doing anything with the payload; compare in constant time.
import { createHmac, timingSafeEqual } from "node:crypto";
export function verifyTelosWebhook(
rawBody: string,
signature: string,
secret: string,
): boolean {
const expected = createHmac("sha256", secret).update(rawBody).digest("hex");
const a = Buffer.from(expected, "hex");
const b = Buffer.from(signature, "hex");
return a.length === b.length && timingSafeEqual(a, b);
}import hmac
import hashlib
def verify_telos_webhook(raw_body: bytes, signature: str, secret: str) -> bool:
expected = hmac.new(secret.encode(), raw_body, hashlib.sha256).hexdigest()
return hmac.compare_digest(expected, signature)Each delivery is attempted up to six times. Non-2xx responses or connection failures trigger a retry on a fixed schedule. The request timeout is 10 seconds. After the sixth failure the delivery is marked dead and you receive a Sentry alert.
| Attempt | Delay |
|---|---|
| 1 | Immediate |
| 2 | +30 seconds |
| 3 | +2 minutes |
| 4 | +10 minutes |
| 5 | +1 hour |
| 6 | +6 hours |
| — | Dead-letter (Sentry alert) |
Auto-generated from the source registry. When the team ships a new event type, it appears here without any docs work.
Telos also accepts inbound events at /api/webhooks/inbound via per-source HMAC-secured connectors (generic, Slack, Salesforce stubs). Supported event types today: metric.external_update and task.external_create. Inbound sources are managed at Configurations → Inbound sources.