---
source_url: https://www.pubnub.com/docs/sdks/unreal/api-reference/publish-and-subscribe
title: Publish/Subscribe API for Unreal SDK
updated_at: 2026-06-04T11:13:22.099Z
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


# Publish/Subscribe API for Unreal SDK

PubNub Unreal SDK, use the latest version: 2.0.5

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

PubNub delivers messages worldwide in less than 30 ms. Send a message to one recipient or broadcast to thousands of subscribers.

For higher-level conceptual details on publishing and subscribing, refer to [Connection Management](https://www.pubnub.com/docs/general/setup/connection-management) and to [Publish Messages](https://www.pubnub.com/docs/general/messages/publish).

:::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->PublishMessageAsync("my-channel", "Hello!", OnPublishMessageResponseDelegate); You can also use native callbacks that accept lambdas instead of dynamic delegates. Native callback types have the Native suffix (for example, FOnPubnubPublishMessageResponseNative).
* Synchronous methods (no suffix) block the main game thread until the operation completes and return a result struct directly. 1FPubnubPublishMessageResult Result = PubnubClient->PublishMessage("my-channel", "Hello!");
:::

## Publish

`PublishMessage()` sends a message to all channel subscribers. PubNub replicates the message across its points of presence and delivers it to all subscribed clients on that channel.

### Prerequisites and limitations

* You must [initialize PubNub](https://www.pubnub.com/docs/sdks/unreal/api-reference/configuration) with the `publishKey`.
* You don't have to be subscribed to a channel to publish to it.
* You cannot publish to multiple channels simultaneously.

### Security

Secure messages with Transport Layer Security (TLS) or Secure Sockets Layer (SSL) during [initialization](https://www.pubnub.com/docs/sdks/unreal/api-reference/configuration). You can also encrypt messages.

### Message data

The message can contain any JavaScript Object Notation (JSON)-serializable data (objects, arrays, integers, strings). Avoid special classes or functions. Strings can include any UTF‑8 characters.

:::warning Don't JSON serialize
You should not JSON serialize the `message` and `meta` parameters when sending signals, messages, or files as the serialization is automatic. Pass the full object as the message/meta payload and let PubNub handle everything.
:::

### Size

The maximum message size is 32 KiB. This includes the escaped character count and the channel name. Aim for under 1,800 bytes for optimal performance.

If your message exceeds the limit, you'll receive a `Message Too Large` error. To learn more or calculate payload size, see [Message size limits](https://www.pubnub.com/docs/general/messages/publish#message-size-limit).

:::tip Need larger messages?
Our platform is optimized for payloads up to 32 KiB. PubNub supports larger messages, but increasing the limit requires a verification of compatibility with your use case.
Talk to [our team](https://www.pubnub.com/company/contact-sales/) to discuss increasing the message size limit for your use case.
:::

### Publish rate

You can publish as fast as bandwidth allows. There is a [soft throughput limit](https://www.pubnub.com/docs/general/setup/limits) because messages may drop if subscribers can't keep up.

For example, publishing 200 messages at once may cause the first 100 to drop if a subscriber hasn't received any yet. The in-memory queue stores only 100 messages.

### Custom message type

You can optionally provide the `CustomMessageType` parameter to add your business-specific label or category to the message, for example `text`, `action`, or `poll`.

### Best practices

* Publish to a channel serially (not concurrently).
* Verify a success return code (for example, `[1,"Sent","136074940..."]`).
* Publish the next message only after a success return code.
* On failure (`[0,"blah","<timetoken>"]`), retry.
* Keep the in-memory queue under 100 messages to avoid drops.
* Throttle bursts to meet latency needs (for example, no more than 5 messages per second).

You can call `PublishMessage()` on a [Channel entity](#channel-entity) (which already knows its channel) or directly on the [PubNub client](#pubnub-client) by passing the channel name explicitly.

### Channel entity

##### Available in entities

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

#### Method(s)

To publish to a channel, you must first create a [Channel entity](https://www.pubnub.com/docs/sdks/unreal/entities/channel) where you provide the name of the channel you want to publish to.

```cpp
UPubnubChannelEntity* ChannelEntity = PubnubSubsystem->CreateChannelEntity("my-channel");

ChannelEntity->PublishMessage(
    FString Message,
    FOnPublishMessageResponse OnPublishMessageResponse,
    FPubnubPublishSettings PublishSettings = FPubnubPublishSettings()
);
```

| Parameter | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| Message | FString | Yes |  | The message to publish. Can be a literal string or JSON-formatted string containing serialized data. |
| OnPublishMessageResponse | FOnPublishMessageResponse | Optional |  | The delegate for the operation's result. You can also use a native callback of the type [FOnPublishMessageResponseNative](#fonpublishmessageresponsenative) to handle the result using a lambda. |
| PublishSettings | FPubnubPublishSettings | Optional |  | Struct defining publish configuration. |

##### FPubnubPublishSettings

| Parameter | Description |
| --- | --- |
| `StoreInHistory`Type: bool | Whether to store the message so it is available to be returned by the History API. `true` by default. |
| `Ttl`Type: `int` | Time-to-live (TTL) for the message in hours. If not specified, the message will use the default retention period configured for the key. |
| `MetaData`Type: `FString` | A JSON object containing additional (meta) data about the message which you can use with the filtering ability. |
| `PublishMethod`Type: `EPubnubPublishMethod` | Which HTTP method to use for the publish transaction. Available values: PPM_SendViaGET, PPM_SendViaPOST, PPM_UsePATCH, PPM_SendViaPOSTwithGZIP, PPM_UsePATCHwithGZIP, PPM_UseDELETE |
| `Replicate`Type: bool | If true, the message is replicated and is received by all subscribers. If false, the message is not replicated and is delivered only to Functions event handlers. |
| `CustomMessageType`Type: `FString` | A case-sensitive, alphanumeric string from 3 to 50 characters describing the business-specific label or category of the message. Dashes `-` and underscores `_` are allowed. The value cannot start with special characters or the string `pn_` or `pn-`. Examples: `text`, `action`, `poll`. |

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

##### Publish a message to a channel

###### C++

###### Actor.h

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

// blueprint.86kccdrk
UFUNCTION(BlueprintCallable, Category = "Pubnub|Samples|ChannelEntity")
void ChannelEntityPublishMessageSample();

UFUNCTION()
void OnPublishResult_ChannelEntitySample(FPubnubOperationResult Result, FPubnubMessageData Message);

	
```

###### Actor.cpp

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

	// Create a channel entity for the game chat channel
	FString GameChatChannel = TEXT("team_alpha_chat");
	UPubnubChannelEntity* ChatChannelEntity = PubnubClient->CreateChannelEntity(GameChatChannel);

	// Set up callback to handle publish result
	// ACTION REQUIRED: Replace ASample_ChannelEntity with name of your Actor class
	FOnPubnubPublishMessageResponse OnPublishResult;
	OnPublishResult.BindDynamic(this, &ASample_ChannelEntity::OnPublishResult_ChannelEntitySample);

	// Publish a tactical message to the team using the channel entity
	FString TacticalMessage = TEXT("Enemy spotted at coordinates B-7, requesting backup!");
	ChatChannelEntity->PublishMessageAsync(TacticalMessage, OnPublishResult);
}

// ACTION REQUIRED: Replace ASample_ChannelEntity with name of your Actor class
void ASample_ChannelEntity::OnPublishResult_ChannelEntitySample(FPubnubOperationResult Result, FPubnubMessageData Message)
{
	if(Result.Error)
	{
		UE_LOG(LogTemp, Error, TEXT("Failed to send tactical message. Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
	}
	else
	{
		UE_LOG(LogTemp, Log, TEXT("Tactical message sent successfully to team. Message timetoken: %s"), *Message.Timetoken);
	}
}
```

###### Blueprint

:::note Subscribe to the channel
Before running the above publish example (either using the [Debug Console](https://www.pubnub.com/docs/console/) or in a separate script running in a new terminal window), [subscribe to the same channel](#subscribe) that you publish the message to.
:::

#### Returns

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

##### FOnPublishMessageResponse

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

##### FPubnubMessageData

| Field | Type | Description |
| --- | --- | --- |
| `Message` | `FString` | The message itself. |
| `Channel` | `FString` | Channel that the message was published to. |
| `UserID` | `FString` | The message information about the publisher. |
| `Timetoken` | `FString` | The time token of the message, indicating when it was published. |
| `Metadata` | `FString` | The message metadata, as published. |
| `MessageType` | [EPubnubMessageType](#epubnubmessagetype) | Indicates the message type: a signal, published, or another type. |
| `CustomMessageType` | `FString` | User-provided message type. |
| `MatchOrGroup` | `FString` | Subscription match or the channel group. |
| `region` | `int` | Region of the message. Not relevant in most cases. |
| `flags` | `int` | Message flags. |

##### EPubnubMessageType

| Field | Description |
| --- | --- |
| `PMT_Signal` | Indicates that the message was received as a signal. |
| `PMT_Published` | Indicates that the message was published. |
| `PMT_Action` | Indicates an action on a published message. |
| `PMT_Objects` | Message about Objects. |
| `PMT_Files` | Message about Files. |

##### FOnPublishMessageResponseNative

| Field | Type | Description |
| --- | --- | --- |
| `Result` | [const FPubnubOperationResult&](https://www.pubnub.com/docs/sdks/unreal/api-reference/configuration#operation-result) | The result of the operation. |
| `PublishedMessage` | [const FPubnubMessageData&](#fpubnubmessagedata) | A struct containing 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.
:::

##### Publish a message with settings

###### Actor.h

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

UFUNCTION(BlueprintCallable, Category = "Pubnub|Samples|ChannelEntity")
void PublishWithSettingsSample();
```

###### Actor.cpp

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

	// Create a channel entity for the channel you want to work with
	FString ChannelName = TEXT("global_chat");
	UPubnubChannelEntity* ChannelEntity = PubnubClient->CreateChannelEntity(ChannelName);

	// Set Message to Publish
	FString JsonMessage = R"({"event": "PowerUpUsed", "powerup": "Invisibility Cloak", "duration": 10})";

	// Create additional PublishSettings
	FPubnubPublishSettings PublishSettings;
	PublishSettings.MetaData = R"({"map": "DesertStrike", "match_id": "MATCH-42"})";
	PublishSettings.CustomMessageType = "game-event";

	// Publish message with settings using the channel entity
	ChannelEntity->PublishMessageAsync(JsonMessage, PublishSettings);
}
```

##### Publish a message with result

###### Actor.h

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

UFUNCTION(BlueprintCallable, Category = "Pubnub|Samples|ChannelEntity")
void PublishWithResultSample();
	
UFUNCTION()
void PublishedMessageResponse(FPubnubOperationResult Result, FPubnubMessageData Message);
```

###### Actor.cpp

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

	// Create a channel entity for the channel you want to work with
	FString ChannelName = TEXT("global_chat");
	UPubnubChannelEntity* ChannelEntity = PubnubClient->CreateChannelEntity(ChannelName);

	// Bind PublishedMessageResponse to be fired with PublishMessage result
	// ACTION REQUIRED: Replace ASample_ChannelEntity with name of your Actor class
	FOnPubnubPublishMessageResponse OnPublishMessageResponse;
	OnPublishMessageResponse.BindDynamic(this, &ASample_ChannelEntity::PublishedMessageResponse);
	
	// Publish simple text message using the channel entity
	FString SimpleMessage = TEXT("Ready to start the mission!");
	ChannelEntity->PublishMessageAsync(SimpleMessage, OnPublishMessageResponse);
}

// ACTION REQUIRED: Replace ASample_ChannelEntity with name of your Actor class
void ASample_ChannelEntity::PublishedMessageResponse(FPubnubOperationResult Result, FPubnubMessageData Message)
{
	if(Result.Error)
	{
		UE_LOG(LogTemp, Error, TEXT("Failed to publish message. Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
	}
	else
	{
		UE_LOG(LogTemp, Log, TEXT("Message published successfully. Published message timetoken: %s"), *Message.Timetoken);
	}
}
```

### PubNub client

#### Method(s)

```cpp
PubnubClient->PublishMessageAsync(
    FString Channel,
    FString Message,
    FOnPubnubPublishMessageResponse OnPublishMessageResponse,
    FPubnubPublishSettings PublishSettings = FPubnubPublishSettings()
);
```

| Parameter | Description |
| --- | --- |
| `Channel` *Type: `FString` | The channel ID to send the message to. |
| `Message` *Type: `FString` | The message to publish. Can be a literal string or JSON-formatted string containing serialized data. |
| `OnPublishMessageResponse`Type: [FOnPubnubPublishMessageResponse](#fonpubnubpublishmessageresponse) | The delegate for the operation's result. You can also use a native callback of the type [FOnPubnubPublishMessageResponseNative](#fonpubnubpublishmessageresponsenative) to handle the result using a lambda. |
| `PublishSettings`Type: [FPubnubPublishSettings](#fpubnubpublishsettings) | Struct defining publish configuration. |

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

##### Publish a message to a channel

###### C++

###### Actor.h

```cpp
#include "PubnubClient.h"

// blueprint.wsbv6i96
UFUNCTION(BlueprintCallable, Category = "Pubnub|Samples|PubSub")
void PublishSimpleSample();
```

###### Actor.cpp

```cpp
// ACTION REQUIRED: Replace ASample_PubSub with name of your Actor class
void ASample_PubSub::PublishSimpleSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set
	
	//Publish simple text message to provided channel
	FString Channel = TEXT("global_chat");
	FString SimpleMessage = TEXT("Ready to start the mission!");
	PubnubClient->PublishMessageAsync(Channel, SimpleMessage);
}
```

###### Blueprint

#### Returns

This method is void. The delegate returns the following struct:

##### FOnPubnubPublishMessageResponse

| Field | Type | Description |
| --- | --- | --- |
| `Result` | [FPubnubOperationResult](https://www.pubnub.com/docs/sdks/unreal/api-reference/configuration#operation-result) | The result of the operation. |
| `PublishedMessage` | [FPubnubMessageData](#fpubnubmessagedata) | A struct containing the published message data including timetoken and channel information. |

##### FOnPubnubPublishMessageResponseNative

| Field | Type | Description |
| --- | --- | --- |
| `Result` | [const FPubnubOperationResult&](https://www.pubnub.com/docs/sdks/unreal/api-reference/configuration#operation-result) | The result of the operation. |
| `PublishedMessage` | [const FPubnubMessageData&](#fpubnubmessagedata) | A struct containing the published message data including timetoken and channel information. |

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

##### Publish a message with settings

###### C++

###### Actor.h

```cpp
#include "PubnubClient.h"

// blueprint._edd6l7i
UFUNCTION(BlueprintCallable, Category = "Pubnub|Samples|PubSub")
void PublishWithSettingsSample();
```

###### Actor.cpp

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

	//Set Channel and Message to Publish
	FString Channel = TEXT("global_chat");
	FString JsonMessage = R"({"event": "PowerUpUsed", "powerup": "Invisibility Cloak", "duration": 10})";

	//Create additional PublishSettings
	FPubnubPublishSettings PublishSettings;
	PublishSettings.MetaData = R"({"map": "DesertStrike", "match_id": "MATCH-42"})";
	PublishSettings.CustomMessageType = "game-event";

	//Publish message with settings
	PubnubClient->PublishMessageAsync(Channel, JsonMessage, PublishSettings);
}
```

###### Blueprint

##### Publish a message with result

###### C++

###### Actor.h

```cpp
#include "PubnubClient.h"

// blueprint.et_v8xym
UFUNCTION(BlueprintCallable, Category = "Pubnub|Samples|PubSub")
void PublishWithResultSample();
	
UFUNCTION()
void PublishedMessageResponse(FPubnubOperationResult Result, FPubnubMessageData Message);
```

###### Actor.cpp

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

	//Bind PublishedMessageResponse to be fired with PublishMessage result
	// ACTION REQUIRED: Replace ASample_PubSub with name of your Actor class
	FOnPubnubPublishMessageResponse OnPublishMessageResponse;
	OnPublishMessageResponse.BindDynamic(this, &ASample_PubSub::PublishedMessageResponse);
	
	//Publish simple text message to provided channel
	FString Channel = TEXT("global_chat");
	FString SimpleMessage = TEXT("Ready to start the mission!");
	PubnubClient->PublishMessageAsync(Channel, SimpleMessage, OnPublishMessageResponse);
}

// ACTION REQUIRED: Replace ASample_PubSub with name of your Actor class
void ASample_PubSub::PublishedMessageResponse(FPubnubOperationResult Result, FPubnubMessageData Message)
{
	if(Result.Error)
	{
		UE_LOG(LogTemp, Error, TEXT("Failed to publish message. Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
	}
	else
	{
		UE_LOG(LogTemp, Log, TEXT("Message published successfully. Published message timetoken: %s"), *Message.Timetoken);
	}
}
```

###### Blueprint

## Signal

The `Signal()` function sends a signal to all subscribers of a channel.

By default, signals are limited to a message payload size of `64` bytes. This limit applies only to the payload, and not to the URI or headers. If you require a larger payload size, [contact support](https://www.pubnub.com/docs/mailto:support@pubnub.com).

### Prerequisites and limitations

* You must [initialize PubNub](https://www.pubnub.com/docs/sdks/unreal/api-reference/configuration) with the `publishKey`.
* The message payload size (without the URI or headers) is limited to `64` bytes. If you require a larger payload size, [contact support](https://www.pubnub.com/docs/mailto:support@pubnub.com).

### Signal vs. Message

| **Feature** | **Signals** | **Messages** |
| --- | --- | --- |
| **Payload size** | Limited to 64 bytes (64B) | Up to 32 KiB |
| **Cost efficiency** | Cost less than standard messages | Generally more expensive than signals |
| **Persistence** | Cannot be saved in [Message Persistence](https://www.pubnub.com/docs/sdks/unreal/api-reference/storage-and-playback) (past signals cannot be accessed) | Can be saved and accessed through Message Persistence |
| **Push Notifications** | Cannot trigger Mobile Push Notifications | Can trigger Mobile Push Notifications |
| **Use case suitability** | Best for non-critical data streams, like geolocation updates | Suitable for critical and non-critical use cases |
| **Metadata support** | Do not support metadata | Support metadata |

:::note Channel separation
Signals and messages should be sent on separate channels to improve connection recovery behavior.
:::

You can call `Signal()` on a [Channel entity](#signal-channel-entity) (which already knows its channel) or directly on the [PubNub client](#signal-pubnub-client) by passing the channel name explicitly.

### Channel entity

##### Available in entities

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

#### Method(s)

To signal to a channel, you must first create a [Channel entity](https://www.pubnub.com/docs/sdks/unreal/entities/channel) where you provide the name of the channel you want to signal to.

```cpp
UPubnubChannelEntity* ChannelEntity = PubnubSubsystem->CreateChannelEntity("my-channel");

ChannelEntity->Signal(
    FString Message,
    FOnSignalResponse OnSignalResponse,
    FPubnubSignalSettings SignalSettings = FPubnubSignalSettings()
);
```

| Parameter | Description |
| --- | --- |
| `Message` *Type: `FString` | The message to publish. Can be a literal string or JSON-formatted string containing serialized data. |
| `OnSignalResponse`Type: [FOnSignalResponse](#fonsignalresponse) | The delegate for the operation's result. You can also use a native callback of the type [FOnSignalResponseNative](#fonsignalresponsenative) to handle the result using a lambda. |
| `SignalSettings`Type: [FPubnubSignalSettings](#fpubnubsignalsettings) | Struct defining signal configuration. |

##### FPubnubSignalSettings

| Parameter | Description |
| --- | --- |
| `CustomMessageType`Type: `FString` | A case-sensitive, alphanumeric string from 3 to 50 characters describing the business-specific label or category of the message. Dashes `-` and underscores `_` are allowed. The value cannot start with special characters or the string `pn_` or `pn-`. Examples: `text`, `action`, `poll`. |

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

##### Signal a message to a channel

###### C++

###### Actor.h

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

UFUNCTION(BlueprintCallable, Category = "Pubnub|Samples|ChannelEntity")
void SimpleSignalSample();
```

###### Actor.cpp

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

	// Create a channel entity for the channel you want to work with
	FString ChannelName = TEXT("global_chat");
	UPubnubChannelEntity* ChannelEntity = PubnubClient->CreateChannelEntity(ChannelName);

	// Send signal message using the channel entity
	FString SimpleMessage = TEXT("Ready to start the mission!");
	ChannelEntity->SignalAsync(SimpleMessage);
}
```

#### Returns

The delegate returns the [FOnSignalResponse](#fonsignalresponse) struct.

##### FOnSignalResponse

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

##### FOnSignalResponseNative

| Field | Type | Description |
| --- | --- | --- |
| `Result` | [const FPubnubOperationResult&](https://www.pubnub.com/docs/sdks/unreal/api-reference/configuration#operation-result) | The result of the operation. |
| `SignalMessage` | [const FPubnubMessageData&](#fpubnubmessagedata) | A struct containing 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.
:::

##### Signal with custom message type

###### Actor.h

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

UFUNCTION(BlueprintCallable, Category = "Pubnub|Samples|ChannelEntity")
void SignalWithSettingsSample();
```

###### Actor.cpp

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

	// Create a channel entity for the channel you want to work with
	FString ChannelName = TEXT("guild_chat");
	UPubnubChannelEntity* ChannelEntity = PubnubClient->CreateChannelEntity(ChannelName);

	// Set Message to Signal
	FString Message = TEXT("PlayerTyping");

	// Create additional SignalSettings
	FPubnubSignalSettings SignalSettings;
	SignalSettings.CustomMessageType = "typing-indicator";

	// Send signal with settings using the channel entity
	ChannelEntity->SignalAsync(Message, SignalSettings);
}
```

### PubNub client

#### Method(s)

```cpp
PubnubClient->SignalAsync(
    FString Channel,
    FString Message,
    FOnPubnubSignalResponse OnSignalResponse,
    FPubnubSignalSettings SignalSettings = FPubnubSignalSettings()
);
```

| Parameter | Description |
| --- | --- |
| `Channel` *Type: `FString` | The channel ID to send the signal to. |
| `Message` *Type: `FString` | The message to publish. Can be a literal string or JSON-formatted string containing serialized data. |
| `OnSignalResponse`Type: [FOnPubnubSignalResponse](#fonpubnubsignalresponse) | The delegate for the operation's result. You can also use a native callback of the type [FOnPubnubSignalResponseNative](#fonpubnubsignalresponsenative) to handle the result using a lambda. |
| `SignalSettings`Type: [FPubnubSignalSettings](#fpubnubsignalsettings) | Struct defining signal configuration. |

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

##### Signal a message to a channel

###### C++

###### Actor.h

```cpp
#include "PubnubClient.h"

// blueprint.mmy6g9-_
UFUNCTION(BlueprintCallable, Category = "Pubnub|Samples|PubSub")
void SimpleSignalSample();
```

###### Actor.cpp

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

	//Send signal message to provided channel
	FString Channel = TEXT("global_chat");
	FString SimpleMessage = TEXT("Ready to start the mission!");
	PubnubClient->SignalAsync(Channel, SimpleMessage);
}
```

###### Blueprint

#### Returns

This method is void. The delegate returns the following struct:

##### FOnPubnubSignalResponse

| Field | Type | Description |
| --- | --- | --- |
| `Result` | [FPubnubOperationResult](https://www.pubnub.com/docs/sdks/unreal/api-reference/configuration#operation-result) | The result of the operation. |
| `SignalMessage` | [FPubnubMessageData](#fpubnubmessagedata) | A struct containing the signal message data including timetoken and channel information. |

##### FOnPubnubSignalResponseNative

| Field | Type | Description |
| --- | --- | --- |
| `Result` | [const FPubnubOperationResult&](https://www.pubnub.com/docs/sdks/unreal/api-reference/configuration#operation-result) | The result of the operation. |
| `SignalMessage` | [const FPubnubMessageData&](#fpubnubmessagedata) | A struct containing the signal message data including timetoken and channel information. |

#### Other examples

##### Signal with custom message type

###### C++

###### Actor.h

```cpp
#include "PubnubClient.h"

// blueprint.xrmsghs7
UFUNCTION(BlueprintCallable, Category = "Pubnub|Samples|PubSub")
void SignalWithSettingsSample();
```

###### Actor.cpp

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

	//Set Channel and Message to Signal
	FString Channel = TEXT("guild_chat");
	FString Message = TEXT("PlayerTyping");

	//Create additional SignalSettings
	FPubnubSignalSettings SignalSettings;
	SignalSettings.CustomMessageType = "typing-indicator";

	//Send signal with settings
	PubnubClient->SignalAsync(Channel, Message, SignalSettings);
}
```

###### Blueprint

##### Signal with result

###### C++

###### Actor.h

```cpp
#include "PubnubClient.h"

// blueprint.larcjidg
UFUNCTION(BlueprintCallable, Category = "Pubnub|Samples|PubSub")
void SignalWithResultSample();

UFUNCTION()
void SignalMessageResponse(FPubnubOperationResult Result, FPubnubMessageData Message);
```

###### Actor.cpp

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

	//Bind SignalMessageResponse to be fired with Signal result
	// ACTION REQUIRED: Replace ASample_PubSub with name of your Actor class
	FOnPubnubSignalResponse OnSignalResponse;
	OnSignalResponse.BindDynamic(this, &ASample_PubSub::SignalMessageResponse);
	
	//Send signal message to provided channel
	FString Channel = TEXT("global_chat");
	FString SimpleMessage = TEXT("Player is aiming");
	PubnubClient->SignalAsync(Channel, SimpleMessage, OnSignalResponse);
}

// ACTION REQUIRED: Replace ASample_PubSub with name of your Actor class
void ASample_PubSub::SignalMessageResponse(FPubnubOperationResult Result, FPubnubMessageData Message)
{
	if(Result.Error)
	{
		UE_LOG(LogTemp, Error, TEXT("Failed to send signal. Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
	}
	else
	{
		UE_LOG(LogTemp, Log, TEXT("Signal sent successfully. Signal timetoken: %s"), *Message.Timetoken);
	}
}
```

###### Blueprint

## Subscribe

Subscribe opens a TCP socket and listens for messages and events on a specified entity or set of entities. Set `SubscribeKey` during [initialization](https://www.pubnub.com/docs/sdks/unreal/api-reference/configuration#configuration-and-initialization).

:::tip Conceptual overview
For more general information about subscriptions, refer to [Subscriptions](https://www.pubnub.com/docs/general/channels/subscribe).
:::

Entities are [first-class citizens](https://en.wikipedia.org/wiki/First-class_citizen) that expose their APIs. You can subscribe using the PubNub client or directly on a specific entity:

* [Channel](https://www.pubnub.com/docs/sdks/unreal/entities/channel)
* [ChannelGroup](https://www.pubnub.com/docs/sdks/unreal/entities/channel-group)
* [UserMetadata](https://www.pubnub.com/docs/sdks/unreal/entities/user-metadata)
* [ChannelMetadata](https://www.pubnub.com/docs/sdks/unreal/entities/channel-metadata)

After `Subscribe()`, the client receives new messages. Configure automatic reconnection handling through the PubNub subsystem.

### Subscription scope

Subscriptions let you attach listeners for specific real-time update types. Your app receives messages and events through those listeners. There are two types:

* [Subscription](#create-a-subscription): created from an entity and scoped to that entity (for example, a particular channel)
* [SubscriptionSet](#create-a-subscription-set): created from the PubNub client and scoped to the client (for example, all subscriptions created on a single `PubnubSubsystem` object). A set can include one or more subscriptions.

The event listener is a single point through which your app receives all the messages, signals, and events in the entities you subscribed to. For information on adding event listeners, refer to [Event listeners](#event-listeners).

### Create a subscription

:::note Managing subscription lifecycle
The subscription object lives independently from the entity and requires separate lifecycle management. The subscription will remain valid and functional even if the entity goes out of scope or is destroyed.
:::

An entity-level `Subscription` allows you to receive messages and events for only that entity for which it was created. Using multiple entity-level `Subscriptions` is useful for handling various message/event types differently in each channel.

```cpp
// Create entity
UPubnubChannelEntity* ChannelEntity = PubnubSubsystem->CreateChannelEntity("my-channel");

// Create subscription from entity
UPubnubSubscription* Subscription = ChannelEntity->CreateSubscription();
```

| Parameter | Description |
| --- | --- |
| `SubscribeSettings`Type: [FPubnubSubscribeSettings](#fpubnubsubscribesettings) | Settings for the subscription configuration. |

#### FPubnubSubscribeSettings

| Parameter | Description |
| --- | --- |
| `ReceivePresenceEvents`Type: bool | Whether to subscribe to [presence events](https://www.pubnub.com/docs/general/presence/presence-events). |

### Create a subscription set

:::note Managing subscription lifecycle
The subscription object lives independently from the entity and requires separate lifecycle management. The subscription will remain valid and functional even if the entity goes out of scope or is destroyed.
:::

A client-level `SubscriptionSet` allows you to receive messages and events for all entities in the set. A single `SubscriptionSet` is useful for similarly handling various message/event types in each channel.

#### From channel or channel group names

You can create a subscription set from channel and channel group names.

```cpp
PubnubSubsystem->CreateSubscriptionSet(Channels, ChannelGroups, SubscriptionSettings);
```

| Parameter | Description |
| --- | --- |
| `Channels`Type: `TArray<FString>` | Array of channel names to include in the subscription set. |
| `ChannelGroups`Type: `TArray<FString>` | Array of channel group names to include in the subscription set. |
| `SubscriptionSettings`Type: [FPubnubSubscribeSettings](#fpubnubsubscribesettings) | Settings for the subscription configuration. |

#### From entities

You can create a subscription set from existing entities.

```cpp
PubnubSubsystem->CreateSubscriptionSetFromEntities(Entities, SubscriptionSettings);
```

| Parameter | Description |
| --- | --- |
| `Entities` *Type: `TArray<UPubnubBaseEntity*>` | Array of entities to include in the subscription set. |
| `SubscriptionSettings`Type: [FPubnubSubscribeSettings](#fpubnubsubscribesettings) | Settings for the subscription configuration. |

### Method(s)

`Subscription` and `SubscriptionSet` use the same methods to subscribe:

* [Subscribe](#subscribe)
* [Subscribe with timetoken](#subscribe-with-timetoken)

#### Subscribe

To subscribe, you can use the following methods:

```cpp
// Subscribe to start receiving messages
Subscription->Subscribe();
// Subscribe to all entities in the set
SubscriptionSet->Subscribe();
```

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

##### Subscribe to a channel

###### C++

###### Actor.h

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

UFUNCTION(BlueprintCallable, Category = "Pubnub|Samples|ChannelEntity")
void SubscribeWithChannelEntitySample();

UFUNCTION()
void OnMessageReceived_ChannelEntitySample(FPubnubMessageData Message);
```

###### Actor.cpp

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

	// Create a channel entity for the channel you want to work with
	FString ChannelName = TEXT("game_lobby");
	UPubnubChannelEntity* ChannelEntity = PubnubClient->CreateChannelEntity(ChannelName);

	// Create a subscription from the channel entity
	UPubnubSubscription* ChannelSubscription = ChannelEntity->CreateSubscription();

	// Add message listener to the subscription
	// ACTION REQUIRED: Replace ASample_ChannelEntity with name of your Actor class
	ChannelSubscription->OnPubnubMessage.AddDynamic(this, &ASample_ChannelEntity::OnMessageReceived_ChannelEntitySample);

	// Subscribe to start receiving messages
	ChannelSubscription->SubscribeAsync();
}

// ACTION REQUIRED: Replace ASample_ChannelEntity with name of your Actor class
void ASample_ChannelEntity::OnMessageReceived_ChannelEntitySample(FPubnubMessageData Message)
{
	UE_LOG(LogTemp, Log, TEXT("Channel Entity - Message received: %s on channel: %s"), *Message.Message, *Message.Channel);
}
```

#### Subscribe with timetoken

You can subscribe with a specific timetoken to receive messages from that point in time.

```cpp
// Subscribe with timetoken
FPubnubSubscriptionCursor Cursor;
Cursor.Timetoken = "15640261328790011";

Subscription->Subscribe(Cursor);
```

##### FPubnubSubscriptionCursor

| Parameter Type | Required | Description | | :---------- | :-------- | :------- | :------ | | `Timetoken` | `FString` | Yes | Timetoken from which messages should be retrieved. | | `Region` | `int` | No | Region of the messages. Set automatically; typically not required to set. |

#### Add subscriptions

You can add individual subscriptions to an existing set to create new sets. If you subscribe to a subscription set and then add more subscriptions, they are automatically subscribed to.

```cpp
// Add individual subscription to set
UPubnubSubscription* NewSubscription = ChannelEntity->CreateSubscription();
SubscriptionSet->AddSubscription(NewSubscription);
```

#### Remove subscriptions

You can remove individual subscriptions from a subscription set.

```cpp
// Remove subscription from set
SubscriptionSet->RemoveSubscription(NewSubscription);
```

#### Merge subscription sets

You can merge multiple subscription sets together.

```cpp
// Merge subscription sets
SubscriptionSet1->AddSubscriptionSet(SubscriptionSet2);
```

#### Remove subscription sets

You can remove entire subscription sets from another set.

```cpp
// Remove subscription set from another set
SubscriptionSet1->RemoveSubscriptionSet(SubscriptionSet2);
```

### Other examples

#### Subscribe to a channel group

##### Actor.h

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

UFUNCTION(BlueprintCallable, Category = "Pubnub|Samples|ChannelGroupEntity")
void SubscribeWithChannelGroupEntitySample();

UFUNCTION()
void OnMessageReceived_ChannelGroupEntitySample(FPubnubMessageData Message);
```

##### Actor.cpp

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

	// Create a channel group entity for the group you want to work with
	FString ChannelGroupName = TEXT("game_rooms");
	UPubnubChannelGroupEntity* ChannelGroupEntity = PubnubClient->CreateChannelGroupEntity(ChannelGroupName);

	// Create a subscription from the channel group entity
	UPubnubSubscription* GroupSubscription = ChannelGroupEntity->CreateSubscription();

	// Add message listener to the subscription
	// ACTION REQUIRED: Replace ASample_ChannelGroupEntity with name of your Actor class
	GroupSubscription->OnPubnubMessage.AddDynamic(this, &ASample_ChannelGroupEntity::OnMessageReceived_ChannelGroupEntitySample);

	// Subscribe to start receiving messages from all channels in the group
	GroupSubscription->SubscribeAsync();
}

// ACTION REQUIRED: Replace ASample_ChannelGroupEntity with name of your Actor class
void ASample_ChannelGroupEntity::OnMessageReceived_ChannelGroupEntitySample(FPubnubMessageData Message)
{
	UE_LOG(LogTemp, Log, TEXT("Channel Group Entity - Message received: %s on channel: %s"), *Message.Message, *Message.Channel);
}
```

#### Subscribe to channel metadata

##### Actor.h

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

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

UFUNCTION()
void OnObjectEvent_ChannelMetadataEntitySample(FPubnubMessageData Message);
```

##### Actor.cpp

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

	// Create a channel metadata entity for the channel you want to monitor metadata changes
	FString ChannelName = TEXT("lobby_settings");
	UPubnubChannelMetadataEntity* ChannelMetadataEntity = PubnubClient->CreateChannelMetadataEntity(ChannelName);

	// Create a subscription from the channel metadata entity
	UPubnubSubscription* MetadataSubscription = ChannelMetadataEntity->CreateSubscription();

	// Add object event listener to receive App Context metadata change notifications
	// ACTION REQUIRED: Replace ASample_ChannelMetadataEntity with name of your Actor class
	MetadataSubscription->OnPubnubObjectEvent.AddDynamic(this, &ASample_ChannelMetadataEntity::OnObjectEvent_ChannelMetadataEntitySample);

	// Subscribe to start receiving metadata change events
	MetadataSubscription->SubscribeAsync();
}

// ACTION REQUIRED: Replace ASample_ChannelMetadataEntity with name of your Actor class
void ASample_ChannelMetadataEntity::OnObjectEvent_ChannelMetadataEntitySample(FPubnubMessageData Message)
{
	UE_LOG(LogTemp, Log, TEXT("Channel Metadata Entity - Object event received: %s"), *Message.Message);
}
```

#### Subscribe to user metadata

##### Actor.h

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

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

UFUNCTION()
void OnObjectEvent_UserMetadataEntitySample(FPubnubMessageData Message);
```

##### Actor.cpp

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

	// Create a user metadata entity for the user you want to monitor metadata changes
	FString UserToMonitor = TEXT("Player_002");
	UPubnubUserMetadataEntity* UserMetadataEntity = PubnubClient->CreateUserMetadataEntity(UserToMonitor);

	// Create a subscription from the user metadata entity
	UPubnubSubscription* UserMetadataSubscription = UserMetadataEntity->CreateSubscription();

	// Add object event listener to receive App Context user metadata change notifications
	// ACTION REQUIRED: Replace ASample_UserMetadataEntity with name of your Actor class
	UserMetadataSubscription->OnPubnubObjectEvent.AddDynamic(this, &ASample_UserMetadataEntity::OnObjectEvent_UserMetadataEntitySample);

	// Subscribe to start receiving user metadata change events
	UserMetadataSubscription->SubscribeAsync();
}

// ACTION REQUIRED: Replace ASample_UserMetadataEntity with name of your Actor class
void ASample_UserMetadataEntity::OnObjectEvent_UserMetadataEntitySample(FPubnubMessageData Message)
{
	UE_LOG(LogTemp, Log, TEXT("User Metadata Entity - Object event received: %s"), *Message.Message);
}
```

#### Create subscription set from names

##### C++

##### Actor.h

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

// blueprint.9d9mt0u6
UFUNCTION(BlueprintCallable, Category = "Pubnub|Samples|SubscriptionSet")
void CreateSubscriptionSetFromNamesSample();

UFUNCTION()
void OnMessage_SubscriptionSetFromNamesSample(FPubnubMessageData Message);
```

##### Actor.cpp

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

	// Define multiple channels and channel groups to monitor for team coordination
	TArray<FString> TeamChannels = {
		TEXT("squad_alpha_chat"),        // Alpha team communication
		TEXT("squad_bravo_chat"),        // Bravo team communication
		TEXT("tactical_announcements")   // Mission updates and announcements
	};

	TArray<FString> OperationChannelGroups = {
		TEXT("mission_channels"),        // All mission-related channels
		TEXT("support_channels")         // Support and logistics channels
	};

	// Create subscription set from channel and group names - monitors all team communications
	UPubnubSubscriptionSet* TeamCommSubscriptionSet = PubnubClient->CreateSubscriptionSet(TeamChannels, OperationChannelGroups);

	// Add message listener to monitor all team communications
	// ACTION REQUIRED: Replace ASample_SubscriptionSet with name of your Actor class
	TeamCommSubscriptionSet->OnPubnubMessage.AddDynamic(this, &ASample_SubscriptionSet::OnMessage_SubscriptionSetFromNamesSample);

	// Subscribe to start monitoring all team channels and groups simultaneously
	TeamCommSubscriptionSet->SubscribeAsync();
}

// ACTION REQUIRED: Replace ASample_SubscriptionSet with name of your Actor class
void ASample_SubscriptionSet::OnMessage_SubscriptionSetFromNamesSample(FPubnubMessageData Message)
{
	UE_LOG(LogTemp, Log, TEXT("TEAM COMMS - Message on %s: %s (from %s)"), 
		*Message.Channel, *Message.Message, *Message.UserID);
}
```

##### Blueprint

#### Create subscription set from entities

##### C++

##### Actor.h

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

// blueprint.alzawuju
UFUNCTION(BlueprintCallable, Category = "Pubnub|Samples|SubscriptionSet")
void CreateSubscriptionSetFromEntitiesSample();

UFUNCTION()
void OnMessage_SubscriptionSetFromEntitiesSample(FPubnubMessageData Message);
```

##### Actor.cpp

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

	// Create individual entities for different aspects of game monitoring
	UPubnubChannelEntity* PlayerStatsChannel = PubnubClient->CreateChannelEntity(TEXT("player_statistics"));
	UPubnubChannelEntity* GameEventsChannel = PubnubClient->CreateChannelEntity(TEXT("game_events_feed"));
	UPubnubChannelGroupEntity* ServerStatusGroup = PubnubClient->CreateChannelGroupEntity(TEXT("server_monitoring"));
	UPubnubChannelMetadataEntity* MatchConfigEntity = PubnubClient->CreateChannelMetadataEntity(TEXT("match_configuration"));

	// Combine different entity types into a comprehensive monitoring subscription set
	TArray<UPubnubBaseEntity*> MonitoringEntities = {
		PlayerStatsChannel,      // Monitor player performance data
		GameEventsChannel,       // Monitor in-game events (kills, objectives, etc.)
		ServerStatusGroup,       // Monitor all server status channels
		MatchConfigEntity        // Monitor match configuration changes
	};

	// Create subscription set from existing entities - provides unified monitoring dashboard
	UPubnubSubscriptionSet* GameMonitoringSet = PubnubClient->CreateSubscriptionSetFromEntities(MonitoringEntities);

	// Add message listener to capture all monitoring data
	// ACTION REQUIRED: Replace ASample_SubscriptionSet with name of your Actor class
	GameMonitoringSet->OnPubnubMessage.AddDynamic(this, &ASample_SubscriptionSet::OnMessage_SubscriptionSetFromEntitiesSample);

	// Add object event listener to monitor configuration changes
	// ACTION REQUIRED: Replace ASample_SubscriptionSet with name of your Actor class
	GameMonitoringSet->OnPubnubObjectEvent.AddDynamic(this, &ASample_SubscriptionSet::OnMessage_SubscriptionSetFromEntitiesSample);

	// Subscribe to start comprehensive game monitoring
	GameMonitoringSet->SubscribeAsync();
}

// ACTION REQUIRED: Replace ASample_SubscriptionSet with name of your Actor class
void ASample_SubscriptionSet::OnMessage_SubscriptionSetFromEntitiesSample(FPubnubMessageData Message)
{
	UE_LOG(LogTemp, Log, TEXT("GAME MONITORING - Message on %s: %s (from %s)"), 
		*Message.Channel, *Message.Message, *Message.UserID);
}
```

##### Blueprint

#### Manage subscriptions in a set

##### Actor.h

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

UFUNCTION(BlueprintCallable, Category = "Pubnub|Samples|SubscriptionSet")
void SubscriptionSetAddRemoveSubscriptionsSample();
```

##### Actor.cpp

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

	// Create a subscription set for tournament management
	TArray<FString> TournamentChannels = {TEXT("tournament_lobby"), TEXT("match_results")};
	UPubnubSubscriptionSet* TournamentSet = PubnubClient->CreateSubscriptionSet(TournamentChannels, TArray<FString>());

	// Create individual subscriptions for different game areas
	UPubnubChannelEntity* PlayerFeedbackChannel = PubnubClient->CreateChannelEntity(TEXT("player_feedback"));
	UPubnubSubscription* FeedbackSubscription = PlayerFeedbackChannel->CreateSubscription();

	UPubnubChannelEntity* AdminNoticesChannel = PubnubClient->CreateChannelEntity(TEXT("admin_notices"));
	UPubnubSubscription* AdminSubscription = AdminNoticesChannel->CreateSubscription();

	// Add individual subscriptions to the tournament set
	TournamentSet->AddSubscription(FeedbackSubscription);
	TournamentSet->AddSubscription(AdminSubscription);

	// Check current subscriptions in the set
	TArray<UPubnubSubscription*> CurrentSubscriptions = TournamentSet->GetSubscriptions();
	UE_LOG(LogTemp, Log, TEXT("Tournament set now contains %d subscriptions"), CurrentSubscriptions.Num());

	// Remove a subscription when no longer needed
	TournamentSet->RemoveSubscription(FeedbackSubscription);

	// Check subscriptions after removal
	TArray<UPubnubSubscription*> SubscriptionsAfterRemoval = TournamentSet->GetSubscriptions();
	UE_LOG(LogTemp, Log, TEXT("Tournament set now contains %d subscriptions after removal"), SubscriptionsAfterRemoval.Num());
}
```

#### Merge subscription sets

##### Actor.h

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

UFUNCTION(BlueprintCallable, Category = "Pubnub|Samples|SubscriptionSet")
void SubscriptionSetMergeOperationsSample();

	
```

##### Actor.cpp

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

	// Create main subscription set for core game channels
	TArray<FString> CoreChannels = {TEXT("game_lobby"), TEXT("general_chat")};
	UPubnubSubscriptionSet* CoreGameSet = PubnubClient->CreateSubscriptionSet(CoreChannels, TArray<FString>());

	// Create additional subscription set for special events
	TArray<FString> EventChannels = {TEXT("special_events"), TEXT("tournament_updates")};
	UPubnubSubscriptionSet* SpecialEventsSet = PubnubClient->CreateSubscriptionSet(EventChannels, TArray<FString>());

	// Create VIP subscription set for premium features
	TArray<FString> VipChannels = {TEXT("vip_lounge"), TEXT("premium_support")};
	UPubnubSubscriptionSet* VipSet = PubnubClient->CreateSubscriptionSet(VipChannels, TArray<FString>());

	UE_LOG(LogTemp, Log, TEXT("Created core game set, special events set, and VIP set"));

	// Merge special events into core game monitoring
	CoreGameSet->AddSubscriptionSet(SpecialEventsSet);
	UE_LOG(LogTemp, Log, TEXT("Merged special events into core game monitoring"));

	// Merge VIP channels for comprehensive monitoring
	CoreGameSet->AddSubscriptionSet(VipSet);
	UE_LOG(LogTemp, Log, TEXT("Merged VIP channels for comprehensive event management"));

	// Later, remove special events if no longer needed
	CoreGameSet->RemoveSubscriptionSet(SpecialEventsSet);
	UE_LOG(LogTemp, Log, TEXT("Removed special events from monitoring (event ended)"));

	// Subscribe to the final combined set
	CoreGameSet->SubscribeAsync();
	UE_LOG(LogTemp, Log, TEXT("Now monitoring core game channels + VIP channels"));
}
```

## Event listeners

Messages and events are received in your app using listeners. This listener allows a single point to receive all messages, signals, and events.

You can attach listeners to the instances of [Subscription](#create-a-subscription), [SubscriptionSet](#create-a-subscription-set).

:::note No built-in event throttling
The PubNub SDK delivers every incoming event to your listener as it arrives — there is no built-in throttling or rate-limiting on the subscriber side. If you need to control how often your application processes events, wrap your listener callback with a throttle or debounce utility from your language or framework ecosystem.
To reduce the number of messages delivered to your client in the first place, use [Subscribe Filters](https://www.pubnub.com/docs/general/channels/subscribe-filters) to filter messages server-side before they reach your listener.
:::

### Add listeners

You can add listeners for various types of updates related to your subscription. You can implement listeners for general updates (that handle multiple event types at once) or choose listeners dedicated to specific event types such as `Message` or `Signal`.

:::tip Catch all events
The `OnAnyEventReceived` listener catches all event types.
:::

#### Handle multiple event types

You can add multiple event listeners to handle different types of events.

```cpp
// Add message listener
Subscription->OnPubnubMessage.AddDynamic(this, &AMyActor::OnMessageReceived);

// Add signal listener
Subscription->OnPubnubSignal.AddDynamic(this, &AMyActor::OnSignalReceived);

// Add presence event listener
Subscription->OnPubnubPresenceEvent.AddDynamic(this, &AMyActor::OnPresenceEventReceived);

// Add object event listener
Subscription->OnPubnubObjectEvent.AddDynamic(this, &AMyActor::OnObjectEventReceived);

// Add message action listener
Subscription->OnPubnubMessageAction.AddDynamic(this, &AMyActor::OnMessageActionReceived);

// Add universal listener (catches all event types)
Subscription->FOnPubnubAnyMessageType.AddDynamic(this, &AMyActor::OnAnyEventReceived);
```

#### Handle one event type with native callbacks

You can also use native callbacks that support lambda expressions.

```cpp
// Add native callback listeners
Subscription->OnPubnubMessageNative.AddLambda([](const FPubnubMessageData& Message) {
    UE_LOG(LogTemp, Log, TEXT("Message received: %s"), *Message.Message);
});

Subscription->OnPubnubSignalNative.AddLambda([](const FPubnubMessageData& Signal) {
    UE_LOG(LogTemp, Log, TEXT("Signal received: %s"), *Signal.Message);
});
```

#### Remove event listener

To remove the listener for a specific event, assign `nullptr` to it or use `RemoveAll()` on the delegate.

```cpp
// Remove specific listener
Subscription->OnPubnubMessage.RemoveDynamic(this, &AMyActor::OnMessageReceived);

// Remove all listeners for a specific event type
Subscription->OnPubnubMessage.RemoveAll(this);
```

### Add connection status listener

Use the subscription status listener with your `PubnubSubsystem` instance to add a listener dedicated to connection status updates.

:::warning Client scope
This listener is only available on the PubNub object.
:::

#### Method(s)

```cpp
// Add subscription status listener
PubnubSubsystem->OnSubscriptionStatusChanged.AddDynamic(this, &AMyActor::OnSubscriptionStatusChanged);
```

#### Sample code

##### C++

#### Actor.h

```cpp
#include "PubnubClient.h"

// blueprint.ld_4o3t8
UFUNCTION(BlueprintCallable, Category = "Pubnub|Samples|Configuration")
void SubscriptionStatusListenerSample();
	
UFUNCTION()
void OnSubscriptionStatusChanged(EPubnubSubscriptionStatus Status, FPubnubSubscriptionStatusData StatusData);
```

#### Actor.cpp

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

	//Bind delegate to the subscription status listener
	// ACTION REQUIRED: Replace ASample_Configuration with name of your Actor class
	PubnubClient->OnSubscriptionStatusChanged.AddDynamic(this, &ASample_Configuration::OnSubscriptionStatusChanged);
}

// ACTION REQUIRED: Replace ASample_Configuration with name of your Actor class
void ASample_Configuration::OnSubscriptionStatusChanged(EPubnubSubscriptionStatus Status, FPubnubSubscriptionStatusData StatusData)
{
	//Do something with changed status, for example print whenever there is connection error
	if(Status == EPubnubSubscriptionStatus::PSS_ConnectionError || Status == EPubnubSubscriptionStatus::PSS_DisconnectedUnexpectedly)
	{
		UE_LOG(LogTemp, Warning, TEXT("Something went wrong with subscription. Reason: %s"), *StatusData.Reason);
	}
}
```

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

#### Subscribe with all event listeners

##### Actor.h

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

UFUNCTION(BlueprintCallable, Category = "Pubnub|Samples|ChannelEntity")
void ChannelEntityAllListenersSample();

UFUNCTION()
void OnMessage_AllListenersSample(FPubnubMessageData Message);

UFUNCTION()
void OnSignal_AllListenersSample(FPubnubMessageData Message);

UFUNCTION()
void OnPresenceEvent_AllListenersSample(FPubnubMessageData Message);

UFUNCTION()
void OnObjectEvent_AllListenersSample(FPubnubMessageData Message);

UFUNCTION()
void OnMessageAction_AllListenersSample(FPubnubMessageData Message);

UFUNCTION()
void OnAnyEvent_AllListenersSample(FPubnubMessageData Message);
```

##### Actor.cpp

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

	// Create a channel entity
	FString ChannelName = TEXT("comprehensive_channel");
	UPubnubChannelEntity* ChannelEntity = PubnubClient->CreateChannelEntity(ChannelName);

	// Create a subscription with presence events enabled to receive all event types
	FPubnubSubscribeSettings SubscriptionSettings;
	SubscriptionSettings.ReceivePresenceEvents = true;
	UPubnubSubscription* Subscription = ChannelEntity->CreateSubscription(SubscriptionSettings);

	// Add ALL listener types to handle different PubNub events

	// 1. Message Listener - Fires when regular messages are published to the channel
	// ACTION REQUIRED: Replace ASample_ChannelEntity with name of your Actor class
	Subscription->OnPubnubMessage.AddDynamic(this, &ASample_ChannelEntity::OnMessage_AllListenersSample);

	// 2. Signal Listener - Fires when signals are sent to the channel
	// ACTION REQUIRED: Replace ASample_ChannelEntity with name of your Actor class
	Subscription->OnPubnubSignal.AddDynamic(this, &ASample_ChannelEntity::OnSignal_AllListenersSample);

	// 3. Presence Event Listener - Fires when users join/leave/timeout on the channel
	// ACTION REQUIRED: Replace ASample_ChannelEntity with name of your Actor class
	Subscription->OnPubnubPresenceEvent.AddDynamic(this, &ASample_ChannelEntity::OnPresenceEvent_AllListenersSample);

	// 4. Object Event Listener - Fires when App Context metadata changes occur
	// ACTION REQUIRED: Replace ASample_ChannelEntity with name of your Actor class
	Subscription->OnPubnubObjectEvent.AddDynamic(this, &ASample_ChannelEntity::OnObjectEvent_AllListenersSample);

	// 5. Message Action Listener - Fires when message actions/reactions are added or removed
	// ACTION REQUIRED: Replace ASample_ChannelEntity with name of your Actor class
	Subscription->OnPubnubMessageAction.AddDynamic(this, &ASample_ChannelEntity::OnMessageAction_AllListenersSample);

	// 6. Universal Listener - Fires for ANY type of PubNub event (catch-all)
	// ACTION REQUIRED: Replace ASample_ChannelEntity with name of your Actor class
	Subscription->FOnPubnubAnyMessageType.AddDynamic(this, &ASample_ChannelEntity::OnAnyEvent_AllListenersSample);

	// Subscribe to start receiving all event types
	Subscription->SubscribeAsync();
}

// ACTION REQUIRED: Replace ASample_ChannelEntity with name of your Actor class
void ASample_ChannelEntity::OnMessage_AllListenersSample(FPubnubMessageData Message)
{
	UE_LOG(LogTemp, Log, TEXT("MESSAGE LISTENER - Content: %s, Channel: %s, User: %s"), 
		*Message.Message, *Message.Channel, *Message.UserID);
}

// ACTION REQUIRED: Replace ASample_ChannelEntity with name of your Actor class
void ASample_ChannelEntity::OnSignal_AllListenersSample(FPubnubMessageData Message)
{
	UE_LOG(LogTemp, Log, TEXT("SIGNAL LISTENER - Content: %s, Channel: %s, User: %s"), 
		*Message.Message, *Message.Channel, *Message.UserID);
}

// ACTION REQUIRED: Replace ASample_ChannelEntity with name of your Actor class
void ASample_ChannelEntity::OnPresenceEvent_AllListenersSample(FPubnubMessageData Message)
{
	UE_LOG(LogTemp, Log, TEXT("PRESENCE LISTENER - Event: %s, Channel: %s"), 
		*Message.Message, *Message.Channel);
}

// ACTION REQUIRED: Replace ASample_ChannelEntity with name of your Actor class
void ASample_ChannelEntity::OnObjectEvent_AllListenersSample(FPubnubMessageData Message)
{
	UE_LOG(LogTemp, Log, TEXT("OBJECT EVENT LISTENER - Event: %s, Channel: %s"), 
		*Message.Message, *Message.Channel);
}

// ACTION REQUIRED: Replace ASample_ChannelEntity with name of your Actor class
void ASample_ChannelEntity::OnMessageAction_AllListenersSample(FPubnubMessageData Message)
{
	UE_LOG(LogTemp, Log, TEXT("MESSAGE ACTION LISTENER - Action: %s, Channel: %s"), 
		*Message.Message, *Message.Channel);
}

// ACTION REQUIRED: Replace ASample_ChannelEntity with name of your Actor class
void ASample_ChannelEntity::OnAnyEvent_AllListenersSample(FPubnubMessageData Message)
{
	UE_LOG(LogTemp, Log, TEXT("UNIVERSAL LISTENER - Type: %d, Content: %s, Channel: %s"), 
		(int32)Message.MessageType, *Message.Message, *Message.Channel);
}
```

#### Add message listener with lambda

##### Actor.h

```cpp
#include "PubnubClient.h"

UFUNCTION(BlueprintCallable, Category = "Pubnub|Samples|Configuration")
void MessageListenerLambdaSample();
	
```

##### Actor.cpp

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

	//Bind lambda delegate to the messages listener
	PubnubClient->OnMessageReceivedNative.AddLambda([](const FPubnubMessageData& MessageData)
	{
		//Do something with the message, for example print it
		UE_LOG(LogTemp, Log, TEXT("Message received on channel: %s. Message: %s"), *MessageData.Channel, *MessageData.Message);
	});
}
```

#### Add error listener

##### Actor.h

```cpp
#include "PubnubClient.h"

```

##### Actor.cpp

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

#include "Samples/Sample_Configuration.h"
#include "PubnubDefaultLogger.h"
#include "Interfaces/PubnubLoggerInterface.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_Configuration::RunSamples()
{
	Super::RunSamples();

	MessageListenerSample();
	MessageListenerLambdaSample();
	SubscriptionStatusListenerSample();
	SubscriptionStatusListenerLambdaSample();
	ListUsersFromChannelLambdaSample();
	AddLoggerSample();
	SetLogLevelAtRuntimeSample();
	SetLogLevelInConfigurationSample();
	GetLoggersSample();
	RemoveLoggerSample();
	ClearLoggersSample();
	
}
//Internal function, don't copy it with the samples
ASample_Configuration::ASample_Configuration()
{
	SamplesName = "Configuration";
}

/* SAMPLE FUNCTIONS */

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

	//Bind delegate to the messages listener
	// ACTION REQUIRED: Replace ASample_Configuration with name of your Actor class
	PubnubClient->OnMessageReceived.AddDynamic(this, &ASample_Configuration::OnPubnubMessageReceived);
}

// ACTION REQUIRED: Replace ASample_Configuration with name of your Actor class
void ASample_Configuration::OnPubnubMessageReceived(FPubnubMessageData MessageData)
{
	//Do something with the message, for example print it
	UE_LOG(LogTemp, Log, TEXT("Message received on channel: %s. Message: %s"), *MessageData.Channel, *MessageData.Message);
}

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

	//Bind lambda delegate to the messages listener
	PubnubClient->OnMessageReceivedNative.AddLambda([](const FPubnubMessageData& MessageData)
	{
		//Do something with the message, for example print it
		UE_LOG(LogTemp, Log, TEXT("Message received on channel: %s. Message: %s"), *MessageData.Channel, *MessageData.Message);
	});
}

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

	//Bind delegate to the subscription status listener
	// ACTION REQUIRED: Replace ASample_Configuration with name of your Actor class
	PubnubClient->OnSubscriptionStatusChanged.AddDynamic(this, &ASample_Configuration::OnSubscriptionStatusChanged);
}

// ACTION REQUIRED: Replace ASample_Configuration with name of your Actor class
void ASample_Configuration::OnSubscriptionStatusChanged(EPubnubSubscriptionStatus Status, FPubnubSubscriptionStatusData StatusData)
{
	//Do something with changed status, for example print whenever there is connection error
	if(Status == EPubnubSubscriptionStatus::PSS_ConnectionError || Status == EPubnubSubscriptionStatus::PSS_DisconnectedUnexpectedly)
	{
		UE_LOG(LogTemp, Warning, TEXT("Something went wrong with subscription. Reason: %s"), *StatusData.Reason);
	}
}

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

	//Bind lambda delegate to the subscription status listener
	PubnubClient->OnSubscriptionStatusChangedNative.AddLambda([](EPubnubSubscriptionStatus Status, FPubnubSubscriptionStatusData StatusData)
	{
		//Do something with changed status, for example print whenever there is connection error
		if(Status == EPubnubSubscriptionStatus::PSS_ConnectionError || Status == EPubnubSubscriptionStatus::PSS_DisconnectedUnexpectedly)
		{
			UE_LOG(LogTemp, Warning, TEXT("Something went wrong with subscription. Reason: %s"), *StatusData.Reason);
		}
	});
}

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

	// Bind response delegate
	// ACTION REQUIRED: Replace ASample_Configuration with name of your Actor class
	FOnPubnubListUsersFromChannelResponse OnListUsersFromChannelResponse;
	OnListUsersFromChannelResponse.BindDynamic(this, &ASample_Configuration::OnListUsersFromChannelResponse);

	//List users from a channel
	FString Channel = TEXT("guild-channel");
	PubnubClient->ListUsersFromChannelAsync(Channel, OnListUsersFromChannelResponse);
}

// ACTION REQUIRED: Replace ASample_Configuration with name of your Actor class
void ASample_Configuration::OnListUsersFromChannelResponse(FPubnubOperationResult Result, FPubnubListUsersFromChannelWrapper Data)
{
	if(Result.Error)
	{
		UE_LOG(LogTemp, Error, TEXT("Failed to list users from channel. Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
	}
	else
	{
		UE_LOG(LogTemp, Log, TEXT("Users successfully listed from channel. Occupancy: %d"), Data.Occupancy);
	}
}

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

	// Bind lambda to response delegate
	FOnPubnubListUsersFromChannelResponseNative OnListUsersFromChannelResponse;
	OnListUsersFromChannelResponse.BindLambda([](const FPubnubOperationResult& Result, const FPubnubListUsersFromChannelWrapper& Data)
	{
		if(Result.Error)
		{
			UE_LOG(LogTemp, Error, TEXT("Failed to list users from channel. Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
		}
		else
		{
			UE_LOG(LogTemp, Log, TEXT("Users successfully listed from channel. Occupancy: %d"), Data.Occupancy);
		}
	});
	
	//List users from a channel
	FString Channel = TEXT("guild-channel");
	PubnubClient->ListUsersFromChannelAsync(Channel, OnListUsersFromChannelResponse);
}

// snippet.create_pubnub_client

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

// ACTION REQUIRED: Replace ASample_Configuration with name of your Actor class
void ASample_Configuration::CreatePubnubClient()
{
	//Get PubnubSubsystem from GameInstance
	UGameInstance* GameInstance = UGameplayStatics::GetGameInstance(this);
	UPubnubSubsystem* PubnubSubsystem = GameInstance->GetSubsystem<UPubnubSubsystem>();

	// Create Pubnub Client using Pubnub Subsystem
	FPubnubConfig PubnubConfig;
	PubnubConfig.PublishKey = TEXT("demo");   //replace with your Publish Key from Admin Portal
	PubnubConfig.SubscribeKey = TEXT("demo"); //replace with your Subscribe Key from Admin Portal
	PubnubConfig.UserID = TEXT("Player_001");
	UPubnubClient* PubnubClient = PubnubSubsystem->CreatePubnubClient(PubnubConfig);
	
	UE_LOG(LogTemp, Log, TEXT("Pubnub Client created with config"));
}

// snippet.get_pubnub_client

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

// ACTION REQUIRED: Replace ASample_Configuration with name of your Actor class
UPubnubClient* ASample_Configuration::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;
}

// snippet.destroy_pubnub_client

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

// ACTION REQUIRED: Replace ASample_Configuration with name of your Actor class
void ASample_Configuration::DestroyPubnubClient()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	UGameInstance* GameInstance = UGameplayStatics::GetGameInstance(this);
	UPubnubSubsystem* PubnubSubsystem = GameInstance->GetSubsystem<UPubnubSubsystem>();
	
	PubnubSubsystem->DestroyPubnubClient(PubnubClient);
}

// snippet.add_logger
// ACTION REQUIRED: Replace ASample_Configuration with name of your Actor class
void ASample_Configuration::AddLoggerSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show

	//Assumes PubnubClient is created and UserID is set

	//Create logger object and register it in PubnubClient
	UPubnubDefaultLogger* CustomLogger = NewObject<UPubnubDefaultLogger>(this);
	if (!CustomLogger)
	{
		UE_LOG(LogTemp, Error, TEXT("Failed to create custom logger."));
		return;
	}

	TScriptInterface<IPubnubLoggerInterface> LoggerInterface;
	LoggerInterface.SetObject(CustomLogger);
	LoggerInterface.SetInterface(Cast<IPubnubLoggerInterface>(CustomLogger));

	PubnubClient->AddLogger(LoggerInterface);
}

// snippet.set_log_level_runtime
// ACTION REQUIRED: Replace ASample_Configuration with name of your Actor class
void ASample_Configuration::SetLogLevelAtRuntimeSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show

	//Assumes PubnubClient is created and UserID is set

	//Get all registered loggers
	TArray<TScriptInterface<IPubnubLoggerInterface>> Loggers = PubnubClient->GetLoggers();
	if (!Loggers.IsEmpty())
	{
		//Set new log levels for the first logger
		IPubnubLoggerInterface::Execute_SetMinimumLogLevel(Loggers[0].GetObject(), EPubnubLogLevel::PLL_Debug);
		IPubnubLoggerInterface::Execute_SetMinimumCCoreLogLevel(Loggers[0].GetObject(), EPubnubLogLevel::PLL_Warning);
	}
}

// snippet.set_log_level_configuration
// ACTION REQUIRED: Replace ASample_Configuration with name of your Actor class
void ASample_Configuration::SetLogLevelInConfigurationSample()
{
	//Get PubnubSubsystem from GameInstance
	UGameInstance* GameInstance = UGameplayStatics::GetGameInstance(this);
	UPubnubSubsystem* PubnubSubsystem = GameInstance->GetSubsystem<UPubnubSubsystem>();

	//Set logger levels directly in client configuration before creating PubnubClient
	FPubnubConfig PubnubConfig;
	PubnubConfig.PublishKey = TEXT("demo");   //replace with your Publish Key from Admin Portal
	PubnubConfig.SubscribeKey = TEXT("demo"); //replace with your Subscribe Key from Admin Portal
	PubnubConfig.UserID = TEXT("Player_001");
	PubnubConfig.LoggerConfig.DefaultLoggerMinLevel = EPubnubLogLevel::PLL_Debug;
	PubnubConfig.LoggerConfig.DefaultLoggerMinCCoreLevel = EPubnubLogLevel::PLL_Warning;

	UPubnubClient* PubnubClient = PubnubSubsystem->CreatePubnubClient(PubnubConfig);

	//Use PubnubClient as needed
	PubnubClient->PublishMessageAsync(TEXT("test-channel"), TEXT("Hello, world!"));
}

// snippet.get_loggers
// ACTION REQUIRED: Replace ASample_Configuration with name of your Actor class
void ASample_Configuration::GetLoggersSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show

	//Assumes PubnubClient is created and UserID is set

	TArray<TScriptInterface<IPubnubLoggerInterface>> Loggers = PubnubClient->GetLoggers();
}

// snippet.remove_logger
// ACTION REQUIRED: Replace ASample_Configuration with name of your Actor class
void ASample_Configuration::RemoveLoggerSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show

	//Assumes PubnubClient is created and UserID is set

	TArray<TScriptInterface<IPubnubLoggerInterface>> Loggers = PubnubClient->GetLoggers();

	//Remove the first registered logger
	PubnubClient->RemoveLogger(Loggers[0]);
}

// snippet.clear_loggers
// ACTION REQUIRED: Replace ASample_Configuration with name of your Actor class
void ASample_Configuration::ClearLoggersSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show

	//Assumes PubnubClient is created and UserID is set

	//Clear all registered loggers
	PubnubClient->ClearLoggers();
}

// snippet.end
```

#### Add error listener with lambda

##### Actor.h

```cpp
#include "PubnubClient.h"

```

##### Actor.cpp

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

#include "Samples/Sample_Configuration.h"
#include "PubnubDefaultLogger.h"
#include "Interfaces/PubnubLoggerInterface.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_Configuration::RunSamples()
{
	Super::RunSamples();

	MessageListenerSample();
	MessageListenerLambdaSample();
	SubscriptionStatusListenerSample();
	SubscriptionStatusListenerLambdaSample();
	ListUsersFromChannelLambdaSample();
	AddLoggerSample();
	SetLogLevelAtRuntimeSample();
	SetLogLevelInConfigurationSample();
	GetLoggersSample();
	RemoveLoggerSample();
	ClearLoggersSample();
	
}
//Internal function, don't copy it with the samples
ASample_Configuration::ASample_Configuration()
{
	SamplesName = "Configuration";
}

/* SAMPLE FUNCTIONS */

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

	//Bind delegate to the messages listener
	// ACTION REQUIRED: Replace ASample_Configuration with name of your Actor class
	PubnubClient->OnMessageReceived.AddDynamic(this, &ASample_Configuration::OnPubnubMessageReceived);
}

// ACTION REQUIRED: Replace ASample_Configuration with name of your Actor class
void ASample_Configuration::OnPubnubMessageReceived(FPubnubMessageData MessageData)
{
	//Do something with the message, for example print it
	UE_LOG(LogTemp, Log, TEXT("Message received on channel: %s. Message: %s"), *MessageData.Channel, *MessageData.Message);
}

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

	//Bind lambda delegate to the messages listener
	PubnubClient->OnMessageReceivedNative.AddLambda([](const FPubnubMessageData& MessageData)
	{
		//Do something with the message, for example print it
		UE_LOG(LogTemp, Log, TEXT("Message received on channel: %s. Message: %s"), *MessageData.Channel, *MessageData.Message);
	});
}

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

	//Bind delegate to the subscription status listener
	// ACTION REQUIRED: Replace ASample_Configuration with name of your Actor class
	PubnubClient->OnSubscriptionStatusChanged.AddDynamic(this, &ASample_Configuration::OnSubscriptionStatusChanged);
}

// ACTION REQUIRED: Replace ASample_Configuration with name of your Actor class
void ASample_Configuration::OnSubscriptionStatusChanged(EPubnubSubscriptionStatus Status, FPubnubSubscriptionStatusData StatusData)
{
	//Do something with changed status, for example print whenever there is connection error
	if(Status == EPubnubSubscriptionStatus::PSS_ConnectionError || Status == EPubnubSubscriptionStatus::PSS_DisconnectedUnexpectedly)
	{
		UE_LOG(LogTemp, Warning, TEXT("Something went wrong with subscription. Reason: %s"), *StatusData.Reason);
	}
}

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

	//Bind lambda delegate to the subscription status listener
	PubnubClient->OnSubscriptionStatusChangedNative.AddLambda([](EPubnubSubscriptionStatus Status, FPubnubSubscriptionStatusData StatusData)
	{
		//Do something with changed status, for example print whenever there is connection error
		if(Status == EPubnubSubscriptionStatus::PSS_ConnectionError || Status == EPubnubSubscriptionStatus::PSS_DisconnectedUnexpectedly)
		{
			UE_LOG(LogTemp, Warning, TEXT("Something went wrong with subscription. Reason: %s"), *StatusData.Reason);
		}
	});
}

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

	// Bind response delegate
	// ACTION REQUIRED: Replace ASample_Configuration with name of your Actor class
	FOnPubnubListUsersFromChannelResponse OnListUsersFromChannelResponse;
	OnListUsersFromChannelResponse.BindDynamic(this, &ASample_Configuration::OnListUsersFromChannelResponse);

	//List users from a channel
	FString Channel = TEXT("guild-channel");
	PubnubClient->ListUsersFromChannelAsync(Channel, OnListUsersFromChannelResponse);
}

// ACTION REQUIRED: Replace ASample_Configuration with name of your Actor class
void ASample_Configuration::OnListUsersFromChannelResponse(FPubnubOperationResult Result, FPubnubListUsersFromChannelWrapper Data)
{
	if(Result.Error)
	{
		UE_LOG(LogTemp, Error, TEXT("Failed to list users from channel. Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
	}
	else
	{
		UE_LOG(LogTemp, Log, TEXT("Users successfully listed from channel. Occupancy: %d"), Data.Occupancy);
	}
}

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

	// Bind lambda to response delegate
	FOnPubnubListUsersFromChannelResponseNative OnListUsersFromChannelResponse;
	OnListUsersFromChannelResponse.BindLambda([](const FPubnubOperationResult& Result, const FPubnubListUsersFromChannelWrapper& Data)
	{
		if(Result.Error)
		{
			UE_LOG(LogTemp, Error, TEXT("Failed to list users from channel. Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
		}
		else
		{
			UE_LOG(LogTemp, Log, TEXT("Users successfully listed from channel. Occupancy: %d"), Data.Occupancy);
		}
	});
	
	//List users from a channel
	FString Channel = TEXT("guild-channel");
	PubnubClient->ListUsersFromChannelAsync(Channel, OnListUsersFromChannelResponse);
}

// snippet.create_pubnub_client

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

// ACTION REQUIRED: Replace ASample_Configuration with name of your Actor class
void ASample_Configuration::CreatePubnubClient()
{
	//Get PubnubSubsystem from GameInstance
	UGameInstance* GameInstance = UGameplayStatics::GetGameInstance(this);
	UPubnubSubsystem* PubnubSubsystem = GameInstance->GetSubsystem<UPubnubSubsystem>();

	// Create Pubnub Client using Pubnub Subsystem
	FPubnubConfig PubnubConfig;
	PubnubConfig.PublishKey = TEXT("demo");   //replace with your Publish Key from Admin Portal
	PubnubConfig.SubscribeKey = TEXT("demo"); //replace with your Subscribe Key from Admin Portal
	PubnubConfig.UserID = TEXT("Player_001");
	UPubnubClient* PubnubClient = PubnubSubsystem->CreatePubnubClient(PubnubConfig);
	
	UE_LOG(LogTemp, Log, TEXT("Pubnub Client created with config"));
}

// snippet.get_pubnub_client

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

// ACTION REQUIRED: Replace ASample_Configuration with name of your Actor class
UPubnubClient* ASample_Configuration::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;
}

// snippet.destroy_pubnub_client

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

// ACTION REQUIRED: Replace ASample_Configuration with name of your Actor class
void ASample_Configuration::DestroyPubnubClient()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	UGameInstance* GameInstance = UGameplayStatics::GetGameInstance(this);
	UPubnubSubsystem* PubnubSubsystem = GameInstance->GetSubsystem<UPubnubSubsystem>();
	
	PubnubSubsystem->DestroyPubnubClient(PubnubClient);
}

// snippet.add_logger
// ACTION REQUIRED: Replace ASample_Configuration with name of your Actor class
void ASample_Configuration::AddLoggerSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show

	//Assumes PubnubClient is created and UserID is set

	//Create logger object and register it in PubnubClient
	UPubnubDefaultLogger* CustomLogger = NewObject<UPubnubDefaultLogger>(this);
	if (!CustomLogger)
	{
		UE_LOG(LogTemp, Error, TEXT("Failed to create custom logger."));
		return;
	}

	TScriptInterface<IPubnubLoggerInterface> LoggerInterface;
	LoggerInterface.SetObject(CustomLogger);
	LoggerInterface.SetInterface(Cast<IPubnubLoggerInterface>(CustomLogger));

	PubnubClient->AddLogger(LoggerInterface);
}

// snippet.set_log_level_runtime
// ACTION REQUIRED: Replace ASample_Configuration with name of your Actor class
void ASample_Configuration::SetLogLevelAtRuntimeSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show

	//Assumes PubnubClient is created and UserID is set

	//Get all registered loggers
	TArray<TScriptInterface<IPubnubLoggerInterface>> Loggers = PubnubClient->GetLoggers();
	if (!Loggers.IsEmpty())
	{
		//Set new log levels for the first logger
		IPubnubLoggerInterface::Execute_SetMinimumLogLevel(Loggers[0].GetObject(), EPubnubLogLevel::PLL_Debug);
		IPubnubLoggerInterface::Execute_SetMinimumCCoreLogLevel(Loggers[0].GetObject(), EPubnubLogLevel::PLL_Warning);
	}
}

// snippet.set_log_level_configuration
// ACTION REQUIRED: Replace ASample_Configuration with name of your Actor class
void ASample_Configuration::SetLogLevelInConfigurationSample()
{
	//Get PubnubSubsystem from GameInstance
	UGameInstance* GameInstance = UGameplayStatics::GetGameInstance(this);
	UPubnubSubsystem* PubnubSubsystem = GameInstance->GetSubsystem<UPubnubSubsystem>();

	//Set logger levels directly in client configuration before creating PubnubClient
	FPubnubConfig PubnubConfig;
	PubnubConfig.PublishKey = TEXT("demo");   //replace with your Publish Key from Admin Portal
	PubnubConfig.SubscribeKey = TEXT("demo"); //replace with your Subscribe Key from Admin Portal
	PubnubConfig.UserID = TEXT("Player_001");
	PubnubConfig.LoggerConfig.DefaultLoggerMinLevel = EPubnubLogLevel::PLL_Debug;
	PubnubConfig.LoggerConfig.DefaultLoggerMinCCoreLevel = EPubnubLogLevel::PLL_Warning;

	UPubnubClient* PubnubClient = PubnubSubsystem->CreatePubnubClient(PubnubConfig);

	//Use PubnubClient as needed
	PubnubClient->PublishMessageAsync(TEXT("test-channel"), TEXT("Hello, world!"));
}

// snippet.get_loggers
// ACTION REQUIRED: Replace ASample_Configuration with name of your Actor class
void ASample_Configuration::GetLoggersSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show

	//Assumes PubnubClient is created and UserID is set

	TArray<TScriptInterface<IPubnubLoggerInterface>> Loggers = PubnubClient->GetLoggers();
}

// snippet.remove_logger
// ACTION REQUIRED: Replace ASample_Configuration with name of your Actor class
void ASample_Configuration::RemoveLoggerSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show

	//Assumes PubnubClient is created and UserID is set

	TArray<TScriptInterface<IPubnubLoggerInterface>> Loggers = PubnubClient->GetLoggers();

	//Remove the first registered logger
	PubnubClient->RemoveLogger(Loggers[0]);
}

// snippet.clear_loggers
// ACTION REQUIRED: Replace ASample_Configuration with name of your Actor class
void ASample_Configuration::ClearLoggersSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show

	//Assumes PubnubClient is created and UserID is set

	//Clear all registered loggers
	PubnubClient->ClearLoggers();
}

// snippet.end
```

#### Returns

This method returns the subscription status and will emit various statuses depending on your client network connection.

For more information on connection management, refer to [SDK Connection Lifecycle](https://www.pubnub.com/docs/general/setup/connection-management#sdk-connection-lifecycle).

#### Other examples

##### Add connection status listener with lambda

```cpp
// Add subscription status listener with lambda
PubnubSubsystem->OnSubscriptionStatusChangedNative.AddLambda([](EPubnubSubscriptionStatus Status) {
    UE_LOG(LogTemp, Log, TEXT("Subscription status changed: %d"), (int32)Status);
});
```

## Unsubscribe

Stop receiving real-time updates from a [Subscription](#create-a-subscription) or a [SubscriptionSet](#create-a-subscription-set).

### Method(s)

```cpp
// Unsubscribe from a subscription
Subscription->Unsubscribe();

// Unsubscribe from a subscription set
SubscriptionSet->Unsubscribe();
```

### Sample code

#### Unsubscribe from a subscription

```cpp
// Unsubscribe from a subscription
Subscription->Unsubscribe();
```

#### Unsubscribe from a subscription set

```cpp
// Unsubscribe from all entities in the set
SubscriptionSet->Unsubscribe();
```

### Returns

None

## Unsubscribe all

Stop receiving real-time updates from all listeners and remove the entities associated with them.

:::warning Client scope
This method is only available on the `UPubnubClient` object.
:::

### Method(s)

```cpp
PubnubClient->UnsubscribeFromAllAsync(FOnPubnubSubscribeOperationResponse OnUnsubscribeFromAllResponse);
```

| Parameter | Description |
| --- | --- |
| `OnUnsubscribeFromAllResponse`Type: [FOnPubnubSubscribeOperationResponse](#fonpubnubsubscribeoperationresponse) | The delegate for the operation's result. You can also use a native callback of the type [FOnPubnubSubscribeOperationResponseNative](#fonpubnubsubscribeoperationresponsenative) 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.uvhdnh8k
UFUNCTION(BlueprintCallable, Category = "Pubnub|Samples|PubSub")
void UnsubscribeFromAllSample();
	
```

#### Actor.cpp

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

	//Unsubscribe from all - stop receiving any messages from all channels and groups
	PubnubClient->UnsubscribeFromAllAsync();
}
```

###### Blueprint

### Returns

This method is void. The delegate returns the following struct:

#### FOnPubnubSubscribeOperationResponse

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

#### FOnPubnubSubscribeOperationResponseNative

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

## Subscribe (old)

:::warning Deprecated
Use `PubnubClient->SubscribeToChannel()` / `PubnubClient->SubscribeToGroup()` or the entity-based [Subscribe](#subscribe) approach instead.
:::

#### Receive messages

Your app receives messages and events via event listeners. The [OnMessageReceived](https://www.pubnub.com/docs/sdks/unreal/api-reference/configuration#event-listeners) event listener is a single point through which your app receives all the messages, signals, and events that are sent in any channel you are subscribed to.

For more information about adding a listener, refer to the [Event Listeners](https://www.pubnub.com/docs/sdks/unreal/api-reference/configuration#event-listeners) section.

#### Description

This function causes the client to create an open TCP socket to the PubNub Real-Time Network and begin listening for messages on a specified `channel` ID. To subscribe to a `channel` ID, the client must send the appropriate `SubscribeKey` at [initialization](https://www.pubnub.com/docs/sdks/unreal/api-reference/configuration#configuration-and-initialization).

By default, a newly subscribed client will only receive messages published to the channel after the `Subscribe()` call completes.

:::warning Unsubscribing from all channels
**Unsubscribing** from all channels, and then **subscribing** to a new channel Y is not the same as subscribing to channel Y and then unsubscribing from the previously-subscribed channel(s). Unsubscribing from all channels resets the last-received `timetoken` and thus, there could be some gaps in the subscription that may lead to message loss.
:::

#### Method(s)

```cpp
// subscribe to a channel
PubnubSubsystem->SubscribeToChannel(FString Channel, FOnSubscribeOperationResponse OnSubscribeToChannelResponse, FPubnubSubscribeSettings SubscribeSettings = FPubnubSubscribeSettings());
// subscribe to a channel group
PubnubSubsystem->SubscribeToGroup(FString ChannelGroup, FOnSubscribeOperationResponse OnSubscribeToGroupResponse, FPubnubSubscribeSettings SubscribeSettings = FPubnubSubscribeSettings());
```

| Parameter | Description |
| --- | --- |
| `Channel` *Type: `FString` | The channel ID to subscribe to. |
| `ChannelGroup` *Type: `FString` | The channel group to subscribe to. |
| `OnSubscribeToChannelResponse`Type: [FOnSubscribeOperationResponse](#fonsubscribeoperationresponse) | The delegate for the operation's result. You can also use a native callback of the type [FOnSubscribeOperationResponseNative](#fonsubscribeoperationresponsenative) to handle the result using a lambda. |
| `OnSubscribeToGroupResponse`Type: [FOnSubscribeOperationResponse](#fonsubscribeoperationresponse) | The delegate for the operation's result. You can also use a native callback of the type [FOnSubscribeOperationResponseNative](#fonsubscribeoperationresponsenative) to handle the result using a lambda. |
| `SubscriptionSettings`Type: [FPubnubSubscribeSettings](#fpubnubsubscribesettings) | Struct defining subscription configuration. |

###### FOnSubscribeOperationResponse

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

###### FOnSubscribeOperationResponseNative

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

#### 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.3fpbztx1
UFUNCTION(BlueprintCallable, Category = "Pubnub|Samples|PubSub")
void SubscribeSample();

UFUNCTION()
void OnMessageReceived_SubscribeSample(FPubnubMessageData Message);
	
```

###### Actor.cpp

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

	//Add Listener/Delegate that will broadcast whenever message is received on any subscribed channel or group
	// ACTION REQUIRED: Replace ASample_PubSub with name of your Actor class
	PubnubClient->OnMessageReceived.AddDynamic(this, &ASample_PubSub::OnMessageReceived_SubscribeSample);

	//Subscribe to the Channel
	FString Channel = TEXT("guild_chat");
	PubnubClient->SubscribeToChannelAsync(Channel);
}

// ACTION REQUIRED: Replace ASample_PubSub with name of your Actor class
void ASample_PubSub::OnMessageReceived_SubscribeSample(FPubnubMessageData Message)
{
	UE_LOG(LogTemp, Log, TEXT("Message received on Channel: %s, Message Content: %s"), *Message.Channel, *Message.Message);
}
```

:::note Event listeners
The response of the call is handled by adding a listener. Refer to the [Event Listeners](https://www.pubnub.com/docs/sdks/unreal/api-reference/configuration#event-listeners) section for more details. Listeners should be added before calling the method.
:::

###### Blueprint

#### Returns

This method doesn't have a return value. To receive messages, you must [add a listener](https://www.pubnub.com/docs/sdks/unreal/api-reference/configuration#add-listeners).

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

##### Subscribe with presence

:::warning Requires Presence
This method requires that the Presence add-on is [enabled](https://support.pubnub.com/hc/en-us/articles/360051974791-How-do-I-enable-add-on-features-for-my-keys-) for your key in the [Admin Portal](https://admin.pubnub.com/). For information on how to receive presence events and what those events are, refer to [Presence Events](https://www.pubnub.com/docs/general/presence/presence-events#subscribe-to-presence-channel).
:::

For any given channel there is an associated Presence channel. You can subscribe directly to the channel by appending `-pnpres` to the channel name or you can use the subscribe method with the `ReceivePresenceEvents` parameter set to `true`. For more information on presence events, refer to the [Presence](https://www.pubnub.com/docs/general/presence/presence-events) section.

###### C++

###### Actor.h

```cpp
#include "PubnubClient.h"

// blueprint.v7n6lycr
UFUNCTION(BlueprintCallable, Category = "Pubnub|Samples|PubSub")
void SubscribeWithPresenceSample();

UFUNCTION()
void OnMessageReceived_SubscribeWithPresenceSample(FPubnubMessageData Message);
```

###### Actor.cpp

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

	//Add Listener/Delegate that will broadcast whenever message is received on any subscribed channel or group
	// ACTION REQUIRED: Replace ASample_PubSub with name of your Actor class
	PubnubClient->OnMessageReceived.AddDynamic(this, &ASample_PubSub::OnMessageReceived_SubscribeWithPresenceSample);

	//Create additional subscribe settings
	FPubnubSubscribeSettings SubscribeSettings;
	SubscribeSettings.ReceivePresenceEvents = true;
	
	//Subscribe to the Channel
	FString Channel = TEXT("guild_chat");
	PubnubClient->SubscribeToChannelAsync(Channel, SubscribeSettings);
}

// ACTION REQUIRED: Replace ASample_PubSub with name of your Actor class
void ASample_PubSub::OnMessageReceived_SubscribeWithPresenceSample(FPubnubMessageData Message)
{
	//Presence events are received on "{channel}-pnpres" channel
	if(Message.Channel.Contains("-pnpres"))
	{
		UE_LOG(LogTemp, Log, TEXT("Event received on Channel: %s, Event Content: %s"), *Message.Channel, *Message.Message);
	}
	else
	{
		UE_LOG(LogTemp, Log, TEXT("Message received on Channel: %s, Message Content: %s"), *Message.Channel, *Message.Message);
	}
}
```

###### Blueprint

:::tip Response
All presence events are received via a [listener](https://www.pubnub.com/docs/sdks/unreal/api-reference/configuration#event-listeners). For more information on the structure of the received events, refer to [Event types](https://www.pubnub.com/docs/sdks/unreal/api-reference/configuration#presence).
:::

##### Subscribe to channel group

###### C++

###### Actor.h

```cpp
#include "PubnubClient.h"

// blueprint.vny2_wkg
UFUNCTION(BlueprintCallable, Category = "Pubnub|Samples|PubSub")
void SubscribeToGroupSample();

UFUNCTION()
void OnMessageReceived_SubscribeToGroupSample(FPubnubMessageData Message);
```

###### Actor.cpp

```cpp
// ACTION REQUIRED: Replace ASample_PubSub with name of your Actor class
void ASample_PubSub::SubscribeToGroupSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set
	
	//Add Listener/Delegate that will broadcast whenever message is received on any subscribed channel or group
	// ACTION REQUIRED: Replace ASample_PubSub with name of your Actor class
	PubnubClient->OnMessageReceived.AddDynamic(this, &ASample_PubSub::OnMessageReceived_SubscribeToGroupSample);

	//Subscribe to the Channel
	FString Group = TEXT("my_group_chats");
	PubnubClient->SubscribeToGroupAsync(Group);
}

// ACTION REQUIRED: Replace ASample_PubSub with name of your Actor class
void ASample_PubSub::OnMessageReceived_SubscribeToGroupSample(FPubnubMessageData Message)
{
	UE_LOG(LogTemp, Log, TEXT("Message received on Channel: %s, Message Content: %s"), *Message.Channel, *Message.Message);
}
```

###### Blueprint

##### Subscribe with lambda

###### Actor.h

```cpp
#include "PubnubClient.h"

UFUNCTION(BlueprintCallable, Category = "Pubnub|Samples|PubSub")
void SubscribeWithLambdaSample();
```

###### Actor.cpp

```cpp
// ACTION REQUIRED: Replace ASample_PubSub with name of your Actor class
void ASample_PubSub::SubscribeWithLambdaSample()
{
	// snippet.hide
	UPubnubClient* PubnubClient = GetPubnubClient();
	// snippet.show
	
	//Assumes PubnubClient is created and UserID is set
	
	//Add Lambda Listener/Delegate that will broadcast whenever message is received on any subscribed channel or group
	PubnubClient->OnMessageReceivedNative.AddLambda([](const FPubnubMessageData& Message)
	{
		UE_LOG(LogTemp, Log, TEXT("Message received on Channel: %s, Message Content: %s"), *Message.Channel, *Message.Message);
	});

	//Subscribe to the Channel
	FString Channel = TEXT("guild_chat");
	PubnubClient->SubscribeToChannelAsync(Channel);
}
```

##### Subscribe with result callback

###### C++

###### Actor.h

```cpp
#include "PubnubClient.h"

// blueprint.pargt46o
UFUNCTION(BlueprintCallable, Category = "Pubnub|Samples|PubSub")
void SubscribeWithResultSample();

UFUNCTION()
void OnMessageReceived_SubscribeWithResultSample(FPubnubMessageData Message);

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

###### Actor.cpp

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

	//Add Listener/Delegate that will broadcast whenever message is received on any subscribed channel or group
	// ACTION REQUIRED: Replace ASample_PubSub with name of your Actor class
	PubnubClient->OnMessageReceived.AddDynamic(this, &ASample_PubSub::OnMessageReceived_SubscribeWithResultSample);

	//Add Listener/Delegate that will be called when subscribe operation is established with it's result
	//Note:: this is not listener for messages incoming to the subscribed channel
	// ACTION REQUIRED: Replace ASample_PubSub with name of your Actor class
	FOnPubnubSubscribeOperationResponse OnSubscribeOperationResponse;
	OnSubscribeOperationResponse.BindDynamic(this, &ASample_PubSub::OnSubscribeResultReceived);
	
	//Subscribe to the Channel
	FString Channel = TEXT("guild_chat");
	PubnubClient->SubscribeToChannelAsync(Channel, OnSubscribeOperationResponse);
}

// ACTION REQUIRED: Replace ASample_PubSub with name of your Actor class
void ASample_PubSub::OnMessageReceived_SubscribeWithResultSample(FPubnubMessageData Message)
{
	UE_LOG(LogTemp, Log, TEXT("Message received on Channel: %s, Message Content: %s"), *Message.Channel, *Message.Message);
}

// ACTION REQUIRED: Replace ASample_PubSub with name of your Actor class
void ASample_PubSub::OnSubscribeResultReceived(FPubnubOperationResult Result)
{
	if(Result.Error)
	{
		UE_LOG(LogTemp, Error, TEXT("Failed to subscribe to channel. Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
	}
	else
	{
		UE_LOG(LogTemp, Log, TEXT("Subscribed to channel successfully."));
	}
}
```

###### Blueprint

## Unsubscribe (old)

:::warning Not recommended
The following approach to unsubscribing is not recommended. We recommend using the entity-based [Unsubscribe](#unsubscribe) approach.
:::

When subscribed to a single channel, this function causes the client to issue a `leave` from the `channel` ID and close any open socket to the PubNub Network. For multiplexed channels, the specified `channel`(s) will be removed and the socket remains open until there are no more channels remaining in the list.

:::warning Unsubscribing from all channels
**Unsubscribing** from all channels, and then **subscribing** to a new channel Y is not the same as subscribing to channel Y and then unsubscribing from the previously-subscribed channel(s). Unsubscribing from all channels resets the last-received `timetoken` and thus, there could be some gaps in the subscription that may lead to message loss.
:::

#### Method(s)

```cpp
// unsubscribe from a channel
PubnubSubsystem->UnsubscribeFromChannel(FString Channel, FOnSubscribeOperationResponse OnUnsubscribeFromChannelResponse);
// unsubscribe from a channel group
PubnubSubsystem->UnsubscribeFromGroup(FString ChannelGroup, FOnSubscribeOperationResponse OnUnsubscribeFromGroupResponse);
```

| Parameter | Description |
| --- | --- |
| `Channel` *Type: `FString` | The channel ID to unsubscribe from. |
| `ChannelGroup` *Type: `FString` | The channel group to unsubscribe from. |
| `OnUnsubscribeFromChannelResponse`Type: [FOnSubscribeOperationResponse](#fonsubscribeoperationresponse) | The delegate for the operation's result. You can also use a native callback of the type [FOnSubscribeOperationResponseNative](#fonsubscribeoperationresponsenative) to handle the result using a lambda. |
| `OnUnsubscribeFromGroupResponse`Type: [FOnSubscribeOperationResponse](#fonsubscribeoperationresponse) | The delegate for the operation's result. You can also use a native callback of the type [FOnSubscribeOperationResponseNative](#fonsubscribeoperationresponsenative) 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.9yloz2xg
UFUNCTION(BlueprintCallable, Category = "Pubnub|Samples|PubSub")
void UnsubscribeFromChannelSample();
	
```

##### Actor.cpp

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

	//Unsubscribe from the Channel - stop listening for messages on that channel
	FString Channel = TEXT("guild_chat");
	PubnubClient->UnsubscribeFromChannelAsync(Channel);
}
```

###### Blueprint

#### Returns

This method doesn't have a return value.

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

##### Unsubscribe from a channel group

###### C++

###### Actor.h

```cpp
#include "PubnubClient.h"

// blueprint.r1ijf67z
UFUNCTION(BlueprintCallable, Category = "Pubnub|Samples|PubSub")
void UnsubscribeFromGroupSample();
```

##### Actor.cpp

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

	//Unsubscribe from the Group - stop listening for messages on all channels that belong to that group
	FString Group = TEXT("my_group_chats");
	PubnubClient->UnsubscribeFromGroupAsync(Group);
}
```

###### Blueprint

## Unsubscribe all (old)

:::warning Not recommended
The following approach to unsubscribing from all channels is not recommended. We recommend using the entity-based [Unsubscribe](#unsubscribe) approach.
:::

Unsubscribe from all channels and all channel groups.

#### Method(s)

```cpp
PubnubSubsystem->UnsubscribeFromAll(FOnSubscribeOperationResponse OnUnsubscribeFromAllResponse);
```

| Parameter | Description |
| --- | --- |
| `OnUnsubscribeFromAllResponse`Type: [FOnSubscribeOperationResponse](#fonsubscribeoperationresponse) | The delegate for the operation's result. You can also use a native callback of the type [FOnSubscribeOperationResponseNative](#fonsubscribeoperationresponsenative) 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.uvhdnh8k
UFUNCTION(BlueprintCallable, Category = "Pubnub|Samples|PubSub")
void UnsubscribeFromAllSample();
	
```

###### Actor.cpp

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

	//Unsubscribe from all - stop receiving any messages from all channels and groups
	PubnubClient->UnsubscribeFromAllAsync();
}
```

###### Blueprint

#### Returns

This method doesn't have a return value.

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

###### C++

#### ASample_PubSubFull.h

```cpp
// blueprint.7s012a54
#pragma once

#include "GameFramework/Actor.h"
#include "CoreMinimal.h"
#include "Sample_PubSubFull.generated.h"

// ACTION REQUIRED: Replace PUBNUBLIBRARYTESTS_API with your project's module API macro (usually ProjectName_API)
UCLASS()
class PUBNUBLIBRARYTESTS_API ASample_PubSubFull : public AActor
{
	GENERATED_BODY()

protected:
	virtual void BeginPlay() override;

public:

	UFUNCTION(BlueprintCallable, Category = "Pubnub|FullExamples|PubSub")
	void RunPubSubFullExample();

	UFUNCTION()
	void OnPubnubMessageReceived(FPubnubMessageData Message);

	UFUNCTION()
	void OnPublishResult(FPubnubOperationResult Result, FPubnubMessageData Message);
};
```

#### ASample_PubSubFull.cpp

```cpp
#include "Samples/Sample_PubSubFull.h"
#include "Kismet/GameplayStatics.h"
#include "Engine/GameInstance.h"
#include "PubnubClient.h"

void ASample_PubSubFull::BeginPlay()
{
	Super::BeginPlay();

	//Run the example on BeginPlay
	RunPubSubFullExample();
}

void ASample_PubSubFull::RunPubSubFullExample()
{
	//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.SecretKey = TEXT("demo");    //replace with your Subscribe Key from Admin Portal
	Config.UserID = TEXT("Player_001");
	UPubnubClient* PubnubClient = PubnubSubsystem->CreatePubnubClient(Config);

	UE_LOG(LogTemp, Log, TEXT("PubSub example, Pubnub Client is created"));

	//Add Listener/Delegate that will broadcast whenever message is received on any subscribed channel or group
	PubnubClient->OnMessageReceived.AddDynamic(this, &ASample_PubSubFull::OnPubnubMessageReceived);

	//Subscribe to the Channel
	FString Channel = TEXT("guild_chat");
	PubnubClient->SubscribeToChannelAsync(Channel);

	// NOTE: Subscribing to a group or channel may take a few seconds to complete.
	// This sleep is used to simulate the waiting period in an actual application.
	FPlatformProcess::Sleep(3);
	
	UE_LOG(LogTemp, Log, TEXT("PubSub example, subscribed to channel: %s"), *Channel);
		
	//Bind delegate to the publish result
	FOnPubnubPublishMessageResponse OnPublishMessageResponse;
	OnPublishMessageResponse.BindDynamic(this, &ASample_PubSubFull::OnPublishResult);
	
	//Publish message to the subscribed channel
	FString Message = R"({"event": "PowerUpUsed", "powerup": "Invisibility Cloak", "duration": 10})";
	PubnubClient->PublishMessageAsync(Channel, Message, OnPublishMessageResponse);

	// NOTE: Give some time to receive message before unsubscribing
	// This sleep is used only to simulate the waiting period in an actual application.
	FPlatformProcess::Sleep(3);
	
	//Unsubscribe from previously subscribed channel
	PubnubClient->UnsubscribeFromChannelAsync(Channel);

	UE_LOG(LogTemp, Log, TEXT("PubSub example, message published"));
}

void ASample_PubSubFull::OnPubnubMessageReceived(FPubnubMessageData Message)
{
	UE_LOG(LogTemp, Log, TEXT("PubSub example, message received on Channel: %s, Message Content: %s"), *Message.Channel, *Message.Message);
}

void ASample_PubSubFull::OnPublishResult(FPubnubOperationResult Result, FPubnubMessageData Message)
{
	if(Result.Error)
	{
		UE_LOG(LogTemp, Error, TEXT("PubSub example, failed to publish message. Status: %d, Reason: %s"), Result.Status, *Result.ErrorMessage);
	}
	else
	{
		UE_LOG(LogTemp, Log, TEXT("PubSub example, message published successfully. Published message timetoken: %s"), *Message.Timetoken);
	}
}
```

###### Blueprint

## Deprecated methods

### Publish message (deprecated)

:::warning Deprecated
This method is deprecated and will be removed in a future version. Use `PubnubClient->PublishMessage()` or `PubnubClient->PublishMessageAsync()` instead.
:::

```cpp
PubnubSubsystem->PublishMessage(
    FString Channel,
    FString Message,
    FOnPublishMessageResponse OnPublishMessageResponse,
    FPubnubPublishSettings PublishSettings = FPubnubPublishSettings()
);
```

| Parameter | Description |
| --- | --- |
| `Channel` *Type: `FString` | The channel ID to send the message to. |
| `Message` *Type: `FString` | The message to publish. Can be a literal string or JSON-formatted string containing serialized data. |
| `OnPublishMessageResponse`Type: `FOnPublishMessageResponse` | The delegate for the operation's result. |
| `PublishSettings`Type: `FPubnubPublishSettings` | Struct defining publish configuration. |

### Signal (deprecated)

:::warning Deprecated
This method is deprecated and will be removed in a future version. Use `PubnubClient->Signal()` or `PubnubClient->SignalAsync()` instead.
:::

```cpp
PubnubSubsystem->Signal(
    FString Channel,
    FString Message,
    FOnSignalResponse OnSignalResponse,
    FPubnubSignalSettings SignalSettings = FPubnubSignalSettings()
);
```

| Parameter | Description |
| --- | --- |
| `Channel` *Type: `FString` | The channel ID to send the signal to. |
| `Message` *Type: `FString` | The message to publish. Can be a literal string or JSON-formatted string containing serialized data. |
| `OnSignalResponse`Type: `FOnSignalResponse` | The delegate for the operation's result. |
| `SignalSettings`Type: `FPubnubSignalSettings` | Struct defining signal configuration. |

### Unsubscribe from all (deprecated)

:::warning Deprecated
This method is deprecated and will be removed in a future version. Use `PubnubClient->UnsubscribeFromAll()` or `PubnubClient->UnsubscribeFromAllAsync()` instead.
:::

```cpp
PubnubSubsystem->UnsubscribeFromAll(FOnSubscribeOperationResponse OnUnsubscribeFromAllResponse);
```

| Parameter | Description |
| --- | --- |
| `OnUnsubscribeFromAllResponse`Type: `FOnSubscribeOperationResponse` | The delegate for the operation's result. |

## Terms in this document

* **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.
* **Entity** - A subscribable object within a PubNub SDK that allows you to perform context-specific operations.
* **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.