Bot Webhook Reference
Configure an endpoint with Bots & Webhooks. The receiving tool gets message text and account, room, and message identifiers. Use a tool whose data policy permits this access.
Request body
Section titled “Request body”{ "version": 1, "id": "stable-delivery-id", "type": "message.created", "triggers": ["direct_message", "mention"], "occurred_at": "2026-09-05T12:00:00Z", "bot_id": "bot-id", "room_id": "room-id", "thread_root_id": null, "message": { "id": "message-id", "author_id": "author-id", "body": "Hello @helper_bot" }}Use triggers to route mentions and DMs. thread_root_id is null for a root
message. The body does not contain attachments. Chatto does not change this
format for specific tools.
Return HTTP 2xx when you accept the request. Do long tasks separately, and reply with the bot API key through the normal API. Chatto ignores the response body.
Signatures and authentication
Section titled “Signatures and authentication”Chatto adds these headers:
Chatto-Webhook-Id: the delivery ID from the body.Chatto-Webhook-Timestamp: Unix time in seconds for this attempt.Chatto-Webhook-Signature:v1=followed by a hexadecimal HMAC-SHA256.
To verify a request:
- Use the signing secret as its displayed UTF-8 text. Do not Base64-decode it.
- Compute HMAC-SHA256 over the timestamp, a full stop (
.), and the exact request body bytes. - Compare the result in constant time.
- Reject old timestamps, for example older than five minutes.
- Deduplicate by delivery ID. A retry has the same ID and a new timestamp.
If your tool cannot verify signatures, authenticate with a secret URL or the
Authorization header instead.
Retries, expiry, and access
Section titled “Retries, expiry, and access”Chatto retries transport failures and all non-2xx responses. It does not follow redirects. By default, Chatto makes up to five attempts within 24 hours of the message. The delay starts at 30 seconds and doubles up to 30 minutes. Each request has a 10-second timeout. To change these values, see Outbound bot webhooks.
Delivery is best effort. A server restart discards pending requests and retries without a failure record. Requests can arrive more than once or out of order, so use the delivery ID to prevent repeated work.
Before each attempt, Chatto checks the current access of the bot. It skips the request if the bot lost access, the message is unavailable, or the endpoint is paused or revoked. The body contains the current message text, so an edit can change it between attempts.
Select Recent failures on an endpoint to see failed deliveries with time,
attempt count, HTTP status, and failure category. Chatto keeps failures for
seven days; change this with core.log.retention. Chatto does not record
successes, so an empty list does not prove that delivery succeeded.
Activate a bot from Chatto activity
Section titled “Activate a bot from Chatto activity”To react to all activity that the bot can see, use the normal realtime
subscription with LIVE_ONLY. There is no bot-only channel. See
Realtime and the
RealtimeEvent
reference.
To react only when Chatto would notify the bot, read
NotificationService.ListNotificationOccurrences and filter by cause:
| Cause | When Chatto creates it |
|---|---|
direct_message_received | Another account sends a message in a DM with the bot. |
direct_mention_received | Another account mentions the bot directly in a channel room. |
reply_received | Another account replies to a message from the bot. |
followed_thread_activity | Another account posts in a thread that the bot follows. |
Ignore other causes. A delivered direct mention also makes the bot follow the
thread, so later replies arrive as followed_thread_activity. An explicit
unfollow stays in effect.
Save the IDs of processed occurrences, because one occurrence can appear more
than once. One message can create more than one cause. To act only once for
each message, also deduplicate by event_id. After a disconnect, read the list
again to recover missed occurrences within the notification retention period.
Then load the message or thread, for example with
ThreadService.GetThreadEvents.