Overview
Conversations represent chat threads between two users. Each conversation can optionally be linked to a horse listing (e.g., when a buyer contacts a seller about a specific horse).
Authentication
All conversation endpoints require authentication via JWT token in the Authorization header.
Authorization: Bearer <your_jwt_token>
Create or Get Conversation
curl -X POST https://api.horsetrust.com/api/chat/conversations \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{
"recipient_id": "507f1f77bcf86cd799439011",
"horse_id": "507f1f77bcf86cd799439012"
}'
Success Response
Error Response
{
"success" : true ,
"data" : {
"_id" : "65a1b2c3d4e5f6a7b8c9d0e1" ,
"participants" : [
"507f1f77bcf86cd799439010" ,
"507f1f77bcf86cd799439011"
],
"horse_id" : "507f1f77bcf86cd799439012" ,
"last_message" : {
"text" : "Is this horse still available?" ,
"sender_id" : "507f1f77bcf86cd799439010" ,
"sent_at" : "2024-03-15T10:30:00.000Z" ,
"is_read" : false
},
"created_at" : "2024-03-15T10:30:00.000Z" ,
"updated_at" : "2024-03-15T10:30:00.000Z"
}
}
POST /api/chat/conversations
Creates a new conversation or returns an existing one between the authenticated user and the recipient. If a conversation already exists between these two users (optionally for the same horse), the existing conversation is returned.
MongoDB ObjectId of the user to start a conversation with. Must be a valid ObjectId and cannot be the current user’s ID.
MongoDB ObjectId of the horse listing this conversation is about. Optional. If provided, the conversation will be linked to this specific horse.
Response Fields
Indicates if the request was successful
The conversation object Unique conversation identifier
Array of exactly 2 user ObjectIds representing the participants in the conversation
MongoDB ObjectId of the related horse listing (if applicable)
Snapshot of the most recent message in the conversation ObjectId of the user who sent the message
ISO 8601 timestamp when the message was sent
Whether the message has been read by the recipient
ISO 8601 timestamp when the conversation was created
ISO 8601 timestamp when the conversation was last updated
Error message (only present when success is false)
Error Responses
400 Bad Request : Invalid recipient ID or attempting to message yourself
500 Internal Server Error : Server error occurred
List Conversations
curl https://api.horsetrust.com/api/chat/conversations \
-H "Authorization: Bearer <token>"
{
"success" : true ,
"data" : [
{
"_id" : "65a1b2c3d4e5f6a7b8c9d0e1" ,
"participants" : [
{
"_id" : "507f1f77bcf86cd799439010" ,
"full_name" : "John Smith" ,
"profile_picture_url" : "https://cdn.horsetrust.com/users/john.jpg" ,
"seller_profile" : {
"is_verified_badge" : true
}
},
{
"_id" : "507f1f77bcf86cd799439011" ,
"full_name" : "Jane Doe" ,
"profile_picture_url" : "https://cdn.horsetrust.com/users/jane.jpg" ,
"seller_profile" : {
"is_verified_badge" : false
}
}
],
"horse_id" : {
"_id" : "507f1f77bcf86cd799439012" ,
"name" : "Thunder" ,
"photos" : [
{
"url" : "https://cdn.horsetrust.com/horses/thunder-1.jpg" ,
"is_primary" : true
}
]
},
"last_message" : {
"text" : "Yes, Thunder is still available!" ,
"sender_id" : "507f1f77bcf86cd799439011" ,
"sent_at" : "2024-03-15T10:35:00.000Z" ,
"is_read" : false
},
"created_at" : "2024-03-15T10:30:00.000Z" ,
"updated_at" : "2024-03-15T10:35:00.000Z"
}
]
}
GET /api/chat/conversations
Returns all conversations for the authenticated user, sorted by most recently updated first. Results include populated participant details and horse information.
Response Fields
Indicates if the request was successful
Array of conversation objects sorted by updated_at (most recent first) Unique conversation identifier
Array of populated user objects URL to the user’s profile picture
Seller profile information Whether the seller has a verified badge
Populated horse object (if conversation is linked to a horse) Horse’s unique identifier
Most recent message in the conversation (see Create or Get Conversation for fields)
ISO 8601 timestamp when the conversation was created
ISO 8601 timestamp when the conversation was last updated
Error Responses
500 Internal Server Error : Server error occurred
Socket.io Events
Join Conversation Room
Join a specific conversation room to receive real-time messages.
socket . emit ( 'join_conversation' , conversationId );
The ID of the conversation to join
New Message Event
Receive new messages in conversations you’ve joined.
socket . on ( 'new_message' , ( message ) => {
console . log ( 'New message:' , message );
});
Event Payload:
{
"_id" : "65a1b2c3d4e5f6a7b8c9d0e3" ,
"conversation_id" : "65a1b2c3d4e5f6a7b8c9d0e1" ,
"sender_id" : {
"_id" : "507f1f77bcf86cd799439010" ,
"full_name" : "John Smith" ,
"profile_picture_url" : "https://cdn.horsetrust.com/users/john.jpg"
},
"text" : "Is this horse still available?" ,
"is_read" : false ,
"sent_at" : "2024-03-15T10:30:00.000Z"
}
Message Notification Event
Receive notifications when someone sends you a message (delivered to your personal user room).
socket . on ( 'message_notification' , ( notification ) => {
console . log ( 'New message notification:' , notification );
});
Event Payload:
{
"conversation_id" : "65a1b2c3d4e5f6a7b8c9d0e1" ,
"sender" : "507f1f77bcf86cd799439010" ,
"preview" : "Is this horse still available?"
}
The preview field contains the first 60 characters of the message text.
Data Model
Conversation Schema
{
participants : [ ObjectId , ObjectId ], // Exactly 2 users (required)
horse_id : ObjectId , // Optional reference to Horse
last_message : {
text : String ,
sender_id : ObjectId ,
sent_at : Date ,
is_read : Boolean
},
created_at : Date ,
updated_at : Date
}
Validation Rules
Conversations must have exactly 2 participants
Participants must be valid user ObjectIds
Users cannot create conversations with themselves
The last_message field is automatically updated when new messages are sent
Indexes
participants: Used for efficiently finding all conversations for a user