Pinned messages

Last Edit: Jan 15 2021

Pinned messages allow users to highlight important messages, make announcements, or temporarily promote content. Pinning a message is, by default, restricted to certain user roles, but this is flexible. Each channel can have multiple pinned messages and these can be created or updated with or without an expiration.

Pin and unpin a message

An existing message can be updated to be pinned or unpinned by using the channel.pinMessage and channel.unpinMessage methods. Or a new message can be pinned when it is sent by setting the pinned and pin_expires fields when using channel.sendMessage.


// create pinned message
const {message} = await channel.sendMessage({
  text: "my message",
  pinned: true,
  pin_expires: "2077-01-01T00:00:00Z",
});

// unpin message
await client.unpinMessage(message);

// pin message for 120 seconds
await client.pinMessage(message, 120);

// change message expiration to 2077
await client.pinMessage(message, "2077-01-01T00:00:00Z");

// remove expiration date from pinned message
await client.pinMessage(message, null);
                    

// Create pinned message
val pinExpirationDate = Calendar.getInstance().apply {
    set(2077, 1, 1)
}.time
val message = Message("my message", pinned = true, pinExpires = pinExpirationDate)
channelClient.sendMessage(message).enqueue { result ->
    if (result.isSuccess) {
        val sentMessage = result.data()
    } else {
        Log.e(TAG, String.format("There was an error %s", result.error()))
   }
}

// Unpin message
channelClient.unpinMessage(message).enqueue { result ->
    if (result.isSuccess) {
        val unpinnedMessage = result.data()
    } else {
        Log.e(TAG, String.format("There was an error %s", result.error()))
    }
}

// Pin message for 120 seconds
channelClient.pinMessage(message, 120).enqueue { result ->
    if (result.isSuccess) {
        val pinnedMessage = result.data()
    } else {
        Log.e(TAG, String.format("There was an error %s", result.error()))
    }
}

// Change message expiration to 2077
channelClient.pinMessage(message, pinExpirationDate).enqueue { result ->
    if (result.isSuccess) {
        val pinnedMessage = result.data()
    } else {
        Log.e(TAG, String.format("There was an error %s", result.error()))
    }
}

// Remove expiration date from pinned message
channelClient.pinMessage(message, null).enqueue { result ->
    if (result.isSuccess) {
        val pinnedMessage = result.data()
    } else {
        Log.e(TAG, String.format("There was an error %s", result.error()))
    }
}
                    

// Create pinned message
Calendar calendar = Calendar.getInstance();
calendar.set(2077, 1, 1);
Date pinExpirationDate = calendar.getTime();

Message message = new Message();
message.setText("my-message");
message.setPinned(true);
message.setPinExpires(pinExpirationDate);

channelClient.sendMessage(message).enqueue(result -> {
    if (result.isSuccess()) {
        Message sentMessage = result.data();
    } else {
        Log.e(TAG, String.format("There was an error %s", result.error()));
    }
});

// Unpin message
channelClient.unpinMessage(message).enqueue(result -> {
    if (result.isSuccess()) {
        Message unpinnedMessage = result.data();
    } else {
        Log.e(TAG, String.format("There was an error %s", result.error()));
    }
});

// Pin message for 120 seconds
channelClient.pinMessage(message, 120).enqueue(result -> {
    if (result.isSuccess()) {
        Message pinnedMessage = result.data();
    } else {
        Log.e(TAG, String.format("There was an error %s", result.error()));
    }
});

// Change message expiration to 2077
channelClient.pinMessage(message, pinExpirationDate).enqueue(result -> {
    if (result.isSuccess()) {
        Message pinnedMessage = result.data();
    } else {
        Log.e(TAG, String.format("There was an error %s", result.error()));
    }
});

// Remove expiration date from pinned message
channelClient.pinMessage(message, null).enqueue(result -> {
    if (result.isSuccess()) {
        Message pinnedMessage = result.data();
    } else {
        Log.e(TAG, String.format("There was an error %s", result.error()));
    }
});
                    
Name Type Description Default Optional
pinned boolean Indicates whether the message is pinned or not false
pinned_at string Date when the message got pinned -
pin_expires string Date when the message pin expires. An empty value means that message does not expire null
pinned_by User The user that pinned the message -
To pin the message user has to have PinMessage permission. You can find the list of permissions and defaults in Permission Resources and Default Permissions sections

Retrieve pinned messages

You can easily retrive last 10 pinned messages from channel.pinned_messages field:


// get channel state
const state = client.channel('messaging', channelId).query();
// get pinned messages from it
const pinnedMessages = channelState.pinnedMessages
                    

val request = QueryChannelRequest().withMessages(limit = 10)
channelClient.query(request).enqueue { result ->
    if (result.isSuccess) {
        val pinnedMessages = result.data().pinnedMessages
    } else {
        Log.e(TAG, String.format("There was an error %s", result.error()))
    }
}
                    

int messagesLimit = 10;
QueryChannelRequest request = new QueryChannelRequest().withMessages(messagesLimit);
channelClient.query(request).enqueue(result -> {
    if (result.isSuccess()) {
        List<Message> pinnedMessages = result.data().getPinnedMessages();
    } else {
        Log.e(TAG, String.format("There was an error %s", result.error()));
    }
});
                    
To learn more about channels you can visit Querying Channels page

Search for all pinned messages

Stream Chat also provides search filter in case if you need to display more than 10 pinned messages in specific channel.


// list all pinned messages of the channel
const response = await channel.search({pinned: true});
                    

val channelFilter = Filters.`in`("cid", "channelType:channelId")
val messageFilter = Filters.eq("pinned", true)
val request = SearchMessagesRequest(offset = 0, limit = 30, channelFilter, messageFilter)

client.searchMessages(request).enqueue { result ->
    if (result.isSuccess) {
        val pinnedMessages = result.data()
    } else {
        Log.e(TAG, String.format("There was an error %s", result.error()))
   }
}
                    

int offset = 0;
int limit = 10;
FilterObject channelFilter = Filters.in("cid", "channelType:channelId");
FilterObject messageFilter = Filters.eq("pinned", true);
SearchMessagesRequest request = new SearchMessagesRequest(offset, limit, channelFilter, messageFilter);

client.searchMessages(request).enqueue(result -> {
    if (result.isSuccess()) {
        List<Message> pinnedMessages = result.data();
    } else {
       Log.e(TAG, String.format("There was an error %s", result.error()));
    }
});
                    
To learn more about message search you can visit Search page