---
source_url: https://www.pubnub.com/docs/general/basics/add-custom-metadata
title: Add custom metadata
updated_at: 2026-06-24T11:04:50.786Z
---

> 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


# Add custom metadata

In PubNub, you can add descriptive metadata to channels, users, and the relationships between them.

There are three items you can assign metadata to: [users](https://www.pubnub.com/docs/general/metadata/users-metadata), [channels](https://www.pubnub.com/docs/general/metadata/channel-metadata), and [memberships](https://www.pubnub.com/docs/general/metadata/membership-metadata). Unlike dynamic state, metadata is stored in PubNub and is available anytime. Let's look at each of them.

Metadata scope by entity:

| Entity Type | Metadata Scope | Use Cases |
| --- | --- | --- |
| Channels | Channel-wide | Topic categorization, display name, description |
| Users | User profile | Preferences, roles, profile fields |
| Memberships | Relationship | Permission levels, user-channel settings |

Users have four predefined metadata properties: `name`, `email`, `profileURL`, and `externalId`. There is also a `custom` property that allows you to store any attribute.

The code below adds a `name`, an `e-mail`, and a custom `nickname` properties to [provide more information about a user](https://www.pubnub.com/docs/general/metadata/users-metadata#set-user-metadata).

:::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).
:::

###### JavaScript

```javascript
pubnub.objects.setUUIDMetadata({
    data: {
        name: "Thomas Anderson",
        email: "t.anderson@pubnub.com",
        custom: {
            "nickname": "The One"
        }
    }
});
```

###### Swift

```swift
let userMetadata = PubNubUserMetadataBase(
  metadataId: "uuid",
  name: "Thomas Anderson",
  email: "t.anderson@pubnub.com",
  custom: [ "nickname": "The One" ]
)

pubnub.setUserMetadata(userMetadata) { result in
  switch result {
  case let .success(metadata):
    print("The metadata for `\(metadata.metadataId)`: \(metadata)")
  case let .failure(error):
    print("Request failed with error: \(error.localizedDescription)")
  }
}
```

###### Objective-C

```objectivec
self.client.objects().setUUIDMetadata()
    .uuid(@"uuid")
    .name(@"Thomas Anderson")
    .custom(@{ @"nickname": @("The One") })
    .email(@"t.anderson@pubnub.com")
    .includeFields(PNUUIDCustomField)
    .performWithCompletion(^(PNSetUUIDMetadataStatus *status) {
        if (!status.isError) {
            /**
             * UUID metadata successfully has been set.
             * UUID metadata information available here: status.data.metadata
             */
        } else {
            /**
             * Handle UUID metadata set error. Check 'category' property to find out possible issue
             * because of which request did fail.
             *
             * Request can be resent using: [status retry]
             */
        }
    });
```

###### Android

```java
Map<String, Object> custom = new HashMap<>();
custom.put("nickname", "The One");
pubnub.setUUIDMetadata()
    .name("Thomas Anderson")
    .email("t.anderson@pubnub.com")
    .custom(custom)
    .includeCustom(true)
    .async(result -> { /* check result */ });
```

###### C#

```csharp
PNResult<PNSetUuidMetadataResult> setUuidMetadataResponse = await pubnub.SetUuidMetadata()
        .Uuid(config.Uuid)
        .Name("Thomas Anderson")
        .Email("t.anderson@pubnub.com")
        .Custom(new Dictionary<string, object>() { { "nickname", "The One" } })
        .ExecuteAsync();
PNSetUuidMetadataResult setUuidMetadataResult = setUuidMetadataResponse.Result;
PNStatus status = setUuidMetadataResponse.Status;
```

###### Python

```python
pubnub.set_uuid_metadata().uuid(this_uuid) \
    .set_name("Thomas Anderson") \
    .email("t.anderson@pubnub.com") \
    .custom({"nickname": "The One"}) \
    .include_custom(True) \
    .sync()
```

###### Dart

```dart
var uuidMetadataInput = UuidMetadataInput(
      name: 'Thomas Anderson',
      email: 't.anderson@pubnub.com',
      custom: {'nickname': 'The One'});
  var result = await pubnub.objects.setUUIDMetadata(uuidMetadataInput);
```

###### Kotlin

```kotlin
pubnub.setUUIDMetadata(
    uuid = "unique uuid",
    includeCustom = true,
    name = "Thomas Anderson",
    email = "t.anderson@pubnub.com",
    custom = "nickname = The One",
).async { result, status ->
            if (status.error) {
                //handle error
            } else if (result != null) {
                //handle result
            }
        }
```

Channels have two predefined metadata properties: `name` and `description`. The `custom` property allows you to store any attribute.

The code below adds all three properties to [provide more information about a channel](https://www.pubnub.com/docs/general/metadata/channel-metadata#set-channel-metadata). This way you're keeping all channel information in one place and can easily present additional data in your app's user interface.

###### JavaScript

```javascript
pubnub.objects.setChannelMetadata({
    channel: "chats_guilds.mages_guild",
    data: {
      name: "Mages guild",
      description: "Mages guild official chatroom.",
      custom: { "administrator": "thomas_anderson" }
    }
});
```

###### Swift

```swift
let channelMetadata = PubNubChannelMetadataBase(
  metadataId: "chats_guilds.mages_guild",
  name: "Mages guild",
  channelDescription: "Mages guild official chatroom.",
  custom: [ "administrator": "thomas_anderson" ]
)

pubnub.set(channel: channelMetadata) { result in
  switch result {
  case let .success(metadata):
    print("The metadata for `\(metadata.metadataId)`: \(metadata)")
  case let .failure(error):
    print("Request failed with error: \(error.localizedDescription)")
  }
}
```

###### Objective-C

```objectivec
self.client.objects().setChannelMetadata(@"chats_guilds.mages_guild")
    .name(@"Mages guild")
    .information(@"Mages guild official chatroom.")
    .custom(@{ @"administrator": @"thomas_anderson" })
    .includeFields(PNChannelCustomField)
    .performWithCompletion(^(PNSetChannelMetadataStatus *status) {
      if (!status.isError) {
          /**
           * Channel metadata successfully has been set.
           * Channel metadata information available here: status.data.metadata
           */
      } else {
          /**
           * Handle channel metadata update 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("administrator", "thomas_anderson");
pubnub.setChannelMetadata()
    .channel("chats_guilds.mages_guild")
    .name("Mages guild")
    .description("Mages guild official chatroom.")
    .custom(custom)
    .includeCustom(true)
    .async(result -> { /* check result */ });
```

###### C#

```csharp
PNResult<PNSetChannelMetadataResult> setChannelMetadataResponse = await pubnub.SetChannelMetadata()
    .Channel("chats_guilds.mages_guild")
    .Name("Mages guild")
    .Description("Mages guild official chatroom.")
    .Custom(new Dictionary<string, object>() { { "administrator", "thomas_anderson" } })
    .IncludeCustom(true)
    .ExecuteAsync();
PNSetChannelMetadataResult setChannelMetadataResult = setChannelMetadataResponse.Result;
PNStatus status = setChannelMetadataResponse.Status;
```

###### Python

```python
pubnub.set_channel_metadata().channel("chats_guilds.mages_guild") \
    .set_name("Mages guild") \
    .description("Mages guild official chatroom.") \
    .custom({"administrator": "thomas_anderson" }) \
    .include_custom(True) \
    .sync()
```

###### Dart

```dart
var channelMetadataInput = ChannelMetadataInput(
    name: 'chats_guilds.mages_guild', description: 'Mages guild official chatroom.', custom: { 'administrator': 'thomas_anderson'});

var result = await pubnub.objects
    .setChannelMetadata('my_channel', channelMetadataInput);
```

###### Kotlin

```kotlin
pubnub.setChannelMetadata(
    channel = "chats_guilds.mages_guild",
    includeCustom = true,
    description = "Mages guild official chatroom",
    custom = "administrator thomas_anderson"
).async { result, status ->
            if (status.error) {
                //handle error
            } else if (result != null) {
                //handle result
            }
        }
```

Memberships are relationships between users and channels. Use membership metadata to display a user’s channel list or to store user‑channel settings.

Memberships have no [predefined metadata properties](https://www.pubnub.com/docs/general/metadata/membership-metadata#set-channel-memberships), as the membership relation is metadata in itself.

The code below adds the current user to the `chats_guilds.mages_guild` and `chats_inbox.user_1905` channels and adds the `friendlist` metadata to the newly created `chats_inbox.user_1905` membership.

###### JavaScript

```javascript
pubnub.objects.setMemberships({
    channels: [
        "chats_guilds.mages_guild",
    {id: "chats_inbox.user_1905", custom: {friendlist: true}
    }]
});
```

###### Swift

```swift
let channels = [
  PubNubMembershipMetadataBase(userMetadataId: "uuid", channelMetadataId: "chats_guilds.mages_guild"),
  PubNubMembershipMetadataBase(userMetadataId: "uuid", channelMetadataId: "chats_inbox.user_1905", custom: [ "friendlist": true ]),
]

pubnub.setMemberships(uuid: "uuid", channels: channels) { result in
  switch result {
  case let .success((memberships, _)):
    print("Memberships: \(metadata)")
  case let .failure(error):
    print("Request failed with error: \(error.localizedDescription)")
  }
}
```

###### Objective-C

```objectivec
NSArray<NSDictionary *> *channels = @[
  @{ @"channel": @"chats_guilds.mages_guild" },
  @{ @"channel": @"chats_inbox.user_1905", @"custom": @{ @"friendlist": @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]
             */
        }
    });
```

###### Android

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

###### C#

```csharp
List<PNMembership> setMembershipChannelMetadataIdList = new List<PNMembership>();
if (!string.IsNullOrEmpty(seMembershipChannelMetaId))
{
    setMembershipChannelMetadataIdList.Add(new PNMembership() { Channel = "chats_guilds.mages_guild" });
    setMembershipChannelMetadataIdList.Add(new PNMembership() { Channel = "chats_inbox.user_1905", Custom = new Dictionary<string, object>() { { "friendlist", true } } });
}

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

###### Python

```python
pubnub.set_memberships().uuid(this_uuid).channel_memberships([
        PNChannelMembership.channel("chats_guilds.mages_guild"),
        PNChannelMembership.channel_with_custom("chats_inbox.user_1905", {"friendlist": True})
    ])
    .include_custom(True)
    .sync()
```

###### Dart

```dart
var setMetadata = [
  MembershipMetadataInput('chats_inbox.user_1905', custom: {'friendlist': 'true'}),
  MembershipMetadataInput('chats_guilds.mages_guild ')
];

var result = await pubnub.objects
    .setMemberships(setMetadata, includeChannelFields: true);
```

###### Kotlin

```kotlin
val custom: MutableMap<String, Any> = HashMap()
custom["friendlist"] = true

pubnub.setMemberships(listOf(
    PNChannelWithCustom(channel = "chats_guilds.mages_guild"),
    PNChannelWithCustom(channel = "chats_inbox.user_1905", custom = custom))
).async { result, status ->
        if (status.error) {
            //handle error
        } else if (result != null) {
            //handle result
        }
    }
```

To manage visibility and permissions, use Access Manager (see [Manage access](https://www.pubnub.com/docs/general/basics/manage-access)).

## Terms in this document

* **Access Manager** - A cryptographic, token-based permission administrator that allows you to regulate clients' access to PubNub resources, such as channels, channel groups, and user IDs.
* **PubNub** - PubNub is a real-time messaging platform that provides APIs and SDKs for building scalable applications. It handles the complex infrastructure of real-time communication, including: Message delivery and persistence, Presence detection, Access control, Push notifications, File sharing, Serverless processing with Functions and Events & Actions, Analytics and monitoring with BizOps Workspace, AI-powered insights with Illuminate.
