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

# Retrieve historical 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 fetch [message actions](https://www.pubnub.com/docs/pub-sub/message-actions/overview.md) for a channel from [Message Persistence](https://www.pubnub.com/docs/data-storage/message-history/overview.md), sorted oldest first by the action's own timetoken.

* Fetch every stored action for a channel.
* Narrow the fetch to a timetoken range with `start`, `end`, and `limit`.
* Page through a response that was truncated because it hit an internal limit.

Every call on this page needs an SDK instance initialized with your subscribe key. 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 retrieving message actions, confirm the [prerequisites](https://www.pubnub.com/docs/pub-sub/message-actions/overview.md#prerequisites) are in place.

## Fetch actions for a channel

Call the fetch method with just the channel name to get every stored action for it, oldest first.

### JavaScript

```javascript
const response = await pubnub.getMessageActions({
  channel: 'chats.room1',
});

response.data.forEach((action) => {
  console.log(`${action.type}: ${action.value}`);
});
```

### Swift

```swift
pubnub.fetchMessageActions(channel: "chats.room1") { result in
  switch result {
  case let .success((actions, _)):
    actions.forEach { print("\($0.actionType): \($0.actionValue)") }
  case let .failure(error):
    print("failed: \(error.localizedDescription)")
  }
}
```

### Java

```java
pubnub.getMessageActions()
    .channel("chats.room1")
    .async(result -> result.onSuccess(res -> {
        for (PNMessageAction action : res.getActions()) {
          System.out.println(action.getType() + ": " + action.getValue());
        }
    }));
```

### Kotlin

```kotlin
pubnub.getMessageActions(channel = "chats.room1").async { result ->
    result.onSuccess { res ->
        res.actions?.forEach { println("${it.type}: ${it.value}") }
    }
}
```

### C#

```csharp
pubnub.GetMessageActions()
  .Channel("chats.room1")
  .Execute(new PNGetMessageActionsResultExt((result, status) => {
    if (result != null) {
      foreach (var action in result.MessageActions) {
        Console.WriteLine(action.Action.Type + ": " + action.Action.Value);
      }
    }
  }));
```

### Python

```python
def get_actions_callback(result, status):
    if status.is_error():
        print(status.error_data.information)
    else:
        for action in result.actions:
            print(f"{action.type}: {action.value}")

pubnub.get_message_actions() \
    .channel("chats.room1") \
    .pn_async(get_actions_callback)
```

### Objective-C

```objectivec
PNFetchMessageActionsRequest *request =
    [PNFetchMessageActionsRequest requestWithChannel:@"chats.room1"];

[self.client fetchMessageActionsWithRequest:request
                                  completion:^(PNFetchMessageActionsResult *result, PNErrorStatus *status) {
  if (!status.isError) {
    for (PNMessageAction *action in result.data.actions) {
      NSLog(@"%@: %@", action.type, action.value);
    }
  }
}];
```

## Narrow the fetch to a time range

Bound the fetch with `start`, `end`, and `limit` when you don't need the whole channel history. For example, fetch only the actions added since a client last caught up.

| Parameter | Behavior |
| --- | --- |
| `start` | Newer boundary, exclusive. Must be a higher timetoken value than `end` when both are set. |
| `end` | Older boundary, inclusive. Must be a lower timetoken value than `start` when both are set. |
| `limit` | Maximum actions to return in one call. Default and maximum is 100. |

### JavaScript

```javascript
const response = await pubnub.getMessageActions({
  channel: 'chats.room1',
  start: '15646822873784630',
  end: '15645905639093361',
  limit: 50,
});
```

### Java

```java
pubnub.getMessageActions()
    .channel("chats.room1")
    .start(15646822873784630L)
    .end(15645905639093361L)
    .limit(50)
    .async(result -> { /* check result */ });
```

### C#

```csharp
pubnub.GetMessageActions()
  .Channel("chats.room1")
  .Start(15646822873784630)
  .End(15645905639093361)
  .Limit(50)
  .Execute(new PNGetMessageActionsResultExt((result, status) => { /* check result */ }));
```

### Python

```python
pubnub.get_message_actions() \
    .channel("chats.room1") \
    .start("15646822873784630") \
    .end("15645905639093361") \
    .limit(50) \
    .pn_async(get_actions_callback)
```

## Page through a truncated response

PubNub truncates the response when it hits an internal limit, even if you asked for fewer actions than exist. How a truncated response tells you there's more depends on the SDK.

C# returns a `More` object with the `Start`, `End`, and `Limit` to use for the next call:

```json
{
  "MessageActions": [ /* ... */ ],
  "More": {
    "Start": 15610547826970050,
    "End": 15645905639093361,
    "Limit": 2
  }
}
```

Kotlin (and PHP) return a page object instead. Pass it straight into another call:

```kotlin
pubnub.getMessageActions(channel = "chats.room1").async { result ->
    result.onSuccess { res ->
        res.actions?.forEach { println("${it.type}: ${it.value}") }
        res.page?.let { nextPage ->
            pubnub.getMessageActions(channel = "chats.room1", page = nextPage).async { /* fetch the rest */ }
        }
    }
}
```

For any SDK, a response containing exactly `limit` actions means more may exist. Repeat the call using the oldest action's own timetoken as the next `end` to keep paging toward older history. Check your language's [Message Actions API reference](https://www.pubnub.com/docs/sdks.md) for the exact field name your SDK uses to report truncation.

## 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.
* [Add message actions](https://www.pubnub.com/docs/pub-sub/message-actions/add-message-actions.md). Attach the actions this call fetches.
* [Receive message actions](https://www.pubnub.com/docs/pub-sub/message-actions/receive-message-actions.md). Handle an action live instead of fetching it after the fact.
* [Remove message actions](https://www.pubnub.com/docs/pub-sub/message-actions/remove-message-actions.md). Delete an action once you've found its `actionTimetoken` here.
* [Retrieve message history](https://www.pubnub.com/docs/data-storage/message-history/retrieve-message-history.md). Fetch the messages these actions are attached to.

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