---
source_url: https://www.pubnub.com/docs/general/metadata/membership-metadata
title: Membership Metadata
updated_at: 2026-06-19T11:35:57.511Z
---

> 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


# Membership Metadata

:::tip Manage membership with BizOps Workspace
You can manage user-channel membership using [BizOps Workspace](https://www.pubnub.com/docs/bizops-workspace/user-management#manage-membership) on Admin Portal. It lets you add, update, or remove users from channels on your apps' keysets.
:::

Besides [users](https://www.pubnub.com/docs/general/metadata/users-metadata) and [channels](https://www.pubnub.com/docs/general/channels/overview), you can store the relationship between them as *memberships*. When you add a user to a channel, the user becomes a member of that channel.

:::note Memberships and subscriptions
Adding channel memberships is not the same as subscribing to a channel. Memberships manage relationships and metadata. To receive messages, [subscribe](https://www.pubnub.com/docs/general/channels/subscribe).
:::

###### Complement membership with presence for live status

Membership records which channels a user belongs to as a persistent relationship. [Presence](https://www.pubnub.com/docs/general/presence/overview) tracks whether those users are currently online as an ephemeral signal. Membership alone cannot show who is active right now, and presence alone cannot render a complete member list when users are offline. Together, they answer "who belongs here" and "who is here now." For details on receiving membership change events through the same listener used for presence events, see [Receive Messages](https://www.pubnub.com/docs/general/messages/receive#add-an-event-handler).

You don’t need to persist membership information to send or receive messages. Persisting memberships helps when you want to track members of a channel, show a user’s channel list, or let a user join or leave channels.

When a user joins channels in your app, the user changes their memberships. Membership methods take the current client’s User ID by default, unless you explicitly specify another user’s ID.

:::note User ID / UUID
User ID is also referred to as **UUID/uuid** in some APIs and server responses but **holds the value** of the **userId** parameter you [set during initialization](https://www.pubnub.com/docs/general/setup/users-and-devices#set-the-user-id).
:::

PubNub emits events to notify clients when users are added to or removed from a channel. You can enable this feature using the [Admin Portal](https://admin.pubnub.com). In the App Context section, select or clear the appropriate checkboxes to enable or disable sending particular events.

:::note Illuminate & sensitive data
You can capture and track your App Context data in [Illuminate](https://www.pubnub.com/docs/illuminate/basics) for real-time decisioning and analytics. Illuminate captures all data you define with JSON paths and [map](https://www.pubnub.com/docs/illuminate/business-objects/basics#data-mapping) when creating measures and dimensions for the Business Objects. To protect privacy, avoid placing any PII (email address, profile URL, or IP address) in the `custom` fields of your App Context mappings.
:::

The App Context service allows you to perform the following operations on memberships:

## Channel memberships

| Operation | Description |
| --- | --- |
| [Set channel memberships](#set-channel-memberships) | Adds the current user to one or more channels or updates the custom metadata for the existing memberships. This operation creates a membership for the user to the specified channels. |
| [Remove channel memberships](#remove-channel-memberships) | Removes the current user from one or more channels. This operation removes a membership for the user from the specified channels. |
| [Get channel memberships](#get-channel-memberships) | Returns a list of channel memberships for the current user. |

### Set channel memberships

You can add a single user to one or more channels, creating memberships, or update custom metadata on existing memberships. Provide custom metadata as key-value pairs.

:::tip API limits
To learn about the maximum length of parameters used to set channel membership metadata, refer to [REST API docs](https://www.pubnub.com/docs/sdks/rest-api/set-membership-metadata).
:::

The example below adds the current user to the channels `my_channel` and `my_channel_2` and adds the `starred` metadata to the newly created `my_channel_2` membership.

###### JavaScript

```javascript
pubnub.objects.setMemberships({
    channels: [
    "channel-1",
    {id: "channel-2", custom: {starred: true}
    }]
});
```

###### Objective-C

```objectivec
NSArray<NSDictionary *> *channels = @[
  @{ @"channel": @"my_channel" },
  @{ @"channel": @"my_channel_2", @"custom": @{ @"starred": @YES } }
];

self.client.objects().setMemberships()
    .uuid(@"uuid")
    .channels(channels)
    .includeCount(YES)
    .limit(40)
    .includeFields(NMembershipCustomField | PNMembershipChannelField)
    .performWithCompletion(^(PNManageMembershipsStatus *status) {
        if (!status.isError) {
            /**
             * UUID's memberships successfully set.
             * Result object has following information:
             *   status.data.memberships - List of UUID's existing memberships.
             *   status.data.next - 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.
             *   status.data.prev - 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.
             *   status.data.totalCount - Total number of UUID's memberships.
             */
        } else {
            /**
             * Handle UUID's memberships set error. Check 'category' property to find out possible
             * issue because of which request did fail.
             *
             * Request can be resent using: [status retry]
             */
        }
    });
```

###### Java

```java
Map<String, Object> custom = new HashMap<>();
custom.put("starred", true);
pubnub.setMemberships()
    .channelMemberships(Arrays.asList(PNChannelMembership.channel("my_channel"), PNChannelMembership.channelWithCustom("my_channel_2", custom)))
    .async(result -> { /* check result */ });
```

###### C#

```csharp
List<PNMembership> setMembershipChannelMetadataIdList = new List<PNMembership>();
if (!string.IsNullOrEmpty(seMembershipChannelMetaId))
{
    setMembershipChannelMetadataIdList.Add(new PNMembership() { Channel = "my_channel" });
    setMembershipChannelMetadataIdList.Add(new PNMembership() { Channel = "my_channel_2", Custom = new Dictionary<string, object>() { { "starred", true } } });
}

PNResult<PNMembershipsResult> setMembershipsResponse = await pubnub.SetMemberships()
    .Uuid("my-user-id")
    .Channels(setMembershipChannelMetadataIdList)
    .Include(new PNMembershipField[] { PNMembershipField.CUSTOM, PNMembershipField.CHANNEL, PNMembershipField.CHANNEL_CUSTOM })
    .IncludeCount(true)
    .ExecuteAsync();
PNMembershipsResult setMembershipsResult = setMembershipsResponse.Result;
PNStatus status = setMembershipsResponse.Status;
```

On success, the SDK returns channel data for the specified channels with HTTP 200. It also emits the `objects` -> `membership` -> `set` event that other clients can consume.

:::note Referential integrity
Enabling [referential integrity](https://www.pubnub.com/docs/general/metadata/basics#configuration) on your app’s keyset in the Admin Portal ensures that memberships can only be created for existing users and channels, and automatically deletes memberships when their associated user or channel is deleted.
If it’s not enabled, memberships can be created even for the non-existent user and channel entities, while deleting a user or channel entity does not automatically delete any associated membership objects.
:::

### Remove channel memberships

You can remove a single user from one or more channels, deleting the membership relationship. The example below removes the current user from the channel `my_channel_2`.

#### JavaScript

```javascript
pubnub.objects.removeMemberships({
  channels: ["my_channel_2"]
});
```

#### Objective-C

```objectivec
self.client.objects().removeMemberships()
    .uuid(@"uuid")
    .channels(@"my_channel_2")
    .includeFields(PNMembershipCustomField | PNMembershipChannelField)
    .performWithCompletion(^(PNManageMembershipsStatus *status) {
        if (!status.isError) {
            /**
             * UUID's memberships successfully removed.
             * Result object has following information:
             *   status.data.memberships - List of UUID's existing memberships.
             *   status.data.next - 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.
             *   status.data.prev - 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.
             *   status.data.totalCount - Total number of UUID's memberships.
             */
        } else {
            /**
             * Handle UUID's memberships remove error. Check 'category' property to find out possible
             * issue because of which request did fail.
             *
             * Request can be resent using: [status retry]
             */
        }
    });
```

#### Java

```java
pubnub.removeMemberships()
    .channelMemberships(Collections.singletonList(PNChannelMembership.channel("my_channel_2")))
    .async(result -> { /* check result */ });
```

#### C#

```csharp
List<string> removeMembershipList = new List<string>();
if (!string.IsNullOrEmpty(removeMembershipChannelMetaId))
{
    removeMembershipList.Add("my_channel_2");
}

PNResult<PNMembershipsResult> removeMembershipsResponse = await pubnub.RemoveMemberships()
    .Uuid("user_Id")
    .Channels(removeMembershipList)
    .Include(new PNMembershipField[] { PNMembershipField.CUSTOM, PNMembershipField.CHANNEL, PNMembershipField.CHANNEL_CUSTOM })
    .IncludeCount(true)
    .ExecuteAsync();
PNMembershipsResult removeMembershipsResult = removeMembershipsResponse.Result;
PNStatus status2 = removeMembershipsResponse.Status;
```

On completion, the SDK emits the `objects` -> `membership` -> `delete` event so it can be consumed for other clients (users). Refer to the [Receive Messages](https://www.pubnub.com/docs/general/messages/receive) to learn more.

### Get channel memberships

You can retrieve a list of channel memberships for the current user. The following example returns all memberships for the current user.

#### JavaScript

```javascript
pubnub.objects.getMemberships();
```

#### Objective-C

```objectivec
self.client.objects().memberships()
    .uuid(@"uuid")
    .includeFields(PNMembershipCustomField | PNMembershipChannelField)
    .performWithCompletion(^(PNFetchMembershipsResult *result, PNErrorStatus *status) {
        if (!status.isError) {
            /**
             * UUID's memberships successfully fetched.
             * Result object has following information:
             *   result.data.memberships - List of UUID's memberships.
             *   result.data.next - 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.
             *   result.data.prev - 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.
             *   result.data.totalCount - Total number of UUID's memberships.
             */
        } else {
            /**
             * Handle UUID's memberships fetch error. Check 'category' property to find out possible
             * issue because of which request did fail.
             *
             * Request can be resent using: [status retry]
             */
        }
    });
```

#### Java

```java
pubnub.getMemberships()
    .async(result -> { /* check result */ });
```

#### C#

```csharp
PNResult<PNGetMembershipsResult> getMembershipsResponse = await pubnub.GetMemberships()
    .Uuid("my-user-id")
    .Include(new PNMembershipField[] { PNMembershipField.CUSTOM, PNMembershipField.CHANNEL, PNMembershipField.CHANNEL_CUSTOM })
    .IncludeCount(true)
    .Page(new PNPageObject() { Next = "", Prev = "" })
    .ExecuteAsync();
PNGetMembershipsResult getMembershipsResult = getMembershipsResponse.Result;
PNStatus status = getMembershipsResponse.Status;
```

On success, the SDK returns all channels for which the user is a member with HTTP 200.

## Channel member

Apart from [users](https://www.pubnub.com/docs/general/metadata/users-metadata) and [channels](https://www.pubnub.com/docs/general/channels/overview), PubNub also allows you to store the relations between them called *memberships*. Each user that you add to a channel becomes a *member* of that specific channel.

The following section describes how to add channel memberships from an external user's perspective, that is, when another user wants to add/remove members to a channel. This is the case when a user already is a member (or a moderator) of a specific channel and wishes to add/remove users to that channel. Setting *members* in a channel is also a more efficient way of handling bulk operations than setting *memberships*.

PubNub emits events to notify clients when users are added to or removed from a channel. You can enable this feature using the [Admin Portal](https://admin.pubnub.com). In the **App Context** section, select or clear the appropriate checkboxes to enable or disable sending particular events.

The App Context service allows you to perform the following operations on channel members:

:::note User ID / UUID
User ID is also referred to as **UUID/uuid** in some APIs and server responses but **holds the value** of the **userId** parameter you [set during initialization](https://www.pubnub.com/docs/general/setup/users-and-devices#set-the-user-id).
:::

| Operation | Description |
| --- | --- |
| [Set members in channel](#set-members-in-channel) | Adds one or more users to a single channel. This operation creates memberships for these users to the specified channel. |
| [Remove members from channel](#remove-members-from-channel) | Removes one or more users from a single channel. This operation removes memberships for these users from the specified channel. |
| [Get members in channel](#get-members-in-channel) | Returns a list of users on a single channel. The list includes user's custom metadata if available and includes only User IDs for users who do not have custom metadata. |

### Set members in channel

You can add one or more users to a single channel (effectively creating a membership relation between the users and the channel) or update the custom metadata of one or more users that are existing members of a single channel. To update custom metadata of existing memberships, provide the desired information as key/value pairs.

:::tip API limits
To learn about the maximum length of parameters used to set channel members metadata, refer to [REST API docs](https://www.pubnub.com/docs/sdks/rest-api/set-channel-members-metadata).
:::

The code below adds the membership to `my_channel` for the users `johndoe_1` and `janedoe_1`. Additionally, custom metadata `trialPeriod` is also added to the newly created membership for `janedoe_1`.

###### JavaScript

```javascript
pubnub.objects.setChannelMembers({
  channel: "my_channel",
  uuids: [
    'johndoe_1',
    { id: 'janedoe_1', custom: { trialPeriod: false } },
  ],
});
```

###### Objective-C

```objectivec
NSArray<NSDictionary *> *uuids = @[
  @{ @"uuid": @"johndoe_1" }
  @{ @"uuid": @"janedoe_1", @"custom": @{ @"trialPeriod": @YES } }
];

self.client.objects().setChannelMembers(@"my_channel")
    .uuids(uuids)
    .includeFields(PNChannelMemberCustomField | PNChannelMemberUserField)
    .performWithCompletion(^(PNManageChannelMembersStatus *status) {
        if (!status.isError) {
            /**
             * Channel's members successfully set.
             * Result object has following information:
             *   result.data.members - List of existing channel's members.
             *   result.data.next - 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.
             *   result.data.prev - 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.
             *   result.data.totalCount - Total number of channel's members.
             */
        } else {
            /**
             * Handle channel's members set error. Check 'category' property to find out possible
             * issue because of which request did fail.
             *
             * Request can be resent using: [status retry]
             */
        }
    });
```

###### Java

```java
Map<String, Object> custom = new HashMap<>();
custom.put("trialPeriod", true);
pubnub.setChannelMembers()
    .channel("my_channel")
    .uuids(Arrays.asList(PNUUID.uuid("johndoe_1"), PNUUID.uuidWithCustom("janedoe_1", custom)))
    .async(result -> { /* check result */ });
```

###### C#

```csharp
List<PNChannelMember> setMemberChannelList = new List<PNChannelMember>();
if (!string.IsNullOrEmpty(setMemberChUuid))
{
    setMemberChannelList.Add(new PNChannelMember() { Uuid = "johndoe_1" } );
    setMemberChannelList.Add(new PNChannelMember() { Uuid = "janedoe_1", Custom = new Dictionary<string, object>() { { "trialPeriod", false } } });
}
PNResult<PNChannelMembersResult> setChannelMembersResponse = await pubnub.SetChannelMembers()
    .Channel(setmemberChMetadataId)
    .Uuids(setMemberChannelList)
    .Include(new PNChannelMemberField[] { PNChannelMemberField.CUSTOM, PNChannelMemberField.UUID, PNChannelMemberField.UUID_CUSTOM })
    .IncludeCount(true)
    .ExecuteAsync();
PNChannelMembersResult setChannelMembersResult = setChannelMembersResponse.Result;
PNStatus status2 = setChannelMembersResponse.Status;
```

On success, the SDK will return the channel data of the specified channel with HTTP 200. It will also fire the `objects` -> `membership` -> `set` event so it can be consumed for other clients (users). Refer to the [Receive Messages](https://www.pubnub.com/docs/general/messages/receive) to learn more.

:::note Referential integrity
Enabling [referential integrity](https://www.pubnub.com/docs/general/metadata/basics#configuration) on your app’s keyset in the Admin Portal ensures that memberships can only be created for existing users and channels, and automatically deletes memberships when their associated user or channel is deleted.
If it’s not enabled, memberships can be created even for the non-existent user and channel entities, while deleting a user or channel entity does not automatically delete any associated membership objects.
:::

### Remove members from channel

You can remove one or more users from a single channel by providing the channel ID and a list of users. The following example deletes the membership to `my_channel_2` for the users `johndoe_1` and `janedoe_1`.

#### JavaScript

```javascript
pubnub.objects.removeChannelMembers({
        channel: "my_channel_2",
        uuids: ["johndoe_1", "janedoe_1"]
    }
);
```

#### Objective-C

```objectivec
self.client.objects().removeChannelMembers(@"my_channel_2")
    .uuids(@[@"johndoe_1", @"janedoe_1"])
    .includeFields(PNChannelMemberCustomField | PNChannelMemberUserField)
    .performWithCompletion(^(PNManageChannelMembersStatus *status) {
        if (!status.isError) {
            /**
             * Channel's members successfully removed.
             * Result object has following information:
             *   result.data.members - List of channel's existing members.
             *   result.data.next - 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.
             *   result.data.prev - 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.
             *   result.data.totalCount - Total number of channel's members.
             */
        } else {
            /**
             * Handle channel's members remove error. Check 'category' property to find out possible
             * issue because of which request did fail.
             *
             * Request can be resent using: [status retry]
             */
        }
    });
```

#### Java

```java
pubnub.removeChannelMembers()
    .channel("my_channel_2")
    .uuids(Arrays.asList(PNUUID.uuid("johndoe_1"), PNUUID.uuid("janedoe_1")))
    .async(result -> { /* check result */ });
```

#### C#

```csharp
List<string> removeChannelMemberList = new List<string>();
removeChannelMemberList.Add("johndoe_1");
removeChannelMemberList.Add("janedoe_1");

PNResult<PNChannelMembersResult> removeChannelMembersResponse = await pubnub.RemoveChannelMembers()
    .Channel("my_channel_2")
    .Uuids(removeChannelMemberList)
    .Include(new PNChannelMemberField[] { PNChannelMemberField.CUSTOM, PNChannelMemberField.UUID, PNChannelMemberField.UUID_CUSTOM })
    .IncludeCount(true)
    .ExecuteAsync();
PNChannelMembersResult removeChannelMembersResult = removeChannelMembersResponse.Result;
PNStatus status = removeChannelMembersResponse.Status;
```

On completion, the SDK emits `objects` -> `membership` -> `delete`.

### Get members in channel

You can retrieve a list of members of a single channel by providing its ID. The following example returns the members of the channel `my_channel`.

#### JavaScript

```javascript
pubnub.objects.getChannelMembers({
    channel: "my_channel"
});
```

#### Objective-C

```objectivec
self.client.objects().channelMembers(@"my_channel")
    .includeFields(PNChannelMemberCustomField | PNChannelMemberUUIDField)
    .performWithCompletion(^(PNFetchChannelMembersResult *result, PNErrorStatus *status) {
        if (!status.isError) {
            /**
             * Channel's members successfully fetched.
             * Result object has following information:
             *   result.data.members - List of channel's members.
             *   result.data.next - 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.
             *   result.data.prev - 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.
             *   result.data.totalCount - Total number of channel's members.
             */
        } else {
            /**
             * Handle channel's members fetch error. Check 'category' property to find out possible
             * issue because of which request did fail.
             *
             * Request can be resent using: [status retry]
             */
        }
    });
```

#### Java

```java
pubnub.getChannelMembers()
    .channel("my_channel")
    .async(result -> { /* check result */ });
```

#### C#

```csharp
PNResult<PNChannelMembersResult> getChannelMembersResponse = await pubnub.GetChannelMembers()
    .Channel("my_channel")
    .Include(new PNChannelMemberField[] { PNChannelMemberField.CUSTOM, PNChannelMemberField.UUID, PNChannelMemberField.UUID_CUSTOM })
    .IncludeCount(true)
    .ExecuteAsync();
PNChannelMembersResult getChannelMembersResult = getChannelMembersResponse.Result;
PNStatus status2 = getChannelMembersResponse.Status;
```

On success, the PubNub SDK returns the UUIDs of all the users, and the associated channel metadata for that channel, along with HTTP 200.

###### Secure membership operations with Access Manager

When [Access Manager](https://www.pubnub.com/docs/general/security/access-control) is enabled, setting or removing memberships requires both channel-level and UUID-level permissions in the same token. Getting a user's memberships requires UUID-level `Get` permission. See the [App Context permissions table](https://www.pubnub.com/docs/general/security/access-control#app-context) for the full mapping of operations to required grants.

###### Automate workflows when memberships change

[Events & Actions](https://www.pubnub.com/docs/serverless/events-and-actions/events#memberships) can trigger custom actions whenever a membership is created, updated, or deleted, letting you react to membership changes without polling. [Illuminate Decisions](https://www.pubnub.com/docs/illuminate/decisions/basics) can also execute an "Update Membership" action as part of a rule, enabling automated membership modifications driven by real-time analytics conditions.

## Terms in this document

* **User** - An individual or entity that interacts with a system, application, or service. In PubNub, a user typically refers to someone who sends or receives messages through the platform, identified by a unique user ID or username.
* **User ID** - UTF-8 encoded, unique string of up to 92 characters used to identify a single client (end user, device, or server) that connects to PubNub.
