---
source_url: https://www.pubnub.com/docs/chat/unity-chat-sdk/build/features/messages/threads
title: Message threads
updated_at: 2026-06-19T11:35:22.916Z
---

> Documentation Index
> For a curated overview of PubNub documentation, see: https://www.pubnub.com/docs/llms.txt
> For the full list of all documentation pages, see: https://www.pubnub.com/docs/llms-full.txt


# Message threads

Organize conversations into threads for topic-specific discussions.

Benefits:

* Focus discussions on specific topics
* Clarify and resolve issues without cross-talk
* Keep main channel conversations clean

Thread channels have IDs starting with `PUBNUB_INTERNAL_THREAD_{channel_id}_{message_id}`. Messages with threads have `HasThread(): true`.

[ThreadMessage](https://www.pubnub.com/docs/chat/unity-chat-sdk/learn/chat-entities/thread-message) and [ThreadChannel](https://www.pubnub.com/docs/chat/unity-chat-sdk/learn/chat-entities/thread-channel) extend the base `message` and `channel` entities with thread-specific methods.

## Create thread

`CreateThread()` creates a thread channel for a selected message.

### Method signature

This method has the following signature:

```csharp
message.CreateThread()
```

#### Input

This method doesn't take any parameters.

#### Output

| Type | Description |
| --- | --- |
| `ChatOperationResult<ThreadChannel>` | An awaitable `Task` with the created `ThreadChannel` object. |

### Sample code

Create a thread for the last message on the `support` channel.

```csharp
using System.Linq;
using System.Threading.Tasks;
using PubnubApi;
using PubnubChatApi;
using Channel = PubnubChatApi.Channel;
using UnityEngine;

// Configuration
PubnubChatConfig chatConfig = new PubnubChatConfig();
        
PNConfiguration pnConfiguration = new PNConfiguration(new UserId("myUniqueUserId"))
{
    SubscribeKey = "demo",
    PublishKey = "demo",
    Secure = true
};

// Initialize Unity Chat
var chatResult = await UnityChat.CreateInstance(chatConfig, pnConfiguration);
if (!chatResult.Error)
{
    chat = chatResult.Result;
}
// retrieve the "support" channel
var channelResult = await chat.GetChannel("support");
if (!channelResult.Error)
{
    var channel = channelResult.Result;
    Debug.Log($"Found channel with name {channel.Name}");

    // fetch the last message from the "support" channel
    // fetch only the last message
    int count = 1;
    var messageHistoryResult = await channel.GetMessageHistory(null, null, count); // Omitting unnecessary time tokens
    if (messageHistoryResult.Error)
    {
        Debug.Log("Could not fetch message history.");
        return;
    }
    var lastMessage = messageHistoryResult.Result.FirstOrDefault();

    // check if there are any messages
    if (lastMessage != null)
    {
        // call the CreateThread method on the last message
        var threadChannelResult = lastMessage.CreateThread();
        if (threadChannelResult.Error)
        {
            Debug.Log($"Could not create thread: {threadChannelResult.Exception.Message}");
            return;
        }
        var threadChannel = threadChannelResult.Result;

        // (optional) display thread creation information
        Debug.Log($"Thread created for message with ID {lastMessage.Id} in channel 'support'.");
        Debug.Log($"Thread Channel ID: {threadChannel.Id}");
    }
    else
    {
        Debug.Log("No messages found in the 'support' channel.");
    }
}
else
{
    Debug.Log("Support channel not found.");
}
```

## Send thread message

Reply to a message in a thread by calling the `SendText()` method from the previously created `threadChannel` object.

### Method signature

Head over to the [SendText() method](https://www.pubnub.com/docs/chat/unity-chat-sdk/build/features/messages/send-receive) section for details.

### Sample code

Send a message in a thread created for the last message on the `support` channel.

```csharp
using System.Linq;
using System.Threading.Tasks;
using PubnubApi;
using PubnubChatApi;
using Channel = PubnubChatApi.Channel;
using UnityEngine;

// Configuration
PubnubChatConfig chatConfig = new PubnubChatConfig();
        
PNConfiguration pnConfiguration = new PNConfiguration(new UserId("myUniqueUserId"))
{
    SubscribeKey = "demo",
    PublishKey = "demo",
    Secure = true
};

// Initialize Unity Chat
var chatResult = await UnityChat.CreateInstance(chatConfig, pnConfiguration);
if (!chatResult.Error)
{
    chat = chatResult.Result;
}
// retrieve the "support" channel
var channelResult = await chat.GetChannel("support");
if (!channelResult.Error)
{
    var channel = channelResult.Result;
    Debug.Log($"Found channel with name {channel.Name}");

    // fetch the last message from the "support" channel
    // fetch only the last message
    int count = 1;
    var messageHistoryResult = await channel.GetMessageHistory(null, null, count); // omitting unnecessary timetokens
    if (messageHistoryResult.Error)
    {
        Debug.Log("Could not fetch message history.");
        return;
    }
    var lastMessage = messageHistoryResult.Result.FirstOrDefault();

    // check if there are any messages
    if (lastMessage != null)
    {
        // call the CreateThread method on the last message
        var threadChannelResult = lastMessage.CreateThread();
        if (threadChannelResult.Error)
        {
            Debug.Log($"Could not create thread: {threadChannelResult.Exception.Message}");
            return;
        }
        var threadChannel = threadChannelResult.Result;

        // (optional) display thread creation information
        Debug.Log($"Thread created for message with ID {lastMessage.Id} in channel 'support'.");
        Debug.Log($"Thread Channel ID: {threadChannel.Id}");

        // send a reply in the created thread
        string replyMessage = "Good job, guys!";
        await threadChannel.SendText(replyMessage);
        Debug.Log($"Sent reply in thread: {replyMessage}");
    }
    else
    {
        Debug.Log("No messages found in the 'support' channel.");
    }
}
else
{
    Debug.Log("Support channel not found.");
}
```

## Get thread

Get the thread channel on which the thread message is published using one of these methods:

* `GetThread()` called on the `Message` object
* `GetThreadChannel()` called on the `Chat` object.

### Method signature

### Method signature

These methods take the following parameters:

* GetThread() 1message.GetThread()
* GetThreadChannel() 1chat.GetThreadChannel(Message message)

#### Input

| Parameter | Required in `GetThread()` | Required in `GetThreadChannel()` | Description |
| --- | --- | --- | --- |
| `message`Type: `Message`Default: n/a | No | Yes | [Message object](https://www.pubnub.com/docs/chat/unity-chat-sdk/learn/chat-entities/message) for which you want to get the related thread channel. |

#### Output

An awaitable `Task<ChatOperationResult<ThreadChannel>>` with the fetched `ThreadChannel` object or an error if one wasn't found.

#### Sample code

Get the thread channel created from the message with the `16200000000000001` timetoken.

* GetThread() using System.Linq; using System.Threading.Tasks; using PubnubApi; using PubnubChatApi; using Channel = PubnubChatApi.Channel; using UnityEngine; // Configuration PubnubChatConfig chatConfig = new PubnubChatConfig(); PNConfiguration pnConfiguration = new PNConfiguration(new UserId("myUniqueUserId")) { SubscribeKey = "demo", PublishKey = "demo", Secure = true }; // Initialize Unity Chat var chatResult = await UnityChat.CreateInstance(chatConfig, pnConfiguration); if (!chatResult.Error) { chat = chatResult.Result; } // reference the "support" channel var channelResult = await chat.GetChannel("support"); if (!channelResult.Error) { var channel = channelResult.Result; // get the message with the specific timetoken var messageResult = await channel.GetMessage("16200000000000001"); if (!messageResult.Error) { var message = messageResult.Result; // get the thread channel created from the message var threadChannelResult = await message.GetThread(); if (!threadChannelResult.Error) { var threadChannel = threadChannelResult.Result; Debug.Log($"Thread channel successfully retrieved: {threadChannel.Name}"); } else { Debug.Log("No thread channel associated with this message."); } } else { Debug.Log("Message with the given timetoken not found."); } } else { Debug.Log("Channel 'support' not found."); }
* GetThreadChannel() using System.Linq; using System.Threading.Tasks; using PubnubApi; using PubnubChatApi; using Channel = PubnubChatApi.Channel; using UnityEngine; // Configuration PubnubChatConfig chatConfig = new PubnubChatConfig(); PNConfiguration pnConfiguration = new PNConfiguration(new UserId("myUniqueUserId")) { SubscribeKey = "demo", PublishKey = "demo", Secure = true }; // Initialize Unity Chat var chatResult = await UnityChat.CreateInstance(chatConfig, pnConfiguration); if (!chatResult.Error) { chat = chatResult.Result; } // reference the "support" channel var channelResult = await chat.GetChannel("support"); if (!channelResult.Error) { var channel = channelResult.Result; // get the message with the specific timetoken var messageResult = await channel.GetMessage("16200000000000001"); if (!messageResult.Error) { var message = messageResult.Result; // get the thread channel created from the message var threadChannelResult = await chat.GetThreadChannel(message); if (!threadChannelResult.Error) { var threadChannel = threadChannelResult.Result; Debug.Log($"Thread channel successfully retrieved: {threadChannel.Name}"); } else { Debug.Log("No thread channel associated with this message."); } } else { Debug.Log("Message with the given timetoken not found."); } } else { Debug.Log("Channel 'support' not found."); }

## Check if message starts thread

You can use the `HasThread()` method to check if a given message starts a thread.

### Method signature

This method has the following signature:

```csharp
message.HasThread()
```

#### Properties

This method doesn't take any parameters.

#### Output

| Type | Description |
| --- | --- |
| `bool` | Specifies if the message has started a thread (`true`) or not (`false`). |

### Sample code

Check if the message with the `16200000000000001` timetoken starts a thread.

```csharp
using System.Linq;
using System.Threading.Tasks;
using PubnubApi;
using PubnubChatApi;
using Channel = PubnubChatApi.Channel;
using UnityEngine;

// Configuration
PubnubChatConfig chatConfig = new PubnubChatConfig();
        
PNConfiguration pnConfiguration = new PNConfiguration(new UserId("myUniqueUserId"))
{
    SubscribeKey = "demo",
    PublishKey = "demo",
    Secure = true
};

// Initialize Unity Chat
var chatResult = await UnityChat.CreateInstance(chatConfig, pnConfiguration);
if (!chatResult.Error)
{
    chat = chatResult.Result;
}
// reference the channel object
var channelResult = await chat.GetChannel("support");
if (!channelResult.Error)
{
    var channel = channelResult.Result;
    // get the message history that includes the message with the specific time token
    var messagesResult = await channel.GetMessageHistory("16200000000000000", null, 1);

    // assuming we get exactly one message in response
    if (!messagesResult.Error && messagesResult.Result.Count > 0)
    {
        var message = messagesResult.Result[0];

        // check if the message starts a thread
        if (message.HasThread())
        {
            Debug.Log("The message starts a thread.");
        }
        else
        {
            Debug.Log("The message does not start a thread.");
        }
    }
    else
    {
        Debug.Log("No messages found for the specified time token.");
    }
}
else
{
    Debug.Log("Channel 'support' not found.");
}
```

## Get thread channel updates

You can receive updates when specific thread channels are edited or removed on other clients.

### Method signature

Head over to [OnUpdated](https://www.pubnub.com/docs/chat/unity-chat-sdk/build/features/channels/updates#get-channel-updates) section for details.

### Sample code

Get updates for the thread channel created from the message with the `16200000000000001` timetoken.

```csharp
using System.Linq;
using System.Threading.Tasks;
using PubnubApi;
using PubnubChatApi;
using Channel = PubnubChatApi.Channel;
using UnityEngine;

// Configuration
PubnubChatConfig chatConfig = new PubnubChatConfig();
        
PNConfiguration pnConfiguration = new PNConfiguration(new UserId("myUniqueUserId"))
{
    SubscribeKey = "demo",
    PublishKey = "demo",
    Secure = true
};

// Initialize Unity Chat
var chatResult = await UnityChat.CreateInstance(chatConfig, pnConfiguration);
if (!chatResult.Error)
{
    chat = chatResult.Result;
}
// reference the "support" channel
var channelResult = await chat.GetChannel("support");
if (!channelResult.Error)
{
    var channel = channelResult.Result;
    // get the message with the specific timetoken
    var messageResult = await channel.GetMessage("16200000000000001");
    if (!messageResult.Error)
    {
        var message = messageResult.Result;
        // get the thread channel created from the message
        var threadChannelResult = await message.GetThread();
        if (!threadChannelResult.Error)
        {
            var threadChannel = threadChannelResult.Result;
            Debug.Log($"Thread channel successfully retrieved: {threadChannel.Name}");

            // subscribe to updates on the thread channel
            threadChannel.OnUpdated += OnThreadChannelUpdateHandler;
        }
        else
        {
            Debug.Log("No thread channel associated with this message.");
        }
    }
    else
    {
        Debug.Log("Message with the given timetoken not found.");
    }
}
else
{
    Debug.Log("Channel 'support' not found.");
}
        
// handler for thread channel updates
void OnThreadChannelUpdateHandler(Channel threadChannel)
{
    Debug.Log($"Thread channel updated: {threadChannel.Id}");
}
```

## Get historical thread message

`GetThreadHistory()` called on the `threadChannel` object fetches historical thread messages from that thread channel.

### Method signature

This method takes the following parameters:

```csharp
threadChannel.GetThreadHistory(
    string startTimeToken, 
    string endTimeToken,
    int count
)
```

#### Input

| Parameter | Description |
| --- | --- |
| `startTimetoken` *Type: `string`Default: n/a | [Timetoken](https://www.pubnub.com/docs/sdks/unity/api-reference/misc#time) delimiting the start of a time slice (exclusive) to pull thread messages from. For details, refer to the [Fetch History section](https://www.pubnub.com/docs/sdks/unity/api-reference/storage-and-playback#fetch-history). |
| `endTimetoken` *Type: `string`Default: n/a | Timetoken delimiting the end of a time slice (inclusive) to pull messages from. For details, refer to the [Fetch History section](https://www.pubnub.com/docs/sdks/unity/api-reference/storage-and-playback#fetch-history). |
| `count` *Type: `int`Default: `25` | Number of historical messages to return for the channel in a single call. Since each call returns all attached [message reactions](https://www.pubnub.com/docs/chat/unity-chat-sdk/build/features/messages/reactions) by default, the maximum number of returned messages is `25`. For more details, refer to the description of the `IncludeMessageActions` parameter in the [Unity SDK docs](https://www.pubnub.com/docs/sdks/unity/api-reference/storage-and-playback#methods). |

#### Output

This method returns an awaitable `Task<ChatOperationResult<List<ThreadMessage>>>` with thread messages sent within the given timeframe.

By default, each call returns all message reactions and metadata attached to the retrieved thread messages.

### Sample code

From the thread created for the last message in the `support` channel, fetch `10` historical thread messages that are older than the timetoken `15343325214676133`.

```csharp
using System.Linq;
using System.Threading.Tasks;
using PubnubApi;
using PubnubChatApi;
using Channel = PubnubChatApi.Channel;
using UnityEngine;

// Configuration
PubnubChatConfig chatConfig = new PubnubChatConfig();
        
PNConfiguration pnConfiguration = new PNConfiguration(new UserId("myUniqueUserId"))
{
    SubscribeKey = "demo",
    PublishKey = "demo",
    Secure = true
};

// Initialize Unity Chat
var chatResult = await UnityChat.CreateInstance(chatConfig, pnConfiguration);
if (!chatResult.Error)
{
    chat = chatResult.Result;
}
// reference the "channel" object
var channelResult = await chat.GetChannel("support");
if (!channelResult.Error)
{
    var channel = channelResult.Result;
    Debug.Log($"Found channel with name {channel.Name}");
            
    // get the last message in the channel
    var messageHistoryResult = await channel.GetMessageHistory(null, null, 1);
    var lastMessage = messageHistoryResult.Result.FirstOrDefault();
    if (lastMessage != null)
    {
        Debug.Log($"Found last message with timetoken {lastMessage.TimeToken}");
                
        // check if the last message has a thread and fetch its thread channel
        var threadChannelResult = await lastMessage.GetThread();
        if (!threadChannelResult.Error)
        {
            var threadChannel = threadChannelResult.Result;
            Debug.Log($"Thread channel successfully retrieved: {threadChannel.Name}");
                    
            // fetch 10 historical thread messages older than timetoken 15343325214676133
            var threadMessagesResult = await threadChannel.GetMessageHistory("15343325214676133", null, 10);
            if (!threadMessagesResult.Error)
            {
                Debug.Log($"Retrieved {threadMessagesResult.Result.Count} historical thread messages.");
                foreach (var threadMessage in threadMessagesResult.Result)
                {
                    Debug.Log($"Thread message: {threadMessage.MessageText}");
                }
            }
            else
            {
                Debug.Log("Could not retrieve historical thread messages.");
            }
        }
        else
        {
            Debug.Log("No thread channel associated with this message.");
        }
    }
    else
    {
        Debug.Log("No messages found in the 'support' channel.");
    }
}
else
{
    Debug.Log("Support channel not found.");
}
```

## Remove thread

`RemoveThread()` removes a thread channel for a selected message.

### Method signature

This method has the following signature:

```csharp
message.RemoveThread()
```

#### Input

This method doesn't take any parameters.

#### Output

An awaitable `Task`.

### Sample code

Remove a thread for the last message on the `support` channel.

```csharp
using System.Linq;
using System.Threading.Tasks;
using PubnubApi;
using PubnubChatApi;
using Channel = PubnubChatApi.Channel;
using UnityEngine;

// Configuration
PubnubChatConfig chatConfig = new PubnubChatConfig();
        
PNConfiguration pnConfiguration = new PNConfiguration(new UserId("myUniqueUserId"))
{
    SubscribeKey = "demo",
    PublishKey = "demo",
    Secure = true
};

// Initialize Unity Chat
var chatResult = await UnityChat.CreateInstance(chatConfig, pnConfiguration);
if (!chatResult.Error)
{
    chat = chatResult.Result;
}
// reference the "channel" object
var channelResult = await chat.GetChannel("support");
if (!channelResult.Error)
{
    var channel = channelResult.Result;
    Debug.Log($"Found channel with name {channel.Name}");
            
    // get the last message in the channel
    var messageHistoryResult = await channel.GetMessageHistory(null, null, 1);
    var lastMessage = messageHistoryResult.Result.FirstOrDefault();
    if (lastMessage != null)
    {
        Debug.Log($"Found last message with timetoken {lastMessage.TimeToken}");
                
        // remove the thread for the last message
        await lastMessage.RemoveThread();
        Debug.Log("Thread removed successfully.");
    }
    else
    {
        Debug.Log("No messages found in the 'support' channel.");
    }
}
else
{
    Debug.Log("Support channel not found.");
}
```

## Pin thread message to thread channel

To pin a selected thread message to the thread channel, use the [PinMessage()](https://www.pubnub.com/docs/chat/unity-chat-sdk/build/features/messages/pinned#pin) method.

This method is available on the `Channel` object, but you can call it from the `ThreadChannel` object as `ThreadChannel` inherits all public methods from the `Channel` object.

### Method signature

Head over to the [PinMessage()](https://www.pubnub.com/docs/chat/unity-chat-sdk/build/features/messages/pinned#pin) section for details.

### Sample code

A thread was created for the last message in the `support` parent channel. Pin the last message from this thread to the thread channel.

```csharp
using System.Linq;
using System.Threading.Tasks;
using PubnubApi;
using PubnubChatApi;
using Channel = PubnubChatApi.Channel;
using UnityEngine;

// Configuration
PubnubChatConfig chatConfig = new PubnubChatConfig();
        
PNConfiguration pnConfiguration = new PNConfiguration(new UserId("myUniqueUserId"))
{
    SubscribeKey = "demo",
    PublishKey = "demo",
    Secure = true
};

// Initialize Unity Chat
var chatResult = await UnityChat.CreateInstance(chatConfig, pnConfiguration);
if (!chatResult.Error)
{
    chat = chatResult.Result;
}
// reference the "support" channel
var channelResult = await chat.GetChannel("support");
if (!channelResult.Error)
{
    var channel = channelResult.Result;
    Debug.Log($"Found channel with name {channel.Name}");

    // get the last message on the channel, which is the root message for the thread
    var channelMessageHistoryResult = await channel.GetMessageHistory(null, null, 1);
    var lastChannelMessage = channelMessageHistoryResult.Result.FirstOrDefault();
    if (lastChannelMessage != null)
    {
        Debug.Log($"Found last channel message with timetoken {lastChannelMessage.TimeToken}");

        // get the thread channel created from the message
        var threadChannelResult = await lastChannelMessage.GetThread();
        if (!threadChannelResult.Error)
        {
            var threadChannel = threadChannelResult.Result;
            Debug.Log($"Thread channel successfully retrieved: {threadChannel.Name}");

            // get the last message from the thread channel
            var threadMessageHistoryResult = await threadChannel.GetMessageHistory(null, null, 1);
            var lastThreadMessage = threadMessageHistoryResult.Result.FirstOrDefault();
            if (lastThreadMessage != null)
            {
                Debug.Log($"Found last thread message with timetoken {lastThreadMessage.TimeToken}");

                // pin the last thread message to the thread channel
                await threadChannel.PinMessage(lastThreadMessage);
                Debug.Log("Message pinned to thread channel successfully.");
            }
            else
            {
                Debug.Log("No messages found in the thread channel.");
            }
        }
        else
        {
            Debug.Log("No thread channel associated with this message.");
        }
    }
    else
    {
        Debug.Log("No messages found in the 'support' channel.");
    }
}
else
{
    Debug.Log("Support channel not found.");
}
```

## Pin thread message to parent channel

You can pin a selected thread message to the parent channel with `PinMessageToParentChannel()` methods. They give the same output, and the only difference is that you call a given method either on the `ThreadChannel` or the `ThreadMessage` object. Depending on the object, these methods take different input parameters - you have to specify the thread message you want to pin or not because it's already known.

### Method signature

These methods take the following parameters:

* PinMessageToParentChannel() (on threadChannel object) 1threadChannel.PinMessageToParentChannel(Message message)
* PinMessageToParentChannel() (on threadMessage object) 1threadMessage.PinMessageToParentChannel()

#### Input

| Parameter | Required in the `threadChannel` object method | Required in the `threadMessage` object method | Description |
| --- | --- | --- | --- |
| `message`Type: `Message`Default: n/a | Yes | No | [Message object](https://www.pubnub.com/docs/chat/unity-chat-sdk/learn/chat-entities/message) you want to pin to the selected parent channel. |

#### Output

An awaitable `Task`.

### Sample code

A thread was created for the last message in the `support` parent channel. Pin the last message from this thread to the parent channel.

```csharp
using System.Linq;
using System.Threading.Tasks;
using PubnubApi;
using PubnubChatApi;
using Channel = PubnubChatApi.Channel;
using UnityEngine;

// Configuration
PubnubChatConfig chatConfig = new PubnubChatConfig();
        
PNConfiguration pnConfiguration = new PNConfiguration(new UserId("myUniqueUserId"))
{
    SubscribeKey = "demo",
    PublishKey = "demo",
    Secure = true
};

// Initialize Unity Chat
var chatResult = await UnityChat.CreateInstance(chatConfig, pnConfiguration);
if (!chatResult.Error)
{
    chat = chatResult.Result;
}
// reference the "support" channel
var channelResult = await chat.GetChannel("support");
if (!channelResult.Error)
{
    var channel = channelResult.Result;
    Debug.Log($"Found channel with name {channel.Name}");

    // get the last message on the channel, which is the root message for the thread
    var channelMessageHistoryResult = await channel.GetMessageHistory(null, null, 1);
    var lastChannelMessage = channelMessageHistoryResult.Result.FirstOrDefault();
    if (lastChannelMessage != null)
    {
        Debug.Log($"Found last channel message with timetoken {lastChannelMessage.TimeToken}");

        // get the thread channel created from the message
        var threadChannelResult = await lastChannelMessage.GetThread();
        if (!threadChannelResult.Error)
        {
            var threadChannel = threadChannelResult.Result;
            Debug.Log($"Thread channel successfully retrieved: {threadChannel.Name}");

            // get the last message from the thread channel
            var threadMessageHistoryResult = await threadChannel.GetMessageHistory(null, null, 1);
            var lastThreadMessage = threadMessageHistoryResult.Result.FirstOrDefault();
            if (lastThreadMessage != null)
            {
                Debug.Log($"Found last thread message with timetoken {lastThreadMessage.TimeToken}");

                // pin the last thread message to the parent channel
                await channel.PinMessage(lastThreadMessage);
                Debug.Log("Thread message pinned to parent channel successfully.");
            }
            else
            {
                Debug.Log("No messages found in the thread channel.");
            }
        }
        else
        {
            Debug.Log("No thread channel associated with this message.");
        }
    }
    else
    {
        Debug.Log("No messages found in the 'support' channel.");
    }
}
else
{
    Debug.Log("Support channel not found.");
}
```

## Unpin thread message from thread channel

To unpin a selected thread message from the thread channel, use the [UnpinMessage()](https://www.pubnub.com/docs/chat/unity-chat-sdk/build/features/messages/pinned#unpin) method.

This method is available on the `Channel` object, but you can call it from the `ThreadChannel` object as `ThreadChannel` inherits all public methods from the `Channel` object.

### Method signature

Head over to the [UnpinMessage()](https://www.pubnub.com/docs/chat/unity-chat-sdk/build/features/messages/pinned#unpin) section for details.

### Sample code

Unpin the thread message from the thread (channel) created for the last message on the `support` channel.

```csharp
using System.Linq;
using System.Threading.Tasks;
using PubnubApi;
using PubnubChatApi;
using Channel = PubnubChatApi.Channel;
using UnityEngine;

// Configuration
PubnubChatConfig chatConfig = new PubnubChatConfig();
        
PNConfiguration pnConfiguration = new PNConfiguration(new UserId("myUniqueUserId"))
{
    SubscribeKey = "demo",
    PublishKey = "demo",
    Secure = true
};

// Initialize Unity Chat
var chatResult = await UnityChat.CreateInstance(chatConfig, pnConfiguration);
if (!chatResult.Error)
{
    chat = chatResult.Result;
}
// reference the "support" channel
var channelResult = await chat.GetChannel("support");
if (!channelResult.Error)
{
    var channel = channelResult.Result;
    Debug.Log($"Found channel with name {channel.Name}");

    // get the last message on the channel, which is the root message for the thread
    var channelMessageHistoryResult = await channel.GetMessageHistory(null, null, 1);
    var lastChannelMessage = channelMessageHistoryResult.Result.FirstOrDefault();
    if (lastChannelMessage != null)
    {
        Debug.Log($"Found last channel message with timetoken {lastChannelMessage.TimeToken}");

        // get the thread channel created from the message
        var threadChannelResult = await lastChannelMessage.GetThread();
        if (!threadChannelResult.Error)
        {
            var threadChannel = threadChannelResult.Result;
            Debug.Log($"Thread channel successfully retrieved: {threadChannel.Name}");

            // unpin the message from the thread channel
            await threadChannel.UnpinMessage();
            Debug.Log("Message unpinned from thread channel successfully.");
        }
        else
        {
            Debug.Log("No thread channel associated with this message.");
        }
    }
    else
    {
        Debug.Log("No messages found in the 'support' channel.");
    }
}
else
{
    Debug.Log("Support channel not found.");
}
```

## Unpin thread message from parent channel

You can unpin the previously pinned thread message from the parent channel with `UnpinMessageFromParentChannel()` methods. They give the same output, and the only difference is that you call a given method either on the `ThreadChannel` or the `ThreadMessage` object.

### Method signature

These methods have the following signatures:

* UnpinMessageFromParentChannel() (on the threadChannel object) 1threadChannel.UnPinMessageFromParentChannel()
* UnpinMessageFromParentChannel() (on the threadMessage object) 1threadMessage.UnPinMessageFromParentChannel()

#### Input

These methods don't take any parameters.

#### Output

An awaitable `Task`.

### Sample code

Unpin the thread message from the `support` parent channel.

```csharp
using System.Linq;
using System.Threading.Tasks;
using PubnubApi;
using PubnubChatApi;
using Channel = PubnubChatApi.Channel;
using UnityEngine;

// Configuration
PubnubChatConfig chatConfig = new PubnubChatConfig();
        
PNConfiguration pnConfiguration = new PNConfiguration(new UserId("myUniqueUserId"))
{
    SubscribeKey = "demo",
    PublishKey = "demo",
    Secure = true
};

// Initialize Unity Chat
var chatResult = await UnityChat.CreateInstance(chatConfig, pnConfiguration);
if (!chatResult.Error)
{
    chat = chatResult.Result;
}
// reference the "support" channel
var channelResult = await chat.GetChannel("support");
if (!channelResult.Error)
{
    var channel = channelResult.Result;
    Debug.Log($"Found channel with name {channel.Name}");

    // unpin the message from the parent channel
    await channel.UnpinMessage();
    Debug.Log("Message unpinned from parent channel successfully.");
}
else
{
    Debug.Log("Support channel not found.");
}
```