---
source_url: https://www.pubnub.com/docs/chat/chat-sdk/build/features/channels/membership
title: Manage the user-channel membership relationship
updated_at: 2026-06-01T12:01:18.843Z
---

> Documentation Index
> For a curated overview of PubNub documentation, see: https://www.pubnub.com/docs/llms.txt
> For the full list of all documentation pages, see: https://www.pubnub.com/docs/llms-full.txt


# Manage the user-channel membership relationship

:::note Requires App Context
Enable [App Context](https://youtu.be/9UEoSlngpYI) for your keyset in the [Admin Portal](https://admin.pubnub.com/).
:::

A [Membership entity](https://www.pubnub.com/docs/chat/chat-sdk/learn/chat-entities/membership) is created when a user [joins](https://www.pubnub.com/docs/chat/chat-sdk/build/features/channels/join) or is [invited](https://www.pubnub.com/docs/chat/chat-sdk/build/features/channels/invite) to a channel, and ends when the user [leaves](https://www.pubnub.com/docs/chat/chat-sdk/build/features/channels/leave).

## Interactive demo

Sample React app demonstrating user-channel membership.

:::tip Want to implement something similar?
[Implementation guide](https://www.pubnub.com/how-to/chat-sdk-manage-user-channel-membership/) | [Source code](https://github.com/PubNubDevelopers/Chat-SDK-How-Tos/tree/main/membership)
:::

### Test it out

Choose whether you want to [join](https://www.pubnub.com/docs/chat/chat-sdk/build/features/channels/join) or [leave](https://www.pubnub.com/docs/chat/chat-sdk/build/features/channels/leave) a given channel and wait until you [get notified](https://www.pubnub.com/docs/chat/chat-sdk/build/features/channels/membership#get-updates) when that happens.

## Get members

Get all members of a channel with `getMembers()`.

##### Under the hood

`getMembers()` calls App Context API and the JavaScript SDK [getChannelMembers()](https://www.pubnub.com/docs/sdks/javascript/api-reference/objects#get-channel-members) method.

### Method signature

This method takes the following parameters:

```ts
channel.getMembers({
    filter?: string,
    sort?: object,
    limit?: number,
    page?: {
        next?: string,
        prev?: string,
    }
}): Promise<{
    page: {
        next: string;
        prev: string;
    };
    total: number;
    status: number;
    members: Membership[];
}>
```

#### Input

| Parameter | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| filter | string | Optional |  | Expression used to filter the results. Returns only these members whose properties satisfy the given expression. The filtering language is [defined here](https://www.pubnub.com/docs/general/metadata/filtering). |
| sort | object | Optional |  | Key-value pair of a property to sort by, and a sort direction. Available options are `id`, `name`, and `updated`. Use `asc` or `desc` to specify the sorting direction, or specify `null` to take the default sorting direction (ascending). For example: `{name: "asc"}`. By default, the items are sorted by the last updated date. |
| limit | number | Optional | `100` | Number of objects to return in response. The default (and maximum) value is `100`. |
| page | object | Optional |  | Object used for pagination to define which previous or next result page you want to fetch. |
| > next | string | Optional |  | Random string returned from the server, indicating a specific position in a data set. Used for forward pagination, it fetches the next page, allowing you to continue from where you left off. |
| > prev | string | Optional |  | Random string returned from the server, indicating a specific position in a data set. Used for backward pagination, it fetches the previous page, enabling access to earlier data. Ignored if the `next` parameter is supplied. |

#### Output

| Parameter | Description |
| --- | --- |
| `Promise<>`Type: `object` | Returned object containing these fields: `page`, `total`, `status`, and `members`. |
| `> page`Type: `object` | Object used for pagination to define which previous or next result page you want to fetch. |
| `>> next`Type: `string` | Random string returned from the server, indicating a specific position in a data set. Used for forward pagination, it fetches the next page, allowing you to continue from where you left off. |
| `>> prev`Type: `string` | Random string returned from the server, indicating a specific position in a data set. Used for backward pagination, it fetches the previous page, enabling access to earlier data. Ignored if the `next` parameter is supplied. |
| `> total`Type: `number` | Total number of channel members. |
| `> status`Type: `number` | Status code of a server response, like `200`. |
| `> members`Type: `Membership[]` | List of all related memberships. |

### Sample code

List all members of the `support` channel on the `premium` support plan.

```ts
// reference the "channel" object
const channel = await chat.getChannel("support")

// get the list of all members with the premium support plan
await channel.getMembers({
    filter: "custom.support_plan == 'premium'"
})
```

## Get membership

Get all channel [memberships](https://www.pubnub.com/docs/chat/chat-sdk/learn/chat-entities/membership) for a user with `getMemberships()`.

##### Under the hood

`getMemberships()` calls App Context API and the JavaScript SDK [getMemberships()](https://www.pubnub.com/docs/sdks/javascript/api-reference/objects#channel-memberships) method.

To list all channels, use [getChannels()](https://www.pubnub.com/docs/chat/chat-sdk/build/features/channels/list) instead.

### Method signature

This method takes the following parameters:

```ts
user.getMemberships({
    filter?: string,
    sort?: object,
    limit?: number,
    page?: {
        next?: string,
        prev?: string
    }
}): Promise<{
        page: {
            next: string,
            prev: string,
        };
        total: number,
        status: number,
        memberships: Membership[]
    }>
```

#### Input

| Parameter | Description |
| --- | --- |
| `filter`Type: `string`Default: n/a | Expression used to filter the results. Returns only these memberships whose properties satisfy the given expression. The filtering language is [defined here](https://www.pubnub.com/docs/general/metadata/filtering). |
| `sort`Type: `object`Default: n/a | Key-value pair of a property to sort by, and a sort direction. Available options are `id`, `name`, and `updated`. Use `asc` or `desc` to specify the sorting direction, or specify `null` to take the default sorting direction (ascending). For example: `{name: "asc"}`. By default, the items are sorted by the last updated date. |
| `limit`Type: `number`Default: `100` | Number of objects to return in response. The default (and maximum) value is `100`. |
| `page`Type: `object`Default: n/a | Object used for pagination to define which previous or next result page you want to fetch. |
| `> next`Type: `string`Default: n/a | Random string returned from the server, indicating a specific position in a data set. Used for forward pagination, it fetches the next page, allowing you to continue from where you left off. |
| `> prev`Type: `string`Default: n/a | Random string returned from the server, indicating a specific position in a data set. Used for backward pagination, it fetches the previous page, enabling access to earlier data. Ignored if the `next` parameter is supplied. |

#### Output

| Parameter | Description |
| --- | --- |
| `Promise<>`Type: `object` | Returned object containing these fields: `page`, `total`, `status`, and `memberships`. |
| `> page`Type: `any` | Object used for pagination to define which previous or next result page you want to fetch. |
| `>> next`Type: `string` | Random string returned from the server, indicating a specific position in a data set. Used for forward pagination, it fetches the next page, allowing you to continue from where you left off. |
| `>> prev`Type: `string` | Random string returned from the server, indicating a specific position in a data set. Used for backward pagination, it fetches the previous page, enabling access to earlier data. Ignored if the `next` parameter is supplied. |
| `> total`Type: `number` | Total number of channel memberships. |
| `> status`Type: `number` | Status code of a server response, like `200`. |
| `> memberships`Type: `Membership[]` | List of all related [memberships](https://www.pubnub.com/docs/chat/chat-sdk/learn/chat-entities/membership). |

### Sample code

Find out which channels the `support_agent_15` user is a member of.

```ts
// reference the "support_agent_15" user
const user = await chat.getUser("support_agent_15")

// get the list of all user memberships
await user.getMemberships()
```

## Check membership

Check whether a specific user is a member of a channel, or whether a user belongs to a specific channel.

### Method signatures

These methods take the following parameters:

* channel.hasMember() — returns true if the given user is a member of the channel. 1channel.hasMember(userId: string): Promise<boolean>
* channel.getMember() — returns the Membership object for the given user on the channel, or null if not a member. 1channel.getMember(userId: string): Promise<Membership | null>
* user.isMemberOf() — returns true if the user is a member of the given channel. 1user.isMemberOf(channelId: string): Promise<boolean>
* user.getMembership() — returns the Membership object for the user on the given channel, or null if not a member. 1user.getMembership(channelId: string): Promise<Membership | null>

### Sample code

Check whether a user is a member of a channel, and retrieve their membership details.

```ts
// reference the "support" channel
const channel = await chat.getChannel("support")

// check if "support_agent_15" is a member of the channel
const isMember = await channel.hasMember("support_agent_15")
console.log("Is member:", isMember)

// get the membership object for "support_agent_15"
const membership = await channel.getMember("support_agent_15")
if (membership) {
    console.log("Membership:", membership)
}

// alternatively, check from the user's perspective
const user = await chat.getUser("support_agent_15")
const belongsToChannel = await user.isMemberOf("support")
console.log("Belongs to channel:", belongsToChannel)

// get the membership from the user's perspective
const userMembership = await user.getMembership("support")
if (userMembership) {
    console.log("User membership:", userMembership)
}
```

## Get updates

Receive updates when [Membership objects](https://www.pubnub.com/docs/chat/chat-sdk/learn/chat-entities/membership) are edited.

### Event-based methods

Use `onUpdated()` and `onDeleted()` to react to membership changes with callbacks:

```ts
membership.onUpdated(callback: (membership: Membership) => void): () => void
membership.onDeleted(callback: () => void): () => void
```

#### Sample code

Listen for updates and deletions on the first user membership.

```ts
const { memberships } = await chat.currentUser.getMemberships()
const membership = memberships[0]

const stopUpdated = membership.onUpdated((updatedMembership) => {
    console.log("Membership updated:", updatedMembership)
})

const stopDeleted = membership.onDeleted(() => {
    console.log("Membership was deleted")
})

// after some time...
stopUpdated()
stopDeleted()
```

### Stream-based methods (deprecated)

:::warning Deprecated
`streamUpdates()` is deprecated. Use [onUpdated()](#event-based-methods) and [onDeleted()](#event-based-methods) instead. `streamUpdatesOn()` remains supported.
:::

* `streamUpdates()` - monitors a single membership
* `streamUpdatesOn()` - monitors multiple memberships

:::note Membership changes
These methods notify about field changes (metadata, status) for existing memberships, not additions or removals.
:::

Both methods accept a callback invoked when membership data changes. They subscribe to a channel and add an [objects event listener](https://www.pubnub.com/docs/sdks/javascript/api-reference/configuration#event-listeners) for `membership` events, returning an `unsubscribe` function.

:::note Stream update behavior
* `streamUpdates()` returns the updated `Membership` object on each change (`null` if deleted)
* `streamUpdatesOn()` returns the complete list of monitored memberships on any change
:::

##### Under the hood

`streamUpdates()` and `streamUpdatesOn()` call Pub/Sub API and the JavaScript SDK [subscribe()](https://www.pubnub.com/docs/sdks/javascript/api-reference/publish-and-subscribe#subscribe) and [unsubscribe()](https://www.pubnub.com/docs/sdks/javascript/api-reference/publish-and-subscribe#unsubscribe) methods.

### Method signature

These methods take the following parameters:

* streamUpdates() 1membership.streamUpdates(2 callback: (membership: Membership) => unknown3): () => void
* streamUpdatesOn() 1static Membership.streamUpdatesOn(2 memberships: Membership[],3 callback: (memberships: Membership[]) => unknown4): () => void

#### Input

| Parameter | Required in `streamUpdates()` | Required in `streamUpdatesOn()` | Description |
| --- | --- | --- | --- |
| `memberships`Type: `Membership[]`Default: n/a | No | Yes | Array of [Membership objects](https://www.pubnub.com/docs/chat/chat-sdk/learn/chat-entities/membership) for which you want to get updates. |
| `callback`Type: n/aDefault: n/a | Yes | Yes | Callback function passed as a parameter to both methods. It defines the custom behavior to be executed when detecting membership changes. |
| `> membership`Type: `Membership`Default: n/a | Yes | No | Returned `Membership` object with the updated data. |
| `> memberships`Type: `Membership[]`Default: n/a | No | Yes | Returned array of `Membership` objects with the updated data. |

#### Output

| Type | Description |
| --- | --- |
| `() => void` | Function you can call to disconnect (unsubscribe) from the channel and stop receiving `objects` events. |

#### Errors

Whenever a list of `Membership` objects is required as a parameter, and you try to get updates on membership without specifying their list, you will receive the `Cannot stream membership updates on an empty list` error.

### Sample code

Get updates on the first user membership.

* streamUpdates() 1const { memberships } = await chat.currentUser.getMemberships()2const membership = memberships[0]3membership.streamUpdates((membership) => {4 // The callback receives the entire updated Membership object each time a change occurs.5 if (membership) {6 console.log("Updated membership: ", membership)7 } else {8 console.log("Membership was deleted")9 }10})

Get updates on the first page of user memberships.

* streamUpdatesOn() 1const { memberships } = await chat.currentUser.getMemberships()2Membership.streamUpdatesOn(memberships, (memberships) => {3 // The callback receives the complete list of all memberships you're monitoring4 // each time any change occurs.5 console.log("Updated memberships: ", memberships)6})

### Other examples

Stop listening to updates on the first user membership.

* streamUpdates() 1const { memberships } = await chat.currentUser.getMemberships()2const membership = memberships[0]3const stopUpdates = membership.streamUpdates(/* handle update callback */)4// after some time...5stopUpdates()

Stop listening to updates on the first page of user memberships.

* streamUpdatesOn() 1const { memberships } = await chat.currentUser.getMemberships()2const stopUpdates = Membership.streamUpdatesOn(memberships, /* handle update callback */)3// after some time...4stopUpdates()

## Delete membership

Delete a user's channel [membership](https://www.pubnub.com/docs/chat/chat-sdk/learn/chat-entities/membership) with `delete()`.

##### Under the hood

`delete()` calls App Context API and the JavaScript SDK [setMemberships()](https://www.pubnub.com/docs/sdks/javascript/api-reference/objects#set-channel-memberships) method.

### Method signature

This method has the following signature:

```ts
membership.delete(): Promise<boolean>
```

#### Input

This method doesn't take any parameters.

#### Output

| Type | Description |
| --- | --- |
| `Promise<boolean>` | Returns `true` when the membership is successfully deleted. |

### Sample code

Delete the membership for the current user on the `support` channel.

```ts
const channel = await chat.getChannel("support")
const membership = await channel.join()

const result = await membership.delete()
console.log("Membership deleted:", result) // true
```

## Update

Update a user's channel [membership](https://www.pubnub.com/docs/chat/chat-sdk/learn/chat-entities/membership) information with `update()`.

##### Under the hood

`update()` calls App Context API and the JavaScript SDK [setMemberships()](https://www.pubnub.com/docs/sdks/javascript/api-reference/objects#set-channel-memberships) method.

### Method signature

This method takes the following parameters:

```ts
membership.update({
    status?: string,
    type?: string,
    custom?: ObjectCustom
}): Promise<Membership>
```

#### Input

| Parameter | Description |
| --- | --- |
| `status`Type: `string`Default: n/a | Current status of the membership, like `active` or `inactive`. |
| `type`Type: `string`Default: n/a | Type of the membership, used to categorize the user-channel relationship. |
| `custom`Type: `ObjectCustom`Default: n/a | Any custom properties or metadata associated with the channel-user membership. |

#### Output

| Type | Description |
| --- | --- |
| `Promise<Membership>` | Returned (modified) object containing all membership data. |

#### Errors

If you try to update a membership that doesn't exist, you will receive the `No such membership exists` error.

### Sample code

Assign the `premium-support` role to `support_agent_15` on the `high-priority-incidents` channel.

```ts
// reference the "support_agent_15" user
const user = await chat.getUser("support_agent_15")

// get the list of all user memberships and filter out the right channel
const { memberships } = await user.getMemberships({
    filter: "channel.id == 'high-priority-incidents'"
})

// add custom metadata to the user membership
await memberships[0].update({
        custom: {role: "premium-support"}
})
```