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
| Method | Path | Description |
|---|---|---|
GET | /api/chatembed-all | Load or create the all-groups chat |
POST | /api/chatembed-all/messages | Send a message and stream the AI reply via SSE |
DELETE | /api/chatembed-all/messages | Clear the chat history and remove the chat |
Authentication
Required. The endpoint accepts the user JWT in either:
Authorization: Bearer <token>header, ortoken: <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 type | Description |
|---|---|
user_message | Confirms the user's message was saved. Use this to replace an optimistic UI placeholder. |
status | Short status label such as Loading..., Understanding the prompt..., or Formulating answer.... |
chunk | Incremental token of the AI reply. Append each chunk to the streaming message. |
done | Final, persisted AI message. Contains metadata.contentReferences when the AI references videos. |
error | If 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
- Collect groups: The server uses the
User↔Groupmany-to-many relationship (throughUserGroup) to find every group the authenticated user belongs to. - Aggregate content: It pulls all
video,audio, andlive streamingcontent linked to those groups throughContentGroupandGroupCourse, then deduplicates bycontentId. - Collect context: It fetches the latest 25 chat messages and 25 posts across all those groups.
- Rephrase and search: The user's prompt is classified into
video-only,audio-only,live-only, oranyand converted into Qdrant-optimized queries. The vector database is searched acrosstranscript-short-segments,transcript-segments-with-context,video-section-summaries,video-concept-summaries, andvideo-metadata, filtered to the aggregatedcontentIds. - Stream the answer: The retrieved context is sent to OpenAI and the reply is streamed back to the client in
chunkevents.
Building a Custom Chat UI
A minimal integration follows the same pattern as the built-in ChatEmbedPage:
- Load history on mount:
const res = await fetch("/api/chatembed-all", { headers: { token } });
const { messages } = await res.json();
- 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;
}
}
}
- 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
AIChattable byGroupId: nullandUserId. - Messages are returned in ascending chronological order.
- The
doneevent'saiMessage.metadata.contentReferencescontains 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.