---
source_url: https://www.pubnub.com/docs/chat/sdks/messages/message-receipts
title: Message receipts and reactions (deprecated)
updated_at: 2026-06-10T11:18:09.318Z
---

> 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 receipts and reactions (deprecated)

:::warning Use Chat SDKs
This documentation is deprecated. Use any of our dedicated [Chat SDKs](https://www.pubnub.com/docs/chat/overview) to quickly implement chat functionality in your application.
:::

[Message receipts](#add-a-receipt) enable users to track delivery of messages in a channel. Receipts are most useful in direct one-to-one chats, or in small group chats to indicate that users have read a particular message. They're not commonly used in high-occupancy chats, or in broadcasts with many users.

There are two kinds of receipts:

* *Delivered receipts* indicate that the message has been delivered to a user
* *Read receipts* indicate that a user has read the message

:::note User ID / UUID
User ID is also referred to as **UUID/uuid** in some APIs and server responses but **holds the value** of the **userId** parameter you [set during initialization](https://www.pubnub.com/docs/general/setup/users-and-devices#set-the-user-id).
:::

## Add a receipt

Use the [addMessageAction](https://www.pubnub.com/docs/sdks/javascript/api-reference/message-actions#add-message-reaction) method to add a receipt on a channel by passing the timetoken of a message. Set the value to `message_delivered` or `message_read` to indicate if the message was delivered and received by the user, or if it was read.

Your application needs to implement client-side logic to determine when receipts should be added. Add receipts when the user comes and goes from a channel, or periodically after every few messages. For efficiency, assume that when a message is marked read, all messages published before that message are also read by the user.

### JavaScript

```js
pubnub.addMessageAction(
  {
    channel: 'ch-1'
    messageTimetoken: '15610547826970040',
    action: {
      type: 'receipt',
      value: 'read',
    },
  },
  function(status, response) {

  }
);
```

### Swift

```swift
extension MyAppMessageAction: MessageAction {}

let action = MyAppMessageAction(type: "receipt", value: "read")

pubnub.addMessageAction(
  channel: "ch-1",
  message: action,
  messageTimetoken: 15610547826970040
) { result in
  switch result {
  case let .success(response):
    print("Successfully Message Reaction Add Response: \(response)")
  case let .failure(error):
    print("Error from failed response: \(error.localizedDescription)")
  }
})
```

### Java

```java
pubnub.addMessageAction()
    .channel("ch-1")
    .messageAction(new PNMessageAction()
            .setType("receipt")
            .setValue("read")
            .setMessageTimetoken(15610547826970040L)
    )
    .async(result -> {
        result.onSuccess(res -> {
            System.out.println(res.getType());
            System.out.println(res.getValue());
            System.out.println(res.getUuid());
            System.out.println(res.getActionTimetoken());
            System.out.println(res.getMessageTimetoken());
        }).onFailure(exception -> {
            exception.printStackTrace();
        });
    });
```

### Unity

```csharp
MessageActionAdd messageAct = new MessageActionAdd();
messageAct.ActionType = "receipt";
messageAct.ActionValue = "read";

pubnub.AddMessageActions().Channel("ch-1").MessageAction(messageAct).MessageTimetoken(15610547826970040).Async((result, status) => {
        if (!status.Error) {
            Debug.Log("result.ActionTimetoken: " + result.ActionTimetoken);
            Debug.Log("result.ActionType: " + result.ActionType);
            Debug.Log("result.ActionValue: " + result.ActionValue);
            Debug.Log("result.MessageTimetoken: " + result.MessageTimetoken);
            Debug.Log("result.UserID: " + result.UserId);
        } else {
            Debug.Log(status.Error);
            Debug.Log(status.ErrorData.Info);
        }

});
```

## Remove a receipt

Use the [removeMessageAction()](https://www.pubnub.com/docs/sdks/javascript/api-reference/message-actions#remove-message-reaction) method to remove a receipt from a message by providing an `actionTimetoken` and `messageTimetoken` for the original message.

### JavaScript

```js
pubnub.removeMessageAction(
  {
    channel: 'ch-1'
    messageTimetoken: '15610547826970040',
    actionTimetoken: '15610547826999081',
  },
  function(status, response) {

  }
);
```

### Swift

```swift
pubnub.removeMessageActions(
  channel: "ch-1",
  message: 15610547826970040,
  action: 15610547826999081
) { result in
  switch result {
  case let .success(response):
    print("Successfully Message Reaction Remove Response: \(response)")
  case let .failure(error):
    print("Error from failed response: \(error.localizedDescription)")
  }
})
```

### Java

```java
pubnub.removeMessageAction()
    .channel("ch-1")
    .messageTimetoken(15610547826970040L)
    .actionTimetoken(15610547826999081L)
    .async(result -> { /* check result */ });
```

### Unity

```csharp
pubnub.RemoveMessageActions().ActionTimetoken(15610547826999081).Channel("ch-1").MessageTimetoken(15610547826970040).Async((result, status) => {
        if (!status.Error) {
            // result has no actionable data
        } else {
            Debug.Log(status.Error);
            Debug.Log(status.ErrorData.Info);
        }
});
```

## Fetch receipts in channel

Receipts are stored in history alongside messages when they are added by a user.

Use the [getMessageActions](https://www.pubnub.com/docs/sdks/javascript/api-reference/message-actions#get-message-reactions) method to fetch receipts in a channel. The method works much like other PubNub history methods, and allows you to pass a start and end timetoken and fetch all message reactions that were published during that time. Your app can parse through these actions and update the message state locally.

### JavaScript

```javascript
pubnub.getMessageActions(
  {
    channel: 'chats.room1',
    start: '15901706735798836',
    end: '15901706735370016',
    limit: 100,
  },
  function(status, response) {
    console.log(status, response);
  }
);
```

### Swift

```swift
pubnub.fetchMessageActions(
  channel: "chats.room1") { result in
    switch result {
    case let .success(response):
      print("Successfully Message Reaction Fetch Response: \(response)")

    case let .failure(error):
      print("Error from failed response: \(error.localizedDescription)")
    }
})
```

### Objective-C

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

request.start = @(1234567891);
request.limit = 100;

[self.pubnub fetchMessageActionsWithRequest:request
      completion:^(PNFetchMessageActionsResult *result, PNErrorStatus *status) {

  if (!status.isError) {

  }
  else {

  }
}];
```

### Java

```java
pubnub.getMessageActions()
  .channel("chats.room1")
  .async(result -> {
      result.onSuccess(res -> {
          List<PNMessageAction> actions = res.getActions();
          for (PNMessageAction action : actions) {
              System.out.println(action.getType());
              System.out.println(action.getValue());
              System.out.println(action.getUuid());
              System.out.println(action.getActionTimetoken());
              System.out.println(action.getMessageTimetoken());
          }
      }).onFailure(exception -> {
          exception.printStackTrace();
      });
  });
```

### C#

```csharp
pubnub.GetMessageActions()
  .Channel("chats.room1")
  .Execute(new PNGetMessageActionsResultExt((result, status) =>
  {

  }));
```

**Return Type**: `PNGetMessageActionsResult`

```json
{
  "MessageActions":[{
    "MessageTimetoken":15610547826970040,
    "Action":{
        "type":"reaction",
        "value":"smiley_face"
    },
    "Uuid":"pn-5903a053-592c-4a1e-8bfd-81d92c962968",
    "ActionTimetoken":15610547826999081
  }],
}
```

### Python

```python
pubnub.get_message_actions()
        .channel('chats.room1')
        .start(15901706735798836) # Some start timetoken or None
        .end(15901706735370016) # Some end timetoken or None
        .pn_async(message_action_callback)
```

## Fetch messages with receipts

Use the [fetchMessages](https://www.pubnub.com/docs/sdks/javascript/api-reference/storage-and-playback#fetch-history) method with the `includeMessageActions` parameter set to fetch past messages in a channel along with receipts that were added to those messages. When you're fetching messages with their receipts, you can only fetch on a single channel at a time.

## Message receipt events

PubNub triggers events to notify clients when receipts are added to or removed from messages. To receive these events, clients should be subscribed to the channel, and add a `messageAction` listener in the code.

| Event | Description |
| --- | --- |
| Message Reaction Added | Generated when a message reaction is added to a message. |
| Message Reaction Removed | Generated when a message reaction is removed from a message. |

Message Reaction Added:

```json
{
   "channel":"my_channel",
   "subscription":null,
   "timetoken":"15610547826970040",
   "publisher":"user-1",
   "message":{
      "source":"actions",
      "version":"1.0",
      "action":"added",
      "data":{
         "type":"receipt",
         "value":"read",
         "messageTimetoken":"15610547826970040",
         "actionTimetoken":"15610547826999081"
      }
   }
}
```

Message Reaction Removed:

```json
{
   "channel":"my_channel",
   "subscription":null,
   "timetoken":"15610547826970040",
   "publisher":"user-1",
   "message":{
      "source":"actions",
      "version":"1.0",
      "action":"removed",
      "data":{
         "type":"receipt",
         "value":"read",
         "messageTimetoken":"15610547826970040",
         "actionTimetoken":"15610547826999081"
      }
   }
}
```