Skip to main content

Support Conversation Controller

Controller: support.conversation.controller.js
Module: Conversation-v2
Purpose: Manages customer support chat sessions, token-based authentication for embedded widgets, and OTP verification

Overview​

The Support Conversation controller handles customer-facing support chat functionality. It manages support sessions for website visitors, token generation for embedded chat widgets, OTP verification for secure sessions, and support configuration retrieval.

Methods​

1. Get Support Conversation (getSupportConv)​

Retrieves a support conversation by ID (admin/agent access).

Endpoint: GET /api/conversation-v2/support/conversation/:conv_id

Authentication: Required (JWT - team member)

Response:

{
"_id": "507f1f77bcf86cd799439011",
"account_id": "507f1f77bcf86cd799439012",
"contact_id": "507f1f77bcf86cd799439013",
"type": "support",
"status": "active",
"sessions": [
{
"session_id": "507f1f77bcf86cd799439014",
"device_id": "device_xyz123",
"ip": "192.168.1.100",
"started_at": "2025-10-08T10:30:00.000Z",
"last_activity": "2025-10-08T11:00:00.000Z"
}
],
"created_at": "2025-10-08T10:00:00.000Z"
}

MongoDB Operations:

CollectionOperationQueryPurpose
support_conversationsfindOne{ _id: conv_id }Get conversation details

Business Logic:

  • Returns full support conversation with session history
  • Used by agents to view customer context
  • Includes device and IP tracking for security

Use Cases:

  • Agent viewing customer conversation details
  • Admin reviewing support interactions
  • Debugging support session issues

2. Generate Token (generateToken)​

Creates an authentication token for embedding chat widget on external websites.

Endpoint: POST /api/conversation-v2/support/token

Authentication: Required (JWT - admin)

Request Body:

{
"domain": "https://example.com",
"scopes": ["chat", "support"],
"expiry_time": 31536000000
}

Response:

{
"success": true,
"token": {
"_id": "507f1f77bcf86cd799439020",
"account_id": "507f1f77bcf86cd799439012",
"domain": "https://example.com",
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"scopes": ["chat", "support"],
"expiry_time": 31536000000,
"created_by": "507f1f77bcf86cd799439013",
"created_at": "2025-10-08T10:30:00.000Z",
"status": "active"
}
}

MongoDB Operations:

CollectionOperationQueryPurpose
support_tokensinsertOneNew tokenCreate auth token

Business Logic:

  • Generates JWT token for public-facing chat widget
  • Token scoped to specific domain for security
  • Expiry time in milliseconds (default: 1 year)
  • Allows widget to authenticate without user credentials

Token Scopes:

  • chat - Basic chat functionality
  • support - Access to support features
  • file_upload - Allow file attachments
  • history - View chat history

Token Generation Flow:

graph TD
A[Admin Creates Token] --> B[Specify Domain]
B --> C[Set Scopes & Expiry]
C --> D[Generate JWT]
D --> E[Store in Database]
E --> F[Return Token String]
F --> G[Embed in Website]
G --> H[Widget Authenticates]

Security Considerations:

  • Tokens domain-locked to prevent misuse
  • Short expiry for sensitive scopes
  • Tokens can be revoked via removeToken

Use Cases:

  • Embedding support chat on company website
  • Mobile app support integration
  • Third-party platform chat widgets

3. Regenerate Token (reGenerateToken)​

Regenerates an existing token (useful when token compromised).

Endpoint: POST /api/conversation-v2/support/token/regenerate

Authentication: Required (JWT - admin)

Request Body:

{
"id": "507f1f77bcf86cd799439020",
"domain": "https://example.com"
}

Response:

{
"success": true,
"token": {
"_id": "507f1f77bcf86cd799439020",
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.NEW_TOKEN...",
"domain": "https://example.com",
"regenerated_at": "2025-10-08T10:30:00.000Z"
}
}

MongoDB Operations:

CollectionOperationQuery/UpdatePurpose
support_tokensfindOne{ _id: id, account_id }Get existing token
support_tokensupdateOne$set: { token }Update with new token

Business Logic:

  • Invalidates old token immediately
  • Generates new JWT with same settings
  • Preserves token ID, domain, and scopes
  • Requires re-deployment of widget with new token

When to Regenerate:

  • Token leaked or compromised
  • Security audit requirements
  • Rotating credentials periodically
  • Domain ownership change

Use Cases:

  • Security incident response
  • Token rotation policy
  • Domain transfer scenarios

4. Get Token (getToken)​

Retrieves all active support tokens for the account.

Endpoint: GET /api/conversation-v2/support/token

Authentication: Required (JWT - admin)

Response:

{
"success": true,
"token": [
{
"_id": "507f1f77bcf86cd799439020",
"domain": "https://example.com",
"scopes": ["chat", "support"],
"status": "active",
"created_at": "2025-10-08T10:30:00.000Z",
"expiry_time": 31536000000,
"last_used": "2025-10-08T11:00:00.000Z"
},
{
"_id": "507f1f77bcf86cd799439021",
"domain": "https://app.example.com",
"scopes": ["chat"],
"status": "active",
"created_at": "2025-10-07T09:00:00.000Z"
}
]
}

MongoDB Operations:

CollectionOperationQueryPurpose
support_tokensfind{ account_id }List all tokens

Business Logic:

  • Returns all tokens for current account
  • Includes usage statistics (last_used)
  • Shows token status (active/expired)
  • Does not return actual token strings (security)

Use Cases:

  • Token management dashboard
  • Auditing widget deployments
  • Reviewing active integrations

5. Remove Token (removeToken)​

Deletes a support token, invalidating all widgets using it.

Endpoint: DELETE /api/conversation-v2/support/token/:id

Authentication: Required (JWT - admin)

Response:

{
"success": true,
"message": "Token deleted"
}

MongoDB Operations:

CollectionOperationQueryPurpose
support_tokensdeleteOne{ _id: id, account_id }Remove token

Business Logic:

  • Immediately invalidates token
  • All widgets using this token stop working
  • Orphaned sessions remain accessible to agents
  • Irreversible action (must generate new token)

Impact:

graph TD
A[Admin Deletes Token] --> B[Token Removed from DB]
B --> C[Widget Auth Fails]
C --> D[Visitors See Error]
D --> E[Must Deploy New Token]

Use Cases:

  • Removing deprecated widget
  • Revoking compromised token
  • Shutting down external integration

6. Get Support Conversation (Public) (getSupportConversation)​

Creates or retrieves a support session for website visitors (public endpoint).

Endpoint: POST /api/conversation-v2/support/session

Authentication: Support token (from widget)

Headers:

Authorization: Bearer <support_token>
X-Device-ID: device_xyz123

Request Body:

{
"email": "customer@example.com",
"name": "John Doe",
"phone": "+1234567890",
"auth_attr": {
"user_id": "external_user_123",
"custom_field": "value"
}
}

Response:

{
"success": true,
"session": {
"session_id": "507f1f77bcf86cd799439030",
"conversation_id": "507f1f77bcf86cd799439031",
"contact": {
"_id": "507f1f77bcf86cd799439032",
"name": "John Doe",
"email": "customer@example.com",
"phone": "+1234567890"
},
"status": "active",
"requires_verification": false,
"device_id": "device_xyz123",
"created_at": "2025-10-08T10:30:00.000Z"
}
}

MongoDB Operations:

CollectionOperationQueryPurpose
contactsfindOneAndUpdateUpsert by email/phoneGet or create contact
support_conversationsfindOneCheck existing sessionReuse session
support_conversationsinsertOneNew conversationCreate if needed
support_sessionsinsertOneNew sessionCreate session

Business Logic:

  • Contact matching by email or phone (creates if new)
  • Session tracking per device (device_id from header)
  • IP address logging for security
  • Returns existing session if recent (within 24 hours)
  • Custom attributes stored in auth_attr for context

Session Creation Flow:

graph TD
A[Visitor Opens Chat] --> B{Email/Phone Provided?}
B -->|Yes| C[Find/Create Contact]
B -->|No| D[Anonymous Session]
C --> E{Existing Session?}
E -->|Yes| F[Return Existing]
E -->|No| G[Create New Session]
D --> G
G --> H[Generate Session ID]
H --> I[Return to Widget]

Contact Matching Logic:

// Priority order:
1. Exact email match
2. Exact phone match
3. Create new contact

Use Cases:

  • Website visitor initiating chat
  • Mobile app user requesting support
  • Authenticated user continuing conversation

7. Get Support Config (getSupportConfig)​

Retrieves public support widget configuration.

Endpoint: GET /api/conversation-v2/support/config

Authentication: Support token

Response:

{
"success": true,
"config": {
"widget_settings": {
"theme": "light",
"primary_color": "#007bff",
"position": "bottom-right",
"greeting_message": "Hi! How can we help you today?",
"offline_message": "We're offline. Leave a message!"
},
"features": {
"file_upload": true,
"emoji_picker": true,
"typing_indicators": true,
"read_receipts": true
},
"business_hours": {
"timezone": "America/New_York",
"schedule": {
"monday": { "start": "09:00", "end": "17:00" },
"tuesday": { "start": "09:00", "end": "17:00" }
}
},
"requires_email": false,
"requires_phone": false,
"otp_verification_enabled": false
}
}

MongoDB Operations:

CollectionOperationQueryPurpose
support_configsfindOne{ account_id }Get config

Business Logic:

  • Returns account-specific widget configuration
  • Used by widget to customize appearance and behavior
  • Determines required fields (email, phone)
  • Specifies enabled features

Configuration Categories:

  1. Widget Settings: Visual appearance
  2. Features: Functional capabilities
  3. Business Hours: Availability schedule
  4. Verification: Security requirements

Use Cases:

  • Widget initialization on website
  • Customizing chat appearance per brand
  • Enforcing data collection requirements

8. Send OTP (sendOTP)​

Sends a one-time password for session verification.

Endpoint: POST /api/conversation-v2/support/otp/send

Authentication: Support token + session

Response:

{
"success": true,
"message": "OTP sent successfully"
}

MongoDB Operations:

CollectionOperationQuery/UpdatePurpose
support_sessionsupdateOneStore OTP + expirySave verification code

Business Logic:

  • Generates 6-digit OTP code
  • Valid for 10 minutes
  • Sent via email or SMS (based on contact info)
  • Rate limited to prevent abuse (max 3 per hour)

OTP Generation:

const otp = Math.floor(100000 + Math.random() * 900000); // 6 digits
const expiry = Date.now() + 10 * 60 * 1000; // 10 minutes

Delivery Methods:

graph TD
A[Generate OTP] --> B{Contact Has Email?}
B -->|Yes| C[Send Email]
B -->|No| D{Contact Has Phone?}
D -->|Yes| E[Send SMS]
D -->|No| F[Error: No Contact Method]
C --> G[Store in Session]
E --> G

Email Template:

Subject: Your verification code

Your verification code is: 123456

This code will expire in 10 minutes.

Use Cases:

  • Verifying customer identity
  • Secure support for sensitive issues
  • Preventing unauthorized access

9. Verify OTP (verifyOTP)​

Validates the OTP code provided by the user.

Endpoint: POST /api/conversation-v2/support/otp/verify

Authentication: Support token + session

Request Body:

{
"code": "123456"
}

Response:

{
"success": true,
"message": "OTP is verified"
}

MongoDB Operations:

CollectionOperationQuery/UpdatePurpose
support_sessionsfindOneGet session with OTPValidate code
support_sessionsupdateOneMark as verifiedUpdate status

Business Logic:

  • Compares provided code with stored OTP
  • Checks expiry time (10 minute window)
  • Marks session as verified on success
  • Clears OTP after successful verification
  • Max 3 attempts before generating new OTP

Verification Flow:

graph TD
A[User Enters Code] --> B{Code Matches?}
B -->|Yes| C{Within Time Limit?}
B -->|No| D[Increment Attempts]
C -->|Yes| E[Mark Verified]
C -->|No| F[Error: Expired]
D --> G{Max Attempts?}
G -->|Yes| H[Error: Too Many Attempts]
G -->|No| I[Try Again]
E --> J[Grant Access]

Error Responses:

// Invalid code
{
"error": "Invalid OTP code",
"statusCode": 400
}

// Expired code
{
"error": "OTP has expired",
"statusCode": 400
}

// Too many attempts
{
"error": "Too many failed attempts. Request new OTP.",
"statusCode": 429
}

Use Cases:

  • Completing identity verification
  • Unlocking verified-only features
  • Account-specific support access

Data Models​

Support Conversation Schema​

{
_id: ObjectId;
account_id: ObjectId;
contact_id: ObjectId; // Linked contact
type: 'support';

// Session Tracking
sessions: Array<{
session_id: ObjectId;
device_id: string;
ip: string;
started_at: Date;
last_activity: Date;
verified: boolean;
}>;

// Authentication
auth_attr: object; // Custom attributes

// Status
status: 'active' | 'closed';

// Timestamps
created_at: Date;
updated_at: Date;
}

Support Token Schema​

{
_id: ObjectId;
account_id: ObjectId;
user_id: ObjectId; // Creator

// Token Details
token: string; // JWT string
domain: string; // Allowed origin
scopes: string[]; // Permissions

// Lifecycle
expiry_time: number; // Milliseconds
status: 'active' | 'revoked';
last_used: Date;

// Timestamps
created_at: Date;
regenerated_at?: Date;
}

Support Session Schema​

{
_id: ObjectId;
conversation_id: ObjectId;
device_id: string;
ip: string;

// OTP Verification
otp_code?: string;
otp_expiry?: number;
otp_attempts: number;
verified: boolean;

// Status
status: 'active' | 'inactive';

// Timestamps
created_at: Date;
last_activity: Date;
}

Security Considerations​

Token Security​

  1. Domain Whitelisting: Tokens only work on specified domains
  2. Token Rotation: Regular regeneration recommended
  3. Scope Limitation: Minimal permissions principle
  4. Revocation: Instant invalidation capability

Session Security​

  1. Device Tracking: Device ID from browser fingerprint
  2. IP Logging: Fraud detection and security auditing
  3. Session Expiry: Automatic timeout after inactivity
  4. OTP Verification: Optional second factor

Rate Limiting​

// OTP requests
- Max 3 OTP sends per hour per contact
- Max 3 verification attempts per OTP

// Session creation
- Max 10 sessions per IP per hour
- Max 5 concurrent sessions per device

Integration Points​

Widget Integration​

<!-- Embed support chat on website -->
<script>
window.supportConfig = {
token: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...',
position: 'bottom-right',
};
</script>
<script src="https://cdn.example.com/support-widget.js"></script>

Mobile App Integration​

// Initialize support session
const session = await fetch('/api/conversation-v2/support/session', {
method: 'POST',
headers: {
Authorization: `Bearer ${supportToken}`,
'X-Device-ID': deviceId,
},
body: JSON.stringify({
email: user.email,
name: user.name,
}),
});

Performance Considerations​

Caching Strategy​

// Support config cached for 5 minutes
GET /support/config
Cache-Control: public, max-age=300

// Token list not cached (security)
GET /support/token
Cache-Control: no-store

Database Indexing​

// support_conversations
db.support_conversations.createIndex({ contact_id: 1, account_id: 1 });
db.support_conversations.createIndex({ 'sessions.device_id': 1 });

// support_tokens
db.support_tokens.createIndex({ account_id: 1, status: 1 });
db.support_tokens.createIndex({ domain: 1 });

// support_sessions
db.support_sessions.createIndex({ conversation_id: 1, device_id: 1 });

Error Handling​

Status CodeErrorCause
400Invalid OTP codeWrong verification code
401Invalid support tokenToken expired or revoked
403Domain not whitelistedToken domain mismatch
429Too many OTP requestsRate limit exceeded

Testing Recommendations​

describe('Support Conversation Controller', () => {
describe('generateToken', () => {
it('should create token with domain', async () => {});
it('should enforce domain whitelist', async () => {});
});

describe('getSupportConversation', () => {
it('should create new contact and session', async () => {});
it('should reuse existing session', async () => {});
it('should track device and IP', async () => {});
});

describe('OTP flow', () => {
it('should send OTP to email', async () => {});
it('should verify valid OTP', async () => {});
it('should reject expired OTP', async () => {});
it('should enforce rate limits', async () => {});
});
});

Last Updated: October 8, 2025
Documented By: AI Documentation System
Source: internal/api/v1/conversation-v2/controllers/support.conversation.controller.js

💬

Documentation Assistant

Ask me anything about the docs

Hi! I'm your documentation assistant. Ask me anything about the docs!

I can help you with:
- Code examples
- Configuration details
- Troubleshooting
- Best practices

Try asking: How do I configure the API?
09:31 AM