Agent-readable docs index: /docs/llms.txt. Full docs in one file: /docs/llms-full.txt. Download /docs/docs.zip to grep all markdown files locally.

Webhooks

In Settings → Developers, select your application and create a webhook. Choose a key, an HTTPS endpoint, and event subscriptions. The webhook inherits that key's explicit inbox grants and read scopes. A message subscription requires messages:read; a conversation subscription requires conversations:read. Expiry, revocation, or disabling the application stops delivery.
Subscribe to message receipt and delivery states, conversation changes, handoffs, connection changes, and contact updates. The broad message.created and message.updated events are available through both the API and settings UI. An attachment added after the initial message produces message.updated. Private notes, deleted messages, and internal activity messages are excluded. Events are captured transactionally with model writes after the subscription is created. Writes that bypass Rails callbacks do not emit events. Poll the API to reconcile state when necessary.

Event envelope

{ "id": "evt_example", "type": "message.received", "api_version": "v2", "account_id": "acct_example", "occurred_at": "2026-10-21T12:00:00.000000Z", "created_at": "2026-10-21T12:00:00.000000Z", "data": { "id": "msg_example", "conversation_id": "con_example", "connection_id": "conn_example" } }
data contains the corresponding v2 resource representation; the example above abbreviates it. Events are snapshots, may arrive out of order, and may be repeated. Use the event id for deduplication and GET the resource for current state. Legacy account and bot webhooks continue using their existing payloads.

Verify the signature

Copy the signing secret when creating the endpoint. It is shown once. Each request includes:
  • Ruut-Webhook-Id: stable delivery identifier.
  • Ruut-Webhook-Timestamp: Unix timestamp in seconds for this attempt.
  • Ruut-Webhook-Signature: v1= followed by a hex HMAC-SHA256 digest.
Compute the digest over timestamp + "." + raw_request_body using the signing secret. Compare it in constant time before parsing or processing the payload. Reject timestamps outside a short tolerance such as five minutes, synchronize your server clock, and deduplicate the event ID. Never recreate the signed bytes by serializing parsed JSON.
Return a 2xx response promptly after durably accepting the event. Process domain work asynchronously.

Failures and replay

The worker retries network failures, HTTP 429, and 5xx responses up to five attempts with exponential delays. Other HTTP failures are terminal. Redirects are not followed. Local, private, and mixed public/private DNS destinations are blocked; delivery pins the validated address and verifies TLS for the original hostname.
Delivery history shows the latest 50 events, attempt counts, HTTP status or error code, and the latest 25 attempt results per delivery. Response bodies are intentionally not stored. Failed and interrupted (unknown) deliveries can be replayed manually; replay preserves the event and delivery IDs. Receivers must deduplicate even if the earlier outcome was uncertain.
Access and visibility are rechecked before dispatch. Events that are no longer authorized are cancelled. A request already in flight may finish after revocation. A scheduled recovery job recovers pending work if enqueueing failed. Interrupted in-flight work becomes unknown for manual review. Delivery records and payloads are retained for 30 days; replay uses the original snapshot and targets the endpoint's current URL and signing secret.
Rotating a signing secret pauses the endpoint. Update your receiver with the replacement secret, then enable the endpoint again. Use Send test event to verify it: tests have type webhook.test and contain no customer data.

Manage subscriptions through the API

Use /api/v2/webhook-endpoints with webhooks:manage to create, list, read, update, or disable endpoints. Supply url, events, and optional connection_ids. Subscriptions remain inside the key's inbox and read permissions. The create response returns the signing secret; list and get responses do not.
Read /api/v2/webhook-deliveries for delivery records and attempts. POST to /api/v2/webhook-deliveries/{delivery_id}/replays to replay exhausted work with the same event and delivery IDs. Every mutation requires Idempotency-Key.
POST to /api/v2/webhook-endpoints/{endpoint_id}/secret-rotations to rotate with a 24-hour verification overlap. API-managed deliveries also include X-Ruut-Signature containing t=TIMESTAMP,v1=DIGEST; during overlap it includes signatures for both secrets. The legacy Ruut-Webhook-* signature headers remain available.