---
source_url: https://www.pubnub.com/docs/sdks/java/api-reference/message-actions
title: Message Actions API for Java SDK
updated_at: 2026-06-19T11:37:27.460Z
sdk_name: PubNub Java SDK
sdk_version: 6.4.5
---

> Documentation Index
> For a curated overview of PubNub documentation, see: https://www.pubnub.com/docs/llms.txt
> For the full list of all documentation pages, see: https://www.pubnub.com/docs/llms-full.txt


# Message Actions API for Java SDK

PubNub Java SDK, use the latest version: 6.4.5

Install:

```bash
Add PubNub dependency to your build@6.4.5
```

:::warning Breaking changes in v9.0.0
PubNub Java SDK version 9.0.0 unifies the codebases for Java and [Kotlin](https://www.pubnub.com/docs/sdks/kotlin) SDKs, introduces a new way of instantiating the PubNub client, and changes asynchronous API callbacks and emitted [status events](https://www.pubnub.com/docs/sdks/java/status-events). These changes can impact applications built with previous versions (< `9.0.0`) of the Java SDK.
For more details about what has changed, refer to [Java/Kotlin SDK migration guide](https://www.pubnub.com/docs/sdks/kotlin/migration-guides/kotlin-v9-migration-guide).
:::

Use message actions to add or remove metadata on published messages. Common uses include receipts and reactions. Clients subscribe to a channel to receive message action events. Clients can also fetch past message actions from Message Persistence, either on demand or when fetching original messages.

:::tip Reactions
"Message Reactions" is a specific application of the Message Actions API for emoji or social reactions.
:::

:::note Message Actions vs. Message Reactions
**Message Actions** is the flexible, low-level API for adding any metadata to messages (read receipts, delivery confirmations, custom data), while **Message Reactions** specifically refers to using Message Actions for emoji/social reactions.
In PubNub [Core](https://www.pubnub.com/docs/sdks) and [Chat](https://www.pubnub.com/docs/chat/overview) SDKs, the same underlying Message Actions API is referred to as **Message Reactions** when used for emoji reactions - it's the same functionality, just different terminology depending on the use case.
:::

## Add message action

:::warning Requires Message Persistence
Enable Message Persistence for your key in the [Admin Portal](https://admin.pubnub.com/) as described in the [support article](https://support.pubnub.com/hc/en-us/articles/360051974791-How-do-I-enable-add-on-features-for-my-keys-).
:::

Add an action to a published message. The response includes the added action.

### Method(s)

Use this Java method:

```java
this.pubnub.addMessageAction()
    .channel(String)
    .messageAction(PNMessageAction);
```

| Parameter | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| channel | String | Yes |  | Channel name to add the message action to. |
| messageAction | PNMessageAction | Yes |  | Message action payload (type, value, message timetoken). |
| async | Consumer<Result> | Yes |  | Callback of type `PNAddMessageActionResult`. |

### Sample code

:::tip Reference code
This example is a self-contained code snippet ready to be run. It includes necessary imports and executes methods with console logging. Use it as a reference when working with other examples in this document.
:::

```java
import com.pubnub.api.PubNubException;
import com.pubnub.api.java.PubNub;
import com.pubnub.api.java.v2.PNConfiguration;
import com.pubnub.api.UserId;
import com.pubnub.api.models.consumer.message_actions.PNMessageAction;

public class MessageReactionsApp {
    public static void main(String[] args) throws PubNubException {
        // Configure PubNub instance
        PNConfiguration.Builder configBuilder = PNConfiguration.builder(new UserId("demoUserId"), "demo");
        configBuilder.publishKey("demo");
        configBuilder.secure(true);

        PubNub pubnub = PubNub.create(configBuilder.build());

        // Create a message action
        PNMessageAction messageAction = new PNMessageAction()
                .setType("reaction")
                .setValue("smiley_face")
                .setMessageTimetoken(15701761818730000L); // Replace with actual message timetoken

        // Add message action
        pubnub.addMessageAction()
                .channel("my_channel")
                .messageAction(messageAction)
                .async(result -> {
                    result.onSuccess(res -> {
                        System.out.println("Type: " + res.getType());
                        System.out.println("Value: " + res.getValue());
                        System.out.println("UUID: " + res.getUuid());
                        System.out.println("Action Timetoken: " + res.getActionTimetoken());
                        System.out.println("Message Timetoken: " + res.getMessageTimetoken());
                    }).onFailure(exception -> {
                        System.out.println("Error adding message action: " + exception.getMessage());
                    });
                });
    }
}
```

### Returns

The `addMessageAction()` operation returns a `PNAddMessageActionResult`:

| Method | Description |
| --- | --- |
| `getType()`Type: `String` | Message action type. |
| `getValue()`Type: `String` | Message action value. |
| `getUuid()`Type: `String` | Publisher of the message action. |
| `getActionTimetoken()`Type: `Long` | Timestamp when the message action was created. |
| `getMessageTimetoken()`Type: `Long` | Timestamp when the message was created that the action belongs to. |

#### PNMessageAction

| Method | Description |
| --- | --- |
| `setType()`Type: `String` | Message action type. |
| `setValue()`Type: `String` | Message action value. |
| `setMessageTimetoken()`Type: `Long` | Timetoken of the target message. |

## Remove message action

:::warning Requires Message Persistence
Enable Message Persistence for your key in the [Admin Portal](https://admin.pubnub.com/) as described in the [support article](https://support.pubnub.com/hc/en-us/articles/360051974791-How-do-I-enable-add-on-features-for-my-keys-).
:::

Remove a previously added action from a published message. The response is empty.

### Method(s)

Use this Java method:

```java
this.pubnub.removeMessageAction()
    .channel(String)
    .messageTimetoken(Long)
    .actionTimetoken(Long);
```

| Parameter | Description |
| --- | --- |
| `channel` *Type: String | Channel name to remove the message action from. |
| `messageTimetoken` *Type: Long | Timetoken of the target message. |
| `actionTimetoken` *Type: Long | Timetoken of the message action to remove. |
| `async` *Type: `Consumer<Result>` | Callback of type `PNRemoveMessageActionResult`. |

### Sample code

```java
pubNub.removeMessageAction()
        .channel("my_channel")
        .messageTimetoken(15701761818730000L)
        .actionTimetoken(15701775691010000L)
        .async(result -> { /* check result */ });
```

### Returns

The `removeMessageAction()` operation returns no actionable data.

## Get message actions

:::warning Requires Message Persistence
Enable Message Persistence for your key in the [Admin Portal](https://admin.pubnub.com/) as described in the [support article](https://support.pubnub.com/hc/en-us/articles/360051974791-How-do-I-enable-add-on-features-for-my-keys-).
:::

Get a list of message actions in a channel. The response sorts actions by the action timetoken in ascending order.

:::note Truncated response
The number of message actions in the response may be truncated when internal limits are hit. If the response is truncated, a `more` property is returned with additional parameters. Send iterative calls to Message Persistence, adjusting the parameters to fetch more message actions.
:::

### Method(s)

Use this Java method:

```java
this.pubnub.getMessageActions()
    .channel(String)
    .start(Long)
    .end(Long)
    .limit(Integer);
```

| Parameter | Description |
| --- | --- |
| `channel` *Type: StringDefault: n/a | Channel name to list message actions for. |
| `start`Type: LongDefault: n/a | Message action timetoken for the start of the range (exclusive). |
| `end`Type: LongDefault: n/a | Message action timetoken for the end of the range (inclusive). |
| `limit`Type: IntegerDefault: 100 | Maximum number of actions to return. Default/Maximum is `100`. |
| `async` *Type: `Consumer<Result>`Default: n/a | Callback of type `PNGetMessageActionsResult`. |

### Sample code

```java
pubNub.getMessageActions()
        .channel("my_channel")
        .async(result -> {
            result.onSuccess(res -> {
                List<PNMessageAction> actions = res.getActions();
                for (PNMessageAction action : actions) {
                    System.out.println(action.getType());
                    System.out.println(action.getValue());
                    System.out.println(action.getUuid());
                    System.out.println(action.getActionTimetoken());
                    System.out.println(action.getMessageTimetoken());
                }
            }).onFailure(exception -> {
                exception.printStackTrace();
            });
        });
```

### Returns

The `getMessageActions()` operation returns a list of `PNGetMessageActionsResult` objects:

| Method | Description |
| --- | --- |
| `getType()`Type: `String` | Message action type. |
| `getValue()`Type: `String` | Message action value. |
| `getUuid()`Type: `String` | Publisher of the message action. |
| `getActionTimetoken()`Type: `Long` | Timestamp when the message action was created. |
| `getMessageTimetoken()`Type: `Long` | Timestamp when the message was created that the action belongs to. |

### Other examples

#### Fetch messages with paging

```java
import com.pubnub.api.PubNubException;
import com.pubnub.api.UserId;
import com.pubnub.api.java.PubNub;
import com.pubnub.api.java.v2.PNConfiguration;
import com.pubnub.api.models.consumer.message_actions.PNMessageAction;

import java.util.List;
import java.util.function.Consumer;

public class GetMessageActionsWithPagingApp {

    public static void main(String[] args) {
        long startTimetoken = System.currentTimeMillis() * 10_000L;
        getAllMessageActions(
                "my_channel",
                startTimetoken,
                actions -> System.out.println("Next set of actions: " + actions.size())
        );
    }

    /**
     * Fetches 5 message reactions at a time, recursively and in a paged manner.
     *
     * @param channel  The channel where the message is published, to fetch message reactions from.
     * @param start    The timetoken which indicates from where to start fetching message reactions.
     * @param callback Consumer to handle each page of fetched message actions.
     */
    private static void getAllMessageActions(
            String channel,
            long start,
            Consumer<List<PNMessageAction>> callback
    ) {
        UserId userId;
        try {
            userId = new UserId("demoUserId");
        } catch (PubNubException e) {
            throw new RuntimeException(e);
        }
        PNConfiguration config = PNConfiguration.builder(userId, "demo")
                .publishKey("demo")
                .secure(true)
                .build();

        PubNub pubnub = PubNub.create(config);

        pubnub.getMessageActions()
                .channel(channel)
                .start(start)
                .limit(5)
                .async(result -> result
                        .onSuccess(res -> {
                            if (!res.getActions().isEmpty()) {
                                callback.accept(res.getActions());
                                getAllMessageActions(
                                        channel,
                                        res.getActions().get(0).getActionTimetoken(),
                                        callback
                                );
                            }
                        })
                        .onFailure((PubNubException exception) -> {
                            // handle error
                            System.err.println("Fetch error: " + exception.getMessage());
                        })
                );
    }
}
```

## Terms in this document

* **Channel** - A pathway for sending and receiving messages between devices, created automatically when you first use it, that can handle any number of users and messages for different communication needs, like 1-1 text chats, group conversations, and other data streaming.
* **Channel pattern** - A way to group and analyze channel data to track performance metrics like message counts and user engagement over time with PubNub Insights.