# Thread messages (/en/realtime-media/im/build/build-groups-rooms-and-threads/threading/thread-messages/web)

> For AI agents: see the complete documentation index at [llms.txt](/llms.txt).

Threads enable users to create a separate conversation from a specific message within a chat group to keep the main chat uncluttered.

    This page shows how to use the Chat SDK to send, receive, recall, and retrieve thread messages in your app.

    ## Understand the tech [#understand-the-tech-2]

    The Chat SDK allows you to implement the following features:

    ## Prerequisites [#prerequisites-2]

    Before proceeding, ensure that you meet the following requirements:

    * You have initialized the Chat SDK. For details, see [SDK quickstart](../../../get-started-sdk).
    * You understand the call frequency limit of the Chat APIs supported by different pricing plans as described in [Limitations](../../limitations).

    <CalloutContainer type="info">
      <CalloutDescription>
        The thread feature is supported by all types of [Pricing Plans](../../../reference/pricing-plan-details) and is enabled by default once you have enabled Chat in [Agora Console](https://console.agora.io/v2).
      </CalloutDescription>
    </CalloutContainer>

    ## Implementation [#implementation-2]

    This section describes how to call the APIs provided by the Chat SDK to implement thread features.

    ### Send a thread message [#send-a-thread-message-2]

    Send a thread message is similar to send a message in a chat group. The difference lies in the `isChatThread` field, as shown in the following code sample:

    ```javascript
    function sendTextMessage() {
        let option = {
            chatType: 'groupChat',     // Sets `chatType` to `groupChat` as a thread belongs to a chat group.
            type: 'txt',               // Sets `type` to `txt` to create and send a text message.
            to: chatThreadId,          // Sets `to` to the thread ID.
            msg: 'message content',    // Sets `msg` to the content of the text message.
            isChatThread:true,         // Sets `isChatThread` to `true` to mark this message as a thread message.
        }
        // Calls `create` to create a text message.
        let msg = WebIM.message.create(option);
        // Calls `send` to send the text message.
        conn.send(msg).then(() => {
            console.log('send private text Success');
        }).catch((e) => {
            console.log("Send private text error");
        })
    };
    ```

    For more information about sending a message, see [Send Messages](../../build-core-messaging/messages/send-receive-messages#send-a-text-message).

    ### Receive a thread message [#receive-a-thread-message-2]

    Once a thread has a new message, all chat group members receive the `onChatThreadChange` callback triggered by the `update` event. Thread members can also listen for the `onTextMessage` callback to receive thread messages, as shown in the following code sample:

    ```javascript
    // The SDK triggers the `onTextMessage` callback when it receives a message.
    // After receiving this callback, the SDK parses the message and displays it.
    connection.addEventHandler('THREADMESSAGE',{
      onTextMessage:(message) =>{
          if(message.chatThread && JSON.stringify(message.chatThread)!=='{}'){
            console.log(message)
            // You can implement subsequent settings in this callback.
          }
      },
    });
    ```

    For more information about receiving a message, see [Receive Messages](../../build-core-messaging/messages/send-receive-messages#receive-a-message).

    ### Recall a thread message [#recall-a-thread-message-2]

    Once a message is recalled in a thread, all chat group members receive the `onChatThreadChange` callback triggered by the `update` event. Thread members can also listen for the `onRecallMessage` callback, as shown in the following code sample:

    ```javascript
    let option = {
      mid: 'msgId',           // The ID of the message to be recalled.
      to: 'chatThreadId',           // The username of the message receiver.
      chatType: 'groupChat'   // Sets `chatType` to `groupChat` as a thread belongs to a chat group.
      isChatThread: true      // Sets `isChatThread` to `true` to mark this message as a thread message.
    };
    // Calls `recallMessage` to recall a message.
    connection.recallMessage(option).then((res) => {
      console.log('success', res)
    }).catch((error) => {
      // Occurs when the message fails to be recalled within the default time limit of two minutes.
      console.log('fail', error)
    })
    // The SDK triggers the `onRecallMessage` callback when it recalls a message.
    // After receiving this callback, the SDK parses the message and updates its display.
    conn.addEventHandler('MESSAGES',{
       onRecallMessage: (msg) => {
           // You can implement subsequent settings in this callback.
            console.log('Message recall succeeds.'，msg)
       },
    })
    ```

    For more information about recalling a message, see [Recall Messages](../../build-core-messaging/messages/send-receive-messages#recall-a-message).

    ### Retrieve messages of a thread from the server [#retrieve-messages-of-a-thread-from-the-server-2]

    You can call `ChatManager#FetchHistoryMessagesFromServer` to retrieve messages of a thread from the server. The only difference between retrieving messages of a thread from the server and retrieving group messages is that a thread ID needs to be passed in for the former and a group ID is required for the latter.

    ```javascript
    let options = {
      // The thread ID.
      targetId: "threadId",
      // The number of thread messages that you expect to get on each page. The value range is [1,50], with `20` as the default.
      pageSize: 20,
      // The starting message ID for retrieving. If you set this parameter to `-1`, `null`, or an empty string, the SDK retrieves messages from the latest one.
      cursor: -1,
      // The chat type is set to `groupChat` as a thread belongs to a group chat.
      chatType: "groupChat",
      // The message search direction: (Default): `up`: The SDK retrieves messages in the descending order of the time when the server receives the messages. `down`: The SDK retrieves messages in the ascending order of the time when the server receives the messages.
      searchDirection: "up",
    };
    conn
      .getHistoryMessages(options)
      .then((res) => {
        // Succeed in getting historical messages.
        console.log(res);
      })
      .catch((e) => {
        // Fail to get historical messages.
      });
    ```

    
  
      
  
      
  
      
  
      
  
