Skip to main content

Chat Across All User Groups

This endpoint retrieves or creates an AI-powered chat session that spans every group the authenticated user belongs to. Instead of restricting the conversation to a single group, the AI searches across the combined video, audio, and live content of all the user's groups and returns a grounded, contextual answer.

For a single-group chat, see Get or Initialize Chat by Group ID.

Endpoints​

MethodPathDescription
GET/api/chatembed-allLoad or create the all-groups chat
POST/api/chatembed-all/messagesSend a message and stream the AI reply via SSE
DELETE/api/chatembed-all/messagesClear the chat history and remove the chat

Authentication​

Required. The endpoint accepts the user JWT in either:

  • Authorization: Bearer <token> header, or
  • token: <token> header (used by embed and mobile clients)

GET /api/chatembed-all​

Retrieves the all-groups AIChat for the current user. If none exists, one is created automatically.

Success Response​

Code: 200 OK

Content Example:

{
"aiChat": {
"id": 93,
"GroupId": null,
"UserId": 123,
"title": "All Groups Chat",
"createdAt": "2026-08-27T10:15:00.000Z",
"updatedAt": "2026-08-27T10:15:00.000Z"
},
"messages": [
{
"id": 202,
"message": "Welcome back! Ask me anything across all your groups.",
"agent": true,
"isAI": true,
"UserId": null,
"createdAt": "2026-08-27T10:15:00.000Z",
"metadata": null,
"user": null
}
],
"createdNewChat": true
}

Error Response​

Code: 500 Internal Server Error

Content Example:

{ "error": "Failed to retrieve or initialize chat" }

POST /api/chatembed-all/messages​

Sends a user message and streams the AI response back as Server-Sent Events (SSE).

Request​

Headers:

Content-Type: application/json
token: <jwt>

Body:

{
"message": "What does the course say about trust?"
}

Response — Server-Sent Events​

Code: 200 OK

Content-Type: text/event-stream

Each SSE line is data: <json>\n\n. Every event has a type field:

Event typeDescription
user_messageConfirms the user's message was saved. Use this to replace an optimistic UI placeholder.
statusShort status label such as Loading..., Understanding the prompt..., or Formulating answer....
chunkIncremental token of the AI reply. Append each chunk to the streaming message.
doneFinal, persisted AI message. Contains metadata.contentReferences when the AI references videos.
errorIf something goes wrong. The stream ends.

Example SSE stream​

data: {"type":"user_message","userMessage":{"id":203,"message":"What does the course say about trust?","createdAt":"...","user":{"id":123,"name":"Leon"}}}

data: {"type":"status","message":"Loading..."}

data: {"type":"status","message":"Searching All Your Groups library for trust, trusting God..."}

data: {"type":"chunk","text":"The"}

data: {"type":"chunk","text":" videos in your groups talk about trust as..."}

data: {"type":"done","aiMessage":{"id":45,"message":"The videos in your groups talk about trust...","metadata":{"contentReferences":[{"contentId":12345,"title":"Trusting God","startTime":0}]}}}

DELETE /api/chatembed-all/messages​

Deletes the all-groups chat and all of its messages.

Success Response​

Code: 200 OK

Content Example:

{
"success": true,
"deleted": 5
}

Error Response​

Code: 404 Not Found

Content Example:

{ "error": "Chat not found" }

How It Works​

  1. Collect groups: The server uses the User ↔ Group many-to-many relationship (through UserGroup) to find every group the authenticated user belongs to.
  2. Aggregate content: It pulls all video, audio, and live streaming content linked to those groups through ContentGroup and GroupCourse, then deduplicates by contentId.
  3. Collect context: It fetches the latest 25 chat messages and 25 posts across all those groups.
  4. Rephrase and search: The user's prompt is classified into video-only, audio-only, live-only, or any and converted into Qdrant-optimized queries. The vector database is searched across transcript-short-segments, transcript-segments-with-context, video-section-summaries, video-concept-summaries, and video-metadata, filtered to the aggregated contentIds.
  5. Stream the answer: The retrieved context is sent to OpenAI and the reply is streamed back to the client in chunk events.

Building a Custom Chat UI​

A minimal integration follows the same pattern as the built-in ChatEmbedPage:

  1. Load history on mount:
const res = await fetch("/api/chatembed-all", { headers: { token } });
const { messages } = await res.json();
  1. Send a message and read the SSE stream:
const response = await fetch("/api/chatembed-all/messages", {
method: "POST",
headers: {
"Content-Type": "application/json",
token
},
body: JSON.stringify({ message: "What does the course say about trust?" })
});

const reader = response.body.getReader();
const decoder = new TextDecoder();
let buffer = "";

while (true) {
const { done, value } = await reader.read();
if (done) break;

buffer += decoder.decode(value, { stream: true });
const lines = buffer.split("\n");
buffer = lines.pop();

for (const line of lines) {
if (!line.startsWith("data: ")) continue;

const event = JSON.parse(line.slice(6));

switch (event.type) {
case "user_message":
// Replace the optimistic user message with the server-confirmed one
break;
case "status":
// Show the status label above the streaming message
break;
case "chunk":
// Append to the streaming AI message
break;
case "done":
// Persist the final AI message
// event.aiMessage.metadata?.contentReferences contains referenced videos
break;
case "error":
// Show an error and stop the stream
break;
}
}
}
  1. Clear history:
await fetch("/api/chatembed-all/messages", {
method: "DELETE",
headers: { token }
});

Example cURL​

Initialize the chat:

curl -X GET "https://api.tribesocial.io/api/chatembed-all" \
-H "token: <jwt>"

Send a message:

curl -X POST "https://api.tribesocial.io/api/chatembed-all/messages" \
-H "Content-Type: application/json" \
-H "token: <jwt>" \
-d '{"message": "What does the course say about trust?"}'

Clear chat:

curl -X DELETE "https://api.tribesocial.io/api/chatembed-all/messages" \
-H "token: <jwt>"

Notes​

  • A user has exactly one all-groups chat at a time. It is identified in the AIChat table by GroupId: null and UserId.
  • Messages are returned in ascending chronological order.
  • The done event's aiMessage.metadata.contentReferences contains referenced videos when the AI cites specific content.
  • If the user does not belong to any groups, the chat is still created but the AI will have no content to search.
  • The AI filters responses by the requested content type. Asking for a video, audio, or livestream will limit the search accordingly.