---
source_url: https://www.pubnub.com/docs/chat/unreal-chat-sdk/build/features/custom-events
title: Create custom events
updated_at: 2026-06-12T11:23:23.197Z
---

> 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


# Create custom events

Learn how Unreal Chat SDK handles events before working with [custom chat events](#custom-events).

## Event handling

### PubNub events

With a standard PubNub SDK like the [Unreal SDK](https://www.pubnub.com/docs/sdks/unreal), building a chat app requires [additional steps](https://www.pubnub.com/docs/general/basics/receive-messages):

* Subscribe to channels to receive messages
* Add event listeners to handle messages, signals, and events

Unreal Chat SDK handles this automatically. All listener methods return a function to stop receiving events and unsubscribe from the channel.

| Entity | Method | Events handled |
| --- | --- | --- |
| `Channel` | [StreamUpdates() or StreamUpdatesOn()](https://www.pubnub.com/docs/chat/unreal-chat-sdk/build/features/channels/updates#get-channel-updates) | (Un)Subscribe the current user to/from a channel and start/stop getting all `objects` events of type `channel`. |
| `User` | [StreamUpdates() or StreamUpdatesOn()](https://www.pubnub.com/docs/chat/unreal-chat-sdk/build/features/users/updates#get-user-updates) | (Un)Subscribe the current user to/from a channel and start/stop getting all `objects` events of type `uuid`. |
| `Message` | [StreamUpdates() or StreamUpdatesOn()](https://www.pubnub.com/docs/chat/unreal-chat-sdk/build/features/messages/updates#get-message-updates) | (Un)Subscribe the current user to/from a channel and start/stop getting all `messageAction` events (for message and message actions changes) of type `added` or `removed`. |
| `Membership` | [StreamUpdates() or StreamUpdatesOn()](https://www.pubnub.com/docs/chat/unreal-chat-sdk/build/features/channels/membership#get-updates) | (Un)Subscribe the current user to/from a channel and start/stop getting all `objects` events of type `membership`. |
| `Channel` | [Connect()](https://www.pubnub.com/docs/chat/unreal-chat-sdk/build/features/channels/watch) | (Un)Subscribe the current user to/from a channel and start/stop getting all `message` events of type `text`. |
| `Channel` | [StreamTyping() and StopStreamingTyping()](https://www.pubnub.com/docs/chat/unreal-chat-sdk/build/features/channels/typing-indicator#stream-typing-events) | (Un)Subscribe the current user to/from a channel and start/stop getting all `signal` events of type `typing`. |
| `Channel` | [StreamPresence()](https://www.pubnub.com/docs/chat/unreal-chat-sdk/build/features/users/presence#get-presence-updates) | (Un)Subscribe the current user to/from a channel and start/stop getting all `presence` events of type `action` (responsible for monitoring when users join, leave the channels, or when their channel connection times out and they get disconnected). |

Unreal Chat SDK wraps server responses into entities like `Channel`, `Message`, and `User` with methods and properties for building your app's UI.

### Chat events

Events are separate [entities](https://www.pubnub.com/docs/chat/unreal-chat-sdk/learn/chat-entities/event) that carry data payloads and can trigger business logic (for example, the Typing Indicator starts or stops based on typing events).

Unreal Chat SDK automatically emits these event types when a user:

* Reports a message (`report` event type for [messages](#events-for-reported-messages))
* Starts/Stops typing a message on a channel ([typing](#events-for-typing-indicator) event type)
* Mentions someone else in the message ([mention](#events-for-mentions) event type)
* Reads a message published on a channel ([receipt](#events-for-read-receipts) event type)
* Invites another user to join a channel ([invite](#events-for-channel-initations) event type)
* Mutes a user, bans them, or removes these restrictions ([moderation](#events-for-user-moderation) event type)

All event types use the PubNub Pub/Sub API with `Publish()` or `Signal()` methods.

Retrieve historical events with:

* `GetEventsHistory()` - for historical events emitted via `Publish()`

:::note History retrieval
`GetEventsHistory()` cannot filter by event type. It returns all events emitted via `Publish()` on the channel within the specified timeframe.
:::

Each event type has a fixed payload structure documented below.

#### Events for reported messages

* **Type:** `report`
* **PubNub method:** PubNub method used to send events you listen for. `Publish()` (with history) is used for all events related to message reporting.
* **Target:** [PUBNUB_INTERNAL_ADMIN_CHANNEL](https://www.pubnub.com/docs/chat/unreal-chat-sdk/build/features/messages/moderation)
* **Trigger:** [Report()](https://www.pubnub.com/docs/chat/unreal-chat-sdk/build/features/messages/moderation#flagreport-messages) method on the `Message` object
* **Listener:** `GetEventsHistory()` (historical) on the `Chat` object
* **Sample use case:** [Message moderation](https://www.pubnub.com/docs/chat/unreal-chat-sdk/build/features/messages/moderation#listen-to-report-events). You might want to create a UI for an operational dashboard to monitor and manage all reported messages.
* **Payload:**

```cpp
payload: {
    // content of the flagged message
    text: string;
    // reason for flagging the message
    reason: string;
    // channel where message was flagged
    reportedMessageChannelId: string;
    // timetoken of the flagged message
    reportedMessageTimetoken: string;
    // author of the flagged message
    reportedUserId: string;
}
```

#### Events for typing indicator

* **Type:** `typing`
* **PubNub method:** PubNub method used to send events you listen for. `Signal()` (without history) is used for all events related to typing.
* **Target:** The same channel where messages are published.
* **Trigger:** [StartTyping() and StopTyping()](https://www.pubnub.com/docs/chat/unreal-chat-sdk/build/features/channels/typing-indicator) methods on the `Channel` object
* **Listener:** `StreamTyping()` on the `Channel` object
* **Sample use case:** [Typing indicator](https://www.pubnub.com/docs/chat/unreal-chat-sdk/build/features/channels/typing-indicator#get-typing-events). You might want to show graphically on the channel that another channel member is typing or has stopped typing a message.
* **Payload:**

```cpp
payload: {
    // value showing whether someone is typing or not
    value: boolean;
}
```

#### Events for mentions

* **Type:** `mention`
* **PubNub method:** PubNub method used to send events you listen for. `Publish()` (with history) is used for all events related to mentions.
* **Target:** Unlike in other event types, a target for mention events is equal to a user ID. This ID is treated as a user-specific channel and is used to send system notifications about changes concerning a [User object](https://www.pubnub.com/docs/chat/unreal-chat-sdk/learn/chat-entities/user), such as creating, updating, or deleting that user. The channel name is equal to the ID (`id`) of the user and you can retrieve it by calling the `currentUser` method on the `Chat` object.
* **Trigger:** [SendText()](https://www.pubnub.com/docs/chat/unreal-chat-sdk/build/features/messages/send-receive) method on the `Channel` object
* **Listener:** `GetEventsHistory()` (historical) on the `Chat` object, or the `OnMentioned` delegate on the `User` object
* **Sample use case:** [User mentions](https://www.pubnub.com/docs/chat/unreal-chat-sdk/build/features/users/mentions#show-notifications-for-mentions). You might want to receive notifications for all events emitted when you are mentioned in a parent or thread channel.
* **Payload:**

```cpp
payload: {
    // timetoken of the message where someone is mentioned
    messageTimetoken: string;
    // channel on which the message with mention was sent
    channel: string;
}
```

#### Events for read receipts

* **Type:** `receipt`
* **PubNub method:** PubNub method used to send events you listen for. `Signal()` (with history persisted as the last read message on the `Membership` object) is used for all events related to message read receipts.
* **Target:** The same channel where messages are published.
* **Trigger:** [MarkAllMessagesAsRead()](https://www.pubnub.com/docs/chat/unreal-chat-sdk/build/features/messages/unread#mark-messages-as-read-all-channels) method on the `Chat` object, the [SetLastReadMessageTimetoken()](https://www.pubnub.com/docs/chat/unreal-chat-sdk/build/features/messages/unread#mark-messages-as-read-one-channel) method on the `Membership` object, and the [SetLastReadMessage()](https://www.pubnub.com/docs/chat/unreal-chat-sdk/build/features/messages/unread#mark-messages-as-read-one-channel) method on the `Membership` object
* **Listener:** [StreamReadReceipts()](https://www.pubnub.com/docs/chat/unreal-chat-sdk/build/features/messages/read-receipts#get-read-receipts) (current) on the `Channel` object
* **Sample use case:** [Read receipts](https://www.pubnub.com/docs/chat/unreal-chat-sdk/build/features/messages/read-receipts). You might want to indicate on a channel - through avatars or some other indicator - that a message was read by another user/other users.
* **Payload:**

```cpp
payload: {
    // timetoken of the read message
    messageTimetoken: string;
}
```

#### Events for channel initations

* **Type:** `invite`
* **PubNub method:** PubNub method used to send events you listen for. `Publish()` (with history) is used for all events related to channel invitations.
* **Target:** The same channel where messages are published.
* **Trigger:** [Invite()](https://www.pubnub.com/docs/chat/unreal-chat-sdk/build/features/channels/invite#invite-one-user) and [InviteMultiple()](https://www.pubnub.com/docs/chat/unreal-chat-sdk/build/features/channels/invite#invite-multiple-users) methods on the `Channel` object
* **Listener:** `GetEventsHistory()` (historical) on the `Chat` object, or the `OnInvited` delegate on the `User` object
* **Sample use case:** [Channel invitations](https://www.pubnub.com/docs/chat/unreal-chat-sdk/build/features/channels/invite). You might want to notify users that they were invited to join a channel.
* **Payload:** Delivered as `FPubnubChatInviteEvent`:

| Field | Type | Description |
| --- | --- | --- |
| `Timetoken` | `FString` | Timetoken of the invite event. |
| `ChannelID` | `FString` | ID of the channel to which the user was invited. |
| `ChannelType` | `FString` | Type of channel (e.g., `direct`, `group`). |
| `InvitedByUserID` | `FString` | User ID of the person who sent the invitation. |

#### Events for user moderation

* **Type:** `moderation`
* **PubNub method:** PubNub method used to send events you listen for. `Publish()` (with history) is used for all events related to user restrictions.
* **Target:** An event is sent to the ID of the moderated user (user channel with the name same as the user ID) preceded by the `PUBNUB_INTERNAL_MODERATION.` prefix, like `PUBNUB_INTERNAL_MODERATION.[UserId]`.
* **Trigger:** [SetRestrictions()](https://www.pubnub.com/docs/chat/unreal-chat-sdk/build/features/users/moderation#mute-or-ban-users) methods on the `Channel`, `Chat`, and `User` objects
* **Listener:** `GetEventsHistory()` (historical) on the `Chat` object, or the `OnRestrictionChanged` delegate on the `User` object
* **Sample use case:** [User moderation](https://www.pubnub.com/docs/chat/unreal-chat-sdk/build/features/users/moderation#mute-or-ban-users). You might want to notify users when they were muted, banned, or when you remove these restrictions from them.
* **Payload:**

```cpp
payload: {
  // ID of the channel on which the user's moderation restrictions were set or lifted
  channelId: `PUBNUB_INTERNAL_MODERATION.String`
  // ID of the channel on which the user's moderation restrictions were set or lifted preceded by the PUBNUB_INTERNAL_MODERATION. prefix",
  restriction: "muted" | "banned" | "lifted"
  // reason for muting or banning the user
  reason?: string
}
```

## Custom events

The `custom` event type carries custom payloads for additional business logic. Methods:

* `GetEventsHistory()` - retrieve historical events
* `StreamCustomEvents()` - listen for real-time custom events on a `Channel` object

### Get historical events

`GetEventsHistory()` retrieves historical events from a channel, similar to [GetHistory()](https://www.pubnub.com/docs/chat/unreal-chat-sdk/build/features/messages/history) for messages. Results cannot be filtered by type and include all events emitted via `Publish()` in the specified timeframe.

#### Method signature

```cpp
Chat->GetEventsHistory(
    FString ChannelID,
    FString StartTimetoken,
    FString EndTimetoken,
    int Count = 100
);
```

| Parameter | Description |
| --- | --- |
| `ChannelID` *Type: `FString`Default: n/a | Channel from which you want to pull historical events. |
| `StartTimetoken`Type: `FString`Default: n/a | [Timetoken](https://www.pubnub.com/docs/sdks/javascript/api-reference/misc#time) delimiting the start of a time slice (exclusive) to pull events from. For details, refer to the [Fetch History section](https://www.pubnub.com/docs/sdks/javascript/api-reference/storage-and-playback#fetch-history). |
| `EndTimetoken`Type: `FString`Default: n/a | Timetoken delimiting the end of a time slice (inclusive) to pull events from. For details, refer to the [Fetch History section](https://www.pubnub.com/docs/sdks/javascript/api-reference/storage-and-playback#fetch-history). |
| `Count`Type: `int`Default: `100` | Number of historical events to return for the channel in a single call. You can pull a maximum number of 100 events in a single call. |

#### Output

| Parameter | Description |
| --- | --- |
| `FPubnubChatEventsResult`Type: `struct` | Returned object containing `Result`, `Events`, and `IsMore`. |
| → `Result`Type: `FPubnubChatOperationResult` | Operation result with `Error` (bool), `ErrorMessage` (FString), and `StepResults`. |
| → `Events`Type: `TArray<FPubnubChatEvent>` | Array listing the requested number of historical event objects. |
| → `IsMore`Type: `bool` | Info whether there are more historical events to pull. |

##### FPubnubChatEvent

| Parameter | Description |
| --- | --- |
| `Timetoken`Type: `FString` | Timetoken of the event. |
| `ChannelID`Type: `FString` | Channel the event occurred on. |
| `UserID`Type: `FString` | User ID associated with the event. |
| `Payload`Type: `FString` | Event payload. |
| `Type`Type: [EPubnubChatEventType](#epubnubchateventtype) | Type of the event. |

##### EPubnubChatEventType

| Value | Description |
| --- | --- |
| `PCET_Typing` | Indicates a user is typing a message. Displayed as Typing. |
| `PCET_Report` | Represents an event where a message has been flagged or reported for offensive content. Displayed as Report. |
| `PCET_Receipt` | Confirms receipt of a message or event. Displayed as Receipt. |
| `PCET_Mention` | Indicates that a user has been mentioned in a message. Displayed as Mention. |
| `PCET_Invite` | Represents an invitation event typically sent to a specific user. Displayed as Invite. |
| `PCET_Custom` | Custom event type for specialized behavior or use cases. Displayed as Custom. |
| `PCET_Moderation` | Represents an event related to content moderation actions. Displayed as Moderation. |

#### Sample code

Fetch the last `10` historical events from the `CUSTOMER-SATISFACTION-CREW` channel.

```cpp
// ACTION REQUIRED: Replace ASample_Chat with name of your Actor class
void ASample_Chat::GetEventsHistorySample()
{
	// snippet.hide
	UPubnubChat* Chat = nullptr;
	FString StartTimetoken = TEXT("0");
	FString EndTimetoken = TEXT("0");
	// snippet.show

	// Assumes Chat is a valid and initialized instance of UPubnubChat
	// StartTimetoken / EndTimetoken: use timetoken range (Start newer than End); e.g. from a previous history or message response

	FOnPubnubChatEventsResponseNative Callback;
	// ACTION REQUIRED: Replace ASample_Chat with name of your Actor class
	Callback.BindUObject(this, &ASample_Chat::OnGetEventsHistoryResponse);
	Chat->GetEventsHistoryAsync(TEXT("Lobby_001"), StartTimetoken, EndTimetoken, Callback, 100);
}

// ACTION REQUIRED: Replace ASample_Chat with name of your Actor class
void ASample_Chat::OnGetEventsHistoryResponse(const FPubnubChatEventsResult& Result)
{
	if (Result.Result.Error) { return; }
	for (const FPubnubChatEvent& Event : Result.Events)
	{
		/* e.g. process moderation/chat events (typing, report, etc.) */
	}
	// Result.IsMore indicates more events exist in the range
}
```

### Emit custom event on a channel

`EmitCustomEvent()` publishes a custom event to a channel. Subscribers listening with [StreamCustomEvents()](#stream-custom-events-on-a-channel) will receive it.

#### Method signature

```cpp
Channel->EmitCustomEvent(
    FString Payload,
    FString Type = "",
    bool StoreInHistory = true
);
```

| Parameter | Description |
| --- | --- |
| `Payload` *Type: `FString`Default: n/a | Custom event data to publish. |
| `Type`Type: `FString`Default: `""` | Optional type label for the custom event. |
| `StoreInHistory`Type: `bool`Default: `true` | Whether to store the event in Message Persistence. |

#### Output

| Type | Description |
| --- | --- |
| `FPubnubChatOperationResult` | Operation result with `Error` (bool) and `ErrorMessage` (FString). |

To emit asynchronously, use `Channel->EmitCustomEventAsync(Payload, OnOperationResponse, Type, StoreInHistory)`.

### Stream custom events on a channel

You can also listen for custom events directly on a `Channel` object using `StreamCustomEvents()`. Custom events are delivered via the `OnCustomEventReceived` delegate on the channel.

Call `StopStreamingCustomEvents()` to stop listening.

#### Method signature

```cpp
Channel->StreamCustomEvents();
```

#### Output

| Type | Description |
| --- | --- |
| `FPubnubChatOperationResult` | Operation result with `Error` (bool), `ErrorMessage` (FString), and `StepResults` (per-step details). |

#### OnCustomEventReceived delegate

Bind to the `OnCustomEventReceived` delegate on the channel to handle incoming custom events.

| Delegate | Parameter |
| --- | --- |
| `FOnPubnubChatCustomEventReceived`Type: `FPubnubChatCustomEvent` | `CustomEvent` |

##### FPubnubChatCustomEvent

| Field | Type | Description |
| --- | --- | --- |
| `Timetoken` | `FString` | Timetoken of the custom event. |
| `UserID` | `FString` | ID of the user who emitted the event. |
| `Payload` | `FString` | Custom event payload. |
| `Type` | `FString` | Custom event type string. |

#### Sample code

###### Actor.h

```cpp
UFUNCTION(BlueprintCallable, Category = "PubnubChat|Samples|ChatChannel")
void StreamCustomEventsSample();

void OnCustomEventReceived(const FPubnubChatCustomEvent& CustomEvent);
```

###### Actor.cpp

```cpp
// ACTION REQUIRED: Replace ASample_ChatChannel with name of your Actor class
void ASample_ChatChannel::StreamCustomEventsSample()
{
	// snippet.hide
	UPubnubChatChannel* Channel = nullptr;
	// snippet.show

	// Assumes Channel is a valid UPubnubChatChannel (e.g. from GetChannel)

	// Bind to receive custom events on this channel
	Channel->OnCustomEventReceivedNative.AddUObject(this, &ASample_ChatChannel::OnCustomEventReceived);

	// Start streaming custom events
	Channel->StreamCustomEventsAsync(nullptr);

	// When custom events are no longer needed, stop streaming
	Channel->StopStreamingCustomEventsAsync(nullptr);
}

// ACTION REQUIRED: Replace ASample_ChatChannel with name of your Actor class
void ASample_ChatChannel::OnCustomEventReceived(const FPubnubChatCustomEvent& CustomEvent)
{
	/* e.g. process application-specific events (game state, commands, etc.) */
}
```