// Create a pinned message
const { message } = await channel.sendMessage({
text: "Important announcement",
pinned: true,
pin_expires: "2077-01-01T00:00:00Z",
});
// Pin an existing message for 120 seconds
await client.pinMessage(message, 120);
// Pin with a specific expiration date
await client.pinMessage(message, "2077-01-01T00:00:00Z");
// Pin indefinitely (remove expiration)
await client.pinMessage(message, null);
// Unpin a message
await client.unpinMessage(message);Pinned Messages
Pinned messages highlight important content in a channel. Use them for announcements, key information, or temporarily promoted content. Each channel can have multiple pinned messages, with optional expiration times.
Pinning and Unpinning Messages
Pin an existing message using pinMessage, or create a pinned message by setting pinned: true when sending.
// Create a pinned message
val pinExpirationDate = Calendar.getInstance().apply { set(2077, 1, 1) }.time
val message = Message(
text = "Important announcement",
pinned = true,
pinExpires = pinExpirationDate
)
channel.sendMessage(message).enqueue { /* ... */ }
// Pin message for 120 seconds
channel.pinMessage(message, timeout = 120).enqueue { /* ... */ }
// Pin with a specific expiration date
channel.pinMessage(message, expirationDate = pinExpirationDate).enqueue { /* ... */ }
// Pin indefinitely (remove expiration)
channel.pinMessage(message, expirationDate = null).enqueue { /* ... */ }
// Unpin message
channel.unpinMessage(message).enqueue { /* ... */ }let messageController = client.messageController(
cid: .init(type: .messaging, id: "general"),
messageId: "message-id"
)
// Pin message for 120 seconds
messageController.pin(.expirationTime(120))
// Pin to a specific date
messageController.pin(.expirationDate(Date()))
// Unpin message
messageController.unpin()// Create a pinned message
final message = await channel
.sendMessage(Message(
text: 'Important announcement',
pinned: true,
pinExpires: DateTime.now().add(Duration(days: 3)),
))
.then((resp) => resp.message);
// Pin message for 120 seconds
await channel.pinMessage(message, 120);
// Pin with a specific expiration date
await channel.pinMessage(message, DateTime(2077));
// Pin indefinitely (remove expiration)
await channel.pinMessage(message, null);
// Unpin message
await channel.unpinMessage(message);// Android SDK
Calendar calendar = Calendar.getInstance();
calendar.set(2077, 1, 1);
Date pinExpirationDate = calendar.getTime();
Message message = new Message();
message.setText("Important announcement");
message.setPinned(true);
message.setPinExpires(pinExpirationDate);
channelClient.sendMessage(message).enqueue(result -> { /* ... */ });
// Pin message for 120 seconds
channelClient.pinMessage(message, 120).enqueue(result -> { /* ... */ });
// Pin with expiration date
channelClient.pinMessage(message, pinExpirationDate).enqueue(result -> { /* ... */ });
// Pin indefinitely
channelClient.pinMessage(message, null).enqueue(result -> { /* ... */ });
// Unpin message
channelClient.unpinMessage(message).enqueue(result -> { /* ... */ });
// Backend SDK
Message message =
Message.send(channelType, channelId)
.message(
MessageRequestObject.builder()
.text("Important announcement")
.pinned(true)
.pinExpires(
new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX")
.parse("2077-01-01T00:00:00Z"))
.userId(userId)
.build())
.request()
.getMessage();
// Unpin message
MessageRequestObject messageRequestObject = MessageRequestObject.buildFrom(message);
messageRequestObject.setPinned(false);
Message.update(message.getId()).message(messageRequestObject).request();# Create a pinned message
response = channel.send_message({"pinned": True, "text": "Important announcement"}, user["id"])
# Pin message for 120 seconds
client.pin_message(response["message"]["id"], user["id"], 120)
# Unpin message
client.unpin_message(response["message"]["id"], user["id"])$response = $channel->sendMessage([
'text' => 'Important announcement',
'pinned' => true,
'pin_expires' => "2077-01-01T00:00:00Z",
], $user["id"]);
// Pin message for 120 seconds
$client->pinMessage($response["message"]["id"], $user["id"], 120);
// Unpin message
$client->unPinMessage($response["message"]["id"], $user["id"]);response = channel.send_message({pinned: true, text: "Important announcement"}, user["id"])
# Pin message for 120 seconds
client.pin_message(response["message"]["id"], user["id"], 120)
# Unpin message
client.unpin_message(response["message"]["id"], user["id"])msg := &Message{Text: "Important announcement", Pinned: true}
messageResp, err := channel.SendMessage(ctx, msg, user.ID)
// Pin message for 120 seconds
exp := time.Now().Add(time.Second * 120)
client.PinMessage(ctx, messageResp.Message.ID, user.ID, &exp)
// Unpin message
client.UnPinMessage(ctx, msg.ID, user.ID)var msg = new MessageRequest { Text = "Important announcement", Pinned = true };
var response = await messageClient.SendMessageAsync(channel.Type, channel.Id, msg, user.Id);
// Pin message for 120 seconds
await messageClient.PinMessageAsync(response.Message.Id, user.Id, TimeSpan.FromSeconds(120));
// Unpin message
await messageClient.UnpinMessageAsync(response.Message.Id, user.Id);// Pin until unpinned
await message.PinAsync();
// Pin for 7 days
await message.PinAsync(new DateTime().AddDays(7));
// Unpin previously pinned message
await message.UnpinAsync();Pin Parameters
| Name | Type | Description | Default | Optional |
|---|---|---|---|---|
| pinned | boolean | Whether the message is pinned | false | ✓ |
| pinned_at | string | Timestamp when the message was pinned | - | ✓ |
| pin_expires | string | Timestamp when the pin expires. Null means the message does not expire | null | ✓ |
| pinned_by | object | The user who pinned the message | - | ✓ |
Pinning a message requires the PinMessage permission. See Permission Resources and Default Permissions for details.
Retrieving Pinned Messages
Query a channel to retrieve the 10 most recent pinned messages from pinned_messages.
const channelState = await client.channel("messaging", channelId).query();
const pinnedMessages = channelState.pinned_messages;channelClient.query(QueryChannelRequest()).enqueue { result ->
if (result is Result.Success) {
val pinnedMessages: List<Message> = result.value.pinnedMessages
} else {
// Handle Result.Failure
}
}let channelController = client.channelController(for: .init(type: .messaging, id: "general"))
channelController.synchronize() { error in
if error == nil {
channelController.channel?.pinnedMessages
}
}final channelState = await channel.query();
final pinnedMessages = channelState.pinnedMessages;// Android SDK
channelClient.query(new QueryChannelRequest()).enqueue(result -> {
if (result.isSuccess()) {
List<Message> pinnedMessages = result.data().getPinnedMessages();
} else {
// Handle result.error()
}
});
// Backend SDK
ChannelGetResponse resp = Channel.getOrCreate("type", "id").request();
List<Message> messages = resp.getPinnedMessages();channel_state = channel.query(watch=False, state=False, presence=False)
pinned_messages = channel_state["pinned_messages"]$response = $channel->query([
"watch" => false,
"state" => false,
"presence" => false
]);
$pinnedMessages = $response["pinned_messages"];channel_state = channel.query(watch: false, state: false, presence: false)
pinned_messages = channel_state['pinned_messages']_, err = channel.Query(ctx, map[string]interface{}{"watch": false, "state": true})
msgs := channel.PinnedMessagesvar currentChannelState = await _channelClient.GetOrCreateAsync(_channel.Type, _channel.Id, new ChannelGetRequest
{
State = true,
Watch = false,
});
var pinnedMessages = currentChannelState.PinnedMessages;Paginating Pinned Messages
Use the dedicated pinned messages endpoint to retrieve all pinned messages with pagination.
// First page, newest first
const page1 = await channel.getPinnedMessages({ limit: 10 }, { pinned_at: -1 });
// Next page
const lastMsg = page1.messages[page1.messages.length - 1];
const page2 = await channel.getPinnedMessages(
{ limit: 10, id_lt: lastMsg.id },
{ pinned_at: -1 },
);
// Oldest first
const ascPage = await channel.getPinnedMessages({ limit: 10 });
const ascLastMsg = ascPage.messages[ascPage.messages.length - 1];
const ascPage2 = await channel.getPinnedMessages({
limit: 10,
id_gt: ascLastMsg.id,
});// First page, newest first
channelClient.getPinnedMessages(
limit = 10,
sort = QuerySortByField.descByName("pinnedAt"),
pagination = PinnedMessagesPagination.BeforeDate(
date = Date(),
inclusive = false,
),
).enqueue { result ->
if (result is Result.Success) {
val pinnedMessages: List<Message> = result.value
} else {
// Handle Result.Failure
}
}
// Next page using pinnedAt from previous response
val nextDate = Date()
channelClient.getPinnedMessages(
limit = 10,
sort = QuerySortByField.descByName("pinnedAt"),
pagination = PinnedMessagesPagination.BeforeDate(
date = nextDate,
inclusive = false,
),
).enqueue { /* ... */ }channelController.loadPinnedMessages(
pageSize: 10,
sorting: [.init(key: .pinnedAt, isAscending: false)],
pagination: .earlier(Date(), inclusive: true)) { result in
switch result {
case .success(let pinnedMessages):
print(pinnedMessages)
case .failure(let failure):
// Handle error
}
}
// Next page using message ID
let fetchedPinnedMessageId = ...
channelController.loadPinnedMessages(
pagination: .before(fetchedPinnedMessageId, inclusive: false)) { result in
// Handle result
}// Android SDK
channelClient.getPinnedMessages(
10,
QuerySortByField.descByName("pinnedAt"),
new PinnedMessagesPagination.BeforeDate(new Date(), false)
).enqueue(result -> {
if (result.isSuccess()) {
List<Message> pinnedMessages = result.data();
} else {
// Handle result.error()
}
});
// Next page
Date nextDate = new Date();
channelClient.getPinnedMessages(
10,
QuerySortByField.descByName("pinnedAt"),
new PinnedMessagesPagination.BeforeDate(nextDate, false)
).enqueue(result -> { /* ... */ });
// Backend SDK
Message.search()
.filterCondition("pinned", true)
.request();