Channel members

Add channel members

Members can be added to a channel either when creating it or by using the addMembers method.

When creating a channel

// members can be added by passing an array of user IDs
var response = await _channelClient.GetOrCreateAsync("messaging", "my-channel-id", createdBy: "user-1",
    members: new[] { "user-2", "user-3" });
var channel = response.Channel;

// or by passing objects
var response2 = await _channelClient.GetOrCreateAsync("messaging", new ChannelGetRequest
{
    Data = new ChannelRequest
    {
        CreatedBy = new UserRequest { Id = "user-1" },
        Members = new List<ChannelMember>
        {
            new() { UserId = "user-2" },
            new() { UserId = "user-3" },
        }
    },
});
var channel2 = response2.Channel;

Using addMembers method

await _channelClient.AddMembersAsync("messaging", "my-channel-id", new[] { "user-2", "user-3" });

Note: You can only add up to 100 members at once.

Message parameter

You can optionally include a message object to allow client-side SDKs to generate a system message. This feature is available for both adding and removing members.

await _channelClient.AddMembersAsync("messaging", "my-channel-id", new[] { "user-2" }, new MessageRequest
{
    Text = "Tommaso joined the channel.",
    UserId = "user-1", // Message sender
}, options: null);

Hide history

When members join a channel, you can specify whether they have access to the channel’s history.

By default, new members can see the history. To hide it, set the hide_history parameter to true.

await _channelClient.AddMembersAsync("messaging", "my-channel-id", new[] { "user-2" }, msg: null,
    new AddMemberOptions
    {
        HideHistory = true
    });

Channel member custom data

Custom data can be added at the channel member level. Ensure it does not exceed 5KB.

await _channelClient.AddMembersAsync("messaging", "my-channel-id", new[] { "user-2" });

var partialRequest = new ChannelMemberPartialRequest
{
    UserId = "user-2",
    Set = new Dictionary<string, object>
    {
        { "hat", "blue" }, // Channel member custom data is separate from user custom data
    },
};
await _channelClient.UpdateMemberPartialAsync("messaging", "my-channel-id", partialRequest);

Remove channel members / Leave a channel

Remove channel members

removeMembers method allows you to remove members from a channel.

await _channelClient.RemoveMembersAsync("messaging", "my-channel-id", new[] { "user-2", "user-3" });

Note: You can only remove up to 100 members at once.

Leave a channel

Users can leave a channel without moderator-level permissions.

Ensure channel members have the Leave Own Channel permission enabled.

await _channelClient.RemoveMembersAsync("messaging", "my-channel-id", new[] { "user-2" });

You can familiarize yourself with all permissions in Permissions section

Add / Remove moderators to a 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.

Add moderators

The addModerators method adds specified users as moderators to a channel. If the users are already members, their role is upgraded to moderator.

await _channelClient.AddModeratorsAsync("messaging", "my-channel-id", new[] { "user-2", "user-3" });

Remove moderators

The demoteModerators method removes the moderator role from specified users.

await _channelClient.DemoteModeratorsAsync("messaging", "my-channel-id", new[] { "user-2", "user-3" });

These operations can only be performed server-side, and a maximum of 100 moderators can be added or removed at once.

Update channel members

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 fields
var memberResponse = await _channelClient.UpdateMemberPartialAsync("messaging", "my-channel-id",
    new ChannelMemberPartialRequest
    {
        UserId = "user-2",
        Set = new Dictionary<string, object>
        {
            { "hat", "blue" },
            { "score", 1000 },
        },
    });

// Unset some fields
var memberResponse2 = await _channelClient.UpdateMemberPartialAsync("messaging", "my-channel-id",
    new ChannelMemberPartialRequest
    {
        UserId = "user-2",
        Unset = new[] { "hat", "score" },
    });

// Set / Unset in a single request
var memberResponse3 = await _channelClient.UpdateMemberPartialAsync("messaging", "my-channel-id",
    new ChannelMemberPartialRequest
    {
        UserId = "user-2",
        Set = new Dictionary<string, object>
        {
            { "hat", "blue" },
        },
        Unset = new[] { "score" },
    });

Query channel members

The queryMembers endpoint enables listing and paginating channel members. It offers filtering options to efficiently retrieve member information. This feature is particularly useful when you need to search through or display a comprehensive overview of channel membership.

Pagination and ordering

By default, members are ordered from oldest to newest and can be paginated using offset-based pagination or by the created_at or user_id fields.

While pagination by offset is the simplest to implement, it can lead to incorrect results if the list of members changes during pagination.

The recommended approach is to sort created_at or user_id for more reliable results.

// Simple members query
var response = await _channelClient.QueryMembersAsync(new QueryMembersRequest
{
    Type = "messaging",
    Id = "my-channel-id",
    FilterConditions = new Dictionary<string, object>(),
});

// Query members with filter and sort
var response2 = await _channelClient.QueryMembersAsync(new QueryMembersRequest
{
    Type = "messaging",
    Id = "my-channel-id",
    FilterConditions = new Dictionary<string, object>
    {
        { "color", "blue" }, // Filters by member custom data (not user custom data)
    },
    Sorts = new[]
    {
        new SortParameter
        {
            Field = "created_at",
            Direction = SortDirection.Descending,
        },
    },
});

// Query members with limit and pagination
var response3 = await _channelClient.QueryMembersAsync(new QueryMembersRequest
{
    Type = "messaging",
    Id = "my-channel-id",
    FilterConditions = new Dictionary<string, object>
    {
        { "color", "blue" }, // Filters by member custom data (not user custom data)
    },
    Limit = 50, // Take 50 records
    Offset = 50, // Skip the first 50 records. Use for pagination -> calc from limit & page
    Sorts = new[]
    {
        new SortParameter
        {
            Field = "created_at",
            Direction = SortDirection.Descending,
        },
    },
});

Here’s some example of how you can query the list of members:

// Get members with pending invites
var response = await _channelClient.QueryMembersAsync(new QueryMembersRequest
{
    Type = "messaging",
    Id = "my-channel-id",
    FilterConditions = new Dictionary<string, object>
    {
        { "invite", "pending" },
    },
});

// Search by name autocomplete
var response2 = await _channelClient.QueryMembersAsync(new QueryMembersRequest
{
    Type = "messaging",
    Id = "my-channel-id",
    FilterConditions = new Dictionary<string, object>
    {
        {
            "name", new Dictionary<string, string>
            {
                { "$autocomplete", "tomm" }
            }
        },
    },
});

// Get moderators
var response3 = await _channelClient.QueryMembersAsync(new QueryMembersRequest
{
    Type = "messaging",
    Id = "my-channel-id",
    FilterConditions = new Dictionary<string, object>
    {
        { "channel_role", "channel_moderator" },
    },
});

// Get members who have joined the channel
var response4 = await _channelClient.QueryMembersAsync(new QueryMembersRequest
{
    Type = "messaging",
    Id = "my-channel-id",
    FilterConditions = new Dictionary<string, object>
    {
        { "joined", true },
    },
});

// Get banned members
var response5 = await _channelClient.QueryMembersAsync(new QueryMembersRequest
{
    Type = "messaging",
    Id = "my-channel-id",
    FilterConditions = new Dictionary<string, object>
    {
        { "banned", true },
    },
});

// Get members by custom data
var response6 = await _channelClient.QueryMembersAsync(new QueryMembersRequest
{
    Type = "messaging",
    Id = "my-channel-id",
    FilterConditions = new Dictionary<string, object>
    {
        { "subscription", "gold_plan" },
    },
});

// Get members by user email
var response7 = await _channelClient.QueryMembersAsync(new QueryMembersRequest
{
    Type = "messaging",
    Id = "my-channel-id",
    FilterConditions = new Dictionary<string, object>
    {
        { "user.email", "example@getstream.io" },
    },
});

Query Parameters

nametypedescriptiondefaultoptional
filtersobjectQuery filters to use. You can query on any of the custom fields defined above{}
sortobjectSort parameters{ created_at:1 }
optionsobjectPagination options{ limit:100, offset:0 }

By default when query members does not have any filter and it will match all members on your channel.

Member Queryable Built-In Fields

The following fields can be used to filter channel members, along with any custom data associated with them:

NameTypeDescriptionSupported operators
idstringUser ID$eq - $in
namestringUser name$eq - $in - $autocomplete - $q
channel_rolestringMember role$eq
bannedbooleanBan status$eq
invitestring accepted values: - pending - accepted - rejectedInvite status$eq
joinedbooleanWhether user joined the channel or not$eq
created_atstring (RFC3339)Time when the member was created$eq - $gt - $gte - $lt - $lte
updated_atstring (RFC3339)Time when the member was updated$eq - $gt - $gte - $lt - $lte
last_activestring (RFC3339)Last time the member was active$eq - $gt - $gte - $lt - $lte
cidstringChannel CID$eq
user.emailstringUser’s email property$eq - $in - $autocomplete

Query options

nametypedescriptiondefaultoptional
limitintegerNumber of members to return100
offsetintegerOffset (max is 1000)0
user_id_ltstringPagination option: excludes members with ID greater or equal the value
user_id_ltestringPagination option: excludes members with ID greater than the value
user_id_gtstringPagination option: excludes members with ID less or equal the value
user_id_gtestringPagination option: excludes members with ID less than the value
created_at_afterstringPagination option: select members created after the date (RFC399)
created_at_beforestringPagination option: select members created before the date (RFC399)
created_at_before_or_equalstringPagination option: select members created before or equal the date (RFC399)
created_at_after_or_equalstringPagination option: select members created after or equal the date (RFC399)

Response

Field nameDescription
MembersThe list of members matching the query
© Getstream.io, Inc. All Rights Reserved.