Skip to main content

REST API Endpoints

The General Socket service exposes HTTP endpoints for triggering Socket.IO emissions from other services.

Base URL: http://localhost:4000


Prospect Endpoints

Base Path: /conversations/:channel/emit/

Emit Prospect Message

Endpoint: GET /conversations/:channel/emit/message/:messageID

Purpose: Broadcast prospect message to all conversation participants

Parameters:

  • channel - Channel identifier (typically 'prospect')
  • messageID - Communication document ID

Response:

{ success: true, message: 'SUCCESS' }

Controller: RestAPI/Controllers/Prospect.js :: emitAddMessage

Flow:

1. Fetch Communication by messageID
2. Populate sent_by (Contact or User based on type)
3. For each conversation_id in message:
- Find ConversationProspect
- Get all user socket IDs
- Emit 'prospect_message' to each socket

Example:

GET /conversations/prospect/emit/message/64abc123def456789

Socket Event Emitted:

io.to(socketID).emit('prospect_message', {
_id: '64msg...',
type: 'INCOMING', // or 'OUTGOING'
data: 'Message content',
sent_by: { _id, name, email, ... },
conversation_id: '64conv...',
is_sender: false, // true if sent_by matches current user
createdAt: '2025-10-13T10:30:00.000Z',
...
});

Emit Prospect Conversation

Endpoint: GET /conversations/:channel/emit/conversation/:convoID/:isNew

Purpose: Broadcast new/updated prospect conversation

Parameters:

  • channel - Channel identifier
  • convoID - ConversationProspect document ID
  • isNew - 'new' or 'existing'

Response:

{ success: true, message: 'SUCCESS' }

Controller: RestAPI/Controllers/Prospect.js :: emitAddConversation

Flow:

1. Fetch ConversationProspect by convoID
2. Populate users, contact_id, last_activity
3. Generate title/image from contact if not set
4. For each user:
- Get user's socket IDs
- Emit 'prospect_add_conversation' with user-specific unread_count

Example:

GET /conversations/prospect/emit/conversation/64conv123/new

Socket Event Emitted:

io.to(socketID).emit('prospect_add_conversation', {
_id: '64conv...',
title: 'John Doe',
image: ['https://...'],
contact_id: { _id, name, email, phone, ... },
users: [...],
unread_count: 2, // User-specific
is_open: true,
isNew: true,
...
});

LeadFinder Endpoints

Base Path: /lead-finder/

Emit Custom Event

Endpoint: POST /lead-finder/:event

Purpose: Send custom event to specific lead scraper

Parameters:

  • event - Event name (e.g., 'scrape_task', 'health_check')

Request Body:

{
"socketId": "scraper-socket-id",
"payload": {
// Event-specific data
}
}

Response:

{ success: true, message: 'SUCCESS' }

Controller: RestAPI/Controllers/LeadFinder.js :: emit

Example:

POST /lead-finder/scrape_task
Content-Type: application/json

{
"socketId": "xyz123abc",
"payload": {
"task_id": "task_001",
"keyword": "plumber near me",
"location": "New York, NY",
"max_results": 50,
"timeout": 30000
}
}

Socket Event Emitted:

io.to('xyz123abc').emit('scrape_task', {
task_id: 'task_001',
keyword: 'plumber near me',
location: 'New York, NY',
max_results: 50,
timeout: 30000,
});

Common Emit Endpoints

Base Path: /emit/

Emit to Single User

Endpoint: POST /emit/:userId/:emitTo

Purpose: Send event to specific user (all their sockets)

Parameters:

  • userId - User document ID
  • emitTo - Event name

Request Body:

{
// Event payload (any structure)
}

Response:

{ success: true, message: 'SUCCESS' }

Controller: RestAPI/Controllers/Common.js :: emit

Example:

POST /emit/64user123abc/notification
Content-Type: application/json

{
"title": "New Lead",
"message": "You have a new lead from John Doe",
"type": "lead_assigned",
"data": {
"lead_id": "64lead...",
"lead_name": "John Doe"
},
"timestamp": "2025-10-13T10:30:00.000Z"
}

Socket Event Emitted:

// To all user's sockets in /v1/shared namespace
io.to(socketID).emit('notification', {
title: 'New Lead',
message: 'You have a new lead from John Doe',
type: 'lead_assigned',
data: { ... },
timestamp: '2025-10-13T10:30:00.000Z'
});

Emit to Multiple Users

Endpoint: POST /emit/:emitTo

Purpose: Broadcast event to multiple users

Parameters:

  • emitTo - Event name

Request Body:

{
"userIds": ["64user1...", "64user2...", "64user3..."], // Array or single string
"data": {
// Event payload
}
}

Response:

{ success: true, message: 'SUCCESS' }

Controller: RestAPI/Controllers/Common.js :: emitMultiple

Example:

POST /emit/system_announcement
Content-Type: application/json

{
"userIds": ["64user1...", "64user2...", "64user3..."],
"data": {
"title": "Scheduled Maintenance",
"message": "System will be down Monday 2AM-4AM EST",
"priority": "high",
"action_url": "/maintenance-info"
}
}

Socket Event Emitted:

// To all sockets of all specified users
io.to(socketID).emit('system_announcement', {
title: 'Scheduled Maintenance',
message: 'System will be down Monday 2AM-4AM EST',
priority: 'high',
action_url: '/maintenance-info',
});

Error Handling

Error Response Format

{
success: false,
errno: 400, // HTTP status code
message: 'Error message'
}

Common Error Codes

CodeErrorCause
400VALIDATION_ERRORMissing required parameters
404NOT_FOUNDMessage/Conversation not found
500`INTERNAL_SERVER_ERRORDatabase or socket emission error

Error Handling Middleware

router.use((error, req, res, next) => {
console.log('error--------------', error);
const status = error.statusCode || 400;
const message = error.message;
res.status(status).json({
success: false,
errno: status,
message: message,
});
});

Rate Limiting

Recommended: Implement rate limiting on REST API endpoints

Example with express-rate-limit:

const rateLimit = require('express-rate-limit');

const emitLimiter = rateLimit({
windowMs: 60 * 1000, // 1 minute
max: 100, // 100 requests per minute
message: { success: false, message: 'Too many emit requests' },
});

router.post('/emit/:userId/:emitTo', emitLimiter, commonController.emit);
router.post('/emit/:emitTo', emitLimiter, commonController.emitMultiple);

Authentication

Note: REST API endpoints currently have no authentication.

Recommendation for Production:

  1. Add API key authentication
  2. Verify requests from trusted services only
  3. Implement IP whitelisting
  4. Use internal network isolation

Example with API Key:

const apiKeyAuth = (req, res, next) => {
const apiKey = req.headers['x-api-key'];
if (apiKey !== process.env.INTERNAL_API_KEY) {
return res.status(401).json({
success: false,
message: 'Unauthorized',
});
}
next();
};

router.post('/emit/:userId/:emitTo', apiKeyAuth, commonController.emit);

Testing REST API

Using cURL

# Emit to single user
curl -X POST http://localhost:4000/emit/64user123/notification \
-H "Content-Type: application/json" \
-d '{
"title": "Test Notification",
"message": "This is a test"
}'

# Emit to multiple users
curl -X POST http://localhost:4000/emit/broadcast \
-H "Content-Type: application/json" \
-d '{
"userIds": ["64user1", "64user2"],
"data": {
"message": "System update"
}
}'

# Emit prospect message
curl -X GET http://localhost:4000/conversations/prospect/emit/message/64msg123

# Emit to scraper
curl -X POST http://localhost:4000/lead-finder/scrape_task \
-H "Content-Type: application/json" \
-d '{
"socketId": "scraper-xyz",
"payload": {
"task_id": "001",
"keyword": "test"
}
}'

Using Postman

  1. Create collection "General Socket API"
  2. Add requests for each endpoint
  3. Set Content-Type: application/json header
  4. Test with actual user IDs and message IDs from database

Integration Example

From Internal API

// internal/api/v1/controllers/lead.controller.js

const axios = require('axios');

async function assignLead(leadId, userId) {
// Assign lead in database
await Lead.updateOne({ _id: leadId }, { assigned_to: userId });

// Notify user via socket
await axios.post(`${process.env.GENERAL_SOCKET_URL}/emit/${userId}/notification`, {
title: 'New Lead Assigned',
message: 'A new lead has been assigned to you',
type: 'lead_assigned',
data: {
lead_id: leadId,
timestamp: new Date().toISOString(),
},
});

return { success: true };
}

From External API (Webhook Handler)

// external/Integrations/Twilio/webhook.js

async function handleIncomingSMS(req, res) {
const { From, Body, To } = req.body;

// Create Communication record
const message = await Communication.create({
type: 'INCOMING',
data: Body,
from_number: From,
to_number: To,
conversation_id: [conversationId],
...
});

// Broadcast to all users in conversation
await axios.get(
`${process.env.GENERAL_SOCKET_URL}/conversations/prospect/emit/message/${message._id}`
);

res.status(200).send('OK');
}
💬

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