Webhooks

129 event types. Signed, retried, dead-lettered.

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.

Setup

Subscribing

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.

Payload

Envelope

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.

event
{
  "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"
}
Trust

Signing & verification

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.

node.js
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);
}
python
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)
Delivery

Retries

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.

AttemptDelay
1Immediate
2+30 seconds
3+2 minutes
4+10 minutes
5+1 hour
6+6 hours
Dead-letter (Sentry alert)
Reference

Event catalog

Auto-generated from the source registry. When the team ships a new event type, it appears here without any docs work.

Audit — Inbound sources

3
  • inbound_source.created
  • inbound_source.rotated
  • inbound_source.deleted

Audit — Webhook subscriptions

3
  • webhook_subscription.created
  • webhook_subscription.updated
  • webhook_subscription.deleted

Comments

3
  • comment.created
  • comment.updated
  • comment.deleted

Customers

7
  • customer.created
  • customer.updated
  • customer.deleted
  • customer.opportunity_linked
  • customer.opportunity_unlinked
  • customer.update_posted
  • customer.contact_added

good_vibes

1
  • good_vibes.posted

Insights

8
  • insight.created
  • insight.updated
  • insight.archived
  • insight.pinned
  • insight.unpinned
  • insight.status_changed
  • insight.linked
  • insight.unlinked

Intake

11
  • intake.created
  • intake.updated
  • intake.owner_claimed
  • intake.shaping_requested
  • intake.needs_context
  • intake.accepted
  • intake.evaluated
  • intake.rejected
  • intake.declined
  • intake.reassigned_to_team
  • intake.promoted_to_opportunity

message

7
  • message.created
  • message.edited
  • message.deleted
  • message.pinned
  • message.unpinned
  • message.reaction_added
  • message.reaction_removed

Metrics

3
  • metric.value_updated
    payload: metricName, previousValue, newValue, unit
  • metric.target_reached
    payload: metricName, currentValue, targetValue, unit
  • metric.deleted

Notifications

3
  • notification.created
  • notification.pinned
  • notification.unpinned

Objectives

7
  • objective.created
  • objective.updated
  • objective.deleted
  • objective.deadline_approaching
    payload: objectiveTitle, deadline, daysRemaining
  • objective.metric_linked
  • objective.metric_unlinked
  • objective.metric_link_updated

Opportunities

19
  • opportunity.status_changed
    payload: previousStatus, newStatus, title
  • opportunity.created
  • opportunity.updated
  • opportunity.deleted
  • opportunity.completed
  • opportunity.cancelled
  • opportunity.synthesized
  • opportunity.risk_vote_cast
  • opportunity.risk_vote_changed
  • opportunity.insight_added
  • opportunity.tags_changed
  • opportunity.prototype_added
  • opportunity.prototype_removed
  • opportunity.objective_linked
  • opportunity.objective_unlinked
  • opportunity.objective_link_updated
  • opportunity.queued
  • opportunity.dequeued
  • opportunity.content_updated

prd_template

3
  • prd_template.created
  • prd_template.updated
  • prd_template.deleted

room

9
  • room.created
  • room.updated
  • room.archived
  • room.member_added
  • room.member_removed
  • room.pinned
  • room.unpinned
  • room.notification_level_changed
  • room.marked_read

Strategy

4
  • strategy.created
  • strategy.updated
  • strategy.published
  • strategy.archived

subscription

2
  • subscription.created
  • subscription.muted

tag

3
  • tag.created
  • tag.updated
  • tag.deleted

tag_theme

3
  • tag_theme.created
  • tag_theme.updated
  • tag_theme.deleted

Tasks

4
  • task.status_changed
    payload: previousStatus, newStatus, title
  • task.assigned
  • task.unassigned
  • task.tags_changed

team_queue

5
  • team_queue.reordered
  • team_queue.chain_added
  • team_queue.chain_removed
  • team_queue.cross_team_chain_added
  • team_queue.window_set

Teams

8
  • team.created
  • team.updated
  • team.lead_changed
  • team.member_added
  • team.member_removed
  • team.invite_sent
  • team.invite_revoked
  • team.invite_accepted

time_entry

4
  • time_entry.created
  • time_entry.updated
  • time_entry.deleted
  • time_entry.range_upserted

Users

1
  • user.updated

Vision

2
  • vision.updated
    payload: visionLabel, action
  • vision.deleted

Workflows

6
  • workflow.created
  • workflow.updated
  • workflow.deleted
  • workflow.assigned
  • workflow.step_status_changed
  • workflow.checklist_item_toggled
External feeds

Inbound webhooks

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.