---
source_url: https://www.pubnub.com/docs/sdks/dart/api-reference/message-actions
title: Message Actions API for Dart SDK
updated_at: 2026-06-19T11:37:13.698Z
sdk_name: PubNub Dart SDK
sdk_version: 7.1.0
---

> 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 Dart SDK

PubNub Dart SDK, use the latest version: 7.1.0

Install:

```bash
dart pub add pubnub@7.1.0
```

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

This method adds a message action to a parent message. A parent message is identified by `subscribeKey`, `channel`, and `timetoken`. The response includes the added action.

:::note Parent message existence
The server doesn't validate if the parent message exists when adding a message action. It does check whether the same action already exists on the parent message. Only one message action with a given `type` and `value` can exist for a parent message.
:::

### Method(s)

Use this Dart method:

```dart
pubnub.addMessageAction(
  {String type,
  String value,
  String channel,
  Timetoken timetoken,
  Keyset? keyset,
  String? using}
) 
```

| Parameter | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| type | String | Yes |  | Message action type. |
| value | String | Yes |  | Message action value. |
| channel | String | Yes |  | Channel name to add the message action to. |
| timetoken | Timetoken | Yes |  | Timetoken of the target message. |
| keyset | Keyset | Optional |  | Override for the default keyset configuration. |
| using | String | Optional |  | Keyset name from the `keysetStore` to use for this call. |

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

```dart
import 'package:pubnub/pubnub.dart';

void main() async {
  // Create PubNub instance with default keyset.
  var pubnub = PubNub(
    defaultKeyset: Keyset(
      subscribeKey: 'demo',
      publishKey: 'demo',
      userId: UserId('myUniqueUserId'),
    ),
  );

  // Channel and message details
  String channel = 'my_channel';
  Timetoken messageTimetoken = Timetoken(BigInt.from(15610547826969050));

  // Add a message action
  var result = await pubnub.addMessageAction(
    type: 'reaction',
    value: 'smiley',
    channel: channel,
    timetoken: messageTimetoken,
  );

  // Print the added message action details
  print('Added message action: ${result.action}');
}
```

### Returns

The `addMessageAction()` operation returns an `AddMessageActionResult` with the following property:

| Property Name | Type | Description |
| --- | --- | --- |
| `action` | `MessageAction` | Added message action. |

The `MessageAction` object contains the following properties:

| Property Name | Type | Description |
| --- | --- | --- |
| `type` | String | Message action type. |
| `value` | String | Message action value. |
| `actionTimetoken` | String | Timetoken assigned to the added message action. |
| `messageTimetoken` | String | Timetoken of the target message. |
| `uuid` | String | UUID of the sender. |

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

```dart
pubnub.deleteMessageAction(String channel,
      {Timetoken messageTimetoken,
      Timetoken actionTimetoken,
      Keyset? keyset,
      String? using})
```

| Parameter | Description |
| --- | --- |
| `channel` *Type: String | Channel the message was sent to. |
| `messageTimetoken` *Type: `Timetoken` | Timetoken of the target message. |
| `actionTimetoken` *Type: `Timetoken` | Timetoken of the message action to remove. |
| `keyset`Type: `Keyset` | Override for the default keyset configuration. |
| `using`Type: `String` | Keyset name from the `keysetStore` to use for this call. |

### Sample code

```dart
  var result = await pubnub.deleteMessageAction(
      'my_channel', Timetoken(15610547826969050), Timetoken(15610547826969159));
```

### Returns

The `deleteMessageAction()` operation returns a `DeleteMessageActionResult` without 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.

### Method(s)

Use this Dart method:

```dart
pubnub.fetchMessageActions(
  String channel,
  {Timetoken? from,
  Timetoken? to,
  int? limit,
  Keyset? keyset,
  String? using})
```

| Parameter | Description |
| --- | --- |
| `channel` *Type: StringDefault: n/a | Channel name to list message actions for. |
| `from`Type: TimetokenDefault: n/a | Message action timetoken for the start of the range (exclusive). |
| `to`Type: TimetokenDefault: n/a | Message action timetoken for the end of the range (inclusive). |
| `limit`Type: intDefault: 100 | Maximum number of actions to return. Default/Maximum is `100`. |
| `keyset`Type: `Keyset`Default: n/a | Override for the default keyset configuration. |
| `using`Type: `String`Default: n/a | Keyset name from the `keysetStore` to use for this call. |

### Sample code

```dart
var result = await pubnub.fetchMessageActions('my_channel');
```

### Response

```json
{
  "status": 200,
  "data": [
    {
      "type": "reaction",
      "value": "smiley_face",
      "actionTimetoken": "15610547826970050",
      "messageTimetoken": "15610547826969050",
      "uuid": "terryterry69420"
    }
  ],
  "more": {
    "url": "/v1/actions/sub-c-6ba5f838-6456-11e8-9307-eaaa55e2558c/channel/my_channel?start=15610547826970050&end=15645905639093361&limit=2",
    "start": "15610547826970050",
    "end": "15645905639093361",
    "limit": 2
  }
}
```

### Returns

The `fetchMessageActions()` operation returns a list of `FetchMessageActionsResult` objects containing the following properties:

| Property Name | Type | Description |
| --- | --- | --- |
| `actions` | `List<MessageAction>` | List of message actions. |
| `moreActions` | `MoreAction` | Pagination information. |

The `MessageAction` has the following properties:

| Property Name | Type | Description |
| --- | --- | --- |
| `type` | String | Message action type. |
| `value` | String | Message action value. |
| `actionTimetoken` | String | Timetoken assigned to the added message action. |
| `messageTimetoken` | String | Timetoken of the target message. |
| `uuid` | String | UUID of the sender. |

The `MoreAction` has the following properties:

| Property Name | Type | Description |
| --- | --- | --- |
| `url` | String | URL to fetch the next page of message actions. |
| `start` | String | Start timetoken for the next page. |
| `limit` | int | Limit for the next page. |

### Other examples

#### Fetch message actions with paging

```dart
// this loop continues fetching message actions when the next batch is available
var fetchMessageActionsResult = FetchMessageActionsResult(<MessageAction>[]);
var loopResult, from, to, limit;
do {
  loopResult = await pubnub.fetchMessageActions('my_channel',
      from: from, to: to, limit: limit);

  fetchMessageActionsResult.actions.addAll(loopResult.actions);

  if (loopResult.moreActions != null) {
    var more = loopResult.moreActions;
    from = Timetoken(BigInt.parse(more.start));
    to = Timetoken(BigInt.parse(more.end));
    limit = more.limit;
  }
} while (loopResult.moreActions != null);
// now `fetchMessageActionsResult` contains all message actions
```

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