Skip to main content
Quick Reference for AI Agents & Developers
  • Send in thread: Set parentMessageId on TextMessage, MediaMessage, or CustomMessage before sending
  • Fetch thread messages: MessagesRequest.MessageRequestBuilder().setParentMessageId(parentMessageId:).build()fetchPrevious(onSuccess:onError:)
  • Hide replies: MessagesRequest.MessageRequestBuilder().hideReplies(hide: true) to exclude thread messages from main conversation
  • Parent message: Original message that starts the thread
  • Related: Send Message · Retrieve Messages · Messaging Overview
Messages that are started from a particular message are called Threaded messages or simply threads. Each Thread is attached to a message which is the Parent message for that thread.

Object Structures

For complete object structures, see Send Message - Object Structures.

Thread Message Properties

PropertyTypeDescription
idIntUnique message identifier
parentMessageIdIntID of the parent message (thread root). 0 for non-threaded messages
senderUserUser who sent the message
receiverUidStringUID of the receiver
receiverTypeCometChat.ReceiverType.user (0) or .group (1)
sentAtDoubleUnix timestamp when sent
textStringMessage text (for TextMessage)
replyCountIntNumber of replies in thread
unreadRepliesCountIntNumber of unread replies

Send Message in a Thread

As mentioned in the Send a Message section. You can either send a message to a User or a Group based on the receiverType and the UID/GUID specified for the message. A message can belong to either of the below types:
  1. Text Message
  2. Media Message
  3. Custom Message.
Any of the above messages can be sent in a thread. As mentioned, a thread is identified based on the Parent message. So while sending a message the parentMessageId must be set for the message to indicate that the message to be sent needs to be a part of the thread with the specified parentMessageId. This can be achieved using the parentMessageId property provided by the object of the TextMessage, MediaMessage, and CustomMessage class. The id specified in the parentMessageId property maps the message sent to the particular thread.

Send Text Message in Thread

let receiverID = "cometchat-uid-2"
let text = "Hello"

let textMessage = TextMessage(receiverUid: receiverID, text: text, receiverType: .user)
textMessage.parentMessageId = 38208

CometChat.sendTextMessage(message: textMessage, onSuccess: { (message) in
  print("TextMessage sent successfully. " + message.stringValue())
}) { (error) in
  print("TextMessage sending failed with error: " + error!.errorDescription);
}
Method: CometChat.sendTextMessage(message:onSuccess:onError:)Object Type: TextMessage (with parentMessageId)
ParameterTypeValue
receiverUidString"cometchat-uid-2"
textString"Thread reply 2026-02-25 13:13:21 +0000"
receiverTypeCometChat.ReceiverType0 (.user)
parentMessageIdInt38208

Send Media Message in Thread

let receiverID = "cometchat-uid-2"
let fileUrl = "https://data-us.cometchat.io/assets/images/avatars/ironman.png"

let mediaMessage = MediaMessage(receiverUid: receiverID, fileurl: fileUrl, messageType: .image, receiverType: .user)
mediaMessage.parentMessageId = 38208

CometChat.sendMediaMessage(message: mediaMessage, onSuccess: { (message) in
  print("MediaMessage sent successfully. " + message.stringValue())
}) { (error) in
  print("MediaMessage sending failed with error: " + error!.errorDescription);
}
Method: CometChat.sendMediaMessage(message:onSuccess:onError:)Object Type: MediaMessage (with parentMessageId)
ParameterTypeValue
receiverUidString"cometchat-uid-2"
fileurlString"https://data-us.cometchat.io/assets/images/avatars/ironman.png"
messageTypeCometChat.MessageType1 (.image)
receiverTypeCometChat.ReceiverType0 (.user)
parentMessageIdInt38208

Send Custom Message in Thread

let receiverID = "cometchat-uid-2"
let customData: [String: Any] = ["emoji": "👍", "timestamp": 1772025206.052701, "replyType": "reaction"]

let customMessage = CustomMessage(receiverUid: receiverID, receiverType: .user, customData: customData, type: "thread_reaction")
customMessage.parentMessageId = 38208

CometChat.sendCustomMessage(message: customMessage, onSuccess: { (message) in
  print("CustomMessage sent successfully. " + message.stringValue())
}) { (error) in
  print("CustomMessage sending failed with error: " + error!.errorDescription);
}
Method: CometChat.sendCustomMessage(message:onSuccess:onError:)Object Type: CustomMessage (with parentMessageId)
ParameterTypeValue
receiverUidString"cometchat-uid-2"
receiverTypeCometChat.ReceiverType0 (.user)
typeString"thread_reaction"
parentMessageIdInt38208
customData ([String: Any]):
KeyTypeValue
emojiString"👍"
timestampDouble1772025206.052701
replyTypeString"reaction"

Receiving Real-Time Messages

The procedure to receive real-time messages is exactly the same as mentioned in the Receive Messages. This can be achieved using the CometChatMessageDelegate class provided by the SDK. In order to receive incoming messages, you must add protocol conformance CometChatMessageDelegate. The only thing that needs to be checked is if the received message belongs to the active thread. This can be done using the parentMessageId field of the message object.
var activeThreadId = 38208

extension ViewController: CometChatMessageDelegate {

  func onTextMessageReceived(textMessage: TextMessage) {
    if textMessage.parentMessageId == activeThreadId {
      print("TextMessage received in thread: " + textMessage.stringValue())
    }
  }

  func onMediaMessageReceived(mediaMessage: MediaMessage) {
    if mediaMessage.parentMessageId == activeThreadId {
      print("MediaMessage received in thread: " + mediaMessage.stringValue())
    }
  }

  func onCustomMessageReceived(customMessage: CustomMessage) {
    if customMessage.parentMessageId == activeThreadId {
      print("CustomMessage received in thread: " + customMessage.stringValue())
    }
  }
}

Fetch all the messages for any particular thread

You can fetch all the messages belonging to a particular thread by using the MessagesRequest class. Use the setParentMessageId() method of the MessagesRequestBuilder to inform the SDK that you only need the messages belonging to the thread with the specified parentMessageId.
let messagesRequest = MessagesRequest.MessageRequestBuilder()
  .setParentMessageId(parentMessageId: 38208)
  .set(limit: 50)
  .build()

messagesRequest.fetchPrevious(onSuccess: { (messages) in
  for message in messages! {
    if let textMessage = message as? TextMessage {
      print("Text Message: " + textMessage.stringValue())
    } else if let mediaMessage = message as? MediaMessage {
      print("Media Message: " + mediaMessage.stringValue())
    } else if let customMessage = message as? CustomMessage {
      print("Custom Message: " + customMessage.stringValue())
    }
  }
}) { (error) in
  print("Messages fetching failed with error: " + error!.errorDescription)
}
Method: messagesRequest.fetchPrevious(onSuccess:onError:)Object Type: MessagesRequest.MessageRequestBuilder
ParameterTypeValue
parentMessageIdInt38208
limitInt50

Avoid Threaded Messages in User/Group Conversations

While fetching messages for normal user/group conversations using the MessagesRequest, the threaded messages by default will be a part of the list of messages received. In order to exclude the threaded messages from the list of user/group messages, you need to use the hideReplies() method of the MessagesRequestBuilder class. This method takes a boolean argument which when set to true excludes the messages belonging to threads from the list of messages.
let messagesRequest = MessagesRequest.MessageRequestBuilder()
  .set(uid: "cometchat-uid-2")
  .set(limit: 50)
  .hideReplies(hide: true)
  .build()

messagesRequest.fetchPrevious(onSuccess: { (messages) in
  for message in messages! {
    print("Message ID: \(message.id), parentMessageId: \(message.parentMessageId)")
  }
}) { (error) in
  print("Messages fetching failed with error: " + error!.errorDescription)
}
Method: messagesRequest.fetchPrevious(onSuccess:onError:)Object Type: MessagesRequest.MessageRequestBuilder
ParameterTypeValue
uidString"cometchat-uid-2"
limitInt50
hideRepliesBooltrue
Method: messagesRequest.fetchPrevious(onSuccess:onError:)Object Type: MessagesRequest.MessageRequestBuilder
ParameterTypeValue
guidString"cometchat-guid-1"
limitInt50
hideRepliesBooltrue

Common Error Codes

Error CodeDescriptionResolution
ERR_MESSAGE_NOT_FOUNDParent message does not existVerify the parent message ID exists
ERR_INVALID_PARENT_MESSAGE_IDInvalid parent message ID providedProvide a valid message ID
ERR_WRONG_MESSAGE_THREADMessage cannot be added to the threadVerify the thread is valid and accessible
ERR_EMPTY_MESSAGEMessage text is emptyProvide message content
ERR_NOT_LOGGED_INUser is not logged inCall CometChat.login() first
ERR_SDK_NOT_INITIALIZEDSDK not initializedCall CometChat.init() first