---
source_url: https://www.pubnub.com/docs/sdks/asyncio/api-reference/storage-and-playback
title: Message Persistence API for Python-Asyncio SDK
updated_at: 2026-05-25T11:27:14.374Z
sdk_name: PubNub Python Asyncio SDK
---

> 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 Python-Asyncio SDK

PubNub Python Asyncio SDK

Install:

```bash
pip install pubnub
```

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:

* 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](https://www.pubnub.com/docs/sdks/asyncio/api-reference/misc#time).
* 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 Python-asyncio SDK:

```python
pubnub.history() \
    .channel(String) \
    .include_meta(True) \
    .reverse(Boolean) \
    .include_timetoken(Boolean) \
    .start(Int) \
    .end(Int) \
    .count(Int)
```

| Parameter | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| channel | String | Yes |  | Specifies `channel` to return history messages from. |
| include_meta | Boolean | Optional |  | Specifies whether or not the message's meta information should be returned. |
| reverse | Boolean | Optional |  | Whether to traverse the timeline in reverse starting with the oldest message first. |
| include_timetoken | Boolean | Optional |  | Whether event dates timetokens should be included in the response. |
| start | Int | Optional |  | Timetoken delimiting the start of time slice (exclusive) to pull messages from. |
| end | Int | Optional |  | Timetoken delimiting the end of time slice (inclusive) to pull messages from. |
| count | Int | Optional |  | Number of historical messages to return. |

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

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

Retrieve the last 100 messages on a channel:

```python
import asyncio
import os
from pubnub.pnconfiguration import PNConfiguration
from pubnub.pubnub_asyncio import PubNubAsyncio
from pubnub.exceptions import PubNubException

async def get_history(pubnub: PubNubAsyncio):
    try:
        # Retrieve the last 100 messages on a channel
        envelope = await pubnub.history() \
            .channel('history_channel') \
            .count(100) \
            .future()

        if envelope.status.is_error():
            print("Error retrieving history")
            return

        for message in envelope.result.messages:
            print(f"Message: {message.entry} with timetoken: {message.timetoken}")

    except PubNubException as e:
        print(f"Error: {e}")

if __name__ == "__main__":
    loop = asyncio.new_event_loop()
    asyncio.set_event_loop(loop)

    # Configuration for PubNub instance
    pn_config = PNConfiguration()
    pn_config.subscribe_key = os.getenv('SUBSCRIBE_KEY', 'demo')
    pn_config.user_id = "my_custom_user_id"

    pubnub = PubNubAsyncio(pn_config)

    try:
        loop.run_until_complete(get_history(pubnub))
    finally:
        loop.run_until_complete(pubnub.stop())
        loop.close()
```

### Returns

The `history()` operation returns a `PNHistoryResult` which contains the following properties:

| Method | Description |
| --- | --- |
| `messages`Type: List | List of messages of type `PNHistoryItemResult`. See [PNHistoryItemResult](#pnhistoryitemresult) for more details. |
| `start_timetoken`Type: Int | Start `timetoken`. |
| `end_timetoken`Type: Int | End `timetoken`. |

#### PNHistoryItemResult

| Method | Description |
| --- | --- |
| `timetoken`Type: Int | `Timetoken` of the message. |
| `entry`Type: Object | Message. |

### Other examples

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

```python
envelope = await pubnub.history() \
    .channel("my_channel") \
    .count(3) \
    .reverse(True) \
    .future()
```

##### Response

```python
{
    end_timetoken: 13406746729185766,
    start_timetoken: 13406746780720711,
    messages: [{
        crypto: None,
        entry: 'Pub1',
        timetoken: None
    },{
        crypto: None,
        entry: 'Pub2',
        timetoken: None
    },{
        crypto: None,
        entry: 'Pub2',
        timetoken: None
    }]
}
```

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

```python
envelope = await pubnub.history()\
    .channel("my_channel")\
    .start(13847168620721752)\
    .reverse(true)\
    .future()
```

##### Response

```python
{
    end_timetoken: 13406746729185766,
    start_timetoken: 13406746780720711,
    messages: [{
        crypto: None,
        entry: 'Pub4',
        timetoken: None
    },{
        crypto: None,
        entry: 'Pub5',
        timetoken: None
    },{
        crypto: None,
        entry: 'Pub6',
        timetoken: None
    }]
}
```

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

```python
envelope = await pubnub.history()\
    .channel("my_channel")\
    .count(100)\
    .start(-1)\
    .end(13847168819178600)\
    .reverse(True)\
    .future()
```

##### Response

```python
{
    end_timetoken: 13406746729185766,
    start_timetoken: 13406746780720711,
    messages: [{
        crypto: None,
        entry: 'Pub4',
        timetoken: None
    },{
        crypto: None,
        entry: 'Pub5',
        timetoken: None
    },{
        crypto: None,
        entry: 'Pub6',
        timetoken: None
    }]
}
```

#### History paging example

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

```python
async def get_all_messages(start_tt):
    envelope = await pubnub.history()\
        .channel('history_channel')\
        .count(100)\
        .start(start_tt)\
        .future()

    msgs = envelope.result.messages
    start = envelope.result.start_timetoken
    end = envelope.result.end_timetoken
    count = len(msgs)

    if count > 0:
        print("%d" % count)
        print("start %d" % start)
        print("end %d" % end)

    if count == 100:
        await get_all_messages(start)

loop = asyncio.get_event_loop()
loop.run_until_complete(get_all_messages(14759343456292767))
```

#### Include timetoken in history response

```python
envelope = await pubnub.history()\
    .channel("my_channel")\
    .count(100)\
    .include_tometoken()
    .future()
```

## 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 Python-asyncio SDK.

```python
pubnub.delete_messages() \
    .channel(String) \
    .start(Int) \
    .end(Int) \
    .future()
```

| Parameter | Description |
| --- | --- |
| `channel` *Type: String | Specifies `channels` to delete messages from. |
| `start`Type: Int | Timetoken delimiting the start of time slice (inclusive) to delete messages from. |
| `end`Type: Int | Timetoken delimiting the end of time slice (exclusive) to delete messages from. |

### Sample code

```python
envelope = yield from pubnub.delete_messages()\
    .channel("my-ch")\
    .start(123)\
    .end(456)
    .future()
```

### 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. For exmaple, if `15526611838554310` is the `publish timetoken`, pass `15526611838554309` in `Start` and `15526611838554310` in `End` parameters respectively as shown in the following code snippet.

```python
envelope = yield from pubnub.delete_messages()\
    .channel("my-ch")\
    .start(15526611838554309)\
    .end(15526611838554310)
    .future()
```

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