---
source_url: https://www.pubnub.com/docs/sdks/javascript/api-reference/message-actions
title: Message Actions API for JavaScript SDK
updated_at: 2026-06-25T11:22:35.000Z
sdk_name: PubNub JavaScript SDK
sdk_version: 13.0.3
---

# Message Actions API for JavaScript SDK

PubNub JavaScript SDK, use the latest version: 13.0.3

Install:

```bash
npm install pubnub@13.0.3
```

> For AI agents: documentation index at https://www.pubnub.com/llms-full.txt

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.

:::note Supported and recommended asynchronous patterns
PubNub supports [Callbacks, Promises, and Async/Await](https://javascript.info/async) for asynchronous JS operations. The recommended pattern is Async/Await and all sample requests in this document are based on it. This pattern returns a status only on detecting an error. To receive the error status, you must add the [try...catch](https://javascript.info/try-catch) syntax to your code.
:::

:::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.md) and [Chat](https://www.pubnub.com/docs/chat/overview.md) 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 JavaScript method:

```javascript
addMessageAction({
    channel: string,
    messageTimetoken: string,
    action: {type: string, value: string}
})
```

| Parameter | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| channel | string | Yes |  | Channel name of the target message. |
| messageTimetoken | string | Yes |  | Timetoken of the target message. |
| action | Hash | Yes |  | Message action payload. |
| action.type | string | Yes |  | Message action type. |
| action.value | string | Yes |  | Message action value. |

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

```javascript
import PubNub from 'pubnub';
// Initialize PubNub with your keys
const pubnub = new PubNub({
  publishKey: 'YOUR_PUBLISH_KEY',
  subscribeKey: 'YOUR_SUBSCRIBE_KEY',
  userId: 'YOUR_USER_ID',
});
```

```javascript
// first publish a message using publish() method to get the message timetoken
try {
  const response = await pubnub.addMessageAction({
    channel: 'channel_name',
    messageTimetoken: 'replace_with_message_timetoken', // Replace with actual message timetoken
    action: {
      type: 'reaction',
      value: 'smiley_face',
    },
  });
  console.log('Message reaction added successfully:', response);
} catch (error) {
  console.error(
    `Error adding reaction: ${error}.${
      (error as PubNubError).status ? ` Additional information: ${(error as PubNubError).status}` : ''
    }`,
  );
}
```

### Returns

```json
// Example of status
{
    "error": false,
    "operation": "PNAddMessageActionOperation",
    "statusCode": 200
}

// Example of response
{
    "data": {
        "type": "reaction",
        "value": "smiley_face",
        "uuid": "user-456",
        "actionTimetoken": "15610547826970050",
        "messageTimetoken": "15610547826969050"
    }
}
```

## 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 JavaScript method:

```javascript
removeMessageAction({
    channel: string,
    messageTimetoken: string,
    actionTimetoken: string
})
```

| Parameter | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| channel | string | Yes |  | Channel name of the target message. |
| messageTimetoken | string | Yes |  | Timetoken of the target message. |
| actionTimetoken | string | Yes |  | Timetoken of the message action to remove. |

### Sample code

```javascript
try {
  const response = await pubnub.removeMessageAction({
    channel: 'channel_name',
    messageTimetoken: 'replace_with_message_timetoken',
    actionTimetoken: 'replace_with_action_timetoken',
  });
  console.log('Message action removed successfully:', response);
} catch (error) {
  console.error(
    `Error removing message action: ${error}.${
      (error as PubNubError).status ? ` Additional information: ${(error as PubNubError).status}` : ''
    }`,
  );
}
```

### Returns

```json
// Example of status
{
    "error": false,
    "operation": "PNRemoveMessageActionOperation",
    "statusCode": 200
}

// Example of response
{
    "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.
:::

:::warning How to use the start and end parameters
PubNub retrieves messages by searching **backward through time** (newest to oldest). Because of this, the parameter names are the reverse of their intuitive meaning:
* **start** is the **newer** boundary (higher timetoken value) - search begins here, **exclusive**
* **end** is the **older** boundary (lower timetoken value) - search stops here, **inclusive**
When you provide both parameters, `start` must be a **higher** timetoken than `end`.
```mermaid
graph LR
    A(["9:00 AM<br/>(oldest)"]) -->|"time flows →"| B["end = 10:00 AM<br/>older boundary<br/>inclusive ✓"]
    B --> C["messages<br/>retrieved"]
    C --> D["start = 11:00 AM<br/>newer boundary<br/>exclusive ✗"]
    D -->|"time flows →"| E(["11:59 AM<br/>(newest)"])
    D -.->|"◄ API searches backward"| B
    style A fill:#f8f9fa,stroke:#6c757d,color:#495057
    style E fill:#f8f9fa,stroke:#6c757d,color:#495057
    style B fill:#d4edda,stroke:#28a745,color:#000
    style C fill:#cce5ff,stroke:#004085,color:#000
    style D fill:#fff3cd,stroke:#856404,color:#000
```
9:00 AM
10:00 AM
11:00 AM
11:59 AM
Results are always returned in oldest-first order.
:::

### Method(s)

Use this JavaScript method:

```javascript
getMessageActions({
    channel: string,
    start: string,
    end: string,
    limit: number
})
```

| Parameter | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| channel | string | Yes |  | Channel name to list message actions for. |
| start | string | Optional |  | Newer boundary of the query (exclusive). Must be a higher timetoken value than `end` when both are provided. |
| end | string | Optional |  | Older boundary of the query (inclusive). Must be a lower timetoken value than `start` when both are provided. |
| limit | number | Optional |  | Number of message actions to return. |

### Sample code

```javascript
// to get some data in response, first publish a message and then add a message action
// using addMessageAction() method.
try {
  const response = await pubnub.getMessageActions({
    channel: 'channel_name',
    start: 'replace_with_start_timetoken',
    end: 'replace_with_end_timetoken',
    limit: 100,
  });
  console.log('Message actions retrieved successfully:', response);
} catch (error) {
  console.error(
    `Error retrieving message actions: ${error}.${
      (error as PubNubError).status ? ` Additional information: ${(error as PubNubError).status}` : ''
    }`,
  );
}
```

### Returns

```json
// Example of status
{
    "error": false,
    "operation": "PNGetMessageActionsOperation",
    "statusCode": 200
}

// Example of response
{
    "data": [
        {
            "type": "reaction",
            "value": "smiley_face",
            "uuid": "user-456",
            "actionTimetoken": "15610547826970050",
            "messageTimetoken": "15610547826969050"
        }
    ],
    "start": "15646822873784630",
    "end": "15645905639093361",
}
```

Last updated at: 2026-06-25T11:22:35.000Z
