---
source_url: https://www.pubnub.com/docs/sdks/unreal/api-reference/objects
title: App Context API for Unreal SDK
updated_at: 2026-05-25T05:47:56.161Z
sdk_name: PubNub Unreal SDK
sdk_version: 2.0.5
---

> 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


# App Context API for Unreal SDK

PubNub Unreal SDK, use the latest version: 2.0.5

App Context provides easy-to-use, serverless storage for user and channel data you need to build innovative, reliable, scalable applications. Use App Context to easily store metadata about your application users and channels, and their membership associations, without the need to stand up your own databases.

PubNub also triggers events when object data is changed: set, updated, or removed from the database. At the same time, making a request to set the same data that already exist, doesn't trigger any event. Clients can receive these events in real time and update their front-end application accordingly.

##### Usage in Blueprints and C++

You can use PubNub's functionality via Blueprints or directly in C++ code.

* In Blueprints, the SDK is managed by a subsystem. Start by calling the Pubnub Subsystem node, then use Create Pubnub Client to create a UPubnubClient instance.
* In a C++ project, you have to add a dependency to PubnubLibrary: In your IDE, navigate to Source/_{YourProject}_/_{YourProject}_.Build.cs and add a dependency to PubnubLibrary. PrivateDependencyModuleNames.AddRange(new string[] { "PubnubLibrary" });, Compile the code and run the project.
* In C++, start by getting the UPubnubSubsystem (a Game Instance Subsystem), then create a UPubnubClient with your configuration. #include "Kismet/GameplayStatics.h"#include "PubnubSubsystem.h"#include "PubnubClient.h" UGameInstance* GameInstance = UGameplayStatics::GetGameInstance(this);UPubnubSubsystem* PubnubSubsystem = GameInstance->GetSubsystem<UPubnubSubsystem>(); FPubnubConfig Config;Config.PublishKey = "pub-c-...";Config.SubscribeKey = "sub-c-...";Config.UserId = "my-user-id"; UPubnubClient* PubnubClient = PubnubSubsystem->CreatePubnubClient(Config); PubnubClient allows you to call PubNub SDK functions, for example: PubnubClient->PublishMessageAsync("my-channel", "Hello!", OnPublishMessageResponseDelegate); The SDK supports multiple UPubnubClient instances within the same game for different contexts such as different users or keysets. For more information, refer to Configuration.

:::note Asynchronous and synchronous method execution
Most PubNub Unreal SDK methods are available in both asynchronous and synchronous variants.
* Asynchronous methods (Async suffix) return void and take an optional delegate parameter that fires when the operation completes. 1PubnubClient->GetAllUserMetadataAsync(OnGetAllUserMetadataResponse, Include, Limit, Filter, Sort, Page); You can also use native callbacks that accept lambdas instead of dynamic delegates. Native callback types have the Native suffix (for example, FOnPubnubGetAllUserMetadataResponseNative).
* Synchronous methods (no suffix) block the main game thread until the operation completes and return a result struct directly. 1FPubnubGetAllUserMetadataResult Result = PubnubClient->GetAllUserMetadata(Include, Limit, Filter, Sort, Page);
:::

## User

### Get metadata for all users

Retrieve user metadata in pages. The list includes the Custom object if requested.

:::warning Required keyset configuration
To get all channel and user metadata, you must uncheck the
Disallow Get All Channel Metadata
and
Disallow Get All User Metadata
checkboxes in the App Context section of your keyset configuration in the
[Admin Portal](https://admin.pubnub.com)
.
:::

#### Method(s)

:::tip Method variants
You can also call the `GetAllUserMetadataRaw` variant of this method which takes String values for `Include` and `Sort` instead of the `FPubnubGetAllInclude` and `FPubnubGetAllSort` structs.
:::

```cpp
// Synchronous
FPubnubGetAllUserMetadataResult Result = PubnubClient->GetAllUserMetadata(
    FPubnubGetAllInclude Include = FPubnubGetAllInclude(),
    int Limit = 100,
    FString Filter = "",
    FPubnubGetAllSort Sort = FPubnubGetAllSort(),
    FPubnubPage Page = FPubnubPage()
);

// Asynchronous
PubnubClient->GetAllUserMetadataAsync(
    FOnPubnubGetAllUserMetadataResponse OnGetAllUserMetadataResponse,
    FPubnubGetAllInclude Include = FPubnubGetAllInclude(),
    int Limit = 100,
    FString Filter = "",
    FPubnubGetAllSort Sort = FPubnubGetAllSort(),
    FPubnubPage Page = FPubnubPage()
);
```

| Parameter | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| OnGetAllUserMetadataResponse | FOnPubnubGetAllUserMetadataResponse | Optional |  | The delegate for the operation's result. You can also use a native callback of the type [FOnPubnubGetAllUserMetadataResponseNative](#fonpubnubgetallusermetadataresponsenative) to handle the result using a lambda. |
| Include | FPubnubGetAllInclude | Optional |  | A list of property names to include in the response. |
| Limit | int | Optional |  | Number of objects to return. Default/Max: 100. |
| Filter | FString | Optional |  | Filter expression. Only matching objects are returned. See filtering. |
| Sort | FPubnubGetAllSort | Optional |  | Sort by id, name, updated with asc/desc for sort direction (for example, `{name: 'asc'}`). |
| Page | FPubnubPage | Optional |  | Cursor-based pagination. Use `Page.Next` and `Page.Prev` to request the next or previous page. |

#### FPubnubGetAllInclude

| Field | Type | Description |
| --- | --- | --- |
| `IncludeCustom` | `bool` | Whether to include the Custom object in the response. |
| `IncludeStatus` | `bool` | Whether to include the membership Status field. |
| `IncludeType` | `bool` | Whether to include the membership Type field. |
| `IncludeTotalCount` | `bool` | Whether to include the total count. |

#### FPubnubGetAllSort

| Field | Type | Description |
| --- | --- | --- |
| `GetAllSort` | `TArray<FPubnubGetAllSingleSort>` | Array of sorts for Membership related function. The order matters, sorts will be applied from the first index to the last. |

#### Sample code

:::tip Reference code
Set up your Unreal project and follow the instructions in the lines marked with
ACTION REQUIRED
before running the code.
:::

###### C++

#### Actor.h

```cpp
#include "PubnubClient.h"

// blueprint.sarms73o
UFUNCTION(BlueprintCallable, Category = "Pubnub|Samples|App Context")
void GetAllUserMetadataSample();

UFUNCTION()
void OnGetAllUserMetadataResponse_Simple(FPubnubOperationResult Result, const TArray<FPubnubUserData>& UsersData, FPubnubPage Page, int TotalCount);
```

#### Actor.cpp

```cpp
// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::GetAllUserMetadataSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set

	// Bind response delegate
	// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
	FOnPubnubGetAllUserMetadataResponse OnGetAllUserMetadataResponse;
	OnGetAllUserMetadataResponse.BindDynamic(this, &ASample_AppContext::OnGetAllUserMetadataResponse_Simple);

	// Get all user metadata with a limit of 5
	PubnubClient->GetAllUserMetadataAsync(OnGetAllUserMetadataResponse, FPubnubGetAllInclude(), 5);
}

// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::OnGetAllUserMetadataResponse_Simple(FPubnubOperationResult Result, const TArray<FPubnubUserData>& UsersData, FPubnubPage Page, int TotalCount)
{
	if(Result.Error)
	{
		UE_LOG(LogTemp, Error, TEXT("Failed to get all user metadata. Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
	}
	else
	{
		UE_LOG(LogTemp, Log, TEXT("Successfully got all user metadata. Number of users: %d"), UsersData.Num());
		// Print all user metadata
		for (const FPubnubUserData& User : UsersData)
		{
			UE_LOG(LogTemp, Log, TEXT("- UserID: %s, Name: %s"), *User.UserID, *User.UserName);
		}
		if (!Page.Next.IsEmpty()) UE_LOG(LogTemp, Log, TEXT("Next Page: %s"), *Page.Next);
		if (!Page.Prev.IsEmpty()) UE_LOG(LogTemp, Log, TEXT("Previous Page: %s"), *Page.Prev);
	}
}
```

###### Blueprint

##### Other examples

:::tip Reference code
Set up your Unreal project and follow the instructions in the lines marked with
ACTION REQUIRED
before running the code.
:::

###### Get metadata for all users with additional settings

###### Actor.h

```cpp
#include "PubnubClient.h"

UFUNCTION(BlueprintCallable, Category = "Pubnub|Samples|App Context")
void GetAllUserMetadataWithSettingsSample();

UFUNCTION()
void OnGetAllUserMetadataResponse_WithSettings(FPubnubOperationResult Result, const TArray<FPubnubUserData>& UsersData, FPubnubPage Page, int TotalCount);
```

###### Actor.cpp

```cpp
// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::GetAllUserMetadataWithSettingsSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set

	// Bind response delegate
	// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
	FOnPubnubGetAllUserMetadataResponse OnGetAllUserMetadataResponse;
	OnGetAllUserMetadataResponse.BindDynamic(this, &ASample_AppContext::OnGetAllUserMetadataResponse_WithSettings);

	// Create settings with includes and a filter
	FPubnubGetAllInclude Include;
	Include.IncludeCustom = true;
	Include.IncludeStatus = true;
	FString Filter = TEXT("status=='active'");
	int Limit = 10;
	
	// Get all user metadata with custom settings
	PubnubClient->GetAllUserMetadataAsync(OnGetAllUserMetadataResponse, Include, Limit, Filter);
}

// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::OnGetAllUserMetadataResponse_WithSettings(FPubnubOperationResult Result, const TArray<FPubnubUserData>& UsersData, FPubnubPage Page, int TotalCount)
{
	if(Result.Error)
	{
		UE_LOG(LogTemp, Error, TEXT("Failed to get all user metadata. Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
	}
	else
	{
		UE_LOG(LogTemp, Log, TEXT("Successfully got all user metadata with settings. Number of users: %d"), UsersData.Num());
		// Print all user metadata
		for (const FPubnubUserData& User : UsersData)
		{
			UE_LOG(LogTemp, Log, TEXT("- UserID: %s, Name: %s, Custom: %s, Status: %s"), *User.UserID, *User.UserName, *User.Custom, *User.Status);
		}
		if (!Page.Next.IsEmpty()) UE_LOG(LogTemp, Log, TEXT("Next Page: %s"), *Page.Next);
		if (!Page.Prev.IsEmpty()) UE_LOG(LogTemp, Log, TEXT("Previous Page: %s"), *Page.Prev);
	}
}
```

###### Get metadata for all users with all includes

###### Actor.h

```cpp
#include "PubnubClient.h"

UFUNCTION(BlueprintCallable, Category = "Pubnub|Samples|App Context")
void GetAllUserMetadataWithAllIncludesSample();

UFUNCTION()
void OnGetAllUserMetadataResponse_WithAllIncludes(FPubnubOperationResult Result, const TArray<FPubnubUserData>& UsersData, FPubnubPage Page, int TotalCount);
```

###### Actor.cpp

```cpp
// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::GetAllUserMetadataWithAllIncludesSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set

	// Bind response delegate
	// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
	FOnPubnubGetAllUserMetadataResponse OnGetAllUserMetadataResponse;
	OnGetAllUserMetadataResponse.BindDynamic(this, &ASample_AppContext::OnGetAllUserMetadataResponse_WithAllIncludes);

	// Get all user metadata with all available data included
	FPubnubGetAllInclude Include = FPubnubGetAllInclude::FromValue(true);
	FString Filter = TEXT("status=='active' || status=='inactive'");
	FPubnubGetAllSort Sort;
	Sort.GetAllSort.Add(FPubnubGetAllSingleSort{EPubnubGetAllSortType::PGAST_Name, true});
	FString NextPage = "Mg"; // Page should be taken from previous response to get next or previous part of the objects
	FPubnubPage Page;
	Page.Next = NextPage;

	PubnubClient->GetAllUserMetadataAsync(OnGetAllUserMetadataResponse, Include, 100, Filter, Sort, Page);
}

// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::OnGetAllUserMetadataResponse_WithAllIncludes(FPubnubOperationResult Result, const TArray<FPubnubUserData>& UsersData, FPubnubPage Page, int TotalCount)
{
	if(Result.Error)
	{
		UE_LOG(LogTemp, Error, TEXT("Failed to get all user metadata. Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
	}
	else
	{
		UE_LOG(LogTemp, Log, TEXT("Successfully got all user metadata with all includes. Number of users: %d"), UsersData.Num());
		// Print all user metadata
		for (const FPubnubUserData& User : UsersData)
		{
			UE_LOG(LogTemp, Log, TEXT("- UserID: %s, Name: %s, Custom: %s, Status: %s"), *User.UserID, *User.UserName, *User.Custom, *User.Status);
		}
		if (!Page.Next.IsEmpty()) UE_LOG(LogTemp, Log, TEXT("Next Page: %s"), *Page.Next);
		if (!Page.Prev.IsEmpty()) UE_LOG(LogTemp, Log, TEXT("Previous Page: %s"), *Page.Prev);
	}
}
```

###### Get metadata for all users with lambda

###### Actor.h

```cpp
#include "PubnubClient.h"

UFUNCTION(BlueprintCallable, Category = "Pubnub|Samples|App Context")
void GetAllUserMetadataWithLambdaSample();
```

###### Actor.cpp

```cpp
// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::GetAllUserMetadataWithLambdaSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set

	// Bind lambda to response delegate
	// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
	FOnPubnubGetAllUserMetadataResponseNative OnGetAllUserMetadataResponse;
	OnGetAllUserMetadataResponse.BindLambda([](const FPubnubOperationResult& Result, const TArray<FPubnubUserData>& UsersData, FPubnubPage Page, int TotalCount)
	{
		if(Result.Error)
		{
			UE_LOG(LogTemp, Error, TEXT("Failed to get all user metadata. Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
		}
		else
		{
			UE_LOG(LogTemp, Log, TEXT("Successfully got all user metadata. Number of users: %d"), UsersData.Num());
			// Print all user metadata
			for (const FPubnubUserData& User : UsersData)
			{
				UE_LOG(LogTemp, Log, TEXT("- UserID: %s, Name: %s"), *User.UserID, *User.UserName);
			}
			if (!Page.Next.IsEmpty()) UE_LOG(LogTemp, Log, TEXT("Next Page: %s"), *Page.Next);
			if (!Page.Prev.IsEmpty()) UE_LOG(LogTemp, Log, TEXT("Previous Page: %s"), *Page.Prev);
		}
	});
	
	// Get all user metadata with a limit of 5
	PubnubClient->GetAllUserMetadataAsync(OnGetAllUserMetadataResponse, FPubnubGetAllInclude(), 5);
}
```

###### Get metadata for all users raw

###### Actor.h

```cpp
#include "PubnubClient.h"

UFUNCTION(BlueprintCallable, Category = "Pubnub|Samples|App Context")
void GetAllUserMetadataRawSample();

UFUNCTION()
void OnGetAllUserMetadataRawResponse(FPubnubOperationResult Result, const TArray<FPubnubUserData>& UsersData, FPubnubPage Page, int TotalCount);
```

###### Actor.cpp

```cpp
// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::GetAllUserMetadataRawSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set

	// Bind response delegate
	// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
	FOnPubnubGetAllUserMetadataResponse OnGetAllUserMetadataResponse;
	OnGetAllUserMetadataResponse.BindDynamic(this, &ASample_AppContext::OnGetAllUserMetadataRawResponse);

	// Create settings with includes and a filter
	FString Include = TEXT("custom,status");
	FString Filter = TEXT("status=='active'");
	FString Sort = TEXT("name:desc,status");
	int Limit = 10;
	
	// Get all user metadata with custom settings
	PubnubClient->GetAllUserMetadataRawAsync(OnGetAllUserMetadataResponse, Include, Limit, Filter, Sort);
}

// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::OnGetAllUserMetadataRawResponse(FPubnubOperationResult Result, const TArray<FPubnubUserData>& UsersData, FPubnubPage Page, int TotalCount)
{
	if(Result.Error)
	{
		UE_LOG(LogTemp, Error, TEXT("Failed to get all user metadata (raw). Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
	}
	else
	{
		UE_LOG(LogTemp, Log, TEXT("Successfully got all user metadata (raw). Number of users: %d"), UsersData.Num());
		// Print all user metadata
		for (const FPubnubUserData& User : UsersData)
		{
			UE_LOG(LogTemp, Log, TEXT("- UserID: %s, Name: %s, Custom: %s, Status: %s"), *User.UserID, *User.UserName, *User.Custom, *User.Status);
		}
		if (!Page.Next.IsEmpty()) UE_LOG(LogTemp, Log, TEXT("Next Page: %s"), *Page.Next);
		if (!Page.Prev.IsEmpty()) UE_LOG(LogTemp, Log, TEXT("Previous Page: %s"), *Page.Prev);
	}
}
```

#### Returns

* **Synchronous:** returns [FPubnubGetAllUserMetadataResult](#fpubnubgetallusermetadataresult) (Result, UsersData, Page, TotalCount).
* **Asynchronous:** delegate [FOnPubnubGetAllUserMetadataResponse](#fonpubnubgetallusermetadataresponse) receives (Result, UsersData, Page, TotalCount).

##### FPubnubGetAllUserMetadataResult

| Field | Type | Description |
| --- | --- | --- |
| `Result` | [FPubnubOperationResult](https://www.pubnub.com/docs/sdks/unreal/api-reference/configuration#operation-result) | The result of the operation. |
| `UsersData` | `TArray<FPubnubUserData>` | Array of [FPubnubUserData](#fpubnubuserdata) structs which are the users with their associated User metadata. |
| `Page` | [FPubnubPage](#fpubnubpage) | Pagination cursor (Next, Prev) for requesting the next or previous page. |
| `TotalCount` | `int` | Total number of users matching the request (when requested). |

##### FOnPubnubGetAllUserMetadataResponse

| Field | Type | Description |
| --- | --- | --- |
| `Result` | [FPubnubOperationResult](https://www.pubnub.com/docs/sdks/unreal/api-reference/configuration#operation-result) | The result of the operation. |
| `UsersData` | [const TArray<FPubnubUserData>&](#fpubnubuserdata) | Array of [FPubnubUserData](#fpubnubuserdata) structs which are the users with their associated User metadata. |
| `Page` | [FPubnubPage](#fpubnubpage) | Pagination cursor (Next, Prev) for requesting the next or previous page. |
| `TotalCount` | `int` | Total number of users matching the request (when requested). |

##### FPubnubPage

| Field | Type | Description |
| --- | --- | --- |
| `Next` | `FString` | Cursor for forward pagination. Use in the next request to fetch the following page. |
| `Prev` | `FString` | Cursor for backward pagination. Use in the next request to fetch the previous page. Ignored if `Next` is supplied. |

##### FPubnubUserData

| Field | Type | Description |
| --- | --- | --- |
| `UserID` | `FString` | UUID. If not supplied, the current user's UUID is used. |
| `UserName` | `FString` | Display name for the user. |
| `ExternalID` | `FString` | User's identifier in an external system. |
| `ProfileUrl` | `FString` | The URL of the user's profile picture. |
| `Email` | `FString` | The user's email address. |
| `Custom` | `FString` | Custom JSON values. Can be strings, numbers, or booleans. Filtering by Custom isn’t supported. |
| `Status` | `FString` | User status. Max. 50 characters. |
| `Type` | `FString` | User type. Max. 50 characters. |
| `Updated` | `FString` | The date when the user's metadata was last updated. |
| `ETag` | `FString` | Information on the object's content fingerprint. |

##### FOnPubnubGetAllUserMetadataResponseNative

| Field | Type | Description |
| --- | --- | --- |
| `Result` | [const FPubnubOperationResult&](https://www.pubnub.com/docs/sdks/unreal/api-reference/configuration#operation-result) | The result of the operation. |
| `UsersData` | [const TArray<FPubnubUserData>&](#fpubnubuserdata) | Array of [FPubnubUserData](#fpubnubuserdata) structs which are the users with their associated User metadata. |
| `Page` | [const FPubnubPage&](#fpubnubpage) | Pagination cursor (Next, Prev) for requesting the next or previous page. |
| `TotalCount` | `int` | Total number of users matching the request (when requested). |

### Get user metadata - UserMetadata entity

##### Available in entities

This method is available to use with the `UserMetadata` entity. For more information, refer to [UserMetadata](https://www.pubnub.com/docs/sdks/unreal/entities/user-metadata).

:::note Requires App Context add-on
This method requires the *App Context* add-on enabled for your key in the [Admin Portal](https://admin.pubnub.com/).
:::

Retrieve metadata for a user. You can include the Custom object.

#### Method(s)

```cpp
UPubnubUserMetadataEntity* UserMetadataEntity = PubnubSubsystem->CreateUserMetadataEntity("user-id");

UserMetadataEntity->GetUserMetadata(
    FOnGetUserMetadataResponse OnGetUserMetadataResponse,
    FPubnubGetMetadataInclude Include = FPubnubGetMetadataInclude()
);
```

| Parameter | Description |
| --- | --- |
| `OnGetUserMetadataResponse` *Type: [FOnGetUserMetadataResponse](#fongetusermetadataresponse) | The delegate for the operation's result. You can also use a native callback of the type [FOnGetUserMetadataResponseNative](#fongetusermetadataresponsenative) to handle the result using a lambda. |
| `Include`Type: [FPubnubGetMetadataInclude](#fpubnubgetmetadatainclude) | List of property names to include in the response. |

#### Sample code

:::tip Reference code
Set up your Unreal project and follow the instructions in the lines marked with
ACTION REQUIRED
before running the code.
:::

###### C++

#### Actor.h

```cpp
#include "PubnubClient.h"
#include "Entities/PubnubUserMetadataEntity.h"
#include "Entities/PubnubSubscription.h"

UFUNCTION(BlueprintCallable, Category = "Pubnub|Samples|UserMetadataEntity")
void GetUserMetadataSample();

UFUNCTION()
void OnGetUserMetadataResponse_Simple(FPubnubOperationResult Result, FPubnubUserData UserData);
```

#### Actor.cpp

```cpp
// ACTION REQUIRED: Replace ASample_UserMetadataEntity with name of your Actor class
void ASample_UserMetadataEntity::GetUserMetadataSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	FString UserID = TEXT("Player_001");
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set

	// Create a user metadata entity
	UPubnubUserMetadataEntity* UserMetadataEntity = PubnubClient->CreateUserMetadataEntity(UserID);

	// Bind response delegate
	// ACTION REQUIRED: Replace ASample_UserMetadataEntity with name of your Actor class
	FOnPubnubGetUserMetadataResponse OnGetUserMetadataResponse;
	OnGetUserMetadataResponse.BindDynamic(this, &ASample_UserMetadataEntity::OnGetUserMetadataResponse_Simple);

	// Get user metadata using the user metadata entity
	UserMetadataEntity->GetUserMetadataAsync(OnGetUserMetadataResponse);
}

// ACTION REQUIRED: Replace ASample_UserMetadataEntity with name of your Actor class
void ASample_UserMetadataEntity::OnGetUserMetadataResponse_Simple(FPubnubOperationResult Result, FPubnubUserData UserData)
{
	if(Result.Error)
	{
		UE_LOG(LogTemp, Error, TEXT("Failed to get user metadata. Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
	}
	else
	{
		UE_LOG(LogTemp, Log, TEXT("Successfully got user metadata. UserID: %s, Name: %s"), *UserData.UserID, *UserData.UserName);
	}
}
```

#### Returns

This function is void, but the delegate returns the [FOnGetUserMetadataResponse](#fongetusermetadataresponse) struct.

#### Other examples

:::tip Reference code
Set up your Unreal project and follow the instructions in the lines marked with
ACTION REQUIRED
before running the code.
:::

##### Get user metadata with lambda

###### Actor.h

```cpp
#include "PubnubClient.h"
#include "Entities/PubnubUserMetadataEntity.h"
#include "Entities/PubnubSubscription.h"

UFUNCTION(BlueprintCallable, Category = "Pubnub|Samples|UserMetadataEntity")
void GetUserMetadataWithLambdaSample();
```

###### Actor.cpp

```cpp
// ACTION REQUIRED: Replace ASample_UserMetadataEntity with name of your Actor class
void ASample_UserMetadataEntity::GetUserMetadataWithLambdaSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	FString UserID = TEXT("Player_003");
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set

	// Create a user metadata entity
	UPubnubUserMetadataEntity* UserMetadataEntity = PubnubClient->CreateUserMetadataEntity(UserID);

	// Bind lambda to response delegate
	FOnPubnubGetUserMetadataResponseNative OnGetUserMetadataResponse;
	OnGetUserMetadataResponse.BindLambda([](const FPubnubOperationResult& Result, const FPubnubUserData& UserData)
	{
		if(Result.Error)
		{
			UE_LOG(LogTemp, Error, TEXT("Failed to get user metadata. Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
		}
		else
		{
			UE_LOG(LogTemp, Log, TEXT("Successfully got user metadata. UserID: %s, Name: %s"), *UserData.UserID, *UserData.UserName);
		}
	});
	
	// Get user metadata using the user metadata entity
	UserMetadataEntity->GetUserMetadataAsync(OnGetUserMetadataResponse);
}
```

### Get user metadata - PubNub client

Retrieve metadata for a user. You can include the Custom object.

#### Method(s)

```cpp
// Synchronous
FPubnubUserMetadataResult Result = PubnubClient->GetUserMetadata(
    FString User,
    FPubnubGetMetadataInclude Include = FPubnubGetMetadataInclude()
);

// Asynchronous
PubnubClient->GetUserMetadataAsync(
    FString User,
    FOnPubnubGetUserMetadataResponse OnGetUserMetadataResponse,
    FPubnubGetMetadataInclude Include = FPubnubGetMetadataInclude()
);
```

| Parameter | Description |
| --- | --- |
| `User` *Type: `FString` | The metadata ID for which to retrieve the user object. Can't be empty. |
| `OnGetUserMetadataResponse`Type: [FOnPubnubGetUserMetadataResponse](#fonpubnubgetusermetadataresponse) | The delegate for the operation's result. You can also use a native callback of the type [FOnPubnubGetUserMetadataResponseNative](#fonpubnubgetusermetadataresponsenative) to handle the result using a lambda. |
| `Include`Type: [FPubnubGetMetadataInclude](#fpubnubgetmetadatainclude) | List of property names to include in the response. |

#### Sample code

:::tip Reference code
Set up your Unreal project and follow the instructions in the lines marked with
ACTION REQUIRED
before running the code.
:::

###### C++

#### Actor.h

```cpp
#include "PubnubClient.h"

// blueprint.2jr6qjos
UFUNCTION(BlueprintCallable, Category = "Pubnub|Samples|App Context")
void GetUserMetadataSample();

UFUNCTION()
void OnGetUserMetadataResponse_Simple(FPubnubOperationResult Result, FPubnubUserData UserData);
```

#### Actor.cpp

```cpp
// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::GetUserMetadataSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set

	// Bind response delegate
	// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
	FOnPubnubGetUserMetadataResponse OnGetUserMetadataResponse;
	OnGetUserMetadataResponse.BindDynamic(this, &ASample_AppContext::OnGetUserMetadataResponse_Simple);

	// Get user metadata
	FString UserID = TEXT("Player_001");
	PubnubClient->GetUserMetadataAsync(UserID, OnGetUserMetadataResponse);
}

// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::OnGetUserMetadataResponse_Simple(FPubnubOperationResult Result, FPubnubUserData UserData)
{
	if(Result.Error)
	{
		UE_LOG(LogTemp, Error, TEXT("Failed to get user metadata. Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
	}
	else
	{
		UE_LOG(LogTemp, Log, TEXT("Successfully got user metadata. UserID: %s, Name: %s"), *UserData.UserID, *UserData.UserName);
	}
}
```

###### Blueprint

#### Returns

* **Synchronous:** returns [FPubnubUserMetadataResult](#fpubnubusermetadataresult) (Result, UserData).
* **Asynchronous:** delegate [FOnPubnubGetUserMetadataResponse](#fonpubnubgetusermetadataresponse) receives (Result, UserData).

##### FPubnubUserMetadataResult

| Field | Type | Description |
| --- | --- | --- |
| `Result` | [FPubnubOperationResult](https://www.pubnub.com/docs/sdks/unreal/api-reference/configuration#operation-result) | The result of the operation. |
| `UserData` | [FPubnubUserData](#fpubnubuserdata) | The user with their associated User metadata. |

##### FOnPubnubGetUserMetadataResponse

| Field | Type | Description |
| --- | --- | --- |
| `Result` | [FPubnubOperationResult](https://www.pubnub.com/docs/sdks/unreal/api-reference/configuration#operation-result) | The result of the operation. |
| `UserData` | [FPubnubUserData](#fpubnubuserdata) | The user with their associated User metadata. |

##### FOnPubnubGetUserMetadataResponseNative

| Field | Type | Description |
| --- | --- | --- |
| `Result` | [const FPubnubOperationResult&](https://www.pubnub.com/docs/sdks/unreal/api-reference/configuration#operation-result) | The result of the operation. |
| `UserData` | [const FPubnubUserData&](#fpubnubuserdata) | The user with their associated User metadata. |

#### Other examples

:::tip Reference code
Set up your Unreal project and follow the instructions in the lines marked with
ACTION REQUIRED
before running the code.
:::

##### Get metadata for a user with all includes

###### Actor.h

```cpp
#include "PubnubClient.h"

UFUNCTION(BlueprintCallable, Category = "Pubnub|Samples|App Context")
void GetUserMetadataWithAllIncludesSample();

UFUNCTION()
void OnGetUserMetadataResponse_WithAllIncludes(FPubnubOperationResult Result, FPubnubUserData UserData);
```

###### Actor.cpp

```cpp
// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::GetUserMetadataWithAllIncludesSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set

	// Bind response delegate
	// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
	FOnPubnubGetUserMetadataResponse OnGetUserMetadataResponse;
	OnGetUserMetadataResponse.BindDynamic(this, &ASample_AppContext::OnGetUserMetadataResponse_WithAllIncludes);

	// Get user metadata with all available data included
	FString UserID = TEXT("Player_002");
	FPubnubGetMetadataInclude Include = FPubnubGetMetadataInclude::FromValue(true);
	PubnubClient->GetUserMetadataAsync(UserID, OnGetUserMetadataResponse, Include);
}

// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::OnGetUserMetadataResponse_WithAllIncludes(FPubnubOperationResult Result, FPubnubUserData UserData)
{
	if(Result.Error)
	{
		UE_LOG(LogTemp, Error, TEXT("Failed to get user metadata. Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
	}
	else
	{
		UE_LOG(LogTemp, Log, TEXT("Successfully got user metadata with all includes. UserID: %s, Name: %s, Custom: %s, Status: %s"), *UserData.UserID, *UserData.UserName, *UserData.Custom, *UserData.Status);
	}
}
```

##### Get metadata for a user with lambda

###### Actor.h

```cpp
#include "PubnubClient.h"

UFUNCTION(BlueprintCallable, Category = "Pubnub|Samples|App Context")
void GetUserMetadataWithLambdaSample();
```

###### Actor.cpp

```cpp
// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::GetUserMetadataWithLambdaSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set

	// Bind lambda to response delegate
	// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
	FOnPubnubGetUserMetadataResponseNative OnGetUserMetadataResponse;
	OnGetUserMetadataResponse.BindLambda([](const FPubnubOperationResult& Result, const FPubnubUserData& UserData)
	{
		if(Result.Error)
		{
			UE_LOG(LogTemp, Error, TEXT("Failed to get user metadata. Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
		}
		else
		{
			UE_LOG(LogTemp, Log, TEXT("Successfully got user metadata. UserID: %s, Name: %s"), *UserData.UserID, *UserData.UserName);
		}
	});
	
	// Get user metadata
	FString UserID = TEXT("Player_003");
	PubnubClient->GetUserMetadataAsync(UserID, OnGetUserMetadataResponse);
}
```

##### Get metadata for a user raw

###### Actor.h

```cpp
#include "PubnubClient.h"

UFUNCTION(BlueprintCallable, Category = "Pubnub|Samples|App Context")
void GetUserMetadataRawSample();

UFUNCTION()
void OnGetUserMetadataRawResponse(FPubnubOperationResult Result, FPubnubUserData UserData);
```

###### Actor.cpp

```cpp
// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::GetUserMetadataRawSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set

	// Bind response delegate
	// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
	FOnPubnubGetUserMetadataResponse OnGetUserMetadataResponse;
	OnGetUserMetadataResponse.BindDynamic(this, &ASample_AppContext::OnGetUserMetadataRawResponse);

	// Get user metadata with raw include string
	FString UserID = TEXT("Player_004");
	FString Include = TEXT("custom,status");
	PubnubClient->GetUserMetadataRawAsync(UserID, OnGetUserMetadataResponse, Include);
}

// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::OnGetUserMetadataRawResponse(FPubnubOperationResult Result, FPubnubUserData UserData)
{
	if(Result.Error)
	{
		UE_LOG(LogTemp, Error, TEXT("Failed to get user metadata (raw). Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
	}
	else
	{
		UE_LOG(LogTemp, Log, TEXT("Successfully got user metadata (raw). UserID: %s, Name: %s, Custom: %s, Status: %s"), *UserData.UserID, *UserData.UserName, *UserData.Custom, *UserData.Status);
	}
}
```

##### Set user metadata with additional settings

###### Actor.h

```cpp
#include "PubnubClient.h"

```

###### Actor.cpp

```cpp
// Copyright 2026 PubNub Inc. All Rights Reserved.

#include "Samples/Sample_AppContext.h"
#include "Kismet/GameplayStatics.h"
#include "Engine/GameInstance.h"
#include "PubnubSubsystem.h"

/**
 * NOTE: Each sample is designed to be fully self-contained and portable. 
 * You can copy-paste any individual sample into a new project, and it should compile and run without errors 
 * — as long as you also include the necessary `#include` statements.
 *
 * The samples assume that in Pubnub SDK settings sections in ProjectSettings following fields are set:
 * PublishKey and SubscribeKey have correct keys, InitializeAutomatically is true.
 */

// NOTE: Comments marked with `ACTION REQUIRED` indicate lines you must change/adjust.

//Internal function, don't copy it with the samples
void ASample_AppContext::RunSamples()
{
	Super::RunSamples();
	
	SetUserMetadataSample();
	SetUserMetadataWithResultSample();
	SetUserMetadataWithLambdaSample();
	SetUserMetadataRawSample();
	UpdateUserMetadataIterativelySample();
	GetAllUserMetadataSample();
	GetAllUserMetadataWithSettingsSample();
	GetAllUserMetadataWithAllIncludesSample();
	GetAllUserMetadataWithLambdaSample();
	GetAllUserMetadataRawSample();
	GetUserMetadataSample();
	GetUserMetadataWithAllIncludesSample();
	GetUserMetadataWithLambdaSample();
	GetUserMetadataRawSample();
	RemoveUserMetadataSample();
	RemoveUserMetadataWithResultSample();
	RemoveUserMetadataWithResultLambdaSample();
	SetChannelMetadataSample();
	SetChannelMetadataWithResultSample();
	SetChannelMetadataWithLambdaSample();
	SetChannelMetadataRawSample();
	UpdateChannelMetadataIterativelySample();
	GetAllChannelMetadataSample();
	GetAllChannelMetadataWithSettingsSample();
	GetAllChannelMetadataWithAllIncludesSample();
	GetAllChannelMetadataWithLambdaSample();
	GetAllChannelMetadataRawSample();
	GetChannelMetadataSample();
	GetChannelMetadataWithAllIncludesSample();
	GetChannelMetadataWithLambdaSample();
	GetChannelMetadataRawSample();
	RemoveChannelMetadataSample();
	RemoveChannelMetadataWithResultSample();
	RemoveChannelMetadataWithResultLambdaSample();
}
//Internal function, don't copy it with the samples
ASample_AppContext::ASample_AppContext()
{
	SamplesName = "App Context";
}

/* SAMPLE FUNCTIONS */

// snippet.set_user_metadata
// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::SetUserMetadataSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set

	// Create user metadata object
	FPubnubUserData UserMetadata;
	UserMetadata.UserName = "Player One";
	UserMetadata.Email = "player.one@pubnub.com";
	UserMetadata.Custom = "{\"level\": 5, \"rank\": \"gold\"}";
	
	// Set user metadata
	FString UserID = TEXT("Player_001");
	FPubnubUserInputData UserInputData = FPubnubUserInputData::FromPubnubUserData(UserMetadata);
	PubnubClient->SetUserMetadataAsync(UserID, UserInputData);
}

// snippet.set_user_metadata_with_result
// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::SetUserMetadataWithResultSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set
	
	// Bind response delegate
	// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
	FOnPubnubSetUserMetadataResponse OnSetUserMetadataResponse;
	OnSetUserMetadataResponse.BindDynamic(this, &ASample_AppContext::OnSetUserMetadataResponse);

	// Create user metadata object
	FString UserID = TEXT("Player_002");
	FPubnubUserData UserMetadata;
	UserMetadata.UserName = "Player Two";
	UserMetadata.Status = "active";
	UserMetadata.Custom = "{\"inventory_slots\": 20, \"guild_id\": \"G2\"}";

	// Set user metadata with all available data included in response
	FPubnubGetMetadataInclude Include = FPubnubGetMetadataInclude::FromValue(true);
	FPubnubUserInputData UserInputData = FPubnubUserInputData::FromPubnubUserData(UserMetadata);
	PubnubClient->SetUserMetadataAsync(UserID, UserInputData, OnSetUserMetadataResponse, Include);
}

// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::OnSetUserMetadataResponse(FPubnubOperationResult Result, FPubnubUserData UserData)
{
	if(Result.Error)
	{
		UE_LOG(LogTemp, Error, TEXT("Failed to set user metadata. Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
	}
	else
	{
		UE_LOG(LogTemp, Log, TEXT("Successfully set user metadata. UserID: %s, Name: %s, Custom: %s, Status: %s"), *UserData.UserID, *UserData.UserName, *UserData.Custom, *UserData.Status);
	}
}

// snippet.set_user_metadata_with_lambda
// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::SetUserMetadataWithLambdaSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set

	// Bind lambda to response delegate
	FOnPubnubSetUserMetadataResponseNative OnSetUserMetadataResponse;
	OnSetUserMetadataResponse.BindLambda([](const FPubnubOperationResult& Result, const FPubnubUserData& UserData)
	{
		if(Result.Error)
		{
			UE_LOG(LogTemp, Error, TEXT("Failed to set user metadata. Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
		}
		else
		{
			UE_LOG(LogTemp, Log, TEXT("Successfully set user metadata. UserID: %s, Name: %s, Custom: %s, Status: %s"), *UserData.UserID, *UserData.UserName, *UserData.Custom, *UserData.Status);
		}
	});
	
	// Create user metadata object
	FString UserID = TEXT("Player_003");
	FPubnubUserData UserMetadata;
	UserMetadata.UserName = "Player Three";
	UserMetadata.Status = "inactive";
	UserMetadata.Custom = "{\"last_seen\": \"2024-01-01\"}";

	// Set user metadata with all available data included in response
	FPubnubGetMetadataInclude Include = FPubnubGetMetadataInclude::FromValue(true);
	FPubnubUserInputData UserInputData = FPubnubUserInputData::FromPubnubUserData(UserMetadata);
	PubnubClient->SetUserMetadataAsync(UserID, UserInputData, OnSetUserMetadataResponse, Include);
}

// snippet.set_user_metadata_raw
// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::SetUserMetadataRawSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set

	// Bind response delegate	
	// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
	FOnPubnubSetUserMetadataResponse OnSetUserMetadataResponse;
	OnSetUserMetadataResponse.BindDynamic(this, &ASample_AppContext::OnSetUserMetadataRawResponse);

	// Create user metadata object as a raw JSON string
	FString UserID = TEXT("Player_004");
	FString UserMetadataJson = R"({"name": "Player Four", "custom": {"class": "mage", "mana": 150}})";
	
	// Set user metadata with a raw include string
	FString Include = TEXT("custom");
	PubnubClient->SetUserMetadataRawAsync(UserID, UserMetadataJson, OnSetUserMetadataResponse, Include);
}

// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::OnSetUserMetadataRawResponse(FPubnubOperationResult Result, FPubnubUserData UserData)
{
	if(Result.Error)
	{
		UE_LOG(LogTemp, Error, TEXT("Failed to set user metadata (raw). Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
	}
	else
	{
		UE_LOG(LogTemp, Log, TEXT("Successfully set user metadata (raw). UserID: %s, Name: %s, Custom: %s"), *UserData.UserID, *UserData.UserName, *UserData.Custom);
	}
}

// snippet.update_user_metadata_iteratively
// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::UpdateUserMetadataIterativelySample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set
	
	// Create initial user metadata object
	FString UserID = TEXT("Player_005");
	FPubnubUserInputData UserInputData;
	UserInputData.UserName = "Player Two";
	UserInputData.Status = "active";
	UserInputData.Custom = "{\"inventory_slots\": 20, \"guild_id\": \"G2\"}";

	// Bind response delegate
	// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
	FOnPubnubSetUserMetadataResponse OnSetUserMetadataResponse;
	OnSetUserMetadataResponse.BindDynamic(this, &ASample_AppContext::OnInitialSetUserMetadataResponse);

	// Set initial user metadata
	FPubnubGetMetadataInclude Include = FPubnubGetMetadataInclude::FromValue(true);
	PubnubClient->SetUserMetadataAsync(UserID, UserInputData, OnSetUserMetadataResponse, Include);
}

// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::OnInitialSetUserMetadataResponse(FPubnubOperationResult Result, FPubnubUserData UserData)
{
	if(Result.Error)
	{
		UE_LOG(LogTemp, Error, TEXT("Failed to set initial user metadata. Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
		return;
	}
	
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show

	FString UserID = TEXT("Player_005");
	
	// Create updated version of user metadata object - change status to "inactive"
	FPubnubUserData UpdatedUserMetadata = UserData;
	UpdatedUserMetadata.Status = "inactive";

	// Bind response delegate
	// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
	FOnPubnubSetUserMetadataResponse OnSetUserMetadataResponse;
	OnSetUserMetadataResponse.BindDynamic(this, &ASample_AppContext::OnUpdateUserMetadataResponse);

	// Update user metadata
	FPubnubGetMetadataInclude Include;
	Include.IncludeStatus = true;
	FPubnubUserInputData UserInputData = FPubnubUserInputData::FromPubnubUserData(UpdatedUserMetadata);
	PubnubClient->SetUserMetadataAsync(UserID, UserInputData, OnSetUserMetadataResponse, Include);
}

// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::OnUpdateUserMetadataResponse(FPubnubOperationResult Result, FPubnubUserData UserData)
{
	if(Result.Error)
	{
		UE_LOG(LogTemp, Error, TEXT("Failed to update user metadata. Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
	}
	else
	{
		UE_LOG(LogTemp, Log, TEXT("Successfully updated user metadata. New status is: %s"), *UserData.Status);
	}
}

// snippet.get_all_user_metadata
// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::GetAllUserMetadataSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set

	// Bind response delegate
	// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
	FOnPubnubGetAllUserMetadataResponse OnGetAllUserMetadataResponse;
	OnGetAllUserMetadataResponse.BindDynamic(this, &ASample_AppContext::OnGetAllUserMetadataResponse_Simple);

	// Get all user metadata with a limit of 5
	PubnubClient->GetAllUserMetadataAsync(OnGetAllUserMetadataResponse, FPubnubGetAllInclude(), 5);
}

// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::OnGetAllUserMetadataResponse_Simple(FPubnubOperationResult Result, const TArray<FPubnubUserData>& UsersData, FPubnubPage Page, int TotalCount)
{
	if(Result.Error)
	{
		UE_LOG(LogTemp, Error, TEXT("Failed to get all user metadata. Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
	}
	else
	{
		UE_LOG(LogTemp, Log, TEXT("Successfully got all user metadata. Number of users: %d"), UsersData.Num());
		// Print all user metadata
		for (const FPubnubUserData& User : UsersData)
		{
			UE_LOG(LogTemp, Log, TEXT("- UserID: %s, Name: %s"), *User.UserID, *User.UserName);
		}
		if (!Page.Next.IsEmpty()) UE_LOG(LogTemp, Log, TEXT("Next Page: %s"), *Page.Next);
		if (!Page.Prev.IsEmpty()) UE_LOG(LogTemp, Log, TEXT("Previous Page: %s"), *Page.Prev);
	}
}

// snippet.get_all_user_metadata_with_settings
// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::GetAllUserMetadataWithSettingsSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set

	// Bind response delegate
	// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
	FOnPubnubGetAllUserMetadataResponse OnGetAllUserMetadataResponse;
	OnGetAllUserMetadataResponse.BindDynamic(this, &ASample_AppContext::OnGetAllUserMetadataResponse_WithSettings);

	// Create settings with includes and a filter
	FPubnubGetAllInclude Include;
	Include.IncludeCustom = true;
	Include.IncludeStatus = true;
	FString Filter = TEXT("status=='active'");
	int Limit = 10;
	
	// Get all user metadata with custom settings
	PubnubClient->GetAllUserMetadataAsync(OnGetAllUserMetadataResponse, Include, Limit, Filter);
}

// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::OnGetAllUserMetadataResponse_WithSettings(FPubnubOperationResult Result, const TArray<FPubnubUserData>& UsersData, FPubnubPage Page, int TotalCount)
{
	if(Result.Error)
	{
		UE_LOG(LogTemp, Error, TEXT("Failed to get all user metadata. Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
	}
	else
	{
		UE_LOG(LogTemp, Log, TEXT("Successfully got all user metadata with settings. Number of users: %d"), UsersData.Num());
		// Print all user metadata
		for (const FPubnubUserData& User : UsersData)
		{
			UE_LOG(LogTemp, Log, TEXT("- UserID: %s, Name: %s, Custom: %s, Status: %s"), *User.UserID, *User.UserName, *User.Custom, *User.Status);
		}
		if (!Page.Next.IsEmpty()) UE_LOG(LogTemp, Log, TEXT("Next Page: %s"), *Page.Next);
		if (!Page.Prev.IsEmpty()) UE_LOG(LogTemp, Log, TEXT("Previous Page: %s"), *Page.Prev);
	}
}

// snippet.get_all_user_metadata_with_all_includes
// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::GetAllUserMetadataWithAllIncludesSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set

	// Bind response delegate
	// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
	FOnPubnubGetAllUserMetadataResponse OnGetAllUserMetadataResponse;
	OnGetAllUserMetadataResponse.BindDynamic(this, &ASample_AppContext::OnGetAllUserMetadataResponse_WithAllIncludes);

	// Get all user metadata with all available data included
	FPubnubGetAllInclude Include = FPubnubGetAllInclude::FromValue(true);
	FString Filter = TEXT("status=='active' || status=='inactive'");
	FPubnubGetAllSort Sort;
	Sort.GetAllSort.Add(FPubnubGetAllSingleSort{EPubnubGetAllSortType::PGAST_Name, true});
	FString NextPage = "Mg"; // Page should be taken from previous response to get next or previous part of the objects
	FPubnubPage Page;
	Page.Next = NextPage;

	PubnubClient->GetAllUserMetadataAsync(OnGetAllUserMetadataResponse, Include, 100, Filter, Sort, Page);
}

// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::OnGetAllUserMetadataResponse_WithAllIncludes(FPubnubOperationResult Result, const TArray<FPubnubUserData>& UsersData, FPubnubPage Page, int TotalCount)
{
	if(Result.Error)
	{
		UE_LOG(LogTemp, Error, TEXT("Failed to get all user metadata. Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
	}
	else
	{
		UE_LOG(LogTemp, Log, TEXT("Successfully got all user metadata with all includes. Number of users: %d"), UsersData.Num());
		// Print all user metadata
		for (const FPubnubUserData& User : UsersData)
		{
			UE_LOG(LogTemp, Log, TEXT("- UserID: %s, Name: %s, Custom: %s, Status: %s"), *User.UserID, *User.UserName, *User.Custom, *User.Status);
		}
		if (!Page.Next.IsEmpty()) UE_LOG(LogTemp, Log, TEXT("Next Page: %s"), *Page.Next);
		if (!Page.Prev.IsEmpty()) UE_LOG(LogTemp, Log, TEXT("Previous Page: %s"), *Page.Prev);
	}
}

// snippet.get_all_user_metadata_with_lambda
// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::GetAllUserMetadataWithLambdaSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set

	// Bind lambda to response delegate
	// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
	FOnPubnubGetAllUserMetadataResponseNative OnGetAllUserMetadataResponse;
	OnGetAllUserMetadataResponse.BindLambda([](const FPubnubOperationResult& Result, const TArray<FPubnubUserData>& UsersData, FPubnubPage Page, int TotalCount)
	{
		if(Result.Error)
		{
			UE_LOG(LogTemp, Error, TEXT("Failed to get all user metadata. Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
		}
		else
		{
			UE_LOG(LogTemp, Log, TEXT("Successfully got all user metadata. Number of users: %d"), UsersData.Num());
			// Print all user metadata
			for (const FPubnubUserData& User : UsersData)
			{
				UE_LOG(LogTemp, Log, TEXT("- UserID: %s, Name: %s"), *User.UserID, *User.UserName);
			}
			if (!Page.Next.IsEmpty()) UE_LOG(LogTemp, Log, TEXT("Next Page: %s"), *Page.Next);
			if (!Page.Prev.IsEmpty()) UE_LOG(LogTemp, Log, TEXT("Previous Page: %s"), *Page.Prev);
		}
	});
	
	// Get all user metadata with a limit of 5
	PubnubClient->GetAllUserMetadataAsync(OnGetAllUserMetadataResponse, FPubnubGetAllInclude(), 5);
}

// snippet.get_all_user_metadata_raw
// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::GetAllUserMetadataRawSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set

	// Bind response delegate
	// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
	FOnPubnubGetAllUserMetadataResponse OnGetAllUserMetadataResponse;
	OnGetAllUserMetadataResponse.BindDynamic(this, &ASample_AppContext::OnGetAllUserMetadataRawResponse);

	// Create settings with includes and a filter
	FString Include = TEXT("custom,status");
	FString Filter = TEXT("status=='active'");
	FString Sort = TEXT("name:desc,status");
	int Limit = 10;
	
	// Get all user metadata with custom settings
	PubnubClient->GetAllUserMetadataRawAsync(OnGetAllUserMetadataResponse, Include, Limit, Filter, Sort);
}

// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::OnGetAllUserMetadataRawResponse(FPubnubOperationResult Result, const TArray<FPubnubUserData>& UsersData, FPubnubPage Page, int TotalCount)
{
	if(Result.Error)
	{
		UE_LOG(LogTemp, Error, TEXT("Failed to get all user metadata (raw). Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
	}
	else
	{
		UE_LOG(LogTemp, Log, TEXT("Successfully got all user metadata (raw). Number of users: %d"), UsersData.Num());
		// Print all user metadata
		for (const FPubnubUserData& User : UsersData)
		{
			UE_LOG(LogTemp, Log, TEXT("- UserID: %s, Name: %s, Custom: %s, Status: %s"), *User.UserID, *User.UserName, *User.Custom, *User.Status);
		}
		if (!Page.Next.IsEmpty()) UE_LOG(LogTemp, Log, TEXT("Next Page: %s"), *Page.Next);
		if (!Page.Prev.IsEmpty()) UE_LOG(LogTemp, Log, TEXT("Previous Page: %s"), *Page.Prev);
	}
}

// snippet.get_user_metadata
// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::GetUserMetadataSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set

	// Bind response delegate
	// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
	FOnPubnubGetUserMetadataResponse OnGetUserMetadataResponse;
	OnGetUserMetadataResponse.BindDynamic(this, &ASample_AppContext::OnGetUserMetadataResponse_Simple);

	// Get user metadata
	FString UserID = TEXT("Player_001");
	PubnubClient->GetUserMetadataAsync(UserID, OnGetUserMetadataResponse);
}

// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::OnGetUserMetadataResponse_Simple(FPubnubOperationResult Result, FPubnubUserData UserData)
{
	if(Result.Error)
	{
		UE_LOG(LogTemp, Error, TEXT("Failed to get user metadata. Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
	}
	else
	{
		UE_LOG(LogTemp, Log, TEXT("Successfully got user metadata. UserID: %s, Name: %s"), *UserData.UserID, *UserData.UserName);
	}
}

// snippet.get_user_metadata_with_all_includes
// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::GetUserMetadataWithAllIncludesSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set

	// Bind response delegate
	// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
	FOnPubnubGetUserMetadataResponse OnGetUserMetadataResponse;
	OnGetUserMetadataResponse.BindDynamic(this, &ASample_AppContext::OnGetUserMetadataResponse_WithAllIncludes);

	// Get user metadata with all available data included
	FString UserID = TEXT("Player_002");
	FPubnubGetMetadataInclude Include = FPubnubGetMetadataInclude::FromValue(true);
	PubnubClient->GetUserMetadataAsync(UserID, OnGetUserMetadataResponse, Include);
}

// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::OnGetUserMetadataResponse_WithAllIncludes(FPubnubOperationResult Result, FPubnubUserData UserData)
{
	if(Result.Error)
	{
		UE_LOG(LogTemp, Error, TEXT("Failed to get user metadata. Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
	}
	else
	{
		UE_LOG(LogTemp, Log, TEXT("Successfully got user metadata with all includes. UserID: %s, Name: %s, Custom: %s, Status: %s"), *UserData.UserID, *UserData.UserName, *UserData.Custom, *UserData.Status);
	}
}

// snippet.get_user_metadata_with_lambda
// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::GetUserMetadataWithLambdaSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set

	// Bind lambda to response delegate
	// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
	FOnPubnubGetUserMetadataResponseNative OnGetUserMetadataResponse;
	OnGetUserMetadataResponse.BindLambda([](const FPubnubOperationResult& Result, const FPubnubUserData& UserData)
	{
		if(Result.Error)
		{
			UE_LOG(LogTemp, Error, TEXT("Failed to get user metadata. Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
		}
		else
		{
			UE_LOG(LogTemp, Log, TEXT("Successfully got user metadata. UserID: %s, Name: %s"), *UserData.UserID, *UserData.UserName);
		}
	});
	
	// Get user metadata
	FString UserID = TEXT("Player_003");
	PubnubClient->GetUserMetadataAsync(UserID, OnGetUserMetadataResponse);
}

// snippet.get_user_metadata_raw
// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::GetUserMetadataRawSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set

	// Bind response delegate
	// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
	FOnPubnubGetUserMetadataResponse OnGetUserMetadataResponse;
	OnGetUserMetadataResponse.BindDynamic(this, &ASample_AppContext::OnGetUserMetadataRawResponse);

	// Get user metadata with raw include string
	FString UserID = TEXT("Player_004");
	FString Include = TEXT("custom,status");
	PubnubClient->GetUserMetadataRawAsync(UserID, OnGetUserMetadataResponse, Include);
}

// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::OnGetUserMetadataRawResponse(FPubnubOperationResult Result, FPubnubUserData UserData)
{
	if(Result.Error)
	{
		UE_LOG(LogTemp, Error, TEXT("Failed to get user metadata (raw). Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
	}
	else
	{
		UE_LOG(LogTemp, Log, TEXT("Successfully got user metadata (raw). UserID: %s, Name: %s, Custom: %s, Status: %s"), *UserData.UserID, *UserData.UserName, *UserData.Custom, *UserData.Status);
	}
}

// snippet.remove_user_metadata
// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::RemoveUserMetadataSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set
	
	// Remove user metadata
	FString UserToRemove = TEXT("Player_001");
	PubnubClient->RemoveUserMetadataAsync(UserToRemove);
}

// snippet.remove_user_metadata_with_result
// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::RemoveUserMetadataWithResultSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set

	// Bind response delegate
	// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
	FOnPubnubRemoveUserMetadataResponse OnRemoveUserMetadataResponse;
	OnRemoveUserMetadataResponse.BindDynamic(this, &ASample_AppContext::OnRemoveUserMetadataResponse);

	// Remove user metadata
	FString UserToRemove = TEXT("Player_002");
	PubnubClient->RemoveUserMetadataAsync(UserToRemove, OnRemoveUserMetadataResponse);
}

// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::OnRemoveUserMetadataResponse(FPubnubOperationResult Result)
{
	if(Result.Error)
	{
		UE_LOG(LogTemp, Error, TEXT("Failed to remove user metadata. Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
	}
	else
	{
		UE_LOG(LogTemp, Log, TEXT("Successfully removed user metadata."));
	}
}

// snippet.remove_user_metadata_with_result_lambda
// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::RemoveUserMetadataWithResultLambdaSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set

	// Bind lambda to response delegate
	FOnPubnubRemoveUserMetadataResponseNative OnRemoveUserMetadataResponse;
	OnRemoveUserMetadataResponse.BindLambda([](const FPubnubOperationResult& Result)
	{
		if(Result.Error)
		{
			UE_LOG(LogTemp, Error, TEXT("Failed to remove user metadata. Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
		}
		else
		{
			UE_LOG(LogTemp, Log, TEXT("Successfully removed user metadata."));
		}
	});
	
	// Remove user metadata
	FString UserToRemove = TEXT("Player_003");
	PubnubClient->RemoveUserMetadataAsync(UserToRemove, OnRemoveUserMetadataResponse);
}

// snippet.set_channel_metadata
// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::SetChannelMetadataSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set

	// Create channel metadata object
	FPubnubChannelData ChannelMetadata;
	ChannelMetadata.ChannelName = "General Chat";
	ChannelMetadata.Description = "Channel for all players to chat.";
	ChannelMetadata.Custom = "{\"topic\": \"welcomes\"}";
	
	// Set channel metadata
	FString Channel = "general-chat-channel";
	FPubnubChannelInputData ChannelInputData = FPubnubChannelInputData::FromPubnubChannelData(ChannelMetadata);
	PubnubClient->SetChannelMetadataAsync(Channel, ChannelInputData);
}

// snippet.set_channel_metadata_with_result
// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::SetChannelMetadataWithResultSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set
	
	// Bind response delegate
	// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
	FOnPubnubSetChannelMetadataResponse OnSetChannelMetadataResponse;
	OnSetChannelMetadataResponse.BindDynamic(this, &ASample_AppContext::OnSetChannelMetadataResponse);

	// Create channel metadata object
	FPubnubChannelInputData ChannelInputData;
	ChannelInputData.ChannelName = "Trade Chat";
	ChannelInputData.Status = "active";
	ChannelInputData.Custom = "{\"rules\": \"wts_wtt_only\"}";

	// Set channel metadata with all available data included in response
	FString Channel = "trade-chat-channel";
	FPubnubGetMetadataInclude Include = FPubnubGetMetadataInclude::FromValue(true);
	PubnubClient->SetChannelMetadataAsync(Channel, ChannelInputData, OnSetChannelMetadataResponse, Include);
}

// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::OnSetChannelMetadataResponse(FPubnubOperationResult Result, FPubnubChannelData ChannelData)
{
	if(Result.Error)
	{
		UE_LOG(LogTemp, Error, TEXT("Failed to set channel metadata. Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
	}
	else
	{
		UE_LOG(LogTemp, Log, TEXT("Successfully set channel metadata. ChannelID: %s, Name: %s, Custom: %s, Status: %s"), *ChannelData.ChannelID, *ChannelData.ChannelName, *ChannelData.Custom, *ChannelData.Status);
	}
}

// snippet.set_channel_metadata_with_lambda
// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::SetChannelMetadataWithLambdaSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set

	// Bind lambda to response delegate
	FOnPubnubSetChannelMetadataResponseNative OnSetChannelMetadataResponse;
	OnSetChannelMetadataResponse.BindLambda([](const FPubnubOperationResult& Result, const FPubnubChannelData& ChannelData)
	{
		if(Result.Error)
		{
			UE_LOG(LogTemp, Error, TEXT("Failed to set channel metadata. Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
		}
		else
		{
			UE_LOG(LogTemp, Log, TEXT("Successfully set channel metadata. ChannelID: %s, Name: %s, Custom: %s, Status: %s"), *ChannelData.ChannelID, *ChannelData.ChannelName, *ChannelData.Custom, *ChannelData.Status);
		}
	});
	
	// Create channel metadata object
	FPubnubChannelData ChannelMetadata;
	ChannelMetadata.ChannelName = "Guild Hall";
	ChannelMetadata.Status = "archived";
	ChannelMetadata.Custom = "{\"motd\": \"Raid tonight at 8!\"}";

	// Set channel metadata with all available data included in response
	FString Channel = "guild-hall-channel";
	FPubnubGetMetadataInclude Include = FPubnubGetMetadataInclude::FromValue(true);
	FPubnubChannelInputData ChannelInputData = FPubnubChannelInputData({ChannelMetadata.ChannelName, ChannelMetadata.Description, ChannelMetadata.Custom, ChannelMetadata.Status, ChannelMetadata.Type});
	PubnubClient->SetChannelMetadataAsync(Channel, ChannelInputData, OnSetChannelMetadataResponse, Include);
}

// snippet.set_channel_metadata_raw
// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::SetChannelMetadataRawSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set

	// Bind response delegate
	// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
	FOnPubnubSetChannelMetadataResponse OnSetChannelMetadataResponse;
	OnSetChannelMetadataResponse.BindDynamic(this, &ASample_AppContext::OnSetChannelMetadataRawResponse);

	// Create channel metadata object as a raw JSON string
	FString ChannelMetadataJson = R"({"name": "Secret Lair", "custom": {"max_players": 4, "password_protected": true}})";
	
	// Set channel metadata with a raw include string
	FString Channel = "secret-lair-channel";
	FString Include = TEXT("custom");
	PubnubClient->SetChannelMetadataRawAsync(Channel, ChannelMetadataJson, OnSetChannelMetadataResponse, Include);
}

// snippet.update_channel_metadata_iteratively
// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::UpdateChannelMetadataIterativelySample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set
	
	// Create initial channel metadata object
	FString ChannelID = TEXT("iterative-channel-update-test");
	FPubnubChannelData ChannelMetadata;
	ChannelMetadata.ChannelName = "Channel For Iterative Update";
	ChannelMetadata.Description = "This is the initial description.";
	ChannelMetadata.Custom = "{\"topic\": \"initial_topic\"}";

	// Bind response delegate
	// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
	FOnPubnubSetChannelMetadataResponse OnSetChannelMetadataResponse;
	OnSetChannelMetadataResponse.BindDynamic(this, &ASample_AppContext::OnInitialSetChannelMetadataResponse);

	// Set initial channel metadata 
	FPubnubChannelInputData ChannelInputData = FPubnubChannelInputData::FromPubnubChannelData(ChannelMetadata);
	PubnubClient->SetChannelMetadataAsync(ChannelID, ChannelInputData, OnSetChannelMetadataResponse);
}

// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::OnInitialSetChannelMetadataResponse(FPubnubOperationResult Result, FPubnubChannelData ChannelData)
{
	if(Result.Error)
	{
		UE_LOG(LogTemp, Error, TEXT("Failed to set initial channel metadata. Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
		return;
	}
	
	UE_LOG(LogTemp, Log, TEXT("Successfully set initial channel metadata. Description: %s"), *ChannelData.Description);

	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show

	// Use the ChannelID from the response
	FString ChannelID = ChannelData.ChannelID;
	
	// Create updated version of channel metadata object - change description only
	FPubnubChannelData UpdatedChannelMetadata;
	UpdatedChannelMetadata.Description = "This is the updated description!";

	// Bind response delegate
	// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
	FOnPubnubSetChannelMetadataResponse OnSetChannelMetadataResponse;
	OnSetChannelMetadataResponse.BindDynamic(this, &ASample_AppContext::OnUpdateChannelMetadataResponse);

	// Update channel metadata 
	FPubnubChannelInputData ChannelInputData = FPubnubChannelInputData::FromPubnubChannelData(UpdatedChannelMetadata);
	PubnubClient->SetChannelMetadataAsync(ChannelID, ChannelInputData, OnSetChannelMetadataResponse);
}

// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::OnUpdateChannelMetadataResponse(FPubnubOperationResult Result, FPubnubChannelData ChannelData)
{
	if(Result.Error)
	{
		UE_LOG(LogTemp, Error, TEXT("Failed to update channel metadata. Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
	}
	else
	{
		UE_LOG(LogTemp, Log, TEXT("Successfully updated channel metadata. New description is: '%s' and channel name is still: '%s'"), *ChannelData.Description, *ChannelData.ChannelName);
	}
}

// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::OnSetChannelMetadataRawResponse(FPubnubOperationResult Result, FPubnubChannelData ChannelData)
{
	if(Result.Error)
	{
		UE_LOG(LogTemp, Error, TEXT("Failed to set channel metadata (raw). Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
	}
	else
	{
		UE_LOG(LogTemp, Log, TEXT("Successfully set channel metadata (raw). ChannelID: %s, Name: %s, Custom: %s"), *ChannelData.ChannelID, *ChannelData.ChannelName, *ChannelData.Custom);
	}
}

// snippet.get_all_channel_metadata
// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::GetAllChannelMetadataSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set

	// Bind response delegate
	// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
	FOnPubnubGetAllChannelMetadataResponse OnGetAllChannelMetadataResponse;
	OnGetAllChannelMetadataResponse.BindDynamic(this, &ASample_AppContext::OnGetAllChannelMetadataResponse_Simple);

	// Get all channel metadata with a limit of 5
	PubnubClient->GetAllChannelMetadataAsync(OnGetAllChannelMetadataResponse, FPubnubGetAllInclude(), 5);
}

// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::OnGetAllChannelMetadataResponse_Simple(FPubnubOperationResult Result, const TArray<FPubnubChannelData>& ChannelsData, FPubnubPage Page, int TotalCount)
{
	if(Result.Error)
	{
		UE_LOG(LogTemp, Error, TEXT("Failed to get all channel metadata. Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
	}
	else
	{
		UE_LOG(LogTemp, Log, TEXT("Successfully got all channel metadata. Number of channels: %d"), ChannelsData.Num());
		// Print all channel metadata
		for (const FPubnubChannelData& Channel : ChannelsData)
		{
			UE_LOG(LogTemp, Log, TEXT("- ChannelID: %s, Name: %s"), *Channel.ChannelID, *Channel.ChannelName);
		}
		if (!Page.Next.IsEmpty()) UE_LOG(LogTemp, Log, TEXT("Next Page: %s"), *Page.Next);
		if (!Page.Prev.IsEmpty()) UE_LOG(LogTemp, Log, TEXT("Previous Page: %s"), *Page.Prev);
	}
}

// snippet.get_all_channel_metadata_with_settings
// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::GetAllChannelMetadataWithSettingsSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set

	// Bind response delegate
	// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
	FOnPubnubGetAllChannelMetadataResponse OnGetAllChannelMetadataResponse;
	OnGetAllChannelMetadataResponse.BindDynamic(this, &ASample_AppContext::OnGetAllChannelMetadataResponse_WithSettings);

	// Create settings with includes and a filter
	FPubnubGetAllInclude Include;
	Include.IncludeCustom = true;
	Include.IncludeStatus = true;
	FString Filter = TEXT("status=='active'");
	int Limit = 10;
	
	// Get all channel metadata with custom settings
	PubnubClient->GetAllChannelMetadataAsync(OnGetAllChannelMetadataResponse, Include, Limit, Filter);
}

// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::OnGetAllChannelMetadataResponse_WithSettings(FPubnubOperationResult Result, const TArray<FPubnubChannelData>& ChannelsData, FPubnubPage Page, int TotalCount)
{
	if(Result.Error)
	{
		UE_LOG(LogTemp, Error, TEXT("Failed to get all channel metadata. Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
	}
	else
	{
		UE_LOG(LogTemp, Log, TEXT("Successfully got all channel metadata with settings. Number of channels: %d"), ChannelsData.Num());
		// Print all channel metadata
		for (const FPubnubChannelData& Channel : ChannelsData)
		{
			UE_LOG(LogTemp, Log, TEXT("- ChannelID: %s, Name: %s, Custom: %s, Status: %s"), *Channel.ChannelID, *Channel.ChannelName, *Channel.Custom, *Channel.Status);
		}
		if (!Page.Next.IsEmpty()) UE_LOG(LogTemp, Log, TEXT("Next Page: %s"), *Page.Next);
		if (!Page.Prev.IsEmpty()) UE_LOG(LogTemp, Log, TEXT("Previous Page: %s"), *Page.Prev);
	}
}

// snippet.get_all_channel_metadata_with_all_includes
// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::GetAllChannelMetadataWithAllIncludesSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set

	// Bind response delegate
	// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
	FOnPubnubGetAllChannelMetadataResponse OnGetAllChannelMetadataResponse;
	OnGetAllChannelMetadataResponse.BindDynamic(this, &ASample_AppContext::OnGetAllChannelMetadataResponse_WithAllIncludes);

	// Get all channel metadata with all available data included
	FPubnubGetAllInclude Include = FPubnubGetAllInclude::FromValue(true);
	FString Filter = TEXT("status=='active' || status=='inactive'");
	FPubnubGetAllSort Sort;
	Sort.GetAllSort.Add(FPubnubGetAllSingleSort{EPubnubGetAllSortType::PGAST_Name, true});
	FString NextPage = "Mg"; // Page should be taken from previous response to get next or previous part of the objects
	FPubnubPage Page;
	Page.Next = NextPage;

	PubnubClient->GetAllChannelMetadataAsync(OnGetAllChannelMetadataResponse, Include, 100, Filter, Sort, Page);
}

// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::OnGetAllChannelMetadataResponse_WithAllIncludes(FPubnubOperationResult Result, const TArray<FPubnubChannelData>& ChannelsData, FPubnubPage Page, int TotalCount)
{
	if(Result.Error)
	{
		UE_LOG(LogTemp, Error, TEXT("Failed to get all channel metadata. Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
	}
	else
	{
		UE_LOG(LogTemp, Log, TEXT("Successfully got all channel metadata with all includes. Number of channels: %d"), ChannelsData.Num());
		// Print all channel metadata
		for (const FPubnubChannelData& Channel : ChannelsData)
		{
			UE_LOG(LogTemp, Log, TEXT("- ChannelID: %s, Name: %s, Custom: %s, Status: %s"), *Channel.ChannelID, *Channel.ChannelName, *Channel.Custom, *Channel.Status);
		}
		if (!Page.Next.IsEmpty()) UE_LOG(LogTemp, Log, TEXT("Next Page: %s"), *Page.Next);
		if (!Page.Prev.IsEmpty()) UE_LOG(LogTemp, Log, TEXT("Previous Page: %s"), *Page.Prev);
	}
}

// snippet.get_all_channel_metadata_with_lambda
// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::GetAllChannelMetadataWithLambdaSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set

	// Bind lambda to response delegate
	FOnPubnubGetAllChannelMetadataResponseNative OnGetAllChannelMetadataResponse;
	OnGetAllChannelMetadataResponse.BindLambda([](const FPubnubOperationResult& Result, const TArray<FPubnubChannelData>& ChannelsData, FPubnubPage Page, int TotalCount)
	{
		if(Result.Error)
		{
			UE_LOG(LogTemp, Error, TEXT("Failed to get all channel metadata. Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
		}
		else
		{
			UE_LOG(LogTemp, Log, TEXT("Successfully got all channel metadata. Number of channels: %d"), ChannelsData.Num());
			for (const FPubnubChannelData& Channel : ChannelsData)
			{
				UE_LOG(LogTemp, Log, TEXT("- ChannelID: %s, Name: %s"), *Channel.ChannelID, *Channel.ChannelName);
			}
			if (!Page.Next.IsEmpty()) UE_LOG(LogTemp, Log, TEXT("Next Page: %s"), *Page.Next);
			if (!Page.Prev.IsEmpty()) UE_LOG(LogTemp, Log, TEXT("Previous Page: %s"), *Page.Prev);
		}
	});
	
	// Get all channel metadata with a limit of 5
	PubnubClient->GetAllChannelMetadataAsync(OnGetAllChannelMetadataResponse, FPubnubGetAllInclude(), 5);
}

// snippet.get_all_channel_metadata_raw
// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::GetAllChannelMetadataRawSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set

	// Bind response delegate
	// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
	FOnPubnubGetAllChannelMetadataResponse OnGetAllChannelMetadataResponse;
	OnGetAllChannelMetadataResponse.BindDynamic(this, &ASample_AppContext::OnGetAllChannelMetadataRawResponse);

	// Create settings with includes and a filter
	FString Include = TEXT("custom,status");
	FString Filter = TEXT("status=='active'");
	FString Sort = TEXT("name:desc,status");
	int Limit = 10;
	
	// Get all channel metadata with custom settings
	PubnubClient->GetAllChannelMetadataRawAsync(OnGetAllChannelMetadataResponse, Include, Limit, Filter, Sort);
}

// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::OnGetAllChannelMetadataRawResponse(FPubnubOperationResult Result, const TArray<FPubnubChannelData>& ChannelsData, FPubnubPage Page, int TotalCount)
{
	if(Result.Error)
	{
		UE_LOG(LogTemp, Error, TEXT("Failed to get all channel metadata (raw). Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
	}
	else
	{
		UE_LOG(LogTemp, Log, TEXT("Successfully got all channel metadata (raw). Number of channels: %d"), ChannelsData.Num());
		// Print all channel metadata
		for (const FPubnubChannelData& Channel : ChannelsData)
		{
			UE_LOG(LogTemp, Log, TEXT("- ChannelID: %s, Name: %s, Custom: %s, Status: %s"), *Channel.ChannelID, *Channel.ChannelName, *Channel.Custom, *Channel.Status);
		}
		if (!Page.Next.IsEmpty()) UE_LOG(LogTemp, Log, TEXT("Next Page: %s"), *Page.Next);
		if (!Page.Prev.IsEmpty()) UE_LOG(LogTemp, Log, TEXT("Previous Page: %s"), *Page.Prev);
	}
}

// snippet.get_channel_metadata
// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::GetChannelMetadataSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set

	// Bind response delegate
	// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
	FOnPubnubGetChannelMetadataResponse OnGetChannelMetadataResponse;
	OnGetChannelMetadataResponse.BindDynamic(this, &ASample_AppContext::OnGetChannelMetadataResponse_Simple);

	// Get channel metadata
	FString Channel = TEXT("general-chat-channel");
	PubnubClient->GetChannelMetadataAsync(Channel, OnGetChannelMetadataResponse);
}

// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::OnGetChannelMetadataResponse_Simple(FPubnubOperationResult Result, FPubnubChannelData ChannelData)
{
	if(Result.Error)
	{
		UE_LOG(LogTemp, Error, TEXT("Failed to get channel metadata. Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
	}
	else
	{
		UE_LOG(LogTemp, Log, TEXT("Successfully got channel metadata. ChannelID: %s, Name: %s"), *ChannelData.ChannelID, *ChannelData.ChannelName);
	}
}

// snippet.get_channel_metadata_with_all_includes
// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::GetChannelMetadataWithAllIncludesSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set

	// Bind response delegate
	// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
	FOnPubnubGetChannelMetadataResponse OnGetChannelMetadataResponse;
	OnGetChannelMetadataResponse.BindDynamic(this, &ASample_AppContext::OnGetChannelMetadataResponse_WithAllIncludes);

	// Get channel metadata with all available data included
	FString Channel = TEXT("trade-chat-channel");
	FPubnubGetMetadataInclude Include = FPubnubGetMetadataInclude::FromValue(true);
	PubnubClient->GetChannelMetadataAsync(Channel, OnGetChannelMetadataResponse, Include);
}

// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::OnGetChannelMetadataResponse_WithAllIncludes(FPubnubOperationResult Result, FPubnubChannelData ChannelData)
{
	if(Result.Error)
	{
		UE_LOG(LogTemp, Error, TEXT("Failed to get channel metadata. Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
	}
	else
	{
		UE_LOG(LogTemp, Log, TEXT("Successfully got channel metadata with all includes. ChannelID: %s, Name: %s, Custom: %s, Status: %s"), *ChannelData.ChannelID, *ChannelData.ChannelName, *ChannelData.Custom, *ChannelData.Status);
	}
}

// snippet.get_channel_metadata_with_lambda
// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::GetChannelMetadataWithLambdaSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set

	// Bind lambda to response delegate
	FOnPubnubGetChannelMetadataResponseNative OnGetChannelMetadataResponse;
	OnGetChannelMetadataResponse.BindLambda([](const FPubnubOperationResult& Result, const FPubnubChannelData& ChannelData)
	{
		if(Result.Error)
		{
			UE_LOG(LogTemp, Error, TEXT("Failed to get channel metadata. Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
		}
		else
		{
			UE_LOG(LogTemp, Log, TEXT("Successfully got channel metadata. ChannelID: %s, Name: %s"), *ChannelData.ChannelID, *ChannelData.ChannelName);
		}
	});
	
	// Get channel metadata
	FString Channel = TEXT("guild-hall-channel");
	PubnubClient->GetChannelMetadataAsync(Channel, OnGetChannelMetadataResponse);
}

// snippet.get_channel_metadata_raw
// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::GetChannelMetadataRawSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set

	// Bind response delegate
	// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
	FOnPubnubGetChannelMetadataResponse OnGetChannelMetadataResponse;
	OnGetChannelMetadataResponse.BindDynamic(this, &ASample_AppContext::OnGetChannelMetadataRawResponse);

	// Get channel metadata with raw include string
	FString Channel = TEXT("trade-chat-channel");
	FString Include = TEXT("custom,status");
	PubnubClient->GetChannelMetadataRawAsync(Channel, OnGetChannelMetadataResponse, Include);
}

// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::OnGetChannelMetadataRawResponse(FPubnubOperationResult Result, FPubnubChannelData ChannelData)
{
	if(Result.Error)
	{
		UE_LOG(LogTemp, Error, TEXT("Failed to get channel metadata (raw). Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
	}
	else
	{
		UE_LOG(LogTemp, Log, TEXT("Successfully got channel metadata (raw). ChannelID: %s, Name: %s, Custom: %s, Status: %s"), *ChannelData.ChannelID, *ChannelData.ChannelName, *ChannelData.Custom, *ChannelData.Status);
	}
}

// snippet.remove_channel_metadata
// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::RemoveChannelMetadataSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set
	
	// Remove channel metadata
	FString Channel = TEXT("general-chat-channel");
	PubnubClient->RemoveChannelMetadataAsync(Channel);
}

// snippet.remove_channel_metadata_with_result
// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::RemoveChannelMetadataWithResultSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set

	// Bind response delegate
	// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
	FOnPubnubRemoveChannelMetadataResponse OnRemoveChannelMetadataResponse;
	OnRemoveChannelMetadataResponse.BindDynamic(this, &ASample_AppContext::OnRemoveChannelMetadataResponse);

	// Remove channel metadata
	FString Channel = TEXT("trade-chat-channel");
	PubnubClient->RemoveChannelMetadataAsync(Channel, OnRemoveChannelMetadataResponse);
}

// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::OnRemoveChannelMetadataResponse(FPubnubOperationResult Result)
{
	if(Result.Error)
	{
		UE_LOG(LogTemp, Error, TEXT("Failed to remove channel metadata. Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
	}
	else
	{
		UE_LOG(LogTemp, Log, TEXT("Successfully removed channel metadata."));
	}
}

// snippet.remove_channel_metadata_with_result_lambda
// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::RemoveChannelMetadataWithResultLambdaSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set

	// Bind lambda to response delegate
	FOnPubnubRemoveChannelMetadataResponseNative OnRemoveChannelMetadataResponse;
	OnRemoveChannelMetadataResponse.BindLambda([](const FPubnubOperationResult& Result)
	{
		if(Result.Error)
		{
			UE_LOG(LogTemp, Error, TEXT("Failed to remove channel metadata. Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
		}
		else
		{
			UE_LOG(LogTemp, Log, TEXT("Successfully removed channel metadata."));
		}
	});
	
	// Remove channel metadata
	FString Channel = TEXT("guild-hall-channel");
	PubnubClient->RemoveChannelMetadataAsync(Channel, OnRemoveChannelMetadataResponse);
}

// snippet.end

UPubnubClient* ASample_AppContext::GetPubnubClient()
{
	UGameInstance* GameInstance = UGameplayStatics::GetGameInstance(this);
	UPubnubSubsystem* PubnubSubsystem = GameInstance->GetSubsystem<UPubnubSubsystem>();
	
	//Get default PubnubClient - created automatically if PluginSettings are set to do so
	UPubnubClient* PubnubClient = PubnubSubsystem->GetPubnubClient(0);
	
	PubnubClient->SetUserID(TEXT("player_001"));
	return PubnubClient;
}
```

##### Set user metadata with result struct

###### Actor.h

```cpp
#include "PubnubClient.h"

// blueprint.w9k9he3e
UFUNCTION(BlueprintCallable, Category = "Pubnub|Samples|App Context")
void SetUserMetadataWithResultSample();

UFUNCTION()
void OnSetUserMetadataResponse(FPubnubOperationResult Result, FPubnubUserData UserData);
```

###### Actor.cpp

```cpp
// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::SetUserMetadataWithResultSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set
	
	// Bind response delegate
	// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
	FOnPubnubSetUserMetadataResponse OnSetUserMetadataResponse;
	OnSetUserMetadataResponse.BindDynamic(this, &ASample_AppContext::OnSetUserMetadataResponse);

	// Create user metadata object
	FString UserID = TEXT("Player_002");
	FPubnubUserData UserMetadata;
	UserMetadata.UserName = "Player Two";
	UserMetadata.Status = "active";
	UserMetadata.Custom = "{\"inventory_slots\": 20, \"guild_id\": \"G2\"}";

	// Set user metadata with all available data included in response
	FPubnubGetMetadataInclude Include = FPubnubGetMetadataInclude::FromValue(true);
	FPubnubUserInputData UserInputData = FPubnubUserInputData::FromPubnubUserData(UserMetadata);
	PubnubClient->SetUserMetadataAsync(UserID, UserInputData, OnSetUserMetadataResponse, Include);
}

// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::OnSetUserMetadataResponse(FPubnubOperationResult Result, FPubnubUserData UserData)
{
	if(Result.Error)
	{
		UE_LOG(LogTemp, Error, TEXT("Failed to set user metadata. Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
	}
	else
	{
		UE_LOG(LogTemp, Log, TEXT("Successfully set user metadata. UserID: %s, Name: %s, Custom: %s, Status: %s"), *UserData.UserID, *UserData.UserName, *UserData.Custom, *UserData.Status);
	}
}
```

##### Remove user metadata with result struct

###### Actor.h

```cpp
#include "PubnubClient.h"

UFUNCTION(BlueprintCallable, Category = "Pubnub|Samples|App Context")
void RemoveUserMetadataWithResultSample();

UFUNCTION()
void OnRemoveUserMetadataResponse(FPubnubOperationResult Result);
```

###### Actor.cpp

```cpp
// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::RemoveUserMetadataWithResultSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set

	// Bind response delegate
	// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
	FOnPubnubRemoveUserMetadataResponse OnRemoveUserMetadataResponse;
	OnRemoveUserMetadataResponse.BindDynamic(this, &ASample_AppContext::OnRemoveUserMetadataResponse);

	// Remove user metadata
	FString UserToRemove = TEXT("Player_002");
	PubnubClient->RemoveUserMetadataAsync(UserToRemove, OnRemoveUserMetadataResponse);
}

// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::OnRemoveUserMetadataResponse(FPubnubOperationResult Result)
{
	if(Result.Error)
	{
		UE_LOG(LogTemp, Error, TEXT("Failed to remove user metadata. Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
	}
	else
	{
		UE_LOG(LogTemp, Log, TEXT("Successfully removed user metadata."));
	}
}
```

### Set user metadata - UserMetadata entity

##### Available in entities

This method is available to use with the `UserMetadata` entity. For more information, refer to [UserMetadata](https://www.pubnub.com/docs/sdks/unreal/entities/user-metadata).

:::note Requires App Context add-on
This method requires the *App Context* add-on enabled for your key in the [Admin Portal](https://admin.pubnub.com/).
:::

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

Set metadata for a User in the database, optionally including the custom data object for each.

#### Method(s)

```cpp
UPubnubUserMetadataEntity* UserMetadataEntity = PubnubSubsystem->CreateUserMetadataEntity("user-id");

UserMetadataEntity->SetUserMetadata(
    FPubnubUserData UserMetadata,
    FOnSetUserMetadataResponse OnSetUserMetadataResponse,
    FPubnubGetMetadataInclude Include = FPubnubGetMetadataInclude()
);
```

| Parameter | Description |
| --- | --- |
| `UserMetadata`Type: [FPubnubUserData](#fpubnubuserdata) | The user metadata object to create. |
| `FOnSetUserMetadataResponse`Type: [FOnSetUserMetadataResponse](#fonsetusermetadataresponse) | The delegate for the operation's result. You can also use a native callback of the type [FOnSetUserMetadataResponseNative](#fonsetusermetadataresponsenative) to handle the result using a lambda. |
| `Include`Type: [FPubnubGetMetadataInclude](#fpubnubgetmetadatainclude) | List of property names to include in the response. |

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

#### Sample code

:::tip Reference code
Set up your Unreal project and follow the instructions in the lines marked with
ACTION REQUIRED
before running the code.
:::

###### C++

#### Actor.h

```cpp
#include "PubnubClient.h"
#include "Entities/PubnubUserMetadataEntity.h"
#include "Entities/PubnubSubscription.h"

UFUNCTION(BlueprintCallable, Category = "Pubnub|Samples|UserMetadataEntity")
void SetUserMetadataSample();
```

#### Actor.cpp

```cpp
// ACTION REQUIRED: Replace ASample_UserMetadataEntity with name of your Actor class
void ASample_UserMetadataEntity::SetUserMetadataSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	FString UserID = TEXT("Player_001");
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set

	// Create a user metadata entity
	UPubnubUserMetadataEntity* UserMetadataEntity = PubnubClient->CreateUserMetadataEntity(UserID);

	// Create user metadata object
	FPubnubUserInputData UserMetadata;
	UserMetadata.UserName = "Player One";
	UserMetadata.Email = "player.one@pubnub.com";
	UserMetadata.Custom = "{\"level\": 5, \"rank\": \"gold\"}";
	
	// Set user metadata using the user metadata entity
	UserMetadataEntity->SetUserMetadataAsync(UserMetadata);
}
```

#### Returns

```json
{
    "Uuid": "uuid-1",
    "Name": "John Doe",
    "Email": "john.doe@pubnub.com",
    "ExternalId": "",
    "ProfileUrl": "",
    "Custom": "",
    "Updated": "2020-06-17T16:28:14.060718Z"
}
```

#### Other examples

:::tip Reference code
Set up your Unreal project and follow the instructions in the lines marked with
ACTION REQUIRED
before running the code.
:::

##### Set user metadata with result

###### Actor.h

```cpp
#include "PubnubClient.h"
#include "Entities/PubnubUserMetadataEntity.h"
#include "Entities/PubnubSubscription.h"

UFUNCTION(BlueprintCallable, Category = "Pubnub|Samples|UserMetadataEntity")
void SetUserMetadataWithResultSample();

UFUNCTION()
void OnSetUserMetadataResponse(FPubnubOperationResult Result, FPubnubUserData UserData);
```

###### Actor.cpp

```cpp
// ACTION REQUIRED: Replace ASample_UserMetadataEntity with name of your Actor class
void ASample_UserMetadataEntity::SetUserMetadataWithResultSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	FString UserID = TEXT("Player_002");
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set

	// Create a user metadata entity
	UPubnubUserMetadataEntity* UserMetadataEntity = PubnubClient->CreateUserMetadataEntity(UserID);
	
	// Bind response delegate
	// ACTION REQUIRED: Replace ASample_UserMetadataEntity with name of your Actor class
	FOnPubnubSetUserMetadataResponse OnSetUserMetadataResponse;
	OnSetUserMetadataResponse.BindDynamic(this, &ASample_UserMetadataEntity::OnSetUserMetadataResponse);

	// Create user metadata object
	FPubnubUserInputData UserMetadata;
	UserMetadata.UserName = "Player Two";
	UserMetadata.Status = "active";
	UserMetadata.Custom = "{\"inventory_slots\": 20, \"guild_id\": \"G2\"}";

	// Set user metadata with all available data included in response using the user metadata entity
	FPubnubGetMetadataInclude Include = FPubnubGetMetadataInclude::FromValue(true);
	UserMetadataEntity->SetUserMetadataAsync(UserMetadata, OnSetUserMetadataResponse, Include);
}

// ACTION REQUIRED: Replace ASample_UserMetadataEntity with name of your Actor class
void ASample_UserMetadataEntity::OnSetUserMetadataResponse(FPubnubOperationResult Result, FPubnubUserData UserData)
{
	if(Result.Error)
	{
		UE_LOG(LogTemp, Error, TEXT("Failed to set user metadata. Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
	}
	else
	{
		UE_LOG(LogTemp, Log, TEXT("Successfully set user metadata. UserID: %s, Name: %s, Custom: %s, Status: %s"), *UserData.UserID, *UserData.UserName, *UserData.Custom, *UserData.Status);
	}
}
```

##### Set user metadata with lambda

###### Actor.h

```cpp
#include "PubnubClient.h"
#include "Entities/PubnubUserMetadataEntity.h"
#include "Entities/PubnubSubscription.h"

UFUNCTION(BlueprintCallable, Category = "Pubnub|Samples|UserMetadataEntity")
void SetUserMetadataWithLambdaSample();
```

###### Actor.cpp

```cpp
// ACTION REQUIRED: Replace ASample_UserMetadataEntity with name of your Actor class
void ASample_UserMetadataEntity::SetUserMetadataWithLambdaSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	FString UserID = TEXT("Player_003");
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set

	// Create a user metadata entity
	UPubnubUserMetadataEntity* UserMetadataEntity = PubnubClient->CreateUserMetadataEntity(UserID);

	// Bind lambda to response delegate
	FOnPubnubSetUserMetadataResponseNative OnSetUserMetadataResponse;
	OnSetUserMetadataResponse.BindLambda([](const FPubnubOperationResult& Result, const FPubnubUserData& UserData)
	{
		if(Result.Error)
		{
			UE_LOG(LogTemp, Error, TEXT("Failed to set user metadata. Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
		}
		else
		{
			UE_LOG(LogTemp, Log, TEXT("Successfully set user metadata. UserID: %s, Name: %s, Custom: %s, Status: %s"), *UserData.UserID, *UserData.UserName, *UserData.Custom, *UserData.Status);
		}
	});
	
	// Create user metadata object
	FPubnubUserInputData UserMetadata;
	UserMetadata.UserName = "Player Three";
	UserMetadata.Status = "inactive";
	UserMetadata.Custom = "{\"last_seen\": \"2024-01-01\"}";

	// Set user metadata with all available data included in response using the user metadata entity
	FPubnubGetMetadataInclude Include = FPubnubGetMetadataInclude::FromValue(true);
	UserMetadataEntity->SetUserMetadataAsync(UserMetadata, OnSetUserMetadataResponse, Include);
}
```

### Set user metadata - PubNub client

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

Set metadata for a User in the database, optionally including the custom data object for each. Use [FPubnubUserInputData](#fpubnubuserinputdata) for the metadata payload (supports ForceSet fields for partial updates).

#### Method(s)

```cpp
// Synchronous
FPubnubUserMetadataResult Result = PubnubClient->SetUserMetadata(
    FString User,
    FPubnubUserInputData UserMetadata,
    FPubnubGetMetadataInclude Include = FPubnubGetMetadataInclude()
);

// Asynchronous
PubnubClient->SetUserMetadataAsync(
    FString User,
    FPubnubUserInputData UserMetadata,
    FOnPubnubSetUserMetadataResponse OnSetUserMetadataResponse,
    FPubnubGetMetadataInclude Include = FPubnubGetMetadataInclude()
);
```

| Parameter | Description |
| --- | --- |
| `User` *Type: `FString` | The metadata ID for which to set the user object. Can't be empty. |
| `UserMetadata` *Type: [FPubnubUserInputData](#fpubnubuserinputdata) | The user metadata to set (input struct; supports ForceSet for partial updates). |
| `OnSetUserMetadataResponse`Type: [FOnPubnubSetUserMetadataResponse](#fonpubnubsetusermetadataresponse) | The delegate for the operation's result. You can also use a native callback of the type [FOnPubnubSetUserMetadataResponseNative](#fonpubnubsetusermetadataresponsenative) to handle the result using a lambda. |
| `Include`Type: [FPubnubGetMetadataInclude](#fpubnubgetmetadatainclude) | List of property names to include in the response. |

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

#### FPubnubUserInputData

Used for set operations. Contains the same fields as [FPubnubUserData](#fpubnubuserdata) (e.g. `UserName`, `Email`, `Custom`, etc.). When present, ForceSet-style fields control which properties are updated (partial updates).

#### FPubnubGetMetadataInclude

| Field | Type | Description |
| --- | --- | --- |
| `IncludeCustom` | `bool` | Whether to include the object's Custom field. |
| `IncludeStatus` | `bool` | Whether to include the object's Status field. |
| `IncludeType` | `bool` | Whether to include the object's Type field. |

#### Returns

* **Synchronous:** returns [FPubnubUserMetadataResult](#fpubnubusermetadataresult) (Result, UserData).
* **Asynchronous:** delegate [FOnPubnubSetUserMetadataResponse](#fonpubnubsetusermetadataresponse) receives (Result, UserData).

#### FOnPubnubSetUserMetadataResponse

| Field | Type | Description |
| --- | --- | --- |
| `Result` | [FPubnubOperationResult](https://www.pubnub.com/docs/sdks/unreal/api-reference/configuration#operation-result) | The result of the operation. |
| `UserData` | [FPubnubUserData](#fpubnubuserdata) | The user metadata object that was set. |

#### FOnPubnubSetUserMetadataResponseNative

| Field | Type | Description |
| --- | --- | --- |
| `Result` | [const FPubnubOperationResult&](https://www.pubnub.com/docs/sdks/unreal/api-reference/configuration#operation-result) | The result of the operation. |
| `UserData` | [const FPubnubUserData&](#fpubnubuserdata) | The user metadata object that was set. |

#### Sample code

:::tip Reference code
Set up your Unreal project and follow the instructions in the lines marked with
ACTION REQUIRED
before running the code.
:::

###### C++

#### Actor.h

```cpp
#include "PubnubClient.h"

// blueprint.3budd992
UFUNCTION(BlueprintCallable, Category = "Pubnub|Samples|App Context")
void SetUserMetadataSample();
```

#### Actor.cpp

```cpp
// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::SetUserMetadataSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set

	// Create user metadata object
	FPubnubUserData UserMetadata;
	UserMetadata.UserName = "Player One";
	UserMetadata.Email = "player.one@pubnub.com";
	UserMetadata.Custom = "{\"level\": 5, \"rank\": \"gold\"}";
	
	// Set user metadata
	FString UserID = TEXT("Player_001");
	FPubnubUserInputData UserInputData = FPubnubUserInputData::FromPubnubUserData(UserMetadata);
	PubnubClient->SetUserMetadataAsync(UserID, UserInputData);
}
```

###### Blueprint

#### Other examples

:::tip Reference code
Set up your Unreal project and follow the instructions in the lines marked with
ACTION REQUIRED
before running the code.
:::

##### Set metadata for a user with result

###### C++

###### Actor.h

```cpp
#include "PubnubClient.h"

// blueprint.w9k9he3e
UFUNCTION(BlueprintCallable, Category = "Pubnub|Samples|App Context")
void SetUserMetadataWithResultSample();

UFUNCTION()
void OnSetUserMetadataResponse(FPubnubOperationResult Result, FPubnubUserData UserData);
```

###### Actor.cpp

```cpp
// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::SetUserMetadataWithResultSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set
	
	// Bind response delegate
	// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
	FOnPubnubSetUserMetadataResponse OnSetUserMetadataResponse;
	OnSetUserMetadataResponse.BindDynamic(this, &ASample_AppContext::OnSetUserMetadataResponse);

	// Create user metadata object
	FString UserID = TEXT("Player_002");
	FPubnubUserData UserMetadata;
	UserMetadata.UserName = "Player Two";
	UserMetadata.Status = "active";
	UserMetadata.Custom = "{\"inventory_slots\": 20, \"guild_id\": \"G2\"}";

	// Set user metadata with all available data included in response
	FPubnubGetMetadataInclude Include = FPubnubGetMetadataInclude::FromValue(true);
	FPubnubUserInputData UserInputData = FPubnubUserInputData::FromPubnubUserData(UserMetadata);
	PubnubClient->SetUserMetadataAsync(UserID, UserInputData, OnSetUserMetadataResponse, Include);
}

// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::OnSetUserMetadataResponse(FPubnubOperationResult Result, FPubnubUserData UserData)
{
	if(Result.Error)
	{
		UE_LOG(LogTemp, Error, TEXT("Failed to set user metadata. Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
	}
	else
	{
		UE_LOG(LogTemp, Log, TEXT("Successfully set user metadata. UserID: %s, Name: %s, Custom: %s, Status: %s"), *UserData.UserID, *UserData.UserName, *UserData.Custom, *UserData.Status);
	}
}
```

###### Blueprint

##### Set metadata for a user with lambda

###### Actor.h

```cpp
#include "PubnubClient.h"

UFUNCTION(BlueprintCallable, Category = "Pubnub|Samples|App Context")
void SetUserMetadataWithLambdaSample();
```

###### Actor.cpp

```cpp
// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::SetUserMetadataWithLambdaSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set

	// Bind lambda to response delegate
	FOnPubnubSetUserMetadataResponseNative OnSetUserMetadataResponse;
	OnSetUserMetadataResponse.BindLambda([](const FPubnubOperationResult& Result, const FPubnubUserData& UserData)
	{
		if(Result.Error)
		{
			UE_LOG(LogTemp, Error, TEXT("Failed to set user metadata. Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
		}
		else
		{
			UE_LOG(LogTemp, Log, TEXT("Successfully set user metadata. UserID: %s, Name: %s, Custom: %s, Status: %s"), *UserData.UserID, *UserData.UserName, *UserData.Custom, *UserData.Status);
		}
	});
	
	// Create user metadata object
	FString UserID = TEXT("Player_003");
	FPubnubUserData UserMetadata;
	UserMetadata.UserName = "Player Three";
	UserMetadata.Status = "inactive";
	UserMetadata.Custom = "{\"last_seen\": \"2024-01-01\"}";

	// Set user metadata with all available data included in response
	FPubnubGetMetadataInclude Include = FPubnubGetMetadataInclude::FromValue(true);
	FPubnubUserInputData UserInputData = FPubnubUserInputData::FromPubnubUserData(UserMetadata);
	PubnubClient->SetUserMetadataAsync(UserID, UserInputData, OnSetUserMetadataResponse, Include);
}
```

##### Set metadata for a user raw

###### Actor.h

```cpp
#include "PubnubClient.h"

UFUNCTION(BlueprintCallable, Category = "Pubnub|Samples|App Context")
void SetUserMetadataRawSample();

UFUNCTION()
void OnSetUserMetadataRawResponse(FPubnubOperationResult Result, FPubnubUserData UserData);

//snippet.update_user_metadata_iteratively
UFUNCTION(BlueprintCallable, Category = "Pubnub|Samples|App Context")
void UpdateUserMetadataIterativelySample();
	
UFUNCTION()
void OnInitialSetUserMetadataResponse(FPubnubOperationResult Result, FPubnubUserData UserData);
	
UFUNCTION()
void OnUpdateUserMetadataResponse(FPubnubOperationResult Result, FPubnubUserData UserData);
```

###### Actor.cpp

```cpp
// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::SetUserMetadataRawSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set

	// Bind response delegate	
	// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
	FOnPubnubSetUserMetadataResponse OnSetUserMetadataResponse;
	OnSetUserMetadataResponse.BindDynamic(this, &ASample_AppContext::OnSetUserMetadataRawResponse);

	// Create user metadata object as a raw JSON string
	FString UserID = TEXT("Player_004");
	FString UserMetadataJson = R"({"name": "Player Four", "custom": {"class": "mage", "mana": 150}})";
	
	// Set user metadata with a raw include string
	FString Include = TEXT("custom");
	PubnubClient->SetUserMetadataRawAsync(UserID, UserMetadataJson, OnSetUserMetadataResponse, Include);
}

// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::OnSetUserMetadataRawResponse(FPubnubOperationResult Result, FPubnubUserData UserData)
{
	if(Result.Error)
	{
		UE_LOG(LogTemp, Error, TEXT("Failed to set user metadata (raw). Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
	}
	else
	{
		UE_LOG(LogTemp, Log, TEXT("Successfully set user metadata (raw). UserID: %s, Name: %s, Custom: %s"), *UserData.UserID, *UserData.UserName, *UserData.Custom);
	}
}
```

##### Iteratively update existing metadata

###### Actor.h

```cpp
#include "PubnubClient.h"

```

###### Actor.cpp

```cpp
// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::UpdateUserMetadataIterativelySample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set
	
	// Create initial user metadata object
	FString UserID = TEXT("Player_005");
	FPubnubUserInputData UserInputData;
	UserInputData.UserName = "Player Two";
	UserInputData.Status = "active";
	UserInputData.Custom = "{\"inventory_slots\": 20, \"guild_id\": \"G2\"}";

	// Bind response delegate
	// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
	FOnPubnubSetUserMetadataResponse OnSetUserMetadataResponse;
	OnSetUserMetadataResponse.BindDynamic(this, &ASample_AppContext::OnInitialSetUserMetadataResponse);

	// Set initial user metadata
	FPubnubGetMetadataInclude Include = FPubnubGetMetadataInclude::FromValue(true);
	PubnubClient->SetUserMetadataAsync(UserID, UserInputData, OnSetUserMetadataResponse, Include);
}

// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::OnInitialSetUserMetadataResponse(FPubnubOperationResult Result, FPubnubUserData UserData)
{
	if(Result.Error)
	{
		UE_LOG(LogTemp, Error, TEXT("Failed to set initial user metadata. Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
		return;
	}
	
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show

	FString UserID = TEXT("Player_005");
	
	// Create updated version of user metadata object - change status to "inactive"
	FPubnubUserData UpdatedUserMetadata = UserData;
	UpdatedUserMetadata.Status = "inactive";

	// Bind response delegate
	// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
	FOnPubnubSetUserMetadataResponse OnSetUserMetadataResponse;
	OnSetUserMetadataResponse.BindDynamic(this, &ASample_AppContext::OnUpdateUserMetadataResponse);

	// Update user metadata
	FPubnubGetMetadataInclude Include;
	Include.IncludeStatus = true;
	FPubnubUserInputData UserInputData = FPubnubUserInputData::FromPubnubUserData(UpdatedUserMetadata);
	PubnubClient->SetUserMetadataAsync(UserID, UserInputData, OnSetUserMetadataResponse, Include);
}

// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::OnUpdateUserMetadataResponse(FPubnubOperationResult Result, FPubnubUserData UserData)
{
	if(Result.Error)
	{
		UE_LOG(LogTemp, Error, TEXT("Failed to update user metadata. Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
	}
	else
	{
		UE_LOG(LogTemp, Log, TEXT("Successfully updated user metadata. New status is: %s"), *UserData.Status);
	}
}
```

### Remove user metadata - UserMetadata entity

##### Available in entities

This method is available to use with the `UserMetadata` entity. For more information, refer to [UserMetadata](https://www.pubnub.com/docs/sdks/unreal/entities/user-metadata).

:::note Requires App Context add-on
This method requires the *App Context* add-on enabled for your key in the [Admin Portal](https://admin.pubnub.com/).
:::

Removes the metadata from a specified user UUID.

#### Method(s)

```cpp
UPubnubUserMetadataEntity* UserMetadataEntity = PubnubSubsystem->CreateUserMetadataEntity("user-id");

UserMetadataEntity->RemoveUserMetadata(
    FOnRemoveUserMetadataResponse OnRemoveUserMetadataResponse
);
```

| Parameter | Description |
| --- | --- |
| `OnRemoveUserMetadataResponse`Type: [FOnRemoveUserMetadataResponse](#fonremoveusermetadataresponse) | The delegate for the operation's result. You can also use a native callback of the type [FOnRemoveUserMetadataResponseNative](#fonremoveusermetadataresponsenative) to handle the result using a lambda. |

#### Sample code

:::tip Reference code
Set up your Unreal project and follow the instructions in the lines marked with
ACTION REQUIRED
before running the code.
:::

###### C++

#### Actor.h

```cpp
#include "PubnubClient.h"
#include "Entities/PubnubUserMetadataEntity.h"
#include "Entities/PubnubSubscription.h"

UFUNCTION(BlueprintCallable, Category = "Pubnub|Samples|UserMetadataEntity")
void RemoveUserMetadataSample();
```

#### Actor.cpp

```cpp
// ACTION REQUIRED: Replace ASample_UserMetadataEntity with name of your Actor class
void ASample_UserMetadataEntity::RemoveUserMetadataSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	FString UserID = TEXT("Player_001");
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set

	// Create a user metadata entity
	UPubnubUserMetadataEntity* UserMetadataEntity = PubnubClient->CreateUserMetadataEntity(UserID);
	
	// Remove user metadata using the user metadata entity
	UserMetadataEntity->RemoveUserMetadataAsync();
}
```

#### Returns

This function is void, but the delegate returns the [FOnRemoveUserMetadataResponse](#fonremoveusermetadataresponse) struct.

#### Other examples

:::tip Reference code
Set up your Unreal project and follow the instructions in the lines marked with
ACTION REQUIRED
before running the code.
:::

##### Remove user metadata with result

###### Actor.h

```cpp
#include "PubnubClient.h"
#include "Entities/PubnubUserMetadataEntity.h"
#include "Entities/PubnubSubscription.h"

UFUNCTION(BlueprintCallable, Category = "Pubnub|Samples|UserMetadataEntity")
void RemoveUserMetadataWithResultSample();

UFUNCTION()
void OnRemoveUserMetadataResponse(FPubnubOperationResult Result);
```

###### Actor.cpp

```cpp
// ACTION REQUIRED: Replace ASample_UserMetadataEntity with name of your Actor class
void ASample_UserMetadataEntity::RemoveUserMetadataWithResultSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set

	// Create a user metadata entity
	FString UserToRemove = TEXT("Player_002");
	UPubnubUserMetadataEntity* UserMetadataEntity = PubnubClient->CreateUserMetadataEntity(UserToRemove);

	// Bind response delegate
	// ACTION REQUIRED: Replace ASample_UserMetadataEntity with name of your Actor class
	FOnPubnubRemoveUserMetadataResponse OnRemoveUserMetadataResponse;
	OnRemoveUserMetadataResponse.BindDynamic(this, &ASample_UserMetadataEntity::OnRemoveUserMetadataResponse);

	// Remove user metadata using the user metadata entity
	UserMetadataEntity->RemoveUserMetadataAsync(OnRemoveUserMetadataResponse);
}

// ACTION REQUIRED: Replace ASample_UserMetadataEntity with name of your Actor class
void ASample_UserMetadataEntity::OnRemoveUserMetadataResponse(FPubnubOperationResult Result)
{
	if(Result.Error)
	{
		UE_LOG(LogTemp, Error, TEXT("Failed to remove user metadata. Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
	}
	else
	{
		UE_LOG(LogTemp, Log, TEXT("Successfully removed user metadata."));
	}
}
```

##### Remove user metadata with lambda

###### Actor.h

```cpp
#include "PubnubClient.h"
#include "Entities/PubnubUserMetadataEntity.h"
#include "Entities/PubnubSubscription.h"

UFUNCTION(BlueprintCallable, Category = "Pubnub|Samples|UserMetadataEntity")
void RemoveUserMetadataWithResultLambdaSample();

	
```

###### Actor.cpp

```cpp
// ACTION REQUIRED: Replace ASample_UserMetadataEntity with name of your Actor class
void ASample_UserMetadataEntity::RemoveUserMetadataWithResultLambdaSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set

	// Create a user metadata entity
	FString UserToRemove = TEXT("Player_003");
	UPubnubUserMetadataEntity* UserMetadataEntity = PubnubClient->CreateUserMetadataEntity(UserToRemove);

	// Bind lambda to response delegate
	FOnPubnubRemoveUserMetadataResponseNative OnRemoveUserMetadataResponse;
	OnRemoveUserMetadataResponse.BindLambda([](const FPubnubOperationResult& Result)
	{
		if(Result.Error)
		{
			UE_LOG(LogTemp, Error, TEXT("Failed to remove user metadata. Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
		}
		else
		{
			UE_LOG(LogTemp, Log, TEXT("Successfully removed user metadata."));
		}
	});
	
	// Remove user metadata using the user metadata entity
	UserMetadataEntity->RemoveUserMetadataAsync(OnRemoveUserMetadataResponse);
}
```

### Remove user metadata - PubNub client

Removes the metadata from a specified user UUID.

#### Method(s)

```cpp
// Synchronous
FPubnubOperationResult Result = PubnubClient->RemoveUserMetadata(FString User);

// Asynchronous
PubnubClient->RemoveUserMetadataAsync(FString User, FOnPubnubRemoveUserMetadataResponse OnRemoveUserMetadataResponse);
```

| Parameter | Description |
| --- | --- |
| `User` *Type: `FString` | The metadata ID to delete from the user object. Can't be empty. |
| `OnRemoveUserMetadataResponse`Type: [FOnPubnubRemoveUserMetadataResponse](#fonpubnubremoveusermetadataresponse) | The delegate for the operation's result. You can also use a native callback of the type [FOnPubnubRemoveUserMetadataResponseNative](#fonpubnubremoveusermetadataresponsenative) to handle the result using a lambda. |

#### Sample code

:::tip Reference code
Set up your Unreal project and follow the instructions in the lines marked with
ACTION REQUIRED
before running the code.
:::

###### C++

#### Actor.h

```cpp
#include "PubnubClient.h"

// blueprint.ugk9ll3z
UFUNCTION(BlueprintCallable, Category = "Pubnub|Samples|App Context")
void RemoveUserMetadataSample();
```

#### Actor.cpp

```cpp
// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::RemoveUserMetadataSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set
	
	// Remove user metadata
	FString UserToRemove = TEXT("Player_001");
	PubnubClient->RemoveUserMetadataAsync(UserToRemove);
}
```

###### Blueprint

#### Returns

* **Synchronous:** returns [FPubnubOperationResult](https://www.pubnub.com/docs/sdks/unreal/api-reference/configuration#operation-result).
* **Asynchronous:** delegate [FOnPubnubRemoveUserMetadataResponse](#fonpubnubremoveusermetadataresponse) receives Result only.

##### FOnPubnubRemoveUserMetadataResponse

| Field | Type | Description |
| --- | --- | --- |
| `Result` | [FPubnubOperationResult](https://www.pubnub.com/docs/sdks/unreal/api-reference/configuration#operation-result) | The result of the operation. |

##### FOnPubnubRemoveUserMetadataResponseNative

| Field | Type | Description |
| --- | --- | --- |
| `Result` | [const FPubnubOperationResult&](https://www.pubnub.com/docs/sdks/unreal/api-reference/configuration#operation-result) | The result of the operation. |

#### Other examples

:::tip Reference code
Set up your Unreal project and follow the instructions in the lines marked with
ACTION REQUIRED
before running the code.
:::

##### Remove metadata for a user with result

###### Actor.h

```cpp
#include "PubnubClient.h"

UFUNCTION(BlueprintCallable, Category = "Pubnub|Samples|App Context")
void RemoveUserMetadataWithResultSample();

UFUNCTION()
void OnRemoveUserMetadataResponse(FPubnubOperationResult Result);
```

###### Actor.cpp

```cpp
// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::RemoveUserMetadataWithResultSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set

	// Bind response delegate
	// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
	FOnPubnubRemoveUserMetadataResponse OnRemoveUserMetadataResponse;
	OnRemoveUserMetadataResponse.BindDynamic(this, &ASample_AppContext::OnRemoveUserMetadataResponse);

	// Remove user metadata
	FString UserToRemove = TEXT("Player_002");
	PubnubClient->RemoveUserMetadataAsync(UserToRemove, OnRemoveUserMetadataResponse);
}

// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::OnRemoveUserMetadataResponse(FPubnubOperationResult Result)
{
	if(Result.Error)
	{
		UE_LOG(LogTemp, Error, TEXT("Failed to remove user metadata. Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
	}
	else
	{
		UE_LOG(LogTemp, Log, TEXT("Successfully removed user metadata."));
	}
}
```

##### Remove metadata for a user with lambda

###### Actor.h

```cpp
#include "PubnubClient.h"

UFUNCTION(BlueprintCallable, Category = "Pubnub|Samples|App Context")
void RemoveUserMetadataWithResultLambdaSample();
```

###### Actor.cpp

```cpp
// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::RemoveUserMetadataWithResultLambdaSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set

	// Bind lambda to response delegate
	FOnPubnubRemoveUserMetadataResponseNative OnRemoveUserMetadataResponse;
	OnRemoveUserMetadataResponse.BindLambda([](const FPubnubOperationResult& Result)
	{
		if(Result.Error)
		{
			UE_LOG(LogTemp, Error, TEXT("Failed to remove user metadata. Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
		}
		else
		{
			UE_LOG(LogTemp, Log, TEXT("Successfully removed user metadata."));
		}
	});
	
	// Remove user metadata
	FString UserToRemove = TEXT("Player_003");
	PubnubClient->RemoveUserMetadataAsync(UserToRemove, OnRemoveUserMetadataResponse);
}
```

## Channel

### Get metadata for all channels

Retrieve channel metadata in pages. The list includes the Custom object if requested.

#### Method(s)

:::tip Method variants
You can also call the `GetAllChannelMetadataRaw` variant of this method which takes String values for `Include` and `Sort` instead of the `FPubnubGetAllInclude` and `FPubnubGetAllSort` structs.
:::

```cpp
// Synchronous
FPubnubGetAllChannelMetadataResult Result = PubnubClient->GetAllChannelMetadata(
    FPubnubGetAllInclude Include = FPubnubGetAllInclude(),
    int Limit = 100,
    FString Filter = "",
    FPubnubGetAllSort Sort = FPubnubGetAllSort(),
    FPubnubPage Page = FPubnubPage()
);

// Asynchronous
PubnubClient->GetAllChannelMetadataAsync(
    FOnPubnubGetAllChannelMetadataResponse OnGetAllChannelMetadataResponse,
    FPubnubGetAllInclude Include = FPubnubGetAllInclude(),
    int Limit = 100,
    FString Filter = "",
    FPubnubGetAllSort Sort = FPubnubGetAllSort(),
    FPubnubPage Page = FPubnubPage()
);
```

| Parameter | Description |
| --- | --- |
| `OnGetAllChannelMetadataResponse`Type: [FOnPubnubGetAllChannelMetadataResponse](#fonpubnubgetallchannelmetadataresponse) | The delegate for the operation's result. You can also use a native callback of the type [FOnPubnubGetAllChannelMetadataResponseNative](#fonpubnubgetallchannelmetadataresponsenative) to handle the result using a lambda. |
| `Include`Type: [FPubnubGetAllInclude](#fpubnubgetallinclude) | A list of property names to include in the response. |
| `Limit`Type: int | Number of objects to return. Default/Max: 100. |
| `Filter`Type: `FString` | Filter expression. Only matching objects are returned. See filtering. |
| `Sort`Type: [FPubnubGetAllSort](#fpubnubgetallsort) | Sort by id, name, updated with asc/desc for sort direction (for example, `{name: 'asc'}`). |
| `Page`Type: [FPubnubPage](#fpubnubpage) | Cursor-based pagination. Use `Page.Next` and `Page.Prev` to request the next or previous page. |

#### Sample code

:::tip Reference code
Set up your Unreal project and follow the instructions in the lines marked with
ACTION REQUIRED
before running the code.
:::

###### C++

#### Actor.h

```cpp
#include "PubnubClient.h"

// blueprint.s3xd4eok
UFUNCTION(BlueprintCallable, Category = "Pubnub|Samples|App Context")
void GetAllChannelMetadataSample();

UFUNCTION()
void OnGetAllChannelMetadataResponse_Simple(FPubnubOperationResult Result, const TArray<FPubnubChannelData>& ChannelsData, FPubnubPage Page, int TotalCount);
```

#### Actor.cpp

```cpp
// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::GetAllChannelMetadataSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set

	// Bind response delegate
	// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
	FOnPubnubGetAllChannelMetadataResponse OnGetAllChannelMetadataResponse;
	OnGetAllChannelMetadataResponse.BindDynamic(this, &ASample_AppContext::OnGetAllChannelMetadataResponse_Simple);

	// Get all channel metadata with a limit of 5
	PubnubClient->GetAllChannelMetadataAsync(OnGetAllChannelMetadataResponse, FPubnubGetAllInclude(), 5);
}

// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::OnGetAllChannelMetadataResponse_Simple(FPubnubOperationResult Result, const TArray<FPubnubChannelData>& ChannelsData, FPubnubPage Page, int TotalCount)
{
	if(Result.Error)
	{
		UE_LOG(LogTemp, Error, TEXT("Failed to get all channel metadata. Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
	}
	else
	{
		UE_LOG(LogTemp, Log, TEXT("Successfully got all channel metadata. Number of channels: %d"), ChannelsData.Num());
		// Print all channel metadata
		for (const FPubnubChannelData& Channel : ChannelsData)
		{
			UE_LOG(LogTemp, Log, TEXT("- ChannelID: %s, Name: %s"), *Channel.ChannelID, *Channel.ChannelName);
		}
		if (!Page.Next.IsEmpty()) UE_LOG(LogTemp, Log, TEXT("Next Page: %s"), *Page.Next);
		if (!Page.Prev.IsEmpty()) UE_LOG(LogTemp, Log, TEXT("Previous Page: %s"), *Page.Prev);
	}
}
```

###### Blueprint

#### Returns

* **Synchronous:** returns [FPubnubGetAllChannelMetadataResult](#fpubnubgetallchannelmetadataresult) (Result, ChannelsData, Page, TotalCount).
* **Asynchronous:** delegate [FOnPubnubGetAllChannelMetadataResponse](#fonpubnubgetallchannelmetadataresponse) receives (Result, ChannelsData, Page, TotalCount).

##### FPubnubGetAllChannelMetadataResult

| Field | Type | Description |
| --- | --- | --- |
| `Result` | [FPubnubOperationResult](https://www.pubnub.com/docs/sdks/unreal/api-reference/configuration#operation-result) | The result of the operation. |
| `ChannelsData` | `TArray<FPubnubChannelData>` | Array of [FPubnubChannelData](#fpubnubchanneldata) structs which are the channels with their associated metadata. |
| `Page` | [FPubnubPage](#fpubnubpage) | Pagination cursor (Next, Prev) for requesting the next or previous page. |
| `TotalCount` | `int` | Total number of channels matching the request (when requested). |

##### FOnPubnubGetAllChannelMetadataResponse

| Field | Type | Description |
| --- | --- | --- |
| `Result` | [const FPubnubOperationResult&](https://www.pubnub.com/docs/sdks/unreal/api-reference/configuration#operation-result) | The result of the operation. |
| `ChannelsData` | [const TArray<FPubnubChannelData>&](#fpubnubchanneldata) | Array of [FPubnubChannelData](#fpubnubchanneldata) structs which are the channels with their associated metadata. |
| `Page` | [FPubnubPage](#fpubnubpage) | Pagination cursor (Next, Prev) for requesting the next or previous page. |
| `TotalCount` | `int` | Total number of channels matching the request (when requested). |

##### FPubnubChannelData

| Field | Type | Description |
| --- | --- | --- |
| `ChannelID` | `FString` | ID of the channel. |
| `ChannelName` | `FString` | Name of the channel. |
| `Description` | `FString` | Additional description of the channel. |
| `Custom` | `FString` | Custom JSON values. Can be strings, numbers, or booleans. Filtering by Custom isn’t supported. |
| `Status` | `FString` | Channel status. Max 50 characters. |
| `Type` | `FString` | Channel type. Max 50 characters. |
| `Updated` | `FString` | The date when the channel's metadata was last updated. |
| `ETag` | `FString` | Version identifier of the user's metadata. |

##### FOnPubnubGetAllChannelMetadataResponseNative

| Field | Type | Description |
| --- | --- | --- |
| `Result` | [const FPubnubOperationResult&](https://www.pubnub.com/docs/sdks/unreal/api-reference/configuration#operation-result) | The result of the operation. |
| `ChannelsData` | [const TArray<FPubnubChannelData>&](#fpubnubchanneldata) | Array of [FPubnubChannelData](#fpubnubchanneldata) structs which are the channels with their associated metadata. |
| `Page` | [const FPubnubPage&](#fpubnubpage) | Pagination cursor (Next, Prev) for requesting the next or previous page. |
| `TotalCount` | `int` | Total number of channels matching the request (when requested). |

#### Other examples

:::tip Reference code
Set up your Unreal project and follow the instructions in the lines marked with
ACTION REQUIRED
before running the code.
:::

##### Get metadata for all channels with settings

###### Actor.h

```cpp
#include "PubnubClient.h"

UFUNCTION(BlueprintCallable, Category = "Pubnub|Samples|App Context")
void GetAllChannelMetadataWithSettingsSample();

UFUNCTION()
void OnGetAllChannelMetadataResponse_WithSettings(FPubnubOperationResult Result, const TArray<FPubnubChannelData>& ChannelsData, FPubnubPage Page, int TotalCount);
```

###### Actor.cpp

```cpp
// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::GetAllChannelMetadataWithSettingsSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set

	// Bind response delegate
	// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
	FOnPubnubGetAllChannelMetadataResponse OnGetAllChannelMetadataResponse;
	OnGetAllChannelMetadataResponse.BindDynamic(this, &ASample_AppContext::OnGetAllChannelMetadataResponse_WithSettings);

	// Create settings with includes and a filter
	FPubnubGetAllInclude Include;
	Include.IncludeCustom = true;
	Include.IncludeStatus = true;
	FString Filter = TEXT("status=='active'");
	int Limit = 10;
	
	// Get all channel metadata with custom settings
	PubnubClient->GetAllChannelMetadataAsync(OnGetAllChannelMetadataResponse, Include, Limit, Filter);
}

// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::OnGetAllChannelMetadataResponse_WithSettings(FPubnubOperationResult Result, const TArray<FPubnubChannelData>& ChannelsData, FPubnubPage Page, int TotalCount)
{
	if(Result.Error)
	{
		UE_LOG(LogTemp, Error, TEXT("Failed to get all channel metadata. Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
	}
	else
	{
		UE_LOG(LogTemp, Log, TEXT("Successfully got all channel metadata with settings. Number of channels: %d"), ChannelsData.Num());
		// Print all channel metadata
		for (const FPubnubChannelData& Channel : ChannelsData)
		{
			UE_LOG(LogTemp, Log, TEXT("- ChannelID: %s, Name: %s, Custom: %s, Status: %s"), *Channel.ChannelID, *Channel.ChannelName, *Channel.Custom, *Channel.Status);
		}
		if (!Page.Next.IsEmpty()) UE_LOG(LogTemp, Log, TEXT("Next Page: %s"), *Page.Next);
		if (!Page.Prev.IsEmpty()) UE_LOG(LogTemp, Log, TEXT("Previous Page: %s"), *Page.Prev);
	}
}
```

##### Get metadata for all channels with all includes

###### Actor.h

```cpp
#include "PubnubClient.h"

UFUNCTION(BlueprintCallable, Category = "Pubnub|Samples|App Context")
void GetAllChannelMetadataWithAllIncludesSample();

UFUNCTION()
void OnGetAllChannelMetadataResponse_WithAllIncludes(FPubnubOperationResult Result, const TArray<FPubnubChannelData>& ChannelsData, FPubnubPage Page, int TotalCount);
```

###### Actor.cpp

```cpp
// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::GetAllChannelMetadataWithAllIncludesSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set

	// Bind response delegate
	// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
	FOnPubnubGetAllChannelMetadataResponse OnGetAllChannelMetadataResponse;
	OnGetAllChannelMetadataResponse.BindDynamic(this, &ASample_AppContext::OnGetAllChannelMetadataResponse_WithAllIncludes);

	// Get all channel metadata with all available data included
	FPubnubGetAllInclude Include = FPubnubGetAllInclude::FromValue(true);
	FString Filter = TEXT("status=='active' || status=='inactive'");
	FPubnubGetAllSort Sort;
	Sort.GetAllSort.Add(FPubnubGetAllSingleSort{EPubnubGetAllSortType::PGAST_Name, true});
	FString NextPage = "Mg"; // Page should be taken from previous response to get next or previous part of the objects
	FPubnubPage Page;
	Page.Next = NextPage;

	PubnubClient->GetAllChannelMetadataAsync(OnGetAllChannelMetadataResponse, Include, 100, Filter, Sort, Page);
}

// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::OnGetAllChannelMetadataResponse_WithAllIncludes(FPubnubOperationResult Result, const TArray<FPubnubChannelData>& ChannelsData, FPubnubPage Page, int TotalCount)
{
	if(Result.Error)
	{
		UE_LOG(LogTemp, Error, TEXT("Failed to get all channel metadata. Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
	}
	else
	{
		UE_LOG(LogTemp, Log, TEXT("Successfully got all channel metadata with all includes. Number of channels: %d"), ChannelsData.Num());
		// Print all channel metadata
		for (const FPubnubChannelData& Channel : ChannelsData)
		{
			UE_LOG(LogTemp, Log, TEXT("- ChannelID: %s, Name: %s, Custom: %s, Status: %s"), *Channel.ChannelID, *Channel.ChannelName, *Channel.Custom, *Channel.Status);
		}
		if (!Page.Next.IsEmpty()) UE_LOG(LogTemp, Log, TEXT("Next Page: %s"), *Page.Next);
		if (!Page.Prev.IsEmpty()) UE_LOG(LogTemp, Log, TEXT("Previous Page: %s"), *Page.Prev);
	}
}
```

##### Get metadata for all channels with lambda

###### Actor.h

```cpp
#include "PubnubClient.h"

UFUNCTION(BlueprintCallable, Category = "Pubnub|Samples|App Context")
void GetAllChannelMetadataWithLambdaSample();
```

###### Actor.cpp

```cpp
// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::GetAllChannelMetadataWithLambdaSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set

	// Bind lambda to response delegate
	FOnPubnubGetAllChannelMetadataResponseNative OnGetAllChannelMetadataResponse;
	OnGetAllChannelMetadataResponse.BindLambda([](const FPubnubOperationResult& Result, const TArray<FPubnubChannelData>& ChannelsData, FPubnubPage Page, int TotalCount)
	{
		if(Result.Error)
		{
			UE_LOG(LogTemp, Error, TEXT("Failed to get all channel metadata. Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
		}
		else
		{
			UE_LOG(LogTemp, Log, TEXT("Successfully got all channel metadata. Number of channels: %d"), ChannelsData.Num());
			for (const FPubnubChannelData& Channel : ChannelsData)
			{
				UE_LOG(LogTemp, Log, TEXT("- ChannelID: %s, Name: %s"), *Channel.ChannelID, *Channel.ChannelName);
			}
			if (!Page.Next.IsEmpty()) UE_LOG(LogTemp, Log, TEXT("Next Page: %s"), *Page.Next);
			if (!Page.Prev.IsEmpty()) UE_LOG(LogTemp, Log, TEXT("Previous Page: %s"), *Page.Prev);
		}
	});
	
	// Get all channel metadata with a limit of 5
	PubnubClient->GetAllChannelMetadataAsync(OnGetAllChannelMetadataResponse, FPubnubGetAllInclude(), 5);
}
```

##### Get metadata for all channels raw

###### Actor.h

```cpp
#include "PubnubClient.h"

UFUNCTION(BlueprintCallable, Category = "Pubnub|Samples|App Context")
void GetAllChannelMetadataRawSample();

UFUNCTION()
void OnGetAllChannelMetadataRawResponse(FPubnubOperationResult Result, const TArray<FPubnubChannelData>& ChannelsData, FPubnubPage Page, int TotalCount);
```

###### Actor.cpp

```cpp
// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::GetAllChannelMetadataRawSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set

	// Bind response delegate
	// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
	FOnPubnubGetAllChannelMetadataResponse OnGetAllChannelMetadataResponse;
	OnGetAllChannelMetadataResponse.BindDynamic(this, &ASample_AppContext::OnGetAllChannelMetadataRawResponse);

	// Create settings with includes and a filter
	FString Include = TEXT("custom,status");
	FString Filter = TEXT("status=='active'");
	FString Sort = TEXT("name:desc,status");
	int Limit = 10;
	
	// Get all channel metadata with custom settings
	PubnubClient->GetAllChannelMetadataRawAsync(OnGetAllChannelMetadataResponse, Include, Limit, Filter, Sort);
}

// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::OnGetAllChannelMetadataRawResponse(FPubnubOperationResult Result, const TArray<FPubnubChannelData>& ChannelsData, FPubnubPage Page, int TotalCount)
{
	if(Result.Error)
	{
		UE_LOG(LogTemp, Error, TEXT("Failed to get all channel metadata (raw). Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
	}
	else
	{
		UE_LOG(LogTemp, Log, TEXT("Successfully got all channel metadata (raw). Number of channels: %d"), ChannelsData.Num());
		// Print all channel metadata
		for (const FPubnubChannelData& Channel : ChannelsData)
		{
			UE_LOG(LogTemp, Log, TEXT("- ChannelID: %s, Name: %s, Custom: %s, Status: %s"), *Channel.ChannelID, *Channel.ChannelName, *Channel.Custom, *Channel.Status);
		}
		if (!Page.Next.IsEmpty()) UE_LOG(LogTemp, Log, TEXT("Next Page: %s"), *Page.Next);
		if (!Page.Prev.IsEmpty()) UE_LOG(LogTemp, Log, TEXT("Previous Page: %s"), *Page.Prev);
	}
}
```

### Get channel metadata - ChannelMetadata entity

##### Available in entities

This method is available to use with the `ChannelMetadata` entity. For more information, refer to [ChannelMetadata](https://www.pubnub.com/docs/sdks/unreal/entities/channel-metadata).

:::note Requires App Context add-on
This method requires the *App Context* add-on enabled for your key in the [Admin Portal](https://admin.pubnub.com/).
:::

Retrieve metadata for a channel. You can include the Custom object.

#### Method(s)

```cpp
UPubnubChannelMetadataEntity* ChannelMetadataEntity = PubnubSubsystem->CreateChannelMetadataEntity("channel-id");

ChannelMetadataEntity->GetChannelMetadata(
    FOnGetChannelMetadataResponse OnGetChannelMetadataResponse,
    FPubnubGetMetadataInclude Include = FPubnubGetMetadataInclude()
);
```

| Parameter | Description |
| --- | --- |
| `OnGetChannelMetadataResponse` *Type: [FOnGetChannelMetadataResponse](#fongetchannelmetadataresponse) | The delegate for the operation's result. You can also use a native callback of the type [FOnGetChannelMetadataResponseNative](#fongetchannelmetadataresponsenative) to handle the result using a lambda. |
| `Include`Type: [FPubnubGetMetadataInclude](#fpubnubgetmetadatainclude) | List of property names to include in the response. |

#### Sample code

:::tip Reference code
Set up your Unreal project and follow the instructions in the lines marked with
ACTION REQUIRED
before running the code.
:::

###### C++

#### Actor.h

```cpp
#include "PubnubClient.h"
#include "Entities/PubnubChannelMetadataEntity.h"
#include "Entities/PubnubSubscription.h"

UFUNCTION(BlueprintCallable, Category = "Pubnub|Samples|ChannelMetadataEntity")
void GetChannelMetadataSample();

UFUNCTION()
void OnGetChannelMetadataResponse_Simple(FPubnubOperationResult Result, FPubnubChannelData ChannelData);
```

#### Actor.cpp

```cpp
// ACTION REQUIRED: Replace ASample_ChannelMetadataEntity with name of your Actor class
void ASample_ChannelMetadataEntity::GetChannelMetadataSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set

	// Create a channel metadata entity
	FString ChannelName = TEXT("general-chat-channel");
	UPubnubChannelMetadataEntity* ChannelMetadataEntity = PubnubClient->CreateChannelMetadataEntity(ChannelName);

	// Bind response delegate
	// ACTION REQUIRED: Replace ASample_ChannelMetadataEntity with name of your Actor class
	FOnPubnubGetChannelMetadataResponse OnGetChannelMetadataResponse;
	OnGetChannelMetadataResponse.BindDynamic(this, &ASample_ChannelMetadataEntity::OnGetChannelMetadataResponse_Simple);

	// Get channel metadata using the channel metadata entity
	ChannelMetadataEntity->GetChannelMetadataAsync(OnGetChannelMetadataResponse);
}

// ACTION REQUIRED: Replace ASample_ChannelMetadataEntity with name of your Actor class
void ASample_ChannelMetadataEntity::OnGetChannelMetadataResponse_Simple(FPubnubOperationResult Result, FPubnubChannelData ChannelData)
{
	if(Result.Error)
	{
		UE_LOG(LogTemp, Error, TEXT("Failed to get channel metadata. Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
	}
	else
	{
		UE_LOG(LogTemp, Log, TEXT("Successfully got channel metadata. ChannelID: %s, Name: %s"), *ChannelData.ChannelID, *ChannelData.ChannelName);
	}
}
```

#### Returns

This function is void, but the delegate returns the [FOnGetChannelMetadataResponse](#fongetchannelmetadataresponse) struct.

#### Other examples

:::tip Reference code
Set up your Unreal project and follow the instructions in the lines marked with
ACTION REQUIRED
before running the code.
:::

##### Get channel metadata with lambda

###### Actor.h

```cpp
#include "PubnubClient.h"
#include "Entities/PubnubChannelMetadataEntity.h"
#include "Entities/PubnubSubscription.h"

UFUNCTION(BlueprintCallable, Category = "Pubnub|Samples|ChannelMetadataEntity")
void GetChannelMetadataWithLambdaSample();
```

###### Actor.cpp

```cpp
// ACTION REQUIRED: Replace ASample_ChannelMetadataEntity with name of your Actor class
void ASample_ChannelMetadataEntity::GetChannelMetadataWithLambdaSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set

	// Create a channel metadata entity
	FString ChannelName = TEXT("guild-hall-channel");
	UPubnubChannelMetadataEntity* ChannelMetadataEntity = PubnubClient->CreateChannelMetadataEntity(ChannelName);

	// Bind lambda to response delegate
	FOnPubnubGetChannelMetadataResponseNative OnGetChannelMetadataResponse;
	OnGetChannelMetadataResponse.BindLambda([](const FPubnubOperationResult& Result, const FPubnubChannelData& ChannelData)
	{
		if(Result.Error)
		{
			UE_LOG(LogTemp, Error, TEXT("Failed to get channel metadata. Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
		}
		else
		{
			UE_LOG(LogTemp, Log, TEXT("Successfully got channel metadata. ChannelID: %s, Name: %s"), *ChannelData.ChannelID, *ChannelData.ChannelName);
		}
	});
	
	// Get channel metadata using the channel metadata entity
	ChannelMetadataEntity->GetChannelMetadataAsync(OnGetChannelMetadataResponse);
}
```

### Get channel metadata - PubNub client

Retrieve metadata for a channel. You can include the Custom object.

#### Method(s)

```cpp
// Synchronous
FPubnubChannelMetadataResult Result = PubnubClient->GetChannelMetadata(
    FString Channel,
    FPubnubGetMetadataInclude Include = FPubnubGetMetadataInclude()
);

// Asynchronous
PubnubClient->GetChannelMetadataAsync(
    FString Channel,
    FOnPubnubGetChannelMetadataResponse OnGetChannelMetadataResponse,
    FPubnubGetMetadataInclude Include = FPubnubGetMetadataInclude()
);
```

| Parameter | Description |
| --- | --- |
| `Channel` *Type: `FString` | The channel ID for which to retrieve the channel object. Can't be empty. |
| `OnGetChannelMetadataResponse`Type: [FOnPubnubGetChannelMetadataResponse](#fonpubnubgetchannelmetadataresponse) | The delegate for the operation's result. You can also use a native callback of the type [FOnPubnubGetChannelMetadataResponseNative](#fonpubnubgetchannelmetadataresponsenative) to handle the result using a lambda. |
| `Include`Type: [FPubnubGetMetadataInclude](#fpubnubgetmetadatainclude) | List of property names to include in the response. |

#### Sample code

:::tip Reference code
Set up your Unreal project and follow the instructions in the lines marked with
ACTION REQUIRED
before running the code.
:::

###### C++

#### Actor.h

```cpp
#include "PubnubClient.h"

// blueprint.rsj2c5zl
UFUNCTION(BlueprintCallable, Category = "Pubnub|Samples|App Context")
void GetChannelMetadataSample();

UFUNCTION()
void OnGetChannelMetadataResponse_Simple(FPubnubOperationResult Result, FPubnubChannelData ChannelData);
```

#### Actor.cpp

```cpp
// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::GetChannelMetadataSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set

	// Bind response delegate
	// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
	FOnPubnubGetChannelMetadataResponse OnGetChannelMetadataResponse;
	OnGetChannelMetadataResponse.BindDynamic(this, &ASample_AppContext::OnGetChannelMetadataResponse_Simple);

	// Get channel metadata
	FString Channel = TEXT("general-chat-channel");
	PubnubClient->GetChannelMetadataAsync(Channel, OnGetChannelMetadataResponse);
}

// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::OnGetChannelMetadataResponse_Simple(FPubnubOperationResult Result, FPubnubChannelData ChannelData)
{
	if(Result.Error)
	{
		UE_LOG(LogTemp, Error, TEXT("Failed to get channel metadata. Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
	}
	else
	{
		UE_LOG(LogTemp, Log, TEXT("Successfully got channel metadata. ChannelID: %s, Name: %s"), *ChannelData.ChannelID, *ChannelData.ChannelName);
	}
}
```

###### Blueprint

#### Returns

* **Synchronous:** returns [FPubnubChannelMetadataResult](#fpubnubchannelmetadataresult) (Result, ChannelData).
* **Asynchronous:** delegate [FOnPubnubGetChannelMetadataResponse](#fonpubnubgetchannelmetadataresponse) receives (Result, ChannelData).

##### FPubnubChannelMetadataResult

| Field | Type | Description |
| --- | --- | --- |
| `Result` | [FPubnubOperationResult](https://www.pubnub.com/docs/sdks/unreal/api-reference/configuration#operation-result) | The result of the operation. |
| `ChannelData` | [FPubnubChannelData](#fpubnubchanneldata) | The channel with its associated metadata. |

##### FOnPubnubGetChannelMetadataResponse

| Field | Type | Description |
| --- | --- | --- |
| `Result` | [FPubnubOperationResult](https://www.pubnub.com/docs/sdks/unreal/api-reference/configuration#operation-result) | The result of the operation. |
| `ChannelData` | [FPubnubChannelData](#fpubnubchanneldata) | The channel with its associated metadata. |

##### FOnPubnubGetChannelMetadataResponseNative

| Field | Type | Description |
| --- | --- | --- |
| `Result` | [const FPubnubOperationResult&](https://www.pubnub.com/docs/sdks/unreal/api-reference/configuration#operation-result) | The result of the operation. |
| `ChannelData` | [const FPubnubChannelData&](#fpubnubchanneldata) | The channel with its associated metadata. |

#### Other examples

:::tip Reference code
Set up your Unreal project and follow the instructions in the lines marked with
ACTION REQUIRED
before running the code.
:::

##### Get metadata for a channel with all includes

###### Actor.h

```cpp
#include "PubnubClient.h"

UFUNCTION(BlueprintCallable, Category = "Pubnub|Samples|App Context")
void GetChannelMetadataWithAllIncludesSample();

UFUNCTION()
void OnGetChannelMetadataResponse_WithAllIncludes(FPubnubOperationResult Result, FPubnubChannelData ChannelData);
```

###### Actor.cpp

```cpp
// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::GetChannelMetadataWithAllIncludesSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set

	// Bind response delegate
	// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
	FOnPubnubGetChannelMetadataResponse OnGetChannelMetadataResponse;
	OnGetChannelMetadataResponse.BindDynamic(this, &ASample_AppContext::OnGetChannelMetadataResponse_WithAllIncludes);

	// Get channel metadata with all available data included
	FString Channel = TEXT("trade-chat-channel");
	FPubnubGetMetadataInclude Include = FPubnubGetMetadataInclude::FromValue(true);
	PubnubClient->GetChannelMetadataAsync(Channel, OnGetChannelMetadataResponse, Include);
}

// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::OnGetChannelMetadataResponse_WithAllIncludes(FPubnubOperationResult Result, FPubnubChannelData ChannelData)
{
	if(Result.Error)
	{
		UE_LOG(LogTemp, Error, TEXT("Failed to get channel metadata. Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
	}
	else
	{
		UE_LOG(LogTemp, Log, TEXT("Successfully got channel metadata with all includes. ChannelID: %s, Name: %s, Custom: %s, Status: %s"), *ChannelData.ChannelID, *ChannelData.ChannelName, *ChannelData.Custom, *ChannelData.Status);
	}
}
```

##### Get metadata for a channel with lambda

###### Actor.h

```cpp
#include "PubnubClient.h"

UFUNCTION(BlueprintCallable, Category = "Pubnub|Samples|App Context")
void GetChannelMetadataWithLambdaSample();
```

###### Actor.cpp

```cpp
// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::GetChannelMetadataWithLambdaSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set

	// Bind lambda to response delegate
	FOnPubnubGetChannelMetadataResponseNative OnGetChannelMetadataResponse;
	OnGetChannelMetadataResponse.BindLambda([](const FPubnubOperationResult& Result, const FPubnubChannelData& ChannelData)
	{
		if(Result.Error)
		{
			UE_LOG(LogTemp, Error, TEXT("Failed to get channel metadata. Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
		}
		else
		{
			UE_LOG(LogTemp, Log, TEXT("Successfully got channel metadata. ChannelID: %s, Name: %s"), *ChannelData.ChannelID, *ChannelData.ChannelName);
		}
	});
	
	// Get channel metadata
	FString Channel = TEXT("guild-hall-channel");
	PubnubClient->GetChannelMetadataAsync(Channel, OnGetChannelMetadataResponse);
}
```

##### Get metadata for a channel raw

###### Actor.h

```cpp
// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::GetChannelMetadataRawSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set

	// Bind response delegate
	// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
	FOnPubnubGetChannelMetadataResponse OnGetChannelMetadataResponse;
	OnGetChannelMetadataResponse.BindDynamic(this, &ASample_AppContext::OnGetChannelMetadataRawResponse);

	// Get channel metadata with raw include string
	FString Channel = TEXT("trade-chat-channel");
	FString Include = TEXT("custom,status");
	PubnubClient->GetChannelMetadataRawAsync(Channel, OnGetChannelMetadataResponse, Include);
}

// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::OnGetChannelMetadataRawResponse(FPubnubOperationResult Result, FPubnubChannelData ChannelData)
{
	if(Result.Error)
	{
		UE_LOG(LogTemp, Error, TEXT("Failed to get channel metadata (raw). Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
	}
	else
	{
		UE_LOG(LogTemp, Log, TEXT("Successfully got channel metadata (raw). ChannelID: %s, Name: %s, Custom: %s, Status: %s"), *ChannelData.ChannelID, *ChannelData.ChannelName, *ChannelData.Custom, *ChannelData.Status);
	}
}
```

###### Actor.cpp

```cpp
// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::GetChannelMetadataRawSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set

	// Bind response delegate
	// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
	FOnPubnubGetChannelMetadataResponse OnGetChannelMetadataResponse;
	OnGetChannelMetadataResponse.BindDynamic(this, &ASample_AppContext::OnGetChannelMetadataRawResponse);

	// Get channel metadata with raw include string
	FString Channel = TEXT("trade-chat-channel");
	FString Include = TEXT("custom,status");
	PubnubClient->GetChannelMetadataRawAsync(Channel, OnGetChannelMetadataResponse, Include);
}

// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::OnGetChannelMetadataRawResponse(FPubnubOperationResult Result, FPubnubChannelData ChannelData)
{
	if(Result.Error)
	{
		UE_LOG(LogTemp, Error, TEXT("Failed to get channel metadata (raw). Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
	}
	else
	{
		UE_LOG(LogTemp, Log, TEXT("Successfully got channel metadata (raw). ChannelID: %s, Name: %s, Custom: %s, Status: %s"), *ChannelData.ChannelID, *ChannelData.ChannelName, *ChannelData.Custom, *ChannelData.Status);
	}
}
```

##### Set channel metadata with additional settings

###### Actor.h

```cpp
#include "PubnubClient.h"

```

###### Actor.cpp

```cpp
// Copyright 2026 PubNub Inc. All Rights Reserved.

#include "Samples/Sample_AppContext.h"
#include "Kismet/GameplayStatics.h"
#include "Engine/GameInstance.h"
#include "PubnubSubsystem.h"

/**
 * NOTE: Each sample is designed to be fully self-contained and portable. 
 * You can copy-paste any individual sample into a new project, and it should compile and run without errors 
 * — as long as you also include the necessary `#include` statements.
 *
 * The samples assume that in Pubnub SDK settings sections in ProjectSettings following fields are set:
 * PublishKey and SubscribeKey have correct keys, InitializeAutomatically is true.
 */

// NOTE: Comments marked with `ACTION REQUIRED` indicate lines you must change/adjust.

//Internal function, don't copy it with the samples
void ASample_AppContext::RunSamples()
{
	Super::RunSamples();
	
	SetUserMetadataSample();
	SetUserMetadataWithResultSample();
	SetUserMetadataWithLambdaSample();
	SetUserMetadataRawSample();
	UpdateUserMetadataIterativelySample();
	GetAllUserMetadataSample();
	GetAllUserMetadataWithSettingsSample();
	GetAllUserMetadataWithAllIncludesSample();
	GetAllUserMetadataWithLambdaSample();
	GetAllUserMetadataRawSample();
	GetUserMetadataSample();
	GetUserMetadataWithAllIncludesSample();
	GetUserMetadataWithLambdaSample();
	GetUserMetadataRawSample();
	RemoveUserMetadataSample();
	RemoveUserMetadataWithResultSample();
	RemoveUserMetadataWithResultLambdaSample();
	SetChannelMetadataSample();
	SetChannelMetadataWithResultSample();
	SetChannelMetadataWithLambdaSample();
	SetChannelMetadataRawSample();
	UpdateChannelMetadataIterativelySample();
	GetAllChannelMetadataSample();
	GetAllChannelMetadataWithSettingsSample();
	GetAllChannelMetadataWithAllIncludesSample();
	GetAllChannelMetadataWithLambdaSample();
	GetAllChannelMetadataRawSample();
	GetChannelMetadataSample();
	GetChannelMetadataWithAllIncludesSample();
	GetChannelMetadataWithLambdaSample();
	GetChannelMetadataRawSample();
	RemoveChannelMetadataSample();
	RemoveChannelMetadataWithResultSample();
	RemoveChannelMetadataWithResultLambdaSample();
}
//Internal function, don't copy it with the samples
ASample_AppContext::ASample_AppContext()
{
	SamplesName = "App Context";
}

/* SAMPLE FUNCTIONS */

// snippet.set_user_metadata
// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::SetUserMetadataSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set

	// Create user metadata object
	FPubnubUserData UserMetadata;
	UserMetadata.UserName = "Player One";
	UserMetadata.Email = "player.one@pubnub.com";
	UserMetadata.Custom = "{\"level\": 5, \"rank\": \"gold\"}";
	
	// Set user metadata
	FString UserID = TEXT("Player_001");
	FPubnubUserInputData UserInputData = FPubnubUserInputData::FromPubnubUserData(UserMetadata);
	PubnubClient->SetUserMetadataAsync(UserID, UserInputData);
}

// snippet.set_user_metadata_with_result
// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::SetUserMetadataWithResultSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set
	
	// Bind response delegate
	// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
	FOnPubnubSetUserMetadataResponse OnSetUserMetadataResponse;
	OnSetUserMetadataResponse.BindDynamic(this, &ASample_AppContext::OnSetUserMetadataResponse);

	// Create user metadata object
	FString UserID = TEXT("Player_002");
	FPubnubUserData UserMetadata;
	UserMetadata.UserName = "Player Two";
	UserMetadata.Status = "active";
	UserMetadata.Custom = "{\"inventory_slots\": 20, \"guild_id\": \"G2\"}";

	// Set user metadata with all available data included in response
	FPubnubGetMetadataInclude Include = FPubnubGetMetadataInclude::FromValue(true);
	FPubnubUserInputData UserInputData = FPubnubUserInputData::FromPubnubUserData(UserMetadata);
	PubnubClient->SetUserMetadataAsync(UserID, UserInputData, OnSetUserMetadataResponse, Include);
}

// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::OnSetUserMetadataResponse(FPubnubOperationResult Result, FPubnubUserData UserData)
{
	if(Result.Error)
	{
		UE_LOG(LogTemp, Error, TEXT("Failed to set user metadata. Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
	}
	else
	{
		UE_LOG(LogTemp, Log, TEXT("Successfully set user metadata. UserID: %s, Name: %s, Custom: %s, Status: %s"), *UserData.UserID, *UserData.UserName, *UserData.Custom, *UserData.Status);
	}
}

// snippet.set_user_metadata_with_lambda
// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::SetUserMetadataWithLambdaSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set

	// Bind lambda to response delegate
	FOnPubnubSetUserMetadataResponseNative OnSetUserMetadataResponse;
	OnSetUserMetadataResponse.BindLambda([](const FPubnubOperationResult& Result, const FPubnubUserData& UserData)
	{
		if(Result.Error)
		{
			UE_LOG(LogTemp, Error, TEXT("Failed to set user metadata. Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
		}
		else
		{
			UE_LOG(LogTemp, Log, TEXT("Successfully set user metadata. UserID: %s, Name: %s, Custom: %s, Status: %s"), *UserData.UserID, *UserData.UserName, *UserData.Custom, *UserData.Status);
		}
	});
	
	// Create user metadata object
	FString UserID = TEXT("Player_003");
	FPubnubUserData UserMetadata;
	UserMetadata.UserName = "Player Three";
	UserMetadata.Status = "inactive";
	UserMetadata.Custom = "{\"last_seen\": \"2024-01-01\"}";

	// Set user metadata with all available data included in response
	FPubnubGetMetadataInclude Include = FPubnubGetMetadataInclude::FromValue(true);
	FPubnubUserInputData UserInputData = FPubnubUserInputData::FromPubnubUserData(UserMetadata);
	PubnubClient->SetUserMetadataAsync(UserID, UserInputData, OnSetUserMetadataResponse, Include);
}

// snippet.set_user_metadata_raw
// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::SetUserMetadataRawSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set

	// Bind response delegate	
	// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
	FOnPubnubSetUserMetadataResponse OnSetUserMetadataResponse;
	OnSetUserMetadataResponse.BindDynamic(this, &ASample_AppContext::OnSetUserMetadataRawResponse);

	// Create user metadata object as a raw JSON string
	FString UserID = TEXT("Player_004");
	FString UserMetadataJson = R"({"name": "Player Four", "custom": {"class": "mage", "mana": 150}})";
	
	// Set user metadata with a raw include string
	FString Include = TEXT("custom");
	PubnubClient->SetUserMetadataRawAsync(UserID, UserMetadataJson, OnSetUserMetadataResponse, Include);
}

// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::OnSetUserMetadataRawResponse(FPubnubOperationResult Result, FPubnubUserData UserData)
{
	if(Result.Error)
	{
		UE_LOG(LogTemp, Error, TEXT("Failed to set user metadata (raw). Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
	}
	else
	{
		UE_LOG(LogTemp, Log, TEXT("Successfully set user metadata (raw). UserID: %s, Name: %s, Custom: %s"), *UserData.UserID, *UserData.UserName, *UserData.Custom);
	}
}

// snippet.update_user_metadata_iteratively
// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::UpdateUserMetadataIterativelySample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set
	
	// Create initial user metadata object
	FString UserID = TEXT("Player_005");
	FPubnubUserInputData UserInputData;
	UserInputData.UserName = "Player Two";
	UserInputData.Status = "active";
	UserInputData.Custom = "{\"inventory_slots\": 20, \"guild_id\": \"G2\"}";

	// Bind response delegate
	// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
	FOnPubnubSetUserMetadataResponse OnSetUserMetadataResponse;
	OnSetUserMetadataResponse.BindDynamic(this, &ASample_AppContext::OnInitialSetUserMetadataResponse);

	// Set initial user metadata
	FPubnubGetMetadataInclude Include = FPubnubGetMetadataInclude::FromValue(true);
	PubnubClient->SetUserMetadataAsync(UserID, UserInputData, OnSetUserMetadataResponse, Include);
}

// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::OnInitialSetUserMetadataResponse(FPubnubOperationResult Result, FPubnubUserData UserData)
{
	if(Result.Error)
	{
		UE_LOG(LogTemp, Error, TEXT("Failed to set initial user metadata. Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
		return;
	}
	
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show

	FString UserID = TEXT("Player_005");
	
	// Create updated version of user metadata object - change status to "inactive"
	FPubnubUserData UpdatedUserMetadata = UserData;
	UpdatedUserMetadata.Status = "inactive";

	// Bind response delegate
	// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
	FOnPubnubSetUserMetadataResponse OnSetUserMetadataResponse;
	OnSetUserMetadataResponse.BindDynamic(this, &ASample_AppContext::OnUpdateUserMetadataResponse);

	// Update user metadata
	FPubnubGetMetadataInclude Include;
	Include.IncludeStatus = true;
	FPubnubUserInputData UserInputData = FPubnubUserInputData::FromPubnubUserData(UpdatedUserMetadata);
	PubnubClient->SetUserMetadataAsync(UserID, UserInputData, OnSetUserMetadataResponse, Include);
}

// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::OnUpdateUserMetadataResponse(FPubnubOperationResult Result, FPubnubUserData UserData)
{
	if(Result.Error)
	{
		UE_LOG(LogTemp, Error, TEXT("Failed to update user metadata. Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
	}
	else
	{
		UE_LOG(LogTemp, Log, TEXT("Successfully updated user metadata. New status is: %s"), *UserData.Status);
	}
}

// snippet.get_all_user_metadata
// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::GetAllUserMetadataSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set

	// Bind response delegate
	// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
	FOnPubnubGetAllUserMetadataResponse OnGetAllUserMetadataResponse;
	OnGetAllUserMetadataResponse.BindDynamic(this, &ASample_AppContext::OnGetAllUserMetadataResponse_Simple);

	// Get all user metadata with a limit of 5
	PubnubClient->GetAllUserMetadataAsync(OnGetAllUserMetadataResponse, FPubnubGetAllInclude(), 5);
}

// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::OnGetAllUserMetadataResponse_Simple(FPubnubOperationResult Result, const TArray<FPubnubUserData>& UsersData, FPubnubPage Page, int TotalCount)
{
	if(Result.Error)
	{
		UE_LOG(LogTemp, Error, TEXT("Failed to get all user metadata. Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
	}
	else
	{
		UE_LOG(LogTemp, Log, TEXT("Successfully got all user metadata. Number of users: %d"), UsersData.Num());
		// Print all user metadata
		for (const FPubnubUserData& User : UsersData)
		{
			UE_LOG(LogTemp, Log, TEXT("- UserID: %s, Name: %s"), *User.UserID, *User.UserName);
		}
		if (!Page.Next.IsEmpty()) UE_LOG(LogTemp, Log, TEXT("Next Page: %s"), *Page.Next);
		if (!Page.Prev.IsEmpty()) UE_LOG(LogTemp, Log, TEXT("Previous Page: %s"), *Page.Prev);
	}
}

// snippet.get_all_user_metadata_with_settings
// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::GetAllUserMetadataWithSettingsSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set

	// Bind response delegate
	// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
	FOnPubnubGetAllUserMetadataResponse OnGetAllUserMetadataResponse;
	OnGetAllUserMetadataResponse.BindDynamic(this, &ASample_AppContext::OnGetAllUserMetadataResponse_WithSettings);

	// Create settings with includes and a filter
	FPubnubGetAllInclude Include;
	Include.IncludeCustom = true;
	Include.IncludeStatus = true;
	FString Filter = TEXT("status=='active'");
	int Limit = 10;
	
	// Get all user metadata with custom settings
	PubnubClient->GetAllUserMetadataAsync(OnGetAllUserMetadataResponse, Include, Limit, Filter);
}

// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::OnGetAllUserMetadataResponse_WithSettings(FPubnubOperationResult Result, const TArray<FPubnubUserData>& UsersData, FPubnubPage Page, int TotalCount)
{
	if(Result.Error)
	{
		UE_LOG(LogTemp, Error, TEXT("Failed to get all user metadata. Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
	}
	else
	{
		UE_LOG(LogTemp, Log, TEXT("Successfully got all user metadata with settings. Number of users: %d"), UsersData.Num());
		// Print all user metadata
		for (const FPubnubUserData& User : UsersData)
		{
			UE_LOG(LogTemp, Log, TEXT("- UserID: %s, Name: %s, Custom: %s, Status: %s"), *User.UserID, *User.UserName, *User.Custom, *User.Status);
		}
		if (!Page.Next.IsEmpty()) UE_LOG(LogTemp, Log, TEXT("Next Page: %s"), *Page.Next);
		if (!Page.Prev.IsEmpty()) UE_LOG(LogTemp, Log, TEXT("Previous Page: %s"), *Page.Prev);
	}
}

// snippet.get_all_user_metadata_with_all_includes
// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::GetAllUserMetadataWithAllIncludesSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set

	// Bind response delegate
	// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
	FOnPubnubGetAllUserMetadataResponse OnGetAllUserMetadataResponse;
	OnGetAllUserMetadataResponse.BindDynamic(this, &ASample_AppContext::OnGetAllUserMetadataResponse_WithAllIncludes);

	// Get all user metadata with all available data included
	FPubnubGetAllInclude Include = FPubnubGetAllInclude::FromValue(true);
	FString Filter = TEXT("status=='active' || status=='inactive'");
	FPubnubGetAllSort Sort;
	Sort.GetAllSort.Add(FPubnubGetAllSingleSort{EPubnubGetAllSortType::PGAST_Name, true});
	FString NextPage = "Mg"; // Page should be taken from previous response to get next or previous part of the objects
	FPubnubPage Page;
	Page.Next = NextPage;

	PubnubClient->GetAllUserMetadataAsync(OnGetAllUserMetadataResponse, Include, 100, Filter, Sort, Page);
}

// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::OnGetAllUserMetadataResponse_WithAllIncludes(FPubnubOperationResult Result, const TArray<FPubnubUserData>& UsersData, FPubnubPage Page, int TotalCount)
{
	if(Result.Error)
	{
		UE_LOG(LogTemp, Error, TEXT("Failed to get all user metadata. Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
	}
	else
	{
		UE_LOG(LogTemp, Log, TEXT("Successfully got all user metadata with all includes. Number of users: %d"), UsersData.Num());
		// Print all user metadata
		for (const FPubnubUserData& User : UsersData)
		{
			UE_LOG(LogTemp, Log, TEXT("- UserID: %s, Name: %s, Custom: %s, Status: %s"), *User.UserID, *User.UserName, *User.Custom, *User.Status);
		}
		if (!Page.Next.IsEmpty()) UE_LOG(LogTemp, Log, TEXT("Next Page: %s"), *Page.Next);
		if (!Page.Prev.IsEmpty()) UE_LOG(LogTemp, Log, TEXT("Previous Page: %s"), *Page.Prev);
	}
}

// snippet.get_all_user_metadata_with_lambda
// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::GetAllUserMetadataWithLambdaSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set

	// Bind lambda to response delegate
	// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
	FOnPubnubGetAllUserMetadataResponseNative OnGetAllUserMetadataResponse;
	OnGetAllUserMetadataResponse.BindLambda([](const FPubnubOperationResult& Result, const TArray<FPubnubUserData>& UsersData, FPubnubPage Page, int TotalCount)
	{
		if(Result.Error)
		{
			UE_LOG(LogTemp, Error, TEXT("Failed to get all user metadata. Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
		}
		else
		{
			UE_LOG(LogTemp, Log, TEXT("Successfully got all user metadata. Number of users: %d"), UsersData.Num());
			// Print all user metadata
			for (const FPubnubUserData& User : UsersData)
			{
				UE_LOG(LogTemp, Log, TEXT("- UserID: %s, Name: %s"), *User.UserID, *User.UserName);
			}
			if (!Page.Next.IsEmpty()) UE_LOG(LogTemp, Log, TEXT("Next Page: %s"), *Page.Next);
			if (!Page.Prev.IsEmpty()) UE_LOG(LogTemp, Log, TEXT("Previous Page: %s"), *Page.Prev);
		}
	});
	
	// Get all user metadata with a limit of 5
	PubnubClient->GetAllUserMetadataAsync(OnGetAllUserMetadataResponse, FPubnubGetAllInclude(), 5);
}

// snippet.get_all_user_metadata_raw
// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::GetAllUserMetadataRawSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set

	// Bind response delegate
	// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
	FOnPubnubGetAllUserMetadataResponse OnGetAllUserMetadataResponse;
	OnGetAllUserMetadataResponse.BindDynamic(this, &ASample_AppContext::OnGetAllUserMetadataRawResponse);

	// Create settings with includes and a filter
	FString Include = TEXT("custom,status");
	FString Filter = TEXT("status=='active'");
	FString Sort = TEXT("name:desc,status");
	int Limit = 10;
	
	// Get all user metadata with custom settings
	PubnubClient->GetAllUserMetadataRawAsync(OnGetAllUserMetadataResponse, Include, Limit, Filter, Sort);
}

// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::OnGetAllUserMetadataRawResponse(FPubnubOperationResult Result, const TArray<FPubnubUserData>& UsersData, FPubnubPage Page, int TotalCount)
{
	if(Result.Error)
	{
		UE_LOG(LogTemp, Error, TEXT("Failed to get all user metadata (raw). Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
	}
	else
	{
		UE_LOG(LogTemp, Log, TEXT("Successfully got all user metadata (raw). Number of users: %d"), UsersData.Num());
		// Print all user metadata
		for (const FPubnubUserData& User : UsersData)
		{
			UE_LOG(LogTemp, Log, TEXT("- UserID: %s, Name: %s, Custom: %s, Status: %s"), *User.UserID, *User.UserName, *User.Custom, *User.Status);
		}
		if (!Page.Next.IsEmpty()) UE_LOG(LogTemp, Log, TEXT("Next Page: %s"), *Page.Next);
		if (!Page.Prev.IsEmpty()) UE_LOG(LogTemp, Log, TEXT("Previous Page: %s"), *Page.Prev);
	}
}

// snippet.get_user_metadata
// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::GetUserMetadataSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set

	// Bind response delegate
	// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
	FOnPubnubGetUserMetadataResponse OnGetUserMetadataResponse;
	OnGetUserMetadataResponse.BindDynamic(this, &ASample_AppContext::OnGetUserMetadataResponse_Simple);

	// Get user metadata
	FString UserID = TEXT("Player_001");
	PubnubClient->GetUserMetadataAsync(UserID, OnGetUserMetadataResponse);
}

// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::OnGetUserMetadataResponse_Simple(FPubnubOperationResult Result, FPubnubUserData UserData)
{
	if(Result.Error)
	{
		UE_LOG(LogTemp, Error, TEXT("Failed to get user metadata. Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
	}
	else
	{
		UE_LOG(LogTemp, Log, TEXT("Successfully got user metadata. UserID: %s, Name: %s"), *UserData.UserID, *UserData.UserName);
	}
}

// snippet.get_user_metadata_with_all_includes
// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::GetUserMetadataWithAllIncludesSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set

	// Bind response delegate
	// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
	FOnPubnubGetUserMetadataResponse OnGetUserMetadataResponse;
	OnGetUserMetadataResponse.BindDynamic(this, &ASample_AppContext::OnGetUserMetadataResponse_WithAllIncludes);

	// Get user metadata with all available data included
	FString UserID = TEXT("Player_002");
	FPubnubGetMetadataInclude Include = FPubnubGetMetadataInclude::FromValue(true);
	PubnubClient->GetUserMetadataAsync(UserID, OnGetUserMetadataResponse, Include);
}

// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::OnGetUserMetadataResponse_WithAllIncludes(FPubnubOperationResult Result, FPubnubUserData UserData)
{
	if(Result.Error)
	{
		UE_LOG(LogTemp, Error, TEXT("Failed to get user metadata. Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
	}
	else
	{
		UE_LOG(LogTemp, Log, TEXT("Successfully got user metadata with all includes. UserID: %s, Name: %s, Custom: %s, Status: %s"), *UserData.UserID, *UserData.UserName, *UserData.Custom, *UserData.Status);
	}
}

// snippet.get_user_metadata_with_lambda
// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::GetUserMetadataWithLambdaSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set

	// Bind lambda to response delegate
	// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
	FOnPubnubGetUserMetadataResponseNative OnGetUserMetadataResponse;
	OnGetUserMetadataResponse.BindLambda([](const FPubnubOperationResult& Result, const FPubnubUserData& UserData)
	{
		if(Result.Error)
		{
			UE_LOG(LogTemp, Error, TEXT("Failed to get user metadata. Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
		}
		else
		{
			UE_LOG(LogTemp, Log, TEXT("Successfully got user metadata. UserID: %s, Name: %s"), *UserData.UserID, *UserData.UserName);
		}
	});
	
	// Get user metadata
	FString UserID = TEXT("Player_003");
	PubnubClient->GetUserMetadataAsync(UserID, OnGetUserMetadataResponse);
}

// snippet.get_user_metadata_raw
// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::GetUserMetadataRawSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set

	// Bind response delegate
	// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
	FOnPubnubGetUserMetadataResponse OnGetUserMetadataResponse;
	OnGetUserMetadataResponse.BindDynamic(this, &ASample_AppContext::OnGetUserMetadataRawResponse);

	// Get user metadata with raw include string
	FString UserID = TEXT("Player_004");
	FString Include = TEXT("custom,status");
	PubnubClient->GetUserMetadataRawAsync(UserID, OnGetUserMetadataResponse, Include);
}

// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::OnGetUserMetadataRawResponse(FPubnubOperationResult Result, FPubnubUserData UserData)
{
	if(Result.Error)
	{
		UE_LOG(LogTemp, Error, TEXT("Failed to get user metadata (raw). Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
	}
	else
	{
		UE_LOG(LogTemp, Log, TEXT("Successfully got user metadata (raw). UserID: %s, Name: %s, Custom: %s, Status: %s"), *UserData.UserID, *UserData.UserName, *UserData.Custom, *UserData.Status);
	}
}

// snippet.remove_user_metadata
// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::RemoveUserMetadataSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set
	
	// Remove user metadata
	FString UserToRemove = TEXT("Player_001");
	PubnubClient->RemoveUserMetadataAsync(UserToRemove);
}

// snippet.remove_user_metadata_with_result
// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::RemoveUserMetadataWithResultSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set

	// Bind response delegate
	// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
	FOnPubnubRemoveUserMetadataResponse OnRemoveUserMetadataResponse;
	OnRemoveUserMetadataResponse.BindDynamic(this, &ASample_AppContext::OnRemoveUserMetadataResponse);

	// Remove user metadata
	FString UserToRemove = TEXT("Player_002");
	PubnubClient->RemoveUserMetadataAsync(UserToRemove, OnRemoveUserMetadataResponse);
}

// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::OnRemoveUserMetadataResponse(FPubnubOperationResult Result)
{
	if(Result.Error)
	{
		UE_LOG(LogTemp, Error, TEXT("Failed to remove user metadata. Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
	}
	else
	{
		UE_LOG(LogTemp, Log, TEXT("Successfully removed user metadata."));
	}
}

// snippet.remove_user_metadata_with_result_lambda
// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::RemoveUserMetadataWithResultLambdaSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set

	// Bind lambda to response delegate
	FOnPubnubRemoveUserMetadataResponseNative OnRemoveUserMetadataResponse;
	OnRemoveUserMetadataResponse.BindLambda([](const FPubnubOperationResult& Result)
	{
		if(Result.Error)
		{
			UE_LOG(LogTemp, Error, TEXT("Failed to remove user metadata. Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
		}
		else
		{
			UE_LOG(LogTemp, Log, TEXT("Successfully removed user metadata."));
		}
	});
	
	// Remove user metadata
	FString UserToRemove = TEXT("Player_003");
	PubnubClient->RemoveUserMetadataAsync(UserToRemove, OnRemoveUserMetadataResponse);
}

// snippet.set_channel_metadata
// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::SetChannelMetadataSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set

	// Create channel metadata object
	FPubnubChannelData ChannelMetadata;
	ChannelMetadata.ChannelName = "General Chat";
	ChannelMetadata.Description = "Channel for all players to chat.";
	ChannelMetadata.Custom = "{\"topic\": \"welcomes\"}";
	
	// Set channel metadata
	FString Channel = "general-chat-channel";
	FPubnubChannelInputData ChannelInputData = FPubnubChannelInputData::FromPubnubChannelData(ChannelMetadata);
	PubnubClient->SetChannelMetadataAsync(Channel, ChannelInputData);
}

// snippet.set_channel_metadata_with_result
// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::SetChannelMetadataWithResultSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set
	
	// Bind response delegate
	// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
	FOnPubnubSetChannelMetadataResponse OnSetChannelMetadataResponse;
	OnSetChannelMetadataResponse.BindDynamic(this, &ASample_AppContext::OnSetChannelMetadataResponse);

	// Create channel metadata object
	FPubnubChannelInputData ChannelInputData;
	ChannelInputData.ChannelName = "Trade Chat";
	ChannelInputData.Status = "active";
	ChannelInputData.Custom = "{\"rules\": \"wts_wtt_only\"}";

	// Set channel metadata with all available data included in response
	FString Channel = "trade-chat-channel";
	FPubnubGetMetadataInclude Include = FPubnubGetMetadataInclude::FromValue(true);
	PubnubClient->SetChannelMetadataAsync(Channel, ChannelInputData, OnSetChannelMetadataResponse, Include);
}

// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::OnSetChannelMetadataResponse(FPubnubOperationResult Result, FPubnubChannelData ChannelData)
{
	if(Result.Error)
	{
		UE_LOG(LogTemp, Error, TEXT("Failed to set channel metadata. Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
	}
	else
	{
		UE_LOG(LogTemp, Log, TEXT("Successfully set channel metadata. ChannelID: %s, Name: %s, Custom: %s, Status: %s"), *ChannelData.ChannelID, *ChannelData.ChannelName, *ChannelData.Custom, *ChannelData.Status);
	}
}

// snippet.set_channel_metadata_with_lambda
// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::SetChannelMetadataWithLambdaSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set

	// Bind lambda to response delegate
	FOnPubnubSetChannelMetadataResponseNative OnSetChannelMetadataResponse;
	OnSetChannelMetadataResponse.BindLambda([](const FPubnubOperationResult& Result, const FPubnubChannelData& ChannelData)
	{
		if(Result.Error)
		{
			UE_LOG(LogTemp, Error, TEXT("Failed to set channel metadata. Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
		}
		else
		{
			UE_LOG(LogTemp, Log, TEXT("Successfully set channel metadata. ChannelID: %s, Name: %s, Custom: %s, Status: %s"), *ChannelData.ChannelID, *ChannelData.ChannelName, *ChannelData.Custom, *ChannelData.Status);
		}
	});
	
	// Create channel metadata object
	FPubnubChannelData ChannelMetadata;
	ChannelMetadata.ChannelName = "Guild Hall";
	ChannelMetadata.Status = "archived";
	ChannelMetadata.Custom = "{\"motd\": \"Raid tonight at 8!\"}";

	// Set channel metadata with all available data included in response
	FString Channel = "guild-hall-channel";
	FPubnubGetMetadataInclude Include = FPubnubGetMetadataInclude::FromValue(true);
	FPubnubChannelInputData ChannelInputData = FPubnubChannelInputData({ChannelMetadata.ChannelName, ChannelMetadata.Description, ChannelMetadata.Custom, ChannelMetadata.Status, ChannelMetadata.Type});
	PubnubClient->SetChannelMetadataAsync(Channel, ChannelInputData, OnSetChannelMetadataResponse, Include);
}

// snippet.set_channel_metadata_raw
// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::SetChannelMetadataRawSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set

	// Bind response delegate
	// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
	FOnPubnubSetChannelMetadataResponse OnSetChannelMetadataResponse;
	OnSetChannelMetadataResponse.BindDynamic(this, &ASample_AppContext::OnSetChannelMetadataRawResponse);

	// Create channel metadata object as a raw JSON string
	FString ChannelMetadataJson = R"({"name": "Secret Lair", "custom": {"max_players": 4, "password_protected": true}})";
	
	// Set channel metadata with a raw include string
	FString Channel = "secret-lair-channel";
	FString Include = TEXT("custom");
	PubnubClient->SetChannelMetadataRawAsync(Channel, ChannelMetadataJson, OnSetChannelMetadataResponse, Include);
}

// snippet.update_channel_metadata_iteratively
// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::UpdateChannelMetadataIterativelySample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set
	
	// Create initial channel metadata object
	FString ChannelID = TEXT("iterative-channel-update-test");
	FPubnubChannelData ChannelMetadata;
	ChannelMetadata.ChannelName = "Channel For Iterative Update";
	ChannelMetadata.Description = "This is the initial description.";
	ChannelMetadata.Custom = "{\"topic\": \"initial_topic\"}";

	// Bind response delegate
	// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
	FOnPubnubSetChannelMetadataResponse OnSetChannelMetadataResponse;
	OnSetChannelMetadataResponse.BindDynamic(this, &ASample_AppContext::OnInitialSetChannelMetadataResponse);

	// Set initial channel metadata 
	FPubnubChannelInputData ChannelInputData = FPubnubChannelInputData::FromPubnubChannelData(ChannelMetadata);
	PubnubClient->SetChannelMetadataAsync(ChannelID, ChannelInputData, OnSetChannelMetadataResponse);
}

// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::OnInitialSetChannelMetadataResponse(FPubnubOperationResult Result, FPubnubChannelData ChannelData)
{
	if(Result.Error)
	{
		UE_LOG(LogTemp, Error, TEXT("Failed to set initial channel metadata. Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
		return;
	}
	
	UE_LOG(LogTemp, Log, TEXT("Successfully set initial channel metadata. Description: %s"), *ChannelData.Description);

	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show

	// Use the ChannelID from the response
	FString ChannelID = ChannelData.ChannelID;
	
	// Create updated version of channel metadata object - change description only
	FPubnubChannelData UpdatedChannelMetadata;
	UpdatedChannelMetadata.Description = "This is the updated description!";

	// Bind response delegate
	// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
	FOnPubnubSetChannelMetadataResponse OnSetChannelMetadataResponse;
	OnSetChannelMetadataResponse.BindDynamic(this, &ASample_AppContext::OnUpdateChannelMetadataResponse);

	// Update channel metadata 
	FPubnubChannelInputData ChannelInputData = FPubnubChannelInputData::FromPubnubChannelData(UpdatedChannelMetadata);
	PubnubClient->SetChannelMetadataAsync(ChannelID, ChannelInputData, OnSetChannelMetadataResponse);
}

// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::OnUpdateChannelMetadataResponse(FPubnubOperationResult Result, FPubnubChannelData ChannelData)
{
	if(Result.Error)
	{
		UE_LOG(LogTemp, Error, TEXT("Failed to update channel metadata. Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
	}
	else
	{
		UE_LOG(LogTemp, Log, TEXT("Successfully updated channel metadata. New description is: '%s' and channel name is still: '%s'"), *ChannelData.Description, *ChannelData.ChannelName);
	}
}

// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::OnSetChannelMetadataRawResponse(FPubnubOperationResult Result, FPubnubChannelData ChannelData)
{
	if(Result.Error)
	{
		UE_LOG(LogTemp, Error, TEXT("Failed to set channel metadata (raw). Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
	}
	else
	{
		UE_LOG(LogTemp, Log, TEXT("Successfully set channel metadata (raw). ChannelID: %s, Name: %s, Custom: %s"), *ChannelData.ChannelID, *ChannelData.ChannelName, *ChannelData.Custom);
	}
}

// snippet.get_all_channel_metadata
// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::GetAllChannelMetadataSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set

	// Bind response delegate
	// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
	FOnPubnubGetAllChannelMetadataResponse OnGetAllChannelMetadataResponse;
	OnGetAllChannelMetadataResponse.BindDynamic(this, &ASample_AppContext::OnGetAllChannelMetadataResponse_Simple);

	// Get all channel metadata with a limit of 5
	PubnubClient->GetAllChannelMetadataAsync(OnGetAllChannelMetadataResponse, FPubnubGetAllInclude(), 5);
}

// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::OnGetAllChannelMetadataResponse_Simple(FPubnubOperationResult Result, const TArray<FPubnubChannelData>& ChannelsData, FPubnubPage Page, int TotalCount)
{
	if(Result.Error)
	{
		UE_LOG(LogTemp, Error, TEXT("Failed to get all channel metadata. Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
	}
	else
	{
		UE_LOG(LogTemp, Log, TEXT("Successfully got all channel metadata. Number of channels: %d"), ChannelsData.Num());
		// Print all channel metadata
		for (const FPubnubChannelData& Channel : ChannelsData)
		{
			UE_LOG(LogTemp, Log, TEXT("- ChannelID: %s, Name: %s"), *Channel.ChannelID, *Channel.ChannelName);
		}
		if (!Page.Next.IsEmpty()) UE_LOG(LogTemp, Log, TEXT("Next Page: %s"), *Page.Next);
		if (!Page.Prev.IsEmpty()) UE_LOG(LogTemp, Log, TEXT("Previous Page: %s"), *Page.Prev);
	}
}

// snippet.get_all_channel_metadata_with_settings
// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::GetAllChannelMetadataWithSettingsSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set

	// Bind response delegate
	// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
	FOnPubnubGetAllChannelMetadataResponse OnGetAllChannelMetadataResponse;
	OnGetAllChannelMetadataResponse.BindDynamic(this, &ASample_AppContext::OnGetAllChannelMetadataResponse_WithSettings);

	// Create settings with includes and a filter
	FPubnubGetAllInclude Include;
	Include.IncludeCustom = true;
	Include.IncludeStatus = true;
	FString Filter = TEXT("status=='active'");
	int Limit = 10;
	
	// Get all channel metadata with custom settings
	PubnubClient->GetAllChannelMetadataAsync(OnGetAllChannelMetadataResponse, Include, Limit, Filter);
}

// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::OnGetAllChannelMetadataResponse_WithSettings(FPubnubOperationResult Result, const TArray<FPubnubChannelData>& ChannelsData, FPubnubPage Page, int TotalCount)
{
	if(Result.Error)
	{
		UE_LOG(LogTemp, Error, TEXT("Failed to get all channel metadata. Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
	}
	else
	{
		UE_LOG(LogTemp, Log, TEXT("Successfully got all channel metadata with settings. Number of channels: %d"), ChannelsData.Num());
		// Print all channel metadata
		for (const FPubnubChannelData& Channel : ChannelsData)
		{
			UE_LOG(LogTemp, Log, TEXT("- ChannelID: %s, Name: %s, Custom: %s, Status: %s"), *Channel.ChannelID, *Channel.ChannelName, *Channel.Custom, *Channel.Status);
		}
		if (!Page.Next.IsEmpty()) UE_LOG(LogTemp, Log, TEXT("Next Page: %s"), *Page.Next);
		if (!Page.Prev.IsEmpty()) UE_LOG(LogTemp, Log, TEXT("Previous Page: %s"), *Page.Prev);
	}
}

// snippet.get_all_channel_metadata_with_all_includes
// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::GetAllChannelMetadataWithAllIncludesSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set

	// Bind response delegate
	// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
	FOnPubnubGetAllChannelMetadataResponse OnGetAllChannelMetadataResponse;
	OnGetAllChannelMetadataResponse.BindDynamic(this, &ASample_AppContext::OnGetAllChannelMetadataResponse_WithAllIncludes);

	// Get all channel metadata with all available data included
	FPubnubGetAllInclude Include = FPubnubGetAllInclude::FromValue(true);
	FString Filter = TEXT("status=='active' || status=='inactive'");
	FPubnubGetAllSort Sort;
	Sort.GetAllSort.Add(FPubnubGetAllSingleSort{EPubnubGetAllSortType::PGAST_Name, true});
	FString NextPage = "Mg"; // Page should be taken from previous response to get next or previous part of the objects
	FPubnubPage Page;
	Page.Next = NextPage;

	PubnubClient->GetAllChannelMetadataAsync(OnGetAllChannelMetadataResponse, Include, 100, Filter, Sort, Page);
}

// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::OnGetAllChannelMetadataResponse_WithAllIncludes(FPubnubOperationResult Result, const TArray<FPubnubChannelData>& ChannelsData, FPubnubPage Page, int TotalCount)
{
	if(Result.Error)
	{
		UE_LOG(LogTemp, Error, TEXT("Failed to get all channel metadata. Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
	}
	else
	{
		UE_LOG(LogTemp, Log, TEXT("Successfully got all channel metadata with all includes. Number of channels: %d"), ChannelsData.Num());
		// Print all channel metadata
		for (const FPubnubChannelData& Channel : ChannelsData)
		{
			UE_LOG(LogTemp, Log, TEXT("- ChannelID: %s, Name: %s, Custom: %s, Status: %s"), *Channel.ChannelID, *Channel.ChannelName, *Channel.Custom, *Channel.Status);
		}
		if (!Page.Next.IsEmpty()) UE_LOG(LogTemp, Log, TEXT("Next Page: %s"), *Page.Next);
		if (!Page.Prev.IsEmpty()) UE_LOG(LogTemp, Log, TEXT("Previous Page: %s"), *Page.Prev);
	}
}

// snippet.get_all_channel_metadata_with_lambda
// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::GetAllChannelMetadataWithLambdaSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set

	// Bind lambda to response delegate
	FOnPubnubGetAllChannelMetadataResponseNative OnGetAllChannelMetadataResponse;
	OnGetAllChannelMetadataResponse.BindLambda([](const FPubnubOperationResult& Result, const TArray<FPubnubChannelData>& ChannelsData, FPubnubPage Page, int TotalCount)
	{
		if(Result.Error)
		{
			UE_LOG(LogTemp, Error, TEXT("Failed to get all channel metadata. Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
		}
		else
		{
			UE_LOG(LogTemp, Log, TEXT("Successfully got all channel metadata. Number of channels: %d"), ChannelsData.Num());
			for (const FPubnubChannelData& Channel : ChannelsData)
			{
				UE_LOG(LogTemp, Log, TEXT("- ChannelID: %s, Name: %s"), *Channel.ChannelID, *Channel.ChannelName);
			}
			if (!Page.Next.IsEmpty()) UE_LOG(LogTemp, Log, TEXT("Next Page: %s"), *Page.Next);
			if (!Page.Prev.IsEmpty()) UE_LOG(LogTemp, Log, TEXT("Previous Page: %s"), *Page.Prev);
		}
	});
	
	// Get all channel metadata with a limit of 5
	PubnubClient->GetAllChannelMetadataAsync(OnGetAllChannelMetadataResponse, FPubnubGetAllInclude(), 5);
}

// snippet.get_all_channel_metadata_raw
// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::GetAllChannelMetadataRawSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set

	// Bind response delegate
	// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
	FOnPubnubGetAllChannelMetadataResponse OnGetAllChannelMetadataResponse;
	OnGetAllChannelMetadataResponse.BindDynamic(this, &ASample_AppContext::OnGetAllChannelMetadataRawResponse);

	// Create settings with includes and a filter
	FString Include = TEXT("custom,status");
	FString Filter = TEXT("status=='active'");
	FString Sort = TEXT("name:desc,status");
	int Limit = 10;
	
	// Get all channel metadata with custom settings
	PubnubClient->GetAllChannelMetadataRawAsync(OnGetAllChannelMetadataResponse, Include, Limit, Filter, Sort);
}

// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::OnGetAllChannelMetadataRawResponse(FPubnubOperationResult Result, const TArray<FPubnubChannelData>& ChannelsData, FPubnubPage Page, int TotalCount)
{
	if(Result.Error)
	{
		UE_LOG(LogTemp, Error, TEXT("Failed to get all channel metadata (raw). Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
	}
	else
	{
		UE_LOG(LogTemp, Log, TEXT("Successfully got all channel metadata (raw). Number of channels: %d"), ChannelsData.Num());
		// Print all channel metadata
		for (const FPubnubChannelData& Channel : ChannelsData)
		{
			UE_LOG(LogTemp, Log, TEXT("- ChannelID: %s, Name: %s, Custom: %s, Status: %s"), *Channel.ChannelID, *Channel.ChannelName, *Channel.Custom, *Channel.Status);
		}
		if (!Page.Next.IsEmpty()) UE_LOG(LogTemp, Log, TEXT("Next Page: %s"), *Page.Next);
		if (!Page.Prev.IsEmpty()) UE_LOG(LogTemp, Log, TEXT("Previous Page: %s"), *Page.Prev);
	}
}

// snippet.get_channel_metadata
// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::GetChannelMetadataSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set

	// Bind response delegate
	// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
	FOnPubnubGetChannelMetadataResponse OnGetChannelMetadataResponse;
	OnGetChannelMetadataResponse.BindDynamic(this, &ASample_AppContext::OnGetChannelMetadataResponse_Simple);

	// Get channel metadata
	FString Channel = TEXT("general-chat-channel");
	PubnubClient->GetChannelMetadataAsync(Channel, OnGetChannelMetadataResponse);
}

// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::OnGetChannelMetadataResponse_Simple(FPubnubOperationResult Result, FPubnubChannelData ChannelData)
{
	if(Result.Error)
	{
		UE_LOG(LogTemp, Error, TEXT("Failed to get channel metadata. Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
	}
	else
	{
		UE_LOG(LogTemp, Log, TEXT("Successfully got channel metadata. ChannelID: %s, Name: %s"), *ChannelData.ChannelID, *ChannelData.ChannelName);
	}
}

// snippet.get_channel_metadata_with_all_includes
// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::GetChannelMetadataWithAllIncludesSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set

	// Bind response delegate
	// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
	FOnPubnubGetChannelMetadataResponse OnGetChannelMetadataResponse;
	OnGetChannelMetadataResponse.BindDynamic(this, &ASample_AppContext::OnGetChannelMetadataResponse_WithAllIncludes);

	// Get channel metadata with all available data included
	FString Channel = TEXT("trade-chat-channel");
	FPubnubGetMetadataInclude Include = FPubnubGetMetadataInclude::FromValue(true);
	PubnubClient->GetChannelMetadataAsync(Channel, OnGetChannelMetadataResponse, Include);
}

// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::OnGetChannelMetadataResponse_WithAllIncludes(FPubnubOperationResult Result, FPubnubChannelData ChannelData)
{
	if(Result.Error)
	{
		UE_LOG(LogTemp, Error, TEXT("Failed to get channel metadata. Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
	}
	else
	{
		UE_LOG(LogTemp, Log, TEXT("Successfully got channel metadata with all includes. ChannelID: %s, Name: %s, Custom: %s, Status: %s"), *ChannelData.ChannelID, *ChannelData.ChannelName, *ChannelData.Custom, *ChannelData.Status);
	}
}

// snippet.get_channel_metadata_with_lambda
// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::GetChannelMetadataWithLambdaSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set

	// Bind lambda to response delegate
	FOnPubnubGetChannelMetadataResponseNative OnGetChannelMetadataResponse;
	OnGetChannelMetadataResponse.BindLambda([](const FPubnubOperationResult& Result, const FPubnubChannelData& ChannelData)
	{
		if(Result.Error)
		{
			UE_LOG(LogTemp, Error, TEXT("Failed to get channel metadata. Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
		}
		else
		{
			UE_LOG(LogTemp, Log, TEXT("Successfully got channel metadata. ChannelID: %s, Name: %s"), *ChannelData.ChannelID, *ChannelData.ChannelName);
		}
	});
	
	// Get channel metadata
	FString Channel = TEXT("guild-hall-channel");
	PubnubClient->GetChannelMetadataAsync(Channel, OnGetChannelMetadataResponse);
}

// snippet.get_channel_metadata_raw
// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::GetChannelMetadataRawSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set

	// Bind response delegate
	// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
	FOnPubnubGetChannelMetadataResponse OnGetChannelMetadataResponse;
	OnGetChannelMetadataResponse.BindDynamic(this, &ASample_AppContext::OnGetChannelMetadataRawResponse);

	// Get channel metadata with raw include string
	FString Channel = TEXT("trade-chat-channel");
	FString Include = TEXT("custom,status");
	PubnubClient->GetChannelMetadataRawAsync(Channel, OnGetChannelMetadataResponse, Include);
}

// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::OnGetChannelMetadataRawResponse(FPubnubOperationResult Result, FPubnubChannelData ChannelData)
{
	if(Result.Error)
	{
		UE_LOG(LogTemp, Error, TEXT("Failed to get channel metadata (raw). Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
	}
	else
	{
		UE_LOG(LogTemp, Log, TEXT("Successfully got channel metadata (raw). ChannelID: %s, Name: %s, Custom: %s, Status: %s"), *ChannelData.ChannelID, *ChannelData.ChannelName, *ChannelData.Custom, *ChannelData.Status);
	}
}

// snippet.remove_channel_metadata
// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::RemoveChannelMetadataSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set
	
	// Remove channel metadata
	FString Channel = TEXT("general-chat-channel");
	PubnubClient->RemoveChannelMetadataAsync(Channel);
}

// snippet.remove_channel_metadata_with_result
// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::RemoveChannelMetadataWithResultSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set

	// Bind response delegate
	// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
	FOnPubnubRemoveChannelMetadataResponse OnRemoveChannelMetadataResponse;
	OnRemoveChannelMetadataResponse.BindDynamic(this, &ASample_AppContext::OnRemoveChannelMetadataResponse);

	// Remove channel metadata
	FString Channel = TEXT("trade-chat-channel");
	PubnubClient->RemoveChannelMetadataAsync(Channel, OnRemoveChannelMetadataResponse);
}

// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::OnRemoveChannelMetadataResponse(FPubnubOperationResult Result)
{
	if(Result.Error)
	{
		UE_LOG(LogTemp, Error, TEXT("Failed to remove channel metadata. Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
	}
	else
	{
		UE_LOG(LogTemp, Log, TEXT("Successfully removed channel metadata."));
	}
}

// snippet.remove_channel_metadata_with_result_lambda
// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::RemoveChannelMetadataWithResultLambdaSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set

	// Bind lambda to response delegate
	FOnPubnubRemoveChannelMetadataResponseNative OnRemoveChannelMetadataResponse;
	OnRemoveChannelMetadataResponse.BindLambda([](const FPubnubOperationResult& Result)
	{
		if(Result.Error)
		{
			UE_LOG(LogTemp, Error, TEXT("Failed to remove channel metadata. Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
		}
		else
		{
			UE_LOG(LogTemp, Log, TEXT("Successfully removed channel metadata."));
		}
	});
	
	// Remove channel metadata
	FString Channel = TEXT("guild-hall-channel");
	PubnubClient->RemoveChannelMetadataAsync(Channel, OnRemoveChannelMetadataResponse);
}

// snippet.end

UPubnubClient* ASample_AppContext::GetPubnubClient()
{
	UGameInstance* GameInstance = UGameplayStatics::GetGameInstance(this);
	UPubnubSubsystem* PubnubSubsystem = GameInstance->GetSubsystem<UPubnubSubsystem>();
	
	//Get default PubnubClient - created automatically if PluginSettings are set to do so
	UPubnubClient* PubnubClient = PubnubSubsystem->GetPubnubClient(0);
	
	PubnubClient->SetUserID(TEXT("player_001"));
	return PubnubClient;
}
```

##### Set channel metadata with result struct

###### Actor.h

```cpp
#include "PubnubClient.h"

// blueprint.fr0nokir
UFUNCTION(BlueprintCallable, Category = "Pubnub|Samples|App Context")
void SetChannelMetadataWithResultSample();

UFUNCTION()
void OnSetChannelMetadataResponse(FPubnubOperationResult Result, FPubnubChannelData ChannelData);
```

###### Actor.cpp

```cpp
// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::SetChannelMetadataWithResultSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set
	
	// Bind response delegate
	// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
	FOnPubnubSetChannelMetadataResponse OnSetChannelMetadataResponse;
	OnSetChannelMetadataResponse.BindDynamic(this, &ASample_AppContext::OnSetChannelMetadataResponse);

	// Create channel metadata object
	FPubnubChannelInputData ChannelInputData;
	ChannelInputData.ChannelName = "Trade Chat";
	ChannelInputData.Status = "active";
	ChannelInputData.Custom = "{\"rules\": \"wts_wtt_only\"}";

	// Set channel metadata with all available data included in response
	FString Channel = "trade-chat-channel";
	FPubnubGetMetadataInclude Include = FPubnubGetMetadataInclude::FromValue(true);
	PubnubClient->SetChannelMetadataAsync(Channel, ChannelInputData, OnSetChannelMetadataResponse, Include);
}

// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::OnSetChannelMetadataResponse(FPubnubOperationResult Result, FPubnubChannelData ChannelData)
{
	if(Result.Error)
	{
		UE_LOG(LogTemp, Error, TEXT("Failed to set channel metadata. Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
	}
	else
	{
		UE_LOG(LogTemp, Log, TEXT("Successfully set channel metadata. ChannelID: %s, Name: %s, Custom: %s, Status: %s"), *ChannelData.ChannelID, *ChannelData.ChannelName, *ChannelData.Custom, *ChannelData.Status);
	}
}
```

##### Remove channel metadata with result struct

###### Actor.h

```cpp
#include "PubnubClient.h"

UFUNCTION(BlueprintCallable, Category = "Pubnub|Samples|App Context")
void RemoveChannelMetadataWithResultSample();

UFUNCTION()
void OnRemoveChannelMetadataResponse(FPubnubOperationResult Result);
```

###### Actor.cpp

```cpp
// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::RemoveChannelMetadataWithResultSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set

	// Bind response delegate
	// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
	FOnPubnubRemoveChannelMetadataResponse OnRemoveChannelMetadataResponse;
	OnRemoveChannelMetadataResponse.BindDynamic(this, &ASample_AppContext::OnRemoveChannelMetadataResponse);

	// Remove channel metadata
	FString Channel = TEXT("trade-chat-channel");
	PubnubClient->RemoveChannelMetadataAsync(Channel, OnRemoveChannelMetadataResponse);
}

// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::OnRemoveChannelMetadataResponse(FPubnubOperationResult Result)
{
	if(Result.Error)
	{
		UE_LOG(LogTemp, Error, TEXT("Failed to remove channel metadata. Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
	}
	else
	{
		UE_LOG(LogTemp, Log, TEXT("Successfully removed channel metadata."));
	}
}
```

### Set channel metadata - ChannelMetadata entity

##### Available in entities

This method is available to use with the `ChannelMetadata` entity. For more information, refer to [ChannelMetadata](https://www.pubnub.com/docs/sdks/unreal/entities/channel-metadata).

:::note Requires App Context add-on
This method requires the *App Context* add-on enabled for your key in the [Admin Portal](https://admin.pubnub.com/).
:::

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

Set metadata for a channel in the database, optionally including the custom data object for each.

#### Method(s)

```cpp
UPubnubChannelMetadataEntity* ChannelMetadataEntity = PubnubSubsystem->CreateChannelMetadataEntity("channel-id");

ChannelMetadataEntity->SetChannelMetadata(
    FPubnubChannelData ChannelMetadata,
    FOnSetChannelMetadataResponse OnSetChannelMetadataResponse,
    FPubnubGetMetadataInclude Include = FPubnubGetMetadataInclude()
);
```

| Parameter | Description |
| --- | --- |
| `ChannelMetadata`Type: [FPubnubChannelData](#fpubnubchanneldata) | The channel metadata object to create. |
| `FOnSetChannelMetadataResponse`Type: [FOnSetChannelMetadataResponse](#fonsetchannelmetadataresponse) | The delegate for the operation's result. You can also use a native callback of the type [FOnSetChannelMetadataResponseNative](#fonsetchannelmetadataresponsenative) to handle the result using a lambda. |
| `Include`Type: [FPubnubGetMetadataInclude](#fpubnubgetmetadatainclude) | List of property names to include in the response. |

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

#### Sample code

:::tip Reference code
Set up your Unreal project and follow the instructions in the lines marked with
ACTION REQUIRED
before running the code.
:::

###### C++

#### Actor.h

```cpp
#include "PubnubClient.h"
#include "Entities/PubnubChannelMetadataEntity.h"
#include "Entities/PubnubSubscription.h"

UFUNCTION(BlueprintCallable, Category = "Pubnub|Samples|ChannelMetadataEntity")
void SetChannelMetadataSample();
```

#### Actor.cpp

```cpp
// ACTION REQUIRED: Replace ASample_ChannelMetadataEntity with name of your Actor class
void ASample_ChannelMetadataEntity::SetChannelMetadataSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set

	// Create a channel metadata entity
	FString ChannelName = TEXT("general-chat-channel");
	UPubnubChannelMetadataEntity* ChannelMetadataEntity = PubnubClient->CreateChannelMetadataEntity(ChannelName);

	// Create channel metadata object
	FPubnubChannelInputData ChannelMetadata;
	ChannelMetadata.ChannelName = "General Chat";
	ChannelMetadata.Description = "Channel for all players to chat.";
	ChannelMetadata.Custom = "{\"topic\": \"welcomes\"}";
	
	// Set channel metadata using the channel metadata entity
	ChannelMetadataEntity->SetChannelMetadataAsync(ChannelMetadata);
}
```

#### Returns

```json
{
    "Channel": "my-channel",
    "Name": "PubNub channel",
    "Description": "The channel for announcements",
    "Updated": "2020-06-17T16:52:19.562469Z"
}
```

#### Other examples

:::tip Reference code
Set up your Unreal project and follow the instructions in the lines marked with
ACTION REQUIRED
before running the code.
:::

##### Set channel metadata with result

###### Actor.h

```cpp
#include "PubnubClient.h"
#include "Entities/PubnubChannelMetadataEntity.h"
#include "Entities/PubnubSubscription.h"

UFUNCTION(BlueprintCallable, Category = "Pubnub|Samples|ChannelMetadataEntity")
void SetChannelMetadataWithResultSample();

UFUNCTION()
void OnSetChannelMetadataResponse(FPubnubOperationResult Result, FPubnubChannelData ChannelData);
```

###### Actor.cpp

```cpp
// ACTION REQUIRED: Replace ASample_ChannelMetadataEntity with name of your Actor class
void ASample_ChannelMetadataEntity::SetChannelMetadataWithResultSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set

	// Create a channel metadata entity
	FString ChannelName = TEXT("trade-chat-channel");
	UPubnubChannelMetadataEntity* ChannelMetadataEntity = PubnubClient->CreateChannelMetadataEntity(ChannelName);
	
	// Bind response delegate
	// ACTION REQUIRED: Replace ASample_ChannelMetadataEntity with name of your Actor class
	FOnPubnubSetChannelMetadataResponse OnSetChannelMetadataResponse;
	OnSetChannelMetadataResponse.BindDynamic(this, &ASample_ChannelMetadataEntity::OnSetChannelMetadataResponse);

	// Create channel metadata object
	FPubnubChannelInputData ChannelMetadata;
	ChannelMetadata.ChannelName = "Trade Chat";
	ChannelMetadata.Status = "active";
	ChannelMetadata.Custom = "{\"rules\": \"wts_wtt_only\"}";

	// Set channel metadata with all available data included in response using the channel metadata entity
	FPubnubGetMetadataInclude Include = FPubnubGetMetadataInclude::FromValue(true);
	ChannelMetadataEntity->SetChannelMetadataAsync(ChannelMetadata, OnSetChannelMetadataResponse, Include);
}

// ACTION REQUIRED: Replace ASample_ChannelMetadataEntity with name of your Actor class
void ASample_ChannelMetadataEntity::OnSetChannelMetadataResponse(FPubnubOperationResult Result, FPubnubChannelData ChannelData)
{
	if(Result.Error)
	{
		UE_LOG(LogTemp, Error, TEXT("Failed to set channel metadata. Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
	}
	else
	{
		UE_LOG(LogTemp, Log, TEXT("Successfully set channel metadata. ChannelID: %s, Name: %s, Custom: %s, Status: %s"), *ChannelData.ChannelID, *ChannelData.ChannelName, *ChannelData.Custom, *ChannelData.Status);
	}
}
```

##### Set channel metadata with lambda

###### Actor.h

```cpp
#include "PubnubClient.h"
#include "Entities/PubnubChannelMetadataEntity.h"
#include "Entities/PubnubSubscription.h"

UFUNCTION(BlueprintCallable, Category = "Pubnub|Samples|ChannelMetadataEntity")
void SetChannelMetadataWithLambdaSample();
```

###### Actor.cpp

```cpp
// ACTION REQUIRED: Replace ASample_ChannelMetadataEntity with name of your Actor class
void ASample_ChannelMetadataEntity::SetChannelMetadataWithLambdaSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set

	// Create a channel metadata entity
	FString ChannelName = TEXT("guild-hall-channel");
	UPubnubChannelMetadataEntity* ChannelMetadataEntity = PubnubClient->CreateChannelMetadataEntity(ChannelName);

	// Bind lambda to response delegate
	FOnPubnubSetChannelMetadataResponseNative OnSetChannelMetadataResponse;
	OnSetChannelMetadataResponse.BindLambda([](const FPubnubOperationResult& Result, const FPubnubChannelData& ChannelData)
	{
		if(Result.Error)
		{
			UE_LOG(LogTemp, Error, TEXT("Failed to set channel metadata. Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
		}
		else
		{
			UE_LOG(LogTemp, Log, TEXT("Successfully set channel metadata. ChannelID: %s, Name: %s, Custom: %s, Status: %s"), *ChannelData.ChannelID, *ChannelData.ChannelName, *ChannelData.Custom, *ChannelData.Status);
		}
	});
	
	// Create channel metadata object
	FPubnubChannelInputData ChannelMetadata;
	ChannelMetadata.ChannelName = "Guild Hall";
	ChannelMetadata.Status = "archived";
	ChannelMetadata.Custom = "{\"motd\": \"Raid tonight at 8!\"}";

	// Set channel metadata with all available data included in response using the channel metadata entity
	FPubnubGetMetadataInclude Include = FPubnubGetMetadataInclude::FromValue(true);
	ChannelMetadataEntity->SetChannelMetadataAsync(ChannelMetadata, OnSetChannelMetadataResponse, Include);
}
```

### Set channel metadata - PubNub client

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

Set metadata for a channel in the database, optionally including the custom data object for each. Use [FPubnubChannelInputData](#fpubnubchannelinputdata) for the metadata payload (supports ForceSet fields for partial updates).

#### Method(s)

```cpp
// Synchronous
FPubnubChannelMetadataResult Result = PubnubClient->SetChannelMetadata(
    FString Channel,
    FPubnubChannelInputData ChannelMetadata,
    FPubnubGetMetadataInclude Include = FPubnubGetMetadataInclude()
);

// Asynchronous
PubnubClient->SetChannelMetadataAsync(
    FString Channel,
    FPubnubChannelInputData ChannelMetadata,
    FOnPubnubSetChannelMetadataResponse OnSetChannelMetadataResponse,
    FPubnubGetMetadataInclude Include = FPubnubGetMetadataInclude()
);
```

| Parameter | Description |
| --- | --- |
| `Channel` *Type: `FString` | The metadata ID for which to set the channel object. Can't be empty. |
| `ChannelMetadata` *Type: [FPubnubChannelInputData](#fpubnubchannelinputdata) | The channel metadata to set (input struct; supports ForceSet for partial updates). |
| `OnSetChannelMetadataResponse`Type: [FOnPubnubSetChannelMetadataResponse](#fonpubnubsetchannelmetadataresponse) | The delegate for the operation's result. You can also use a native callback of the type [FOnPubnubSetChannelMetadataResponseNative](#fonpubnubsetchannelmetadataresponsenative) to handle the result using a lambda. |
| `Include`Type: [FPubnubGetMetadataInclude](#fpubnubgetmetadatainclude) | List of property names to include in the response. |

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

#### FPubnubChannelInputData

Used for set operations. Contains the same fields as [FPubnubChannelData](#fpubnubchanneldata) (e.g. `ChannelName`, `Description`, `Custom`, etc.). When present, ForceSet-style fields control which properties are updated (partial updates).

#### Returns

* **Synchronous:** returns [FPubnubChannelMetadataResult](#fpubnubchannelmetadataresult) (Result, ChannelData).
* **Asynchronous:** delegate [FOnPubnubSetChannelMetadataResponse](#fonpubnubsetchannelmetadataresponse) receives (Result, ChannelData).

#### FOnPubnubSetChannelMetadataResponse

| Field | Type | Description |
| --- | --- | --- |
| `Result` | [FPubnubOperationResult](https://www.pubnub.com/docs/sdks/unreal/api-reference/configuration#operation-result) | The result of the operation. |
| `ChannelData` | [FPubnubChannelData](#fpubnubchanneldata) | The channel metadata object that was set. |

#### FOnPubnubSetChannelMetadataResponseNative

| Field | Type | Description |
| --- | --- | --- |
| `Result` | [const FPubnubOperationResult&](https://www.pubnub.com/docs/sdks/unreal/api-reference/configuration#operation-result) | The result of the operation. |
| `ChannelData` | [const FPubnubChannelData&](#fpubnubchanneldata) | The channel metadata object that was set. |

#### Sample code

:::tip Reference code
Set up your Unreal project and follow the instructions in the lines marked with
ACTION REQUIRED
before running the code.
:::

###### C++

#### Actor.h

```cpp
#include "PubnubClient.h"

// blueprint.3mxkam_d
UFUNCTION(BlueprintCallable, Category = "Pubnub|Samples|App Context")
void SetChannelMetadataSample();
```

#### Actor.cpp

```cpp
// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::SetChannelMetadataSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set

	// Create channel metadata object
	FPubnubChannelData ChannelMetadata;
	ChannelMetadata.ChannelName = "General Chat";
	ChannelMetadata.Description = "Channel for all players to chat.";
	ChannelMetadata.Custom = "{\"topic\": \"welcomes\"}";
	
	// Set channel metadata
	FString Channel = "general-chat-channel";
	FPubnubChannelInputData ChannelInputData = FPubnubChannelInputData::FromPubnubChannelData(ChannelMetadata);
	PubnubClient->SetChannelMetadataAsync(Channel, ChannelInputData);
}
```

###### Blueprint

#### Other examples

:::tip Reference code
Set up your Unreal project and follow the instructions in the lines marked with
ACTION REQUIRED
before running the code.
:::

##### Set metadata for a channel with result

###### C++

###### Actor.h

```cpp
#include "PubnubClient.h"

// blueprint.fr0nokir
UFUNCTION(BlueprintCallable, Category = "Pubnub|Samples|App Context")
void SetChannelMetadataWithResultSample();

UFUNCTION()
void OnSetChannelMetadataResponse(FPubnubOperationResult Result, FPubnubChannelData ChannelData);
```

###### Actor.cpp

```cpp
// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::SetChannelMetadataWithResultSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set
	
	// Bind response delegate
	// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
	FOnPubnubSetChannelMetadataResponse OnSetChannelMetadataResponse;
	OnSetChannelMetadataResponse.BindDynamic(this, &ASample_AppContext::OnSetChannelMetadataResponse);

	// Create channel metadata object
	FPubnubChannelInputData ChannelInputData;
	ChannelInputData.ChannelName = "Trade Chat";
	ChannelInputData.Status = "active";
	ChannelInputData.Custom = "{\"rules\": \"wts_wtt_only\"}";

	// Set channel metadata with all available data included in response
	FString Channel = "trade-chat-channel";
	FPubnubGetMetadataInclude Include = FPubnubGetMetadataInclude::FromValue(true);
	PubnubClient->SetChannelMetadataAsync(Channel, ChannelInputData, OnSetChannelMetadataResponse, Include);
}

// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::OnSetChannelMetadataResponse(FPubnubOperationResult Result, FPubnubChannelData ChannelData)
{
	if(Result.Error)
	{
		UE_LOG(LogTemp, Error, TEXT("Failed to set channel metadata. Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
	}
	else
	{
		UE_LOG(LogTemp, Log, TEXT("Successfully set channel metadata. ChannelID: %s, Name: %s, Custom: %s, Status: %s"), *ChannelData.ChannelID, *ChannelData.ChannelName, *ChannelData.Custom, *ChannelData.Status);
	}
}
```

###### Blueprint

##### Set metadata for a channel with lambda

###### Actor.h

```cpp
#include "PubnubClient.h"

UFUNCTION(BlueprintCallable, Category = "Pubnub|Samples|App Context")
void SetChannelMetadataWithLambdaSample();
```

###### Actor.cpp

```cpp
// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::SetChannelMetadataWithLambdaSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set

	// Bind lambda to response delegate
	FOnPubnubSetChannelMetadataResponseNative OnSetChannelMetadataResponse;
	OnSetChannelMetadataResponse.BindLambda([](const FPubnubOperationResult& Result, const FPubnubChannelData& ChannelData)
	{
		if(Result.Error)
		{
			UE_LOG(LogTemp, Error, TEXT("Failed to set channel metadata. Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
		}
		else
		{
			UE_LOG(LogTemp, Log, TEXT("Successfully set channel metadata. ChannelID: %s, Name: %s, Custom: %s, Status: %s"), *ChannelData.ChannelID, *ChannelData.ChannelName, *ChannelData.Custom, *ChannelData.Status);
		}
	});
	
	// Create channel metadata object
	FPubnubChannelData ChannelMetadata;
	ChannelMetadata.ChannelName = "Guild Hall";
	ChannelMetadata.Status = "archived";
	ChannelMetadata.Custom = "{\"motd\": \"Raid tonight at 8!\"}";

	// Set channel metadata with all available data included in response
	FString Channel = "guild-hall-channel";
	FPubnubGetMetadataInclude Include = FPubnubGetMetadataInclude::FromValue(true);
	FPubnubChannelInputData ChannelInputData = FPubnubChannelInputData({ChannelMetadata.ChannelName, ChannelMetadata.Description, ChannelMetadata.Custom, ChannelMetadata.Status, ChannelMetadata.Type});
	PubnubClient->SetChannelMetadataAsync(Channel, ChannelInputData, OnSetChannelMetadataResponse, Include);
}
```

##### Set metadata for a channel raw

###### Actor.h

```cpp
// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::SetChannelMetadataRawSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set

	// Bind response delegate
	// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
	FOnPubnubSetChannelMetadataResponse OnSetChannelMetadataResponse;
	OnSetChannelMetadataResponse.BindDynamic(this, &ASample_AppContext::OnSetChannelMetadataRawResponse);

	// Create channel metadata object as a raw JSON string
	FString ChannelMetadataJson = R"({"name": "Secret Lair", "custom": {"max_players": 4, "password_protected": true}})";
	
	// Set channel metadata with a raw include string
	FString Channel = "secret-lair-channel";
	FString Include = TEXT("custom");
	PubnubClient->SetChannelMetadataRawAsync(Channel, ChannelMetadataJson, OnSetChannelMetadataResponse, Include);
}
```

###### Actor.cpp

```cpp
// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::SetChannelMetadataRawSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set

	// Bind response delegate
	// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
	FOnPubnubSetChannelMetadataResponse OnSetChannelMetadataResponse;
	OnSetChannelMetadataResponse.BindDynamic(this, &ASample_AppContext::OnSetChannelMetadataRawResponse);

	// Create channel metadata object as a raw JSON string
	FString ChannelMetadataJson = R"({"name": "Secret Lair", "custom": {"max_players": 4, "password_protected": true}})";
	
	// Set channel metadata with a raw include string
	FString Channel = "secret-lair-channel";
	FString Include = TEXT("custom");
	PubnubClient->SetChannelMetadataRawAsync(Channel, ChannelMetadataJson, OnSetChannelMetadataResponse, Include);
}
```

##### Iteratively update existing metadata

###### Actor.h

```cpp
#include "PubnubClient.h"

```

###### Actor.cpp

```cpp
// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::UpdateChannelMetadataIterativelySample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set
	
	// Create initial channel metadata object
	FString ChannelID = TEXT("iterative-channel-update-test");
	FPubnubChannelData ChannelMetadata;
	ChannelMetadata.ChannelName = "Channel For Iterative Update";
	ChannelMetadata.Description = "This is the initial description.";
	ChannelMetadata.Custom = "{\"topic\": \"initial_topic\"}";

	// Bind response delegate
	// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
	FOnPubnubSetChannelMetadataResponse OnSetChannelMetadataResponse;
	OnSetChannelMetadataResponse.BindDynamic(this, &ASample_AppContext::OnInitialSetChannelMetadataResponse);

	// Set initial channel metadata 
	FPubnubChannelInputData ChannelInputData = FPubnubChannelInputData::FromPubnubChannelData(ChannelMetadata);
	PubnubClient->SetChannelMetadataAsync(ChannelID, ChannelInputData, OnSetChannelMetadataResponse);
}

// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::OnInitialSetChannelMetadataResponse(FPubnubOperationResult Result, FPubnubChannelData ChannelData)
{
	if(Result.Error)
	{
		UE_LOG(LogTemp, Error, TEXT("Failed to set initial channel metadata. Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
		return;
	}
	
	UE_LOG(LogTemp, Log, TEXT("Successfully set initial channel metadata. Description: %s"), *ChannelData.Description);

	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show

	// Use the ChannelID from the response
	FString ChannelID = ChannelData.ChannelID;
	
	// Create updated version of channel metadata object - change description only
	FPubnubChannelData UpdatedChannelMetadata;
	UpdatedChannelMetadata.Description = "This is the updated description!";

	// Bind response delegate
	// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
	FOnPubnubSetChannelMetadataResponse OnSetChannelMetadataResponse;
	OnSetChannelMetadataResponse.BindDynamic(this, &ASample_AppContext::OnUpdateChannelMetadataResponse);

	// Update channel metadata 
	FPubnubChannelInputData ChannelInputData = FPubnubChannelInputData::FromPubnubChannelData(UpdatedChannelMetadata);
	PubnubClient->SetChannelMetadataAsync(ChannelID, ChannelInputData, OnSetChannelMetadataResponse);
}

// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::OnUpdateChannelMetadataResponse(FPubnubOperationResult Result, FPubnubChannelData ChannelData)
{
	if(Result.Error)
	{
		UE_LOG(LogTemp, Error, TEXT("Failed to update channel metadata. Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
	}
	else
	{
		UE_LOG(LogTemp, Log, TEXT("Successfully updated channel metadata. New description is: '%s' and channel name is still: '%s'"), *ChannelData.Description, *ChannelData.ChannelName);
	}
}

// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::OnSetChannelMetadataRawResponse(FPubnubOperationResult Result, FPubnubChannelData ChannelData)
{
	if(Result.Error)
	{
		UE_LOG(LogTemp, Error, TEXT("Failed to set channel metadata (raw). Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
	}
	else
	{
		UE_LOG(LogTemp, Log, TEXT("Successfully set channel metadata (raw). ChannelID: %s, Name: %s, Custom: %s"), *ChannelData.ChannelID, *ChannelData.ChannelName, *ChannelData.Custom);
	}
}
```

### Remove channel metadata - ChannelMetadata entity

##### Available in entities

This method is available to use with the `ChannelMetadata` entity. For more information, refer to [ChannelMetadata](https://www.pubnub.com/docs/sdks/unreal/entities/channel-metadata).

:::note Requires App Context add-on
This method requires the *App Context* add-on enabled for your key in the [Admin Portal](https://admin.pubnub.com/).
:::

Removes the metadata from a specified channel.

#### Method(s)

```cpp
UPubnubChannelMetadataEntity* ChannelMetadataEntity = PubnubSubsystem->CreateChannelMetadataEntity("channel-id");

ChannelMetadataEntity->RemoveChannelMetadata(
    FOnRemoveChannelMetadataResponse OnRemoveChannelMetadataResponse
);
```

| Parameter | Description |
| --- | --- |
| `OnRemoveChannelMetadataResponse`Type: [FOnRemoveChannelMetadataResponse](#fonremovechannelmetadataresponse) | The delegate for the operation's result. You can also use a native callback of the type [FOnRemoveChannelMetadataResponseNative](#fonremovechannelmetadataresponsenative) to handle the result using a lambda. |

#### Sample code

:::tip Reference code
Set up your Unreal project and follow the instructions in the lines marked with
ACTION REQUIRED
before running the code.
:::

###### C++

#### Actor.h

```cpp
#include "PubnubClient.h"
#include "Entities/PubnubChannelMetadataEntity.h"
#include "Entities/PubnubSubscription.h"

UFUNCTION(BlueprintCallable, Category = "Pubnub|Samples|ChannelMetadataEntity")
void RemoveChannelMetadataSample();
```

#### Actor.cpp

```cpp
// ACTION REQUIRED: Replace ASample_ChannelMetadataEntity with name of your Actor class
void ASample_ChannelMetadataEntity::RemoveChannelMetadataSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set

	// Create a channel metadata entity
	FString ChannelName = TEXT("general-chat-channel");
	UPubnubChannelMetadataEntity* ChannelMetadataEntity = PubnubClient->CreateChannelMetadataEntity(ChannelName);
	
	// Remove channel metadata using the channel metadata entity
	ChannelMetadataEntity->RemoveChannelMetadataAsync();
}
```

#### Returns

This function is void, but the delegate returns the [FOnRemoveChannelMetadataResponse](#fonremovechannelmetadataresponse) struct.

#### Other examples

:::tip Reference code
Set up your Unreal project and follow the instructions in the lines marked with
ACTION REQUIRED
before running the code.
:::

##### Remove channel metadata with result

###### Actor.h

```cpp
#include "PubnubClient.h"
#include "Entities/PubnubChannelMetadataEntity.h"
#include "Entities/PubnubSubscription.h"

UFUNCTION(BlueprintCallable, Category = "Pubnub|Samples|ChannelMetadataEntity")
void RemoveChannelMetadataWithResultSample();

UFUNCTION()
void OnRemoveChannelMetadataResponse(FPubnubOperationResult Result);
```

###### Actor.cpp

```cpp
// ACTION REQUIRED: Replace ASample_ChannelMetadataEntity with name of your Actor class
void ASample_ChannelMetadataEntity::RemoveChannelMetadataWithResultSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set

	// Create a channel metadata entity
	FString ChannelName = TEXT("trade-chat-channel");
	UPubnubChannelMetadataEntity* ChannelMetadataEntity = PubnubClient->CreateChannelMetadataEntity(ChannelName);

	// Bind response delegate
	// ACTION REQUIRED: Replace ASample_ChannelMetadataEntity with name of your Actor class
	FOnPubnubRemoveChannelMetadataResponse OnRemoveChannelMetadataResponse;
	OnRemoveChannelMetadataResponse.BindDynamic(this, &ASample_ChannelMetadataEntity::OnRemoveChannelMetadataResponse);

	// Remove channel metadata using the channel metadata entity
	ChannelMetadataEntity->RemoveChannelMetadataAsync(OnRemoveChannelMetadataResponse);
}

// ACTION REQUIRED: Replace ASample_ChannelMetadataEntity with name of your Actor class
void ASample_ChannelMetadataEntity::OnRemoveChannelMetadataResponse(FPubnubOperationResult Result)
{
	if(Result.Error)
	{
		UE_LOG(LogTemp, Error, TEXT("Failed to remove channel metadata. Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
	}
	else
	{
		UE_LOG(LogTemp, Log, TEXT("Successfully removed channel metadata."));
	}
}
```

##### Remove channel metadata with lambda

###### Actor.h

```cpp
#include "PubnubClient.h"
#include "Entities/PubnubChannelMetadataEntity.h"
#include "Entities/PubnubSubscription.h"

UFUNCTION(BlueprintCallable, Category = "Pubnub|Samples|ChannelMetadataEntity")
void RemoveChannelMetadataWithResultLambdaSample();

	
```

###### Actor.cpp

```cpp
// ACTION REQUIRED: Replace ASample_ChannelMetadataEntity with name of your Actor class
void ASample_ChannelMetadataEntity::RemoveChannelMetadataWithResultLambdaSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set

	// Create a channel metadata entity
	FString ChannelName = TEXT("guild-hall-channel");
	UPubnubChannelMetadataEntity* ChannelMetadataEntity = PubnubClient->CreateChannelMetadataEntity(ChannelName);

	// Bind lambda to response delegate
	FOnPubnubRemoveChannelMetadataResponseNative OnRemoveChannelMetadataResponse;
	OnRemoveChannelMetadataResponse.BindLambda([](const FPubnubOperationResult& Result)
	{
		if(Result.Error)
		{
			UE_LOG(LogTemp, Error, TEXT("Failed to remove channel metadata. Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
		}
		else
		{
			UE_LOG(LogTemp, Log, TEXT("Successfully removed channel metadata."));
		}
	});
	
	// Remove channel metadata using the channel metadata entity
	ChannelMetadataEntity->RemoveChannelMetadataAsync(OnRemoveChannelMetadataResponse);
}
```

### Remove channel metadata - PubNub client

Removes the metadata from a specified channel.

#### Method(s)

```cpp
// Synchronous
FPubnubOperationResult Result = PubnubClient->RemoveChannelMetadata(FString Channel);

// Asynchronous
PubnubClient->RemoveChannelMetadataAsync(FString Channel, FOnPubnubRemoveChannelMetadataResponse OnRemoveChannelMetadataResponse);
```

| Parameter | Description |
| --- | --- |
| `Channel` *Type: `FString` | The metadata ID to delete from the channel object. Can't be empty. |
| `OnRemoveChannelMetadataResponse`Type: [FOnPubnubRemoveChannelMetadataResponse](#fonpubnubremovechannelmetadataresponse) | The delegate for the operation's result. You can also use a native callback of the type [FOnPubnubRemoveChannelMetadataResponseNative](#fonpubnubremovechannelmetadataresponsenative) to handle the result using a lambda. |

#### Sample code

:::tip Reference code
Set up your Unreal project and follow the instructions in the lines marked with
ACTION REQUIRED
before running the code.
:::

###### C++

#### Actor.h

```cpp
#include "PubnubClient.h"

// blueprint.k80afln-
UFUNCTION(BlueprintCallable, Category = "Pubnub|Samples|App Context")
void RemoveChannelMetadataSample();
```

#### Actor.cpp

```cpp
// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::RemoveChannelMetadataSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set
	
	// Remove channel metadata
	FString Channel = TEXT("general-chat-channel");
	PubnubClient->RemoveChannelMetadataAsync(Channel);
}
```

###### Blueprint

#### Returns

* **Synchronous:** returns [FPubnubOperationResult](https://www.pubnub.com/docs/sdks/unreal/api-reference/configuration#operation-result).
* **Asynchronous:** delegate [FOnPubnubRemoveChannelMetadataResponse](#fonpubnubremovechannelmetadataresponse) receives Result only.

##### FOnPubnubRemoveChannelMetadataResponse

| Field | Type | Description |
| --- | --- | --- |
| `Result` | [FPubnubOperationResult](https://www.pubnub.com/docs/sdks/unreal/api-reference/configuration#operation-result) | The result of the operation. |

##### FOnPubnubRemoveChannelMetadataResponseNative

| Field | Type | Description |
| --- | --- | --- |
| `Result` | [const FPubnubOperationResult&](https://www.pubnub.com/docs/sdks/unreal/api-reference/configuration#operation-result) | The result of the operation. |

#### Other examples

:::tip Reference code
Set up your Unreal project and follow the instructions in the lines marked with
ACTION REQUIRED
before running the code.
:::

##### Remove metadata for a channel with result

###### Actor.h

```cpp
#include "PubnubClient.h"

UFUNCTION(BlueprintCallable, Category = "Pubnub|Samples|App Context")
void RemoveChannelMetadataWithResultSample();

UFUNCTION()
void OnRemoveChannelMetadataResponse(FPubnubOperationResult Result);
```

###### Actor.cpp

```cpp
// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::RemoveChannelMetadataWithResultSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set

	// Bind response delegate
	// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
	FOnPubnubRemoveChannelMetadataResponse OnRemoveChannelMetadataResponse;
	OnRemoveChannelMetadataResponse.BindDynamic(this, &ASample_AppContext::OnRemoveChannelMetadataResponse);

	// Remove channel metadata
	FString Channel = TEXT("trade-chat-channel");
	PubnubClient->RemoveChannelMetadataAsync(Channel, OnRemoveChannelMetadataResponse);
}

// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::OnRemoveChannelMetadataResponse(FPubnubOperationResult Result)
{
	if(Result.Error)
	{
		UE_LOG(LogTemp, Error, TEXT("Failed to remove channel metadata. Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
	}
	else
	{
		UE_LOG(LogTemp, Log, TEXT("Successfully removed channel metadata."));
	}
}
```

##### Remove metadata for a channel with lambda

###### Actor.h

```cpp
#include "PubnubClient.h"

UFUNCTION(BlueprintCallable, Category = "Pubnub|Samples|App Context")
void RemoveChannelMetadataWithResultLambdaSample();
```

###### Actor.cpp

```cpp
// ACTION REQUIRED: Replace ASample_AppContext with name of your Actor class
void ASample_AppContext::RemoveChannelMetadataWithResultLambdaSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set

	// Bind lambda to response delegate
	FOnPubnubRemoveChannelMetadataResponseNative OnRemoveChannelMetadataResponse;
	OnRemoveChannelMetadataResponse.BindLambda([](const FPubnubOperationResult& Result)
	{
		if(Result.Error)
		{
			UE_LOG(LogTemp, Error, TEXT("Failed to remove channel metadata. Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
		}
		else
		{
			UE_LOG(LogTemp, Log, TEXT("Successfully removed channel metadata."));
		}
	});
	
	// Remove channel metadata
	FString Channel = TEXT("guild-hall-channel");
	PubnubClient->RemoveChannelMetadataAsync(Channel, OnRemoveChannelMetadataResponse);
}
```

## Channel memberships

### Get channel memberships

The method returns a list of channel memberships for a user. This method doesn't return a user's subscriptions.

#### Method(s)

:::tip Method variants
You can also call the `GetMembershipsRaw` variant of this method which takes String values for `Include` and `Sort` instead of the `FPubnubMembershipInclude` and `FPubnubMembershipSort` structs.
:::

```cpp
// Synchronous
FPubnubMembershipsResult Result = PubnubClient->GetMemberships(
    FString User,
    FPubnubMembershipInclude Include = FPubnubMembershipInclude(),
    int Limit = 100,
    FString Filter = "",
    FPubnubMembershipSort Sort = FPubnubMembershipSort(),
    FPubnubPage Page = FPubnubPage()
);

// Asynchronous
PubnubClient->GetMembershipsAsync(
    FString User,
    FOnPubnubGetMembershipsResponse OnGetMembershipsResponse,
    FPubnubMembershipInclude Include = FPubnubMembershipInclude(),
    int Limit = 100,
    FString Filter = "",
    FPubnubMembershipSort Sort = FPubnubMembershipSort(),
    FPubnubPage Page = FPubnubPage()
);
```

| Parameter | Description |
| --- | --- |
| `User` *Type: `FString` | The user UUID for whom to retrieve memberships. |
| `OnGetMembershipsResponse`Type: [FOnPubnubGetMembershipsResponse](#fonpubnubgetmembershipsresponse) | The delegate for the operation's result. You can also use a native callback of the type [FOnPubnubGetMembershipsResponseNative](#fonpubnubgetmembershipsresponsenative) to handle the result using a lambda. |
| `Include`Type: [FPubnubMembershipInclude](#fpubnubmembershipinclude) | List of property names to include in the response. |
| `Limit`Type: int | Number of objects to return. Default/Max: 100. |
| `Filter`Type: `FString` | Filter expression. Only matching objects are returned. See filtering. |
| `Sort`Type: [FPubnubMembershipSort](#fpubnubmembershipsort) | Key-value pair of a property to sort by, and a sort direction. |
| `Page`Type: [FPubnubPage](#fpubnubpage) | Cursor-based pagination. Use `Page.Next` and `Page.Prev` to request the next or previous page. |

#### FPubnubMembershipInclude

| Field Name | Type | Default Value | Description |
| --- | --- | --- | --- |
| `IncludeCustom` | bool | false | Whether to include the membership's `Custom` field. |
| `IncludeStatus` | bool | false | Whether to include the membership's `Status` field. |
| `IncludeType` | bool | false | Whether to include the membership's `Type` field. |
| `IncludeChannel` | bool | false | Whether to include the membership's Channel data field (in form of FPubnubChannelData). |
| `IncludeChannelCustom` | bool | false | Whether to include the membership's Channel Custom field. |
| `IncludeChannelStatus` | bool | false | Whether to include the membership's Channel Status field |
| `IncludeChannelType` | bool | false | Whether to include the membership's Channel Type field |
| `IncludeTotalCount` | bool | false | Whether to include the total count of memberships |

#### FPubnubMembershipSort

| Field Name | Type | Description |
| --- | --- | --- |
| `MembershipSort` | `TArray<FPubnubMembershipSingleSort>` | Array of sort criteria used in Membership-related functions. Order matters (applied in sequence). |

#### FPubnubMembershipSingleSort

| Field Name | Type | Default | Description |
| --- | --- | --- | --- |
| SortType | [EPubnubMembershipSortType](#epubnubmembershipsorttype) | `EPubnubMembershipSortType::PMST_ChannelID` | Field to sort by in the Membership context |
| SortOrder | bool | false | Ascending when false, descending when true |

#### EPubnubMembershipSortType

| Enum Value | Display Name | Description |
| --- | --- | --- |
| `PMST_ChannelID` | `ChannelID` | Sort by Channel ID |
| `PMST_ChannelName` | `ChannelName` | Sort by Channel Name |
| `PMST_ChannelUpdated` | `ChannelUpdated` | Sort by last update to the Channel |
| `PMST_ChannelStatus` | `ChannelStatus` | Sort by Channel Status |
| `PMST_ChannelType` | `ChannelType` | Sort by Channel Type |
| `PMST_Updated` | `Updated` | Sort by Membership update timestamp |
| `PMST_Status` | `Status` | Sort by Membership status |
| `PMST_Type` | `Type` | Sort by Membership type |

#### Sample code

:::tip Reference code
Set up your Unreal project and follow the instructions in the lines marked with
ACTION REQUIRED
before running the code.
:::

###### C++

#### Actor.h

```cpp
#include "PubnubClient.h"

// blueprint.cnuss9_f
UFUNCTION(BlueprintCallable, Category = "Pubnub|Samples|App Context")
void GetMembershipsSample();
	
UFUNCTION()
void OnGetMembershipsResponse_Simple(FPubnubOperationResult Result, const TArray<FPubnubMembershipData>& MembershipsData, FPubnubPage Page, int TotalCount);
	
```

#### Actor.cpp

```cpp
// ACTION REQUIRED: Replace ASample_Memberships with name of your Actor class
void ASample_Memberships::GetMembershipsSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set

	// Bind response delegate
	// ACTION REQUIRED: Replace ASample_Memberships with name of your Actor class
	FOnPubnubGetMembershipsResponse OnGetMembershipsResponse;
	OnGetMembershipsResponse.BindDynamic(this, &ASample_Memberships::OnGetMembershipsResponse_Simple);

	// Get memberships for a user
	FString UserID = TEXT("Player_001");
	PubnubClient->GetMembershipsAsync(UserID, OnGetMembershipsResponse);
}

// ACTION REQUIRED: Replace ASample_Memberships with name of your Actor class
void ASample_Memberships::OnGetMembershipsResponse_Simple(FPubnubOperationResult Result, const TArray<FPubnubMembershipData>& MembershipsData, FPubnubPage Page, int TotalCount)
{
	if(Result.Error)
	{
		UE_LOG(LogTemp, Error, TEXT("Failed to get memberships. Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
	}
	else
	{
		UE_LOG(LogTemp, Log, TEXT("Successfully got memberships. Count: %d"), MembershipsData.Num());
		for (const auto& Membership : MembershipsData)
		{
			UE_LOG(LogTemp, Log, TEXT("- Channel: %s"), *Membership.Channel.ChannelID);
		}
	}
}
```

###### Blueprint

#### Returns

* **Synchronous:** returns [FPubnubMembershipsResult](#fpubnubmembershipsresult) (Result, MembershipsData, Page, TotalCount).
* **Asynchronous:** delegate [FOnPubnubGetMembershipsResponse](#fonpubnubgetmembershipsresponse) receives (Result, MembershipsData, Page, TotalCount).

##### FPubnubMembershipsResult

| Field | Type | Description |
| --- | --- | --- |
| `Result` | [FPubnubOperationResult](https://www.pubnub.com/docs/sdks/unreal/api-reference/configuration#operation-result) | The result of the operation. |
| `MembershipsData` | `TArray<FPubnubMembershipData>` | Array of [FPubnubMembershipData](#fpubnubmembershipdata) structs which are the memberships. |
| `Page` | [FPubnubPage](#fpubnubpage) | Pagination cursor (Next, Prev) for requesting the next or previous page. |
| `TotalCount` | `int` | Total number of memberships matching the request (when requested). |

##### FOnPubnubGetMembershipsResponse

| Field | Type | Description |
| --- | --- | --- |
| `Result` | [FPubnubOperationResult](https://www.pubnub.com/docs/sdks/unreal/api-reference/configuration#operation-result) | The result of the operation. |
| `MembershipsData` | [const TArray<FPubnubMembershipData>&](#fpubnubmembershipdata) | Array of [FPubnubMembershipData](#fpubnubmembershipdata) structs which are the memberships. |
| `Page` | [FPubnubPage](#fpubnubpage) | Pagination cursor (Next, Prev) for requesting the next or previous page. |
| `TotalCount` | `int` | Total number of memberships matching the request (when requested). |

##### FPubnubMembershipData

| Field | Type | Description |
| --- | --- | --- |
| `Channel` | [FPubnubChannelData](#fpubnubchanneldata) | Contains channel metadata, including unique channel identifier and other relevant information. |
| `Custom` | `FString` | Custom JSON values. Can be strings, numbers, or booleans. Filtering by Custom isn’t supported. |
| `Status` | `FString` | Status of the membership. Max 50 characters. |
| `Type` | `FString` | Type of the membership. Max 50 characters. |
| `Updated` | `FString` | The date when the channel's membership was last updated. |
| `ETag` | `FString` | Version identifier of the membership metadata. |

##### FOnPubnubGetMembershipsResponseNative

| Field | Type | Description |
| --- | --- | --- |
| `Result` | [const FPubnubOperationResult&](https://www.pubnub.com/docs/sdks/unreal/api-reference/configuration#operation-result) | The result of the operation. |
| `MembershipsData` | [const TArray<FPubnubMembershipData>&](#fpubnubmembershipdata) | Array of [FPubnubMembershipData](#fpubnubmembershipdata) structs which are the memberships. |
| `Page` | [const FPubnubPage&](#fpubnubpage) | Pagination cursor (Next, Prev) for requesting the next or previous page. |
| `TotalCount` | `int` | Total number of memberships matching the request (when requested). |

#### Other examples

:::tip Reference code
Set up your Unreal project and follow the instructions in the lines marked with
ACTION REQUIRED
before running the code.
:::

##### Get memberships for a user with settings

###### Actor.h

```cpp
#include "PubnubClient.h"

UFUNCTION(BlueprintCallable, Category = "Pubnub|Samples|App Context")
void GetMembershipsWithSettingsSample();

UFUNCTION()
void OnGetMembershipsResponse_WithSettings(FPubnubOperationResult Result, const TArray<FPubnubMembershipData>& MembershipsData, FPubnubPage Page, int TotalCount);
```

###### Actor.cpp

```cpp
// ACTION REQUIRED: Replace ASample_Memberships with name of your Actor class
void ASample_Memberships::GetMembershipsWithSettingsSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set

	// Bind response delegate
	// ACTION REQUIRED: Replace ASample_Memberships with name of your Actor class
	FOnPubnubGetMembershipsResponse OnGetMembershipsResponse;
	OnGetMembershipsResponse.BindDynamic(this, &ASample_Memberships::OnGetMembershipsResponse_WithSettings);

	// Create settings
	FString UserID = TEXT("Player_002");
	FPubnubMembershipInclude Include = FPubnubMembershipInclude::FromValue(true);
	FString Filter = TEXT("status=='active'");
	FPubnubMembershipSort Sort;
	Sort.MembershipSort.Add(FPubnubMembershipSingleSort{EPubnubMembershipSortType::PMST_ChannelID, true});
	
	// Get memberships with custom settings
	PubnubClient->GetMembershipsAsync(UserID, OnGetMembershipsResponse, Include, 100, Filter, Sort);
}

// ACTION REQUIRED: Replace ASample_Memberships with name of your Actor class
void ASample_Memberships::OnGetMembershipsResponse_WithSettings(FPubnubOperationResult Result, const TArray<FPubnubMembershipData>& MembershipsData, FPubnubPage Page, int TotalCount)
{
	if(Result.Error)
	{
		UE_LOG(LogTemp, Error, TEXT("Failed to get memberships. Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
	}
	else
	{
		UE_LOG(LogTemp, Log, TEXT("Successfully got memberships with settings. Count: %d"), MembershipsData.Num());
		for (const auto& Membership : MembershipsData)
		{
			UE_LOG(LogTemp, Log, TEXT("- Channel: %s, Custom: %s"), *Membership.Channel.ChannelID, *Membership.Custom);
		}
	}
}
```

##### Get memberships for a user with lambda

###### Actor.h

```cpp
#include "PubnubClient.h"

UFUNCTION(BlueprintCallable, Category = "Pubnub|Samples|App Context")
void GetMembershipsWithLambdaSample();
```

###### Actor.cpp

```cpp
// ACTION REQUIRED: Replace ASample_Memberships with name of your Actor class
void ASample_Memberships::GetMembershipsWithLambdaSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set

	// Bind lambda to response delegate
	FOnPubnubGetMembershipsResponseNative OnGetMembershipsResponse;
	OnGetMembershipsResponse.BindLambda([](const FPubnubOperationResult& Result, const TArray<FPubnubMembershipData>& MembershipsData, FPubnubPage Page, int TotalCount)
	{
		if(Result.Error)
		{
			UE_LOG(LogTemp, Error, TEXT("Failed to get memberships. Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
		}
		else
		{
			UE_LOG(LogTemp, Log, TEXT("Successfully got memberships. Count: %d"), MembershipsData.Num());
			for (const auto& Membership : MembershipsData)
			{
				UE_LOG(LogTemp, Log, TEXT("- Channel: %s"), *Membership.Channel.ChannelID);
			}
		}
	});
	
	// Get memberships for a user
	FString UserID = TEXT("Player_003");
	PubnubClient->GetMembershipsAsync(UserID, OnGetMembershipsResponse);
}
```

##### Get memberships for a user with raw

###### Actor.h

```cpp
#include "PubnubClient.h"

UFUNCTION(BlueprintCallable, Category = "Pubnub|Samples|App Context")
void GetMembershipsRawSample();

UFUNCTION()
void OnGetMembershipsRawResponse(FPubnubOperationResult Result, const TArray<FPubnubMembershipData>& MembershipsData, FPubnubPage Page, int TotalCount);
```

###### Actor.cpp

```cpp
// ACTION REQUIRED: Replace ASample_Memberships with name of your Actor class
void ASample_Memberships::GetMembershipsRawSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set

	// Bind response delegate
	// ACTION REQUIRED: Replace ASample_Memberships with name of your Actor class
	FOnPubnubGetMembershipsResponse OnGetMembershipsResponse;
	OnGetMembershipsResponse.BindDynamic(this, &ASample_Memberships::OnGetMembershipsRawResponse);
	
	// Create settings as raw strings
	FString UserID = TEXT("Player_004");
	FString Include = "custom,channel.custom";
	FString Filter = TEXT("status=='active'");
	FString Sort = "channel.id:desc";
	
	// Get memberships with raw settings
	PubnubClient->GetMembershipsRawAsync(UserID, OnGetMembershipsResponse, Include, 100, Filter, Sort);
}

// ACTION REQUIRED: Replace ASample_Memberships with name of your Actor class
void ASample_Memberships::OnGetMembershipsRawResponse(FPubnubOperationResult Result, const TArray<FPubnubMembershipData>& MembershipsData, FPubnubPage Page, int TotalCount)
{
	if(Result.Error)
	{
		UE_LOG(LogTemp, Error, TEXT("Failed to get memberships (raw). Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
	}
	else
	{
		UE_LOG(LogTemp, Log, TEXT("Successfully got memberships (raw). Count: %d"), MembershipsData.Num());
		for (const auto& Membership : MembershipsData)
		{
			UE_LOG(LogTemp, Log, TEXT("- Channel: %s, Custom: %s"), *Membership.Channel.ChannelID, *Membership.Custom);
		}
	}
}
```

### Set channel memberships

Set channel memberships for a User.

#### Method(s)

```cpp
// Synchronous
FPubnubMembershipsResult Result = PubnubClient->SetMemberships(
    FString User,
    TArray<FPubnubMembershipInputData> Channels,
    FPubnubMembershipInclude Include = FPubnubMembershipInclude(),
    int Limit = 100,
    FString Filter = "",
    FPubnubMembershipSort Sort = FPubnubMembershipSort(),
    FPubnubPage Page = FPubnubPage()
);

// Asynchronous
PubnubClient->SetMembershipsAsync(
    FString User,
    TArray<FPubnubMembershipInputData> Channels,
    FOnPubnubSetMembershipsResponse OnSetMembershipsResponse,
    FPubnubMembershipInclude Include = FPubnubMembershipInclude(),
    int Limit = 100,
    FString Filter = "",
    FPubnubMembershipSort Sort = FPubnubMembershipSort(),
    FPubnubPage Page = FPubnubPage()
);
```

| Parameter | Description |
| --- | --- |
| `User` *Type: `FString` | The user UUID to add/update the memberships. Can't be empty. |
| `Channels` *Type: [TArray<FPubnubMembershipInputData>](#fpubnubmembershipinputdata) | The array of channel memberships to add/update. Can't be empty. |
| `OnSetMembershipsResponse`Type: [FOnPubnubSetMembershipsResponse](#fonpubnubsetmembershipsresponse) | The delegate for the operation's result. You can also use a native callback of the type [FOnPubnubSetMembershipsResponseNative](#fonpubnubsetmembershipsresponsenative) to handle the result using a lambda. |
| `Include`Type: [FPubnubMembershipInclude](#fpubnubmembershipinclude) | List of property names to include in the response. |
| `Limit`Type: `int` | The maximum number of memberships to return. |
| `Filter`Type: `FString` | The filter to apply to the memberships. |
| `Sort`Type: [FPubnubMembershipSort](#fpubnubmembershipsort) | The sort order to apply to the memberships. |
| `Page`Type: [FPubnubPage](#fpubnubpage) | Cursor-based pagination. Use `Page.Next` and `Page.Prev` to request the next or previous page. |

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

#### FPubnubMembershipInputData

| Field | Type | Description |
| --- | --- | --- |
| `Channel` | `FString` | The channel ID to add/update the membership. Can't be empty. |
| `Custom` | `FString` | The custom data to add/update the membership. |
| `Status` | `FString` | The status of the membership. |
| `Type` | `FString` | The type of the membership. |

#### Returns

* **Synchronous:** returns [FPubnubMembershipsResult](#fpubnubmembershipsresult) (Result, MembershipsData, Page, TotalCount).
* **Asynchronous:** delegate [FOnPubnubSetMembershipsResponse](#fonpubnubsetmembershipsresponse) receives (Result, MembershipsData, Page, TotalCount).

#### FOnPubnubSetMembershipsResponse

| Field | Type | Description |
| --- | --- | --- |
| `Result` | [FPubnubOperationResult](https://www.pubnub.com/docs/sdks/unreal/api-reference/configuration#operation-result) | The result of the operation. |
| `MembershipsData` | [const TArray<FPubnubMembershipData>&](#fpubnubmembershipdata) | Array of [FPubnubMembershipData](#fpubnubmembershipdata) structs which are the memberships. |
| `Page` | [FPubnubPage](#fpubnubpage) | Pagination cursor (Next, Prev) for requesting the next or previous page. |
| `TotalCount` | `int` | Total number of memberships matching the request (when requested). |

#### FOnPubnubSetMembershipsResponseNative

| Field | Type | Description |
| --- | --- | --- |
| `Result` | [const FPubnubOperationResult&](https://www.pubnub.com/docs/sdks/unreal/api-reference/configuration#operation-result) | The result of the operation. |
| `MembershipsData` | [const TArray<FPubnubMembershipData>&](#fpubnubmembershipdata) | Array of [FPubnubMembershipData](#fpubnubmembershipdata) structs which are the memberships. |
| `Page` | [const FPubnubPage&](#fpubnubpage) | Pagination cursor (Next, Prev) for requesting the next or previous page. |
| `TotalCount` | `int` | Total number of memberships matching the request (when requested). |

#### Sample code

:::tip Reference code
Set up your Unreal project and follow the instructions in the lines marked with
ACTION REQUIRED
before running the code.
:::

###### C++

#### Actor.h

```cpp
#include "PubnubClient.h"

// blueprint.3mw6rugy
UFUNCTION(BlueprintCallable, Category = "Pubnub|Samples|App Context")
void SetMembershipsSample();
```

#### Actor.cpp

```cpp
// ACTION REQUIRED: Replace ASample_Memberships with name of your Actor class
void ASample_Memberships::SetMembershipsSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set

	// Create memberships data
	TArray<FPubnubMembershipInputData> MembershipsToSet;
	FPubnubMembershipInputData Membership1;
	Membership1.Channel = "general-chat-channel";
	Membership1.Type = "standard";
	MembershipsToSet.Add(Membership1);
	
	FPubnubMembershipInputData Membership2;
	Membership2.Channel = "trade-chat-channel";
	Membership2.Custom = "{\"is_moderator\": true}";
	Membership2.Status = "active";
	MembershipsToSet.Add(Membership2);
	
	// Set memberships for the user
	FString UserID = TEXT("Player_001");
	PubnubClient->SetMembershipsAsync(UserID, MembershipsToSet);
}
```

###### Blueprint

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

#### Other examples

:::tip Reference code
Set up your Unreal project and follow the instructions in the lines marked with
ACTION REQUIRED
before running the code.
:::

##### Set memberships for a user with result

###### Actor.h

```cpp
#include "PubnubClient.h"

UFUNCTION(BlueprintCallable, Category = "Pubnub|Samples|App Context")
void SetMembershipsWithResultSample();

UFUNCTION()
void OnSetMembershipsResponse(FPubnubOperationResult Result, const TArray<FPubnubMembershipData>& MembershipsData, FPubnubPage Page, int TotalCount);
```

###### Actor.cpp

```cpp
// ACTION REQUIRED: Replace ASample_Memberships with name of your Actor class
void ASample_Memberships::SetMembershipsWithResultSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set

	// Bind response delegate
	// ACTION REQUIRED: Replace ASample_Memberships with name of your Actor class
	FOnPubnubSetMembershipsResponse OnSetMembershipsResponse;
	OnSetMembershipsResponse.BindDynamic(this, &ASample_Memberships::OnSetMembershipsResponse);
	
	// Create memberships data
	TArray<FPubnubMembershipInputData> MembershipsToSet;
	FPubnubMembershipInputData Membership1;
	Membership1.Channel = "guild-hall-channel";
	Membership1.Status = "pending";
	MembershipsToSet.Add(Membership1);

	// Set memberships and include extra data in the response
	FString UserID = TEXT("Player_002");
	FPubnubMembershipInclude Include = FPubnubMembershipInclude::FromValue(true);
	PubnubClient->SetMembershipsAsync(UserID, MembershipsToSet, OnSetMembershipsResponse, Include);
}

// ACTION REQUIRED: Replace ASample_Memberships with name of your Actor class
void ASample_Memberships::OnSetMembershipsResponse(FPubnubOperationResult Result, const TArray<FPubnubMembershipData>& MembershipsData, FPubnubPage Page, int TotalCount)
{
	if(Result.Error)
	{
		UE_LOG(LogTemp, Error, TEXT("Failed to set memberships. Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
	}
	else
	{
		UE_LOG(LogTemp, Log, TEXT("Successfully set memberships. Count: %d"), MembershipsData.Num());
		for (const auto& Membership : MembershipsData)
		{
			UE_LOG(LogTemp, Log, TEXT("- Channel: %s, Type: %s, Status: %s, Custom: %s"), *Membership.Channel.ChannelID, *Membership.Type, *Membership.Status, *Membership.Custom);
		}
	}
}
```

##### Set memberships for a user with lambda

###### Actor.h

```cpp
#include "PubnubClient.h"

UFUNCTION(BlueprintCallable, Category = "Pubnub|Samples|App Context")
void SetMembershipsWithLambdaSample();
```

###### Actor.cpp

```cpp
// ACTION REQUIRED: Replace ASample_Memberships with name of your Actor class
void ASample_Memberships::SetMembershipsWithLambdaSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set

	// Bind lambda to response delegate
	FOnPubnubSetMembershipsResponseNative OnSetMembershipsResponse;
	OnSetMembershipsResponse.BindLambda([](const FPubnubOperationResult& Result, const TArray<FPubnubMembershipData>& MembershipsData, FPubnubPage Page, int TotalCount)
	{
		if(Result.Error)
		{
			UE_LOG(LogTemp, Error, TEXT("Failed to set memberships. Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
		}
		else
		{
			UE_LOG(LogTemp, Log, TEXT("Successfully set memberships. Count: %d"), MembershipsData.Num());
			for (const auto& Membership : MembershipsData)
			{
				UE_LOG(LogTemp, Log, TEXT("- Channel: %s, Type: %s, Status: %s, Custom: %s"), *Membership.Channel.ChannelID, *Membership.Type, *Membership.Status, *Membership.Custom);
			}
		}
	});

	// Create memberships data
	TArray<FPubnubMembershipInputData> MembershipsToSet;
	FPubnubMembershipInputData Membership1;
	Membership1.Channel = "private-lounge-channel";
	Membership1.Type = "premium";
	MembershipsToSet.Add(Membership1);
	
	// Set memberships and include extra data in the response
	FString UserID = TEXT("Player_003");
	FPubnubMembershipInclude Include = FPubnubMembershipInclude::FromValue(true);
	PubnubClient->SetMembershipsAsync(UserID, MembershipsToSet, OnSetMembershipsResponse, Include);
}
```

##### Set memberships for a user with raw

###### Actor.h

```cpp
#include "PubnubClient.h"

UFUNCTION(BlueprintCallable, Category = "Pubnub|Samples|App Context")
void SetMembershipsRawSample();
	
UFUNCTION()
void OnSetMembershipsRawResponse(FPubnubOperationResult Result, const TArray<FPubnubMembershipData>& MembershipsData, FPubnubPage Page, int TotalCount);
```

###### Actor.cpp

```cpp
// ACTION REQUIRED: Replace ASample_Memberships with name of your Actor class
void ASample_Memberships::SetMembershipsRawSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set

	// Bind response delegate
	// ACTION REQUIRED: Replace ASample_Memberships with name of your Actor class
	FOnPubnubSetMembershipsResponse OnSetMembershipsResponse;
	OnSetMembershipsResponse.BindDynamic(this, &ASample_Memberships::OnSetMembershipsRawResponse);
	
	// Create memberships data as a raw JSON string
	FString MembershipsJson = R"([{"channel": {"id": "arena-channel"}, "custom": {"rank": "diamond"}, "status": "active"}, {"channel": {"id": "spectator-channel"}, "type": "viewer"}])";
	
	// Set memberships with raw JSON and includes
	FString UserID = TEXT("Player_004");
	FString Include = "custom,status,type,channel.custom";
	PubnubClient->SetMembershipsRawAsync(UserID, MembershipsJson, OnSetMembershipsResponse, Include);
}

// ACTION REQUIRED: Replace ASample_Memberships with name of your Actor class
void ASample_Memberships::OnSetMembershipsRawResponse(FPubnubOperationResult Result, const TArray<FPubnubMembershipData>& MembershipsData, FPubnubPage Page, int TotalCount)
{
	if(Result.Error)
	{
		UE_LOG(LogTemp, Error, TEXT("Failed to set memberships. Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
	}
	else
	{
		UE_LOG(LogTemp, Log, TEXT("Successfully set memberships. Count: %d"), MembershipsData.Num());
		for (const auto& Membership : MembershipsData)
		{
			UE_LOG(LogTemp, Log, TEXT("- Channel: %s, Type: %s, Status: %s, Custom: %s"), *Membership.Channel.ChannelID, *Membership.Type, *Membership.Status, *Membership.Custom);
		}
	}
}
```

### Remove Channel Memberships

Remove channel memberships for a user.

#### Method(s)

```cpp
// Synchronous
FPubnubMembershipsResult Result = PubnubClient->RemoveMemberships(
    FString User,
    TArray<FString> Channels,
    FPubnubMembershipInclude Include = FPubnubMembershipInclude(),
    int Limit = 100,
    FString Filter = "",
    FPubnubMembershipSort Sort = FPubnubMembershipSort(),
    FPubnubPage Page = FPubnubPage()
);

// Asynchronous
PubnubClient->RemoveMembershipsAsync(
    FString User,
    TArray<FString> Channels,
    FOnPubnubRemoveMembershipsResponse OnRemoveMembershipsResponse,
    FPubnubMembershipInclude Include = FPubnubMembershipInclude(),
    int Limit = 100,
    FString Filter = "",
    FPubnubMembershipSort Sort = FPubnubMembershipSort(),
    FPubnubPage Page = FPubnubPage()
);
```

| Parameter | Description |
| --- | --- |
| `User` *Type: `FString` | The user UUID to remove the memberships. Can't be empty. |
| `Channels` *Type: `TArray<FString>` | The array of channel IDs to remove the memberships. Can't be empty. |
| `OnRemoveMembershipsResponse`Type: [FOnPubnubRemoveMembershipsResponse](#fonpubnubremovemembershipsresponse) | The delegate for the operation's result. You can also use a native callback of the type [FOnPubnubRemoveMembershipsResponseNative](#fonpubnubremovemembershipsresponsenative) to handle the result using a lambda. |
| `Include`Type: [FPubnubMembershipInclude](#fpubnubmembershipinclude) | List of property names to include in the response. |
| `Limit`Type: `int` | The maximum number of memberships to return. |
| `Filter`Type: `FString` | The filter to apply to the memberships. |
| `Sort`Type: [FPubnubMembershipSort](#fpubnubmembershipsort) | The sort order to apply to the memberships. |
| `Page`Type: [FPubnubPage](#fpubnubpage) | Cursor-based pagination. Use `Page.Next` and `Page.Prev` to request the next or previous page. |

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

#### Sample code

:::tip Reference code
Set up your Unreal project and follow the instructions in the lines marked with
ACTION REQUIRED
before running the code.
:::

###### C++

#### Actor.h

```cpp
#include "PubnubClient.h"

// blueprint.zpirbmkw
UFUNCTION(BlueprintCallable, Category = "Pubnub|Samples|App Context")
void RemoveMembershipsSample();
```

#### Actor.cpp

```cpp
// ACTION REQUIRED: Replace ASample_Memberships with name of your Actor class
void ASample_Memberships::RemoveMembershipsSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set

	// Create a list of channel IDs to remove memberships from
	TArray<FString> ChannelsToRemove;
	ChannelsToRemove.Add("general-chat-channel");
	ChannelsToRemove.Add("trade-chat-channel");
	
	// Remove memberships for the user
	FString UserID = TEXT("Player_001");
	PubnubClient->RemoveMembershipsAsync(UserID, ChannelsToRemove);
}
```

###### Blueprint

#### Returns

* **Synchronous:** returns [FPubnubMembershipsResult](#fpubnubmembershipsresult) (Result, MembershipsData, Page, TotalCount).
* **Asynchronous:** delegate [FOnPubnubRemoveMembershipsResponse](#fonpubnubremovemembershipsresponse) receives (Result, MembershipsData, Page, TotalCount).

##### FOnPubnubRemoveMembershipsResponse

| Field | Type | Description |
| --- | --- | --- |
| `Result` | [FPubnubOperationResult](https://www.pubnub.com/docs/sdks/unreal/api-reference/configuration#operation-result) | The result of the operation. |
| `MembershipsData` | [const TArray<FPubnubMembershipData>&](#fpubnubmembershipdata) | Array of [FPubnubMembershipData](#fpubnubmembershipdata) structs which are the memberships. |
| `Page` | [FPubnubPage](#fpubnubpage) | Pagination cursor (Next, Prev) for requesting the next or previous page. |
| `TotalCount` | `int` | Total number of memberships matching the request (when requested). |

##### FOnPubnubRemoveMembershipsResponseNative

| Field | Type | Description |
| --- | --- | --- |
| `Result` | [const FPubnubOperationResult&](https://www.pubnub.com/docs/sdks/unreal/api-reference/configuration#operation-result) | The result of the operation. |
| `MembershipsData` | [const TArray<FPubnubMembershipData>&](#fpubnubmembershipdata) | Array of [FPubnubMembershipData](#fpubnubmembershipdata) structs which are the memberships. |
| `Page` | [const FPubnubPage&](#fpubnubpage) | Pagination cursor (Next, Prev) for requesting the next or previous page. |
| `TotalCount` | `int` | Total number of memberships matching the request (when requested). |

#### Other examples

:::tip Reference code
Set up your Unreal project and follow the instructions in the lines marked with
ACTION REQUIRED
before running the code.
:::

##### Remove memberships for a user with result

###### Actor.h

```cpp
#include "PubnubClient.h"

UFUNCTION(BlueprintCallable, Category = "Pubnub|Samples|App Context")
void RemoveMembershipsWithResultSample();

UFUNCTION()
void OnRemoveMembershipsResponse(FPubnubOperationResult Result, const TArray<FPubnubMembershipData>& MembershipsData, FPubnubPage Page, int TotalCount);
```

###### Actor.cpp

```cpp
// ACTION REQUIRED: Replace ASample_Memberships with name of your Actor class
void ASample_Memberships::RemoveMembershipsWithResultSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set

	// Bind response delegate
	// ACTION REQUIRED: Replace ASample_Memberships with name of your Actor class
	FOnPubnubRemoveMembershipsResponse OnRemoveMembershipsResponse;
	OnRemoveMembershipsResponse.BindDynamic(this, &ASample_Memberships::OnRemoveMembershipsResponse);
	
	// Create a list of channel IDs to remove memberships from
	TArray<FString> ChannelsToRemove;
	ChannelsToRemove.Add("guild-hall-channel");

	// Remove memberships and include extra data in the response
	FString UserID = TEXT("Player_002");
	FPubnubMembershipInclude Include = FPubnubMembershipInclude::FromValue(true);
	PubnubClient->RemoveMembershipsAsync(UserID, ChannelsToRemove, OnRemoveMembershipsResponse, Include);
}

// ACTION REQUIRED: Replace ASample_Memberships with name of your Actor class
void ASample_Memberships::OnRemoveMembershipsResponse(FPubnubOperationResult Result, const TArray<FPubnubMembershipData>& MembershipsData, FPubnubPage Page, int TotalCount)
{
	if(Result.Error)
	{
		UE_LOG(LogTemp, Error, TEXT("Failed to remove memberships. Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
	}
	else
	{
		UE_LOG(LogTemp, Log, TEXT("Successfully removed memberships. Count: %d"), MembershipsData.Num());
	}
}
```

##### Remove memberships for a user with lambda

###### Actor.h

```cpp
#include "PubnubClient.h"

UFUNCTION(BlueprintCallable, Category = "Pubnub|Samples|App Context")
void RemoveMembershipsWithLambdaSample();
```

###### Actor.cpp

```cpp
// ACTION REQUIRED: Replace ASample_Memberships with name of your Actor class
void ASample_Memberships::RemoveMembershipsWithLambdaSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set

	// Bind lambda to response delegate
	FOnPubnubRemoveMembershipsResponseNative OnRemoveMembershipsResponse;
	OnRemoveMembershipsResponse.BindLambda([](const FPubnubOperationResult& Result, const TArray<FPubnubMembershipData>& MembershipsData, FPubnubPage Page, int TotalCount)
	{
		if(Result.Error)
		{
			UE_LOG(LogTemp, Error, TEXT("Failed to remove memberships. Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
		}
		else
		{
			UE_LOG(LogTemp, Log, TEXT("Successfully removed memberships. Count: %d"), MembershipsData.Num());
		}
	});

	// Create a list of channel IDs to remove memberships from
	TArray<FString> ChannelsToRemove;
	ChannelsToRemove.Add("private-lounge-channel");
	
	// Remove memberships and include extra data in the response
	FString UserID = TEXT("Player_003");
	FPubnubMembershipInclude Include = FPubnubMembershipInclude::FromValue(true);
	PubnubClient->RemoveMembershipsAsync(UserID, ChannelsToRemove, OnRemoveMembershipsResponse, Include);
}
```

##### Remove memberships for a user with raw

###### Actor.h

```cpp
#include "PubnubClient.h"

UFUNCTION(BlueprintCallable, Category = "Pubnub|Samples|App Context")
void RemoveMembershipsRawSample();
	
UFUNCTION()
void OnRemoveMembershipsRawResponse(FPubnubOperationResult Result, const TArray<FPubnubMembershipData>& MembershipsData, FPubnubPage Page, int TotalCount);
```

###### Actor.cpp

```cpp
// ACTION REQUIRED: Replace ASample_Memberships with name of your Actor class
void ASample_Memberships::RemoveMembershipsRawSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set

	// Bind response delegate
	// ACTION REQUIRED: Replace ASample_Memberships with name of your Actor class
	FOnPubnubRemoveMembershipsResponse OnRemoveMembershipsResponse;
	OnRemoveMembershipsResponse.BindDynamic(this, &ASample_Memberships::OnRemoveMembershipsRawResponse);
	
	// Create memberships data as a raw JSON string
	FString MembershipsJson = R"([{"channel": {"id": "arena-channel"}}, {"channel": {"id": "spectator-channel"}}])";
	
	// Remove memberships with raw JSON and includes
	FString UserID = TEXT("Player_004");
	FString Include = "custom,channel.custom";
	PubnubClient->RemoveMembershipsRawAsync(UserID, MembershipsJson, OnRemoveMembershipsResponse, Include);
}

// ACTION REQUIRED: Replace ASample_Memberships with name of your Actor class
void ASample_Memberships::OnRemoveMembershipsRawResponse(FPubnubOperationResult Result, const TArray<FPubnubMembershipData>& MembershipsData, FPubnubPage Page, int TotalCount)
{
	if(Result.Error)
	{
		UE_LOG(LogTemp, Error, TEXT("Failed to remove memberships. Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
	}
	else
	{
		UE_LOG(LogTemp, Log, TEXT("Successfully removed memberships. Count: %d"), MembershipsData.Num());
	}
}
```

## Channel members

### Get channel members

The method returns a list of members in a channel. The list will include user metadata for members that have additional metadata stored in the database.

#### Method(s)

:::tip Method variants
You can also call the `GetChannelMembersRaw` variant of this method which takes String values for `Include`, and `Sort` instead of the `FPubnubMemberInclude` and `FPubnubMemberSort` structs.
:::

```cpp
// Synchronous
FPubnubChannelMembersResult Result = PubnubClient->GetChannelMembers(
    FString Channel,
    FPubnubMemberInclude Include = FPubnubMemberInclude(),
    int Limit = 100,
    FString Filter = "",
    FPubnubMemberSort Sort = FPubnubMemberSort(),
    FPubnubPage Page = FPubnubPage()
);

// Asynchronous
PubnubClient->GetChannelMembersAsync(
    FString Channel,
    FOnPubnubGetChannelMembersResponse OnGetChannelMembersResponse,
    FPubnubMemberInclude Include = FPubnubMemberInclude(),
    int Limit = 100,
    FString Filter = "",
    FPubnubMemberSort Sort = FPubnubMemberSort(),
    FPubnubPage Page = FPubnubPage()
);
```

| Parameter | Description |
| --- | --- |
| `Channel` *Type: `FString` | The Channel ID for which to retrieve members. |
| `OnGetChannelMembersResponse`Type: [FOnPubnubGetChannelMembersResponse](#fonpubnubgetchannelmembersresponse) | The delegate for the operation's result. You can also use a native callback of the type [FOnPubnubGetChannelMembersResponseNative](#fonpubnubgetchannelmembersresponsenative) to handle the result using a lambda. |
| `Include`Type: [FPubnubMemberInclude](#fpubnubmemberinclude) | List of property names to include in the response. |
| `Limit`Type: int | Number of objects to return. Default/Max: 100. |
| `Filter`Type: `FString` | Expression used to filter the results. Check online documentation to see exact filter formulas. |
| `Sort`Type: [FPubnubMemberSort](#fpubnubmembersort) | Key-value pair of a property to sort by, and a sort direction. |
| `Page`Type: [FPubnubPage](#fpubnubpage) | Cursor-based pagination. Use `Page.Next` and `Page.Prev` to request the next or previous page. |

#### FPubnubMemberInclude

| Field Name | Type | Default | Description |
| --- | --- | --- | --- |
| `IncludeCustom` | bool | false | Whether to include the member's `Custom` field |
| `IncludeStatus` | bool | false | Whether to include the member's `Status` field |
| `IncludeType` | bool | false | Whether to include the member's `Type` field |
| `IncludeUUID` | bool | false | Whether to include the member's User data (FPubnubUUIDMetadata) |
| `IncludeUUIDCustom` | bool | false | Whether to include the member's User Custom field |
| `IncludeUUIDStatus` | bool | false | Whether to include the member's User Status field |
| `IncludeUUIDType` | bool | false | Whether to include the member's User Type field |
| `IncludeTotalCount` | bool | false | Whether to include the total count of paginated records |

#### FPubnubMemberSort

| Field Name | Type | Description |
| --- | --- | --- |
| `MemberSort` | `TArray<FPubnubMemberSingleSort>` | Array of sort criteria used in Member-related functions. Order matters (applied in sequence). |

#### FPubnubMemberSingleSort

| Field Name | Type | Default | Description |
| --- | --- | --- | --- |
| SortType | [EPubnubMemberSortType](#epubnubmembersorttype) | `EPubnubMemberSortType::PMeST_UserID` | Field to sort by in the Member context |
| SortOrder | bool | false | Ascending when false, descending when true |

#### EPubnubMemberSortType

| Enum Value | Display Name | Description |
| --- | --- | --- |
| `PMeST_UserID` | `UserID` | Sort by Member's User ID |
| `PMeST_UserName` | `UserName` | Sort by Member's User Name |
| `PMeST_UserUpdated` | `UserUpdated` | Sort by when the User was updated |
| `PMeST_UserStatus` | `UserStatus` | Sort by User Status |
| `PMeST_UserType` | `UserType` | Sort by User Type |
| `PMeST_Updated` | `Updated` | Sort by Member record update timestamp |
| `PMeST_Status` | `Status` | Sort by Member Status |
| `PMeST_Type` | `Type` | Sort by Member Type |

#### Sample code

:::tip Reference code
Set up your Unreal project and follow the instructions in the lines marked with
ACTION REQUIRED
before running the code.
:::

###### C++

#### Actor.h

```cpp
#include "PubnubClient.h"

// blueprint.reh47h3d
UFUNCTION(BlueprintCallable, Category = "Pubnub|Samples|App Context")
void GetChannelMembersSample();
	
UFUNCTION()
void OnGetChannelMembersResponse_Simple(FPubnubOperationResult Result, const TArray<FPubnubChannelMemberData>& MembersData, FPubnubPage Page, int TotalCount);
	
```

#### Actor.cpp

```cpp
// ACTION REQUIRED: Replace ASample_Memberships with name of your Actor class
void ASample_Memberships::GetChannelMembersSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set

	// Bind response delegate
	// ACTION REQUIRED: Replace ASample_Memberships with name of your Actor class
	FOnPubnubGetChannelMembersResponse OnGetChannelMembersResponse;
	OnGetChannelMembersResponse.BindDynamic(this, &ASample_Memberships::OnGetChannelMembersResponse_Simple);

	// Get members for a channel
	PubnubClient->GetChannelMembersAsync("general-chat-channel", OnGetChannelMembersResponse);
}

// ACTION REQUIRED: Replace ASample_Memberships with name of your Actor class
void ASample_Memberships::OnGetChannelMembersResponse_Simple(FPubnubOperationResult Result, const TArray<FPubnubChannelMemberData>& MembersData, FPubnubPage Page, int TotalCount)
{
	if(Result.Error)
	{
		UE_LOG(LogTemp, Error, TEXT("Failed to get channel members. Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
	}
	else
	{
		UE_LOG(LogTemp, Log, TEXT("Successfully got channel members. Count: %d"), MembersData.Num());
		for (const auto& Member : MembersData)
		{
			UE_LOG(LogTemp, Log, TEXT("- User: %s"), *Member.User.UserID);
		}
	}
}
```

###### Blueprint

#### Returns

* **Synchronous:** returns [FPubnubChannelMembersResult](#fpubnubchannelmembersresult) (Result, MembersData, Page, TotalCount).
* **Asynchronous:** delegate [FOnPubnubGetChannelMembersResponse](#fonpubnubgetchannelmembersresponse) receives (Result, MembersData, Page, TotalCount).

##### FPubnubChannelMembersResult

| Field | Type | Description |
| --- | --- | --- |
| `Result` | [FPubnubOperationResult](https://www.pubnub.com/docs/sdks/unreal/api-reference/configuration#operation-result) | The result of the operation. |
| `MembersData` | `TArray<FPubnubChannelMemberData>` | Array of [FPubnubChannelMemberData](#fpubnubchannelmemberdata) structs which are the members of the channel. |
| `Page` | [FPubnubPage](#fpubnubpage) | Pagination cursor (Next, Prev) for requesting the next or previous page. |
| `TotalCount` | `int` | Total number of members matching the request (when requested). |

##### FOnPubnubGetChannelMembersResponse

| Field | Type | Description |
| --- | --- | --- |
| `Result` | [FPubnubOperationResult](https://www.pubnub.com/docs/sdks/unreal/api-reference/configuration#operation-result) | The result of the operation. |
| `MembersData` | [const TArray<FPubnubChannelMemberData>&](#fpubnubchannelmemberdata) | Array of [FPubnubChannelMemberData](#fpubnubchannelmemberdata) structs which are the members of the channel. |
| `Page` | [FPubnubPage](#fpubnubpage) | Pagination cursor (Next, Prev) for requesting the next or previous page. |
| `TotalCount` | `int` | Total number of members matching the request (when requested). |

##### FPubnubChannelMemberData

| Field | Type | Description |
| --- | --- | --- |
| `User` | [FPubnubUserData](#fpubnubuserdata) | Contains user metadata, including unique user identifier and other relevant information. |
| `Custom` | `FString` | Custom JSON values. Can be strings, numbers, or booleans. Filtering by Custom isn't supported. |
| `Status` | `FString` | Status of the member. Max 50 characters. |
| `Type` | `FString` | Type of the member. Max 50 characters. |
| `Updated` | `FString` | The date when the channel's member was last updated. |
| `ETag` | `FString` | Version identifier of the member metadata. |

##### FOnPubnubGetChannelMembersResponseNative

| Field | Type | Description |
| --- | --- | --- |
| `Result` | [const FPubnubOperationResult&](https://www.pubnub.com/docs/sdks/unreal/api-reference/configuration#operation-result) | The result of the operation. |
| `MembersData` | [const TArray<FPubnubChannelMemberData>&](#fpubnubchannelmemberdata) | Array of [FPubnubChannelMemberData](#fpubnubchannelmemberdata) structs which are the members of the channel. |
| `Page` | [const FPubnubPage&](#fpubnubpage) | Pagination cursor (Next, Prev) for requesting the next or previous page. |
| `TotalCount` | `int` | Total number of members matching the request (when requested). |

#### Other examples

:::tip Reference code
Set up your Unreal project and follow the instructions in the lines marked with
ACTION REQUIRED
before running the code.
:::

##### Get channel members with settings

###### Actor.h

```cpp
#include "PubnubClient.h"

UFUNCTION(BlueprintCallable, Category = "Pubnub|Samples|App Context")
void GetChannelMembersWithSettingsSample();

UFUNCTION()
void OnGetChannelMembersResponse_WithSettings(FPubnubOperationResult Result, const TArray<FPubnubChannelMemberData>& MembersData, FPubnubPage Page, int TotalCount);
```

###### Actor.cpp

```cpp
// ACTION REQUIRED: Replace ASample_Memberships with name of your Actor class
void ASample_Memberships::GetChannelMembersWithSettingsSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set

	// Bind response delegate
	// ACTION REQUIRED: Replace ASample_Memberships with name of your Actor class
	FOnPubnubGetChannelMembersResponse OnGetChannelMembersResponse;
	OnGetChannelMembersResponse.BindDynamic(this, &ASample_Memberships::OnGetChannelMembersResponse_WithSettings);

	// Create settings
	FPubnubMemberInclude Include = FPubnubMemberInclude::FromValue(true);
	FString Filter = TEXT("status=='active'");
	FPubnubMemberSort Sort;
	Sort.MemberSort.Add(FPubnubMemberSingleSort{EPubnubMemberSortType::PMeST_UserID, true});
	
	// Get members with custom settings
	PubnubClient->GetChannelMembersAsync("guild-hall-channel", OnGetChannelMembersResponse, Include, 100, Filter, Sort);
}

// ACTION REQUIRED: Replace ASample_Memberships with name of your Actor class
void ASample_Memberships::OnGetChannelMembersResponse_WithSettings(FPubnubOperationResult Result, const TArray<FPubnubChannelMemberData>& MembersData, FPubnubPage Page, int TotalCount)
{
	if(Result.Error)
	{
		UE_LOG(LogTemp, Error, TEXT("Failed to get channel members. Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
	}
	else
	{
		UE_LOG(LogTemp, Log, TEXT("Successfully got channel members with settings. Count: %d"), MembersData.Num());
		for (const auto& Member : MembersData)
		{
			UE_LOG(LogTemp, Log, TEXT("- User: %s, Custom: %s"), *Member.User.UserID, *Member.Custom);
		}
	}
}
```

##### Get channel members with lambda

###### Actor.h

```cpp
#include "PubnubClient.h"

UFUNCTION(BlueprintCallable, Category = "Pubnub|Samples|App Context")
void GetChannelMembersWithLambdaSample();
```

###### Actor.cpp

```cpp
// ACTION REQUIRED: Replace ASample_Memberships with name of your Actor class
void ASample_Memberships::GetChannelMembersWithLambdaSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set

	// Bind lambda to response delegate
	FOnPubnubGetChannelMembersResponseNative OnGetChannelMembersResponse;
	OnGetChannelMembersResponse.BindLambda([](const FPubnubOperationResult& Result, const TArray<FPubnubChannelMemberData>& MembersData, FPubnubPage Page, int TotalCount)
	{
		if(Result.Error)
		{
			UE_LOG(LogTemp, Error, TEXT("Failed to get channel members. Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
		}
		else
		{
			UE_LOG(LogTemp, Log, TEXT("Successfully got channel members. Count: %d"), MembersData.Num());
			for (const auto& Member : MembersData)
			{
				UE_LOG(LogTemp, Log, TEXT("- User: %s"), *Member.User.UserID);
			}
		}
	});
	
	// Get members for a channel
	PubnubClient->GetChannelMembersAsync("private-lounge-channel", OnGetChannelMembersResponse);
}
```

##### Get channel members raw

###### Actor.h

```cpp
#include "PubnubClient.h"

UFUNCTION(BlueprintCallable, Category = "Pubnub|Samples|App Context")
void GetChannelMembersRawSample();

UFUNCTION()
void OnGetChannelMembersRawResponse(FPubnubOperationResult Result, const TArray<FPubnubChannelMemberData>& MembersData, FPubnubPage Page, int TotalCount);
```

###### Actor.cpp

```cpp
// ACTION REQUIRED: Replace ASample_Memberships with name of your Actor class
void ASample_Memberships::GetChannelMembersRawSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set

	// Bind response delegate
	// ACTION REQUIRED: Replace ASample_Memberships with name of your Actor class
	FOnPubnubGetChannelMembersResponse OnGetChannelMembersResponse;
	OnGetChannelMembersResponse.BindDynamic(this, &ASample_Memberships::OnGetChannelMembersRawResponse);
	
	// Create settings as raw strings
	FString Include = "custom,user.custom";
	FString Filter = TEXT("status=='active'");
	FString Sort = "user.id:desc";
	
	// Get members with raw settings
	PubnubClient->GetChannelMembersRawAsync("arena-channel", OnGetChannelMembersResponse, Include, 100, Filter, Sort);
}

// ACTION REQUIRED: Replace ASample_Memberships with name of your Actor class
void ASample_Memberships::OnGetChannelMembersRawResponse(FPubnubOperationResult Result, const TArray<FPubnubChannelMemberData>& MembersData, FPubnubPage Page, int TotalCount)
{
	if(Result.Error)
	{
		UE_LOG(LogTemp, Error, TEXT("Failed to get channel members (raw). Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
	}
	else
	{
		UE_LOG(LogTemp, Log, TEXT("Successfully got channel members (raw). Count: %d"), MembersData.Num());
		for (const auto& Member : MembersData)
		{
			UE_LOG(LogTemp, Log, TEXT("- User: %s, Custom: %s"), *Member.User.UserID, *Member.Custom);
		}
	}
}
```

### Set channel members

This method sets members in a channel.

#### Method(s)

```cpp
// Synchronous
FPubnubChannelMembersResult Result = PubnubClient->SetChannelMembers(
    FString Channel,
    TArray<FPubnubChannelMemberInputData> Users,
    FPubnubMemberInclude Include = FPubnubMemberInclude(),
    int Limit = 100,
    FString Filter = "",
    FPubnubMemberSort Sort = FPubnubMemberSort(),
    FPubnubPage Page = FPubnubPage()
);

// Asynchronous
PubnubClient->SetChannelMembersAsync(
    FString Channel,
    TArray<FPubnubChannelMemberInputData> Users,
    FOnPubnubSetChannelMembersResponse OnSetChannelMembersResponse,
    FPubnubMemberInclude Include = FPubnubMemberInclude(),
    int Limit = 100,
    FString Filter = "",
    FPubnubMemberSort Sort = FPubnubMemberSort(),
    FPubnubPage Page = FPubnubPage()
);
```

| Parameter | Description |
| --- | --- |
| `Channel` *Type: `FString` | The channel ID to add/update the members. Can't be empty. |
| `Users` *Type: [TArray<FPubnubChannelMemberInputData>](#fpubnubchannelmemberinputdata) | The array of channel members to add/update. Can't be empty. |
| `OnSetChannelMembersResponse`Type: [FOnPubnubSetChannelMembersResponse](#fonpubnubsetchannelmembersresponse) | The delegate for the operation's result. You can also use a native callback of the type [FOnPubnubSetChannelMembersResponseNative](#fonpubnubsetchannelmembersresponsenative) to handle the result using a lambda. |
| `Include`Type: [FPubnubMemberInclude](#fpubnubmemberinclude) | List of property names to include in the response. |
| `Limit`Type: `int` | The maximum number of members to return. |
| `Filter`Type: `FString` | The filter to apply to the members. |
| `Sort`Type: [FPubnubMemberSort](#fpubnubmembersort) | The sort order to apply to the members. |
| `Page`Type: [FPubnubPage](#fpubnubpage) | Cursor-based pagination. Use `Page.Next` and `Page.Prev` to request the next or previous page. |

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

#### FPubnubChannelMemberInputData

| Field | Type | Description |
| --- | --- | --- |
| `User` | `FString` | The user UUID to add/update the membership. Can't be empty. |
| `Custom` | `FString` | The custom data to add/update the membership. |
| `Status` | `FString` | The status of the membership. |
| `Type` | `FString` | The type of the membership. |

#### Returns

* **Synchronous:** returns [FPubnubChannelMembersResult](#fpubnubchannelmembersresult) (Result, MembersData, Page, TotalCount).
* **Asynchronous:** delegate [FOnPubnubSetChannelMembersResponse](#fonpubnubsetchannelmembersresponse) receives (Result, MembersData, Page, TotalCount).

#### FOnPubnubSetChannelMembersResponse

| Field | Type | Description |
| --- | --- | --- |
| `Result` | [FPubnubOperationResult](https://www.pubnub.com/docs/sdks/unreal/api-reference/configuration#operation-result) | The result of the operation. |
| `MembersData` | [const TArray<FPubnubChannelMemberData>&](#fpubnubchannelmemberdata) | Array of [FPubnubChannelMemberData](#fpubnubchannelmemberdata) structs which are the members of the channel. |
| `Page` | [FPubnubPage](#fpubnubpage) | Pagination cursor (Next, Prev) for requesting the next or previous page. |
| `TotalCount` | `int` | Total number of members matching the request (when requested). |

#### FOnPubnubSetChannelMembersResponseNative

| Field | Type | Description |
| --- | --- | --- |
| `Result` | [const FPubnubOperationResult&](https://www.pubnub.com/docs/sdks/unreal/api-reference/configuration#operation-result) | The result of the operation. |
| `MembersData` | [const TArray<FPubnubChannelMemberData>&](#fpubnubchannelmemberdata) | Array of [FPubnubChannelMemberData](#fpubnubchannelmemberdata) structs which are the members of the channel. |
| `Page` | [const FPubnubPage&](#fpubnubpage) | Pagination cursor (Next, Prev) for requesting the next or previous page. |
| `TotalCount` | `int` | Total number of members matching the request (when requested). |

#### Sample code

:::tip Reference code
Set up your Unreal project and follow the instructions in the lines marked with
ACTION REQUIRED
before running the code.
:::

###### C++

#### Actor.h

```cpp
#include "PubnubClient.h"

// blueprint.usr3zz15
UFUNCTION(BlueprintCallable, Category = "Pubnub|Samples|App Context")
void SetChannelMembersSample();
```

#### Actor.cpp

```cpp
// ACTION REQUIRED: Replace ASample_Memberships with name of your Actor class
void ASample_Memberships::SetChannelMembersSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set

	// Create members data
	TArray<FPubnubChannelMemberInputData> MembersToSet;
	FPubnubChannelMemberInputData Member1;
	Member1.User = "User_001";
	Member1.Type = "standard";
	MembersToSet.Add(Member1);
	
	FPubnubChannelMemberInputData Member2;
	Member2.User = "User_002";
	Member2.Custom = "{\"is_moderator\": true}";
	Member2.Status = "active";
	MembersToSet.Add(Member2);
	
	// Set members for the channel
	PubnubClient->SetChannelMembersAsync("general-chat-channel", MembersToSet);
}
```

###### Blueprint

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

#### Other examples

:::tip Reference code
Set up your Unreal project and follow the instructions in the lines marked with
ACTION REQUIRED
before running the code.
:::

##### Set channel members with result

###### Actor.h

```cpp
#include "PubnubClient.h"

UFUNCTION(BlueprintCallable, Category = "Pubnub|Samples|App Context")
void SetChannelMembersWithResultSample();

UFUNCTION()
void OnSetChannelMembersResponse(FPubnubOperationResult Result, const TArray<FPubnubChannelMemberData>& MembersData, FPubnubPage Page, int TotalCount);
```

###### Actor.cpp

```cpp
// ACTION REQUIRED: Replace ASample_Memberships with name of your Actor class
void ASample_Memberships::SetChannelMembersWithResultSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set

	// Bind response delegate
	// ACTION REQUIRED: Replace ASample_Memberships with name of your Actor class
	FOnPubnubSetChannelMembersResponse OnSetChannelMembersResponse;
	OnSetChannelMembersResponse.BindDynamic(this, &ASample_Memberships::OnSetChannelMembersResponse);
	
	// Create members data
	TArray<FPubnubChannelMemberInputData> MembersToSet;
	FPubnubChannelMemberInputData Member1;
	Member1.User = "User_003";
	Member1.Status = "pending";
	MembersToSet.Add(Member1);

	// Set members and include extra data in the response
	FPubnubMemberInclude Include = FPubnubMemberInclude::FromValue(true);
	PubnubClient->SetChannelMembersAsync("guild-hall-channel", MembersToSet, OnSetChannelMembersResponse, Include);
}

// ACTION REQUIRED: Replace ASample_Memberships with name of your Actor class
void ASample_Memberships::OnSetChannelMembersResponse(FPubnubOperationResult Result, const TArray<FPubnubChannelMemberData>& MembersData, FPubnubPage Page, int TotalCount)
{
	if(Result.Error)
	{
		UE_LOG(LogTemp, Error, TEXT("Failed to set channel members. Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
	}
	else
	{
		UE_LOG(LogTemp, Log, TEXT("Successfully set channel members. Count: %d"), MembersData.Num());
		for (const auto& Member : MembersData)
		{
			UE_LOG(LogTemp, Log, TEXT("- User: %s, Type: %s, Status: %s, Custom: %s"), *Member.User.UserID, *Member.Type, *Member.Status, *Member.Custom);
		}
	}
}
```

##### Set channel members with lambda

###### Actor.h

```cpp
#include "PubnubClient.h"

UFUNCTION(BlueprintCallable, Category = "Pubnub|Samples|App Context")
void SetChannelMembersWithLambdaSample();
```

###### Actor.cpp

```cpp
// ACTION REQUIRED: Replace ASample_Memberships with name of your Actor class
void ASample_Memberships::SetChannelMembersWithLambdaSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set

	// Bind lambda to response delegate
	FOnPubnubSetChannelMembersResponseNative OnSetChannelMembersResponse;
	OnSetChannelMembersResponse.BindLambda([](const FPubnubOperationResult& Result, const TArray<FPubnubChannelMemberData>& MembersData, FPubnubPage Page, int TotalCount)
	{
		if(Result.Error)
		{
			UE_LOG(LogTemp, Error, TEXT("Failed to set channel members. Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
		}
		else
		{
			UE_LOG(LogTemp, Log, TEXT("Successfully set channel members. Count: %d"), MembersData.Num());
			for (const auto& Member : MembersData)
			{
				UE_LOG(LogTemp, Log, TEXT("- User: %s, Type: %s, Status: %s, Custom: %s"), *Member.User.UserID, *Member.Type, *Member.Status, *Member.Custom);
			}
		}
	});

	// Create members data
	TArray<FPubnubChannelMemberInputData> MembersToSet;
	FPubnubChannelMemberInputData Member1;
	Member1.User = "User_004";
	Member1.Type = "premium";
	MembersToSet.Add(Member1);
	
	// Set members and include extra data in the response
	FPubnubMemberInclude Include = FPubnubMemberInclude::FromValue(true);
	PubnubClient->SetChannelMembersAsync("private-lounge-channel", MembersToSet, OnSetChannelMembersResponse, Include);
}
```

##### Set channel members raw

###### Actor.h

```cpp
#include "PubnubClient.h"

UFUNCTION(BlueprintCallable, Category = "Pubnub|Samples|App Context")
void SetChannelMembersRawSample();
	
UFUNCTION()
void OnSetChannelMembersRawResponse(FPubnubOperationResult Result, const TArray<FPubnubChannelMemberData>& MembersData, FPubnubPage Page, int TotalCount);
```

###### Actor.cpp

```cpp
// ACTION REQUIRED: Replace ASample_Memberships with name of your Actor class
void ASample_Memberships::SetChannelMembersRawSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set

	// Bind response delegate
	// ACTION REQUIRED: Replace ASample_Memberships with name of your Actor class
	FOnPubnubSetChannelMembersResponse OnSetChannelMembersResponse;
	OnSetChannelMembersResponse.BindDynamic(this, &ASample_Memberships::OnSetChannelMembersRawResponse);
	
	// Create members data as a raw JSON string
	FString MembersJson = R"([{"user": {"id": "User_005"}, "custom": {"rank": "diamond"}, "status": "active"}, {"user": {"id": "User_006"}, "type": "viewer"}])";
	
	// Set members with raw JSON and includes
	FString Include = "custom,status,type,user.custom";
	PubnubClient->SetChannelMembersRawAsync("arena-channel", MembersJson, OnSetChannelMembersResponse, Include);
}

// ACTION REQUIRED: Replace ASample_Memberships with name of your Actor class
void ASample_Memberships::OnSetChannelMembersRawResponse(FPubnubOperationResult Result, const TArray<FPubnubChannelMemberData>& MembersData, FPubnubPage Page, int TotalCount)
{
	if(Result.Error)
	{
		UE_LOG(LogTemp, Error, TEXT("Failed to set channel members. Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
	}
	else
	{
		UE_LOG(LogTemp, Log, TEXT("Successfully set channel members. Count: %d"), MembersData.Num());
		for (const auto& Member : MembersData)
		{
			UE_LOG(LogTemp, Log, TEXT("- User: %s, Type: %s, Status: %s, Custom: %s"), *Member.User.UserID, *Member.Type, *Member.Status, *Member.Custom);
		}
	}
}
```

### Remove Channel Members

Remove members from a channel.

#### Method(s)

```cpp
// Synchronous
FPubnubChannelMembersResult Result = PubnubClient->RemoveChannelMembers(
    FString Channel,
    TArray<FString> Users,
    FPubnubMemberInclude Include = FPubnubMemberInclude(),
    int Limit = 100,
    FString Filter = "",
    FPubnubMemberSort Sort = FPubnubMemberSort(),
    FPubnubPage Page = FPubnubPage()
);

// Asynchronous
PubnubClient->RemoveChannelMembersAsync(
    FString Channel,
    TArray<FString> Users,
    FOnPubnubRemoveChannelMembersResponse OnRemoveChannelMembersResponse,
    FPubnubMemberInclude Include = FPubnubMemberInclude(),
    int Limit = 100,
    FString Filter = "",
    FPubnubMemberSort Sort = FPubnubMemberSort(),
    FPubnubPage Page = FPubnubPage()
);
```

| Parameter | Description |
| --- | --- |
| `Channel` *Type: `FString` | The channel ID to remove the members. Can't be empty. |
| `Users` *Type: `TArray<FString>` | The array of user UUIDs to remove from the channel. Can't be empty. |
| `OnRemoveChannelMembersResponse`Type: [FOnPubnubRemoveChannelMembersResponse](#fonpubnubremovechannelmembersresponse) | The delegate for the operation's result. You can also use a native callback of the type [FOnPubnubRemoveChannelMembersResponseNative](#fonpubnubremovechannelmembersresponsenative) to handle the result using a lambda. |
| `Include`Type: [FPubnubMemberInclude](#fpubnubmemberinclude) | List of property names to include in the response. |
| `Limit`Type: `int` | The maximum number of members to return. |
| `Filter`Type: `FString` | The filter to apply to the members. |
| `Sort`Type: [FPubnubMemberSort](#fpubnubmembersort) | The sort order to apply to the members. |
| `Page`Type: [FPubnubPage](#fpubnubpage) | Cursor-based pagination. Use `Page.Next` and `Page.Prev` to request the next or previous page. |

#### Sample code

:::tip Reference code
Set up your Unreal project and follow the instructions in the lines marked with
ACTION REQUIRED
before running the code.
:::

###### C++

#### Actor.h

```cpp
#include "PubnubClient.h"

// blueprint.8qmyssi1
UFUNCTION(BlueprintCallable, Category = "Pubnub|Samples|App Context")
void RemoveChannelMembersSample();
```

#### Actor.cpp

```cpp
// ACTION REQUIRED: Replace ASample_Memberships with name of your Actor class
void ASample_Memberships::RemoveChannelMembersSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set

	// Create a list of user IDs to remove from the channel
	TArray<FString> UsersToRemove;
	UsersToRemove.Add("User_001");
	UsersToRemove.Add("User_002");
	
	// Remove members from the channel
	PubnubClient->RemoveChannelMembersAsync("general-chat-channel", UsersToRemove);
}
```

###### Blueprint

#### Returns

* **Synchronous:** returns [FPubnubChannelMembersResult](#fpubnubchannelmembersresult) (Result, MembersData, Page, TotalCount).
* **Asynchronous:** delegate [FOnPubnubRemoveChannelMembersResponse](#fonpubnubremovechannelmembersresponse) receives (Result, MembersData, Page, TotalCount).

##### FOnPubnubRemoveChannelMembersResponse

| Field | Type | Description |
| --- | --- | --- |
| `Result` | [FPubnubOperationResult](https://www.pubnub.com/docs/sdks/unreal/api-reference/configuration#operation-result) | The result of the operation. |
| `MembersData` | [const TArray<FPubnubChannelMemberData>&](#fpubnubchannelmemberdata) | Array of [FPubnubChannelMemberData](#fpubnubchannelmemberdata) structs which are the members of the channel. |
| `Page` | [FPubnubPage](#fpubnubpage) | Pagination cursor (Next, Prev) for requesting the next or previous page. |
| `TotalCount` | `int` | Total number of members matching the request (when requested). |

##### FOnPubnubRemoveChannelMembersResponseNative

| Field | Type | Description |
| --- | --- | --- |
| `Result` | [const FPubnubOperationResult&](https://www.pubnub.com/docs/sdks/unreal/api-reference/configuration#operation-result) | The result of the operation. |
| `MembersData` | [const TArray<FPubnubChannelMemberData>&](#fpubnubchannelmemberdata) | Array of [FPubnubChannelMemberData](#fpubnubchannelmemberdata) structs which are the members of the channel. |
| `Page` | [const FPubnubPage&](#fpubnubpage) | Pagination cursor (Next, Prev) for requesting the next or previous page. |
| `TotalCount` | `int` | Total number of members matching the request (when requested). |

#### Other examples

:::tip Reference code
Set up your Unreal project and follow the instructions in the lines marked with
ACTION REQUIRED
before running the code.
:::

##### Remove channel members with result

###### Actor.h

```cpp
#include "PubnubClient.h"

UFUNCTION(BlueprintCallable, Category = "Pubnub|Samples|App Context")
void RemoveChannelMembersWithResultSample();

UFUNCTION()
void OnRemoveChannelMembersResponse(FPubnubOperationResult Result, const TArray<FPubnubChannelMemberData>& MembersData, FPubnubPage Page, int TotalCount);
```

###### Actor.cpp

```cpp
// ACTION REQUIRED: Replace ASample_Memberships with name of your Actor class
void ASample_Memberships::RemoveChannelMembersWithResultSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set

	// Bind response delegate
	// ACTION REQUIRED: Replace ASample_Memberships with name of your Actor class
	FOnPubnubRemoveChannelMembersResponse OnRemoveChannelMembersResponse;
	OnRemoveChannelMembersResponse.BindDynamic(this, &ASample_Memberships::OnRemoveChannelMembersResponse);
	
	// Create a list of user IDs to remove
	TArray<FString> UsersToRemove;
	UsersToRemove.Add("User_003");

	// Remove members and include extra data in the response
	FPubnubMemberInclude Include = FPubnubMemberInclude::FromValue(true);
	PubnubClient->RemoveChannelMembersAsync("guild-hall-channel", UsersToRemove, OnRemoveChannelMembersResponse, Include);
}

// ACTION REQUIRED: Replace ASample_Memberships with name of your Actor class
void ASample_Memberships::OnRemoveChannelMembersResponse(FPubnubOperationResult Result, const TArray<FPubnubChannelMemberData>& MembersData, FPubnubPage Page, int TotalCount)
{
	if(Result.Error)
	{
		UE_LOG(LogTemp, Error, TEXT("Failed to remove channel members. Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
	}
	else
	{
		UE_LOG(LogTemp, Log, TEXT("Successfully removed channel members. Count: %d"), MembersData.Num());
	}
}
```

##### Remove channel members with lambda

###### Actor.h

```cpp
#include "PubnubClient.h"

UFUNCTION(BlueprintCallable, Category = "Pubnub|Samples|App Context")
void RemoveChannelMembersWithLambdaSample();
```

###### Actor.cpp

```cpp
// ACTION REQUIRED: Replace ASample_Memberships with name of your Actor class
void ASample_Memberships::RemoveChannelMembersWithLambdaSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set

	// Bind lambda to response delegate
	FOnPubnubRemoveChannelMembersResponseNative OnRemoveChannelMembersResponse;
	OnRemoveChannelMembersResponse.BindLambda([](const FPubnubOperationResult& Result, const TArray<FPubnubChannelMemberData>& MembersData, FPubnubPage Page, int TotalCount)
	{
		if(Result.Error)
		{
			UE_LOG(LogTemp, Error, TEXT("Failed to remove channel members. Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
		}
		else
		{
			UE_LOG(LogTemp, Log, TEXT("Successfully removed channel members. Count: %d"), MembersData.Num());
		}
	});

	// Create a list of user IDs to remove
	TArray<FString> UsersToRemove;
	UsersToRemove.Add("User_004");
	
	// Remove members and include extra data in the response
	FPubnubMemberInclude Include = FPubnubMemberInclude::FromValue(true);
	PubnubClient->RemoveChannelMembersAsync("private-lounge-channel", UsersToRemove, OnRemoveChannelMembersResponse, Include);
}
```

##### Remove channel members raw

###### Actor.h

```cpp
#include "PubnubClient.h"

UFUNCTION(BlueprintCallable, Category = "Pubnub|Samples|App Context")
void RemoveChannelMembersRawSample();
	
UFUNCTION()
void OnRemoveChannelMembersRawResponse(FPubnubOperationResult Result, const TArray<FPubnubChannelMemberData>& MembersData, FPubnubPage Page, int TotalCount);
```

###### Actor.cpp

```cpp
// ACTION REQUIRED: Replace ASample_Memberships with name of your Actor class
void ASample_Memberships::RemoveChannelMembersRawSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set

	// Bind response delegate
	// ACTION REQUIRED: Replace ASample_Memberships with name of your Actor class
	FOnPubnubRemoveChannelMembersResponse OnRemoveChannelMembersResponse;
	OnRemoveChannelMembersResponse.BindDynamic(this, &ASample_Memberships::OnRemoveChannelMembersRawResponse);
	
	// Create members data as a raw JSON string
	FString MembersJson = R"([{"user": {"id": "User_005"}}, {"user": {"id": "User_006"}}])";
	
	// Remove members with raw JSON and includes
	FString Include = "custom,user.custom";
	PubnubClient->RemoveChannelMembersRawAsync("arena-channel", MembersJson, OnRemoveChannelMembersResponse, Include);
}

// ACTION REQUIRED: Replace ASample_Memberships with name of your Actor class
void ASample_Memberships::OnRemoveChannelMembersRawResponse(FPubnubOperationResult Result, const TArray<FPubnubChannelMemberData>& MembersData, FPubnubPage Page, int TotalCount)
{
	if(Result.Error)
	{
		UE_LOG(LogTemp, Error, TEXT("Failed to remove channel members. Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
	}
	else
	{
		UE_LOG(LogTemp, Log, TEXT("Successfully removed channel members. Count: %d"), MembersData.Num());
	}
}
```

## Complete example

:::tip Reference code
Set up your Unreal project and follow the instructions in the lines marked with
ACTION REQUIRED
before running the code.
:::

#### ASample_AppContextFull.h

```cpp
#pragma once

#include "PubnubClient.h"
#include "GameFramework/Actor.h"
#include "CoreMinimal.h"

#include "Sample_AppContextFull.generated.h"

// ACTION REQUIRED: Replace PUBNUBLIBRARYTESTS_API with your project's module API macro (usually ProjectName_API)
UCLASS()
class PUBNUBLIBRARYTESTS_API ASample_AppContextFull : public AActor
{
	GENERATED_BODY()

protected:
	virtual void BeginPlay() override;

public:

	UFUNCTION(BlueprintCallable, Category = "Pubnub|FullExamples|App Context")
	void RunAppContextFullExample();
	
private:

	UPROPERTY()
	UPubnubClient* PubnubClient = nullptr;

	FString ExampleUserID = "DragonSlayer_91";
	FString ExampleChannelID = "quest-the-dark-forest";

	UFUNCTION()
	void OnSetUserMetadataResponse(FPubnubOperationResult Result, FPubnubUserData UserData);

	UFUNCTION()
	void OnSetChannelMetadataResponse(FPubnubOperationResult Result, FPubnubChannelData ChannelData);

	UFUNCTION()
	void OnSetMembershipsResponse(FPubnubOperationResult Result, const TArray<FPubnubMembershipData>& MembershipsData, FPubnubPage Page, int TotalCount);

	UFUNCTION()
	void OnGetMembershipsResponse(FPubnubOperationResult Result, const TArray<FPubnubMembershipData>& MembershipsData, FPubnubPage Page, int TotalCount);

	UFUNCTION()
	void OnGetChannelMembersResponse(FPubnubOperationResult Result, const TArray<FPubnubChannelMemberData>& MembersData, FPubnubPage Page, int TotalCount);
    
	UFUNCTION()
	void OnRemoveMembershipsResponse(FPubnubOperationResult Result, const TArray<FPubnubMembershipData>& MembershipsData, FPubnubPage Page, int TotalCount);

	UFUNCTION()
	void OnRemoveUserMetadataResponse(FPubnubOperationResult Result);

	UFUNCTION()
	void OnRemoveChannelMetadataResponse(FPubnubOperationResult Result);
};
```

#### ASample_AppContextFull.cpp

```cpp
#include "Samples/Sample_AppContextFull.h"
#include "Kismet/GameplayStatics.h"
#include "Engine/GameInstance.h"
#include "PubnubSubsystem.h"
#include "PubnubClient.h"

void ASample_AppContextFull::BeginPlay()
{
	Super::BeginPlay();

	//Run the example on BeginPlay
	RunAppContextFullExample();
}

void ASample_AppContextFull::RunAppContextFullExample()
{
	//Get PubnubSubsystem from GameInstance
	UGameInstance* GameInstance = UGameplayStatics::GetGameInstance(this);
	UPubnubSubsystem* PubnubSubsystem = GameInstance->GetSubsystem<UPubnubSubsystem>();
	
	//Create Pubnub Client using Pubnub Subsystem
	FPubnubConfig Config;
	Config.PublishKey = TEXT("demo");   //replace with your Publish Key from Admin Portal
	Config.SubscribeKey = TEXT("demo"); //replace with your Subscribe Key from Admin Portal
	Config.UserID = ExampleUserID;
	PubnubClient = PubnubSubsystem->CreatePubnubClient(Config);

	UE_LOG(LogTemp, Log, TEXT("App Context Example: Pubnub Client is created"));
	
	// Start the example by setting user metadata
	UE_LOG(LogTemp, Log, TEXT("App Context Example: Running..."));
	
	// 1. Set User Metadata
	UE_LOG(LogTemp, Log, TEXT("App Context Example: Step 1: Setting User Metadata for user '%s'"), *ExampleUserID);

	FPubnubUserData UserMetadata;
	UserMetadata.UserName = "Dragon Slayer 91";
	UserMetadata.Email = "dragon.slayer91@email.com";
	UserMetadata.Custom = "{\"class\": \"Warrior\", \"level\": 42, \"guild\": \"TheSilverSwords\"}";

	FOnPubnubSetUserMetadataResponse OnSetUserMetadataResponse;
	OnSetUserMetadataResponse.BindDynamic(this, &ASample_AppContextFull::OnSetUserMetadataResponse);
	
	FPubnubUserInputData UserInputData = FPubnubUserInputData::FromPubnubUserData(UserMetadata);
	PubnubClient->SetUserMetadataAsync(ExampleUserID, UserInputData, OnSetUserMetadataResponse);
}

void ASample_AppContextFull::OnSetUserMetadataResponse(FPubnubOperationResult Result, FPubnubUserData UserData)
{
	if (Result.Error)
	{
		UE_LOG(LogTemp, Error, TEXT("App Context Example: Example failed at Step 1 (SetUserMetadata). Reason: %s"), *Result.ErrorMessage);
		return;
	}
	UE_LOG(LogTemp, Log, TEXT("App Context Example: Step 1 successful. User metadata set for '%s'."), *UserData.UserID);
	
	// 2. Set Channel Metadata
	UE_LOG(LogTemp, Log, TEXT("App Context Example: Step 2: Setting Channel Metadata for channel '%s'"), *ExampleChannelID);

	FPubnubChannelData ChannelMetadata;
	ChannelMetadata.ChannelName = "The Dark Forest Quest";
	ChannelMetadata.Description = "A dangerous quest to retrieve the Sunstone.";
	ChannelMetadata.Custom = "{\"difficulty\": \"Hard\", \"min_level\": 30}";

	FOnPubnubSetChannelMetadataResponse OnSetChannelMetadataResponse;
	OnSetChannelMetadataResponse.BindDynamic(this, &ASample_AppContextFull::OnSetChannelMetadataResponse);
	
	FPubnubChannelInputData ChannelInputData = FPubnubChannelInputData::FromPubnubChannelData(ChannelMetadata);
	PubnubClient->SetChannelMetadataAsync(ExampleChannelID, ChannelInputData, OnSetChannelMetadataResponse);
}

void ASample_AppContextFull::OnSetChannelMetadataResponse(FPubnubOperationResult Result, FPubnubChannelData ChannelData)
{
	if (Result.Error)
	{
		UE_LOG(LogTemp, Error, TEXT("App Context Example: Example failed at Step 2 (SetChannelMetadata). Reason: %s"), *Result.ErrorMessage);
		return;
	}
	UE_LOG(LogTemp, Log, TEXT("App Context Example: Step 2 successful. Channel metadata set for '%s'."), *ChannelData.ChannelID);
	
	// 3. Set Membership for the user in the channel
	UE_LOG(LogTemp, Log, TEXT("App Context Example: Step 3: Setting Membership for user '%s' in channel '%s'"), *ExampleUserID, *ExampleChannelID);

	TArray<FPubnubMembershipInputData> MembershipsToSet;
	FPubnubMembershipInputData Membership;
	Membership.Channel = ExampleChannelID;
	Membership.Custom = "{\"role\": \"QuestLeader\", \"party_invite_pending\": false}";
	MembershipsToSet.Add(Membership);

	FOnPubnubSetMembershipsResponse OnSetMembershipsResponse;
	OnSetMembershipsResponse.BindDynamic(this, &ASample_AppContextFull::OnSetMembershipsResponse);

	PubnubClient->SetMembershipsAsync(ExampleUserID, MembershipsToSet, OnSetMembershipsResponse);
}

void ASample_AppContextFull::OnSetMembershipsResponse(FPubnubOperationResult Result, const TArray<FPubnubMembershipData>& MembershipsData, FPubnubPage Page, int TotalCount)
{
	if (Result.Error)
	{
		UE_LOG(LogTemp, Error, TEXT("App Context Example: Example failed at Step 3 (SetMemberships). Reason: %s"), *Result.ErrorMessage);
		return;
	}
	UE_LOG(LogTemp, Log, TEXT("App Context Example: Step 3 successful. Membership set."));
	
	// 4a. Verify by getting the user's memberships
	UE_LOG(LogTemp, Log, TEXT("App Context Example: Step 4a: Verifying by getting user's memberships..."));
	
	FOnPubnubGetMembershipsResponse OnGetMembershipsResponse;
	OnGetMembershipsResponse.BindDynamic(this, &ASample_AppContextFull::OnGetMembershipsResponse);

	PubnubClient->GetMembershipsAsync(ExampleUserID, OnGetMembershipsResponse);
}

void ASample_AppContextFull::OnGetMembershipsResponse(FPubnubOperationResult Result, const TArray<FPubnubMembershipData>& MembershipsData, FPubnubPage Page, int TotalCount)
{
	if (Result.Error || MembershipsData.Num() == 0 || MembershipsData[0].Channel.ChannelID != ExampleChannelID)
	{
		UE_LOG(LogTemp, Error, TEXT("App Context Example: Example failed at Step 4a (GetMemberships). Reason: %s"), *Result.ErrorMessage);
		return;
	}
	UE_LOG(LogTemp, Log, TEXT("App Context Example: Step 4a successful. Verified user is in channel '%s'."), *ExampleChannelID);
	
	// 4b. Verify by getting the channel's members
	UE_LOG(LogTemp, Log, TEXT("App Context Example: Step 4b: Verifying by getting channel's members..."));

	FOnPubnubGetChannelMembersResponse OnGetChannelMembersResponse;
	OnGetChannelMembersResponse.BindDynamic(this, &ASample_AppContextFull::OnGetChannelMembersResponse);

	PubnubClient->GetChannelMembersAsync(ExampleChannelID, OnGetChannelMembersResponse);
}

void ASample_AppContextFull::OnGetChannelMembersResponse(FPubnubOperationResult Result, const TArray<FPubnubChannelMemberData>& MembersData, FPubnubPage Page, int TotalCount)
{
	if (Result.Error || MembersData.Num() == 0 || MembersData[0].User.UserID != ExampleUserID)
	{
		UE_LOG(LogTemp, Error, TEXT("App Context Example: Example failed at Step 4b (GetChannelMembers). Reason: %s"), *Result.ErrorMessage);
		return;
	}
	UE_LOG(LogTemp, Log, TEXT("App Context Example: Step 4b successful. Verified channel has user '%s' as a member."), *ExampleUserID);
	
	// 5. Clean up: Remove the membership
	UE_LOG(LogTemp, Log, TEXT("App Context Example: Step 5: Cleaning up... Removing membership."));
	
	TArray<FString> ChannelsToRemove;
	ChannelsToRemove.Add(ExampleChannelID);

	FOnPubnubRemoveMembershipsResponse OnRemoveMembershipsResponse;
	OnRemoveMembershipsResponse.BindDynamic(this, &ASample_AppContextFull::OnRemoveMembershipsResponse);

	PubnubClient->RemoveMembershipsAsync(ExampleUserID, ChannelsToRemove, OnRemoveMembershipsResponse);
}

void ASample_AppContextFull::OnRemoveMembershipsResponse(FPubnubOperationResult Result, const TArray<FPubnubMembershipData>& MembershipsData, FPubnubPage Page, int TotalCount)
{
	if (Result.Error)
	{
		UE_LOG(LogTemp, Error, TEXT("App Context Example: Example failed at Step 5 (RemoveMemberships). Reason: %s"), *Result.ErrorMessage);
		return;
	}
	UE_LOG(LogTemp, Log, TEXT("App Context Example: Step 5 successful. Membership removed."));
	
	// 6. Clean up: Remove the user metadata
	UE_LOG(LogTemp, Log, TEXT("App Context Example: Step 6: Cleaning up... Removing user metadata."));

	FOnPubnubRemoveUserMetadataResponse OnRemoveUserMetadataResponse;
	OnRemoveUserMetadataResponse.BindDynamic(this, &ASample_AppContextFull::OnRemoveUserMetadataResponse);

	PubnubClient->RemoveUserMetadataAsync(ExampleUserID, OnRemoveUserMetadataResponse);
}

void ASample_AppContextFull::OnRemoveUserMetadataResponse(FPubnubOperationResult Result)
{
	if (Result.Error)
	{
		UE_LOG(LogTemp, Error, TEXT("App Context Example: Example failed at Step 6 (RemoveUserMetadata). Reason: %s"), *Result.ErrorMessage);
		return;
	}
	UE_LOG(LogTemp, Log, TEXT("App Context Example: Step 6 successful. User metadata removed."));
	
	// 7. Clean up: Remove the channel metadata
	UE_LOG(LogTemp, Log, TEXT("App Context Example: Step 7: Cleaning up... Removing channel metadata."));

	FOnPubnubRemoveChannelMetadataResponse OnRemoveChannelMetadataResponse;
	OnRemoveChannelMetadataResponse.BindDynamic(this, &ASample_AppContextFull::OnRemoveChannelMetadataResponse);

	PubnubClient->RemoveChannelMetadataAsync(ExampleChannelID, OnRemoveChannelMetadataResponse);
}

void ASample_AppContextFull::OnRemoveChannelMetadataResponse(FPubnubOperationResult Result)
{
	if (Result.Error)
	{
		UE_LOG(LogTemp, Error, TEXT("App Context Example: Example failed at Step 7 (RemoveChannelMetadata). Reason: %s"), *Result.ErrorMessage);
		return;
	}
	UE_LOG(LogTemp, Log, TEXT("App Context Example: Step 7 successful. Channel metadata removed."));
	UE_LOG(LogTemp, Log, TEXT("App Context Example: finished successfully!"));
}
```

## Deprecated methods

### Get metadata for all users (deprecated)

:::warning Deprecated
Use `PubnubClient->GetAllUserMetadata` / `GetAllUserMetadataAsync` instead.
:::

**Old signature:** `PubnubSubsystem->GetAllUserMetadata(FOnGetAllUserMetadataResponse, Include, Limit, Filter, Sort, PageNext, PagePrev);` — delegate returned (Result, UsersData, PageNext, PagePrev).

### Get user metadata - PubNub client (deprecated)

:::warning Deprecated
Use `PubnubClient->GetUserMetadata` / `GetUserMetadataAsync` instead.
:::

**Old signature:** `PubnubSubsystem->GetUserMetadata(User, FOnGetUserMetadataResponse, Include);`

### Set user metadata - PubNub client (deprecated)

:::warning Deprecated
Use `PubnubClient->SetUserMetadata` / `SetUserMetadataAsync` with `FPubnubUserInputData` instead.
:::

**Old signature:** `PubnubSubsystem->SetUserMetadata(User, FPubnubUserData UserMetadata, FOnSetUserMetadataResponse, Include);`

### Remove user metadata - PubNub client (deprecated)

:::warning Deprecated
Use `PubnubClient->RemoveUserMetadata` / `RemoveUserMetadataAsync` instead.
:::

**Old signature:** `PubnubSubsystem->RemoveUserMetadata(User, FOnRemoveUserMetadataResponse);`

### Get metadata for all channels (deprecated)

:::warning Deprecated
Use `PubnubClient->GetAllChannelMetadata` / `GetAllChannelMetadataAsync` instead.
:::

**Old signature:** `PubnubSubsystem->GetAllChannelMetadata(FOnGetAllChannelMetadataResponse, Include, Limit, Filter, Sort, PageNext, PagePrev);` — delegate returned (Result, ChannelsData, PageNext, PagePrev).

### Get channel metadata - PubNub client (deprecated)

:::warning Deprecated
Use `PubnubClient->GetChannelMetadata` / `GetChannelMetadataAsync` instead.
:::

**Old signature:** `PubnubSubsystem->GetChannelMetadata(Include, Channel, FOnGetChannelMetadataResponse);`

### Set channel metadata - PubNub client (deprecated)

:::warning Deprecated
Use `PubnubClient->SetChannelMetadata` / `SetChannelMetadataAsync` with `FPubnubChannelInputData` instead.
:::

**Old signature:** `PubnubSubsystem->SetChannelMetadata(Channel, FPubnubChannelData ChannelMetadata, FOnSetChannelMetadataResponse, Include);`

### Remove channel metadata - PubNub client (deprecated)

:::warning Deprecated
Use `PubnubClient->RemoveChannelMetadata` / `RemoveChannelMetadataAsync` instead.
:::

**Old signature:** `PubnubSubsystem->RemoveChannelMetadata(Channel, FOnRemoveChannelMetadataResponse);`

### Get channel memberships (deprecated)

:::warning Deprecated
Use `PubnubClient->GetMemberships` / `GetMembershipsAsync` instead.
:::

**Old signature:** `PubnubSubsystem->GetMemberships(User, FOnGetMembershipsResponse, Include, Limit, Filter, Sort, PageNext, PagePrev);` — delegate returned (Result, MembershipsData, PageNext, PagePrev).

### Set channel memberships (deprecated)

:::warning Deprecated
Use `PubnubClient->SetMemberships` / `SetMembershipsAsync` instead.
:::

**Old signature:** `PubnubSubsystem->SetMemberships(User, Channels, FOnSetMembershipsResponse, Include, Limit, Filter, Sort, PageNext, PagePrev);` — delegate returned (Result, MembershipsData, PageNext, PagePrev).

### Remove Channel Memberships (deprecated)

:::warning Deprecated
Use `PubnubClient->RemoveMemberships` / `RemoveMembershipsAsync` instead.
:::

**Old signature:** `PubnubSubsystem->RemoveMemberships(User, Channels, FOnRemoveMembershipsResponse, Include, Limit, Filter, Sort, PageNext, PagePrev);` — delegate returned (Result, MembershipsData, PageNext, PagePrev).

### Get channel members (deprecated)

:::warning Deprecated
Use `PubnubClient->GetChannelMembers` / `GetChannelMembersAsync` instead.
:::

**Old signature:** `PubnubSubsystem->GetChannelMembers(Channel, FOnGetChannelMembersResponse, Include, Limit, Filter, Sort, PageNext, PagePrev);` — delegate returned (Result, MembersData, PageNext, PagePrev).

### Set channel members (deprecated)

:::warning Deprecated
Use `PubnubClient->SetChannelMembers` / `SetChannelMembersAsync` instead.
:::

**Old signature:** `PubnubSubsystem->SetChannelMembers(Channel, Users, FOnSetChannelMembersResponse, Include, Limit, Filter, Sort, PageNext, PagePrev);` — delegate returned (Result, MembersData, PageNext, PagePrev).

### Remove Channel Members (deprecated)

:::warning Deprecated
Use `PubnubClient->RemoveChannelMembers` / `RemoveChannelMembersAsync` instead.
:::

**Old signature:** `PubnubSubsystem->RemoveChannelMembers(Channel, Users, FOnRemoveChannelMembersResponse, Include, Limit, Filter, Sort, PageNext, PagePrev);` — delegate returned (Result, MembersData, PageNext, PagePrev).

## 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.
* **Action** - The type of activity (procedure) to execute when a condition is satisfied (for example, sending a message).
* **Billing alert notification** - A means of informing a user that a billing alert has been triggered. Before notifications can happen, a billing alert must be triggered first.
* **Business Object** - A container for data fields and metrics that defines aggregations and data sources.
* **Channel** - A pathway for sending and receiving messages between devices, created automatically when you first use it, that can handle any number of users and messages for different communication needs, like 1-1 text chats, group conversations, and other data streaming.
* **Channel pattern** - A way to group and analyze channel data to track performance metrics like message counts and user engagement over time with PubNub Insights.
* **Condition** - A requirement that must be satisfied or evaluated to true for an action to be executed. Input in a decision table.
* **Cryptor** - An implementation of a specific cryptographic algorithm used for data encryption/decryption that adheres to a standard interface.
* **Dashboard** - A collection of widgets (charts) that give an overview of the metrics one is evaluating.
* **Data fields** - Data you want Illuminate to track. These can be quantitative (measures), like "Number" or "Timestamp" or qualitative (dimensions) values, like "String" that can be used to categorize and segment data. Data fields can be aggregated and calculated.
* **Decision** - A collection (or decision table) of conditions and actions. When conditions are satisfied, the corresponding actions are triggered as per defined rules.
* **End Customer** - A customer of a PubNub partner. End customers do not have direct access to the Admin Portal. Instead, they interact with PubNub products—such as Illuminate—through the partner’s portal, where PubNub services are embedded. They can create PubNub objects only within this partner-provided environment.
* **Entity** - A subscribable object within a PubNub SDK that allows you to perform context-specific operations.
* **Listener** - A function or objectthat reacts to events or messages, like new chat messages or connection updates, letting your app respond in real-time.
* **Mapped/Unmapped** - Whether the data source for a data field has been defined or the action has been configured.
* **MCP Server** - A Model Context Protocol server that coordinates communication and synchronization between AI agents, clients, or services, such as Cursor IDE and Windsurf.
* **Message** - A unit of data transmitted between clients or between a client and a server in PubNub, containing information such as text, binary data, or structured data formats like JSON. Messages are sent over channels and can be tracked for delivery and read status.
* **Metric** - What exactly is evaluated using measures and dimensions (collectively called data fields), as well as aggregation functions.
* **Module** - A Functions v1 container that groups related functions for configuration and deployment on an app’s keysets.
* **Origin** - The subdomain used to establish a connection to the PubNub network that allows your application's traffic to appear like it's coming from your own domain.
* **Package** - A Functions v2 container that groups Functions, tracks Revisions, and is deployed to keysets.
* **Partner** - A PubNub customer who resells PubNub products, such as Illuminate, to their own customers. Partners have access to the Admin Portal, enabling them to create and manage PubNub objects for themselves or on behalf of their end customers.
* **Publish Key** - A unique identifier that allows your application to send messages to PubNub channels. It's part of your app's credentials and should be kept secure.
* **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.
* **Push token** - A device identifier issued by a push provider (APNs or FCM) used to register a device for receiving mobile push notifications.
* **Rule** - A definition (row in a decision table) stating which action should be triggered for which condition.
* **Service Integration** - A machine identity that represents a program or service consuming the Admin API, scoped to your account and authenticated using expirable API keys with configurable permissions.
* **Signal** - A non-persistent message limited to 64 bytes designed for high-volume usecases where the the most recent data is relevant, like GPS location updates.
* **Subscribe Key** - A unique identifier that allows your application to receive messages from PubNub channels. It's part of your app's credentials and should be kept secure.
* **Timetoken** - A unique identifier for each message that represents the number of 100-nanosecond intervals since January 1, 1970, for example, 16200000000000000.
* **Trigger details** - A set of predefined criteria for a given billing alert. When met, billing alert notifications are generated.
* **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.
* **Vibe Coding** - A way to build applications in an intuitive, relaxed, and improvisational manner, using AI tools and natural language descriptions.