API
All routes and connections require a JWT and the four CPET headers (X-Customer, X-Product, X-Env, X-Tenant).
WebSocket
Section titled “WebSocket”Connect
Section titled “Connect”wss://<host>/chat/joinThe JWT may be supplied via the Authorization header, a jwt cookie, or a ?token=<jwt> query parameter (the query form is what makes browser WebSocket auth possible). The authenticated user id is the identity; the connection is implicitly subscribed to every chat the user belongs to.
Client → server frames
Section titled “Client → server frames”{ "action": "<action>", "body": { … } }action | body | Effect |
|---|---|---|
listchats | {} | List the caller’s chats |
getmessages | {chatid, threadid, since} | Fetch messages since a timestamp (empty = all); replies to the calling socket only |
publishmessage | {chatid, threadid, message, blocks:{data:[…]}, clientidentifier} | Post a message; fanned out to all members |
createchat | {name, chattype, visibility, members:{data:[…]}} | Create a chat; pushed to all members |
lastseentill | {chatid, threadid, seentill} | Advance the caller’s read marker |
listfilesinchat | {chatid, meta, media, depth, subfolder} | List files shared in a chat |
userevent.action | {chatid, threadid, …} | Broadcast a transient event (typing, presence) to chat members |
Server → client frames
Section titled “Server → client frames”Success:
{ "action": "<action>", "status": "success", "response": { "data": { … } } }Error:
{ "status": "error", "error": { "code": "rtc-…", "message": "…" } }Server-pushed (no client request):
| Frame | Payload |
|---|---|
publishmessage | response.data.chatid, response.data.rtmchatthreadmessage, and the echoed clientidentifier (for optimistic-UI dedupe) |
createchat | The new chat, pushed to every member |
lastseentill | Read-marker updates |
notification.received | response.data.inappnotification — an in-app notification |
userevent.action | response.data{userid, chatid, threadid, …} |
getmessages, listchats, and listfilesinchat reply only to the requesting socket; publishmessage, createchat, lastseentill, and notifications fan out to all recipients’ sockets.
Message blocks
Section titled “Message blocks”A message’s blocks.data[] carries structured content, each {type, id, detail}. Types include mentions, reactions, files, code, text, and more. A mention or reaction block additionally generates an in-app notification to the referenced users.
| Method | Path | Purpose |
|---|---|---|
| POST | /chat/single | Create a 1:1 chat — {name, visibility, members:{data:[{id,type}]}} |
| POST | /chat/group | Create a group chat |
| GET | /chat/info/:chatid | Chat + its default thread |
| GET | /chat/fetch/:chatid/thread/:threadid/since/:timestamp | Page of messages (newest first) |
| POST | /chat/message/:chatid | Post a message (REST equivalent of publishmessage) |
| PATCH | /chat/list | The caller’s chats |
| GET | /chat/join | WebSocket upgrade |
| Method | Path | Purpose |
|---|---|---|
| POST / PUT | /chat/bot | Register / update a bot — {name, displayname, config:{…}, avatar, state} |
| GET | /chat/bot/:botid | Fetch a bot |
| PATCH | /chat/botlist | List bots |
A bot’s config holds the callback URLs the service invokes when a conversation starts, a message is posted, or a conversation closes.
Files shared in a chat are stored through the Content block:
| Method | Path | Purpose |
|---|---|---|
| POST | /chat/id/:chatid/file?filename=&description=&media= | Upload (raw body) |
| PUT | /chat/id/:chatid/file/:fileid | Replace |
| GET | /chat/id/:chatid/file/:fileid | Download (streamed) |
| DELETE | /chat/id/:chatid/file/:fileid | Delete |
| PATCH | /chat/id/:chatid/file | List files |
Notifications ingress
Section titled “Notifications ingress”| Method | Path | Purpose |
|---|---|---|
| POST | /notifications/send | Used by the Notifications block to push in-app notifications to live connections — {status, notifications:[…]} |
Health
Section titled “Health”GET /health, GET /ready — unauthenticated.