---
source_url: https://www.pubnub.com/docs/sdks/cocoa-swift/api-reference/message-actions
title: Message Actions API for Cocoa Swift SDK
updated_at: 2026-05-27T17:02:09.157Z
---

> 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 Actions API for Cocoa Swift SDK

This SDK has been replaced by a new PubNub Swift SDK written purely in Swift. Check out the [Swift SDK documentation](https://www.pubnub.com/docs/sdks/swift).

Use message actions to add or remove metadata on published messages. Common uses include receipts and reactions. Clients subscribe to a channel to receive message action events. Clients can also fetch past message actions from Message Persistence, either on demand or when fetching original messages.

:::tip Reactions
"Message Reactions" is a specific application of the Message Actions API for emoji or social reactions.
:::

:::note Message Actions vs. Message Reactions
**Message Actions** is the flexible, low-level API for adding any metadata to messages (read receipts, delivery confirmations, custom data), while **Message Reactions** specifically refers to using Message Actions for emoji/social reactions.
In PubNub [Core](https://www.pubnub.com/docs/sdks) and [Chat](https://www.pubnub.com/docs/chat/overview) SDKs, the same underlying Message Actions API is referred to as **Message Reactions** when used for emoji reactions - it's the same functionality, just different terminology depending on the use case.
:::

## Add message action

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

Add an action to a published message. The response includes the added action.

### Method(s)

Use this Swift method:

```swift
open func addMessageAction(with: PNAddMessageActionRequest, completion: PNAddMessageActionCompletionBlock?)
```

| Parameter | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| request | PNAddMessageActionRequest | Yes |  | Request containing the message action details. |
| closure | PNAddMessageActionCompletionBlock | Optional |  | Completion closure. |

#### PNAddMessageActionRequest

| Parameter | Description |
| --- | --- |
| `type` *Type: String | Message action type. Maximum `15` characters. |
| `value` *Type: String | Message action value. |
| `channel` *Type: String | Channel name of the target message. |
| `messageTimetoken` *Type: NSNumber | Timetoken of the target message. |

### Sample code

```swift
let request = PNAddMessageActionRequest(channel: "chat", messageTimetoken: 1234567890)
request.type = "reaction"
request.value = "smile"

self.client.addMessageAction(with: request, completion: { status in
    if !status.isError {
        /**
         * Message action successfully added.
         * Created message action information available here: status.data.action
         */
    } else {
        if status.statusCode == 207 {
            // Message action has been added, but event not published.
        } else {
            /**
             * Handle add message action error. Check 'category' property to find out possible
             * issue because of which request did fail.
             *
             * Request can be resent using: status.retry()
             */
        }
    }
})
```

### Response

```swift
open class PNAddMessageActionData : PNServiceData {
    // Added message action.
    open var action: PNMessageAction? { get }
}

open class PNAddMessageActionStatus : PNAcknowledgmentStatus {
    // Add message action request processed information.
    open var data: PNAddMessageActionData { get }
}
```

## Add message action (builder pattern)

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

Add an action to a published message. The response includes the added action.

### Method(s)

Use this Swift method:

```swift
addMessageAction()
    .channel(String)
    .messageTimetoken(NSNumber)
    .type(String)
    .value(String)
    .performWithCompletion(PNAddMessageActionCompletionBlock?)
```

| Parameter | Description |
| --- | --- |
| `channel` *Type: String | Channel name of the target message. |
| `messageTimetoken` *Type: NSNumber | Timetoken of the target message. |
| `type` *Type: String | Message action type. |
| `value` *Type: String | Message action value. |
| `closure`Type: PNAddMessageActionCompletionBlock | Completion closure. |

### Sample code

```swift
self.client.addMessageAction()
    .channel("chat")
    .messageTimetoken(1234567890)
    .type("reaction")
    .value("smile")
    .performWithCompletion({ status in
        if !status.isError {
            /**
             * Message action successfully added.
             * Created message action information available here: status.data.action
             */
        } else {
            if status.statusCode == 207 {
                // Message action has been added, but event not published.
            } else {
                /**
                 * Handle add message action error. Check 'category' property to find out possible
                 * issue because of which request did fail.
                 *
                 * Request can be resent using: status.retry()
                 */
            }
        }
    })
```

### Response

```swift
open class PNAddMessageActionData : PNServiceData {
    // Added message action.
    open var action: PNMessageAction? { get }
}

open class PNAddMessageActionStatus : PNAcknowledgmentStatus {
    // Add message action request processed information.
    open var data: PNAddMessageActionData { get }
}
```

## Remove message action

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

Remove a previously added action from a published message. The response is empty.

### Method(s)

Use this Swift method:

```swift
open func removeMessageAction(
    with request: PNRemoveMessageActionRequest,
    completion: PNRemoveMessageActionCompletionBlock?
)
```

| Parameter | Description |
| --- | --- |
| `request` *Type: [PNRemoveMessageActionRequest](#pnremovemessageactionrequest) | Request containing the message action to remove. |
| `closure`Type: PNRemoveMessageActionCompletionBlock | Completion closure. |

#### PNRemoveMessageActionRequest

| Parameter | Description |
| --- | --- |
| `actionTimetoken` *Type: NSNumber | Timetoken of the message action to remove. |
| `channel` *Type: NSString | Channel name of the target message. |
| `messageTimetoken` *Type: NSNumber | Timetoken of the target message. |

### Sample code

```swift
let request = PNRemoveMessageActionRequest(channel: "chat", messageTimetoken: 1234567890)
request.actionTimetoken = 1234567891

self.client.removeMessageAction(with: request, completion: { status in
    if !status.isError {
        // Message action successfully removed.
    } else {
        /**
         * Handle remove message action error. Check 'category' property to find out possible
         * issue because of which request did fail.
         *
         * Request can be resent using: status.retry()
         */
    }
})
```

### Response

```swift
open class PNErrorData : PNServiceData {
    // Stringified error information.
    open var information: String { get }
}

open class PNAcknowledgmentStatus : PNErrorStatus {
    // Whether status object represent error or not.
    open var isError: Bool { get }

    // Additional information related to error status object.
    open var data: PNErrorData { get }
}
```

## Remove message action (builder pattern)

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

Remove a previously added action from a published message. The response is empty.

### Method(s)

```swift
removeMessageAction()
    .channel(String)
    .messageTimetoken(NSNumber)
    .actionTimetoken(NSNumber)
    .performWithCompletion(PNRemoveMessageActionCompletionBlock?)
```

| Parameter | Description |
| --- | --- |
| `channel` *Type: String | Channel name of the target message. |
| `messageTimetoken` *Type: NSNumber | Timetoken of the target message. |
| `actionTimetoken` *Type: NSNumber | Timetoken of the message action to remove. |
| `closure`Type: PNCreateSpaceCompletionBlock | Completion closure. |

### Sample code

```swift
self.client.removeMessageAction()
    .channel("channel")
    .messageTimetoken(1234567890)
    .actionTimetoken(1234567891)
    .performWithCompletion({ status in
        if !status.isError {
            // Message action successfully removed.
        } else {
            /**
             * Handle remove message action error. Check 'category' property to find out possible
             * issue because of which request did fail.
             *
             * Request can be resent using: status.retry()
            */
        }
    })
```

### Response

```swift
open class PNErrorData : PNServiceData {
    // Stringified error information.
    open var information: String { get }
}

open class PNAcknowledgmentStatus : PNErrorStatus {
    // Whether status object represent error or not.
    open var isError: Bool { get }

    // Additional information related to error status object.
    open var data: PNErrorData { get }
}
```

## Get message actions

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

Get a list of message actions in a channel. The response sorts actions by the action timetoken in ascending order.

### Method(s)

Use this Swift method:

```swift
open func fetchMessageActions(
    with request: PNFetchMessageActionsRequest,
    completion: PNFetchMessageActionsCompletionBlock
)
```

| Parameter | Description |
| --- | --- |
| `request` *Type: [PNFetchMessageActionsRequest](#pnfetchmessageactionsrequest) | Request with parameters to fetch message actions. |
| `closure` *Type: PNFetchMessageActionsCompletionBlock | Completion closure. |

#### PNFetchMessageActionsRequest

| Parameter | Description |
| --- | --- |
| `start` *Type: NSNumber | Message action timetoken for the start of the range (exclusive). |
| `end` *Type: NSNumber | Message action timetoken for the end of the range (inclusive). |
| `limit` *Type: UInt | Number of message actions to return. |
| `channel` *Type: String | Channel name to list message actions for. |

### Sample code

```swift
self.client.fetchMessageActions()
    .channel("chat")
    .start(1234567891)
    .limit(200)
    .performWithCompletion({ (result, status) in
        if !(status?.isError ?? false) {
            /**
             * Message actions successfully fetched.
             * Result object has following information:
             *     result.data.actions - list of message action instances
             *     result.data.start - fetched messages actions time range start (oldest message
             *         action timetoken).
             *     result.data.end - fetched messages actions time range end (newest action timetoken).
            */
        } else {
            /**
             * Handle fetch message actions error. Check 'category' property to find out possible
             * issue because of which request did fail.
             *
             * Request can be resent using: status.retry()
            */
        }
    })
```

### Response

```swift
open class PNFetchMessageActionsData : PNServiceData {
    // List of fetched messages actions.
    open var actions: [PNMessageAction] { get }

    /**
     * Fetched messages actions time range start (oldest message action timetoken).
     *
     * This timetoken can be used as 'start' value to fetch older messages actions.
    */
    open var start: NSNumber { get }

    // Fetched messages actions time range end (newest action timetoken).
    open var end: NSNumber { get }
}

open class PNFetchMessageActionsResult : PNResult {
    // Fetch message reactions request processed information.
    open var data: PNFetchMessageActionsData { get }
}
```

Error response which is used in case of Message Reaction API call failure:

```swift
open class PNErrorData : PNServiceData {
    // Stringified error information.
    open var information: String { get }
}

open class PNErrorStatus : PNStatus {
    // Whether status object represent error or not.
    open var isError: Bool { get }

    // Additional information related to error status object.
    open var data: PNErrorData { get }
}
```

## Get Message Reactions (builder pattern)

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

Get a list of message reactions in a `channel`. Returns a list of actions sorted by the action's timetoken in ascending order.

### Method(s)

To Get Message Reactions you can use the following method(s) in the Swift SDK:

```swift
fetchMessageActions()
    .channel(String)
    .start(NSNumber)
    .end(NSNumber)
    .limit(UInt)
    .performWithCompletion(PNFetchMessageActionsCompletionBlock)
```

| Parameter | Description |
| --- | --- |
| `channel` *Type: String | Name of channel from which list of messages `actions` should be retrieved. |
| `start`Type: NSNumber | Message reaction timetoken denoting the start of the range requested. Return values will be less than start. |
| `end`Type: NSNumber | Message reaction timetoken denoting the end of the range requested. Return values will be greater than or equal to end. |
| `limit`Type: UInt | Number of message reactions to return in response. |
| `closure` *Type: PNFetchMessageActionsCompletionBlock | `Fetch message reactions` request completion `closure`. |

### Sample code

```swift
self.client.fetchMessageActions()
    .channel("chat")
    .start(1234567891)
    .limit(200)
    .performWithCompletion({ (result, status) in
        if !(status?.isError ?? false) {
            /**
             * Message reaction successfully fetched.
             * Result object has following information:
             *     result.data.actions - list of message reaction instances
             *     result.data.start - fetched messages actions time range start (oldest message
             *         action timetoken).
             *     result.data.end - fetched messages actions time range end (newest action timetoken).
            */
        } else {
            /**
             * Handle fetch message reactions error. Check 'category' property to find out possible
             * issue because of which request did fail.
             *
             * Request can be resent using: status.retry()
            */
        }
    })
```

### Response

Response objects which is returned by client when `fetch message reactions` Message Reaction API is used:

```swift
open class PNFetchMessageActionsData : PNServiceData {
    // List of fetched messages actions.
    open var actions: [PNMessageAction] { get }

    /**
     * Fetched messages actions time range start (oldest message reaction timetoken).
     *
     * This timetoken can be used as 'start' value to fetch older messages reactions.
    */
    open var start: NSNumber { get }

    // Fetched messages actions time range end (newest action timetoken).
    open var end: NSNumber { get }
}

open class PNFetchMessageActionsResult : PNResult {
    // Fetch message reactions request processed information.
    open var data: PNFetchMessageActionsData { get }
}
```

### Error response

```swift
open class PNErrorData : PNServiceData {
    // Stringified error information.
    open var information: String { get }
}

open class PNErrorStatus : PNStatus {
    // Whether status object represent error or not.
    open var isError: Bool { get }

    // Additional information related to error status object.
    open var data: PNErrorData { get }
}
```

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