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

# Set, get, and remove channel metadata

## 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 give a single [channel](https://www.pubnub.com/docs/architecture/core-concepts.md#channel) its [App Context](https://www.pubnub.com/docs/data-storage/metadata/overview.md) metadata: set its built-in and custom fields, read them back, and remove the whole record. App Context must be enabled on the keyset before you call it, and new keysets don't enable it by default. To read or list every channel's metadata at once instead of one channel, refer to [Get metadata for all channels](https://www.pubnub.com/docs/data-storage/metadata/get-metadata-for-all-channels.md).

## Set channel metadata

Call `Set Channel Metadata` with the channel's name and a `data` object holding the built-in `name` and `description` fields plus any `custom` fields your application needs. The call creates the record if it doesn't exist yet, or updates it if it does.

:::warning Unsupported partial updates of custom metadata
The value of the custom metadata parameter sent in this method always overwrites the value stored on PubNub servers. If you want to add new custom data to an existing one, you must:
1. Get the existing metadata and store it locally.
2. Append the new custom metadata to the existing one.
3. Set the entire updated custom object.
:::

### JavaScript

```javascript
try {
  const response = await pubnub.objects.setChannelMetadata({
    channel: 'team.red',
    data: {
      name: 'Red Team',
      description: 'The channel for Red team and no other teams.',
      custom: {
        owner: 'Red Leader',
      },
    },
    include: {
      customFields: false,
    },
  });
  console.log('Set channel metadata response:', response);
} catch (error) {
  console.error(`Set channel metadata error: ${error}`);
}
```

### Java

```java
pubNub.setChannelMetadata()
        .channel("myChannel")
        .name("Some Name")
        .includeCustom(true)
        .async(result -> { /* check result */ });
```

### Kotlin

```kotlin
pubnub.setChannelMetadata(channel = "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);
        
// Set Metadata for a specific channel
PNResult<PNSetChannelMetadataResult> setChannelMetadataResponse = await pubnub.SetChannelMetadata()
    .Channel("my-channel")
    .Name("John Doe")
    .Description("sample description")
    .Custom(new Dictionary<string, object>() { { "color", "blue" } })
    .IncludeCustom(true)
    .ExecuteAsync();

PNSetChannelMetadataResult setChannelMetadataResult = setChannelMetadataResponse.Result;
PNStatus status = setChannelMetadataResponse.Status;
```

### Go

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

import (
	"fmt"
	"time"

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

// Example_setChannelMetadata demonstrates setting channel metadata
func Example_setChannelMetadata() {
	config := pubnub.NewConfigWithUserId(pubnub.UserId("demo-user"))
	config.SubscribeKey = "demo"
	config.PublishKey = "demo"

	pn := pubnub.NewPubNub(config)

	// Set channel metadata with descriptive information
	response, status, err := pn.SetChannelMetadata().
		Channel("support-channel-123").            // Channel ID
		Name("Customer Support").                  // Display name
		Description("24/7 customer support chat"). // Description
		Custom(map[string]interface{}{             // Custom metadata
			"department": "support",
			"priority":   "high",
		}).
		Execute()

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

	if status.StatusCode == 200 {
		fmt.Printf("Channel metadata set for: %s\n", response.Data.ID)
	}

	// Output:
	// Channel metadata set for: support-channel-123
}
```

### Swift

```swift
// Set channel metadata for a specific identifier
let channelMetadataToSet = PubNubChannelMetadataBase(
  metadataId: "some-channel-id",
  name: "Channel Name"
)

pubnub.setChannelMetadata(channelMetadataToSet) { result in
  switch result {
  case let .success(channelMetadata):
    print("The metadata for `\(channelMetadata.metadataId)`: \(channelMetadata)")
  case let .failure(error):
    print("Create request failed with error: \(error.localizedDescription)")
  }
}
```

### PHP

```php
foreach ($sampleChannels as $channel) {
    $setChannelMetadataResult = $pubnub->setChannelMetadata()
        ->channel($channel['id'])
        ->setName($channel['name'])
        ->setDescription($channel['description'])
        ->setCustom($channel['custom'])
        ->sync();
    assert($setChannelMetadataResult->getId() === $channel['id']);
    assert($setChannelMetadataResult->getName() === $channel['name']);
    assert($setChannelMetadataResult->getDescription() === $channel['description']);
}
```

### 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;
*/

// Set Metadata for a specific channel
PNResult<PNSetChannelMetadataResult> setChannelMetadataResponse = await pubnub.SetChannelMetadata()
    .Channel("my-channel")
    .Name("John Doe")
    .Description("sample description")
    .Custom(new Dictionary<string, object>() { { "color", "blue" } })
    .IncludeCustom(true)
    .ExecuteAsync();

PNSetChannelMetadataResult setChannelMetadataResult = setChannelMetadataResponse.Result;
PNStatus status = setChannelMetadataResponse.Status;
```

If [Access Manager](https://www.pubnub.com/docs/security/access-control/overview.md) is enabled on your keyset, this call requires an `update` permission grant on the channel. On success, the call also fires the `set` [App Context event](https://www.pubnub.com/docs/data-storage/metadata/events.md) other subscribers receive.

Pass the `eTag` from a get call as `ifMatchesEtag` on a set call to apply the update only if the record hasn't changed since you read it, so a mismatch returns HTTP 412. Most SDKs document this parameter on the same method as `ifMatchesEtag`. Check the API reference for your platform in [Available SDKs](https://www.pubnub.com/docs/sdks.md) for the exact name.

## Get channel metadata

Call `Get Channel Metadata` with the channel's name to read its current record. Most SDKs include the `custom` object in the response by default. Check your platform's API reference in [Available SDKs](https://www.pubnub.com/docs/sdks.md) to confirm.

### JavaScript

```javascript
try {
  const response = await pubnub.objects.getChannelMetadata({
    // `channel` is the `id` in the _metadata_, not `name`
    channel: 'team.blue',
  });
  console.log('Get channel metadata response:', response);
} catch (error) {
  console.error(`Get channel metadata error: ${error}`);
}
```

### Java

```java
PNGetChannelMetadataResult pnGetChannelMetadataResult = pubNub.getChannelMetadata()
        .channel("myChannel")
        .sync();
```

### Kotlin

```kotlin
pubnub.getChannelMetadata(channel = "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);
        
// Get Metadata for a specific channel
PNResult<PNGetChannelMetadataResult> getChannelMetadataResponse = await pubnub.GetChannelMetadata()
    .Channel("my-channel")
    .IncludeCustom(true)
    .ExecuteAsync();

PNGetChannelMetadataResult getChannelMetadataResult = getChannelMetadataResponse.Result;
PNStatus status = getChannelMetadataResponse.Status;
```

### Go

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

import (
	"fmt"
	"time"

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

// Example_getChannelMetadata demonstrates retrieving channel metadata
func Example_getChannelMetadata() {
	config := pubnub.NewConfigWithUserId(pubnub.UserId("demo-user"))
	config.SubscribeKey = "demo"
	config.PublishKey = "demo"

	pn := pubnub.NewPubNub(config)

	// First, set channel metadata
	pn.SetChannelMetadata().
		Channel("sales-channel-456").
		Name("Sales Team").
		Description("Sales team discussions").
		Execute()

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

	// Then retrieve the channel metadata
	response, status, err := pn.GetChannelMetadata().
		Channel("sales-channel-456"). // Channel ID to retrieve
		Execute()

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

	if status.StatusCode == 200 {
		fmt.Printf("Channel: %s\n", response.Data.Name)
		fmt.Printf("Description: %s\n", response.Data.Description)
	}

	// Output:
	// Channel: Sales Team
	// Description: Sales team discussions
}
```

### Swift

```swift
// Retrieve channel metadata for a specific identifier
pubnub.fetchChannelMetadata("some-channel-id") { result in
  switch result {
  case let .success(channelMetadata):
    print("The metadata for `\(channelMetadata.metadataId)`: \(channelMetadata)")
  case let .failure(error):
    print("Fetch request failed with error: \(error.localizedDescription)")
  }
}
```

### PHP

```php
$getChannelMetadataResult = $pubnub->getChannelMetadata()
    ->channel($sampleChannels[0]['id'])
    ->sync();
assert($getChannelMetadataResult->getId() === $sampleChannels[0]['id']);
assert($getChannelMetadataResult->getName() === $sampleChannels[0]['name']);
```

### 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;
*/

// Get Metadata for a specific channel
PNResult<PNGetChannelMetadataResult> getChannelMetadataResponse = await pubnub.GetChannelMetadata()
    .Channel("my-channel")
    .IncludeCustom(true)
    .ExecuteAsync();

PNGetChannelMetadataResult getChannelMetadataResult = getChannelMetadataResponse.Result;
PNStatus status = getChannelMetadataResponse.Status;
```

If Access Manager is enabled, this call requires a `get` permission grant on the channel. A channel with no metadata record yet returns a not-found error, since publishing to a channel doesn't create one.

## Remove channel metadata

Call `Remove Channel Metadata` with the channel's name to delete its record entirely, including every custom field. There's no way to remove a single field without rewriting the record. Refer to [Set channel metadata](#set-channel-metadata) to overwrite `custom` with everything except the field you want gone.

### JavaScript

```javascript
try {
  const response = await pubnub.objects.removeChannelMetadata({
    channel: 'team.red',
  });
} catch (error) {
  console.error(`Remove channel metadata error: ${error}`);
}
```

### Java

```java
pubNub.removeChannelMetadata()
        .channel("myChannel")
        .async(result -> { /* check result */ });
```

### Kotlin

```kotlin
pubnub.removeChannelMetadata(channel = "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);
        
// Delete Metadata for a specific channel
PNResult<PNRemoveChannelMetadataResult> removeChannelMetadataResponse = await pubnub.RemoveChannelMetadata()
    .Channel("mychannel")
    .ExecuteAsync();

PNRemoveChannelMetadataResult removeChannelMetadataResult = removeChannelMetadataResponse.Result;
PNStatus status = removeChannelMetadataResponse.Status;
```

### Go

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

import (
	"fmt"
	"time"

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

// Example_removeChannelMetadata demonstrates removing channel metadata
func Example_removeChannelMetadata() {
	config := pubnub.NewConfigWithUserId(pubnub.UserId("demo-user"))
	config.SubscribeKey = "demo"
	config.PublishKey = "demo"

	pn := pubnub.NewPubNub(config)

	// Remove channel metadata
	_, status, err := pn.RemoveChannelMetadata().
		Channel("temp-channel"). // Channel ID to remove
		Execute()

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

	if status.StatusCode == 200 {
		fmt.Println("Channel metadata removed successfully")
	}

	// Output:
	// Channel metadata removed successfully
}
```

### Swift

```swift
// Remove channel metadata for a specific identifier
pubnub.removeChannelMetadata("some-channel-id") { result in
  switch result {
  case let .success(metadataId):
    print("The metadata has been removed for the channel `\(metadataId)`")
  case let .failure(error):
    print("Delete request failed with error: \(error.localizedDescription)")
  }
}
```

### PHP

```php
$removeChannelMetadataResult = $pubnub->removeChannelMetadata()
    ->channel($sampleChannels[1]['id'])
    ->sync();
assert($removeChannelMetadataResult);
```

### 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;
*/

// Delete Metadata for a specific channel
PNResult<PNRemoveChannelMetadataResult> removeChannelMetadataResponse = await pubnub.RemoveChannelMetadata()
    .Channel("mychannel")
    .ExecuteAsync();

PNRemoveChannelMetadataResult removeChannelMetadataResult = removeChannelMetadataResponse.Result;
PNStatus status = removeChannelMetadataResponse.Status;
```

If Access Manager is enabled, this call requires a `delete` permission grant on the channel. Turning on **Enforce referential integrity for memberships** in the Admin Portal also deletes every membership pointing at this channel when you remove its metadata. Leaving that setting off leaves those memberships in place, pointing at a channel with no metadata record. Refer to [Membership connects users and channels](https://www.pubnub.com/docs/data-storage/metadata/overview.md#membership-connects-users-and-channels) for the full referential-integrity behavior.

## Set, get, and remove channel metadata without code

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

* [Create channels](https://www.pubnub.com/docs/data-storage/metadata/manage-channel-metadata.md). Set a new channel's `name`, `description`, and custom fields.
* [Update channels](https://www.pubnub.com/docs/data-storage/metadata/manage-channel-metadata.md). Change an existing channel's fields.
* [Delete channels](https://www.pubnub.com/docs/data-storage/metadata/manage-channel-metadata.md). Remove a channel's metadata, including in bulk.

A record 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.

## Related tasks

* [App Context](https://www.pubnub.com/docs/data-storage/metadata/overview.md). The three entity types and how App Context relates to messages and [Presence](https://www.pubnub.com/docs/presence/overview.md).
* [Get metadata for all channels](https://www.pubnub.com/docs/data-storage/metadata/get-metadata-for-all-channels.md). Page through every channel's metadata instead of one.
* [Set, get, and remove members](https://www.pubnub.com/docs/data-storage/metadata/manage-members.md). Manage this channel's user roster.
* [App Context events](https://www.pubnub.com/docs/data-storage/metadata/events.md). The `set` and `delete` event payload this operation produces.
* [App Context API limits](https://www.pubnub.com/docs/data-storage/metadata/api-limits.md). Field-length limits for `name`, `description`, and `custom`.

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