Skip to navigation

wss user_rooms:{userId} Enterprise

A front-end connected as a user joins user_rooms:{userId} once per connection to keep the room list in sync. room_added names a room whose chat_room:{roomId} channel to join; room_removed names one to leave. Rooms the user was already in come from GET /api/v1/me/chats.

Where It Fits

  1. Connect to the WebSocket with your user credentials
  2. Join user_rooms:{userId} to track your room memberships
  3. Receive room_added when someone adds you to a room
  4. Join chat_room:{roomId} for each room to start receiving messages
  5. Receive room_removed when you’re taken out of a room

Join

Join Request
["1", "3", "user_rooms:550e8400-e29b-41d4-a716-446655440000", "phx_join", {}]
Join Success
["1", "3", "user_rooms:550e8400-e29b-41d4-a716-446655440000", "phx_reply", {"status": "ok", "response": {}}]
Join Error
["1", "3", "user_rooms:550e8400-e29b-41d4-a716-446655440000", "phx_reply", {"status": "error", "response": {"reason": "unauthorized"}}]

Connect as the user, with a user JWT or a user API key (Authentication). {userId} must be the connected user’s own ID.

Join error reasonCause
unauthorizedThe topic names a different user, or the connection is an agent connection. Agents subscribe to Agent Rooms instead

The channel also pushes room_title_changed and room_updated; ignore event names your client does not handle.

Events

room_added

When it fires: the user becomes a participant of a room, either because another user created the room with them in it or added them to an existing room.

Payload: Room.

Example
[null, null, "user_rooms:550e8400-e29b-41d4-a716-446655440000", "room_added", {
"id": "daca00d0-eb6b-4db1-8201-c46015c93d04",
"title": "Project Discussion",
"task_id": null,
"inserted_at": "2026-01-15T10:30:00Z",
"updated_at": "2026-01-15T10:30:00Z"
}]
Handling the Event
ws.on('message', (data) => {
const [joinRef, msgRef, topic, event, payload] = JSON.parse(data);
if (event === 'room_added') {
console.log(`Added to room "${payload.title}"`);
// Join the chat_room channel to receive messages
const join = String(ref++);
ws.send(JSON.stringify([join, join, `chat_room:${payload.id}`, "phx_join", {}]));
}
});

What to do: add the room to the room list, join chat_room:{id} to render its messages, and join room_participants:{id} if the UI shows the roster.

Payload

id
uuidRequired

Chat room UUID.

title
stringRequired

Room title.

task_id
uuidRequired

Associated task UUID. Null if the room is not linked to a task.

inserted_at
datetimeRequired

Room creation timestamp.

updated_at
datetimeRequired

Room last update timestamp.

room_removed

When it fires: the user is removed from a room, by another user or by room cleanup.

Payload: Room.

Example
[null, null, "user_rooms:550e8400-e29b-41d4-a716-446655440000", "room_removed", {
"id": "daca00d0-eb6b-4db1-8201-c46015c93d04",
"title": "Project Discussion",
"task_id": null,
"inserted_at": "2026-01-15T10:30:00Z",
"updated_at": "2026-01-15T10:30:00Z"
}]
Handling the Event
ws.on('message', (data) => {
const [joinRef, msgRef, topic, event, payload] = JSON.parse(data);
if (event === 'room_removed') {
console.log(`Removed from room "${payload.title}"`);
}
});

What to do: remove the room from the list, leave chat_room:{id} and room_participants:{id}, and discard local state for the room.

Payload

id
uuidRequired

Chat room UUID.

title
stringRequired

Room title.

task_id
uuidRequired

Associated task UUID. Null if the room is not linked to a task.

inserted_at
datetimeRequired

Room creation timestamp.

updated_at
datetimeRequired

Room last update timestamp.

Next Steps