diff --git a/chat-call.mdx b/chat-call.mdx
index b85b12834..ccc6b5559 100644
--- a/chat-call.mdx
+++ b/chat-call.mdx
@@ -213,6 +213,7 @@ npx @cometchat/skills add
} href="/sdk/android/overview" horizontal />
} href="/sdk/flutter/overview" horizontal />
} href="/sdk/ionic/overview" horizontal />
+ } href="/sdk/unreal/overview" horizontal />
diff --git a/docs.json b/docs.json
index a064bb587..a014a3746 100644
--- a/docs.json
+++ b/docs.json
@@ -4613,6 +4613,45 @@
}
]
},
+ {
+ "dropdown": "Unreal Engine",
+ "icon": "/images/icons/unreal.svg",
+ "pages": [
+ "sdk/unreal/overview",
+ "sdk/unreal/setup",
+ "sdk/unreal/key-concepts",
+ {
+ "group": "Authentication",
+ "pages": [
+ "sdk/unreal/authentication"
+ ]
+ },
+ {
+ "group": "Messaging",
+ "pages": [
+ "sdk/unreal/send-message",
+ "sdk/unreal/receive-messages",
+ "sdk/unreal/real-time-events",
+ "sdk/unreal/typing-indicators",
+ "sdk/unreal/delivery-read-receipts",
+ "sdk/unreal/connection-status"
+ ]
+ },
+ {
+ "group": "Users & Groups",
+ "pages": [
+ "sdk/unreal/users",
+ "sdk/unreal/groups"
+ ]
+ },
+ {
+ "group": "Reference",
+ "pages": [
+ "sdk/unreal/reference"
+ ]
+ }
+ ]
+ },
{
"dropdown": "Ionic (Legacy)",
"icon": "/images/icons/ionic.svg",
diff --git a/images/icons/unreal.svg b/images/icons/unreal.svg
new file mode 100644
index 000000000..0cdc617af
--- /dev/null
+++ b/images/icons/unreal.svg
@@ -0,0 +1,4 @@
+
+
\ No newline at end of file
diff --git a/images/unreal_chat_sample.png b/images/unreal_chat_sample.png
new file mode 100644
index 000000000..90003ba71
Binary files /dev/null and b/images/unreal_chat_sample.png differ
diff --git a/sdk/unreal/authentication.mdx b/sdk/unreal/authentication.mdx
new file mode 100644
index 000000000..00d208c81
--- /dev/null
+++ b/sdk/unreal/authentication.mdx
@@ -0,0 +1,267 @@
+---
+title: "Authentication"
+description: "Log users in and out of CometChat in your Unreal Engine project."
+---
+
+## Create User
+
+Before you log in a user, the user must exist in CometChat.
+
+1. **For proof of concept / MVPs**: Create users via the [CometChat Dashboard](https://app.cometchat.com).
+2. **For production apps**: Use the [Create User REST API](https://api-explorer.cometchat.com/reference/creates-user) when your user signs up.
+
+
+**Sample Users**
+
+CometChat provides 5 pre-created users for testing: `cometchat-uid-1`, `cometchat-uid-2`, `cometchat-uid-3`, `cometchat-uid-4`, and `cometchat-uid-5`.
+
+
+---
+
+## Login using Auth Key
+
+
+This authentication method is ideal for **proof-of-concept** development or early-stage apps. For production environments, we recommend using an **Auth Token** instead of an Auth Key for enhanced security.
+
+
+### Auth Flow
+
+```mermaid
+flowchart LR
+ A["Configure"] --> B["Bind Delegates"] --> C["Login Async"]
+ C -->|"Success"| D["User Authenticated"]
+ C -->|"Failure"| E["Handle Error"]
+ D --> F["SDK Ready — Send messages, fetch data"]
+
+ style A fill:#333,stroke:#666,color:#fff
+ style B fill:#333,stroke:#666,color:#fff
+ style C fill:#444,stroke:#888,color:#fff
+ style D fill:#333,stroke:#666,color:#fff
+ style E fill:#555,stroke:#999,color:#ccc
+ style F fill:#333,stroke:#666,color:#fff
+```
+
+The Login node authenticates a user with CometChat. You should call it:
+
+1. When the user is logging in for the first time
+2. When `IsLoggedIn` returns `false`
+
+
+
+1. Get a reference to the **CometChat Subsystem**
+2. Call the **Login Async** node
+3. Wire the **On Success** and **On Failure** pins
+
+| Parameter | Type | Description |
+| --------- | ---- | ----------- |
+| Uid | `FString` | The unique ID of the user to log in |
+| Auth Key | `FString` | Your CometChat Auth Key |
+
+
+```cpp
+#include "CometChatSubsystem.h"
+#include "AsyncActions/CometChatLoginAction.h"
+
+void AMyActor::BeginPlay()
+{
+ Super::BeginPlay();
+
+ // 1. Configure the SDK (do this once)
+ UCometChatSubsystem* Chat = GetGameInstance()->GetSubsystem();
+ Chat->Configure(TEXT("YOUR_APP_ID"), TEXT("us"));
+
+ // 2. Bind real-time events before login
+ Chat->OnMessageReceived.AddDynamic(this, &AMyActor::OnMessage);
+
+ // 3. Login
+ if (!Chat->IsLoggedIn())
+ {
+ auto* Login = UCometChatLoginAction::LoginAsync(
+ this,
+ TEXT("cometchat-uid-1"),
+ TEXT("YOUR_AUTH_KEY")
+ );
+ Login->OnSuccess.AddDynamic(this, &AMyActor::OnLoginSuccess);
+ Login->OnFailure.AddDynamic(this, &AMyActor::OnLoginFailed);
+ Login->Activate();
+ }
+}
+
+void AMyActor::OnLoginSuccess()
+{
+ UE_LOG(LogTemp, Log, TEXT("Login successful!"));
+}
+
+void AMyActor::OnLoginFailed(const FString& Error)
+{
+ UE_LOG(LogTemp, Error, TEXT("Login failed: %s"), *Error);
+}
+```
+
+
+
+
+**UID format**: UIDs can be alphanumeric with underscores and hyphens. Spaces, punctuation, and other special characters are not allowed.
+
+
+---
+
+## Login using Auth Token
+
+
+This is the **recommended authentication method for production** apps. Auth Tokens are generated server-side using the CometChat REST API and provide enhanced security since your Auth Key is never exposed on the client.
+
+
+### How Auth Tokens Work
+
+```mermaid
+flowchart LR
+ A["Your Backend"] --> B["CometChat REST API"]
+ B -->|"Returns Auth Token"| A
+ A -->|"Sends Token to Client"| C["Unreal Client"]
+ C --> D["Login with Auth Token"]
+ D -->|"Success"| E["User Authenticated"]
+ D -->|"Failure"| F["Handle Error"]
+
+ style A fill:#333,stroke:#666,color:#fff
+ style B fill:#333,stroke:#666,color:#fff
+ style C fill:#444,stroke:#888,color:#fff
+ style D fill:#444,stroke:#888,color:#fff
+ style E fill:#333,stroke:#666,color:#fff
+ style F fill:#555,stroke:#999,color:#ccc
+```
+
+1. Your backend calls the [Create Auth Token REST API](https://api-explorer.cometchat.com/reference/create-authtoken) with the user's UID
+2. The API returns an Auth Token
+3. Your backend sends the token to the Unreal client
+4. The client calls `LoginWithAuthTokenAsync` with the token
+
+
+
+1. Get a reference to the **CometChat Subsystem**
+2. Call the **Login With Auth Token Async** node
+3. Wire the **On Success** and **On Failure** pins
+
+| Parameter | Type | Description |
+| --------- | ---- | ----------- |
+| Auth Token | `FString` | The auth token received from your backend |
+
+
+```cpp
+#include "CometChatSubsystem.h"
+#include "AsyncActions/CometChatLoginWithAuthTokenAction.h"
+
+void AMyActor::LoginWithToken(const FString& AuthToken)
+{
+ UCometChatSubsystem* Chat = GetGameInstance()->GetSubsystem();
+
+ if (!Chat->IsLoggedIn())
+ {
+ auto* Login = UCometChatLoginWithAuthTokenAction::LoginWithAuthTokenAsync(
+ this,
+ AuthToken
+ );
+ Login->OnSuccess.AddDynamic(this, &AMyActor::OnLoginSuccess);
+ Login->OnFailure.AddDynamic(this, &AMyActor::OnLoginFailed);
+ Login->Activate();
+ }
+}
+
+void AMyActor::OnLoginSuccess()
+{
+ UE_LOG(LogTemp, Log, TEXT("Auth token login successful!"));
+}
+
+void AMyActor::OnLoginFailed(const FString& Error)
+{
+ UE_LOG(LogTemp, Error, TEXT("Auth token login failed: %s"), *Error);
+}
+```
+
+
+
+
+**Security**: Never hardcode Auth Tokens in your client. Always fetch them from your backend at runtime.
+
+
+---
+
+## Check Login State
+
+Before performing operations, you can check whether a user is currently logged in.
+
+
+
+Call the **Is Logged In** node on the CometChat Subsystem. It returns a `bool`.
+
+
+```cpp
+UCometChatSubsystem* Chat = GetGameInstance()->GetSubsystem();
+
+if (Chat->IsLoggedIn())
+{
+ // User is authenticated — safe to send messages, fetch data, etc.
+}
+```
+
+
+
+---
+
+## Logout
+
+Logs the current user out and disconnects the real-time WebSocket.
+
+
+
+Call the **Logout Async** node on the CometChat Subsystem. Wire the **On Success** and **On Failure** pins.
+
+
+```cpp
+#include "AsyncActions/CometChatLogoutAction.h"
+
+void AMyActor::PerformLogout()
+{
+ auto* Logout = UCometChatLogoutAction::LogoutAsync(this);
+ Logout->OnSuccess.AddDynamic(this, &AMyActor::OnLogoutSuccess);
+ Logout->OnFailure.AddDynamic(this, &AMyActor::OnLogoutFailed);
+ Logout->Activate();
+}
+```
+
+
+
+---
+
+## Shutdown
+
+To fully tear down the SDK (e.g., when your game is closing), call **Shutdown** on the Subsystem. This releases all resources and closes connections.
+
+
+
+Call the **Shutdown** node on the CometChat Subsystem.
+
+
+```cpp
+UCometChatSubsystem* Chat = GetGameInstance()->GetSubsystem();
+Chat->Shutdown();
+```
+
+
+
+
+You typically don't need to call Shutdown manually — the Subsystem's `Deinitialize` handles cleanup when the game instance is destroyed.
+
+
+---
+
+## Next Steps
+
+
+
+ Send your first text message after logging in.
+
+
+ Listen for incoming messages and presence updates.
+
+
diff --git a/sdk/unreal/connection-status.mdx b/sdk/unreal/connection-status.mdx
new file mode 100644
index 000000000..1c0290cac
--- /dev/null
+++ b/sdk/unreal/connection-status.mdx
@@ -0,0 +1,93 @@
+---
+title: "Connection Status"
+description: "Monitor the WebSocket connection state and handle reconnection."
+---
+
+The CometChat SDK maintains a persistent WebSocket connection for real-time events. The `OnConnectionStateChanged` delegate lets you track the connection lifecycle and show appropriate UI (e.g., a "Reconnecting..." banner).
+
+---
+
+## Listen for Connection Changes
+
+
+
+1. Get a reference to the **CometChat Subsystem**
+2. Drag off and search for **On Connection State Changed**
+3. Use **Bind Event** to connect it to a custom event
+4. The custom event receives an `ECometChatConnectionState` enum value
+
+
+```cpp
+void AMyActor::BeginPlay()
+{
+ Super::BeginPlay();
+
+ UCometChatSubsystem* Chat = GetGameInstance()->GetSubsystem();
+ Chat->OnConnectionStateChanged.AddDynamic(this, &AMyActor::HandleConnection);
+}
+
+void AMyActor::HandleConnection(ECometChatConnectionState State)
+{
+ switch (State)
+ {
+ case ECometChatConnectionState::Connected:
+ UE_LOG(LogTemp, Log, TEXT("Connected — real-time events active"));
+ HideConnectionBanner();
+ break;
+
+ case ECometChatConnectionState::Disconnected:
+ UE_LOG(LogTemp, Warning, TEXT("Disconnected — no real-time events"));
+ ShowConnectionBanner(TEXT("Connection lost"));
+ break;
+
+ case ECometChatConnectionState::Reconnecting:
+ UE_LOG(LogTemp, Warning, TEXT("Reconnecting..."));
+ ShowConnectionBanner(TEXT("Reconnecting..."));
+ break;
+ }
+}
+```
+
+
+
+---
+
+## ECometChatConnectionState
+
+| Value | Description |
+| ----- | ----------- |
+| `Connected` | WebSocket is active. Real-time events (messages, presence, typing, receipts) are flowing. |
+| `Disconnected` | WebSocket is closed. No real-time events will be received until reconnection. |
+| `Reconnecting` | The SDK detected a disconnect and is automatically attempting to reconnect. |
+
+---
+
+## Reconnection Behavior
+
+The SDK handles reconnection automatically:
+
+1. When the WebSocket drops (network change, server timeout, etc.), the state moves to `Reconnecting`
+2. The SDK retries with exponential backoff
+3. On successful reconnection, the state moves back to `Connected`
+4. If reconnection fails permanently, the state moves to `Disconnected`
+
+
+**UI pattern**: Show a subtle banner at the top of your chat screen when the state is `Disconnected` or `Reconnecting`. Hide it when `Connected` fires again. This gives players confidence that the chat system is working.
+
+
+
+While disconnected, you can still call async nodes like **Get Messages Async** — those use HTTP requests, not the WebSocket. Only real-time push events are affected by the connection state.
+
+
+---
+
+## Next Steps
+
+
+
+ See all five real-time delegates in one place.
+
+
+ Complete reference of all nodes, structs, and enums.
+
+
diff --git a/sdk/unreal/delivery-read-receipts.mdx b/sdk/unreal/delivery-read-receipts.mdx
new file mode 100644
index 000000000..c435fcdb4
--- /dev/null
+++ b/sdk/unreal/delivery-read-receipts.mdx
@@ -0,0 +1,96 @@
+---
+title: "Delivery & Read Receipts"
+description: "Track when messages are delivered to and read by recipients."
+---
+
+Delivery and read receipts let you show checkmark indicators (✓ delivered, ✓✓ read) next to messages in your chat UI. The CometChat Unreal SDK delivers these as real-time events through the `OnReceiptReceived` delegate.
+
+---
+
+## Listen for Receipt Events
+
+Bind to the `OnReceiptReceived` delegate on the Subsystem.
+
+
+
+1. Get a reference to the **CometChat Subsystem**
+2. Drag off and search for **On Receipt Received**
+3. Use **Bind Event** to connect it to a custom event
+4. The custom event receives an `FCometChatReceiptEvent` parameter
+
+
+```cpp
+void AMyActor::BeginPlay()
+{
+ Super::BeginPlay();
+
+ UCometChatSubsystem* Chat = GetGameInstance()->GetSubsystem();
+ Chat->OnReceiptReceived.AddDynamic(this, &AMyActor::HandleReceipt);
+}
+
+void AMyActor::HandleReceipt(const FCometChatReceiptEvent& Event)
+{
+ if (Event.Status == TEXT("delivered"))
+ {
+ // Show single checkmark ✓
+ MarkMessageDelivered(Event.MessageId);
+ }
+ else if (Event.Status == TEXT("read"))
+ {
+ // Show double checkmark ✓✓
+ MarkMessageRead(Event.MessageId);
+ }
+}
+```
+
+
+
+---
+
+## FCometChatReceiptEvent
+
+| Property | Type | Description |
+| -------- | ---- | ----------- |
+| `MessageId` | `FString` | The message this receipt applies to |
+| `Uid` | `FString` | The user who triggered the receipt (the recipient) |
+| `Status` | `FString` | `delivered` — message reached the device; `read` — message was viewed |
+| `Timestamp` | `int64` | Unix timestamp when the receipt was generated |
+
+---
+
+## Receipt Flow
+
+```mermaid
+flowchart TD
+ A["Sender sends message"] --> B["Message arrives on recipient's device"]
+ B --> C["'delivered' receipt"]
+ C -.-> D["OnReceiptReceived — Status: delivered"]
+ B --> E["Recipient views message"]
+ E --> F["'read' receipt"]
+ F -.-> G["OnReceiptReceived — Status: read"]
+
+ style A fill:#333,stroke:#666,color:#fff
+ style B fill:#444,stroke:#888,color:#fff
+ style C fill:#333,stroke:#666,color:#fff
+ style D fill:#333,stroke:#666,color:#fff
+ style E fill:#444,stroke:#888,color:#fff
+ style F fill:#333,stroke:#666,color:#fff
+ style G fill:#333,stroke:#666,color:#fff
+```
+
+
+A `read` receipt implies `delivered`. If you receive a `read` event for a message you haven't seen a `delivered` event for, treat it as both delivered and read.
+
+
+---
+
+## Next Steps
+
+
+
+ Monitor the WebSocket connection state.
+
+
+ See all five delegates in one place.
+
+
diff --git a/sdk/unreal/groups.mdx b/sdk/unreal/groups.mdx
new file mode 100644
index 000000000..75515c162
--- /dev/null
+++ b/sdk/unreal/groups.mdx
@@ -0,0 +1,194 @@
+---
+title: "Groups"
+description: "Create, join, leave, and message groups in your Unreal Engine game."
+---
+
+Groups let multiple users communicate in a shared conversation. The CometChat Unreal SDK provides async nodes for creating groups, joining existing ones, leaving, and sending/receiving group messages.
+
+### Group Lifecycle
+
+```mermaid
+flowchart LR
+ A["Create Group Async"] --> B["Group exists"]
+ B --> C["Join Group Async"]
+ C --> D["Member of group"]
+ D --> E["Send / Receive messages"]
+ D --> F["Leave Group Async"]
+
+ style A fill:#444,stroke:#888,color:#fff
+ style B fill:#333,stroke:#666,color:#fff
+ style C fill:#444,stroke:#888,color:#fff
+ style D fill:#333,stroke:#666,color:#fff
+ style E fill:#333,stroke:#666,color:#fff
+ style F fill:#555,stroke:#999,color:#ccc
+```
+
+---
+
+## Create a Group
+
+Create a new group with a name and an initial set of member UIDs.
+
+
+
+Call the **Create Group Async** node.
+
+| Parameter | Type | Description |
+| --------- | ---- | ----------- |
+| Name | `FString` | Display name for the group |
+| Member Ids | `TArray` | UIDs of users to add as initial members |
+
+**On Success** returns an `FCometChatGroup` with the server-assigned `Guid`.
+
+
+```cpp
+#include "AsyncActions/CometChatCreateGroupAction.h"
+
+void AMyActor::CreateLobbyGroup()
+{
+ TArray Members;
+ Members.Add(TEXT("cometchat-uid-1"));
+ Members.Add(TEXT("cometchat-uid-2"));
+ Members.Add(TEXT("cometchat-uid-3"));
+
+ auto* Action = UCometChatCreateGroupAction::CreateGroupAsync(
+ this,
+ TEXT("Game Lobby"), // Group name
+ Members // Initial members
+ );
+ Action->OnSuccess.AddDynamic(this, &AMyActor::OnGroupCreated);
+ Action->OnFailure.AddDynamic(this, &AMyActor::OnGroupCreateFailed);
+ Action->Activate();
+}
+
+void AMyActor::OnGroupCreated(const FCometChatGroup& Group)
+{
+ UE_LOG(LogTemp, Log, TEXT("Group created: %s (GUID: %s)"),
+ *Group.Name, *Group.Guid);
+}
+
+void AMyActor::OnGroupCreateFailed(const FString& Error)
+{
+ UE_LOG(LogTemp, Error, TEXT("Create group failed: %s"), *Error);
+}
+```
+
+
+
+---
+
+## Join a Group
+
+Join an existing group by its GUID.
+
+
+
+Call the **Join Group Async** node.
+
+| Parameter | Type | Description |
+| --------- | ---- | ----------- |
+| Guid | `FString` | The unique identifier of the group to join |
+
+**On Success** fires with no output — the user is now a member.
+
+
+```cpp
+#include "AsyncActions/CometChatJoinGroupAction.h"
+
+void AMyActor::JoinGroup(const FString& Guid)
+{
+ auto* Action = UCometChatJoinGroupAction::JoinGroupAsync(this, Guid);
+ Action->OnSuccess.AddDynamic(this, &AMyActor::OnGroupJoined);
+ Action->OnFailure.AddDynamic(this, &AMyActor::OnJoinFailed);
+ Action->Activate();
+}
+
+void AMyActor::OnGroupJoined()
+{
+ UE_LOG(LogTemp, Log, TEXT("Successfully joined the group"));
+}
+
+void AMyActor::OnJoinFailed(const FString& Error)
+{
+ UE_LOG(LogTemp, Error, TEXT("Join failed: %s"), *Error);
+}
+```
+
+
+
+---
+
+## Leave a Group
+
+Leave a group you're currently a member of.
+
+
+
+Call the **Leave Group Async** node.
+
+| Parameter | Type | Description |
+| --------- | ---- | ----------- |
+| Guid | `FString` | The unique identifier of the group to leave |
+
+**On Success** fires with no output.
+
+
+```cpp
+#include "AsyncActions/CometChatLeaveGroupAction.h"
+
+void AMyActor::LeaveGroup(const FString& Guid)
+{
+ auto* Action = UCometChatLeaveGroupAction::LeaveGroupAsync(this, Guid);
+ Action->OnSuccess.AddDynamic(this, &AMyActor::OnGroupLeft);
+ Action->OnFailure.AddDynamic(this, &AMyActor::OnLeaveFailed);
+ Action->Activate();
+}
+
+void AMyActor::OnGroupLeft()
+{
+ UE_LOG(LogTemp, Log, TEXT("Left the group"));
+}
+
+void AMyActor::OnLeaveFailed(const FString& Error)
+{
+ UE_LOG(LogTemp, Error, TEXT("Leave failed: %s"), *Error);
+}
+```
+
+
+
+---
+
+## Send a Group Message
+
+Send a text message to all members of a group. See [Send a Message → Group Messages](/sdk/unreal/send-message#send-a-group-message) for details.
+
+---
+
+## Fetch Group Message History
+
+Retrieve previous messages from a group with pagination. See [Receive Messages → Group Messages](/sdk/unreal/receive-messages#fetch-group-messages) for details.
+
+---
+
+## FCometChatGroup Properties
+
+| Property | Type | Description |
+| -------- | ---- | ----------- |
+| `Guid` | `FString` | Server-assigned unique group identifier |
+| `Name` | `FString` | Group display name |
+| `Description` | `FString` | Group description text |
+| `MemberIds` | `TArray` | UIDs of current group members |
+
+---
+
+## Next Steps
+
+
+
+ Send messages to users and groups.
+
+
+ Listen for messages, presence, typing, and more.
+
+
diff --git a/sdk/unreal/key-concepts.mdx b/sdk/unreal/key-concepts.mdx
new file mode 100644
index 000000000..a0c03be3d
--- /dev/null
+++ b/sdk/unreal/key-concepts.mdx
@@ -0,0 +1,216 @@
+---
+title: "Key Concepts"
+description: "Understand the architecture, patterns, and data types used by the CometChat Unreal SDK."
+---
+
+Before diving into individual features, it helps to understand the three building blocks of the plugin: the **Subsystem**, **Latent Async Nodes**, and **Real-Time Delegates**.
+
+---
+
+## The Subsystem
+
+`UCometChatSubsystem` is a [UGameInstanceSubsystem](https://dev.epicgames.com/documentation/en-us/unreal-engine/programming-subsystems-in-unreal-engine) — Unreal creates one instance automatically when your game starts, and it lives for the entire session. You never need to spawn or manage it yourself.
+
+
+
+Get a reference from any Blueprint:
+
+**Get Game Instance** → **Get Subsystem** → select **CometChatSubsystem**
+
+
+```cpp
+UCometChatSubsystem* Chat = GetGameInstance()->GetSubsystem();
+```
+
+
+
+The Subsystem handles:
+- **Configuration** — storing your App ID and Region
+- **SDK lifecycle** — creating and shutting down the underlying C++ SDK
+- **Auth state** — tracking whether a user is logged in
+- **Real-time events** — exposing multicast delegates for push notifications
+
+---
+
+## Latent Async Nodes
+
+Every SDK operation that talks to the network (Login, Send Message, Get Messages, etc.) is exposed as a **latent async action** — a Blueprint node with two output execution pins:
+
+| Pin | When it fires |
+| --- | ------------- |
+| **On Success** | The operation completed successfully. Output data is available on the success pin. |
+| **On Failure** | Something went wrong. An `FString` error message describes what happened. |
+
+### How an Async Node Executes
+
+```mermaid
+flowchart LR
+ A["Blueprint calls Async Node"] --> B["C++ SDK makes request"] --> C{"Response"}
+ C -->|"Success"| D["On Success pin fires"]
+ C -->|"Error"| E["On Failure pin fires"]
+
+ style A fill:#333,stroke:#666,color:#fff
+ style B fill:#333,stroke:#666,color:#fff
+ style C fill:#444,stroke:#888,color:#fff
+ style D fill:#333,stroke:#666,color:#fff
+ style E fill:#555,stroke:#999,color:#ccc
+```
+
+In C++, these are `UCometChatAsyncAction` subclasses. You create them with a static factory method, bind delegates, and call `Activate()`:
+
+```cpp
+auto* Action = UCometChatLoginAction::LoginAsync(this, TEXT("user-123"), TEXT("auth-key"));
+Action->OnSuccess.AddDynamic(this, &AMyActor::HandleLoginSuccess);
+Action->OnFailure.AddDynamic(this, &AMyActor::HandleLoginFailure);
+Action->Activate();
+```
+
+
+All async callbacks fire on the **Game Thread**, so it's safe to update UI, spawn actors, or call other engine APIs directly from the callback.
+
+
+### Available Async Nodes
+
+| Category | Node | Success Output |
+| -------- | ---- | -------------- |
+| Auth | **Login Async** | — |
+| Auth | **Logout Async** | — |
+| Messaging | **Send Message Async** | `FCometChatMessage` |
+| Messaging | **Send Group Message Async** | `FCometChatMessage` |
+| Messaging | **Get Messages Async** | `TArray` |
+| Messaging | **Get Group Messages Async** | `TArray` + `FCometChatPagination` |
+| Users | **Get User Async** | `FCometChatUser` |
+| Groups | **Create Group Async** | `FCometChatGroup` |
+| Groups | **Join Group Async** | — |
+| Groups | **Leave Group Async** | — |
+
+---
+
+## Real-Time Delegates
+
+The Subsystem exposes five multicast delegates for real-time push events. Bind to them once after calling **Configure**, and they'll fire whenever the server pushes an update.
+
+| Delegate | Payload Type | Fires When |
+| -------- | ------------ | ---------- |
+| `OnMessageReceived` | `FCometChatMessage` | A new message arrives in any conversation |
+| `OnPresenceChanged` | `FCometChatPresence` | A user goes online, offline, or away |
+| `OnTypingChanged` | `FCometChatTypingEvent` | A user starts or stops typing |
+| `OnReceiptReceived` | `FCometChatReceiptEvent` | A message is delivered or read |
+| `OnConnectionStateChanged` | `ECometChatConnectionState` | WebSocket connects, disconnects, or reconnects |
+
+
+
+Drag off the Subsystem reference and search for the delegate name (e.g., **On Message Received**). Use **Bind Event** to wire it to a custom event.
+
+
+```cpp
+UCometChatSubsystem* Chat = GetGameInstance()->GetSubsystem();
+
+Chat->OnMessageReceived.AddDynamic(this, &AMyActor::HandleNewMessage);
+Chat->OnPresenceChanged.AddDynamic(this, &AMyActor::HandlePresence);
+Chat->OnTypingChanged.AddDynamic(this, &AMyActor::HandleTyping);
+Chat->OnReceiptReceived.AddDynamic(this, &AMyActor::HandleReceipt);
+Chat->OnConnectionStateChanged.AddDynamic(this, &AMyActor::HandleConnection);
+```
+
+
+
+
+Bind your delegates **before** calling Login. Events that arrive between Login and binding will be missed.
+
+
+---
+
+## Data Types
+
+The plugin uses Unreal-native `USTRUCT` types — no `std::string` or STL containers leak into your game code.
+
+### FCometChatUser
+
+| Property | Type | Description |
+| -------- | ---- | ----------- |
+| `Uid` | `FString` | Unique user identifier |
+| `Name` | `FString` | Display name |
+| `AvatarUrl` | `FString` | URL to the user's avatar image |
+| `Status` | `FString` | Current status text |
+
+### FCometChatMessage
+
+| Property | Type | Description |
+| -------- | ---- | ----------- |
+| `Id` | `FString` | Unique message identifier |
+| `SenderUid` | `FString` | UID of the sender |
+| `ReceiverUid` | `FString` | UID of the receiver (user or group) |
+| `Text` | `FString` | Message body |
+| `SentAt` | `int64` | Unix timestamp (seconds) when sent |
+| `Type` | `FString` | Message type: `text`, `image`, `file`, `custom` |
+| `Category` | `FString` | Category: `message`, `action`, `call`, `custom` |
+| `ReceiverType` | `FString` | `user` or `group` |
+| `ConversationId` | `FString` | Conversation identifier |
+| `SenderName` | `FString` | Sender's display name |
+| `SenderAvatar` | `FString` | Sender's avatar URL |
+| `UpdatedAt` | `int64` | Unix timestamp of last update |
+
+### FCometChatGroup
+
+| Property | Type | Description |
+| -------- | ---- | ----------- |
+| `Guid` | `FString` | Unique group identifier |
+| `Name` | `FString` | Group display name |
+| `Description` | `FString` | Group description |
+| `MemberIds` | `TArray` | UIDs of group members |
+
+### FCometChatPagination
+
+| Property | Type | Description |
+| -------- | ---- | ----------- |
+| `Total` | `int32` | Total messages available |
+| `Count` | `int32` | Messages returned in this page |
+| `PerPage` | `int32` | Page size requested |
+| `CurrentPage` | `int32` | Current page number |
+| `TotalPages` | `int32` | Total pages available |
+| `HasMore` | `bool` | Whether more pages exist |
+| `NextCursor` | `int32` | Message ID to pass as `BeforeMessageId` for the next page |
+
+### FCometChatPresence
+
+| Property | Type | Description |
+| -------- | ---- | ----------- |
+| `Uid` | `FString` | User identifier |
+| `Status` | `ECometChatPresenceStatus` | `Online`, `Offline`, or `Away` |
+| `LastActiveAt` | `int64` | Unix timestamp of last activity |
+
+### FCometChatTypingEvent
+
+| Property | Type | Description |
+| -------- | ---- | ----------- |
+| `Uid` | `FString` | User who is typing |
+| `ConversationId` | `FString` | Conversation where typing is happening |
+| `bIsTyping` | `bool` | `true` if started typing, `false` if stopped |
+
+### FCometChatReceiptEvent
+
+| Property | Type | Description |
+| -------- | ---- | ----------- |
+| `MessageId` | `FString` | The message this receipt is for |
+| `Uid` | `FString` | User who triggered the receipt |
+| `Status` | `FString` | `delivered` or `read` |
+| `Timestamp` | `int64` | Unix timestamp of the receipt |
+
+### Enums
+
+**ECometChatConnectionState**
+
+| Value | Description |
+| ----- | ----------- |
+| `Connected` | WebSocket is connected and active |
+| `Disconnected` | WebSocket is disconnected |
+| `Reconnecting` | SDK is attempting to reconnect |
+
+**ECometChatPresenceStatus**
+
+| Value | Description |
+| ----- | ----------- |
+| `Online` | User is currently online |
+| `Offline` | User is offline |
+| `Away` | User is away |
diff --git a/sdk/unreal/overview.mdx b/sdk/unreal/overview.mdx
new file mode 100644
index 000000000..a3dc2b800
--- /dev/null
+++ b/sdk/unreal/overview.mdx
@@ -0,0 +1,177 @@
+---
+title: "Overview"
+description: "Add in-app chat to your Unreal Engine game using the CometChat SDK plugin."
+---
+
+
+
+
+
+
+**Beta Release** — The CometChat Unreal SDK is currently in beta. APIs and features may change, and you may encounter stability issues.
+
+
+This guide walks you through integrating CometChat into an Unreal Engine 5 project. The SDK ships as a native UE5 plugin with full **Blueprint** and **C++** support — so whether you're wiring up a quick prototype in the visual graph or building a production multiplayer title in code, you're covered.
+
+
+Before you begin, we recommend reading the [Key Concepts](/sdk/unreal/key-concepts) page to understand the architecture.
+
+
+---
+
+## Supported Platforms
+
+| Platform | Status |
+| -------- | ------ |
+| Windows (Win64) | ✅ Supported |
+| macOS | ✅ Supported |
+| Linux | ✅ Supported |
+| iOS | ✅ Supported |
+| Android | ✅ Supported |
+
+---
+
+## Minimum Requirements
+
+- Unreal Engine **5.3** or higher
+- C++17 compatible compiler
+- [CometChat account](https://app.cometchat.com) with **App ID**, **Region**, and **Auth Key**
+
+---
+
+## Quick Start
+
+Get up and running in five steps:
+
+
+
+ [Sign up for CometChat](https://app.cometchat.com), create a new app, and note your **App ID**, **Auth Key**, and **Region**.
+
+
+ Copy the `CometChat` plugin into your project's `Plugins/` directory. See [Setup](/sdk/unreal/setup) for details.
+
+
+ Call **Configure** on the `CometChatSubsystem` with your App ID and Region.
+
+
+ Use the **Login Async** node with a user UID and Auth Key.
+
+
+ Use the **Send Message Async** node to send your first message.
+
+
+
+---
+
+## Architecture
+
+The plugin has three layers:
+
+```mermaid
+graph TD
+ A["Your Game — Blueprint / C++"] --> B["Unreal Plugin Layer Subsystem + Async Nodes + Delegates"]
+ B --> C["C++ Chat SDK Core"]
+ C --> D["CometChat Cloud"]
+
+ style A fill:#333,stroke:#666,color:#fff
+ style B fill:#444,stroke:#888,color:#fff
+ style C fill:#333,stroke:#666,color:#fff
+ style D fill:#555,stroke:#999,color:#fff
+```
+
+- **UCometChatSubsystem** — A `UGameInstanceSubsystem` that owns the SDK lifecycle. Access it from any Actor or Widget.
+- **Latent Async Nodes** — Blueprint-friendly async actions with **Success** and **Failure** output pins.
+- **Real-Time Delegates** — Multicast delegates on the Subsystem for push events. All fire on the **Game Thread**.
+
+---
+
+## How It Works in Blueprints
+
+```mermaid
+flowchart TD
+ A["Event BeginPlay"] --> B["Get CometChat Subsystem"]
+ B --> C["Configure — App Id, Region"]
+ C --> D["Bind Delegates OnMessageReceived, OnPresenceChanged"]
+ D --> E["Login Async"]
+ E -->|"On Success"| F["Ready"]
+ E -->|"On Failure"| G["Handle Error"]
+
+ F --> H["Send Message Async"]
+ F --> I["Get Messages Async"]
+ F --> J["Create / Join / Leave Group"]
+
+ H -->|"On Success"| K["Update Chat UI"]
+ I -->|"On Success"| K
+
+ L["CometChat Cloud"] -.->|"WebSocket"| M["OnMessageReceived fires"]
+ M --> K
+
+ style A fill:#333,stroke:#666,color:#fff
+ style B fill:#333,stroke:#666,color:#fff
+ style C fill:#333,stroke:#666,color:#fff
+ style D fill:#333,stroke:#666,color:#fff
+ style E fill:#444,stroke:#888,color:#fff
+ style F fill:#333,stroke:#666,color:#fff
+ style G fill:#555,stroke:#999,color:#ccc
+ style H fill:#444,stroke:#888,color:#fff
+ style I fill:#444,stroke:#888,color:#fff
+ style J fill:#444,stroke:#888,color:#fff
+ style K fill:#333,stroke:#666,color:#fff
+ style L fill:#555,stroke:#999,color:#ccc
+ style M fill:#333,stroke:#666,color:#fff
+```
+
+1. **Get the Subsystem** — `Get Game Instance` → `Get Subsystem` → `CometChatSubsystem`
+2. **Configure** — Pass your App ID and Region once
+3. **Bind Delegates** — Wire up `OnMessageReceived` and other events before Login
+4. **Async Nodes** — Every operation has **On Success** and **On Failure** exec pins
+5. **Real-Time Events** — Incoming messages and presence updates arrive automatically via delegates
+
+
+All callbacks fire on the **Game Thread** — safe to update UI directly.
+
+
+---
+
+## What's Included
+
+| Category | Capabilities |
+| -------- | ------------ |
+| **Authentication** | Login, Logout, session check |
+| **Messaging** | Send & receive text messages (1:1 and group), message history with pagination |
+| **Users** | Fetch user profiles, real-time presence |
+| **Groups** | Create, join, leave groups, group messaging |
+| **Real-Time Events** | Message received, presence changed, typing indicators, read receipts, connection state |
+
+---
+
+## Sample Users
+
+CometChat provides 5 pre-created users for testing:
+
+| UID | Name |
+| --- | ---- |
+| `cometchat-uid-1` | Andrew Joseph |
+| `cometchat-uid-2` | George Alan |
+| `cometchat-uid-3` | Nancy Grace |
+| `cometchat-uid-4` | Susan Marie |
+| `cometchat-uid-5` | Peter Reed |
+
+---
+
+## Next Steps
+
+
+
+ Install the plugin and configure your project.
+
+
+ Understand the Subsystem, async nodes, and event model.
+
+
+ Log users in and manage sessions.
+
+
+ Send your first text message.
+
+
diff --git a/sdk/unreal/real-time-events.mdx b/sdk/unreal/real-time-events.mdx
new file mode 100644
index 000000000..cd7c43fa8
--- /dev/null
+++ b/sdk/unreal/real-time-events.mdx
@@ -0,0 +1,237 @@
+---
+title: "Real-Time Events"
+description: "Listen for incoming messages, presence changes, typing indicators, receipts, and connection state."
+---
+
+The `UCometChatSubsystem` exposes five multicast delegates that fire whenever the server pushes a real-time update. All delegates are guaranteed to fire on the **Game Thread**, so you can safely update UI directly.
+
+### Event Flow
+
+```mermaid
+flowchart LR
+ A["CometChat Cloud"] -.->|"WebSocket"| B["C++ SDK"]
+ B --> C["Subsystem Delegate"]
+ C --> D["Your Blueprint / C++ handler"]
+
+ style A fill:#555,stroke:#999,color:#ccc
+ style B fill:#333,stroke:#666,color:#fff
+ style C fill:#444,stroke:#888,color:#fff
+ style D fill:#333,stroke:#666,color:#fff
+```
+
+
+**Bind delegates before calling Login.** Events that arrive between Login completing and your bindings being set up will be missed.
+
+
+---
+
+## Binding Delegates
+
+
+
+1. Get a reference to the **CometChat Subsystem**
+2. Drag off the Subsystem pin and search for the delegate name (e.g., **On Message Received**)
+3. Select **Bind Event** to wire it to a custom event node
+4. The custom event automatically gets the correct parameter type
+
+
+```cpp
+void AMyActor::BeginPlay()
+{
+ Super::BeginPlay();
+
+ UCometChatSubsystem* Chat = GetGameInstance()->GetSubsystem();
+
+ Chat->OnMessageReceived.AddDynamic(this, &AMyActor::HandleMessage);
+ Chat->OnPresenceChanged.AddDynamic(this, &AMyActor::HandlePresence);
+ Chat->OnTypingChanged.AddDynamic(this, &AMyActor::HandleTyping);
+ Chat->OnReceiptReceived.AddDynamic(this, &AMyActor::HandleReceipt);
+ Chat->OnConnectionStateChanged.AddDynamic(this, &AMyActor::HandleConnection);
+}
+```
+
+
+
+---
+
+## OnMessageReceived
+
+Fires when a new message arrives in any conversation (1:1 or group).
+
+| Payload | Type |
+| ------- | ---- |
+| `Message` | `FCometChatMessage` |
+
+
+
+The custom event receives an `FCometChatMessage`. Use `ReceiverType` to check if it's a `user` (1:1) or `group` message, and `ConversationId` to route it to the right chat window.
+
+
+```cpp
+void AMyActor::HandleMessage(const FCometChatMessage& Message)
+{
+ if (Message.ReceiverType == TEXT("group"))
+ {
+ UE_LOG(LogTemp, Log, TEXT("[Group %s] %s: %s"),
+ *Message.ConversationId, *Message.SenderName, *Message.Text);
+ }
+ else
+ {
+ UE_LOG(LogTemp, Log, TEXT("[DM] %s: %s"),
+ *Message.SenderName, *Message.Text);
+ }
+}
+```
+
+
+
+---
+
+## OnPresenceChanged
+
+Fires when a user's online status changes.
+
+| Payload | Type |
+| ------- | ---- |
+| `Presence` | `FCometChatPresence` |
+
+
+
+The custom event receives an `FCometChatPresence` with `Uid`, `Status` (an `ECometChatPresenceStatus` enum), and `LastActiveAt`.
+
+
+```cpp
+void AMyActor::HandlePresence(const FCometChatPresence& Presence)
+{
+ FString StatusStr;
+ switch (Presence.Status)
+ {
+ case ECometChatPresenceStatus::Online: StatusStr = TEXT("Online"); break;
+ case ECometChatPresenceStatus::Offline: StatusStr = TEXT("Offline"); break;
+ case ECometChatPresenceStatus::Away: StatusStr = TEXT("Away"); break;
+ }
+
+ UE_LOG(LogTemp, Log, TEXT("%s is now %s"), *Presence.Uid, *StatusStr);
+}
+```
+
+
+
+For more details, see [Users → User Presence](/sdk/unreal/users#user-presence).
+
+---
+
+## OnTypingChanged
+
+Fires when a user starts or stops typing in a conversation.
+
+| Payload | Type |
+| ------- | ---- |
+| `Event` | `FCometChatTypingEvent` |
+
+
+
+The custom event receives an `FCometChatTypingEvent` with `Uid`, `ConversationId`, and `bIsTyping`.
+
+
+```cpp
+void AMyActor::HandleTyping(const FCometChatTypingEvent& Event)
+{
+ if (Event.bIsTyping)
+ {
+ UE_LOG(LogTemp, Log, TEXT("%s is typing in %s..."),
+ *Event.Uid, *Event.ConversationId);
+ }
+ else
+ {
+ UE_LOG(LogTemp, Log, TEXT("%s stopped typing in %s"),
+ *Event.Uid, *Event.ConversationId);
+ }
+}
+```
+
+
+
+For more details, see [Typing Indicators](/sdk/unreal/typing-indicators).
+
+---
+
+## OnReceiptReceived
+
+Fires when a message is delivered to or read by the recipient.
+
+| Payload | Type |
+| ------- | ---- |
+| `Event` | `FCometChatReceiptEvent` |
+
+
+
+The custom event receives an `FCometChatReceiptEvent` with `MessageId`, `Uid`, `Status` (`delivered` or `read`), and `Timestamp`.
+
+
+```cpp
+void AMyActor::HandleReceipt(const FCometChatReceiptEvent& Event)
+{
+ UE_LOG(LogTemp, Log, TEXT("Message %s was %s by %s"),
+ *Event.MessageId, *Event.Status, *Event.Uid);
+}
+```
+
+
+
+For more details, see [Delivery & Read Receipts](/sdk/unreal/delivery-read-receipts).
+
+---
+
+## OnConnectionStateChanged
+
+Fires when the WebSocket connection state changes.
+
+| Payload | Type |
+| ------- | ---- |
+| `State` | `ECometChatConnectionState` |
+
+| Value | Meaning |
+| ----- | ------- |
+| `Connected` | WebSocket is active and receiving events |
+| `Disconnected` | Connection lost |
+| `Reconnecting` | SDK is attempting to reconnect automatically |
+
+
+
+The custom event receives an `ECometChatConnectionState` enum value.
+
+
+```cpp
+void AMyActor::HandleConnection(ECometChatConnectionState State)
+{
+ switch (State)
+ {
+ case ECometChatConnectionState::Connected:
+ UE_LOG(LogTemp, Log, TEXT("Connected to CometChat"));
+ break;
+ case ECometChatConnectionState::Disconnected:
+ UE_LOG(LogTemp, Warning, TEXT("Disconnected from CometChat"));
+ break;
+ case ECometChatConnectionState::Reconnecting:
+ UE_LOG(LogTemp, Warning, TEXT("Reconnecting..."));
+ break;
+ }
+}
+```
+
+
+
+For more details, see [Connection Status](/sdk/unreal/connection-status).
+
+---
+
+## Delegate Summary
+
+| Delegate | Payload | Use Case |
+| -------- | ------- | -------- |
+| `OnMessageReceived` | `FCometChatMessage` | Display new messages in chat UI |
+| `OnPresenceChanged` | `FCometChatPresence` | Update online/offline indicators |
+| `OnTypingChanged` | `FCometChatTypingEvent` | Show "typing..." animations |
+| `OnReceiptReceived` | `FCometChatReceiptEvent` | Show delivery/read checkmarks |
+| `OnConnectionStateChanged` | `ECometChatConnectionState` | Show connection status banners |
diff --git a/sdk/unreal/receive-messages.mdx b/sdk/unreal/receive-messages.mdx
new file mode 100644
index 000000000..699388b8e
--- /dev/null
+++ b/sdk/unreal/receive-messages.mdx
@@ -0,0 +1,220 @@
+---
+title: "Receive Messages"
+description: "Fetch message history and listen for incoming messages in real time."
+---
+
+There are two ways to get messages in the CometChat Unreal SDK:
+
+1. **Fetch history** — pull previous messages for a conversation using async nodes
+2. **Real-time push** — listen for new messages as they arrive via the `OnMessageReceived` delegate
+
+### How Messages Flow
+
+```mermaid
+flowchart TD
+ subgraph Fetch["Fetch History"]
+ A["Get Messages Async"] --> B["CometChat REST API"] --> C["Returns message array"]
+ end
+
+ subgraph Realtime["Real-Time Push"]
+ D["CometChat Cloud"] -.->|"WebSocket"| E["OnMessageReceived delegate fires"]
+ end
+
+ C --> F["Display in Chat UI"]
+ E --> F
+
+ style A fill:#333,stroke:#666,color:#fff
+ style B fill:#444,stroke:#888,color:#fff
+ style C fill:#333,stroke:#666,color:#fff
+ style D fill:#555,stroke:#999,color:#ccc
+ style E fill:#333,stroke:#666,color:#fff
+ style F fill:#444,stroke:#888,color:#fff
+ style Fetch fill:#2a2a2a,stroke:#555,color:#ccc
+ style Realtime fill:#2a2a2a,stroke:#555,color:#ccc
+```
+
+---
+
+## Fetch User Messages
+
+Retrieve the message history for a 1:1 conversation.
+
+
+
+Call the **Get Messages Async** node.
+
+| Parameter | Type | Description |
+| --------- | ---- | ----------- |
+| Uid | `FString` | The UID of the other user in the conversation |
+| Limit | `int32` | Maximum number of messages to return (default: 50) |
+
+**On Success** returns a `TArray` — an array of messages sorted by timestamp.
+
+
+```cpp
+#include "AsyncActions/CometChatGetMessagesAction.h"
+
+void AMyActor::FetchMessages()
+{
+ auto* Action = UCometChatGetMessagesAction::GetMessagesAsync(
+ this,
+ TEXT("cometchat-uid-2"), // Other user's UID
+ 30 // Limit
+ );
+ Action->OnSuccess.AddDynamic(this, &AMyActor::OnMessagesFetched);
+ Action->OnFailure.AddDynamic(this, &AMyActor::OnFetchFailed);
+ Action->Activate();
+}
+
+void AMyActor::OnMessagesFetched(const TArray& Messages)
+{
+ for (const FCometChatMessage& Msg : Messages)
+ {
+ UE_LOG(LogTemp, Log, TEXT("[%s]: %s"), *Msg.SenderName, *Msg.Text);
+ }
+}
+
+void AMyActor::OnFetchFailed(const FString& Error)
+{
+ UE_LOG(LogTemp, Error, TEXT("Fetch failed: %s"), *Error);
+}
+```
+
+
+
+---
+
+## Fetch Group Messages
+
+Retrieve the message history for a group conversation, with pagination support.
+
+
+
+Call the **Get Group Messages Async** node.
+
+| Parameter | Type | Description |
+| --------- | ---- | ----------- |
+| Guid | `FString` | The group's unique identifier |
+| Limit | `int32` | Maximum messages per page (default: 50) |
+| Before Message Id | `int32` | Pass `0` for the first page. For subsequent pages, pass the `NextCursor` value from the previous response's `FCometChatPagination`. |
+
+**On Success** returns two outputs:
+- `TArray` — the messages for this page
+- `FCometChatPagination` — pagination metadata including `HasMore` and `NextCursor`
+
+
+```cpp
+#include "AsyncActions/CometChatGetGroupMessagesAction.h"
+
+void AMyActor::FetchGroupMessages(int32 BeforeId)
+{
+ auto* Action = UCometChatGetGroupMessagesAction::GetGroupMessagesAsync(
+ this,
+ TEXT("group-abc-123"), // Group GUID
+ 20, // Limit
+ BeforeId // 0 for first page
+ );
+ Action->OnSuccess.AddDynamic(this, &AMyActor::OnGroupMessagesFetched);
+ Action->OnFailure.AddDynamic(this, &AMyActor::OnGroupFetchFailed);
+ Action->Activate();
+}
+
+void AMyActor::OnGroupMessagesFetched(
+ const TArray& Messages,
+ const FCometChatPagination& Pagination)
+{
+ for (const FCometChatMessage& Msg : Messages)
+ {
+ UE_LOG(LogTemp, Log, TEXT("[%s]: %s"), *Msg.SenderName, *Msg.Text);
+ }
+
+ if (Pagination.HasMore)
+ {
+ // Load next page
+ FetchGroupMessages(Pagination.NextCursor);
+ }
+}
+```
+
+
+
+### Pagination
+
+The `FCometChatPagination` struct tells you where you are in the message history:
+
+| Property | Type | Description |
+| -------- | ---- | ----------- |
+| `Total` | `int32` | Total messages available in the conversation |
+| `Count` | `int32` | Messages returned in this page |
+| `PerPage` | `int32` | Page size that was requested |
+| `HasMore` | `bool` | `true` if there are older messages to fetch |
+| `NextCursor` | `int32` | Pass this as `BeforeMessageId` to get the next page |
+
+
+**Infinite scroll pattern**: Start with `BeforeMessageId = 0`, then keep passing `NextCursor` from each response until `HasMore` is `false`.
+
+
+---
+
+## Real-Time: Incoming Messages
+
+To receive messages as they arrive (without polling), bind to the `OnMessageReceived` delegate on the Subsystem.
+
+
+
+1. Get a reference to the **CometChat Subsystem**
+2. Drag off and search for **On Message Received**
+3. Use **Bind Event** to connect it to a custom event
+4. The custom event receives an `FCometChatMessage` parameter
+
+Bind this **before** calling Login so you don't miss any messages.
+
+
+```cpp
+void AMyActor::BeginPlay()
+{
+ Super::BeginPlay();
+
+ UCometChatSubsystem* Chat = GetGameInstance()->GetSubsystem();
+ Chat->OnMessageReceived.AddDynamic(this, &AMyActor::HandleNewMessage);
+}
+
+void AMyActor::HandleNewMessage(const FCometChatMessage& Message)
+{
+ // This fires on the Game Thread — safe to update UI
+ UE_LOG(LogTemp, Log, TEXT("New message from %s: %s"),
+ *Message.SenderName, *Message.Text);
+
+ // Check if it's a group or user message
+ if (Message.ReceiverType == TEXT("group"))
+ {
+ // Group message — Message.ReceiverUid is the group GUID
+ }
+ else
+ {
+ // 1:1 message — Message.SenderUid is the other user
+ }
+}
+```
+
+
+
+
+The `OnMessageReceived` delegate fires for **all** conversations — both 1:1 and group. Use `ReceiverType` to distinguish between them, and `ConversationId` to route messages to the right chat window.
+
+
+---
+
+## Next Steps
+
+
+
+ Fetch user profiles and track presence.
+
+
+ Create, join, and leave groups.
+
+
+ All five real-time delegates explained in detail.
+
+
diff --git a/sdk/unreal/reference.mdx b/sdk/unreal/reference.mdx
new file mode 100644
index 000000000..0533b3d7a
--- /dev/null
+++ b/sdk/unreal/reference.mdx
@@ -0,0 +1,189 @@
+---
+title: "API Reference"
+description: "Complete reference of all Blueprint nodes, structs, enums, and delegates in the CometChat Unreal SDK."
+---
+
+This page is a single-stop reference for every public API surface in the CometChat Unreal SDK plugin.
+
+---
+
+## Subsystem Methods
+
+These are called directly on `UCometChatSubsystem`.
+
+| Method | Category | Parameters | Returns | Description |
+| ------ | -------- | ---------- | ------- | ----------- |
+| `Configure` | Config | `AppId: FString`, `Region: FString` | `void` | Initialize the SDK with your CometChat credentials. Must be called before Login. |
+| `IsLoggedIn` | Auth | — | `bool` | Returns `true` if a user is currently authenticated. |
+| `Shutdown` | Lifecycle | — | `void` | Tear down the SDK and release all resources. |
+
+---
+
+## Async Action Nodes
+
+Each node is a latent Blueprint action with **On Success** and **On Failure** output pins. In C++, create via the static factory method, bind delegates, and call `Activate()`.
+
+### Authentication
+
+| Node | Parameters | Success Output | Description |
+| ---- | ---------- | -------------- | ----------- |
+| **Login Async** | `Uid: FString`, `AuthKey: FString` | — | Authenticate a user with CometChat. |
+| **Logout Async** | — | — | Log out the current user and disconnect. |
+
+### Messaging
+
+| Node | Parameters | Success Output | Description |
+| ---- | ---------- | -------------- | ----------- |
+| **Send Message Async** | `ReceiverUid: FString`, `Text: FString` | `FCometChatMessage` | Send a 1:1 text message. |
+| **Send Group Message Async** | `Guid: FString`, `Text: FString` | `FCometChatMessage` | Send a text message to a group. |
+| **Get Messages Async** | `Uid: FString`, `Limit: int32` | `TArray` | Fetch message history for a 1:1 conversation. |
+| **Get Group Messages Async** | `Guid: FString`, `Limit: int32`, `BeforeMessageId: int32` | `TArray`, `FCometChatPagination` | Fetch paginated message history for a group. |
+
+### Users
+
+| Node | Parameters | Success Output | Description |
+| ---- | ---------- | -------------- | ----------- |
+| **Get User Async** | `Uid: FString` | `FCometChatUser` | Fetch a user's profile. |
+
+### Groups
+
+| Node | Parameters | Success Output | Description |
+| ---- | ---------- | -------------- | ----------- |
+| **Create Group Async** | `Name: FString`, `MemberIds: TArray` | `FCometChatGroup` | Create a new group with initial members. |
+| **Join Group Async** | `Guid: FString` | — | Join an existing group. |
+| **Leave Group Async** | `Guid: FString` | — | Leave a group. |
+
+---
+
+## Real-Time Delegates
+
+All delegates are `UPROPERTY(BlueprintAssignable)` on `UCometChatSubsystem`. They fire on the **Game Thread**.
+
+| Delegate | Payload Type | Fires When |
+| -------- | ------------ | ---------- |
+| `OnMessageReceived` | `FCometChatMessage` | A new message arrives (1:1 or group) |
+| `OnPresenceChanged` | `FCometChatPresence` | A user goes online, offline, or away |
+| `OnTypingChanged` | `FCometChatTypingEvent` | A user starts or stops typing |
+| `OnReceiptReceived` | `FCometChatReceiptEvent` | A message is delivered or read |
+| `OnConnectionStateChanged` | `ECometChatConnectionState` | WebSocket connection state changes |
+
+---
+
+## Structs
+
+### FCometChatUser
+
+| Property | Type | Description |
+| -------- | ---- | ----------- |
+| `Uid` | `FString` | Unique user identifier |
+| `Name` | `FString` | Display name |
+| `AvatarUrl` | `FString` | URL to avatar image |
+| `Status` | `FString` | Current status text |
+
+### FCometChatMessage
+
+| Property | Type | Description |
+| -------- | ---- | ----------- |
+| `Id` | `FString` | Unique message identifier |
+| `SenderUid` | `FString` | UID of the sender |
+| `ReceiverUid` | `FString` | UID of the receiver (user or group) |
+| `Text` | `FString` | Message body |
+| `SentAt` | `int64` | Unix timestamp when sent |
+| `Type` | `FString` | `text`, `image`, `file`, `custom` |
+| `Category` | `FString` | `message`, `action`, `call`, `custom` |
+| `ReceiverType` | `FString` | `user` or `group` |
+| `ConversationId` | `FString` | Conversation identifier |
+| `SenderName` | `FString` | Sender's display name |
+| `SenderAvatar` | `FString` | Sender's avatar URL |
+| `UpdatedAt` | `int64` | Unix timestamp of last update |
+
+### FCometChatGroup
+
+| Property | Type | Description |
+| -------- | ---- | ----------- |
+| `Guid` | `FString` | Unique group identifier |
+| `Name` | `FString` | Group display name |
+| `Description` | `FString` | Group description |
+| `MemberIds` | `TArray` | UIDs of group members |
+
+### FCometChatPagination
+
+| Property | Type | Description |
+| -------- | ---- | ----------- |
+| `Total` | `int32` | Total messages available |
+| `Count` | `int32` | Messages returned in this page |
+| `PerPage` | `int32` | Page size requested |
+| `CurrentPage` | `int32` | Current page number |
+| `TotalPages` | `int32` | Total pages available |
+| `HasMore` | `bool` | Whether more pages exist |
+| `NextCursor` | `int32` | Message ID for next page (`BeforeMessageId`) |
+
+### FCometChatPresence
+
+| Property | Type | Description |
+| -------- | ---- | ----------- |
+| `Uid` | `FString` | User identifier |
+| `Status` | `ECometChatPresenceStatus` | `Online`, `Offline`, or `Away` |
+| `LastActiveAt` | `int64` | Unix timestamp of last activity |
+
+### FCometChatTypingEvent
+
+| Property | Type | Description |
+| -------- | ---- | ----------- |
+| `Uid` | `FString` | User who is typing |
+| `ConversationId` | `FString` | Conversation where typing occurs |
+| `bIsTyping` | `bool` | `true` = started, `false` = stopped |
+
+### FCometChatReceiptEvent
+
+| Property | Type | Description |
+| -------- | ---- | ----------- |
+| `MessageId` | `FString` | The message this receipt is for |
+| `Uid` | `FString` | User who triggered the receipt |
+| `Status` | `FString` | `delivered` or `read` |
+| `Timestamp` | `int64` | Unix timestamp of the receipt |
+
+---
+
+## Enums
+
+### ECometChatConnectionState
+
+| Value | Description |
+| ----- | ----------- |
+| `Connected` | WebSocket is active |
+| `Disconnected` | WebSocket is closed |
+| `Reconnecting` | SDK is attempting to reconnect |
+
+### ECometChatPresenceStatus
+
+| Value | Description |
+| ----- | ----------- |
+| `Online` | User is currently active |
+| `Offline` | User is not connected |
+| `Away` | User is connected but idle |
+
+---
+
+## C++ Header Includes
+
+When working in C++, here are the headers you'll need:
+
+```cpp
+// Subsystem (always needed)
+#include "CometChatSubsystem.h"
+
+// Async action nodes (include as needed)
+#include "AsyncActions/CometChatLoginAction.h"
+#include "AsyncActions/CometChatLogoutAction.h"
+#include "AsyncActions/CometChatSendMessageAction.h"
+#include "AsyncActions/CometChatSendGroupMessageAction.h"
+#include "AsyncActions/CometChatGetMessagesAction.h"
+#include "AsyncActions/CometChatGetGroupMessagesAction.h"
+#include "AsyncActions/CometChatGetUserAction.h"
+#include "AsyncActions/CometChatCreateGroupAction.h"
+#include "AsyncActions/CometChatJoinGroupAction.h"
+#include "AsyncActions/CometChatLeaveGroupAction.h"
+```
+
+All types (`FCometChatUser`, `FCometChatMessage`, `FCometChatGroup`, etc.) are defined in `CometChatSubsystem.h`.
diff --git a/sdk/unreal/send-message.mdx b/sdk/unreal/send-message.mdx
new file mode 100644
index 000000000..d8b6c36ee
--- /dev/null
+++ b/sdk/unreal/send-message.mdx
@@ -0,0 +1,149 @@
+---
+title: "Send a Message"
+description: "Send text messages to users and groups from your Unreal Engine game."
+---
+
+Once a user is [logged in](/sdk/unreal/authentication), you can send text messages to other users (1:1) or to groups.
+
+### Message Flow
+
+```mermaid
+flowchart LR
+ A["Your Game"] --> B["Send Message Async"]
+ B --> C["C++ SDK"] --> D["CometChat Cloud"]
+ D --> E["Delivered to recipient"]
+ B -->|"On Success"| F["FCometChatMessage returned"]
+
+ style A fill:#333,stroke:#666,color:#fff
+ style B fill:#444,stroke:#888,color:#fff
+ style C fill:#333,stroke:#666,color:#fff
+ style D fill:#555,stroke:#999,color:#ccc
+ style E fill:#333,stroke:#666,color:#fff
+ style F fill:#333,stroke:#666,color:#fff
+```
+
+---
+
+## Send a User Message
+
+Send a text message to a specific user by their UID.
+
+
+
+1. Get a reference to the **CometChat Subsystem**
+2. Call the **Send Message Async** node
+3. Wire the **On Success** and **On Failure** pins
+
+| Parameter | Type | Description |
+| --------- | ---- | ----------- |
+| Receiver Uid | `FString` | The UID of the user to send the message to |
+| Text | `FString` | The message body |
+
+**On Success** returns an `FCometChatMessage` with the sent message details (including the server-assigned `Id` and `SentAt` timestamp).
+
+
+```cpp
+#include "AsyncActions/CometChatSendMessageAction.h"
+
+void AMyActor::SendDirectMessage()
+{
+ auto* Action = UCometChatSendMessageAction::SendMessageAsync(
+ this,
+ TEXT("cometchat-uid-2"), // Receiver UID
+ TEXT("Hey, want to play?") // Message text
+ );
+ Action->OnSuccess.AddDynamic(this, &AMyActor::OnMessageSent);
+ Action->OnFailure.AddDynamic(this, &AMyActor::OnMessageFailed);
+ Action->Activate();
+}
+
+void AMyActor::OnMessageSent(const FCometChatMessage& Message)
+{
+ UE_LOG(LogTemp, Log, TEXT("Message sent! ID: %s"), *Message.Id);
+}
+
+void AMyActor::OnMessageFailed(const FString& Error)
+{
+ UE_LOG(LogTemp, Error, TEXT("Send failed: %s"), *Error);
+}
+```
+
+
+
+---
+
+## Send a Group Message
+
+Send a text message to a group by its GUID.
+
+
+
+Call the **Send Group Message Async** node.
+
+| Parameter | Type | Description |
+| --------- | ---- | ----------- |
+| Guid | `FString` | The unique identifier of the target group |
+| Text | `FString` | The message body |
+
+**On Success** returns an `FCometChatMessage`.
+
+
+```cpp
+#include "AsyncActions/CometChatSendGroupMessageAction.h"
+
+void AMyActor::SendToGroup()
+{
+ auto* Action = UCometChatSendGroupMessageAction::SendGroupMessageAsync(
+ this,
+ TEXT("group-abc-123"), // Group GUID
+ TEXT("Team, ready up!") // Message text
+ );
+ Action->OnSuccess.AddDynamic(this, &AMyActor::OnGroupMessageSent);
+ Action->OnFailure.AddDynamic(this, &AMyActor::OnGroupMessageFailed);
+ Action->Activate();
+}
+
+void AMyActor::OnGroupMessageSent(const FCometChatMessage& Message)
+{
+ UE_LOG(LogTemp, Log, TEXT("Group message sent! ID: %s"), *Message.Id);
+}
+
+void AMyActor::OnGroupMessageFailed(const FString& Error)
+{
+ UE_LOG(LogTemp, Error, TEXT("Group send failed: %s"), *Error);
+}
+```
+
+
+
+---
+
+## The FCometChatMessage Struct
+
+Both send operations return an `FCometChatMessage` on success. Here's a quick reference of the key fields:
+
+| Property | Type | Description |
+| -------- | ---- | ----------- |
+| `Id` | `FString` | Server-assigned unique message ID |
+| `SenderUid` | `FString` | UID of the sender (the logged-in user) |
+| `ReceiverUid` | `FString` | UID of the receiver (user UID or group GUID) |
+| `Text` | `FString` | The message body |
+| `SentAt` | `int64` | Unix timestamp when the message was sent |
+| `Type` | `FString` | `text` for text messages |
+| `ReceiverType` | `FString` | `user` for 1:1, `group` for group messages |
+| `ConversationId` | `FString` | Unique conversation identifier |
+
+For the full struct definition, see [Key Concepts → FCometChatMessage](/sdk/unreal/key-concepts#fchatmessage).
+
+---
+
+## Next Steps
+
+
+
+ Fetch message history and listen for incoming messages in real time.
+
+
+ Create and manage groups before sending group messages.
+
+
diff --git a/sdk/unreal/setup.mdx b/sdk/unreal/setup.mdx
new file mode 100644
index 000000000..12168bc56
--- /dev/null
+++ b/sdk/unreal/setup.mdx
@@ -0,0 +1,141 @@
+---
+title: "Setup"
+description: "Install the CometChat plugin in your Unreal Engine project."
+---
+
+## Get your Application Keys
+
+[Sign up for CometChat](https://app.cometchat.com) and then:
+
+1. Create a new app
+2. Head over to the **API & Auth Keys** section and note the **Auth Key**, **App ID**, and **Region**
+
+
+**Minimum Requirements**
+
+- Unreal Engine **5.3** or higher
+- C++17 compatible compiler
+- Windows (Win64), macOS, Linux, iOS, or Android target
+
+
+---
+
+## Install the Plugin
+
+### Option 1: Pre-built Plugin (Recommended)
+
+Copy the `CometChat` plugin folder into your project's `Plugins/` directory:
+
+```
+YourProject/
+├── Plugins/
+│ └── CometChat/
+│ ├── CometChat.uplugin
+│ ├── Source/
+│ ├── Config/
+│ └── ThirdParty/
+├── Source/
+└── YourProject.uproject
+```
+
+Then regenerate your project files:
+
+
+
+```bash
+# From your project root
+/Users/Shared/Epic\ Games/UE_5.4/Engine/Build/BatchFiles/Mac/GenerateProjectFiles.sh \
+ -project="$(pwd)/YourProject.uproject" -game -engine
+```
+
+
+```powershell
+# From your project root
+& "C:\Program Files\Epic Games\UE_5.4\Engine\Build\BatchFiles\GenerateProjectFiles.bat" ^
+ -project="%cd%\YourProject.uproject" -game -engine
+```
+
+
+
+---
+
+## Add Module Dependency
+
+In your game module's `.Build.cs` file, add the `CometChat` module as a dependency:
+
+```csharp
+using UnrealBuildTool;
+
+public class YourGame : ModuleRules
+{
+ public YourGame(ReadOnlyTargetRules Target) : base(Target)
+ {
+ PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs;
+
+ PublicDependencyModuleNames.AddRange(new string[]
+ {
+ "Core",
+ "CoreUObject",
+ "Engine",
+ "CometChat" // Add this line
+ });
+ }
+}
+```
+
+---
+
+## Verify the Plugin
+
+After regenerating project files and building:
+
+1. Open your project in the Unreal Editor
+2. Go to **Edit → Plugins**
+3. Search for **CometChat** — it should appear under the **Networking** category and be enabled
+
+
+The plugin loads at the **PreDefault** phase, so it's available before your game module initializes.
+
+
+---
+
+## Initialize CometChat
+
+The `CometChatSubsystem` is a `UGameInstanceSubsystem` — it's created automatically when your game starts. You just need to call **Configure** with your App ID and Region before using any other SDK methods.
+
+
+
+1. In any Blueprint, get a reference to the **CometChat Subsystem** via `Get Game Instance` → `Get Subsystem` → select `CometChatSubsystem`
+2. Call the **Configure** node with your **App ID** and **Region**
+
+| Parameter | Type | Description |
+| --------- | ---- | ----------- |
+| App Id | `FString` | Your CometChat App ID |
+| Region | `FString` | Your app region (`us` or `eu`) |
+
+
+```cpp
+#include "CometChatSubsystem.h"
+
+void AMyActor::BeginPlay()
+{
+ Super::BeginPlay();
+
+ UCometChatSubsystem* Chat = GetGameInstance()->GetSubsystem();
+ Chat->Configure(TEXT("YOUR_APP_ID"), TEXT("us"));
+}
+```
+
+
+
+
+**Configure must be called before Login.** Calling Login without configuring first will result in a failure callback.
+
+
+Make sure you replace `YOUR_APP_ID` with your actual CometChat **App ID**.
+
+---
+
+## Next Steps
+
+Now that the plugin is installed and configured, head to [Authentication](/sdk/unreal/authentication) to log in your first user.
diff --git a/sdk/unreal/typing-indicators.mdx b/sdk/unreal/typing-indicators.mdx
new file mode 100644
index 000000000..692418233
--- /dev/null
+++ b/sdk/unreal/typing-indicators.mdx
@@ -0,0 +1,73 @@
+---
+title: "Typing Indicators"
+description: "Show real-time typing indicators when users are composing messages."
+---
+
+Typing indicators let you show a "user is typing..." animation in your chat UI. The CometChat Unreal SDK delivers these as real-time events through the `OnTypingChanged` delegate.
+
+---
+
+## Listen for Typing Events
+
+Bind to the `OnTypingChanged` delegate on the Subsystem to receive typing start/stop notifications.
+
+
+
+1. Get a reference to the **CometChat Subsystem**
+2. Drag off and search for **On Typing Changed**
+3. Use **Bind Event** to connect it to a custom event
+4. The custom event receives an `FCometChatTypingEvent` parameter
+
+
+```cpp
+void AMyActor::BeginPlay()
+{
+ Super::BeginPlay();
+
+ UCometChatSubsystem* Chat = GetGameInstance()->GetSubsystem();
+ Chat->OnTypingChanged.AddDynamic(this, &AMyActor::HandleTyping);
+}
+
+void AMyActor::HandleTyping(const FCometChatTypingEvent& Event)
+{
+ if (Event.bIsTyping)
+ {
+ // Show typing indicator for this user/conversation
+ ShowTypingBubble(Event.Uid, Event.ConversationId);
+ }
+ else
+ {
+ // Hide typing indicator
+ HideTypingBubble(Event.Uid, Event.ConversationId);
+ }
+}
+```
+
+
+
+---
+
+## FCometChatTypingEvent
+
+| Property | Type | Description |
+| -------- | ---- | ----------- |
+| `Uid` | `FString` | The user who started or stopped typing |
+| `ConversationId` | `FString` | The conversation where typing is happening |
+| `bIsTyping` | `bool` | `true` when the user starts typing, `false` when they stop |
+
+
+**UI pattern**: When `bIsTyping` is `true`, show a typing animation (e.g., three bouncing dots). When `false`, hide it. Consider adding a timeout (e.g., 5 seconds) to auto-hide the indicator in case the stop event is missed.
+
+
+---
+
+## Next Steps
+
+
+
+ Track when messages are delivered and read.
+
+
+ Monitor the WebSocket connection state.
+
+
diff --git a/sdk/unreal/users.mdx b/sdk/unreal/users.mdx
new file mode 100644
index 000000000..17b4d7031
--- /dev/null
+++ b/sdk/unreal/users.mdx
@@ -0,0 +1,130 @@
+---
+title: "Users"
+description: "Fetch user profiles and track user presence in real time."
+---
+
+## Get User
+
+Retrieve a user's profile by their UID.
+
+
+
+Call the **Get User Async** node.
+
+| Parameter | Type | Description |
+| --------- | ---- | ----------- |
+| Uid | `FString` | The unique identifier of the user to fetch |
+
+**On Success** returns an `FCometChatUser`.
+
+
+```cpp
+#include "AsyncActions/CometChatGetUserAction.h"
+
+void AMyActor::FetchUser()
+{
+ auto* Action = UCometChatGetUserAction::GetUserAsync(
+ this,
+ TEXT("cometchat-uid-2")
+ );
+ Action->OnSuccess.AddDynamic(this, &AMyActor::OnUserFetched);
+ Action->OnFailure.AddDynamic(this, &AMyActor::OnUserFetchFailed);
+ Action->Activate();
+}
+
+void AMyActor::OnUserFetched(const FCometChatUser& User)
+{
+ UE_LOG(LogTemp, Log, TEXT("User: %s (%s)"), *User.Name, *User.Status);
+}
+
+void AMyActor::OnUserFetchFailed(const FString& Error)
+{
+ UE_LOG(LogTemp, Error, TEXT("Fetch user failed: %s"), *Error);
+}
+```
+
+
+
+### FCometChatUser Properties
+
+| Property | Type | Description |
+| -------- | ---- | ----------- |
+| `Uid` | `FString` | Unique user identifier |
+| `Name` | `FString` | Display name |
+| `AvatarUrl` | `FString` | URL to the user's avatar image |
+| `Status` | `FString` | Current status text |
+
+---
+
+## User Presence
+
+Track when users come online, go offline, or go away by binding to the `OnPresenceChanged` delegate on the Subsystem.
+
+
+
+1. Get a reference to the **CometChat Subsystem**
+2. Drag off and search for **On Presence Changed**
+3. Use **Bind Event** to connect it to a custom event
+4. The custom event receives an `FCometChatPresence` parameter
+
+
+```cpp
+void AMyActor::BeginPlay()
+{
+ Super::BeginPlay();
+
+ UCometChatSubsystem* Chat = GetGameInstance()->GetSubsystem();
+ Chat->OnPresenceChanged.AddDynamic(this, &AMyActor::HandlePresence);
+}
+
+void AMyActor::HandlePresence(const FCometChatPresence& Presence)
+{
+ switch (Presence.Status)
+ {
+ case ECometChatPresenceStatus::Online:
+ UE_LOG(LogTemp, Log, TEXT("%s is online"), *Presence.Uid);
+ break;
+ case ECometChatPresenceStatus::Offline:
+ UE_LOG(LogTemp, Log, TEXT("%s went offline"), *Presence.Uid);
+ break;
+ case ECometChatPresenceStatus::Away:
+ UE_LOG(LogTemp, Log, TEXT("%s is away"), *Presence.Uid);
+ break;
+ }
+}
+```
+
+
+
+### FCometChatPresence Properties
+
+| Property | Type | Description |
+| -------- | ---- | ----------- |
+| `Uid` | `FString` | The user whose presence changed |
+| `Status` | `ECometChatPresenceStatus` | `Online`, `Offline`, or `Away` |
+| `LastActiveAt` | `int64` | Unix timestamp of the user's last activity |
+
+### ECometChatPresenceStatus
+
+| Value | Description |
+| ----- | ----------- |
+| `Online` | User is currently active |
+| `Offline` | User is not connected |
+| `Away` | User is connected but idle |
+
+
+Use presence data to show green/gray status dots next to player names in your friends list or lobby UI.
+
+
+---
+
+## Next Steps
+
+
+
+ Create, join, and manage groups.
+
+
+ All five real-time delegates in one place.
+
+