---
source_url: https://www.pubnub.com/docs/sdks/twisted/api-reference/storage-and-playback
title: Message Persistence API for Python-Twisted SDK
updated_at: 2026-06-02T11:35:08.196Z
---

> 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-Twisted SDK

:::note Deprecated
**NOTICE:** Based on current web trends and our own usage data, PubNub's Python Twisted SDK is **deprecated** as of May 1, 2019. Deprecation means we will no longer be updating the Python Twisted SDK but will continue to support users currently using it. Please feel free to use our other Python SDK offerings as they will continue to be supported and maintained. If you would like to use the Python Twisted SDK specifically, we would love to work with you on keeping this project alive!
:::

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
This method requires that Message Persistence is [enabled](https://support.pubnub.com/hc/en-us/articles/360051974791-How-do-I-enable-add-on-features-for-my-keys-) for your key in the [Admin Portal](https://admin.pubnub.com/).
:::

This function fetches historical messages of a channel.

It is possible to control how messages are returned and in what order, for example you can:

* Search for messages starting on the newest end of the timeline (default behavior - `reverse` = `False`)
* Search for messages 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 time line by providing both a `start` AND `end` timetoken.
* Limit the number of messages to a specific quantity using the `count` parameter.

:::tip Start & End parameter usage clarity:
If only the `start` parameter is specified (without `end`), you will receive messages that are **older** than and up to that `start` timetoken value. If only the `end` parameter is specified (without `start`) you will receive messages that match that `end` timetoken value and **newer** Specifying values for both `start` *and* `end` parameters will return messages between those timetoken values (inclusive on the `end` value). Keep in mind that you will still receive a maximum of 100 messages even if there are more messages that meet the timetoken values. Iterative calls to history adjusting the `start` timetoken is necessary to page through the full set of results if more than 100 messages meet the timetoken values.
:::

### Method(s)

Use the following method(s) in the Python-Twisted 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 | `False` | Specifies whether or not the message's meta information should be returned. |
| reverse | Boolean | Optional | `False` | Setting to `True` will traverse the time line in reverse starting with the oldest message first. |
| include_timetoken | Boolean | Optional | `False` | Whether event dates timetokens should be included in response or not. |
| 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 |  | Specifies the 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

Retrieve the last 100 messages on a channel:

```python
envelope = yield pubnub.history()\
    .channel("history_channel")\
    .count(100)\
    .future()
```

### Returns

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

| 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 = yield 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
d = pubnub.history()\
    .channel("my_channel")\
    .start(13847168620721752)\
    .reverse(true)\
    .deferred()
d.addCallback(my_callback)
```

##### 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
d = pubnub.history()\
    .channel("my_channel")\
    .count(100)\
    .start(-1)\
    .end(13847168819178600)\
    .reverse(True)\
    .deferred()
d.addCallback(my_callback)
```

##### 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
@inlineCallbacks
def get_all_messages(start_tt):
     envelope = yield pubnub.history()\
         .channel('channel')\
         .count(100)\
         .start(start_tt)\
         .deferred()

     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:
         get_all_messages(start)
```

#### Include timetoken in history response

```python
d = pubnub.history()\
    .channel("my_channel")\
    .count(100)\
    .include_tometoken()
    .deferred()
d.addCallback(my_callback)
```

## Delete messages from history

:::warning Requires Message Persistence
This method requires that Message Persistence is [enabled](https://support.pubnub.com/hc/en-us/articles/360051974791-How-do-I-enable-add-on-features-for-my-keys-) for your key in the [Admin Portal](https://admin.pubnub.com/).
:::

Removes the messages from the history of a specific channel.

:::note
There is a setting to accept delete from history requests for a key, which you must enable by checking the Enable `Delete-From-History` checkbox in the key settings for your key in the Admin Portal.
Requires Initialization with secret key.
:::

### Method(s)

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

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

| Parameter | Description |
| --- | --- |
| `channel` *Type: StringDefault: n/a | Specifies `channels` to delete messages from. |
| `start`Type: IntDefault: n/a | timetoken delimiting the `start` of time slice (inclusive) to delete messages from. |
| `end`Type: IntDefault: n/a | timetoken delimiting the `end` of time slice (exclusive) to delete messages from. |

### Sample code

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

d.addCallback(my_callback)
```

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

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

d.addCallback(my_callback)
```

## Terms in this document

* **Channel** - A pathway for sending and receiving messages between devices, created automatically when you first use it, that can handle any number of users and messages for different communication needs, like 1-1 text chats, group conversations, and other data streaming.
* **Channel pattern** - A way to group and analyze channel data to track performance metrics like message counts and user engagement over time with PubNub Insights.
* **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.
* **Timetoken** - A unique identifier for each message that represents the number of 100-nanosecond intervals since January 1, 1970, for example, 16200000000000000.
