# 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

<codetabs>

<codetabs-item value="javascript" label="JavaScript">

```js
// members can be added by passing an array of user IDs
const channel = client.channel("messaging", randomID, {
  members: ["userid1", "userid2", "userid3"],
});

// or by passing objects
const channel = client.channel("messaging", randomID, {
  members: [
    { user_id: "userid1" },
    { user_id: "userid2" },
    { user_id: "userid3" },
  ],
});
```

</codetabs-item>

<codetabs-item value="swift" label="Swift">

```swift
let channelController = try ChatClient.shared.channelController(
	createChannelWithId: randomId,
	members: [
		"userid1",
		"userid2",
		"userid3"
	]
)
// Calling synchronize() is required to persist the channel to the server.
channelController.synchronize()
```

</codetabs-item>

<codetabs-item value="java" label="Java">

```java
ChannelGetResponse channel = Channel.getOrCreate("messaging", "channel-1")
    .data(
        ChannelRequestObject.builder()
            .createdBy(user1)
            .members(
                users.stream().map((x) -> ChannelMemberRequestObject.builder().user(x).build())
                    .collect(Collectors.toList()))
            .build())
    .request();
```

</codetabs-item>

<codetabs-item value="csharp" label="C#">

```csharp
// 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;
```

</codetabs-item>

<codetabs-item value="kotlin" label="Kotlin">

```kotlin
// members can be added by passing a list of user IDs
channelClient.create(
  memberIds = listOf("userid1", "userid2", "userid3"),
  extraData = emptyMap(),
).enqueue()

// or by passing objects
val params = CreateChannelParams(
  members = listOf(
    MemberData(userId = "userid1"),
    MemberData(userId = "userid2"),
    MemberData(userId = "userid3", extraData = mapOf("custom" to "value")),
  ),
  extraData = emptyMap(),
)
channelClient.create(params).enqueue()
```

</codetabs-item>

</codetabs>

#### Using `addMembers` method

<codetabs>

<codetabs-item value="javascript" label="JavaScript">

```js
await channel.addMembers(["userid1", "userid2"]);

// you can set channel_role in the meantime
await channel.addMembers([
  { user_id: "userid1", channel_role: "channel_moderator" },
]);
```

</codetabs-item>

<codetabs-item value="swift" label="Swift">

```swift
// members can be added by passing an array of user IDs
let channelController = ChatClient.shared.channelController(for: randomId)
channelController.addMembers(userIds: ["userid1", "userid2", "userid3"])

// or by passing objects
let channelController = ChatClient.shared.channelController(for: randomId)
channelController.addMembers([
	MemberInfo(userId: "userid1"),
	MemberInfo(userId: "userid2"),
	MemberInfo(userId: "userid3", extraData: ["custom": .string("value")])
])
```

</codetabs-item>

<codetabs-item value="java" label="Java">

```java
Channel.update("messaging", "channel-1").addMember("user-3").request();
```

</codetabs-item>

<codetabs-item value="csharp" label="C#">

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

</codetabs-item>

<codetabs-item value="kotlin" label="Kotlin">

```kotlin
// members can be added by passing a list of user IDs
channelClient.addMembers(listOf("userid1", "userid2", "userid3")).enqueue()

// or by passing objects
val params = AddMembersParams(
  members = listOf(
    MemberData(userId = "userid1"),
    MemberData(userId = "userid2"),
    MemberData(userId = "userid3", extraData = mapOf("custom" to "value")),
  ),
)
channelClient.addMembers(params).enqueue()
```

</codetabs-item>

</codetabs>

<admonition type="info">

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

</admonition>

**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.

<codetabs>

<codetabs-item value="javascript" label="JavaScript">

```js
await channel.addMembers(["userid1"], { text: "Tommaso joined the channel." });

// using server-side client, you need to specify the sender user_id
await channel.addMembers(["userid1"], {
  text: "Tommaso joined the channel.",
  user_id: "userid2",
});
```

</codetabs-item>

<codetabs-item value="swift" label="Swift">

```swift
channelController.addMembers(
	userIds: ['userid1'],
	message: "Tommaso joined the channel."
) { error in
	// handle error
}
```

</codetabs-item>

<codetabs-item value="java" label="Java">

```java
Channel.update("messaging", "channel-1").addMember("user-3")
    .message(MessageRequestObject.builder().text("User 3 joined!").build()).request();
```

</codetabs-item>

<codetabs-item value="csharp" label="C#">

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

</codetabs-item>

<codetabs-item value="kotlin" label="Kotlin">

```kotlin
channelClient.addMembers(
  memberIds = listOf("userid1"),
  systemMessage = Message(text = "New user joined this channel."),
).enqueue()
```

</codetabs-item>

</codetabs>

**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` .

<codetabs>

<codetabs-item value="javascript" label="JavaScript">

```js
await channel.addMembers(["userid1"], undefined, { hide_history: true });
```

</codetabs-item>

<codetabs-item value="swift" label="Swift">

```swift
channelController.addMembers(userIds: ['userid1'], hideHistory: true)
```

</codetabs-item>

<codetabs-item value="java" label="Java">

```java
Channel.update("messaging", "channel-1").addMember("user-3").hideHistory(true).request();
```

</codetabs-item>

<codetabs-item value="csharp" label="C#">

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

</codetabs-item>

<codetabs-item value="kotlin" label="Kotlin">

```kotlin
channelClient.addMembers(
  memberIds = listOf("userid1"),
  hideHistory = true,
).enqueue()
```

</codetabs-item>

</codetabs>

### Channel member custom data

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

<codetabs>

<codetabs-item value="javascript" label="JavaScript">

```js
// add custom data while creating the channel
const channel = client.channel("messaging", randomID, {
  members: [
    { user_id: "userid1", key1: "value1" },
    { user_id: "userid2", key1: "value1" },
    { user_id: "userid3", key2: "value2" },
  ],
});

// add custom data with `addMembers` method
await channel.addMembers([{ user_id: "userid1", key1: "value1" }]);
```

</codetabs-item>

<codetabs-item value="swift" label="Swift">

```swift
channelController.addMembers([
	MemberInfo(userId: "userid1", extraData: ["key1": .string("value1")]),
	MemberInfo(userId: "userid2", extraData: ["key2": .string("value2")]),
	MemberInfo(userId: "userid3", extraData: ["key3": .string("value3")])
])
```

</codetabs-item>

<codetabs-item value="csharp" label="C#">

```csharp
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);
```

</codetabs-item>

<codetabs-item value="kotlin" label="Kotlin">

```kotlin
// add custom data while creating the channel
val 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` method
val params = AddMembersParams(
  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")),
  ),
)
channelClient.addMembers(params).enqueue()
```

</codetabs-item>

</codetabs>

Remove channel members / Leave a channel

#### Remove channel members

`removeMembers` method allows you to remove members from a channel.

<codetabs>

<codetabs-item value="javascript" label="JavaScript">

```js
await channel.removeMembers(["userid1", "userid2"]);
```

</codetabs-item>

<codetabs-item value="swift" label="Swift">

```swift
channelController.removeMembers(userIds: ["userid1", "userid2"])
```

</codetabs-item>

<codetabs-item value="csharp" label="C#">

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

</codetabs-item>

<codetabs-item value="kotlin" label="Kotlin">

```kotlin
channelClient.removeMembers(listOf("userid1", "userid2")).enqueue()
```

</codetabs-item>

</codetabs>

<admonition type="info">

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

</admonition>

#### Leave a channel

Users can leave a channel without moderator-level permissions.

Ensure channel members have the `Leave Own Channel` permission enabled.

<codetabs>

<codetabs-item value="javascript" label="JavaScript">

```js
// remove own channel membership
await channel.removeMembers(["myuserid"]);
```

</codetabs-item>

<codetabs-item value="swift" label="Swift">

```swift
channelController.removeMembers(userIds: ["myuserid"])
```

</codetabs-item>

<codetabs-item value="csharp" label="C#">

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

</codetabs-item>

<codetabs-item value="kotlin" label="Kotlin">

```kotlin
channelClient.removeMembers(listOf("myuserid")).enqueue()
```

</codetabs-item>

</codetabs>

<admonition type="info">

You can familiarize yourself with all permissions in [Permissions section](/chat/docs/<framework>/chat_permission_policies/)

</admonition>

### 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.

<codetabs>

<codetabs-item value="javascript" label="JavaScript">

```js
await channel.addModerators(["userid1", "userid2"]);
```

</codetabs-item>

<codetabs-item value="csharp" label="C#">

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

</codetabs-item>

</codetabs>

#### Remove moderators

The `demoteModerators` method removes the moderator role from specified users.

<codetabs>

<codetabs-item value="javascript" label="JavaScript">

```js
await channel.demoteModerators(["userid1"]);
```

</codetabs-item>

<codetabs-item value="csharp" label="C#">

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

</codetabs-item>

</codetabs>

<admonition type="info">

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

</admonition>

### 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.

<codetabs>

<codetabs-item value="javascript" label="JavaScript">

```js
// set some fields
await channel.updateMemberPartial(
  {
    set: {
      key1: "new value 1",
      key2: "new value 2",
      channel_role: "channel_moderator",
    },
  },
  { userId: "jane" },
);

// unset some fields
await channel.updateMemberPartial(
  {
    unset: ["key1", "key2"],
  },
  { userId: "jane" },
);

// set / unset in the same call
await channel.updateMemberPartial(
  {
    set: {
      key1: "new value 1",
      key2: "new value 2",
    },
    unset: ["key3"],
  },
  { userId: "jane" },
);
```

</codetabs-item>

<codetabs-item value="swift" label="Swift">

```swift
// set some fields
let memberController = ChatClient.shared.memberController(
	userId: someUserId,
	in: someChannelId
)
memberController.partialUpdate(extraData: [
	"key1": .string("value1"),
	"key2": .string("value2")
])

// unset some fields
memberController.partialUpdate(extraData: nil, unsetProperties: ["key1", "key2"])

// set / unset in the same call
memberController.partialUpdate(
	extraData: [
		"key1": .string("value1"),
		"key2": .string("value2"),
	],
	unsetProperties: ["key3"]
)
```

</codetabs-item>

<codetabs-item value="go" label="Go">

```go
// set some fields
member, err := ch.PartialUpdateMember(ctx, members[0], PartialUpdate{
	Set: map[string]interface{}{
		"color": "red",
	},
})

// unset some fields
member, err := ch.PartialUpdateMember(ctx, members[0], PartialUpdate{
	Unset: []string{"age"},
})

// set / unset in the same call
member, err := ch.PartialUpdateMember(ctx, members[0], PartialUpdate{
	Set: map[string]interface{}{
		"color": "red",
	},
	Unset: []string{"age"},
})
```

</codetabs-item>

<codetabs-item value="php" label="Php">

```php
$userId = "amy";

// set some fields
$response = $this->channel->updateMemberPartial($userId, ["hat" => "blue"]);

// unset some fields
$response = $this->channel->updateMemberPartial($userId, null, ["hat"]);

// set / unset in the same call
$response = $this->channel->updateMemberPartial($userId, ["hat" => "blue"], ["hat"]);
```

</codetabs-item>

<codetabs-item value="python" label="Python">

```python
user_id = "amy"

// set some fields
response = channel.update_member_partial(user_id, to_set={"hat": "blue"})

// unset some fields
response = channel.update_member_partial(user_id, to_set=None, to_unset=["hat"])

// set / unset in the same call
response = channel.update_member_partial(user_id, to_set={"color": "red"}, to_unset=["hat"])
```

</codetabs-item>

<codetabs-item value="ruby" label="Ruby">

```ruby
# require 'stream-chat'

user_id = "amy"

// set some fields
response = channel.update_member_partial(user_id, set: { 'color' => 'red' })

// unset some fields
response = channel.update_member_partial(user_id, set: nil, unset: ['hat'])

// set / unset in the same call
response = channel.update_member_partial(user_id, set: { 'color' => 'red' }, unset: ['hat'])
```

</codetabs-item>

<codetabs-item value="java" label="Java">

```java
// set some fields
Channel.updateMemberPartial(channel.getType(), channel.getId(), "user-1")
    .setValue("custom_key", "custom_value")
    .setValue("channel_role", "channel_moderator")
    .request();

// unset some field
Channel.updateMemberPartial(channel.getType(), channel.getId(), "user-1")
    .unsetValue("custom_key")
    .request();

// set / unset in the same call
Channel.updateMemberPartial(channel.getType(), channel.getId(), "user-1")
    .setValue("color", "red")
    .unsetValue("age")
    .request();
```

</codetabs-item>

<codetabs-item value="csharp" label="C#">

```csharp
// 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" },
    });
```

</codetabs-item>

<codetabs-item value="kotlin" label="Kotlin">

```kotlin
// set some fields
channelClient.partialUpdateMember(
  userId = "userid1",
  set = mapOf(
    "key1" to "new value 1",
    "key2" to "new value 2",
  ),
).enqueue()

// unset some fields
channelClient.partialUpdateMember(
  userId = "userid1",
  unset = listOf("key1", "key2"),
).enqueue()

// set / unset in the same call
channelClient.partialUpdateMember(
  userId = "userid1",
  set = mapOf(
    "key1" to "new value 1",
    "key2" to "new value 2",
  ),
  unset = listOf("key3"),
).enqueue()
```

</codetabs-item>

</codetabs>

### 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.

<codetabs>

<codetabs-item value="javascript" label="JavaScript">

```js
await channel.queryMembers({}, sort, {});

// returns up to 100 members ordered by created_at descending
let sort = { created_at: -1 };
await channel.queryMembers({}, sort, {});

// returns up to 100 members ordered by user_id descending
sort = { user_id: -1 };
await channel.queryMembers({}, sort, {});

// paginate by user_id in descending order
sort = { user_id: 1 };
let options = { user_id_lt: lastMember.user_id };
await channel.queryMembers({}, sort, options);

// paginate by created at in ascending order
sort = { created_at: -1 };
options = { created_at_before: lastMember.created_at };
await channel.queryMembers({}, sort, options);

// paginate using offset
options = { offset: 20 };
await channel.queryMembers({}, sort, {});
```

</codetabs-item>

<codetabs-item value="swift" label="Swift">

```swift
// creates the controller and synchronizes the first batch of 25 members
let query = ChannelMemberListQuery(cid: channelId)
let memberListController = client.memberListController(query: query)
memberListController.synchronize()

// changing the default page size to 50
let query = ChannelMemberListQuery(cid: channelId, pageSize: 50)
let memberListController = client.memberListController(query: query)
memberListController.synchronize()

// changing the sort order by user_id in descending order
let query = ChannelMemberListQuery(cid: channelId, sort: [.init(key: .userId, isAscending: false)])
let memberListController = client.memberListController(query: query)
memberListController.synchronize()
```

</codetabs-item>

<codetabs-item value="csharp" label="C#">

```csharp
// 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,
        },
    },
});
```

</codetabs-item>

<codetabs-item value="kotlin" label="Kotlin">

```kotlin
// Returns the first batch of 25 members
channelClient.queryMembers(
    offset = 0,
    limit = 25,
    filter = Filters.neutral(),
    sort = QuerySortByField()
).enqueue()

// Sort the members by user_id in descending order
channelClient.queryMembers(
    offset = 0,
    limit = 3,
    filter = Filters.neutral(),
    sort = QuerySortByField.descByName("user_id")
).enqueue()
```

</codetabs-item>

</codetabs>

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

<codetabs>

<codetabs-item value="javascript" label="JavaScript">

```js
// query members by user.name
channel.queryMembers({'name':'tommaso'})

// autocomplete members by user name
channel.queryMembers({name:{"$autocomplete":'tomm'}})

// query member by id
channel.queryMembers({user_id:'tommaso'})

// query multiple members by id
channel.queryMembers({user_id:{'$in:'['tommaso','thierry']}})

// query channel moderators
channel.queryMembers({is_moderator:true})

// query for banned members in channel
channel.queryMembers({banned:true})

// query members with pending invites
channel.queryMembers({invite:'pending'})

// query members who joined the channel directly or accepted an invite
channel.queryMembers({joined: true})

// query members who have rejected invite or have pending invite
channel.queryMembers({joined: false}

// query all the members
channel.queryMembers({})

// order results by member created at descending
channel.queryMembers({}, {created_at:-1})

// query by user.email
client.queryMembers({ 'user.email':'awesome@getstream.io' })

// you can also query members by custom data
// subscription is a custom field
client.queryMembers({ 'subscription':'gold_plan' })
```

</codetabs-item>

<codetabs-item value="swift" label="Swift">

```swift
// query members by user.name
let query = ChannelMemberListQuery(cid: channelId, filter: .equal(.name, to: "tommaso"))
let memberListController = client.memberListController(query: query)
memberListController.synchronize()

// autocomplete members by user name
let query = ChannelMemberListQuery(cid: channelId, filter: .autocomplete(.name, text: "tomm"))
let memberListController = client.memberListController(query: query)
memberListController.synchronize()

// query member by id
let query = ChannelMemberListQuery(cid: channelId, filter: .equal(.id, to: "tommaso"))
let memberListController = client.memberListController(query: query)
memberListController.synchronize()

// query multiple members by id
let query = ChannelMemberListQuery(cid: channelId, filter: .in(.id, values: ["tommaso", "thierry"]))
let memberListController = client.memberListController(query: query)
memberListController.synchronize()

// query channel moderators
let query = ChannelMemberListQuery(cid: channelId, filter: .equal(.isModerator, to: true))
let memberListController = client.memberListController(query: query)
memberListController.synchronize()

// query for banned members in channel
let query = ChannelMemberListQuery(cid: channelId, filter: .equal(.banned, to: true))
let memberListController = client.memberListController(query: query)
memberListController.synchronize()

// query members who joined the channel directly or accepted an invite
let query = ChannelMemberListQuery(cid: channelId, filter: .equal(.joined, to: true))
let memberListController = client.memberListController(query: query)
memberListController.synchronize()

// query members who have rejected invite or have pending invite
let query = ChannelMemberListQuery(cid: channelId, filter: .equal(.joined, to: false))
let memberListController = client.memberListController(query: query)
memberListController.synchronize()

// you can also query members by custom data by providing a string directly
let query = ChannelMemberListQuery(cid: channelId, filter: .equal("subscription", to: "gold_plan"))
let memberListController = client.memberListController(query: query)
memberListController.synchronize()
```

</codetabs-item>

<codetabs-item value="csharp" label="C#">

```csharp
// 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" },
    },
});
```

</codetabs-item>

<codetabs-item value="kotlin" label="Kotlin">

```kotlin
// query members by user.name
channelClient.queryMembers(
    offset = 0,
    limit = 10,
    filter = Filters.eq("name", "tommaso"),
    sort = QuerySortByField()
).enqueue()

// autocomplete members by user name
channelClient.queryMembers(
    offset = 0,
    limit = 10,
    filter = Filters.autocomplete("name", "tomm"),
    sort = QuerySortByField()
).enqueue()

// query member by id
channelClient.queryMembers(
    offset = 0,
    limit = 10,
    filter = Filters.eq("id", "tommaso"),
    sort = QuerySortByField()
).enqueue()

// query multiple members by id
channelClient.queryMembers(
    offset = 0,
    limit = 10,
    filter = Filters.`in`("id", listOf("tommaso", "thierry")),
    sort = QuerySortByField()
).enqueue()

// query channel moderators
channelClient.queryMembers(
    offset = 0,
    limit = 10,
    filter = Filters.eq("is_moderator", true),
    sort = QuerySortByField()
).enqueue()

// query for banned members in channel
channelClient.queryMembers(
    offset = 0,
    limit = 10,
    filter = Filters.eq("banned", true),
    sort = QuerySortByField()
).enqueue()

// query members who joined the channel directly or accepted an invite
channelClient.queryMembers(
    offset = 0,
    limit = 10,
    filter = Filters.eq("joined", true),
    sort = QuerySortByField()
).enqueue()

// query members who have rejected invite or have pending invite
channelClient.queryMembers(
    offset = 0,
    limit = 10,
    filter = Filters.eq("joined", false),
    sort = QuerySortByField()
).enqueue()

// you can also query members by custom data by providing a string directly
channelClient.queryMembers(
    offset = 0,
    limit = 10,
    filter = Filters.eq("subscription", "gold_plan"),
    sort = QuerySortByField()
).enqueue()
```

</codetabs-item>

</codetabs>

#### Query Parameters

| name    | type   | description                                                                   | default                 | optional |
| ------- | ------ | ----------------------------------------------------------------------------- | ----------------------- | -------- |
| filters | object | Query filters to use. You can query on any of the custom fields defined above | {}                      |          |
| sort    | object | Sort parameters                                                               | { created_at:1 }        | ✓        |
| options | object | Pagination 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:

| Name         | Type                                                    | Description                            | Supported operators            |
| ------------ | ------------------------------------------------------- | -------------------------------------- | ------------------------------ |
| id           | string                                                  | User ID                                | $eq - $in                      |
| name         | string                                                  | User name                              | $eq - $in - $autocomplete - $q |
| channel_role | string                                                  | Member role                            | $eq                            |
| banned       | boolean                                                 | Ban status                             | $eq                            |
| invite       | string accepted values: - pending - accepted - rejected | Invite status                          | $eq                            |
| joined       | boolean                                                 | Whether user joined the channel or not | $eq                            |
| created_at   | string (RFC3339)                                        | Time when the member was created       | $eq - $gt - $gte - $lt - $lte  |
| updated_at   | string (RFC3339)                                        | Time when the member was updated       | $eq - $gt - $gte - $lt - $lte  |
| last_active  | string (RFC3339)                                        | Last time the member was active        | $eq - $gt - $gte - $lt - $lte  |
| cid          | string                                                  | Channel CID                            | $eq                            |
| user.email   | string                                                  | User's email property                  | $eq - $in - $autocomplete      |

#### Query options

| name                       | type    | description                                                                 | default | optional |
| -------------------------- | ------- | --------------------------------------------------------------------------- | ------- | -------- |
| limit                      | integer | Number of members to return                                                 | 100     | ✓        |
| offset                     | integer | Offset (max is 1000)                                                        | 0       | ✓        |
| user_id_lt                 | string  | Pagination option: excludes members with ID greater or equal the value      |         | ✓        |
| user_id_lte                | string  | Pagination option: excludes members with ID greater than the value          |         | ✓        |
| user_id_gt                 | string  | Pagination option: excludes members with ID less or equal the value         |         | ✓        |
| user_id_gte                | string  | Pagination option: excludes members with ID less than the value             |         | ✓        |
| created_at_after           | string  | Pagination option: select members created after the date (RFC399)           |         | ✓        |
| created_at_before          | string  | Pagination option: select members created before the date (RFC399)          |         | ✓        |
| created_at_before_or_equal | string  | Pagination option: select members created before or equal the date (RFC399) |         | ✓        |
| created_at_after_or_equal  | string  | Pagination option: select members created after or equal the date (RFC399)  |         | ✓        |

#### Response

| Field name | Description                            |
| ---------- | -------------------------------------- |
| Members    | The list of members matching the query |

---

This page was last updated at 2025-08-15T14:14:36.347Z.

For the most recent version of this documentation, visit [https://getstream.io/chat/docs/ios-swift/channel_member/](https://getstream.io/chat/docs/ios-swift/channel_member/).