---
source_url: https://www.pubnub.com/docs/chat/kotlin-chat-sdk/build/features/messages/pinned
title: Pinned messages
updated_at: 2026-06-10T11:17:56.190Z
---

> 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


# Pinned messages

Pin messages to channels for easy access. Only one message can be pinned per channel at a time.

Use cases:

* Essential announcements and updates
* Action items and reminders
* Polls and persistent questions

:::note Requires App Context and Message Persistence
Enable [App Context](https://youtu.be/9UEoSlngpYI) and [Message Persistence](https://youtu.be/qLMtbINWGig) in the [Admin Portal](https://admin.pubnub.com/).
:::

## Pin

`pin()` and `pinMessage()` attach a message to a channel. Call `pin()` on a message object or `pinMessage()` on a channel object.

Alternatively, you can also use other Chat SDK methods to pin a message in a thread (thread message) to the [thread channel](https://www.pubnub.com/docs/chat/kotlin-chat-sdk/build/features/messages/threads#pin-thread-message-to-thread-channel) or the [parent channel](https://www.pubnub.com/docs/chat/kotlin-chat-sdk/build/features/messages/threads#pin-thread-message-to-parent-channel).

### Method signature

These methods take the following parameters:

* pin() 1message.pin(): PNFuture<Channel>
* pinMessage() 1channel.pinMessage(message: Message): PNFuture<Channel>

#### Input

| Parameter | Required in pin() | Required in pinMessage() | Description |
| --- | --- | --- | --- |
| message | Message | Optional |  | No | Yes | [Message object](https://www.pubnub.com/docs/chat/kotlin-chat-sdk/learn/chat-entities/message) that you want to pin to the selected channel. |

#### Output

| Type | Description |
| --- | --- |
| `PNFuture<Channel>` | `PNFuture` containing the updated channel metadata. |

### Sample code

Pin the last message on the `incident-management` channel.

* `pin()`

```kotlin
fun pinLastMessageInIncidentManagementChannel(chat: Chat) {
    // obtain the incident-management channel details
    chat.getChannel("incident-management").async { channelResult ->
        channelResult.onSuccess { channel ->
            // handle success
            // retrieve the history of messages
            channel.getHistory(count = 1).async { historyResult ->
                historyResult.onSuccess { historyResponse ->
                    // handle success
                    val messages = historyResponse.messages
                    if (messages.isNotEmpty()) {
                        val lastMessage = messages.last()
                        
                        // pin the last message
                        lastMessage.pin().async { pinResult ->
                            pinResult.onSuccess {
                                // handle success
                                println("Message pinned successfully in incident-management channel.")
                            }.onFailure {
                                // handle failure
                                println("Failed to pin the message: ${it.message}")
                            }
                        }
                    } else {
                        println("The channel history is empty. No message to pin.")
                    }
                }.onFailure {
                    // handle failure
                    println("Failed to retrieve channel history: ${it.message}")
                }
            }
        }.onFailure {
            // handle failure
            println("Failed to get channel details: ${it.message}")
        }
    }
}
```

* `pinMessage()`

```kotlin
fun pinLastMessageInIncidentManagementChannel(chat: Chat) {
    // obtain the incident-management channel details
    chat.getChannel("incident-management").async { channelResult ->
        channelResult.onSuccess { channel ->
            // handle success
            // retrieve the history of messages
            channel.getHistory(count = 1).async { historyResult ->
                historyResult.onSuccess { historyResponse ->
                    // handle success
                    val messages = historyResponse.messages
                    if (messages.isNotEmpty()) {
                        // get the last message
                        val lastMessage = messages.last()
                        
                        // pin the last message
                        channel.pinMessage(lastMessage).async { pinResult ->
                            pinResult.onSuccess {
                                // handle success
                                println("Message pinned successfully in incident-management channel.")
                            }.onFailure {
                                // handle failure
                                println("Failed to pin the message: ${it.message}")
                            }
                        }
                    } else {
                        println("The channel history is empty. No message to pin.")
                    }
                }.onFailure {
                    // handle failure
                    println("Failed to retrieve channel history: ${it.message}")
                }
            }
        }.onFailure {
            // handle failure
            println("Failed to get channel details: ${it.message}")
        }
    }
}
```

## Get

`getPinnedMessage()` retrieves the currently pinned message.

### Method signature

This method has the following signature:

```kotlin
channel.getPinnedMessage(): PNFuture<Message?>
```

#### Input

This method doesn't take any parameters.

#### Output

| Type | Description |
| --- | --- |
| `PNFuture<Message?>` | Returned [Message object](https://www.pubnub.com/docs/chat/kotlin-chat-sdk/learn/chat-entities/message). |

### Sample code

Get the message pinned to the `incident-management` channel.

```kotlin
chat.getChannel("incident-management").async { result ->
    result.onSuccess { channel ->
        val pinnedMessageFuture = channel.getPinnedMessage()

        pinnedMessageFuture.async { pinnedMessageResult ->
            pinnedMessageResult.onSuccess { message ->
                if (message != null) {
                    // handle success
                    println("Pinned message content: ${message.text}")
                } else {
                    println("No pinned message found in the channel.")
                }
            }.onFailure { exception ->
                // handle failure
                exception.printStackTrace()
                println("Failed to get the pinned message: ${exception.message}")
            }
        }
    }.onFailure { exception ->
        // handle failure
        exception.printStackTrace()
        println("Failed to get channel details: ${exception.message}")
    }
}
```

## Unpin

`unpinMessage()` unpins a message from the channel.

Alternatively, you can also use other Chat SDK methods to unpin a message in a thread (thread message) from the [thread channel](https://www.pubnub.com/docs/chat/kotlin-chat-sdk/build/features/messages/threads#unpin-thread-message-from-thread-channel) or the [parent channel](https://www.pubnub.com/docs/chat/kotlin-chat-sdk/build/features/messages/threads#unpin-thread-message-from-parent-channel).

### Method signature

This method has the following signature:

```kotlin
channel.unpinMessage(): PNFuture<Channel>
```

#### Input

This method doesn't take any parameters.

#### Output

| Type | Description |
| --- | --- |
| `PNFuture<Channel>` | `PNFuture` containing the updated channel metadata. |

### Sample code

Unpin the message from the `incident-management` channel.

```kotlin
chat.getChannel("incident-management").async { result ->
    result.onSuccess { channel ->
        // attempt to unpin the message
        val unpinMessageFuture = channel.unpinMessage()

        unpinMessageFuture.async { unpinMessageResult ->
            unpinMessageResult.onSuccess { updatedChannel ->
                // handle success
                println("Message successfully unpinned from the channel.")
            }.onFailure { exception ->
                // handle failure
                exception.printStackTrace()
                println("Failed to unpin the message: ${exception.message}")
            }
        }
    }.onFailure { exception ->
        // handle failure
        exception.printStackTrace()
        println("Failed to get channel details: ${exception.message}")
    }
}
```