Support Message Controller
Controller: support.message.controller.js
Module: Conversation-v2
Purpose: Handles bidirectional messaging between support agents and customers
Overview
The Support Message controller manages message exchange in support conversations. It provides separate endpoints for agents (team) and customers (support widget), enabling real-time communication with Socket.IO integration.
Methods
1. Send Message (Agent) (sendMessage)
Sends a message from support agent to customer.
Endpoint: POST /api/conversation-v2/support/message
Authentication: Required (JWT - agent)
Request Body:
{
"room_id": "507f1f77bcf86cd799439011",
"message": {
"type": "text",
"content": "Hello! How can I assist you today?"
},
"new_room": false,
"integration_app": null
}
Response:
{
"success": true,
"messages": {
"message": {
"_id": "507f1f77bcf86cd799439020",
"room_id": "507f1f77bcf86cd799439011",
"conversation_id": "507f1f77bcf86cd799439012",
"content": "Hello! How can I assist you today?",
"type": "text",
"created_at": "2025-10-08T10:30:00.000Z"
}
}
}
MongoDB Operations:
| Collection | Operation | Query | Purpose |
|---|---|---|---|
messages | insertOne | New message | Create message |
rooms | updateOne | Update last message | Room metadata |
Business Logic:
- Message sent from agent's conversation context
- Broadcasts to customer via Socket.IO (type: 'team')
- Notes (
type: 'note') not broadcasted to customer - Optional integration app tracking for automation
Message Types:
text- Plain text messagenote- Internal agent note (not visible to customer)image- Image attachmentfile- File attachment
Note Messages:
graph TD
A[Agent Sends Message] --> B{Type = note?}
B -->|Yes| C[No Customer Notification]
B -->|No| D[Broadcast to Customer]
C --> E[Only Agents See]
D --> F[Customer Receives]
Use Cases:
- Agent responding to customer inquiry
- Sending attachments or images
- Internal notes between agents
2. Send Message (Customer) (sendUserMessage)
Sends a message from customer to support agents.
Endpoint: POST /api/conversation-v2/support/user/message
Authentication: Support token + session
Request Body:
{
"room_id": "507f1f77bcf86cd799439011",
"message": {
"type": "text",
"content": "I need help with my account"
}
}
Response:
{
"success": true,
"messages": {
"message": {
"_id": "507f1f77bcf86cd799439030",
"room_id": "507f1f77bcf86cd799439011",
"conversation_id": "507f1f77bcf86cd799439031",
"content": "I need help with my account",
"type": "text",
"created_at": "2025-10-08T10:31:00.000Z"
}
}
}
MongoDB Operations:
| Collection | Operation | Query | Purpose |
|---|---|---|---|
messages | insertOne | New message | Create message |
Business Logic:
- Message sent from customer's support conversation
- Uses
support_conversation._idfrom auth context - Broadcasts to assigned agents via Socket.IO (type: 'support')
- Increments unread count for agents
Authentication Flow:
graph TD
A[Customer Widget] --> B[Support Token Auth]
B --> C[Session Validation]
C --> D[Get Support Conversation]
D --> E[Send Message]
E --> F[Broadcast to Agents]
Use Cases:
- Customer asking questions
- Sending files from widget
- Replying to agent messages
3. Query Messages (Agent) (queryMessages)
Retrieves message history for agents viewing support room.
Endpoint: GET /api/conversation-v2/support/message
Authentication: Required (JWT - agent)
Query Parameters:
{
room_id: string;
upperRef?: string; // Pagination - older messages
lowerRef?: string; // Pagination - newer messages
limit?: number; // Messages per page
sort?: 'asc' | 'desc';
search?: string; // Search query
}
Response:
{
"success": true,
"messages": [
{
"_id": "507f1f77bcf86cd799439030",
"content": "I need help with my account",
"conversation_id": "507f1f77bcf86cd799439031",
"created_at": "2025-10-08T10:31:00.000Z",
"sender_type": "customer"
},
{
"_id": "507f1f77bcf86cd799439020",
"content": "Hello! How can I assist you today?",
"conversation_id": "507f1f77bcf86cd799439012",
"created_at": "2025-10-08T10:30:00.000Z",
"sender_type": "agent",
"type": "text"
}
],
"hasMore": true
}
MongoDB Operations:
| Collection | Operation | Query | Purpose |
|---|---|---|---|
messages | find | Pagination query | Get messages |
Business Logic:
- Shows all messages including agent notes
- Supports bidirectional pagination
- Search across message content
- Marks sender type (agent vs customer)
4. Query Messages (Customer) (queryUserMessages)
Retrieves message history for customers in widget.
Endpoint: GET /api/conversation-v2/support/user/message
Authentication: Support token + session
Query Parameters: Same as agent version
Response:
{
"success": true,
"messages": [
{
"_id": "507f1f77bcf86cd799439030",
"content": "I need help with my account",
"created_at": "2025-10-08T10:31:00.000Z",
"is_mine": true
},
{
"_id": "507f1f77bcf86cd799439020",
"content": "Hello! How can I assist you today?",
"created_at": "2025-10-08T10:30:00.000Z",
"is_mine": false
}
]
}
MongoDB Operations:
| Collection | Operation | Query | Purpose |
|---|---|---|---|
messages | find | Filter notes | Get customer-visible messages |
Business Logic:
- Filters out agent notes (
type: 'note') - Only shows messages customer should see
- Marks which messages belong to customer (
is_mine) - Same pagination support as agent endpoint
Message Filtering:
graph TD
A[All Messages] --> B{Filter by Type}
B -->|text, image, file| C[Include in Response]
B -->|note| D[Exclude from Response]
C --> E[Customer Sees Message]
D --> F[Agent-Only Visibility]
Data Models
Message Schema (Support Context)
{
_id: ObjectId;
room_id: ObjectId;
conversation_id: ObjectId; // Agent or support conversation
// Content
content: string;
type: 'text' | 'image' | 'file' | 'note';
attachments?: Array<{
url: string;
type: string;
name: string;
size: number;
}>;
// Integration
integration_app?: string; // Bot/automation identifier
// Timestamps
created_at: Date;
updated_at: Date;
}
Socket.IO Integration
Agent-side Events
// New customer message
socket.to(`account_${accountId}`).emit('newMessage', {
message: messageObject,
type: 'support',
});
Customer-side Events
// New agent message
socket.to(`support_${conversationId}`).emit('newMessage', {
message: messageObject,
type: 'team',
});
Message Types Deep Dive
Text Message
{
"type": "text",
"content": "Hello! How can I help?"
}
Image Message
{
"type": "image",
"content": "Screenshot attached",
"attachments": [
{
"url": "https://cdn.example.com/images/screenshot.png",
"type": "image/png",
"size": 245678
}
]
}
Agent Note (Internal)
{
"type": "note",
"content": "Customer seems frustrated. Offer discount if needed."
}
Security Considerations
Agent Authentication
- JWT token with
conversation.id(agent's conversation) - Account-level isolation via
account_id - Only assigned agents can view room messages
Customer Authentication
- Support token from widget embed
- Session validation via
support_sessionheader - Device ID tracking for security
Note Protection
// Agent notes never sent to customers
if (message.type !== 'note') {
emitToCustomer(message);
}
Performance Considerations
Indexing
db.messages.createIndex({
room_id: 1,
created_at: -1,
type: 1,
});
Pagination
- Default limit: 20 messages
- Use
upperRef/lowerReffor efficient pagination - Avoid loading entire conversation history
Error Handling
| Status Code | Error | Cause |
|---|---|---|
| 401 | Unauthorized | Invalid token or session |
| 403 | Forbidden | Not assigned to room |
| 404 | Room not found | Invalid room_id |
Testing Recommendations
describe('Support Message Controller', () => {
describe('sendMessage (agent)', () => {
it('should send text message to customer', async () => {});
it('should not broadcast notes to customer', async () => {});
});
describe('sendUserMessage (customer)', () => {
it('should send message from widget', async () => {});
it('should validate session', async () => {});
});
describe('queryMessages', () => {
it('should show all messages to agents', async () => {});
it('should hide notes from customers', async () => {});
});
});
Last Updated: October 8, 2025
Documented By: AI Documentation System
Source: internal/api/v1/conversation-v2/controllers/support.message.controller.js