---
source_url: https://www.pubnub.com/docs/data-storage/metadata/manage-memberships
title: Set, get, and remove memberships
updated_at: 2026-09-30T07:20:08.000Z
---

# Set, get, and remove memberships

## Documentation index

To discover more PubNub resources:

1. Fetch [PubNub's llms.txt](https://www.pubnub.com/llms-full.txt) for a list of available pages in Markdown format.
2. Identify relevant URLs from that index.
3. Fetch the target pages.

Do not assume a path exists, always check the index first.

:::note Starting a new app? Use DataSync
[DataSync](https://www.pubnub.com/docs/data-storage/structured-data/overview.md) is the successor to App Context. It does everything App Context does for users, channels, and memberships, and adds typed schemas, partial updates with ETags, field-level access control, and per-class expiry. Refer to [How DataSync compares to App Context](https://www.pubnub.com/docs/data-storage/structured-data/overview.md) for a feature-by-feature comparison.
DataSync is currently available to new accounts and to accounts that are not actively using App Context. If your keysets already use App Context, keep using it for now. App Context remains fully supported and these pages stay accurate.
:::

This guide shows you how to manage a user's channel list from the user's side: add the user to channels, read their current list, and remove them from channels. App Context must be enabled on the keyset before you call it, and new keysets don't enable it by default. This is the [memberships direction](https://www.pubnub.com/docs/data-storage/metadata/overview.md#membership-connects-users-and-channels) of a membership, which starts from the user. To manage the same relationship from a channel's side instead, refer to [Set, get, and remove members](https://www.pubnub.com/docs/data-storage/metadata/manage-members.md).

:::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/architecture/core-concepts.md).
:::

Platform limits apply: up to 50,000 memberships per user and up to 5,000 members per channel.

A single set or remove call also caps how many memberships it can change at once. Refer to [App Context API limits](https://www.pubnub.com/docs/data-storage/metadata/api-limits.md) for the current maximum.

## Add a user to channels

Call `Set Memberships` with a list of channels to add a User ID to them, creating a membership record for each. If you omit the User ID, the call applies to the client's own User ID. Pass an object instead of a plain channel-name string to attach `custom` fields to that membership record.

### JavaScript

```javascript
// Using UUID from the config
try {
  const response = await pubnub.objects.setMemberships({
    channels: [
      'my-channel',
      { id: 'channel-with-status-type', custom: { hello: 'World' }, status: 'helloStatus', type: 'helloType' },
    ],
  });
  console.log('Set memberships response:', response);
} catch (error) {
  console.error(`Set memberships error: ${error}`);
}

// Using the passed in UUID
try {
  const response = await pubnub.objects.setMemberships({
    uuid: 'my-uuid',
    channels: [
      'my-channel',
      { id: 'channel-with-status-type', custom: { hello: 'World' }, status: 'helloStatus', type: 'helloType' },
    ],
    include: {
      // To include channel fields in response
      channelFields: true,
    },
  });
  console.log('Set memberships response:', response);
} catch (error) {
  console.error(`Set memberships error: ${error}`);
}
```

### Java

```java
final Map<String, Object> customMap = new HashMap<>();
customMap.putIfAbsent("membership_param1", "val1");
customMap.putIfAbsent("membership_param2", "val2");

PNChannelMembership pnChannelMembership = PNChannelMembership.builder("myChannelId")
        .custom(customMap)
        .status("inactive")
        .type("member")
        .build();

pubNub.setMemberships(Arrays.asList(pnChannelMembership))
        .include(MembershipInclude.builder()
                .includeTotalCount(true)
                .includeCustom(true)
                .includeChannel(true)
                .includeChannelCustom(true)
                .build())
        .async(result -> { /* check result */ });
```

### Kotlin

```kotlin
pubnub.setMemberships(
    channels = listOf(
        PNChannelMembership.Partial(
            channelId = "myChannel",
            custom = mapOf("owner" to "PubNub"),
            status = "active",
            type = "regular_membership"
        )
    ),
    include = MembershipInclude(
        includeCustom = true,
        includeStatus = true,
        includeType = true,
        includeChannel = true,
        includeChannelCustom = true,
        includeChannelType = true,
        includeChannelStatus = true,
        includeTotalCount = true
    ),
).async { result ->
    result.onFailure { exception ->
        // Handle error
    }.onSuccess { value ->
        // Handle successful method result
    }
}
```

### C#

```csharp
using PubnubApi;

// Configuration
PNConfiguration pnConfiguration = new PNConfiguration(new UserId("myUniqueUserId"))
{
    SubscribeKey = "demo",
    PublishKey = "demo",
    Secure = true
};

// Initialize PubNub
Pubnub pubnub = new Pubnub(pnConfiguration);
        
List<PNMembership> setMembershipChannelMetadataIdList =
[
    new PNMembership()
        { Channel = "my-channel", Custom = new Dictionary<string, object>() { { "item", "book" } } }
];

PNResult<PNMembershipsResult> setMembershipsResponse = await pubnub.SetMemberships()
    .Uuid("my-uuid")
    .Channels(setMembershipChannelMetadataIdList)
    .Include(new PNMembershipField[] { PNMembershipField.CUSTOM, PNMembershipField.CHANNEL, PNMembershipField.CHANNEL_CUSTOM })
    .IncludeCount(true)
    .ExecuteAsync();

PNMembershipsResult setMembershipsResult = setMembershipsResponse.Result;
PNStatus status = setMembershipsResponse.Status;
```

### Go

```go
// Replace with your package name (usually "main")
package pubnub_samples_test

import (
	"fmt"
	"time"

	pubnub "github.com/pubnub/go/v10"
)

// Example_setMemberships demonstrates adding a user to channels (memberships)
func Example_setMemberships() {
	config := pubnub.NewConfigWithUserId(pubnub.UserId("demo-user"))
	config.SubscribeKey = "demo"
	config.PublishKey = "demo"

	pn := pubnub.NewPubNub(config)

	// Add user to multiple channels with custom metadata
	response, status, err := pn.SetMemberships().
		UUID("member-user-789").       // User ID
		Set([]pubnub.PNMembershipsSet{ // Channels to join
			{
				Channel: pubnub.PNMembershipsChannel{ID: "channel-member-1"},
				Custom: map[string]interface{}{
					"role": "moderator",
				},
			},
			{
				Channel: pubnub.PNMembershipsChannel{ID: "channel-member-2"},
				Custom: map[string]interface{}{
					"role": "member",
				},
			},
		}).
		Execute()

	if err != nil {
		fmt.Printf("Error: %v\n", err)
		return
	}

	if status.StatusCode == 200 {
		fmt.Printf("User added to %d channel(s)\n", len(response.Data))
	}

	// Output:
	// User added to 2 channel(s)
}
```

### Swift

```swift
let membershipToSet = PubNubMembershipMetadataBase(
  userMetadataId: "my_user",
  channelMetadataId: "my_channel"
)

// Set channel memberships for a specific user identifier
pubnub.setMemberships(
  userId: membershipToSet.userMetadataId,
  channels: [membershipToSet]
) { result in
  switch result {
  case let .success(response):
    print("The channel memberships for the userId: \(response.memberships)")
    print("The next page used for pagination: \(String(describing: response.next))")
  case let .failure(error):
    print("Update Memberships request failed with error: \(error.localizedDescription)")
  }
}
```

### PHP

```php
$memberships = [
    new PNChannelMembership($sampleChannels[0]['id']),
    new PNChannelMembership($sampleChannels[1]['id'])
];

$setMembershipsResult = $pubnub->setMemberships()
    ->uuid($sampleUsers[0]['id'])
    ->memberships($memberships)
    ->sync();
assert(count($setMembershipsResult->getData()) >= 1);
```

### Unity

```csharp
using PubnubApi;
using PubnubApi.Unity;

// Configuration
PNConfiguration pnConfiguration = new PNConfiguration(new UserId("myUniqueUserId"))
{
    SubscribeKey = "demo",
    PublishKey = "demo",
    Secure = true
};

// Initialize PubNub
Pubnub pubnub = PubnubUnityUtils.NewUnityPubnub(pnConfiguration);

// If you're using Unity Editor setup you can get the Pubnub instance from PNManagerBehaviour
// For more details, see https://www.pubnub.com/docs/sdks/unity#configure-pubnub
/*
[SerializeField] private PNManagerBehaviour pubnubManager;
Pubnub pubnub = pubnubManager.pubnub;
*/

List<PNMembership> setMembershipChannelMetadataIdList =
 new() {
  new PNMembership()
   { Channel = "my-channel", Custom = new Dictionary<string, object>() { { "item", "book" } } }
 };

PNResult<PNMembershipsResult> setMembershipsResponse = await pubnub.SetMemberships()
    .Uuid("my-uuid")
    .Channels(setMembershipChannelMetadataIdList)
    .Include(new PNMembershipField[] { PNMembershipField.CUSTOM, PNMembershipField.CHANNEL, PNMembershipField.CHANNEL_CUSTOM })
    .IncludeCount(true)
    .ExecuteAsync();

PNMembershipsResult setMembershipsResult = setMembershipsResponse.Result;
PNStatus status = setMembershipsResponse.Status;
```

If [Access Manager](https://www.pubnub.com/docs/security/access-control/overview.md) is enabled, this call requires both a `join` permission grant on every channel and an `update` permission grant on the User ID, in the same token. This is more than [setting members from the channel's side](https://www.pubnub.com/docs/data-storage/metadata/manage-members.md#add-members-to-a-channel) needs, which requires only a channel-level grant. Refer to [App Context and access control](https://www.pubnub.com/docs/data-storage/metadata/overview.md#app-context-and-access-control) for the full permission model. On success, the call also fires the membership `set` [App Context event](https://www.pubnub.com/docs/data-storage/metadata/events.md) other subscribers receive.

Turning on **Enforce referential integrity for memberships** in the Admin Portal changes what this call allows. With it on, the User ID and every channel need their own metadata record before you can add the membership. Leaving it off lets you add a membership for a User ID or channel that has no metadata record yet.

## Get a user's memberships

Call `Get Memberships` to list a User ID's current channels. If you omit the User ID, the call applies to the client's own User ID. Pass `include.channelFields` to receive each channel's full metadata alongside the membership's own custom fields, instead of only the channel name.

### JavaScript

```javascript
// Using UUID from the config
try {
  const response = await pubnub.objects.getMemberships();
} catch (error) {
  console.error(`Get memberships error: ${error}`);
}

// Using the passed in UUID
try {
  const response = await pubnub.objects.getMemberships({
    uuid: 'myUuid',
    include: {
      channelFields: true,
    },
  });
} catch (error) {
  console.error(`Get memberships with channels fields included error: ${error}`);
}

// Get all memberships that are starred by the user
try {
  const response = await pubnub.objects.getMemberships({
    uuid: 'myUuid',
    filter: 'custom.starred == true',
  });
} catch (error) {
  console.error(`Get filtered memberships error: ${error}`);
}
```

### Java

```java
PNGetMembershipsResult pnGetMembershipsResult = pubNub.getMemberships()
        .userId("userId01")
        .limit(10)
        .include(MembershipInclude.builder()
                .includeCustom(true)
                .includeStatus(true)
                .includeType(true)
                .includeTotalCount(true)
                .includeChannel(true)
                .includeChannelCustom(true)
                .includeChannelType(true)
                .includeChannelStatus(true)
                .build())
        .sort(Arrays.asList(PNSortKey.asc(PNSortKey.Key.TYPE)))
        .sync();
```

### Kotlin

```kotlin
pubnub.getMemberships(
    include = MembershipInclude(
        includeCustom = true,
        includeStatus = true,
        includeType = true,
        includeTotalCount = true,
        includeChannel = true,
        includeChannelCustom = true,
        includeChannelType = true,
        includeChannelStatus = true
    ),
    sort = listOf(PNSortKey.PNAsc(PNMembershipKey.CHANNEL_ID))
).async { result ->
    result.onFailure { exception ->
        // Handle error
    }.onSuccess { value ->
        // Handle successful method result
    }
}
```

### C#

```csharp
using PubnubApi;

// Configuration
PNConfiguration pnConfiguration = new PNConfiguration(new UserId("myUniqueUserId"))
{
    SubscribeKey = "demo",
    PublishKey = "demo",
    Secure = true
};

// Initialize PubNub
Pubnub pubnub = new Pubnub(pnConfiguration);
        
PNResult<PNMembershipsResult> getMembershipsResponse = await pubnub.GetMemberships()
    .Uuid("my-uuid")
    .Include(new PNMembershipField[] { PNMembershipField.CUSTOM, PNMembershipField.CHANNEL, PNMembershipField.CHANNEL_CUSTOM })
    .IncludeCount(true)
    .Page(new PNPageObject() { Next = "", Prev = "" })
    .ExecuteAsync();

PNMembershipsResult getMembeshipsResult = getMembershipsResponse.Result;
PNStatus status = getMembershipsResponse.Status;
```

### Go

```go
// Replace with your package name (usually "main")
package pubnub_samples_test

import (
	"fmt"
	"time"

	pubnub "github.com/pubnub/go/v10"
)

// Example_getMembershipsWithAllIncludes demonstrates getting memberships with all include options
func Example_getMembershipsWithAllIncludes() {
	config := pubnub.NewConfigWithUserId(pubnub.UserId("demo-user"))
	config.SubscribeKey = "demo"
	config.PublishKey = "demo"

	pn := pubnub.NewPubNub(config)

	// Create user and channel with all fields
	pn.SetUUIDMetadata().
		UUID("user-full-membership").
		Name("Full Member").
		Status("active").
		Type("user").
		Execute()

	pn.SetChannelMetadata().
		Channel("channel-full-membership").
		Name("Full Channel").
		Custom(map[string]interface{}{"category": "tech"}).
		Status("active").
		Type("public").
		Execute()

	// Add user to channel with custom membership data
	pn.SetMemberships().
		UUID("user-full-membership").
		Set([]pubnub.PNMembershipsSet{
			{
				Channel: pubnub.PNMembershipsChannel{ID: "channel-full-membership"},
				Custom: map[string]interface{}{
					"role": "moderator",
				},
				Status: "active",
				Type:   "membership",
			},
		}).
		Execute()

	// Small delay to ensure metadata is persisted before retrieval
	time.Sleep(2 * time.Second)

	// Get memberships with all include options
	response, status, err := pn.GetMemberships().
		UUID("user-full-membership").
		Include([]pubnub.PNMembershipsInclude{
			pubnub.PNMembershipsIncludeCustom,        // Include membership custom data
			pubnub.PNMembershipsIncludeChannel,       // Include channel details
			pubnub.PNMembershipsIncludeChannelCustom, // Include channel custom data
			pubnub.PNMembershipsIncludeChannelStatus, // Include channel status
			pubnub.PNMembershipsIncludeChannelType,   // Include channel type
			pubnub.PNMembershipsIncludeStatus,        // Include membership status
			pubnub.PNMembershipsIncludeType,          // Include membership type
		}).
		Execute()

	if err != nil {
		fmt.Printf("Error: %v\n", err)
		return
	}

	if status.StatusCode == 200 && len(response.Data) > 0 {
		membership := response.Data[0]
		fmt.Printf("Channel: %s\n", membership.Channel.Name)
		fmt.Printf("Channel Status: %s\n", membership.Channel.Status)
		fmt.Printf("Membership Status: %s\n", membership.Status)
		if role, ok := membership.Custom["role"].(string); ok {
			fmt.Printf("Role: %s\n", role)
		}
	}

	// Output:
	// Channel: Full Channel
	// Channel Status: active
	// Membership Status: active
	// Role: moderator
}
```

### Swift

```swift
// Retrieve channel memberships for a specific user identifier
pubnub.fetchMemberships(userId: "some-user-id") { result in
  switch result {
  case let .success(response):
    print("The channel memberships for the userId: \(response.memberships)")
    print("The next page used for pagination: \(String(describing: response.next))")
  case let .failure(error):
    print("Fetch Memberships request failed with error: \(error.localizedDescription)")
  }
}
```

### PHP

```php
$membershipIncludes = new PNMembershipIncludes();
$membershipIncludes->custom()->channel()->channelCustom();

$getMembershipsResult = $pubnub->getMemberships()
    ->uuid($sampleUsers[0]['id'])
    ->include($membershipIncludes)
    ->sync();
assert(count($getMembershipsResult->getData()) >= 1);
```

### Unity

```csharp
using PubnubApi;
using PubnubApi.Unity;

// Configuration
PNConfiguration pnConfiguration = new PNConfiguration(new UserId("myUniqueUserId"))
{
    SubscribeKey = "demo",
    PublishKey = "demo",
    Secure = true
};

// Initialize PubNub
Pubnub pubnub = PubnubUnityUtils.NewUnityPubnub(pnConfiguration);

// If you're using Unity Editor setup you can get the Pubnub instance from PNManagerBehaviour
// For more details, see https://www.pubnub.com/docs/sdks/unity#configure-pubnub
/*
[SerializeField] private PNManagerBehaviour pubnubManager;
Pubnub pubnub = pubnubManager.pubnub;
*/

PNResult<PNMembershipsResult> getMembershipsResponse = await pubnub.GetMemberships()
    .Uuid("my-uuid")
    .Include(new PNMembershipField[] { PNMembershipField.CUSTOM, PNMembershipField.CHANNEL, PNMembershipField.CHANNEL_CUSTOM })
    .IncludeCount(true)
    .Page(new PNPageObject() { Next = "", Prev = "" })
    .ExecuteAsync();

PNMembershipsResult getMembeshipsResult = getMembershipsResponse.Result;
PNStatus status = getMembershipsResponse.Status;
```

If Access Manager is enabled, this call requires only a `get` permission grant on the User ID. This call returns a list, so it accepts the same `filter`, `sort`, and `page` parameters as [Get metadata for all channels](https://www.pubnub.com/docs/data-storage/metadata/get-metadata-for-all-channels.md#page-through-the-list). Refer to [App Context filtering](https://www.pubnub.com/docs/data-storage/metadata/filtering.md) for the `channel.*` fields a memberships call accepts.

Every paginated App Context call takes the same three parameters. `limit` caps how many records come back in one call. It defaults to 100, and 100 is also the maximum. `page.next` and `page.prev` are opaque cursor strings copied from a previous response: pass the one you want to continue from, and PubNub returns the adjacent page in that direction. If you supply both, PubNub uses `next` and ignores `prev`.

## Remove a user from channels

Call `Remove Memberships` with a list of channels to remove the User ID's membership to them.

### JavaScript

```javascript
// Using UUID from the config
try {
  const response = await pubnub.objects.removeMemberships({
    channels: ['ch-1', 'ch-2'],
  });
} catch (error) {
  console.error(`Remove memberships error: ${error}`);
}

// Using the passed in UUID
try {
  const response = await pubnub.objects.removeMemberships({
    uuid: 'myUuid',
    channels: ['ch-1', 'ch-2'],
  });
} catch (error) {
  console.error(`Remove memberships for given uuids error: ${error}`);
}
```

### Java

```java
final Map<String, Object> customMap = new HashMap<>();
customMap.putIfAbsent("membership_param1", "val1");
customMap.putIfAbsent("membership_param2", "val2");

PNRemoveMembershipResult pnRemoveMembershipResult = pubNub.removeMemberships(Arrays.asList("myChannelName"))
        .include(MembershipInclude.builder()
                .includeTotalCount(true)
                .includeCustom(true)
                .includeChannel(true)
                .includeType(true)
                .includeStatus(true)
                .build())
        .sync();
```

### Kotlin

```kotlin
pubnub.removeMemberships(listOf("myChannel"))
    .async { result ->
        result.onFailure { exception ->
            // Handle error
        }.onSuccess { value ->
            // Handle successful method result
        }
    }
```

### C#

```csharp
using PubnubApi;

// Configuration
PNConfiguration pnConfiguration = new PNConfiguration(new UserId("myUniqueUserId"))
{
    SubscribeKey = "demo",
    PublishKey = "demo",
    Secure = true
};

// Initialize PubNub
Pubnub pubnub = new Pubnub(pnConfiguration);
        
List<string> removeMembershipList =
[
    "my-channel",
    "your-channel"
];

PNResult<PNMembershipsResult> removeMembershipsResponse = await pubnub.RemoveMemberships()
    .Uuid("uuid")
    .Channels(removeMembershipList)
    .Include(new PNMembershipField[] { PNMembershipField.CUSTOM, PNMembershipField.CHANNEL, PNMembershipField.CHANNEL_CUSTOM })
    .IncludeCount(true)
    .ExecuteAsync();

PNMembershipsResult removeMembershipsResult = removeMembershipsResponse.Result;
PNStatus status2 = removeMembershipsResponse.Status;
```

### Go

```go
// Replace with your package name (usually "main")
package pubnub_samples_test

import (
	"fmt"
	"time"

	pubnub "github.com/pubnub/go/v10"
)

// Example_removeMemberships demonstrates removing a user from channels (removing memberships)
func Example_removeMemberships() {
	config := pubnub.NewConfigWithUserId(pubnub.UserId("demo-user"))
	config.SubscribeKey = "demo"
	config.PublishKey = "demo"

	pn := pubnub.NewPubNub(config)

	// Remove user from specific channels
	response, status, err := pn.RemoveMemberships().
		UUID("remove-user-888").             // User ID
		Remove([]pubnub.PNMembershipsRemove{ // Channels to remove from
			{Channel: pubnub.PNMembershipsChannel{ID: "temp-channel-1"}},
		}).
		Execute()

	if err != nil {
		fmt.Printf("Error: %v\n", err)
		return
	}

	if status.StatusCode == 200 {
		fmt.Printf("Removed from %d channel(s)\n", len(response.Data))
	}

	// Output:
	// Removed from 1 channel(s)
}
```

### Swift

```swift
let membershipToRemove = PubNubMembershipMetadataBase(
  userMetadataId: "my_user",
  channelMetadataId: "my_channel"
)

// Remove channel memberships for a specific user identifier
pubnub.removeMemberships(
  userId: membershipToRemove.userMetadataId,
  channels: [membershipToRemove]
) { result in
  switch result {
  case let .success(response):
    print("The channel memberships for the userId: \(response.memberships)")
    print("The next page used for pagination: \(String(describing: response.next))")
  case let .failure(error):
    print("Update Memberships request failed with error: \(error.localizedDescription)")
  }
}
```

### PHP

```php
$removeMembershipsList = [new PNChannelMembership($sampleChannels[0]['id'])];

$removeMembershipsResult = $pubnub->removeMemberships()
    ->uuid($sampleUsers[0]['id'])
    ->memberships($removeMembershipsList)
    ->sync();
assert($removeMembershipsResult);
```

### Unity

```csharp
using PubnubApi;
using PubnubApi.Unity;

// Configuration
PNConfiguration pnConfiguration = new PNConfiguration(new UserId("myUniqueUserId"))
{
    SubscribeKey = "demo",
    PublishKey = "demo",
    Secure = true
};

// Initialize PubNub
Pubnub pubnub = PubnubUnityUtils.NewUnityPubnub(pnConfiguration);

// If you're using Unity Editor setup you can get the Pubnub instance from PNManagerBehaviour
// For more details, see https://www.pubnub.com/docs/sdks/unity#configure-pubnub
/*
[SerializeField] private PNManagerBehaviour pubnubManager;
Pubnub pubnub = pubnubManager.pubnub;
*/

List<string> removeMembershipList =
 new() {
  "my-channel",
  "your-channel"
 };

PNResult<PNMembershipsResult> removeMembershipsResponse = await pubnub.RemoveMemberships()
    .Uuid("uuid")
    .Channels(removeMembershipList)
    .Include(new PNMembershipField[] { PNMembershipField.CUSTOM, PNMembershipField.CHANNEL, PNMembershipField.CHANNEL_CUSTOM })
    .IncludeCount(true)
    .ExecuteAsync();

PNMembershipsResult removeMembershipsResult = removeMembershipsResponse.Result;
PNStatus status2 = removeMembershipsResponse.Status;
```

If Access Manager is enabled, this call requires both a `join` permission grant on every channel and an `update` permission grant on the User ID, in the same token. That's the same pairing [Add a user to channels](#add-a-user-to-channels) needs. On success, the call also fires the membership `delete` [App Context event](https://www.pubnub.com/docs/data-storage/metadata/events.md) other subscribers receive. Removing a membership deletes the membership record. It doesn't delete the user's or the channel's own metadata.

## Manage a user's memberships without code

[BizOps Workspace](https://www.pubnub.com/docs/data-storage/metadata/overview.md)'s **User Management** module manages the same channel list from the Admin Portal, with no SDK call required:

* [Add membership](https://www.pubnub.com/docs/data-storage/metadata/manage-user-metadata.md). Assign the user to one or more channels.
* [Update membership](https://www.pubnub.com/docs/data-storage/metadata/manage-user-metadata.md). Change a membership's custom fields.
* [Delete membership](https://www.pubnub.com/docs/data-storage/metadata/manage-user-metadata.md). Remove one membership, or several at once.

A membership you create, edit, or delete in BizOps Workspace is the same record your SDK calls read and write. Changes in either place are immediately visible in the other, and from either direction: a channel you add here also appears when you [get that channel's members](https://www.pubnub.com/docs/data-storage/metadata/manage-members.md#get-a-channels-members).

## Related tasks

* [App Context](https://www.pubnub.com/docs/data-storage/metadata/overview.md). The two directions of a membership and how they relate to [Presence](https://www.pubnub.com/docs/presence/overview.md).
* [Set, get, and remove members](https://www.pubnub.com/docs/data-storage/metadata/manage-members.md). Manage the same relationship from a channel's side.
* [Set, get, and remove user metadata](https://www.pubnub.com/docs/data-storage/metadata/manage-user-metadata.md). Give this user their own name, email, and custom fields.
* [App Context filtering](https://www.pubnub.com/docs/data-storage/metadata/filtering.md). Filter a memberships list by `channel.*` fields.
* [App Context API limits](https://www.pubnub.com/docs/data-storage/metadata/api-limits.md). Memberships per user and memberships per write.

Last updated at: 2026-09-30T07:20:08.000Z
