---
source_url: https://www.pubnub.com/docs/sdks/go/api-reference/objects
title: App Context API for Go SDK
updated_at: 2026-06-18T11:27:37.481Z
sdk_name: PubNub Go SDK
sdk_version: v9.0.1
---

> 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


# App Context API for Go SDK

PubNub Go SDK, use the latest version: v9.0.1

Install:

```bash
go get github.com/pubnub/go/v9@v9.0.1
```

This page describes App Context (formerly Objects v2). To upgrade from Objects v1, refer to the [migration guide](https://www.pubnub.com/docs/general/resources/migration-guides/objects-v2-migration).

App Context provides easy-to-use, serverless storage for user and channel data you need to build innovative, reliable, scalable applications. Use App Context to store metadata about your application users and channels, and their membership associations, without the need to stand up your own databases.

PubNub also triggers events when object data is changed: set, updated, or removed from the database. Making a request to set the same data that already exists doesn't trigger an event. Clients can receive these events in real time and update their front-end application accordingly.

## User

### Get metadata for all users

Returns a paginated list of UUID Metadata objects, optionally including the custom data object for each.

:::warning Required keyset configuration
To get all channel and user metadata, you must uncheck the
Disallow Get All Channel Metadata
and
Disallow Get All User Metadata
checkboxes in the App Context section of your keyset configuration in the
[Admin Portal](https://admin.pubnub.com)
.
:::

#### Method(s)

To `Get All UUID Metadata` you can use the following method(s) in the Go SDK:

```go
pn.GetAllUUIDMetadata().
    Include([]pubnub.PNUUIDMetadataIncludeCustom).
    Sort(sort).
    Limit(int).
    Count(bool).
    Start(string).
    End(string).
    Filter(string).
    Execute()
```

| Parameter | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| Include | []pubnub.PNUUIDMetadataInclude | Optional |  | List of additional/complex UUID attributes to include in response. Omit this parameter if you don't want to retrieve additional attributes. **Available values:** `pubnub.PNUUIDMetadataIncludeCustom` |
| Sort | Array | Optional |  | Sort by `id`, `name`, `updated` with `asc`/`desc` for sort direction (for example, `{name: 'asc'}`). |
| Limit | int | Optional |  | Number of objects to return. Default/Max: 100. |
| Count | bool | Optional |  | Whether to include the total count in the paginated response. Default is false. |
| Start | string | Optional |  | Cursor-based pagination. |
| End | string | Optional |  | Cursor-based pagination. |
| Filter | string | Optional |  | Filter expression. Only matching objects are returned. See [filtering](https://www.pubnub.com/docs/general/metadata/filtering). |

#### 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"
	"time"

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

// Example_getAllUUIDMetadataWithIncludes demonstrates listing all users with all include options
func Example_getAllUUIDMetadataWithIncludes() {
	config := pubnub.NewConfigWithUserId(pubnub.UserId("demo-user"))
	config.SubscribeKey = "demo"
	config.PublishKey = "demo"

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

	pn := pubnub.NewPubNub(config)

	// snippet.hide
	defer pn.RemoveUUIDMetadata().UUID("user-all-list-1").Execute()
	// snippet.show

	// Create user with all fields
	pn.SetUUIDMetadata().
		UUID("user-all-list-1").
		Name("Full User").
		Custom(map[string]interface{}{"role": "admin"}).
		Status("active").
		Type("staff").
		Execute()

	// Get all users with all include options
	response, status, err := pn.GetAllUUIDMetadata().
		Include([]pubnub.PNUUIDMetadataInclude{
			pubnub.PNUUIDMetadataIncludeCustom, // Include custom fields
			pubnub.PNUUIDMetadataIncludeStatus, // Include status field
			pubnub.PNUUIDMetadataIncludeType,   // Include type field
		}).
		Limit(10).
		Execute()

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

	if status.StatusCode == 200 && len(response.Data) > 0 {
		fmt.Println("Retrieved users with all metadata fields")
	}

	// Output:
	// Retrieved users with all metadata fields
}
```

#### Response

The `GetAllUUIDMetadata()` operation returns a `PNGetAllChannelMetadataResponse` which contains the following parameters:

| Property Name | Type | Description |
| --- | --- | --- |
| `Data` | []PNUUID | Details of type `PNUUID` are [here](#pnuuid) |
| `TotalCount` | int | Total count of objects without pagination. |
| `Next` | string | Random string returned from the server, indicating a specific position in a data set. Used for forward pagination, it fetches the next page, allowing you to continue from where you left off. |
| `Prev` | string | Random string returned from the server, indicating a specific position in a data set. Used for backward pagination, it fetches the previous page, enabling access to earlier data. Ignored if the `Next` parameter is supplied. |

### Get user metadata

Returns metadata for the specified UUID, optionally including the custom data object for each.

#### Method(s)

To `Get UUID Metadata` you can use the following method(s) in the Go SDK:

```go
pn.PNUUIDMetadataInclude().
    Include([]pubnub.PNUUIDMetadataIncludeCustom).
    Sort(sort).
    ID(string).
    Execute()
```

| Parameter | Description |
| --- | --- |
| `Include`Type: []pubnub.PNUUIDMetadataIncludeCustom | List of additional/complex UUID attributes to include in response. Omit this parameter if you don't want to retrieve additional attributes. **Available values** `pubnub.PNUUIDMetadataIncludeCustom` |
| `Sort`Type: Array | Sort by `id`, `name`, `updated` with `asc`/`desc` for sort direction (for example, `{name: 'asc'}`). |
| `ID` *Type: string | UUID. If not supplied, the current user's UUID is used. |

#### Sample code

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

import (
	"fmt"
	"time"

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

// Example_getUUIDMetadataWithIncludes demonstrates retrieving user metadata with all include options
func Example_getUUIDMetadataWithIncludes() {
	config := pubnub.NewConfigWithUserId(pubnub.UserId("demo-user"))
	config.SubscribeKey = "demo"
	config.PublishKey = "demo"

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

	pn := pubnub.NewPubNub(config)

	// snippet.hide
	defer pn.RemoveUUIDMetadata().UUID("user-with-all").Execute()
	// snippet.show

	// Create user metadata with all fields
	pn.SetUUIDMetadata().
		UUID("user-with-all").
		Name("Complete User").
		Custom(map[string]interface{}{
			"department": "engineering",
		}).
		Status("active").
		Type("employee").
		Execute()

	// Get user metadata with all include options
	response, status, err := pn.GetUUIDMetadata().
		UUID("user-with-all").
		Include([]pubnub.PNUUIDMetadataInclude{
			pubnub.PNUUIDMetadataIncludeCustom, // Include custom fields
			pubnub.PNUUIDMetadataIncludeStatus, // Include status field
			pubnub.PNUUIDMetadataIncludeType,   // Include type field
		}).
		Execute()

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

	if status.StatusCode == 200 {
		fmt.Printf("User: %s\n", response.Data.Name)
		fmt.Printf("Status: %s\n", response.Data.Status)
		fmt.Printf("Type: %s\n", response.Data.Type)
		if dept, ok := response.Data.Custom["department"].(string); ok {
			fmt.Printf("Department: %s\n", dept)
		}
	}

	// Output:
	// User: Complete User
	// Status: active
	// Type: employee
	// Department: engineering
}
```

#### Response

The `GetUUIDMetadata()` operation returns a `PNGetUUIDMetadataResponse` which contains the following parameters:

| Property Name | Type | Description |
| --- | --- | --- |
| `Data` | PNUUID | Details of type `PNUUID` are [here](#pnuuid) |

### Set user metadata

:::warning Unsupported partial updates of custom metadata
The value of the custom metadata parameter sent in this method always overwrites the value stored on PubNub servers. If you want to add new custom data to an existing one, you must:
1. Get the existing metadata and store it locally.
2. Append the new custom metadata to the existing one.
3. Set the entire updated custom object.
:::

Set metadata for a UUID in the database, optionally including the custom data object for each.

#### Method(s)

To `Set UUID Metadata` you can use the following method(s) in the Go SDK:

```go
pn.SetUUIDMetadata().
    Include([]pubnub.PNUUIDMetadataIncludeCustom).
    Sort(sort).
    ID(id).
    Name(string).
    ExternalID(string).
    ProfileURL(string).
    Email(string).
    Custom(map[string]interface{}).
    IfMatchETag(string).
    Execute()
```

| Parameter | Description |
| --- | --- |
| `Include`Type: []pubnub.PNUUIDMetadataInclude | List of additional/complex UUID attributes to include in response. Omit this parameter if you don't want to retrieve additional attributes. **Available values:** `pubnub.PNUUIDMetadataIncludeCustom` |
| `ID` *Type: string | Unique user identifier. If not supplied then current user's `uuid` is used. |
| `Sort`Type: Array | Sort by `id`, `name`, `updated` with `asc`/`desc` for sort direction (for example, `{name: 'asc'}`). |
| `Name` *Type: string | Display name for the user. |
| `ExternalID`Type: string | User's identifier in an external system |
| `ProfileURL`Type: string | The URL of the user's profile picture |
| `Email`Type: string | The user's email address. |
| `Custom`Type: `map[string]interface{}` | Custom JSON values. Can be strings, numbers, or booleans. [Filtering](https://www.pubnub.com/docs/general/metadata/filtering) by `Custom` isn't supported. |
| `IfMatchETag`Type: string | The entity tag to be used to ensure updates only happen if the object hasn't been modified since it was read. Use the eTag you received from an applicable get metadata method to check against the server entity tag. If the eTags don't match, an HTTP 412 error is thrown. |

:::tip API limits
To learn about the maximum length of parameters used to set user metadata, refer to [REST API docs](https://www.pubnub.com/docs/sdks/rest-api/set-user-metadata).
:::

#### Sample code

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

import (
	"fmt"
	"time"

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

// Example_setUUIDMetadata demonstrates setting user metadata (UUID metadata)
func Example_setUUIDMetadata() {
	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)

	// snippet.hide
	// Cleanup: Remove metadata after test
	defer pn.RemoveUUIDMetadata().UUID("user-123").Execute()
	// snippet.show

	// Set user metadata with profile information
	response, status, err := pn.SetUUIDMetadata().
		UUID("user-123").                                // User ID
		Name("John Doe").                                // Display name
		Email("john.doe@example.com").                   // Email address
		ProfileURL("https://example.com/profiles/john"). // Profile URL
		ExternalID("ext-123").                           // External system ID
		Custom(map[string]interface{}{                   // Custom metadata
			"role":     "admin",
			"language": "en",
		}).
		Execute()

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

	if status.StatusCode == 200 {
		fmt.Printf("User metadata set for UUID: %s\n", response.Data.ID)
	}

	// Output:
	// User metadata set for UUID: user-123
}
```

#### Response

The `SetUUIDMetadata()` operation returns a `PNSetUUIDMetadataResponse` which contains the following parameters:

| Property Name | Type | Description |
| --- | --- | --- |
| `Data` | PNUUID | Details of type `PNUUID` are [here](#pnuuid) |

#### PNUUID

| Property Name | Type | Description |
| --- | --- | --- |
| `ID` | string | Unique user identifier. If not supplied then current user's `uuid` is used. |
| `Name` | string | Display name for the user. |
| `ExternalID` | string | User's identifier in an external system |
| `ProfileURL` | string | The URL of the user's profile picture |
| `Email` | string | The user's email address. |
| `Custom` | map[string]interface | Custom JSON values. Can be strings, numbers, or booleans. |
| `Updated` | string | Last updated date. |
| `ETag` | string | The ETag. |
| `Status` | string | User status. Max. 50 characters. |
| `Type` | string | User type. Max. 50 characters. |

### Remove user metadata

Removes the metadata from a specified UUID.

#### Method(s)

To `Remove UUID Metadata` you can use the following method(s) in the Go SDK:

```go
pn.RemoveUUIDMetadata().
    ID(string).
    Execute()
```

| Parameter | Description |
| --- | --- |
| `ID` *Type: string | Unique user identifier. If not supplied then current user's `uuid` is used. |

#### Sample code

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

import (
	"fmt"
	"time"

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

// Example_removeUUIDMetadata demonstrates removing user metadata
func Example_removeUUIDMetadata() {
	config := pubnub.NewConfigWithUserId(pubnub.UserId("demo-user"))
	config.SubscribeKey = "demo"
	config.PublishKey = "demo"

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

	pn := pubnub.NewPubNub(config)

	// snippet.hide
	// Setup: Create metadata first
	pn.SetUUIDMetadata().UUID("user-to-remove").Name("Temp User").Execute()
	// snippet.show

	// Remove user metadata
	_, status, err := pn.RemoveUUIDMetadata().
		UUID("user-to-remove"). // User ID to remove
		Execute()

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

	if status.StatusCode == 200 {
		fmt.Println("User metadata removed successfully")
	}

	// Output:
	// User metadata removed successfully
}
```

#### Response

The `RemoveUUIDMetadata()` operation returns a `PNRemoveUUIDMetadataResponse` which contains the following parameters:

| Property Name | Type | Description |
| --- | --- | --- |
| `Data` | interface | Returns an empty interface. |

## Channel

### Get metadata for all channels

Returns a paginated list of Channel Metadata objects, optionally including the custom data object for each.

:::warning Required keyset configuration
To get all channel and user metadata, you must uncheck the
Disallow Get All Channel Metadata
and
Disallow Get All User Metadata
checkboxes in the App Context section of your keyset configuration in the
[Admin Portal](https://admin.pubnub.com)
.
:::

#### Method(s)

To `Get All Channel Metadata` you can use the following method(s) in the Go SDK:

```go
pn.GetAllChannelMetadata().
    Include([]pubnub.PNChannelMetadataInclude).
    Sort(sort).
    Limit(int).
    Count(bool).
    Start(string).
    End(string).
    Filter(string).
    Execute()
```

| Parameter | Description |
| --- | --- |
| `Include`Type: []pubnub.PNChannelMetadataInclude | List of additional/complex space attributes to include in response. Omit this parameter if you don't want to retrieve additional attributes. **Available values** `pubnub.PNChannelMetadataIncludeCustom` |
| `Sort`Type: Array | Sort by `id`, `name`, `updated` with `asc`/`desc` for sort direction (for example, `{name: 'asc'}`). |
| `Limit`Type: int | Number of objects to return. Default/Max: 100. |
| `Count`Type: bool | Whether to include the total count in the paginated response. Default is false. |
| `Start`Type: string | Cursor-based pagination. |
| `End`Type: string | Cursor-based pagination. |
| `Filter`Type: string | Filter expression. Only matching objects are returned. See [filtering](https://www.pubnub.com/docs/general/metadata/filtering). |

#### Sample code

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

import (
	"fmt"
	"time"

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

// Example_getAllChannelMetadataWithIncludes demonstrates listing all channels with all include options
func Example_getAllChannelMetadataWithIncludes() {
	config := pubnub.NewConfigWithUserId(pubnub.UserId("demo-user"))
	config.SubscribeKey = "demo"
	config.PublishKey = "demo"

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

	pn := pubnub.NewPubNub(config)

	// snippet.hide
	defer pn.RemoveChannelMetadata().Channel("channel-all-list-1").Execute()
	// snippet.show

	// Create channel with all fields
	pn.SetChannelMetadata().
		Channel("channel-all-list-1").
		Name("Full Channel").
		Custom(map[string]interface{}{"priority": "high"}).
		Status("active").
		Type("team").
		Execute()

	// Get all channels with all include options
	response, status, err := pn.GetAllChannelMetadata().
		Include([]pubnub.PNChannelMetadataInclude{
			pubnub.PNChannelMetadataIncludeCustom, // Include custom fields
			pubnub.PNChannelMetadataIncludeStatus, // Include status field
			pubnub.PNChannelMetadataIncludeType,   // Include type field
		}).
		Limit(10).
		Execute()

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

	if status.StatusCode == 200 && len(response.Data) > 0 {
		fmt.Println("Retrieved channels with all metadata fields")
	}

	// Output:
	// Retrieved channels with all metadata fields
}
```

#### Response

The `GetAllChannelMetadata()` operation returns a `PNGetAllChannelMetadataResponse` which contains the following parameters:

| Property Name | Type | Description |
| --- | --- | --- |
| `Data` | []PNChannel | Details of type `PNChannel` are [here](#pnchannel) |
| `TotalCount` | int | Total count of objects without pagination. |
| `Next` | string | Random string returned from the server, indicating a specific position in a data set. Used for forward pagination, it fetches the next page, allowing you to continue from where you left off. |
| `Prev` | string | Random string returned from the server, indicating a specific position in a data set. Used for backward pagination, it fetches the previous page, enabling access to earlier data. Ignored if the `Next` parameter is supplied. |

### Get channel metadata

Returns metadata for the specified Channel, optionally including the custom data object for each.

#### Method(s)

To `Get Channel Metadata` you can use the following method(s) in the Go SDK:

```go
pn.GetChannelMetadata().
    Include([]pubnub.PNChannelMetadataInclude).
     Sort(sort).
     ID(string).
     Execute()
```

| Parameter | Description |
| --- | --- |
| `Include`Type: []pubnub.PNChannelMetadataInclude | List of additional/complex space attributes to include in response. Omit this parameter if you don't want to retrieve additional attributes. **Available values** `pubnub.PNChannelMetadataIncludeCustom` |
| `Sort`Type: Array | Sort by `id`, `name`, `updated` with `asc`/`desc` for sort direction (for example, `{name: 'asc'}`). |
| `ID` *Type: string | UUID. If not supplied, the current user's UUID is used. |

#### Sample code

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

import (
	"fmt"
	"time"

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

// Example_getChannelMetadataWithIncludes demonstrates retrieving channel metadata with all include options
func Example_getChannelMetadataWithIncludes() {
	config := pubnub.NewConfigWithUserId(pubnub.UserId("demo-user"))
	config.SubscribeKey = "demo"
	config.PublishKey = "demo"

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

	pn := pubnub.NewPubNub(config)

	// snippet.hide
	defer pn.RemoveChannelMetadata().Channel("channel-with-all").Execute()
	// snippet.show

	// Create channel metadata with all fields
	pn.SetChannelMetadata().
		Channel("channel-with-all").
		Name("Complete Channel").
		Description("Full featured channel").
		Custom(map[string]interface{}{
			"category": "general",
		}).
		Status("active").
		Type("public").
		Execute()

	// Small delay to ensure metadata is persisted before retrieval
	time.Sleep(2 * time.Second)

	// Get channel metadata with all include options
	response, status, err := pn.GetChannelMetadata().
		Channel("channel-with-all").
		Include([]pubnub.PNChannelMetadataInclude{
			pubnub.PNChannelMetadataIncludeCustom, // Include custom fields
			pubnub.PNChannelMetadataIncludeStatus, // Include status field
			pubnub.PNChannelMetadataIncludeType,   // Include type field
		}).
		Execute()

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

	if status.StatusCode == 200 {
		fmt.Printf("Channel: %s\n", response.Data.Name)
		fmt.Printf("Status: %s\n", response.Data.Status)
		fmt.Printf("Type: %s\n", response.Data.Type)
		if cat, ok := response.Data.Custom["category"].(string); ok {
			fmt.Printf("Category: %s\n", cat)
		}
	}

	// Output:
	// Channel: Complete Channel
	// Status: active
	// Type: public
	// Category: general
}
```

#### Response

The `GetChannelMetadata()` operation returns a `PNGetChannelMetadataResponse` which contains the following parameters:

| Property Name | Type | Description |
| --- | --- | --- |
| `Data` | PNChannel | Details of type `PNChannel` are [here](#pnchannel) |

### Set channel metadata

:::warning Unsupported partial updates of custom metadata
The value of the custom metadata parameter sent in this method always overwrites the value stored on PubNub servers. If you want to add new custom data to an existing one, you must:
1. Get the existing metadata and store it locally.
2. Append the new custom metadata to the existing one.
3. Set the entire updated custom object.
:::

Set metadata for a Channel in the database, optionally including the custom data object for each.

#### Method(s)

To `Set Channel Metadata` you can use the following method(s) in the Go SDK:

```go
pn.SetChannelMetadata().
    Include([]pubnub.PNChannelMetadataInclude).
    Sort(sort).
    ID(string).
    Name(string).
    Description(string).
    Custom(map[string]interface{}).
    IfMatchETag(string).
    Execute()
```

| Parameter | Description |
| --- | --- |
| `Include`Type: []pubnub.PNChannelMetadataInclude | List of additional/complex space attributes to include in response. Omit this parameter if you don't want to retrieve additional attributes. **Available values** `pubnub.PNChannelMetadataIncludeCustom` |
| `Sort`Type: Array | Sort by `id`, `name`, `updated` with `asc`/`desc` for sort direction (for example, `{name: 'asc'}`). |
| `ID` *Type: string | Unique user identifier. If not supplied then current user's `uuid` is used. |
| `Name` *Type: string | Name of a channel. |
| `Description`Type: string | Description of a channel. |
| `Custom`Type: map[string]interface | Custom JSON values. Can be strings, numbers, or booleans. [Filtering](https://www.pubnub.com/docs/general/metadata/filtering) by `Custom` isn't supported. |
| `IfMatchETag`Type: string | The entity tag to be used to ensure updates only happen if the object hasn't been modified since it was read. Use the eTag you received from an applicable get metadata method to check against the server entity tag. If the eTags don't match, an HTTP 412 error is thrown. |

:::tip API limits
To learn about the maximum length of parameters used to set channel metadata, refer to [REST API docs](https://www.pubnub.com/docs/sdks/rest-api/set-channel-metadata).
:::

#### Sample code

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

import (
	"fmt"
	"time"

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

// Example_setChannelMetadata demonstrates setting channel metadata
func Example_setChannelMetadata() {
	config := pubnub.NewConfigWithUserId(pubnub.UserId("demo-user"))
	config.SubscribeKey = "demo"
	config.PublishKey = "demo"

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

	pn := pubnub.NewPubNub(config)

	// snippet.hide
	// Cleanup: Remove metadata after test
	defer pn.RemoveChannelMetadata().Channel("support-channel-123").Execute()
	// snippet.show

	// Set channel metadata with descriptive information
	response, status, err := pn.SetChannelMetadata().
		Channel("support-channel-123").            // Channel ID
		Name("Customer Support").                  // Display name
		Description("24/7 customer support chat"). // Description
		Custom(map[string]interface{}{             // Custom metadata
			"department": "support",
			"priority":   "high",
		}).
		Execute()

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

	if status.StatusCode == 200 {
		fmt.Printf("Channel metadata set for: %s\n", response.Data.ID)
	}

	// Output:
	// Channel metadata set for: support-channel-123
}
```

#### Response

The `SetChannelMetadata()` operation returns a `PNSetChannelMetadataResponse` which contains the following parameters:

| Property Name | Type | Description |
| --- | --- | --- |
| `Data` | PNChannel | Details of type `PNChannel` are [here](#pnchannel) |

#### PNChannel

| Property Name | Type | Description |
| --- | --- | --- |
| `ID` | string | Unique user identifier. If not supplied then current user's `uuid` is used. |
| `Name` | string | Display name for the user. |
| `Description` | string | Description of a channel. |
| `Custom` | map[string]interface | Custom JSON values. Can be strings, numbers, or booleans. |
| `Updated` | string | Last updated date. |
| `ETag` | string | The ETag. |
| `Status` | string | Channel status. Max. 50 characters. |
| `Type` | string | Channel type. Max. 50 characters. |

#### Other examples

##### Iteratively update existing user metadata

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

import (
	"fmt"
	"time"

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

// Example_uuidMetadataETagConditionalUpdate demonstrates using ETags for optimistic concurrency control
// when updating UUID metadata. ETags prevent concurrent updates from overwriting each other's changes.
func Example_uuidMetadataETagConditionalUpdate() {
	config := pubnub.NewConfigWithUserId(pubnub.UserId("demo-user"))
	config.SubscribeKey = "demo"
	config.PublishKey = "demo"

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

	pn := pubnub.NewPubNub(config)

	// snippet.hide
	// Cleanup: Remove UUID metadata after test
	defer pn.RemoveUUIDMetadata().UUID("etag-test-uuid").Execute()
	// snippet.show

	// Step 1: Set initial UUID metadata
	// When creating or updating metadata, PubNub returns an ETag that represents the version of the data
	_, status, err := pn.SetUUIDMetadata().
		UUID("etag-test-uuid").
		Name("Initial Name").
		Email("initial@example.com").
		Custom(map[string]interface{}{
			"version": 1,
		}).
		Execute()

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

	if status.StatusCode == 200 {
		fmt.Println("Step 1: Initial metadata set successfully")
	}

	// Step 2: Try to update metadata with an INCORRECT ETag
	// This simulates a scenario where someone else might have updated the data
	incorrectETag := "incorrect-etag-value-123"
	_, status, err = pn.SetUUIDMetadata().
		UUID("etag-test-uuid").
		Name("Updated Name").
		IfMatchETag(incorrectETag). // Using wrong ETag
		Execute()

	// Step 3: Handle the error from incorrect ETag
	// When the ETag doesn't match, PubNub returns a 412 Precondition Failed error
	if err != nil && status.StatusCode == 412 {
		fmt.Println("Step 2: Update rejected - ETag mismatch detected")
	} else if err != nil {
		fmt.Printf("Unexpected error: %v\n", err)
		return
	}

	// Step 4: Get current metadata to retrieve the correct ETag
	// In a real application, you would typically get the latest data before updating
	getResponse, status, err := pn.GetUUIDMetadata().
		UUID("etag-test-uuid").
		Include([]pubnub.PNUUIDMetadataInclude{
			pubnub.PNUUIDMetadataIncludeCustom,
		}).
		Execute()

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

	if status.StatusCode == 200 {
		fmt.Println("Step 3: Retrieved current metadata with correct ETag")
	}

	// Get the current ETag from the retrieved data
	correctETag := getResponse.Data.ETag

	// Step 5: Update metadata with the CORRECT ETag
	// This ensures we're updating the latest version of the data
	updateResponse, status, err := pn.SetUUIDMetadata().
		UUID("etag-test-uuid").
		Name("Updated Name").
		Email("updated@example.com").
		Custom(map[string]interface{}{
			"version": 2,
		}).
		IfMatchETag(correctETag). // Using correct ETag
		Execute()

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

	if status.StatusCode == 200 && updateResponse.Data.Name == "Updated Name" {
		fmt.Println("Step 4: Update successful with correct ETag")
		// Note: The new ETag will be different from the previous one
		fmt.Println("Step 5: New ETag generated after successful update")
	}

	// Output:
	// Step 1: Initial metadata set successfully
	// Step 2: Update rejected - ETag mismatch detected
	// Step 3: Retrieved current metadata with correct ETag
	// Step 4: Update successful with correct ETag
	// Step 5: New ETag generated after successful update
}
```

##### Iteratively update existing channel metadata

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

import (
	"fmt"
	"time"

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

// Example_channelMetadataETagConditionalUpdate demonstrates using ETags for optimistic concurrency control
// when updating channel metadata. ETags prevent concurrent updates from overwriting each other's changes.
func Example_channelMetadataETagConditionalUpdate() {
	config := pubnub.NewConfigWithUserId(pubnub.UserId("demo-user"))
	config.SubscribeKey = "demo"
	config.PublishKey = "demo"

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

	pn := pubnub.NewPubNub(config)

	// snippet.hide
	// Cleanup: Remove channel metadata after test
	defer pn.RemoveChannelMetadata().Channel("etag-test-channel").Execute()
	// snippet.show

	// Step 1: Set initial channel metadata
	// When creating or updating metadata, PubNub returns an ETag that represents the version of the data
	_, status, err := pn.SetChannelMetadata().
		Channel("etag-test-channel").
		Name("Initial Name").
		Description("Initial description").
		Custom(map[string]interface{}{
			"version": 1,
		}).
		Execute()

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

	if status.StatusCode == 200 {
		fmt.Println("Step 1: Initial metadata set successfully")
	}

	// Step 2: Try to update metadata with an INCORRECT ETag
	// This simulates a scenario where someone else might have updated the data
	incorrectETag := "incorrect-etag-value-123"
	_, status, err = pn.SetChannelMetadata().
		Channel("etag-test-channel").
		Name("Updated Name").
		IfMatchETag(incorrectETag). // Using wrong ETag
		Execute()

	// Step 3: Handle the error from incorrect ETag
	// When the ETag doesn't match, PubNub returns a 412 Precondition Failed error
	if err != nil && status.StatusCode == 412 {
		fmt.Println("Step 2: Update rejected - ETag mismatch detected")
	} else if err != nil {
		fmt.Printf("Unexpected error: %v\n", err)
		return
	}

	// Step 4: Get current metadata to retrieve the correct ETag
	// In a real application, you would typically get the latest data before updating
	getResponse, status, err := pn.GetChannelMetadata().
		Channel("etag-test-channel").
		Include([]pubnub.PNChannelMetadataInclude{
			pubnub.PNChannelMetadataIncludeCustom,
		}).
		Execute()

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

	if status.StatusCode == 200 {
		fmt.Println("Step 3: Retrieved current metadata with correct ETag")
	}

	// Get the current ETag from the retrieved data
	correctETag := getResponse.Data.ETag

	// Step 5: Update metadata with the CORRECT ETag
	// This ensures we're updating the latest version of the data
	updateResponse, status, err := pn.SetChannelMetadata().
		Channel("etag-test-channel").
		Name("Updated Name").
		Description("Successfully updated with correct ETag").
		Custom(map[string]interface{}{
			"version": 2,
		}).
		IfMatchETag(correctETag). // Using correct ETag
		Execute()

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

	if status.StatusCode == 200 && updateResponse.Data.Name == "Updated Name" {
		fmt.Println("Step 4: Update successful with correct ETag")
		// Note: The new ETag will be different from the previous one
		fmt.Println("Step 5: New ETag generated after successful update")
	}

	// Output:
	// Step 1: Initial metadata set successfully
	// Step 2: Update rejected - ETag mismatch detected
	// Step 3: Retrieved current metadata with correct ETag
	// Step 4: Update successful with correct ETag
	// Step 5: New ETag generated after successful update
}
```

### Remove channel metadata

Removes the metadata from a specified channel.

#### Method(s)

To `Remove Channel Metadata` you can use the following method(s) in the Go SDK:

```go
pn.RemoveChannelMetadata().
    ID(string).
    Execute()
```

| Parameter | Description |
| --- | --- |
| `ID` *Type: string | Unique user identifier. If not supplied then current user's `uuid` is used. |

#### Sample code

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

import (
	"fmt"
	"time"

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

// Example_removeChannelMetadata demonstrates removing channel metadata
func Example_removeChannelMetadata() {
	config := pubnub.NewConfigWithUserId(pubnub.UserId("demo-user"))
	config.SubscribeKey = "demo"
	config.PublishKey = "demo"

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

	pn := pubnub.NewPubNub(config)

	// snippet.hide
	// Setup: Create metadata first
	pn.SetChannelMetadata().Channel("temp-channel").Name("Temporary Channel").Execute()
	// snippet.show

	// Remove channel metadata
	_, status, err := pn.RemoveChannelMetadata().
		Channel("temp-channel"). // Channel ID to remove
		Execute()

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

	if status.StatusCode == 200 {
		fmt.Println("Channel metadata removed successfully")
	}

	// Output:
	// Channel metadata removed successfully
}
```

#### Response

The `RemoveChannelMetadata()` operation returns a `PNRemoveChannelMetadataResponse` which contains the following parameters:

| Property Name | Type | Description |
| --- | --- | --- |
| `Data` | interface | Returns an empty interface. |

## Channel memberships

### Get channel memberships

The method returns a list of channel memberships for a user. This method doesn't return a user's subscriptions.

#### Method(s)

To `Get Memberships` you can use the following method(s) in the Go SDK:

```go
pn.GetMemberships().
    UUID(string).
    Include([]pubnub.PNMembershipsInclude).
    Sort(sort).
    Limit(int).
    Count(bool).
    Start(string).
    End(string).
    Filter(string).
    Execute()
```

| Parameter | Description |
| --- | --- |
| `UUID` *Type: string | UUID. If not supplied, the current user's UUID is used. |
| `Include`Type: []pubnub.PNMembershipsInclude | List of additional/complex attributes to include in response. Omit this parameter if you don't want to retrieve additional attributes. **Available values** `pubnub.PNMembershipsIncludeCustom`, `pubnub.PNMembershipsIncludeChannel`, `pubnub.PNMembershipsIncludeChannelCustom` |
| `Sort`Type: Array | Sort by `id`, `name`, `updated` with `asc`/`desc` for sort direction (for example, `{name: 'asc'}`). |
| `Limit`Type: int | Number of objects to return. Default/Max: 100. |
| `Count`Type: bool | Whether to include the total count in the paginated response. Default is false. |
| `Start`Type: string | Cursor-based pagination. |
| `End`Type: string | Cursor-based pagination. |
| `Filter`Type: string | Filter expression. Only matching objects are returned. See [filtering](https://www.pubnub.com/docs/general/metadata/filtering). |

#### Sample code

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

import (
	"fmt"
	"time"

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

// Example_getMembershipsWithAllIncludes demonstrates getting memberships with all include options
func Example_getMembershipsWithAllIncludes() {
	config := pubnub.NewConfigWithUserId(pubnub.UserId("demo-user"))
	config.SubscribeKey = "demo"
	config.PublishKey = "demo"

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

	pn := pubnub.NewPubNub(config)

	// snippet.hide
	defer pn.RemoveUUIDMetadata().UUID("user-full-membership").Execute()
	defer pn.RemoveChannelMetadata().Channel("channel-full-membership").Execute()
	// snippet.show

	// Create user and channel with all fields
	pn.SetUUIDMetadata().
		UUID("user-full-membership").
		Name("Full Member").
		Status("active").
		Type("user").
		Execute()

	pn.SetChannelMetadata().
		Channel("channel-full-membership").
		Name("Full Channel").
		Custom(map[string]interface{}{"category": "tech"}).
		Status("active").
		Type("public").
		Execute()

	// Add user to channel with custom membership data
	pn.SetMemberships().
		UUID("user-full-membership").
		Set([]pubnub.PNMembershipsSet{
			{
				Channel: pubnub.PNMembershipsChannel{ID: "channel-full-membership"},
				Custom: map[string]interface{}{
					"role": "moderator",
				},
				Status: "active",
				Type:   "membership",
			},
		}).
		Execute()

	// Small delay to ensure metadata is persisted before retrieval
	time.Sleep(2 * time.Second)

	// Get memberships with all include options
	response, status, err := pn.GetMemberships().
		UUID("user-full-membership").
		Include([]pubnub.PNMembershipsInclude{
			pubnub.PNMembershipsIncludeCustom,        // Include membership custom data
			pubnub.PNMembershipsIncludeChannel,       // Include channel details
			pubnub.PNMembershipsIncludeChannelCustom, // Include channel custom data
			pubnub.PNMembershipsIncludeChannelStatus, // Include channel status
			pubnub.PNMembershipsIncludeChannelType,   // Include channel type
			pubnub.PNMembershipsIncludeStatus,        // Include membership status
			pubnub.PNMembershipsIncludeType,          // Include membership type
		}).
		Execute()

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

	if status.StatusCode == 200 && len(response.Data) > 0 {
		membership := response.Data[0]
		fmt.Printf("Channel: %s\n", membership.Channel.Name)
		fmt.Printf("Channel Status: %s\n", membership.Channel.Status)
		fmt.Printf("Membership Status: %s\n", membership.Status)
		if role, ok := membership.Custom["role"].(string); ok {
			fmt.Printf("Role: %s\n", role)
		}
	}

	// Output:
	// Channel: Full Channel
	// Channel Status: active
	// Membership Status: active
	// Role: moderator
}
```

#### Response

The `GetMemberships()` operation returns a `PNGetMembershipsResponse` which contains the following parameters:

| Property Name | Type | Description |
| --- | --- | --- |
| `Data` | []PNMemberships | Details of type `PNMemberships` are [here](#pnmemberships) |
| `TotalCount` | int | Total count of objects without pagination. |
| `Next` | string | Random string returned from the server, indicating a specific position in a data set. Used for forward pagination, it fetches the next page, allowing you to continue from where you left off. |
| `Prev` | string | Random string returned from the server, indicating a specific position in a data set. Used for backward pagination, it fetches the previous page, enabling access to earlier data. Ignored if the `Next` parameter is supplied. |

#### PNMemberships

| Property Name | Type | Description |
| --- | --- | --- |
| `ID` | string | Unique user identifier. If not supplied then current user's `uuid` is used. |
| `Channel` | PNChannel | Details of type PNChannel are [here](#pnchannel) |
| `Custom` | map[string]interface | Custom JSON values. Can be strings, numbers, or booleans. |
| `Updated` | string | Last updated date. |
| `ETag` | string | The ETag. |
| `Status` | string | Status of the membership. Max. 50 characters. |
| `Type` | string | Type of the membership. Max. 50 characters. |

### Set channel memberships

Set channel memberships for a UUID.

#### Method(s)

To `Set Memberships` you can use the following method(s) in the Go SDK:

```go
pn.SetMemberships().
    UUID(string).
    Set([]pubnub.PNMembershipsSet).
    Include([]pubnub.PNMembershipsInclude).
    Sort(sort).
    Limit(int).
    Count(bool).
    Start(string).
    End(string).
    Execute()
```

| Parameter | Description |
| --- | --- |
| `UUID` *Type: string | UUID. If not supplied, the current user's UUID is used. |
| `Set`Type: pubnub.PNMembershipsSet | Struct of type `pubnub.PNMembershipsSet` to be added for the specified `UUID`. In `PNMembershipsSet` you can set the Channel (of type `PNMembershipsChannel` - consisting of an `ID` of `string` type ) and a `Custom` map. |
| `Include`Type: []pubnub.PNMembershipsInclude | List of additional/complex attributes to include in response. Omit this parameter if you don't want to retrieve additional attributes. **Available values** `pubnub.PNMembershipsIncludeCustom`, `pubnub.PNMembershipsIncludeChannel`, `pubnub.PNMembershipsIncludeChannelCustom` |
| `Sort`Type: Array | Sort by `id`, `name`, `updated` with `asc`/`desc` for sort direction (for example, `{name: 'asc'}`). |
| `Limit`Type: int | Number of objects to return. Default/Max: 100. |
| `Count`Type: bool | Whether to include the total count in the paginated response. Default is false. |
| `Start`Type: string | Cursor-based pagination. |
| `End`Type: string | Cursor-based pagination. |

:::tip API limits
To learn about the maximum length of parameters used to set channel membership metadata, refer to [REST API docs](https://www.pubnub.com/docs/sdks/rest-api/set-membership-metadata).
:::

#### Sample code

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

import (
	"fmt"
	"time"

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

// Example_setMemberships demonstrates adding a user to channels (memberships)
func Example_setMemberships() {
	config := pubnub.NewConfigWithUserId(pubnub.UserId("demo-user"))
	config.SubscribeKey = "demo"
	config.PublishKey = "demo"

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

	pn := pubnub.NewPubNub(config)

	// snippet.hide
	// Setup: Create user and channels first
	pn.SetUUIDMetadata().UUID("member-user-789").Name("Member User").Execute()
	pn.SetChannelMetadata().Channel("channel-member-1").Name("Channel 1").Execute()
	pn.SetChannelMetadata().Channel("channel-member-2").Name("Channel 2").Execute()
	defer pn.RemoveUUIDMetadata().UUID("member-user-789").Execute()
	defer pn.RemoveChannelMetadata().Channel("channel-member-1").Execute()
	defer pn.RemoveChannelMetadata().Channel("channel-member-2").Execute()
	// snippet.show

	// Add user to multiple channels with custom metadata
	response, status, err := pn.SetMemberships().
		UUID("member-user-789").       // User ID
		Set([]pubnub.PNMembershipsSet{ // Channels to join
			{
				Channel: pubnub.PNMembershipsChannel{ID: "channel-member-1"},
				Custom: map[string]interface{}{
					"role": "moderator",
				},
			},
			{
				Channel: pubnub.PNMembershipsChannel{ID: "channel-member-2"},
				Custom: map[string]interface{}{
					"role": "member",
				},
			},
		}).
		Execute()

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

	if status.StatusCode == 200 {
		fmt.Printf("User added to %d channel(s)\n", len(response.Data))
	}

	// Output:
	// User added to 2 channel(s)
}
```

#### Response

The `SetMemberships()` operation returns a `PNSetMembershipsResponse` which contains the following parameters:

| Property Name | Type | Description |
| --- | --- | --- |
| `Data` | []PNMemberships | Details of type `PNMemberships` are [here](#pnmemberships) |
| `TotalCount` | int | Total count of objects without pagination. |
| `Next` | string | Random string returned from the server, indicating a specific position in a data set. Used for forward pagination, it fetches the next page, allowing you to continue from where you left off. |
| `Prev` | string | Random string returned from the server, indicating a specific position in a data set. Used for backward pagination, it fetches the previous page, enabling access to earlier data. Ignored if the `Next` parameter is supplied. |

### Remove channel memberships

Remove channel memberships for a UUID.

#### Method(s)

To `Remove Memberships` you can use the following method(s) in the Go SDK:

```go
pn.RemoveMemberships().
    UUID(string).
    Remove([]pubnub.PNMembershipsRemove).
    Include([]pubnub.PNMembershipsInclude).
    Limit(int).
    Count(bool).
    Start(string).
    End(string).
    Execute()
```

| Parameter | Description |
| --- | --- |
| `UUID` *Type: string | UUID. If not supplied, the current user's UUID is used. |
| `Remove`Type: pubnub.PNMembershipsRemove | Struct of type `pubnub.PNMembershipsRemove` to be added for the specified `UUID`. In `PNMembershipsRemove` you can set the Channel (of type `PNMembershipsChannel` - consisting of an `ID` of `string` type ) and a `Custom` map. |
| `Include`Type: []pubnub.PNMembershipsInclude | List of additional/complex attributes to include in response. Omit this parameter if you don't want to retrieve additional attributes. **Available values** `pubnub.PNMembershipsIncludeCustom`, `pubnub.PNMembershipsIncludeChannel`, `pubnub.PNMembershipsIncludeChannelCustom` |
| `Limit`Type: int | Number of objects to return. Default/Max: 100. |
| `Count`Type: bool | Whether to include the total count in the paginated response. Default is false. |
| `Start`Type: string | Cursor-based pagination. |
| `End`Type: string | Cursor-based pagination. |

#### Sample code

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

import (
	"fmt"
	"time"

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

// Example_removeMemberships demonstrates removing a user from channels (removing memberships)
func Example_removeMemberships() {
	config := pubnub.NewConfigWithUserId(pubnub.UserId("demo-user"))
	config.SubscribeKey = "demo"
	config.PublishKey = "demo"

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

	pn := pubnub.NewPubNub(config)

	// snippet.hide
	// Setup: Create channels and add memberships
	pn.SetChannelMetadata().Channel("temp-channel-1").Name("Temp 1").Execute()
	pn.SetChannelMetadata().Channel("temp-channel-2").Name("Temp 2").Execute()
	pn.SetUUIDMetadata().UUID("remove-user-888").Name("Bob").Execute()
	defer pn.RemoveChannelMetadata().Channel("temp-channel-1").Execute()
	defer pn.RemoveChannelMetadata().Channel("temp-channel-2").Execute()
	defer pn.RemoveUUIDMetadata().UUID("remove-user-888").Execute()

	pn.SetMemberships().
		UUID("remove-user-888").
		Set([]pubnub.PNMembershipsSet{
			{Channel: pubnub.PNMembershipsChannel{ID: "temp-channel-1"}},
			{Channel: pubnub.PNMembershipsChannel{ID: "temp-channel-2"}},
		}).
		Execute()
	// snippet.show

	// Remove user from specific channels
	response, status, err := pn.RemoveMemberships().
		UUID("remove-user-888").             // User ID
		Remove([]pubnub.PNMembershipsRemove{ // Channels to remove from
			{Channel: pubnub.PNMembershipsChannel{ID: "temp-channel-1"}},
		}).
		Execute()

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

	if status.StatusCode == 200 {
		fmt.Printf("Removed from %d channel(s)\n", len(response.Data))
	}

	// Output:
	// Removed from 1 channel(s)
}
```

#### Response

The `RemoveMemberships()` operation returns a `PNRemoveMembershipsResponse` which contains the following parameters:

| Property Name | Type | Description |
| --- | --- | --- |
| `Data` | []PNMemberships | Details of type `PNMemberships` are [here](#pnmemberships) |
| `TotalCount` | int | Total count of objects without pagination. |
| `Next` | string | Random string returned from the server, indicating a specific position in a data set. Used for forward pagination, it fetches the next page, allowing you to continue from where you left off. |
| `Prev` | string | Random string returned from the server, indicating a specific position in a data set. Used for backward pagination, it fetches the previous page, enabling access to earlier data. Ignored if the `Next` parameter is supplied. |

### Manage channel memberships

Manage the specified UUID's memberships. You can `Add`, `Remove`, and `Update` a UUID's memberships.

#### Method(s)

To `Manage Memberships` you can use the following method(s) in the Go SDK:

```go
pn.ManageMemberships().
    UUID(string).
    Set([]pubnub.PNMembershipsSet).
    Remove([]pubnub.PNMembershipsRemove).
    Include([]pubnub.PNMembershipsInclude).
    Sort(sort).
    Limit(int).
    Count(bool).
    Start(string).
    End(string).
    Execute()
```

| Parameter | Description |
| --- | --- |
| `UUID`Type: string | Unique user identifier. If not supplied then current user's `Uuid` is used. |
| `Set`Type: pubnub.PNMembershipsSet | Struct of type `pubnub.PNMembershipsSet` to be added for the specified `UUID`. In `PNMembershipsSet` you can set the `Channel` (of type `PNMembershipsChannel` - consisting of an `ID` of `string` type ) and a `Custom` map. |
| `Remove`Type: pubnub.PNMembershipsRemove | Struct of type `pubnub.PNMembershipsRemove` to be added for the specified UUID. In `PNMembershipsRemove` you can set the `Channel` (of type `PNMembershipsChannel` - consisting of an `ID` of `string` type ) |
| `Include`Type: []pubnub.PNMembershipsInclude | List of additional/complex attributes to include in response. Omit this parameter if you don't want to retrieve additional attributes. **Available values** `pubnub.PNMembershipsIncludeCustom`, `pubnub.PNMembershipsIncludeChannel`, `pubnub.PNMembershipsIncludeChannelCustom` |
| `Sort`Type: Array | Sort by `id`, `name`, `updated` with `asc`/`desc` for sort direction (for example, `{name: 'asc'}`). |
| `Limit`Type: int | Number of objects to return. Default/Max: 100. |
| `Count`Type: bool | Whether to include the total count in the paginated response. Default is false. |
| `Start`Type: string | Cursor-based pagination. |
| `End`Type: string | Cursor-based pagination. |

#### Sample code

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

import (
	"fmt"
	"time"

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

// Example_manageMemberships demonstrates adding and removing channel memberships in a single call
func Example_manageMemberships() {
	config := pubnub.NewConfigWithUserId(pubnub.UserId("demo-user"))
	config.SubscribeKey = "demo"
	config.PublishKey = "demo"

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

	pn := pubnub.NewPubNub(config)

	// snippet.hide
	// Setup: Create channels
	pn.SetChannelMetadata().Channel("add-channel-999").Name("Add Channel").Execute()
	pn.SetChannelMetadata().Channel("remove-channel-999").Name("Remove Channel").Execute()
	pn.SetUUIDMetadata().UUID("manage-user-999").Name("Charlie").Execute()
	defer pn.RemoveChannelMetadata().Channel("add-channel-999").Execute()
	defer pn.RemoveChannelMetadata().Channel("remove-channel-999").Execute()
	defer pn.RemoveUUIDMetadata().UUID("manage-user-999").Execute()

	// Add initial membership to be removed
	pn.SetMemberships().
		UUID("manage-user-999").
		Set([]pubnub.PNMembershipsSet{
			{Channel: pubnub.PNMembershipsChannel{ID: "remove-channel-999"}},
		}).
		Execute()
	// snippet.show

	// Manage memberships: add to some channels and remove from others
	response, status, err := pn.ManageMemberships().
		UUID("manage-user-999").       // User ID
		Set([]pubnub.PNMembershipsSet{ // Channels to add
			{
				Channel: pubnub.PNMembershipsChannel{ID: "add-channel-999"},
				Custom: map[string]interface{}{
					"role": "participant",
				},
			},
		}).
		Remove([]pubnub.PNMembershipsRemove{ // Channels to remove
			{Channel: pubnub.PNMembershipsChannel{ID: "remove-channel-999"}},
		}).
		Execute()

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

	if status.StatusCode == 200 {
		fmt.Printf("Managed memberships: %d channel(s)\n", len(response.Data))
	}

	// Output:
	// Managed memberships: 1 channel(s)
}
```

#### Response

The `ManageMemberships()` operation returns a `PNManageMembershipsResponse` which contains the following parameters:

| Property Name | Type | Description |
| --- | --- | --- |
| `Data` | []PNMemberships | Details of type `PNMemberships` are [here](#pnmemberships) |
| `TotalCount` | int | Total count of objects without pagination. |
| `Next` | string | Random string returned from the server, indicating a specific position in a data set. Used for forward pagination, it fetches the next page, allowing you to continue from where you left off. |
| `Prev` | string | Random string returned from the server, indicating a specific position in a data set. Used for backward pagination, it fetches the previous page, enabling access to earlier data. Ignored if the `Next` parameter is supplied. |

## Channel members

### Get channel members

The method returns a list of members in a channel. The list will include user metadata for members that have additional metadata stored in the database.

#### Method(s)

To `Get Channel Members` you can use the following method(s) in the Go SDK:

```go
pn.GetChannelMembers().
    Channel(string).
    Include(PNChannelMembersInclude).
    Sort(sort).
    Limit(int).
    Count(bool).
    Start(string).
    End(string).
    Filter(string).
    Execute()
```

| Parameter | Description |
| --- | --- |
| `Channel` *Type: string | Channel name. |
| `Include`Type: []pubnub.PNChannelMembersInclude | List of additional/complex attributes to include in response. Omit this parameter if you don't want to retrieve additional attributes. **Available values** `pubnub.PNChannelMembersIncludeCustom`, `pubnub.PNChannelMembersIncludeUUID`, `pubnub.PNChannelMembersIncludeUUIDCustom` |
| `Sort`Type: Array | List of criteria (name of field) which should be used for sorting. Available options are `id`, `name`, and `updated`. Use `asc` or `desc` to specify sort direction. For example: `{name: 'asc'}` |
| `Limit`Type: int | Number of objects to return. Default/Max: 100. |
| `Count`Type: bool | Whether to include the total count in the paginated response. Default is false. |
| `Start`Type: string | Cursor-based pagination. |
| `End`Type: string | Cursor-based pagination. |
| `Filter`Type: string | Filter expression. Only matching objects are returned. See [filtering](https://www.pubnub.com/docs/general/metadata/filtering). |

#### Sample code

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

import (
	"fmt"
	"time"

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

// Example_getChannelMembersWithAllIncludes demonstrates getting channel members with all include options
func Example_getChannelMembersWithAllIncludes() {
	config := pubnub.NewConfigWithUserId(pubnub.UserId("demo-user"))
	config.SubscribeKey = "demo"
	config.PublishKey = "demo"

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

	pn := pubnub.NewPubNub(config)

	// snippet.hide
	defer pn.RemoveChannelMetadata().Channel("channel-full-members").Execute()
	defer pn.RemoveUUIDMetadata().UUID("user-full-member").Execute()
	// snippet.show

	// Create channel and user with all fields
	pn.SetChannelMetadata().
		Channel("channel-full-members").
		Name("Complete Team").
		Status("active").
		Type("team").
		Execute()

	pn.SetUUIDMetadata().
		UUID("user-full-member").
		Name("Complete Member").
		Custom(map[string]interface{}{"department": "dev"}).
		Status("active").
		Type("employee").
		Execute()

	// Add user to channel with custom member data
	pn.SetChannelMembers().
		Channel("channel-full-members").
		Set([]pubnub.PNChannelMembersSet{
			{
				UUID: pubnub.PNChannelMembersUUID{ID: "user-full-member"},
				Custom: map[string]interface{}{
					"access": "admin",
				},
				Status: "active",
				Type:   "member",
			},
		}).
		Execute()

	// Small delay to ensure metadata is persisted before retrieval
	time.Sleep(2 * time.Second)

	// Get channel members with all include options
	response, status, err := pn.GetChannelMembers().
		Channel("channel-full-members").
		Include([]pubnub.PNChannelMembersInclude{
			pubnub.PNChannelMembersIncludeCustom,     // Include member custom data
			pubnub.PNChannelMembersIncludeUUID,       // Include user details
			pubnub.PNChannelMembersIncludeUUIDCustom, // Include user custom data
			pubnub.PNChannelMembersIncludeUUIDStatus, // Include user status
			pubnub.PNChannelMembersIncludeUUIDType,   // Include user type
			pubnub.PNChannelMembersIncludeStatus,     // Include member status
			pubnub.PNChannelMembersIncludeType,       // Include member type
		}).
		Execute()

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

	if status.StatusCode == 200 && len(response.Data) > 0 {
		member := response.Data[0]
		fmt.Printf("Member: %s\n", member.UUID.Name)
		fmt.Printf("User Status: %s\n", member.UUID.Status)
		fmt.Printf("Member Status: %s\n", member.Status)
		if access, ok := member.Custom["access"].(string); ok {
			fmt.Printf("Access: %s\n", access)
		}
	}

	// Output:
	// Member: Complete Member
	// User Status: active
	// Member Status: active
	// Access: admin
}
```

#### Response

The `GetChannelMembers()` operation returns a `PNGetChannelMembersResponse` which contains the following parameters:

| Property Name | Type | Description |
| --- | --- | --- |
| `Data` | []PNChannelMembers | Details of type `PNChannelMembers` are [here](#pnchannelmembers) |
| `TotalCount` | int | Total count of objects without pagination. |
| `Next` | string | Random string returned from the server, indicating a specific position in a data set. Used for forward pagination, it fetches the next page, allowing you to continue from where you left off. |
| `Prev` | string | Random string returned from the server, indicating a specific position in a data set. Used for backward pagination, it fetches the previous page, enabling access to earlier data. Ignored if the `Next` parameter is supplied. |

#### PNChannelMembers

| Property Name | Type | Description |
| --- | --- | --- |
| `ID` | string | Unique user identifier. If not supplied then current user's `uuid` is used. |
| `UUID` | PNUUID | Details of type `PNUUID` are [here](#pnuuid) |
| `Custom` | map[string]interface | Custom JSON values. Can be strings, numbers, or booleans. |
| `Updated` | string | Last updated date. |
| `ETag` | string | The ETag. |
| `Status` | string | Status of the member. Max. 50 characters. |
| `Type` | string | Type of the member. Max. 50 characters. |

### Set channel members

This method sets members in a channel.

#### Method(s)

To `Set Channel Members` you can use the following method(s) in the Go SDK:

```go
pn.SetChannelMembers().
    Channel(string).
    Set([]pubnub.PNChannelMembersSet).
    Include([]pubnub.PNChannelMembersInclude).
    Sort(sort).
    Limit(int).
    Count(bool).
    Start(string).
    End(string).
    Execute()
```

| Parameter | Description |
| --- | --- |
| `Channel` *Type: string | Channel name. |
| `Set`Type: pubnub.PNChannelMembersSet | Struct of type `pubnub.PNChannelMembersSet` to be added for the specified space. In `PNChannelMembersSet` you can set the `UUID` (of type `PNChannelMembersUUID` - consisting of an `ID` of `string` type ) and a `Custom` map. |
| `Include`Type: []pubnub.PNChannelMembersInclude | List of additional/complex attributes to include in response. Omit this parameter if you don't want to retrieve additional attributes. **Available values** `pubnub.PNChannelMembersIncludeCustom`, `pubnub.PNChannelMembersIncludeUUID`, `pubnub.PNChannelMembersIncludeUUIDCustom` |
| `Sort`Type: Array | Sort by `id`, `name`, `updated` with `asc`/`desc` for sort direction (for example, `{name: 'asc'}`). |
| `Limit`Type: int | Number of objects to return. Default/Max: 100. |
| `Count`Type: bool | Whether to include the total count in the paginated response. Default is false. |
| `Start`Type: string | Cursor-based pagination. |
| `End`Type: string | Cursor-based pagination. |

:::tip API limits
To learn about the maximum length of parameters used to set channel members metadata, refer to [REST API docs](https://www.pubnub.com/docs/sdks/rest-api/set-channel-members-metadata).
:::

#### Sample code

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

import (
	"fmt"
	"time"

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

// Example_setChannelMembers demonstrates adding users to a channel (channel members)
func Example_setChannelMembers() {
	config := pubnub.NewConfigWithUserId(pubnub.UserId("demo-user"))
	config.SubscribeKey = "demo"
	config.PublishKey = "demo"

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

	pn := pubnub.NewPubNub(config)

	// snippet.hide
	// Setup: Create channel and users first
	pn.SetChannelMetadata().Channel("team-channel-555").Name("Team Channel").Execute()
	pn.SetUUIDMetadata().UUID("team-member-1").Name("Alice").Execute()
	pn.SetUUIDMetadata().UUID("team-member-2").Name("Bob").Execute()
	defer pn.RemoveChannelMetadata().Channel("team-channel-555").Execute()
	defer pn.RemoveUUIDMetadata().UUID("team-member-1").Execute()
	defer pn.RemoveUUIDMetadata().UUID("team-member-2").Execute()
	// snippet.show

	// Add multiple users to a channel with custom metadata
	response, status, err := pn.SetChannelMembers().
		Channel("team-channel-555").      // Channel ID
		Set([]pubnub.PNChannelMembersSet{ // Users to add
			{
				UUID: pubnub.PNChannelMembersUUID{ID: "team-member-1"},
				Custom: map[string]interface{}{
					"role": "admin",
				},
			},
			{
				UUID: pubnub.PNChannelMembersUUID{ID: "team-member-2"},
				Custom: map[string]interface{}{
					"role": "member",
				},
			},
		}).
		Execute()

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

	if status.StatusCode == 200 {
		fmt.Printf("Added %d member(s) to channel\n", len(response.Data))
	}

	// Output:
	// Added 2 member(s) to channel
}
```

#### Response

The `SetChannelMembers()` operation returns a `PNSetChannelMembersResponse` which contains the following parameters:

| Property Name | Type | Description |
| --- | --- | --- |
| `Data` | []PNChannelMembers | Details of type `PNChannelMembers` are [here](#pnchannelmembers) |
| `TotalCount` | int | Total count of objects without pagination. |
| `Next` | string | Random string returned from the server, indicating a specific position in a data set. Used for forward pagination, it fetches the next page, allowing you to continue from where you left off. |
| `Prev` | string | Random string returned from the server, indicating a specific position in a data set. Used for backward pagination, it fetches the previous page, enabling access to earlier data. Ignored if the `Next` parameter is supplied. |

### Remove channel members

Remove members from a Channel.

#### Method(s)

To `Remove Channel Members` you can use the following method(s) in the Go SDK:

```go
pn.RemoveChannelMembers().
    Channel(string).
    Remove([]pubnub.PNChannelMembersRemove{}).
    Include([]pubnub.PNChannelMembersInclude).
    Limit(int).
    Count(bool).
    Start(string).
    End(string).
    Execute()
```

| Parameter | Description |
| --- | --- |
| `channel` *Type: StringDefault: n/a | Name of channel from which members should be fetched. |
| `uuids` *Type: ArrayDefault: n/a | List of `UUIDs` for which `metadata` associated with each of them in context of `channel` should be set. Each entry is dictionary with `UUID` and optional `custom` fields. `custom` should be dictionary with simple objects: `String` and `Integer`. |
| `sort`Type: ArrayDefault: n/a | List of criteria (name of field) which should be used for sorting. Available options are `id`, `name`, and `updated`. Use `asc` or `desc` to specify sort direction. For example: `{name: 'asc'}` |
| `include`Type: ObjectDefault: `{ count: true }` | Additional information which should be included in response. Available options: count- include how many UUID has been associated with metadata., custom - include field with additional information from metadata which has been used during UUID metadata set requests. |
| `filter`Type: StringDefault: n/a | Expression to filter out results basing on specified criteria. For more details on the supported grammar, check [here](https://www.pubnub.com/docs/general/metadata/filtering) |
| `start`Type: StringDefault: n/a | Random string returned from the server, indicating a specific position in a data set. Used for forward pagination, it fetches the next page, allowing you to continue from where you left off. |
| `end`Type: StringDefault: n/a | Random string returned from the server, indicating a specific position in a data set. Used for backward pagination, it fetches the previous page, enabling access to earlier data. Ignored if the `start` parameter is supplied. |
| `limit`Type: IntegerDefault: 100 | Number of objects to return in response. Default is `100`, which is also the maximum value. |
| `http_sync`Type: BooleanDefault: false | Method will be executed `asynchronously` and will return future, to get its `value` you can use `value` method. If set to `true`, method will return array of envelopes (even if there's only one `envelope`). For `sync` methods `Envelope` object will be returned. |
| `callback`Type: Lambda accepting one parameterDefault: n/a | `Callback` that will be called for each envelope. For `async` methods future will be returned, to retrieve `value` `Envelope` object you have to call `value` method (thread will be locked until the `value` is returned). |

#### Sample code

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

import (
	"fmt"
	"time"

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

// Example_removeChannelMembers demonstrates removing users from a channel
func Example_removeChannelMembers() {
	config := pubnub.NewConfigWithUserId(pubnub.UserId("demo-user"))
	config.SubscribeKey = "demo"
	config.PublishKey = "demo"

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

	pn := pubnub.NewPubNub(config)

	// snippet.hide
	// Setup: Create channel and users, then add them as members
	pn.SetChannelMetadata().Channel("remove-members-channel").Name("Team").Execute()
	pn.SetUUIDMetadata().UUID("remove-member-1").Name("Alice").Execute()
	pn.SetUUIDMetadata().UUID("remove-member-2").Name("Bob").Execute()
	defer pn.RemoveChannelMetadata().Channel("remove-members-channel").Execute()
	defer pn.RemoveUUIDMetadata().UUID("remove-member-1").Execute()
	defer pn.RemoveUUIDMetadata().UUID("remove-member-2").Execute()

	pn.SetChannelMembers().
		Channel("remove-members-channel").
		Set([]pubnub.PNChannelMembersSet{
			{UUID: pubnub.PNChannelMembersUUID{ID: "remove-member-1"}},
			{UUID: pubnub.PNChannelMembersUUID{ID: "remove-member-2"}},
		}).
		Execute()
	// snippet.show

	// Remove specific users from the channel
	response, status, err := pn.RemoveChannelMembers().
		Channel("remove-members-channel").      // Channel ID
		Remove([]pubnub.PNChannelMembersRemove{ // Users to remove
			{UUID: pubnub.PNChannelMembersUUID{ID: "remove-member-1"}},
		}).
		Execute()

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

	if status.StatusCode == 200 {
		fmt.Printf("Removed %d member(s) from channel\n", len(response.Data))
	}

	// Output:
	// Removed 1 member(s) from channel
}
```

#### Response

The `RemoveChannelMembers()` operation returns a `PNRemoveChannelMembersResponse` which contains the following parameters:

| Property Name | Type | Description |
| --- | --- | --- |
| `Data` | []PNChannelMembers | Details of type `PNChannelMembers` are [here](#pnchannelmembers) |
| `TotalCount` | int | Total count of objects without pagination. |
| `Next` | string | Random string returned from the server, indicating a specific position in a data set. Used for forward pagination, it fetches the next page, allowing you to continue from where you left off. |
| `Prev` | string | Random string returned from the server, indicating a specific position in a data set. Used for backward pagination, it fetches the previous page, enabling access to earlier data. Ignored if the `Next` parameter is supplied. |

### Manage channel members

The method Set and Remove channel memberships for a user.

#### Method(s)

To `Manage Channel Members` you can use the following method(s) in the Go SDK:

```go
pn.ManageChannelMembers().
    Channel(string).
    Set([]pubnub.PNChannelMembersSet).
    Remove([]pubnub.PNChannelMembersRemove{}).
    Include([]pubnub.PNChannelMembersInclude).
    Sort(sort).
    Limit(int).
    Count(bool).
    Start(string).
    End(string).
    Execute()
```

| Parameter | Description |
| --- | --- |
| `Channel` *Type: string | Channel Name. |
| `Set`Type: pubnub.PNChannelMembersSet | Struct of type `pubnub.PNChannelMembersSet` to be added for the specified space. In `PNChannelMembersSet` you can set the `UUID` (of type `PNChannelMembersUUID` - consisting of an `ID` of `string` type ) and a `Custom` map. |
| `Remove`Type: pubnub.PNChannelMembersRemove | Struct of type `pubnub.PNChannelMembersRemove` to be removed for the specified space. In `PNChannelMembersRemove` you can set the `UUID` (of type `PNChannelMembersUUID` - consisting of an `ID` of `string` type ) |
| `Limit`Type: int | Maximum number of results to return per page. Default 100. |
| `Count`Type: bool | Whether to include the total count in the paginated response. Default is false. |
| `Start`Type: string | Cursor-based pagination. |
| `End`Type: string | Cursor-based pagination. |
| `Sort`Type: Array | Sort by `id`, `name`, `updated` with `asc`/`desc` for sort direction (for example, `{name: 'asc'}`). |
| `Include`Type: []pubnub.PNChannelMembersInclude | List of additional/complex attributes to include in response. Omit this parameter if you don't want to retrieve additional attributes. **Available values** `pubnub.PNChannelMembersIncludeCustom`, `pubnub.PNChannelMembersIncludeUUID`, `pubnub.PNChannelMembersIncludeUUIDCustom` |

#### Sample code

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

import (
	"fmt"
	"time"

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

// Example_manageChannelMembers demonstrates adding and removing channel members in a single call
func Example_manageChannelMembers() {
	config := pubnub.NewConfigWithUserId(pubnub.UserId("demo-user"))
	config.SubscribeKey = "demo"
	config.PublishKey = "demo"

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

	pn := pubnub.NewPubNub(config)

	// snippet.hide
	// Setup: Create channel and users
	pn.SetChannelMetadata().Channel("manage-members-channel").Name("Project Team").Execute()
	pn.SetUUIDMetadata().UUID("new-member-111").Name("David").Execute()
	pn.SetUUIDMetadata().UUID("old-member-111").Name("Eve").Execute()
	defer pn.RemoveChannelMetadata().Channel("manage-members-channel").Execute()
	defer pn.RemoveUUIDMetadata().UUID("new-member-111").Execute()
	defer pn.RemoveUUIDMetadata().UUID("old-member-111").Execute()

	// Add initial member to be removed
	pn.SetChannelMembers().
		Channel("manage-members-channel").
		Set([]pubnub.PNChannelMembersSet{
			{UUID: pubnub.PNChannelMembersUUID{ID: "old-member-111"}},
		}).
		Execute()
	// snippet.show

	// Manage channel members: add new members and remove others
	response, status, err := pn.ManageChannelMembers().
		Channel("manage-members-channel"). // Channel ID
		Set([]pubnub.PNChannelMembersSet{  // Members to add
			{
				UUID: pubnub.PNChannelMembersUUID{ID: "new-member-111"},
				Custom: map[string]interface{}{
					"role": "developer",
				},
			},
		}).
		Remove([]pubnub.PNChannelMembersRemove{ // Members to remove
			{UUID: pubnub.PNChannelMembersUUID{ID: "old-member-111"}},
		}).
		Execute()

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

	if status.StatusCode == 200 {
		fmt.Printf("Managed channel members: %d member(s)\n", len(response.Data))
	}

	// Output:
	// Managed channel members: 1 member(s)
}
```

#### Response

The `ManageChannelMembers()` operation returns a `PNManageMembersResponse` which contains the following parameters:

| Property Name | Type | Description |
| --- | --- | --- |
| `Data` | []PNChannelMembers | Details of type `PNChannelMembers` are [here](#pnchannelmembers) |
| `TotalCount` | int | Total count of objects without pagination. |
| `Next` | string | Random string returned from the server, indicating a specific position in a data set. Used for forward pagination, it fetches the next page, allowing you to continue from where you left off. |
| `Prev` | string | Random string returned from the server, indicating a specific position in a data set. Used for backward pagination, it fetches the previous page, enabling access to earlier data. Ignored if the `Next` parameter is supplied. |

## 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.
* **User** - An individual or entity that interacts with a system, application, or service. In PubNub, a user typically refers to someone who sends or receives messages through the platform, identified by a unique user ID or username.
* **User ID** - UTF-8 encoded, unique string of up to 92 characters used to identify a single client (end user, device, or server) that connects to PubNub.