---
source_url: https://www.pubnub.com/docs/sdks/angular/api-reference/storage-and-playback
title: Message Persistence API for AngularJS SDK
updated_at: 2026-05-27T12:41:50.102Z
---

> 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 Persistence API for AngularJS SDK

Message Persistence gives you real-time access to the history of messages published to PubNub. Each message is timestamped to the nearest 10 nanoseconds and stored across multiple availability zones in several geographic locations. You can encrypt stored messages with AES-256 so they are not readable on PubNub’s network. For details, see [Message Persistence](https://www.pubnub.com/docs/general/storage).

You control how long messages are stored through your account’s retention policy. Options include: 1 day, 7 days, 30 days, 3 months, 6 months, 1 year, or Unlimited.

You can retrieve the following:

* Messages
* Message reactions
* Files (using the File Sharing API)

## History

:::warning Requires Message Persistence
Enable Message Persistence for your key in the [Admin Portal](https://admin.pubnub.com/). See how to [enable add-on features](https://support.pubnub.com/hc/en-us/articles/360051974791-How-do-I-enable-add-on-features-for-my-keys-).
:::

This function fetches historical messages of a channel.

You can control how messages are returned and in what order. For example, you can:

* Search from the newest end of the timeline (default: `reverse` = `false`).
* Search from the oldest end of the timeline by setting `reverse` to `true`.
* Page through results by providing a `start` or `end` timetoken.
* Retrieve a slice of the timeline by providing both a `start` and `end` timetoken.
* Limit the number of messages using the `count` parameter.

:::tip Start & End parameter usage clarity
If you specify only `start` (without `end`), you receive messages older than and up to that `start` timetoken. If you specify only `end` (without `start`), you receive messages that match that `end` timetoken and newer. If you specify both `start` and `end`, you receive messages between those timetokens (inclusive of `end`). You still receive up to 100 messages even if more match. Make iterative calls to history, adjusting `start`, to page through the full result set.
:::

### Method(s)

To run `History` you can use the following method(s) in the AngularJS SDK:

```javascript
history( {String channel, Boolean reverse, Number count, Boolean stringifiedTimeToken, Boolean includeMeta, String start, String end}, Function callback )
```

| Parameter | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| channel | String | Yes |  | Specifies `channel` to return history messages from. |
| reverse | Boolean | Optional | `false` | Whether to traverse the timeline in reverse (oldest to newest). If both `start` and `end` are provided, `reverse` is ignored and messages are returned starting with the newest message. |
| count | Number | Optional | `100` | Specifies the number of historical messages to return. Default/Maximum is `100`. |
| stringifiedTimeToken | Boolean | Optional | `false` | If `stringifiedTimeToken` is `true`, the SDK returns `timetoken` values as strings instead of integers. This is encouraged in JavaScript environments which round large integers. |
| includeMeta | Boolean | Optional |  | Whether to include message meta information. |
| start | String | Optional |  | Timetoken delimiting the start of the time slice (exclusive) to pull messages from. |
| end | String | Optional |  | Timetoken delimiting the end of the time slice (inclusive) to pull messages from. |
| callback | Function | Optional |  | Executes on a successful/unsuccessful `history`. |

:::tip Using the reverse parameter
Messages are always returned sorted in ascending time direction from history regardless of `reverse`. The `reverse` direction matters when you have more than 100 (or `count`, if it's set) messages in the time interval, in which case `reverse` determines the end of the time interval from which it should start retrieving the messages.
:::

### Sample code

Retrieve the last 100 messages on a channel:

```javascript
Pubnub.history(
    {
        channel: 'history_channel',
        count: 100, // 100 is the default
        stringifiedTimeToken: true // false is the default
    },
    function (status, response) {
        // handle status, response
    }
);
```

### Response

```javascript
// Example of Status
{
    error: false,
    operation: "PNHistoryOperation",
    statusCode: 200
}

// Example of Response
{
    endTimeToken: "14867650866860159",
    messages: [
        {
            timetoken: "14867650866860159",
            entry: "[User 636] hello World"
        },
        {...},
        {...},
        {...}
    ],
    startTimeToken: "14867650866860159"
}
```

### Other examples

#### Use history() to retrieve the three oldest messages by retrieving from the time line in reverse

```javascript
// get last 3 messages published to my_channel

Pubnub.history(
    {
        channel: ['my_channel'],
        reverse: true, // Setting to true will traverse the time line in reverse starting with the oldest message first.
        count: 3,
        stringifiedTimeToken: true // false is the default
    },
    function (status, response) {
        // handle status, response
    }
);
```

#### Use history() to retrieve messages newer than a given timetoken by paging from oldest message to newest message starting at a single point in time (exclusive)

```javascript
// get messages starting at timetoken order oldest first

Pubnub.history(
    {
        channel: 'my_channel',
        reverse: true, // Setting to true will traverse the time line in reverse starting with the oldest message first.
        stringifiedTimeToken: true, // false is the default
        start: '13406746780720711'
    },
    function (status, response) {
        // handle status, response
    }
);
```

#### Use history() to retrieve messages until a given timetoken by paging from newest message to oldest message until a specific end point in time (inclusive)

```javascript
// return 100 messages ending on timetoken

Pubnub.history(
    {
        channel: 'my_channel',
        stringifiedTimeToken: true,
        end: '13406746780720711'
    },
    function (status, response) {
        // handle status, response
    }
);
```

#### History paging example

:::note Usage
You can call the method by passing 0 or a valid **timetoken** as the argument.
:::

```javascript
getAllMessages = function(timetoken) {
    Pubnub.history(
        {
            channel: 'history_test',
            stringifiedTimeToken: true, // false is the default
            start: timetoken
        },
        function (status, response) {
            var msgs = response.messages;
            var start = response.startTimeToken;
            var end = response.endTimeToken;
            // if msgs were retrieved, do something useful with them
            if (msgs != "undefined" && msgs.length > 0) {
                console.log(msgs.length);
                console.log("start : " + start);
                console.log("end : " + end);
            }
            // if 100 msgs were retrieved, there might be more; call history again
            if (msgs.length == 100)
                getAllMessages(start);
        }
    );
}

//Usage examples:
//getAllMessages();
//getAllMessages(null);
//getAllMessages(14264873967138188);
```

#### Fetch messages with metadata

```javascript
pubnub.history(
    {
        channel: 'my_channel',
        stringifiedTimeToken: true,
        includeMeta: true,
    },
    function (status, response) {
        // handle status, response
    }
);
```

## Batch history

:::warning Requires Message Persistence
Enable Message Persistence for your key in the [Admin Portal](https://admin.pubnub.com/). See how to [enable add-on features](https://support.pubnub.com/hc/en-us/articles/360051974791-How-do-I-enable-add-on-features-for-my-keys-).
:::

Fetch historical messages from multiple channels. The `includeMessageActions` or `includeActions` flag also allows you to fetch message reactions along with the messages.

You can control how messages are returned and in what order:

* Search from the newest end of the timeline.
* Search from the oldest end of the timeline.
* Page through results by providing a `start` or `end` timetoken.
* Retrieve a slice of the timeline by providing both a `start` and `end` timetoken.
* Retrieve a specific (maximum) number of messages using the `count` parameter.

Batch history returns up to 100 messages on a single channel, or 25 per channel on a maximum of 500 channels. Use the `start` and `end` timestamps to page through the next batch of messages.

:::tip Start & End parameter usage clarity
If you specify only the `start` parameter (without `end`), you receive messages older than the `start` timetoken.
If you specify only the `end` parameter (without `start`), you receive messages from that `end` timetoken and newer.
If you specify both `start` and `end`, you retrieve messages between those timetokens (inclusive of the `end` value).
You still receive a maximum of 100 messages (or 25, for multiple channels) even if more messages match. Make iterative calls to history, adjusting the `start` timetoken, to page through the full set of results.
:::

### Method(s)

Use the following method(s) in the AngularJS SDK:

```javascript
fetchMessages(
    {Array channels, Number count, Boolean stringifiedTimeToken, Boolean includeMeta, Boolean includeMessageType, Boolean includeUUID, Boolean includeMessageActions, String start, String end},
    Function callback )
```

| Parameter | Description |
| --- | --- |
| `channels` *Type: ArrayDefault: n/a | Specifies `channels` to return history messages from. |
| `count`Type: NumberDefault: `25` | Specifies the number of historical messages to return per channel. Default/Maximum is `25` per `channel`. |
| `stringifiedTimeToken`Type: BooleanDefault: `false` | If `stringifiedTimeToken` is `true`, the SDK returns `timetoken` values as strings instead of integers. This is encouraged in JavaScript environments which round large integers. |
| `includeMessageType`Type: BooleanDefault: `true` | Whether to include the message type with each history message. |
| `includeUUID`Type: BooleanDefault: `true` | Whether to include the publisher `uuid` with each history message. |
| `includeMeta`Type: BooleanDefault: n/a | Whether message meta information should be fetched. |
| `includeMessageActions`Type: BooleanDefault: n/a | Whether to fetch message reactions. Throws an exception if called with more than one `channel`. Truncation occurs if the number of actions across returned messages exceeds 25,000. Each message can have up to 25,000 actions. For example: querying 10 messages where the first five have 5,000 actions each returns those five messages and all 25,000 actions, plus a `more` link to fetch the remainder. |
| `start`Type: StringDefault: n/a | Timetoken delimiting the start of the time slice (exclusive) to pull messages from. |
| `end`Type: StringDefault: n/a | Timetoken delimiting the end of the time slice (inclusive) to pull messages from. |
| `callback`Type: FunctionDefault: n/a | Executes on a successful/unsuccessful `fetchMessages`. |

### Sample code

Retrieve the last message on a channel:

```javascript
// assuming pubnub is an initialized instance
// start, end, count are optional
pubnub.fetchMessages(
    {
        channels: ['ch1', 'ch2', 'ch3'],
        start: "15343325214676133",
        end: "15343325004275466",
        count: 25
    },
    (status, response) => {
        // handle response
    }
);
```

### Response

```javascript
//Example of status
{
    error: false,
    operation: 'PNFetchMessagesOperation',
    statusCode: 200
}

//Example of response
{
    "channels":{
        "my-channel":[
            {
                "message":"message_1",
                "timetoken":"15483367794816642",
                "uuid":"my-uuid",
                "message_type":null
            },
            {
                "message":"message_2",
                "timetoken":"15483367810978163",
                "uuid":"my-uuid",
                "message_type":null
            }
        ],
        "my-channel-2":[
            {
                "message":"message_1",
                "timetoken":"15483367827886667",
                "uuid":"my-uuid",
                "message_type":null
            }
        ]
    }
}
```

### Other examples

#### Fetch messages with metadata and actions

```javascript
pubnub.fetchMessages(
    {
        channels: ['my_channel'],
        stringifiedTimeToken: true,
        includeMeta: true,
        includeMessageActions: true,
    },
    function (status, response) {
        // handle status, response
    }
);
```

Fetch messages with metadata and actions Response

```javascript
// Example of status
{
    "error": false,
    "operation": "PNFetchMessagesOperation",
    "statusCode": 200
}

// Example of response
{
    "channels":{
        "my_channel":[
            {
                "timetoken":"15741125155552287",
                "message":{
                    "text":"Hello world!",
                    "uuid":"my-uuid",
                    "message_type":null,
                    "meta":""
                },
                "data":{
                    "reaction":{
                        "smiley_face":[
                            {
                                "uuid":"my-uuid",
                                "actionTimetoken":"15741125155943280"
                            }
                        ]
                    }
                }
            }
        ]
    },
"more": {
    "url": "/v3/history-with-actions/sub-key/subscribeKey/channel/myChannel?start=15610547826970000&max=98",
    "start": "15610547826970000",
    "max": 98
}
}
```

## Delete messages from history

:::warning Requires Message Persistence
Enable Message Persistence for your key in the [Admin Portal](https://admin.pubnub.com/). See how to [enable add-on features](https://support.pubnub.com/hc/en-us/articles/360051974791-How-do-I-enable-add-on-features-for-my-keys-).
:::

Remove messages from the history of a specific channel.

:::note Required setting
To accept delete-from-history requests, enable the `Delete-From-History` setting for your key in the Admin Portal and initialize the SDK with a secret key.
:::

### Method(s)

To `Delete Messages from History` you can use the following method(s) in the AngularJS SDK.

:::note
The Delete Messages method behaves slightly differently than other history methods. Note that the `start` parameter is exclusive and the `end` parameter is inclusive.
:::

```javascript
deleteMessages({String channel, String start, String end},Function callback)
```

| Parameter | Description |
| --- | --- |
| `channel` *Type: String | Channel to delete messages from. |
| `start`Type: String | Timetoken delimiting the start of the time slice (exclusive) to delete messages from. |
| `end`Type: String | Timetoken delimiting the end of the time slice (inclusive) to delete messages from. |
| `callback`Type: Function | Executes on successful or unsuccessful execution of `deleteMessages`. |

### Sample code

```javascript
Pubnub.deleteMessages(
    {
        channel: 'ch1',
        start: '15088506076921021',
        end: '15088532035597390'
    },
    (result) => {
        console.log(result);
    }
);
```

### Response

```javascript
{
    error: false,
    operation: 'PNDeleteMessagesOperation',
    statusCode: 200
}
```

### Other examples

#### Delete specific message from history

To delete a specific message, pass the `publish timetoken` (received from a successful publish) in the `End` parameter and `timetoken +/- 1` in the `Start` parameter. e.g. if `15526611838554310` is the `publish timetoken`, pass `15526611838554309` in `Start` and `15526611838554310` in `End` parameters respectively as shown in the following code snippet.

```javascript
Pubnub.deleteMessages(
    {
        channel: 'ch1',
        start: '15526611838554309',
        end: '15526611838554310'
    },
    (result) => {
        console.log(result);
    }
);
```

## Terms in this document

* **Message** - A unit of data transmitted between clients or between a client and a server in PubNub, containing information such as text, binary data, or structured data formats like JSON. Messages are sent over channels and can be tracked for delivery and read status.
* **PubNub** - PubNub is a real-time messaging platform that provides APIs and SDKs for building scalable applications. It handles the complex infrastructure of real-time communication, including: Message delivery and persistence, Presence detection, Access control, Push notifications, File sharing, Serverless processing with Functions and Events & Actions, Analytics and monitoring with BizOps Workspace, AI-powered insights with Illuminate.
