---
source_url: https://www.pubnub.com/docs/sdks/go/api-reference/message-actions
title: Message Actions API for Go SDK
updated_at: 2026-05-29T11:10:52.645Z
sdk_name: PubNub Go SDK
sdk_version: 8.2.0
---

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

PubNub Go SDK, use the latest version: 8.2.0

Install:

```bash
go get github.com/pubnub/go/v8@8.2.0
```

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

```go
pn.AddMessageAction().
    Channel(string).
    MessageTimetoken(string).
    Action(pubnub.MessageAction).
    Execute()
```

| Parameter | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| Channel | string | Yes |  | Channel name to add the message action to. |
| MessageTimetoken | string | Yes |  | Timetoken of the target message. |
| Action | pubnub.MessageAction | Yes |  | Message action payload: `ActionType` (type) and `ActionValue` (value). |

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

```go
// Replace with your package name (usually "main")
package pubnub_samples_test

import (
	"fmt"

	pubnub "github.com/pubnub/go/v8"
)

// Example_addMessageAction demonstrates adding a reaction to a message
func Example_addMessageAction() {
	config := pubnub.NewConfigWithUserId(pubnub.UserId("demo-user"))
	config.SubscribeKey = "demo" // Replace with your subscribe key
	config.PublishKey = "demo"   // Replace with your publish key

	// snippet.hide
	config = setPubnubExampleConfigData(config)
	// snippet.show

	pn := pubnub.NewPubNub(config)

	// Publish a message first to get a timetoken
	publishResp, _, _ := pn.Publish().
		Channel("my-channel").
		Message("Hello, World!").
		Execute()

	messageTimetoken := fmt.Sprintf("%d", publishResp.Timestamp)

	response, status, err := pn.AddMessageAction().
		Channel("my-channel").
		MessageTimetoken(messageTimetoken). // Timetoken of the message to react to
		Action(pubnub.MessageAction{
			ActionType:  "reaction", // Type of action (e.g., "reaction", "receipt")
			ActionValue: "👍",        // Value (e.g., emoji, "read", "delivered")
		}).
		Execute()

	if err != nil {
		fmt.Printf("Error: %v\n", err)
		return
	}

	if status.StatusCode == 200 && response.Data.ActionTimetoken != "" {
		fmt.Println("Message action added successfully")
	}

	// Output:
	// Message action added successfully
}
```

### Returns

The `AddMessageAction()` operation returns a `PNAddMessageActionsResponse`:

| Property Name | Type | Description |
| --- | --- | --- |
| `Data` | PNMessageActionsResponse | See [PNMessageActionsResponse](#pnmessageactionsresponse). |

#### PNMessageActionsResponse

| Property Name | Type | Description |
| --- | --- | --- |
| `ActionType` | string | Message action type. |
| `ActionValue` | string | Message action value. |
| `ActionTimetoken` | string | Timetoken when the action was added. |
| `MessageTimetoken` | string | Timetoken of the target message. |

## 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 Go method:

```go
pn.RemoveMessageAction().
    Channel(string).
    MessageTimetoken(string).
    ActionTimetoken(string).
    Execute()
```

| Parameter | Description |
| --- | --- |
| `Channel` *Type: string | Channel name to remove the message action from. |
| `MessageTimetoken` *Type: string | Timetoken of the target message. |
| `ActionTimetoken` *Type: string | Timetoken of the message action to remove. |

### Sample code

```go
// Replace with your package name (usually "main")
package pubnub_samples_test

import (
	"fmt"

	pubnub "github.com/pubnub/go/v8"
)

// Example_removeMessageAction demonstrates removing a specific action from a message
func Example_removeMessageAction() {
	config := pubnub.NewConfigWithUserId(pubnub.UserId("demo-user"))
	config.SubscribeKey = "demo"
	config.PublishKey = "demo"

	// snippet.hide
	config = setPubnubExampleConfigData(config)
	// snippet.show

	pn := pubnub.NewPubNub(config)

	// Publish a message and add an action
	publishResp, _, _ := pn.Publish().
		Channel("my-channel").
		Message("Message to react to").
		Execute()

	messageTimetoken := fmt.Sprintf("%d", publishResp.Timestamp)

	addResp, _, _ := pn.AddMessageAction().
		Channel("my-channel").
		MessageTimetoken(messageTimetoken).
		Action(pubnub.MessageAction{
			ActionType:  "reaction",
			ActionValue: "👋",
		}).
		Execute()

	actionTimetoken := addResp.Data.ActionTimetoken

	// Remove a specific message action
	_, status, err := pn.RemoveMessageAction().
		Channel("my-channel").
		MessageTimetoken(messageTimetoken). // Timetoken of the original message
		ActionTimetoken(actionTimetoken).   // Timetoken of the action to remove
		Execute()

	if err != nil {
		fmt.Printf("Error: %v\n", err)
		return
	}

	if status.StatusCode == 200 {
		fmt.Println("Message action removed successfully")
	}

	// Output:
	// Message action removed successfully
}
```

### Returns

The `RemoveMessageAction()` operation returns a `PNRemoveMessageActionsResponse`:

| Property Name | Type | Description |
| --- | --- | --- |
| `Data` | interface | Empty object. |

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

:::note Truncated response
The number of message actions in the response may be truncated when internal limits are hit. If the response is truncated, a `more` property is returned with additional parameters. Send iterative calls to Message Persistence, adjusting the parameters to fetch more message actions.
:::

### Method(s)

Use this Go method:

```go
pn.GetMessageActions().
    Channel(string).
    Start(string).
    End(string).
    Limit(int).
    Execute()
```

| Parameter | Description |
| --- | --- |
| `Channel` *Type: string | Channel name to list message actions for. |
| `Start`Type: string | Message action timetoken for the start of the range (exclusive). |
| `End`Type: string | Message action timetoken for the end of the range (inclusive). |
| `Limit`Type: int | Number of actions to return. |

### Sample code

```go
// Replace with your package name (usually "main")
package pubnub_samples_test

import (
	"fmt"

	pubnub "github.com/pubnub/go/v8"
)

// Example_getMessageActions demonstrates retrieving all actions on a channel
func Example_getMessageActions() {
	config := pubnub.NewConfigWithUserId(pubnub.UserId("demo-user"))
	config.SubscribeKey = "demo"
	config.PublishKey = "demo"

	// snippet.hide
	config = setPubnubExampleConfigData(config)
	// snippet.show

	pn := pubnub.NewPubNub(config)

	// Publish a message and add an action to it
	publishResp, _, _ := pn.Publish().
		Channel("get-actions-channel").
		Message("Test message").
		Execute()

	messageTimetoken := fmt.Sprintf("%d", publishResp.Timestamp)

	pn.AddMessageAction().
		Channel("get-actions-channel").
		MessageTimetoken(messageTimetoken).
		Action(pubnub.MessageAction{
			ActionType:  "reaction",
			ActionValue: "😊",
		}).
		Execute()

	// Get all message actions in a channel
	response, status, err := pn.GetMessageActions().
		Channel("get-actions-channel").
		Limit(25). // Limit number of results
		Execute()

	if err != nil {
		fmt.Printf("Error: %v\n", err)
		return
	}

	if status.StatusCode == 200 && len(response.Data) > 0 {
		fmt.Println("Message actions retrieved successfully")
		// Print the first message action as an example
		action := response.Data[0]
		fmt.Printf("Example action: %s = %s (by %s)\n",
			action.ActionType, action.ActionValue, action.UUID)
	}

	// Output:
	// Message actions retrieved successfully
	// Example action: reaction = 😊 (by GO_SDK_EXAMPLE_USER)
}
```

### Returns

The `GetMessageActions()` operation returns a `PNGetMessageActionsResponse`:

| Property Name | Type | Description |
| --- | --- | --- |
| `Data` | []PNMessageActionsResponse | See [PNMessageActionsResponse](#pnmessageactionsresponse). |
| `More` | PNGetMessageActionsMore | See [PNGetMessageActionsMore](#pngetmessageactionsmore). |

#### PNGetMessageActionsMore

| Property Name | Type | Description |
| --- | --- | --- |
| `URL` | string | URL of the next set of results. |
| `Start` | string | Start parameter for the next set of results. |
| `End` | string | End parameter for the next set of results. |
| `Limit` | int | Limit for the next set of results. |

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