---
source_url: https://www.pubnub.com/docs/pub-sub/message-actions/add-message-actions
title: Add message actions
updated_at: 2026-09-30T07:20:08.000Z
---

# Add message actions

## Documentation index

To discover more PubNub resources:

1. Fetch [PubNub's llms.txt](https://www.pubnub.com/llms-full.txt) for a list of available pages in Markdown format.
2. Identify relevant URLs from that index.
3. Fetch the target pages.

Do not assume a path exists, always check the index first.

This guide shows you how to attach a [message action](https://www.pubnub.com/docs/pub-sub/message-actions/overview.md) to a message PubNub already delivered, such as an emoji reaction, a read receipt, or a custom annotation.

* Add an action with a `type` and a `value` to an existing message.
* Confirm the action was stored from the response PubNub returns.
* Recognize the one status code that means the action was written but its event wasn't published.

Every call on this page needs an SDK instance initialized with your publish key. It also targets a message that already exists, identified by that message's [timetoken](https://www.pubnub.com/docs/architecture/core-concepts.md#timetoken), the value a successful [publish](https://www.pubnub.com/docs/pub-sub/publish/overview.md#publish-response-and-the-timetoken) call returned. Examples use the JavaScript, Swift, Java, Kotlin, C#, Python, and Objective-C SDKs. For any other language, refer to [Available SDKs](https://www.pubnub.com/docs/getting-started/available-sdks.md).

Before adding a message action, confirm the [prerequisites](https://www.pubnub.com/docs/pub-sub/message-actions/overview.md#prerequisites) are in place.

A message action is a standard PubNub API request, so it's subject to the same size limit as a publish call.

| Item | Limit | Notes |
| --- | --- | --- |
| Request size | Same limit as [Publish](https://www.pubnub.com/docs/architecture/limits.md#publish). | A message action is sent as a standard PubNub API request, so the publish request-body limit applies. |
| `type` and `value` fields | No dedicated limit | Bounded only by the overall request size. |

## Add an action to a message

Call the add-action method with the channel, the target message's timetoken, and the `type`/`value` pair you're attaching.

### JavaScript

```javascript
const response = await pubnub.addMessageAction({
  channel: 'chats.room1',
  messageTimetoken: '15610547826969050',
  action: {
    type: 'reaction',
    value: 'smiley_face',
  },
});

console.log('actionTimetoken:', response.data.actionTimetoken);
```

### Swift

```swift
pubnub.addMessageAction(
  channel: "chats.room1",
  type: "reaction",
  value: "smiley_face",
  messageTimetoken: 15610547826969050
) { result in
  switch result {
  case let .success(action):
    print("actionTimetoken: \(action.actionTimetoken)")
  case let .failure(error):
    print("failed: \(error.localizedDescription)")
  }
}
```

### Java

```java
PNMessageAction messageAction = new PNMessageAction()
    .setType("reaction")
    .setValue("smiley_face")
    .setMessageTimetoken(15610547826969050L);

pubnub.addMessageAction()
    .channel("chats.room1")
    .messageAction(messageAction)
    .async(result -> result.onSuccess(res ->
        System.out.println("actionTimetoken: " + res.getActionTimetoken())));
```

### Kotlin

```kotlin
val messageAction = PNMessageAction().apply {
    type = "reaction"
    value = "smiley_face"
    messageTimetoken = 15610547826969050L
}

pubnub.addMessageAction(
    channel = "chats.room1",
    messageAction = messageAction
).async { result ->
    result.onSuccess { println("actionTimetoken: ${it.actionTimetoken}") }
}
```

### C#

```csharp
pubnub.AddMessageAction()
  .Channel("chats.room1")
  .MessageTimetoken(15610547826969050)
  .Action(new PNMessageAction { Type = "reaction", Value = "smiley_face" })
  .Execute(new PNAddMessageActionResultExt((result, status) => {
    if (result != null) {
      Console.WriteLine("actionTimetoken: " + result.ActionTimetoken);
    }
  }));
```

### Python

```python
msg_action = PNMessageAction()
msg_action.type = "reaction"
msg_action.value = "smiley_face"
msg_action.message_timetoken = "15610547826969050"

def add_action_callback(result, status):
    if status.is_error():
        print(status.error_data.information)
    else:
        print("actionTimetoken:", result.action_timetoken)

pubnub.add_message_action() \
    .channel("chats.room1") \
    .message_action(msg_action) \
    .pn_async(add_action_callback)
```

### Objective-C

```objectivec
PNAddMessageActionRequest *request =
    [PNAddMessageActionRequest requestWithChannel:@"chats.room1"
                                  messageTimetoken:@15610547826969050];
request.type = @"reaction";
request.value = @"smiley_face";

[self.client addMessageActionWithRequest:request completion:^(PNAddMessageActionStatus *status) {
  if (!status.isError) {
    NSLog(@"actionTimetoken: %@", status.data.action.actionTimetoken);
  }
}];
```

A successful call returns the action PubNub stored:

```json
{
  "type": "reaction",
  "value": "smiley_face",
  "uuid": "user-456",
  "actionTimetoken": "15610547826970050",
  "messageTimetoken": "15610547826969050"
}
```

Keep the returned `actionTimetoken`. [Removing this action later](https://www.pubnub.com/docs/pub-sub/message-actions/remove-message-actions.md) needs it, and it isn't derivable from the message's own timetoken.

## Handle a 207 status

A `207` status means PubNub stored the action but couldn't publish its Message Action event to subscribers. Treat the action as added. Don't call add again for the same reaction or receipt. That creates a second, duplicate action instead of retrying the first one. If your code depends on subscribers seeing it, have them catch up with [Retrieve historical message actions](https://www.pubnub.com/docs/pub-sub/message-actions/retrieve-historical-message-actions.md) instead.

## Related tasks

* [Message Actions in PubNub](https://www.pubnub.com/docs/pub-sub/message-actions/overview.md). The type/value model, the event model, and the Message Persistence requirement.
* [Receive message actions](https://www.pubnub.com/docs/pub-sub/message-actions/receive-message-actions.md). Handle the event this call generates on a live subscription.
* [Retrieve historical message actions](https://www.pubnub.com/docs/pub-sub/message-actions/retrieve-historical-message-actions.md). Fetch actions for a channel, or catch up on one added while a client was offline.
* [Remove message actions](https://www.pubnub.com/docs/pub-sub/message-actions/remove-message-actions.md). Delete a previously added action using the `actionTimetoken` this call returns.
* [Send different message types](https://www.pubnub.com/docs/pub-sub/publish/send-different-message-types.md). Publish the message an action attaches to.

Last updated at: 2026-09-30T07:20:08.000Z
