---
source_url: https://www.pubnub.com/docs/release-notes/2024/november
title: Documentation Release Notes - November 2024
updated_at: 2026-06-04T11:10:45.282Z
---

> 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


# Documentation Release Notes - November 2024

As the November chill sets in and the pace slows down, we're warming things up with some exciting updates.

In the world of SDKs, we've introduced message drafts in our Kotlin and Swift mobile chat SDKs. You can now create and tweak your messages before hitting send! Plus, we've added support for custom message types across multiple APIs, making it easier than ever to organize your messages.

For those using our JavaScript SDK, you'll love the new shared workers feature, which helps manage connections and keeps your data consistent across multiple windows. We've also added tree shaking to help cut down on functionalities you don't need and speed up load times.

The Publish API got a little enhancement too – we now accept floating-point numbers for the TTL parameter, giving you more precision in message expiration.

What's more, we've finally documented all the roles and permissions you can assign in the Admin Portal. This means you can now easily see who has access to what and manage permissions smoothly.

Finally, our Insights and BizOps tools are working more closely together. You can now export top user and channel data directly from Insights to BizOps, making data management easier than ever.

See what’s new!

## General 🛠️

### Roles & permissions in Admin Portal

**Type**: Update

We've finally documented all the [roles](https://www.pubnub.com/docs/portal/my-account#members-and-roles) you can assign to your organization members in the Admin Portal. Each role grants a different set of permissions, allowing general access on various levels or restricting access to specific features, like Functions, BizOps, or Illuminate.

## SDKs 📦

### Message drafts in mobile Chat SDKs

**Type**: New feature

As of this month, [Kotlin](https://www.pubnub.com/docs/chat/kotlin-chat-sdk/build/features/messages/drafts) and [Swift](https://www.pubnub.com/docs/chat/swift-chat-sdk/build/features/messages/drafts) Chat SDKs support message drafts. The new functionality lets you create, edit, and manage messages before sending them in a chat application.

The integral message elements listener handles any changes in the draft message, including plain text, user mentions (`@sue`), channel references (`#channel`), or links, and lets you display these message elements to users.

#### Kotlin

```kotlin
// Create an empty message draft
val messageDraft = channel.createMessageDraft(isTypingIndicatorTriggered = channel.type != ChannelType.PUBLIC)

// Add a text
messageDraft.update(text = "Hello Alex!")

// Add a user mention to the string 'Alex'
messageDraft.addMention(offset = 6, length = 4, target = MentionTarget.User(userId = "alex_d"))

// Change the text
messageDraft.update(text = "Hello Alex! I have sent you this link on the #offtopic channel.")

// Add a link to the string 'link'
messageDraft.addMention(offset = 33, length = 4, target = MentionTarget.Url(url = "www.pubnub.com"))

// Add a channel mention to the string '#offtopic'
messageDraft.addMention(offset = 45, length = 9, target = MentionTarget.Channel(channelId = "group.offtopic"))
```

#### Swift

```swift
// Create an empty message draft
if let messageDraft = channel?.createMessageDraft(isTypingIndicatorTriggered: channel?.type != .public) {

    // Add initial text
    messageDraft.update(text: "Hello Alex!")

    // Add a user mention to the string "Alex"
    messageDraft.addMention(offset: 6, length: 4, target: .user(userId: "alex_d"))
    
    // Change the text
    messageDraft.update(text: "Hello Alex! I have sent you this link on the #offtopic channel.")

    // Add a URL mention to the string "link"
    messageDraft.addMention(offset: 33, length: 4, target: .url(url: "www.pubnub.com"))

    // Add a channel mention to the string "#offtopic"
    messageDraft.addMention(offset: 45, length: 9, target: .channel(channelId: "group.offtopic"))
}
```

:::note Local storage
Drafts do not automatically save locally. If you switch channels, the draft will be lost unless you implement your own storage solution to keep it saved.
:::

### Custom message type

**Type**: New feature

[Last month](https://www.pubnub.com/docs/release-notes/2024/october#custom-message-type-in-rest-api), we mentioned a plan to introduce a message type parameter in SDKs to categorize messages. Following the updates in the REST API from last month, we now added support for the message type parameter in Publish, Subscribe, Message Persistence, and Files APIs in the following SDKs:

#### JavaScript

```js
try {
    const result = await pubnub.publish({
        message: {
            such: "object",
        },
        channel: "my_channel",
        sendByPost: false, // true to send via post
        storeInHistory: false, //override default Message Persistence options
        meta: {
            cool: "meta",
        }, // publish extra meta with the request
        customMessageType: "text-message",
    });
} catch (status) {
    console.log(status);
}
```

#### Kotlin

```kotlin
val configBuilder = com.pubnub.api.v2.PNConfiguration.builder(UserId("myUserId"), "demo").apply {
    publishKey = "demo"
}
val pubnub = PubNub.create(configBuilder.build())

val channel = pubnub.channel("myChannel")

val myMessage = JsonObject().apply {
    addProperty("lat", 32L)
    addProperty("lng", 32L)
}

channel.publish(
    message = myMessage, 
    customMessageType = "text-message"
).async { result ->
    result.onFailure { exception ->
        println("Error while publishing")
        exception.printStackTrace()
    }.onSuccess { value ->
        println("Message sent, timetoken: ${value.timetoken}")
    }
}
```

#### Java

```java
PNConfiguration.Builder configBuilder = PNConfiguration.builder(new UserId("yourUserId"), "demo");
configBuilder.publishKey("demo");

PNConfiguration pnConfiguration = configBuilder.build();
PubNub pubnub = PubNub.create(pnConfiguration);
Channel channel = pubnub.channel("myChannel");

JsonObject position = new JsonObject();
position.addProperty("lat", 32L);
position.addProperty("lng", 32L);

System.out.println("before pub: " + position);
channel.publish(position)
    .customMessageType("text-message")
    .async(result -> {
        result.onSuccess(res -> {
            System.out.println("pub timetoken: " + res.getTimetoken());
        });
    });
```

#### Swift

```swift
pubnub.publish(
  channel: "my-channel",
  message: "Hello from PubNub Swift SDK",
  customMessageType: "text-message"
) { result in
  switch result {
  case let .success(timetoken):
    print("Message Successfully Published at: \(timetoken)")
  case let .failure(error):
    print("Failed Response: \(error.localizedDescription)")
  }
}
```

#### Objective-C

```objectivec
self.client.publish()
    .channel(@"my_channel")
    .message(@"Hello from PubNub iOS!")
    .shouldStore(YES)
    .ttl(16)
    .customMessageType(@"text-message")
    .performWithCompletion(^(PNPublishStatus *status) {

    if (!status.isError) {

        // Message successfully published to specified channel.
    }
    else {

        /**
         Handle message publish error. Check 'category' property to find
         out possible reason because of which request did fail.
         Review 'errorData' property (which has PNErrorData data type) of status
         object to get additional information about issue.

         Request can be resent using: [status retry];
         */
    }
});
```

#### Python

```python
from pubnub.exceptions import PubNubException
try:
    envelope = pubnub.publish().channel("my_channel") \
    .message({ 
        'name': 'Alex',
        'online': True
    }) \
    .custom_message_type("text-message") \
    .sync()
    print("publish timetoken: %d" % envelope.result.timetoken)
except PubNubException as e:
    handle_exception(e)
```

#### PHP

```php
$result = $pubnub->publish()
    ->channel("my_channel")
    ->message(["hello", "there"])
    ->shouldStore(true)
    ->ttl(15)
    ->usePost(true)
    ->customMessageType("file-message")
    ->sync();
```

#### Unreal

```cpp
#include "Kismet/GameplayStatics.h"
#include "PubnubSubsystem.h"

UGameInstance* GameInstance = UGameplayStatics::GetGameInstance(this);
UPubnubSubsystem* PubnubSubsystem = GameInstance->GetSubsystem<UPubnubSubsystem>();

FString Channel = "randomChannel";
FString Message = "{ \"text\" : \"This is my message\" }";

// Create an instance of FPubnubPublishSettings
FPubnubPublishSettings PublishSettings;
PublishSettings.CustomMessageType = "text-message"; // Set the CustomMessageType

// Publish the message with custom publish settings
PubnubSubsystem->PublishMessage(ChannelName, Message, PublishSettings);
```

Read [Message Types](https://www.pubnub.com/docs/general/messages/type) for an overview of the new parameter and information on how it differs from the internal PubNub message type.

### Unreal SDK JSON wrappers

**Type**: Improvement

Until now, all functions that provide server data like `GetChannelMetadata()` or `FetchHistory()` returned a JSON string, which may be difficult to handle due to the complex structure and possible parsing and debugging issues. That's why we decided to support an additional format of returned data and introduced output wrappers (custom structs) to encapsulate data in a more structured and type-safe way.

```cpp
PubnubSubsystem->FetchHistory(
    FString Channel, 
    FOnFetchHistoryResponse OnFetchHistoryResponse, 
    FPubnubFetchHistorySettings FetchHistorySettings = FPubnubFetchHistorySettings()
);
```

:::tip Response variants
You can also call the `{MethodName}_JSON()` variant of each such method to get a `FOnPubnubResponse`, which contains pure JSON, like `FetchHistory_JSON()`.
:::

### Shared workers in JS SDK

**Type**: New feature

We introduced a new [shared workers](https://www.pubnub.com/docs/sdks/javascript/api-reference/configuration#shared-workers) configuration option in the JavaScript SDK to help you:

* Manage concurrent connections across multiple client instances.
* Reduce redundant operations such as multiple long-poll subscriptions by aggregating requests across multiple contexts.
* Prevent false presence events by ensuring that `leave` events are only triggered when all associated tabs and windows are closed.
* Coordinate shared data or state across different parts of an application running in separate contexts (like collaborative editing, shared state management, or ensuring data consistency across different views or interfaces).

The shared worker source must be hosted under the exact origin as the client app, following the [Same-origin Policy](https://developer.mozilla.org/en-US/docs/Web/Security/Same-origin_policy).

To use shared workers, configure the `subscriptionWorkerUrl` parameter in the PubNub client during initialization:

```js
const pubnub = new PubNub({
  subscribeKey: "demo",
  publishKey: "demo",
  userId: "unique-user-id",
  // using PubNub JS SDK v8.3.1, make sure the versions match
  subscriptionWorkerUrl: 'https://www.my-domain.com/static/js/pubnub.worker.8.3.1.js'
});
```

### Tree shaking in JS SDK

**Type**: New feature

The JS SDK now lets you opt out of specific modules you don't need and optimize the final bundle size. You can do that by using either of two popular JavaScript build tools: [Rollup](https://rollupjs.org/) or [Webpack](https://webpack.js.org/).

By only including the necessary modules and excluding the ones that aren't used, the application becomes more efficient and faster to load.

Refer to the [Configuration](https://www.pubnub.com/docs/sdks/javascript/api-reference/configuration#bundling) doc for details.

### TTL in publish API accepts floats

**Type**: Enhancement

We extended the scope of the time-to-live (`ttl`) parameter, which you can use in [Publish API](https://www.pubnub.com/docs/sdks/rest-api/publish-message-to-channel) calls to override the TTL value for Message Persistence set on your keyset.

`ttl` now accepts both integer (like `1` = 1 hour) and floating-point (`0.5` = 30 minutes) numbers.

```curl
curl -L 'https://ps.pndsn.com/publish/demo/demo/0/channel/myCallback/%7B%22text%22%3A%22PubNub%20is%20awesome!%22%7D?uuid=user&ttl=0.5' \
-H 'Accept: application/json'
```

## Insights 📊

### Insights & BizOps collab

**Type**: New feature

Back in June, we communicated a new [Import from Insights](https://www.pubnub.com/docs/release-notes/2024/june#top-20-userschannels) feature in BizOps Workspace that let you automatically import top 20 users and channels from Insights directly to your User and Channel Management views.

This time, we mirrored this functionality on the Insights end, letting you **Export to BizOps** top 20 data for [users](https://www.pubnub.com/docs/pubnub-insights/dashboards/users#insights--bizops) and [channels](https://www.pubnub.com/docs/pubnub-insights/dashboards/channels#insights--bizops).

![Export data to BizOps](https://www.pubnub.com/assets/images/export-data-to-bizops-1868176d0bbb13a1e00e6b3061e269fc.png)

In addition, the new embedded links in the **Top 20 Users** and **Top 20 Channels** tables let you view the details of individual users and channels in BizOps Workspace.

![View data in BizOps](https://www.pubnub.com/assets/images/view-data-in-bizops-537980be1fbdb5f3acd5d7f02663c814.png)