Documentation

Group chat

Multi-member chat rooms backed by the CommunityChatGateway WebSocket.

A group is a multi-member chat room: a named space with a member list, role-based posting, and a persistent message history. Groups share the CommunityChatGateway WebSocket namespace with direct messaging but have their own REST endpoints and their own socket rooms.

Endpoints

POST/client/community/groupsJWT
GET/client/community/groupsJWT
GET/client/community/groups/:groupIdJWT
POST/client/community/groups/:groupId/messagesJWT
GET/client/community/groups/:groupId/messagesJWT
POST/client/community/groups/:groupId/membersJWT
DELETE/client/community/groups/:groupId/members/:emailJWT

Creating a group

await fetch('/client/community/groups', {
  method: 'POST',
  headers: {
    orgid: 'my-org',
    Authorization: `Bearer ${customerJwt}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    name: 'Logo project',
    description: 'Working group for the Q2 rebrand',
    type: 'private',                  // 'public' | 'private'
    members: [
      { email: '[email protected]', role: 'member' },
      { email: '[email protected]', role: 'admin' },
    ],
    page: 'optional-page-id',         // attach to a community page
  }),
});

The creator becomes an admin automatically. Members not yet in the org are still added — they'll see the group on their next sign-in.

Listing your groups

GET /client/community/groups returns { data, total } for groups the caller belongs to. Filters: ?page=<pageId>, limit, pageNum.

Sending messages

There are two ways to send into a group: REST and the WebSocket gateway. REST is the simplest path for occasional sends or non-real-time clients; WS gives you live fan-out and typing indicators.

REST

await fetch(`/client/community/groups/${groupId}/messages`, {
  method: 'POST',
  headers: {
    orgid: 'my-org',
    Authorization: `Bearer ${customerJwt}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    content: 'Approved — let’s ship.',
    contentType: 'text',
    attachments: [],
    replyTo: undefined,
  }),
});

WebSocket

import { io } from 'socket.io-client';

const socket = io('https://appengine.appmint.io/community-chat', {
  transports: ['websocket'],
  auth: { token: customerJwt, orgId: 'my-org' },
});

// On connect, the gateway auto-joins all groups the user belongs to.

socket.emit('sendGroupMessage', {
  groupId: 'group-id-here',
  content: 'Hi team',
  contentType: 'text',
});

socket.on('newGroupMessage', (msg) => { /* render */ });
socket.on('groupTyping', ({ groupId, from }) => { /* show indicator */ });

Joining and leaving group rooms manually

If your client lazily joins rooms (rather than auto-joining on connect):

socket.emit('joinGroup', { groupId });
socket.emit('leaveGroup', { groupId });

Member management

// Add a member
await fetch(`/client/community/groups/${groupId}/members`, {
  method: 'POST',
  headers: { orgid: 'my-org', Authorization: `Bearer ${jwt}`, 'Content-Type': 'application/json' },
  body: JSON.stringify({ email: '[email protected]', role: 'member' }),
});

// Remove
await fetch(`/client/community/groups/${groupId}/members/[email protected]`, {
  method: 'DELETE',
  headers: { orgid: 'my-org', Authorization: `Bearer ${jwt}` },
});

Member roles are admin and member. Only admins can add/remove members or rename the group.

Reading history

GET /client/community/groups/:groupId/messages returns messages in reverse-chronological order with limit + before cursor params. Combine with the newGroupMessage socket event to keep an open chat window in sync.

const res = await fetch(
  `/client/community/groups/${groupId}/messages?limit=50&before=${oldestSeenId}`,
  { headers: { orgid: 'my-org', Authorization: `Bearer ${jwt}` } }
);

Group chat vs. staff chat

The Community group chat is for member-to-member conversation. The staff ChatModule (under /chat/*) handles customer-support style inbound — it has presence, queues, AI assistant routing, and CRM inbox integration. They're distinct namespaces; do not pipe community group messages through the staff chat.

Group rooms are scoped per org — the WebSocket connection's orgId from the handshake is the boundary. A user with the same email in two orgs will see two distinct group sets, one per token.