SilentChat

Team chat API

With team chat, your staff write to each other directly or in groups — with files, mentions and a reference to a customer conversation. The dashboard and our app use exactly the endpoints on this page. Base URL as for the rest of the API: https://api.silentchat.de/api

Access

  • Included from the first paid plan. Without team chat in the plan, every endpoint responds with 403 ERR_FEATURE_NOT_AVAILABLE.
  • Only with a signed-in user’s access token (Authorization: Bearer …). API keys are rejected, because team chat always belongs to a person.
  • Lite seats can read and set their read status, but cannot write, create or manage.
  • Only members can see a chat — administrators cannot read other people’s direct messages either. For everyone else a chat responds as if it did not exist (404).

Endpoints

All paths relative to the base URL. People appear in responses only as { id, display_name, avatar_url }.

MethodPathDescription
GET/v1/team-chat/channelsYour chats, most recently active first, with unread count, last message and, for direct chats, the other person (peer). Cursor-based.
POST/v1/team-chat/channelsCreate a group: { name, member_ids[] }. At most 200 members.
POST/v1/team-chat/directGet or create a direct chat with a person: { user_id }. There is exactly one per pair.
GET/v1/team-chat/channels/:idA chat with all members and can_manage (may rename, archive, manage members).
PATCH/v1/team-chat/channels/:idRename or archive a group: { name?, is_archived? }. Group owner and administrators only.
POST/v1/team-chat/channels/:id/membersAdd members: { user_ids[] }. Only people from the same account.
DELETE/v1/team-chat/channels/:id/members/:user_idRemove a member or leave the group yourself.
GET/v1/team-chat/channels/:id/messagesHistory, newest first, cursor-based (limit default 25, at most 100).
POST/v1/team-chat/channels/:id/messagesSend a message: { content, conversation_id?, file_ids? }.
POST/v1/team-chat/channels/:id/readRead up to a message: { message_id }.
PATCH/v1/team-chat/channels/:id/membershipMute for yourself only: { is_muted }. Muted means no notification for direct messages and no count in /unread — mentions still notify you. Allowed for lite seats too.
PATCH/v1/team-chat/messages/:idEdit your own message: { content } — up to 15 minutes after sending.
DELETE/v1/team-chat/messages/:idDelete your own message. A placeholder remains, attachments are removed.
GET/v1/team-chat/unreadTotal of all unread messages: { unread_count } — for the sidebar and app badge.
GET/v1/team-chat/files/:idShort-lived link to an attachment (members only). With ?download=true always as a download.

Paging

Lists return data and pagination. While hasMore is true, fetch the next page with the cursor from the last response. A tampered cursor results in 400 ERR_INVALID_CURSOR.

GET /api/v1/team-chat/channels/:id/messages?limit=50&cursor=<token>

200 → {
  "data": [ { "id": "…", "content": "…", "created_at": "2026-09-17T09:04:00Z", … } ],
  "pagination": { "cursor": "eyJhdCI6…", "hasMore": true }
}

Messages

A message needs text, attachments or a reference to a customer conversation — at least one of them. Text is at most 10,000 characters long.

POST /api/v1/team-chat/channels/:id/messages
{
  "content": "<@5f0c6b1e-3a1d-4c55-9a1e-2b7d0c1e4f10> can you take this one?",
  "conversation_id": "…",   // optional
  "file_ids": ["…"]         // optional, max. 10
}

201 → { "message": { "id": "…", "mentions": ["5f0c6b1e-…"], "attachments": [ … ], … } }
  • Mentions appear in the text as <@user-id>. Only chat members count; the response lists them in mentions. Display the person’s name instead.
  • conversation_id refers to a customer conversation of your account; a foreign one results in 400 ERR_INVALID_CONVERSATION.
  • Editing is possible for 15 minutes, deleting at any time. Deleted messages return removed_at and no content.
  • Text is never interpreted as HTML. Display it as plain text.

Attachments

  1. Request an upload: POST /api/v1/files/upload with file name, type and size — without conversation_id.
  2. Send the file via PUT to the returned upload_url.
  3. Pass the file_ids when sending (at most 10). Only now do we check the actual content against the declared type; at most 20 MB per file.
  4. To display or download, get a link via GET /api/v1/team-chat/files/:id. It is valid for just under an hour (expires_at).
POST /api/v1/files/upload
{ "filename": "screenshot.png", "mime_type": "image/png", "size": 48213 }
201 → { "file": { "id": "…" }, "upload_url": "https://…" }

PUT <upload_url>            (Content-Type: image/png, body = file)

POST /api/v1/team-chat/channels/:id/messages
{ "content": "", "file_ids": ["…"] }

GET /api/v1/team-chat/files/:file_id?download=true
200 → { "file": { "url": "https://…", "expires_at": "…", "filename": "…", "mime_type": "…", "size": 48213 } }

The general endpoint /api/v1/files/:id/download does not serve team attachments. Uploaded files that are not attached to a message within 24 hours are cleaned up.

Real time

Via the dashboard’s WebSocket connection (user token) you join the room team:<id> — members only. New chats and unread counts also arrive via your personal user room.

EventRoomDescription
team.message.newteam:<id>New message, complete as in the API.
team.message.updatedteam:<id>Message edited.
team.message.removedteam:<id>Message deleted: { channel_id, message_id }.
team.readteam:<id>, user roomSomeone has read: { channel_id, user_id, message_id }.
team.channel.updatedteam:<id>Name, archive state or members changed. With removed: true to the person who was removed.
team.message.newuser roomShort form { channel_id, message_id } for chats that are not open — a cue to reload the list and counters.
team.channel.updateduser roomMuted or unmuted on another device: { channel_id, is_muted } — reload the list and the unread count.
team.channel.addeduser roomYou were added to a chat: { channel_id }.

Notifications

Direct messages and mentions in groups trigger the event team.message — as an entry in the bell, as a toast and as a browser push, depending on the person’s settings (GET/PUT /api/v1/me/notification-preferences). The metadata contains channel_id and message_id, and for mentions mention: "true".

Error codes

StatusCodeDescription
403ERR_USER_TOKEN_REQUIREDCalled with an API key instead of a user token.
403ERR_FEATURE_NOT_AVAILABLEThe plan does not include team chat.
403ERR_LITE_SEAT_RESTRICTEDA lite seat tried to write.
404ERR_NOT_CHANNEL_MEMBERThe chat does not exist, or you are not a member.
400ERR_USER_NOT_IN_TENANTThe person does not belong to your account.
400ERR_INVALID_CONVERSATIONThe customer conversation does not belong to your account.
400ERR_INVALID_ATTACHMENTThe file does not exist, belongs to someone else, is already attached to a message or was never uploaded.
400ERR_FILE_TOO_LARGEThe file is larger than 20 MB.
400ERR_FILE_MIME_MISMATCHThe content does not match the declared type; the file was removed.
400ERR_INVALID_CURSORThe cursor is invalid.
409ERR_CHANNEL_ARCHIVEDThe group is archived.
409ERR_MESSAGE_NOT_EDITABLEThe message is older than 15 minutes or was deleted.

All errors follow the usual format { "error": …, "code": … } — see error codes.