Bots & Webhooks
A bot is a visible user account for an unattended integration. It uses the normal public ConnectRPC API and realtime protocol. A bot starts with no permissions and cannot sign in through the login forms.
Create and configure a bot
Section titled “Create and configure a bot”- Open Server Admin → Bots and select Create Bot.
- Enter a username and a display name.
- Copy the API key before you close the dialog. Chatto cannot show it again.
- Open the detail page of the bot and select Permissions. Enable the server, room-group, or room permissions that the integration needs.
- Enable
room.joinfor the rooms that the bot needs. In the Joined row at the top of the matrix, select each room to add the bot, and confirm. Clear a room to remove the bot.
On a new server, only the admin role has bot.create. To let members create
bots, allow bot.create for everyone or for a role. A human owner can always
manage their bots. A bot with an explicit bot.create grant can create a bot
for its own human owner. The new bot starts without permissions. Bot creators
need bot.manage for later management. Accounts with bot.manage can manage all bots and can select
Reassign owner to give a bot to another active human account. Reassignment
keeps the permissions and API keys of the bot. If the previous owner must lose
access, create a new key and revoke the old one.
When you delete the owner account, Chatto also deletes all bots that the account owns. Reassign long-lived bots first.
Grant permissions
Section titled “Grant permissions”Bots do not inherit everyone, named roles, or the roles of their owner. The
bot matrix is an allowlist. A permission is effective only while the owner also
has it at that scope. A lock icon marks a permission that the owner ceiling
blocks. If the owner loses a permission, the bot also loses it. Bots do not
need privileged mode, and they keep working while the owner is signed out.
To grant a permission that requires elevation, activate privileged mode. You must have that permission active at the target scope. Removal of a grant does not require activation.
Room membership alone does not let a bot read messages. Grant one read permission:
message.readreads all messages in the room. It includesmessage.read-interactions.message.read-interactionsreads only complete threads that the bot started, where another account mentioned it directly, or where it received a DM. A mention also gives access to older messages in that thread.
Grant one post permission:
message.postposts root messages and thread replies.message.post-in-threadposts replies in all readable threads.message.post-in-interactionsposts replies only in the threads thatmessage.read-interactionsallows.
For a bot that reads all messages but replies only when someone speaks to it,
grant message.read and message.post-in-interactions.
You can add your own bots to rooms without room.manage. Room suspensions and
archived rooms prevent joining. Universal-room membership is automatic.
Authenticate requests
Section titled “Authenticate requests”Send the API key as a bearer credential:
Authorization: Bearer cht_BK_…Requests use the bot’s permissions and its owner’s current authority. Grant
bot.manage only when you intend to delegate management of other bots, including
issuing their credentials. Bots cannot acquire human passwords, sessions,
OAuth tokens, verified email addresses, or external logins.
See the BotService reference for API methods.
Create and revoke API keys
Section titled “Create and revoke API keys”A bot can have at most 20 active API keys. Create one named key for each integration. To replace a key, create a new key, move the integration to it, and revoke the old key. Revocation immediately makes only that key invalid and closes its realtime connections.
The Integrations page of the bot shows when each key was created and approximately when Chatto last recorded its use. No use recorded does not prove that nobody used the key.
Direct messages
Section titled “Direct messages”A bot can start a DM with RoomService.StartDM when it has message.post
at the Direct messages scope. It can also use this method to find an
existing DM without posting permission. To let a bot talk in DMs without
channel access,
grant message.read and message.post at the Direct messages scope. The
owner must have the same permissions at that scope. For a bot that only
replies, message.read-interactions at this scope is enough to read its DMs
and receive their outbound webhooks.
Post from an external webhook
Section titled “Post from an external webhook”An incoming webhook lets an external tool post as the bot without an API key.
- Open the detail page of the bot, select Integrations, and then select Create Webhook.
- Enter a name that identifies the caller. Optionally, select a destination channel room. Chatto adds its room ID to the URL.
- Copy the complete URL before you close the dialog. Chatto cannot show it again.
Send JSON with Slack-compatible text and channel fields:
POST /webhooks/incoming/YOUR_WEBHOOK_CREDENTIALContent-Type: application/json
{"text":"Deployment finished","channel":"YOUR_ROOM_ID"}- Chatto also accepts
messageorbodyfor the text, androom_idfor the room. You can putroom_idin the URL query string. - Every request needs a room ID. Use the ID, not the room name. If you send more than one text field or room ID, all non-empty values must match.
- Set
"create_thread": trueto start a thread in a channel room that supports threads. - The bot must be a member of the room and have
message.post. A webhook can post to an existing DM that includes the bot. Use an API key andRoomService.StartDMto create the DM first. - A successful request returns HTTP 200 with the body
ok. There is no idempotency key, so a retry can post the message two times.
A bot can have at most 20 active webhooks. Create one webhook for each integration. To replace a webhook, create a new one, move the caller to it, and revoke the old one.
Webhook troubleshooting
Section titled “Webhook troubleshooting”| Response | Check |
|---|---|
400 invalid_payload | Send valid JSON with non-empty text, message, or body, and a room ID. Make sure that duplicate fields match. Message size and room policy limits apply. |
404 channel_not_found | Use the room ID. Make sure that the bot is a member, and that the bot and its owner can post there. |
401 invalid_token | The credential is invalid or revoked. Create a new webhook and update the caller. |
Send Grafana alerts
Section titled “Send Grafana alerts”Grafana’s Webhook integration works without a custom payload. Chatto reads
the message field of the default Grafana JSON.
- Create a bot, add it to the destination channel room, and grant it
message.post. The owner must have this permission too. - Create an incoming webhook named
Grafanaand select the destination room. Make sure that the URL ends with?room_id=YOUR_ROOM_ID. - In Grafana Alerting, open Contact points and add a contact point. Select Webhook and paste the Chatto URL. Keep the POST method. Leave Custom Payload unset.
- Send a test notification and make sure that it appears in the room. Then select the contact point in an alert rule or a notification policy.
To change the text, use the Message field of the contact point. You can use Grafana notification templates there. Firing and resolved alerts post separate messages. Chatto does not update or group earlier alerts. See Grafana’s webhook documentation.
Outbound webhooks
Section titled “Outbound webhooks”An outbound webhook sends an HTTP request to your tool when someone speaks to the bot.
- Open the bot in Server Admin → Bots and select Integrations. In Outbound webhooks, select Create webhook.
- Enter a name, the destination URL, and, if necessary, the complete
Authorizationheader value. - Copy the signing secret if your tool verifies signatures. Chatto shows it only once.
Each enabled endpoint receives new messages, including thread replies, that mention the bot directly or that are in a DM with the bot. A DM that mentions the bot sends one request with both triggers. Messages from the bot, ordinary channel messages, edits, and reactions do not send requests. Notification preferences do not apply.
- A bot can have up to 20 endpoints, including paused ones.
- Edit webhook changes the URL and the
Authorizationheader. It keeps the signing secret and cancels queued retries. To change the name or secret, create a new endpoint and revoke the old one. - Pause stops new requests and cancels queued retries. Resume does not send messages from the paused period.
- Revoke webhook removes the endpoint permanently.
Destinations require public HTTPS. localhost and *.localhost also permit
HTTP, but only when every resolved address is a loopback address. IP literals
such as 127.0.0.1 and other private-network hosts are not permitted.
The Runling bot example receives these requests and replies through the Chatto API.
See the Bot Webhook Reference for payloads, signature verification, delivery retries, and reply handling. Your receiving tool gets message content; check its data policy before you connect it.