Channel members are users who have been added to a channel and can participate in conversations. This page covers how to manage channel membership, including adding and removing members, controlling message history visibility, and managing member roles.
Using the addMembers() method adds the given users as members to a channel.
val channelClient = client.channel("messaging", "general")// Add members with ids "thierry" and "josh"channelClient.addMembers(listOf("thierry", "josh")).enqueue { result -> if (result is Result.Success) { val channel: Channel = result.value } else { // Handle Result.Failure }}// Add member "thierry" with custom data with key: "code_name" and value "007"val params = AddMembersParams( members = listOf( MemberData(userId = "thierry", extraData = mapOf("code_name" to "007")), ),)channelClient.addMembers(params).enqueue { result -> if (result is Result.Success) { val channel: Channel = result.value } else { // Handle Result.Failure }}
await channel.addMembers(["thierry", "josh"]);// Add user to the channel with role setawait channel.addMembers([ { user_id: "james_bond", channel_role: "channel_moderator" },]);// Add new channel member with custom dataawait channel.addMembers([{ user_id: "james_bond", code_name: "007" }]);
await channel.addMembers(["thierry", "josh"]);
use GetStream\ChatClient;use GetStream\GeneratedModels as Models;$client->updateChannel("messaging", "channel-id", new Models\UpdateChannelRequest( addMembers: [ new Models\ChannelMemberRequest(userID: "thierry"), new Models\ChannelMemberRequest(userID: "jenny"), ],));
// Android SDKChannelClient channelClient = client.channel("messaging", "general");// Add members with ids "thierry" and "josh"channelClient.addMembers(Arrays.asList("thierry", "josh"), null).enqueue(result -> { if (result.isSuccess()) { Channel channel = result.data(); } else { // Handle result.error() }});// Backend SDKchat.updateChannel("messaging", "general", UpdateChannelRequest.builder() .addMembers(List.of( ChannelMemberRequest.builder().userID("thierry").build(), ChannelMemberRequest.builder().userID("josh").build())) .build()).execute();
var channel = await Client.GetOrCreateChannelWithIdAsync(ChannelType.Messaging, channelId: "my-channel-id");// Add IStreamUser collection as membersawait channel.AddMembersAsync(users);// Or add by IDawait channel.AddMembersAsync("some-user-id-1", "some-user-id-2");
Note: You can only add/remove up to 100 members at once.
Members can also be added when creating a channel:
val channelClient = client.channel("messaging", "general")// Add members during channel creationchannelClient.create( memberIds = listOf("james_bond", "alec_trevelyan", "bill_fairbanks"), extraData = emptyMap(),).enqueue()// Add members with custom extra data during channel creationval params = CreateChannelParams( members = listOf( MemberData(userId = "james_bond", extraData = mapOf("code_name" to "007")), MemberData(userId = "alec_trevelyan", extraData = mapOf("code_name" to "006")), ), extraData = emptyMap(),)channelClient.create(params).enqueue()
let channelId = ChannelId(type: .messaging, id: "general")let channelController = try chatClient.channelController( createChannelWithId: channelId, members: ["thierry", "tommaso"])channelController.synchronize { error in if let error = error { print(error) }}
// Members can be added when creating a channelvar resp = await chat.GetOrCreateChannelAsync("messaging", "my-channel-id", new ChannelGetOrCreateRequest { Data = new ChannelInput { CreatedByID = "user-1", Members = new List<ChannelMemberRequest> { new ChannelMemberRequest { UserID = "user-1" }, new ChannelMemberRequest { UserID = "user-2" }, new ChannelMemberRequest { UserID = "user-3" } } } });
Using the removeMembers() method removes the given users from the channel.
// Remove member with id "tommaso"channelClient.removeMembers(listOf("tommaso")).enqueue { result -> if (result is Result.Success) { val channel: Channel = result.value } else { // Handle Result.Failure }}
await channel.removeMembers(["tommaso"]);
await channel.removeMembers(["tommaso"]);
use GetStream\ChatClient;use GetStream\GeneratedModels as Models;$client->updateChannel("messaging", "channel-id", new Models\UpdateChannelRequest( removeMembers: ["thierry", "jenny"],));
// Controllerscontroller.removeMembers(userIds: ["tommaso"])// State layer (async-await)try await chat.removeMembers(["tommaso"])
Channel->RemoveMembers({TEXT("tommaso")});
channel.update(remove_members=["tommaso"])
await chat.UpdateChannelAsync("messaging", channelId, new UpdateChannelRequest { RemoveMembers = new List<string> { "thierry", "josh" } });
// Access channel members via channel.Membersvar member = channel.Members.First();await channel.RemoveMembersAsync(member);// Remove by user IDawait channel.RemoveMembersAsync("some-user-id-1", "some-user-id-2");
When members join a channel, you can specify whether they have access to the channel's message history. By default, new members can see the history. Set hide_history to true to hide it for new members.
// Add members by their IDs with hideHistory=truechannelClient.addMembers( memberIds = listOf("thierry"), hideHistory = true,).enqueue()// Add members by their IDs with hideHistory=true and custom extra dataval params = AddMembersParams( members = listOf( MemberData(userId = "thierry", extraData = mapOf("new_member" to true)), ), hideHistory = true,)channelClient.addMembers(params).enqueue()
from getstream.models import ChannelMemberRequestchannel.update( add_members=[ChannelMemberRequest(user_id="thierry")], hide_history=True,)
use GetStream\ChatClient;use GetStream\GeneratedModels as Models;$client->updateChannel("messaging", "channel-id", new Models\UpdateChannelRequest( addMembers: [new Models\ChannelMemberRequest(userID: "thierry")], hideHistory: true,));
await chat.UpdateChannelAsync("messaging", channelId, new UpdateChannelRequest { AddMembers = new List<ChannelMemberRequest> { new ChannelMemberRequest { UserID = "thierry" } }, HideHistory = true });
Alternatively, hide_history_before can be used to hide any history before a given timestamp while giving members access to later messages. The value must be a timestamp in the past in RFC 3339 format. If both parameters are defined, hide_history_before takes precedence over hide_history.
from datetime import datetime, timedelta, timezonefrom getstream.models import ChannelMemberRequestcutoff = datetime.now(timezone.utc) - timedelta(days=7) # Last 7 dayschannel.update( add_members=[ChannelMemberRequest(user_id="thierry")], hide_history_before=cutoff,)
use GetStream\ChatClient;use GetStream\GeneratedModels as Models;$client->updateChannel("messaging", "channel-id", new Models\UpdateChannelRequest( addMembers: [new Models\ChannelMemberRequest(userID: "thierry")], hideHistoryBefore: new \DateTime("-7 days"),));
var cutoff = DateTime.UtcNow.AddDays(-7); // Last 7 daysawait chat.UpdateChannelAsync("messaging", channelId, new UpdateChannelRequest { AddMembers = new List<ChannelMemberRequest> { new ChannelMemberRequest { UserID = "thierry" } }, HideHistoryBefore = cutoff });
You can optionally include a message object when adding or removing members that client-side SDKs will use to display a system message. This works for both adding and removing members.
val channelClient = client.channel("messaging", "general")// Add members with a system messagechannelClient.addMembers( listOf("thierry", "josh"), Message(text = "Thierry and Josh joined this channel."),).enqueue()// Add members with custom extra data and a system messageval params = AddMembersParams( members = listOf( MemberData(userId = "thierry", extraData = mapOf("new_member" to true)), MemberData(userId = "josh", extraData = mapOf("new_member" to true)), ), systemMessage = Message(text = "Thierry and Josh joined this channel."),)channelClient.addMembers(params).enqueue()// Remove member with a system messagechannelClient.removeMembers( listOf("tommaso"), Message(text = "Tommaso was removed from this channel."),).enqueue()
// Using client-side clientawait channel.addMembers(["tommaso"], { text: "Tommaso joined the channel." });// Using server-side client, you need to specify the sender user_idawait channel.addMembers(["tommaso"], { text: "Tommaso joined the channel.", user_id: "tommaso",});
channel.Update(ctx, &getstream.UpdateChannelRequest{ AddMembers: []getstream.ChannelMemberRequest{{UserID: "tommaso"}}, Message: &getstream.MessageRequest{ Text: getstream.PtrTo("Tommaso joined the channel."), UserID: getstream.PtrTo("tommaso"), },})
from getstream.models import ChannelMemberRequest, MessageRequestchannel.update( add_members=[ ChannelMemberRequest(user_id="tommaso"), ChannelMemberRequest(user_id="josh"), ], message=MessageRequest( text="Tommaso joined the channel.", user_id="tommaso", ),)
use GetStream\ChatClient;use GetStream\GeneratedModels as Models;$client->updateChannel("messaging", "channel-id", new Models\UpdateChannelRequest( addMembers: [new Models\ChannelMemberRequest(userID: "tommaso")], message: new Models\MessageRequest( text: "Tommaso joined the channel.", userID: "tommaso", ),));
await chat.UpdateChannelAsync("messaging", channelId, new UpdateChannelRequest { AddMembers = new List<ChannelMemberRequest> { new ChannelMemberRequest { UserID = "tommaso" } }, Message = new MessageRequest { Text = "Tommaso joined the channel", UserID = "tommaso" } });
// Android SDKMessage addMemberSystemMessage = new Message();addMemberSystemMessage.setText("Thierry and Josh were added to this channel");channelClient.addMembers(Arrays.asList("thierry", "josh"), addMemberSystemMessage).enqueue(result -> { if (result.isSuccess()) { Channel channel = result.data(); } else { // Handle result.error() }});// Backend SDKchat.updateChannel("messaging", "general", UpdateChannelRequest.builder() .addMembers(List.of( ChannelMemberRequest.builder().userID("thierry").build(), ChannelMemberRequest.builder().userID("josh").build())) .message(MessageRequest.builder() .text("Thierry and Josh were added to this channel") .build()) .build()).execute();
Channel->AddMembers({TEXT("tommaso")}, FMessage{TEXT("Tommaso joined the channel.")});
await channel.AddMembersAsync(users, hideHistory: default, new StreamMessageRequest{ Text = "John has joined the channel"});
// ControllerschannelController.addMembers( userIds: ["tommaso"], message: "Tommaso joined the channel") { error in // …}// State layer (async-await)try await chat.addMembers(["tommaso"], systemMessage: "Tommaso joined the channel")
Using the addModerators() method adds the given users as moderators (or updates their role to moderator if already members), while demoteModerators() removes the moderator status.
use GetStream\ChatClient;use GetStream\GeneratedModels as Models;$client->updateChannel("messaging", "channel-id", new Models\UpdateChannelRequest( addModerators: ["thierry", "jenny"],));
use GetStream\ChatClient;use GetStream\GeneratedModels as Models;$client->updateChannel("messaging", "channel-id", new Models\UpdateChannelRequest( demoteModerators: ["thierry", "jenny"],));
Custom data can be added at the channel member level. This is useful for storing member-specific information that is separate from user-level data. Ensure custom data does not exceed 5KB.
// Add custom data while creating the channelval params = CreateChannelParams( members = listOf( MemberData(userId = "userid1", extraData = mapOf("key1" to "value1")), MemberData(userId = "userid2", extraData = mapOf("key2" to "value2")), MemberData(userId = "userid3", extraData = mapOf("key3" to "value3")), ), extraData = emptyMap(),)channelClient.create(params).enqueue()// Add custom data with addMembers methodval params = AddMembersParams( members = listOf( MemberData(userId = "userid1", extraData = mapOf("key1" to "value1")), ),)channelClient.addMembers(params).enqueue()
// Add a member firstawait chat.UpdateChannelAsync("messaging", "my-channel-id", new UpdateChannelRequest { AddMembers = new List<ChannelMemberRequest> { new ChannelMemberRequest { UserID = "user-2" } } });// Set custom data on the memberawait chat.UpdateMemberPartialAsync("messaging", "my-channel-id", new UpdateMemberPartialRequest { Set = new Dictionary<string, object> { ["hat"] = "blue" // Channel member custom data is separate from user custom data } });
Channel members can be partially updated. Only custom data and channel roles are eligible for modification. You can set or unset fields, either separately or in the same call.
// Set some fieldsawait channel.updateMemberPartial( { set: { key1: "new value 1", key2: "new value 2", channel_role: "channel_moderator", }, }, { userId: "jane" },);// Unset some fieldsawait channel.updateMemberPartial( { unset: ["key1", "key2"], }, { userId: "jane" },);// Set and unset in the same callawait channel.updateMemberPartial( { set: { key1: "new value 1", key2: "new value 2", }, unset: ["key3"], }, { userId: "jane" },);
// Set some fieldslet memberController = ChatClient.shared.memberController( userId: someUserId, in: someChannelId)memberController.partialUpdate(extraData: [ "key1": .string("value1"), "key2": .string("value2")])// Unset some fieldsmemberController.partialUpdate(extraData: nil, unsetProperties: ["key1", "key2"])// Set and unset in the same callmemberController.partialUpdate( extraData: [ "key1": .string("value1"), "key2": .string("value2"), ], unsetProperties: ["key3"])
channel := client.Chat().Channel("messaging", "general")// Set some fieldschannel.UpdateMemberPartial(ctx, &getstream.UpdateMemberPartialRequest{ UserID: getstream.PtrTo("userid1"), Set: map[string]any{"color": "red"},})// Unset some fieldschannel.UpdateMemberPartial(ctx, &getstream.UpdateMemberPartialRequest{ UserID: getstream.PtrTo("userid1"), Unset: []string{"age"},})// Set and unset in the same callchannel.UpdateMemberPartial(ctx, &getstream.UpdateMemberPartialRequest{ UserID: getstream.PtrTo("userid1"), Set: map[string]any{"color": "red"}, Unset: []string{"age"},})
use GetStream\ChatClient;use GetStream\GeneratedModels as Models;// Set some fields$client->updateMemberPartial("messaging", "channel-id", "amy", new Models\UpdateMemberPartialRequest( set: (object)["hat" => "blue"],));// Unset some fields$client->updateMemberPartial("messaging", "channel-id", "amy", new Models\UpdateMemberPartialRequest( unset: ["hat"],));// Set and unset in the same call$client->updateMemberPartial("messaging", "channel-id", "amy", new Models\UpdateMemberPartialRequest( set: (object)["hat" => "blue"], unset: ["hat"],));
user_id = "amy"# Set some fieldsresponse = channel.update_member_partial(user_id=user_id, set={"hat": "blue"})# Unset some fieldsresponse = channel.update_member_partial(user_id=user_id, unset=["hat"])# Set and unset in the same callresponse = channel.update_member_partial(user_id=user_id, set={"color": "red"}, unset=["hat"])
require 'getstream_ruby'Models = GetStream::Generated::Modelsuser_id = "amy"# Set some fieldsclient.chat.update_member_partial("messaging", "channel-id", Models::UpdateMemberPartialRequest.new( set: { 'color' => 'red' }), user_id)# Unset some fieldsclient.chat.update_member_partial("messaging", "channel-id", Models::UpdateMemberPartialRequest.new( unset: ['hat']), user_id)# Set and unset in the same callclient.chat.update_member_partial("messaging", "channel-id", Models::UpdateMemberPartialRequest.new( set: { 'color' => 'red' }, unset: ['hat']), user_id)
// Set some fieldschat.updateMemberPartial(channel.getType(), channel.getId(), UpdateMemberPartialRequest.builder() .UserID("user-1") .set(Map.of("custom_key", "custom_value", "channel_role", "channel_moderator")) .build()).execute();// Unset some fieldschat.updateMemberPartial(channel.getType(), channel.getId(), UpdateMemberPartialRequest.builder() .UserID("user-1") .unset(List.of("custom_key")) .build()).execute();// Set and unset in the same callchat.updateMemberPartial(channel.getType(), channel.getId(), UpdateMemberPartialRequest.builder() .UserID("user-1") .set(Map.of("color", "red")) .unset(List.of("age")) .build()).execute();
// Set some fields// Note: user_id is passed as a query parameterawait client.MakeRequestAsync<UpdateMemberPartialRequest, UpdateMemberPartialResponse>( "PATCH", "/api/v2/chat/channels/{type}/{id}/member", new Dictionary<string, string> { ["user_id"] = "user-2" }, new UpdateMemberPartialRequest { Set = new Dictionary<string, object> { ["hat"] = "blue", ["score"] = 1000 } }, new Dictionary<string, string> { ["type"] = "messaging", ["id"] = "my-channel-id" });// Unset some fieldsawait client.MakeRequestAsync<UpdateMemberPartialRequest, UpdateMemberPartialResponse>( "PATCH", "/api/v2/chat/channels/{type}/{id}/member", new Dictionary<string, string> { ["user_id"] = "user-2" }, new UpdateMemberPartialRequest { Unset = new List<string> { "hat", "score" } }, new Dictionary<string, string> { ["type"] = "messaging", ["id"] = "my-channel-id" });// Set and unset in a single requestawait client.MakeRequestAsync<UpdateMemberPartialRequest, UpdateMemberPartialResponse>( "PATCH", "/api/v2/chat/channels/{type}/{id}/member", new Dictionary<string, string> { ["user_id"] = "user-2" }, new UpdateMemberPartialRequest { Set = new Dictionary<string, object> { ["hat"] = "blue" }, Unset = new List<string> { "score" } }, new Dictionary<string, string> { ["type"] = "messaging", ["id"] = "my-channel-id" });
// Set some fieldschannelClient.partialUpdateMember( userId = "userid1", set = mapOf( "key1" to "new value 1", "key2" to "new value 2", ),).enqueue()// Unset some fieldschannelClient.partialUpdateMember( userId = "userid1", unset = listOf("key1", "key2"),).enqueue()// Set and unset in the same callchannelClient.partialUpdateMember( userId = "userid1", set = mapOf( "key1" to "new value 1", "key2" to "new value 2", ), unset = listOf("key3"),).enqueue()