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

# Receive 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 handle the [Message Action event](https://www.pubnub.com/docs/architecture/events.md#message-action) PubNub delivers when someone adds or removes a [message action](https://www.pubnub.com/docs/pub-sub/message-actions/overview.md) on a channel you're subscribed to.

* Register the dedicated handler for this event on an existing subscription.
* Tell an added action from a removed one, and read the type, value, and timetokens it carries.
* Recognize when the handler won't fire, and where to go to catch up.

This page covers only the handler specific to message actions and assumes you already have a subscription. For creating one and registering handlers in general, refer to [Receive messages](https://www.pubnub.com/docs/pub-sub/subscribe/receive-messages.md). Examples use the JavaScript, Java, Kotlin, C#, and Python SDKs, which have entity-based subscriptions. If yours doesn't, skip to [Register the handler without entities](#register-the-handler-without-entities).

## Register the handler

Register the handler on your subscription the same way you would for any other event type.

### JavaScript

```javascript
subscription.onMessageAction = (event) => {
  console.log(`${event.event}: ${event.data.type} = ${event.data.value}`);
};
```

### Java

```java
subscription.setOnMessageAction(event -> { /* Handle message action */ });
```

### Kotlin

```kotlin
subscription.onMessageAction = { messageAction -> /* Handle message action */ }
```

### C#

```csharp
subscription.onMessageAction += (Pubnub pn, PNMessageActionEventResult e) => { /* Handle message action */ };
```

### Python

```python
def on_message_action(message_action):
    pass  # Handle message action

subscription.on_message_action = on_message_action
```

Registering this handler doesn't start anything by itself. Nothing arrives until `subscribe()` runs on this subscription, the same as for any other handler. Refer to [A listener is a callback, not a connection](https://www.pubnub.com/docs/pub-sub/subscribe/event-listeners.md#a-listener-is-a-callback-not-a-connection).

## Read the event payload

The event carries two timetokens instead of one, because it always refers back to a message published earlier:

| Field | Description |
| --- | --- |
| `channel` | Channel the message action was added to or removed from |
| `publisher` | User ID that added or removed the action |
| `event` | `added` or `removed` |
| `data.type` | The action's `type` |
| `data.value` | The action's `value` |
| `data.messageTimetoken` | Timetoken of the message the action refers to |
| `data.actionTimetoken` | Timetoken of the action itself |

This table matches the field names JavaScript uses. Other SDKs expose the same fields through their own accessors. Check your language's [Message Actions API reference](https://www.pubnub.com/docs/sdks.md) for the exact getter or property name. For the complete client-side event model, refer to [Message Action](https://www.pubnub.com/docs/architecture/events.md#message-action).

## Tell an add from a removal

Branch on the `event` field to handle an added action differently from a removed one, for example to increment or decrement a reaction count in your UI:

```javascript
subscription.onMessageAction = (event) => {
  if (event.event === 'added') {
    // Show the new reaction or receipt
  } else if (event.event === 'removed') {
    // Take the reaction or receipt back off the message
  }
};
```

## Register the handler without entities

SDKs that predate entities register every listener on the PubNub client object instead of on a subscription.

### Objective-C

```objectivec
- (void)client:(PubNub *)client didReceiveMessageAction:(PNMessageActionResult *)action {
    NSLog(@"Action type: %@, value: %@", action.data.action.type, action.data.action.value);
}
```

For how listener scope works on these SDKs, and the tradeoffs against entity-based scoping, refer to [Listener scope follows the subscription, not the channel name](https://www.pubnub.com/docs/pub-sub/subscribe/event-listeners.md#listener-scope-follows-the-subscription-not-the-channel-name).

## Catch up on missed events

A Message Action event follows the same [at-most-once live delivery](https://www.pubnub.com/docs/pub-sub/overview.md#at-most-once-live-delivery) rule as any other event: only a client subscribed at the moment of the add or remove receives it. Because the action itself is stored, a client that misses the live event can still catch up. Call [Retrieve historical message actions](https://www.pubnub.com/docs/pub-sub/message-actions/retrieve-historical-message-actions.md) for the channel to fetch what it missed.

## 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](https://www.pubnub.com/docs/data-storage/message-history/overview.md) requirement.
* [Add message actions](https://www.pubnub.com/docs/pub-sub/message-actions/add-message-actions.md). Generate the event this handler receives.
* [Retrieve historical message actions](https://www.pubnub.com/docs/pub-sub/message-actions/retrieve-historical-message-actions.md). Fetch actions added while a client was offline.
* [Event listeners](https://www.pubnub.com/docs/pub-sub/subscribe/event-listeners.md). The listener model, both registration styles, and how handler scope works.
* [Receive messages](https://www.pubnub.com/docs/pub-sub/subscribe/receive-messages.md). Create a subscription and register handlers on it.

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