---
source_url: https://www.pubnub.com/docs/sdks/javascript/api-reference/subscribe
title: Subscribe API for JavaScript SDK
updated_at: 2026-11-09T13:29:01.000Z
sdk_name: PubNub JavaScript SDK
sdk_version: 13.1.3
description: "Reference for the subscribe methods of the PubNub JavaScript SDK: subscriptions, subscription sets, SDK entities, event listeners, and unsubscribing, with parameters and sample code."
---

# Subscribe API for JavaScript SDK

PubNub JavaScript SDK, use the latest version: 13.1.3

Install:

```bash
npm install pubnub@13.1.3
```

> For AI agents: documentation index at https://www.pubnub.com/llms-full.txt

The Subscribe API lets a PubNub client for JavaScript receive messages and events in real time. You create a subscription for one SDK entity, or a subscription set for several, add an event listener, and then subscribe.

For the concepts behind publishing and subscribing, see [Connection management](https://www.pubnub.com/docs/architecture/connection-management/overview.md), [Subscriptions](https://www.pubnub.com/docs/pub-sub/subscribe/subscriptions.md), and [Publish messages](https://www.pubnub.com/docs/pub-sub/publish/overview.md).

## Subscribe

`subscribe()` starts receiving real-time messages and events for a subscription or subscription set of a PubNub client for JavaScript.

To subscribe, set `subscribeKey` when you create the PubNub client. See [Initialization](https://www.pubnub.com/docs/sdks/javascript/api-reference/configuration.md#initialization).

By default, a subscription receives the messages that PubNub publishes after the subscribe request completes. Calling `subscribe()` starts the subscription but delivers nothing to your code until you add an event listener.

A PubNub client for JavaScript retries failed subscribe requests as set by `retryConfiguration`. The setting applies when `enableEventEngine` is `true`, which is the default. See [Configuration](https://www.pubnub.com/docs/sdks/javascript/api-reference/configuration.md#configuration).

Calling `subscribe()` on a subscription or subscription set that is already subscribed has no effect.

### Subscription scope

Subscriptions let you attach listeners for specific real-time update types. Your app receives messages and events through those listeners. There are two types:

* [`subscription`](#create-a-subscription): created from an SDK entity and scoped to that entity, for example a particular channel
* [`subscriptionSet`](#create-a-subscription-set): created from the PubNub client and scoped to the channels, channel groups, and subscriptions that you put in the set

```mermaid
flowchart TD
    C(Scope of real-time updates)
    C -->|Client scope<br/><code>subscriptionSet</code>| G[Create a subscription set <br>on the pubnub object]
    C -->|SDK entity scope<br/><code>subscription</code>| D[Create an SDK entity]
    
    D --> E[Create a subscription<br>on that SDK entity]
    E --> F[Add event listeners] 
    F --> H[Subscribe]
    
    G --> I[Add event listeners]
    I --> J[Subscribe]
    
    style H fill:#bbf,stroke:#f66,stroke-width:2px,stroke-dasharray: 5, 5
    style J fill:#bbf,stroke:#f66,stroke-width:2px,stroke-dasharray: 5, 5
```

`subscription` and `subscriptionSet` use the same `subscribe()` method.

| Parameter | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| timetoken | string | Optional | n/a | The timetoken from which to start returning available cached messages. PubNub provides cached messages on a best-effort basis. |

A wildcard channel name such as `sports.*` subscribes the same way. The message event reports the concrete channel in `channel` and the matching pattern in `subscription`.

### Returns

`subscribe()` returns nothing.

### Examples for Subscribe

#### Syntax

```typescript
subscription.subscribe({ timetoken?: string }): void;
subscriptionSet.subscribe({ timetoken?: string }): void;
```

#### Basic usage

```javascript
const channelsSubscriptionSet = pubnub.subscriptionSet({ channels: ['ch1', 'ch2'] });
channelsSubscriptionSet.subscribe();
```

#### Basic usage (React)

In React, create the subscription inside a `useEffect` hook and unsubscribe in the cleanup function to avoid memory leaks when the component unmounts.

```jsx
import React, { useEffect, useState } from 'react';
import PubNub from 'pubnub';

const pubnub = new PubNub({
  publishKey: 'YOUR_PUBLISH_KEY',
  subscribeKey: 'YOUR_SUBSCRIBE_KEY',
  userId: 'YOUR_USER_ID',
});

function SubscribedComponent() {
  const [isSubscribed, setIsSubscribed] = useState(false);

  useEffect(() => {
    const listener = {
      status: (statusEvent) => {
        if (
          statusEvent.category === 'PNConnectedCategory' ||
          statusEvent.category === 'PNSubscriptionChangedCategory'
        ) {
          setIsSubscribed(true);
        }
      },
    };
    pubnub.addListener(listener);

    const channel = pubnub.channel('my_channel');
    const subscription = channel.subscription({
      receivePresenceEvents: true,
    });
    subscription.subscribe();

    return () => {
      subscription.unsubscribe();
      pubnub.removeListener(listener);
    };
  }, []);

  return <div>{isSubscribed ? 'Subscribed to my_channel' : 'Connecting to channel...'}</div>;
}
```

## Create a subscription

`subscription()` creates a subscription for one SDK entity of a PubNub client for JavaScript. The subscription receives messages and events for only that entity.

Use several subscriptions to handle the message and event types of each channel differently.

| Parameter | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| subscriptionOptions | SubscriptionOptions | Optional | n/a | The options that control how the subscription behaves. See [`subscriptionOptions`](#subscriptionoptions). |

### subscriptionOptions

`subscriptionOptions` is an object of type `SubscriptionOptions`. Its properties are:

| Property | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| receivePresenceEvents | boolean | Optional | `false` | Whether the subscription delivers presence events for the entity to its listeners. The option has an effect only for channel and channel group SDK entities. For the events and how to receive them, see [Presence events](https://www.pubnub.com/docs/presence/presence-events.md). |
| filter | function | Optional | n/a | A function with the signature `(event) => boolean` that the SDK calls for each received event. The subscription passes the event to its listeners only when the function returns `true`. |

### Examples for Create a subscription

#### Syntax

```typescript
channel.subscription(subscriptionOptions?: SubscriptionOptions): Subscription;
```

#### Basic usage

```javascript
const channel = pubnub.channel('my_channel');

const subscriptionOptions = { receivePresenceEvents: true };
channel.subscription(subscriptionOptions);
```

## Create a subscription set

`subscriptionSet()` creates a subscription set in a PubNub client for JavaScript. The set receives messages and events for all the SDK entities that it contains.

Use a subscription set to handle the message and event types of several channels in the same way.

| Parameter | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| channels | string[] | Optional | n/a | The IDs of the channels that the subscription set subscribes to. The set creates an SDK channel entity for each ID. |
| channelGroups | string[] | Optional | n/a | The names of the channel groups that the subscription set subscribes to. The set creates an SDK channel group entity for each name. |
| subscriptionOptions | SubscriptionOptions | Optional | n/a | The behavior options, described in [`subscriptionOptions`](#subscriptionoptions). The set applies them to each subscription that it creates. |

A set created with neither `channels` nor `channelGroups` starts empty. Add subscriptions to it later, as described in [Modify a subscription set](#modify-a-subscription-set).

### Examples for Create a subscription set

#### Syntax

```typescript
pubnub.subscriptionSet({
    channels?: string[],
    channelGroups?: string[],
    subscriptionOptions?: SubscriptionOptions
}): SubscriptionSet;
```

## SDK entities

An SDK entity is a local handle that represents something you can subscribe to in a PubNub client for JavaScript. Creating one performs no network call and needs no matching server-side record.

Every SDK entity has a `subscription()` method. The PubNub client returns the same SDK entity object when you call a creation method again with the same name or ID.

The client has a creation method for each kind of SDK entity:

* [`channel`](#create-an-sdk-channel-entity)
* [`channelGroup`](#create-an-sdk-channel-group-entity)
* [`userMetadata`](#create-an-sdk-user-metadata-entity)
* [`channelMetadata`](#create-an-sdk-channel-metadata-entity)
* [`dataSyncUser`, `dataSyncChannel`, `dataSyncEntity`, `dataSyncRelationship`, and `dataSyncMembership`](#datasync-sdk-entities)

An SDK entity is not a DataSync entity. A DataSync entity is a stored server-side record, the source of truth for your application state, which you manage through the [DataSync API](https://www.pubnub.com/docs/sdks/javascript/api-reference/datasync.md). The [DataSync SDK entities](#datasync-sdk-entities) are SDK entities that subscribe to DataSync entities.

## Create an SDK channel entity

`channel()` returns an SDK channel entity that represents a channel in a PubNub client for JavaScript.

| Parameter | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| name | string | Yes | n/a | The ID of the channel to subscribe to. See [channels](https://www.pubnub.com/docs/pub-sub/subscribe/channels.md). |

### Examples for Create an SDK channel entity

#### Syntax

```typescript
pubnub.channel(name: string): Channel;
```

#### Basic usage

```javascript
const channel = pubnub.channel('my_channel');
```

## Create an SDK channel group entity

`channelGroup()` returns an SDK channel group entity that represents a channel group in a PubNub client for JavaScript.

| Parameter | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| name | string | Yes | n/a | The name of the channel group to subscribe to. See [channel groups](https://www.pubnub.com/docs/pub-sub/subscribe/subscriptions.md). |

### Examples for Create an SDK channel group entity

#### Syntax

```typescript
pubnub.channelGroup(name: string): ChannelGroup;
```

#### Basic usage

```javascript
// Initialize PubNub with demo keys
const channelGroup = pubnub.channelGroup('channelGroup_1');
```

## Create an SDK channel metadata entity

`channelMetadata()` returns an SDK channel metadata entity that represents the App Context metadata of a channel in a PubNub client for JavaScript.

| Parameter | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| id | string | Yes | n/a | The ID of the channel metadata object to observe. See [channel metadata](https://www.pubnub.com/docs/data-storage/metadata/manage-channel-metadata.md). |

### Examples for Create an SDK channel metadata entity

#### Syntax

```typescript
pubnub.channelMetadata(id: string): ChannelMetadata;
```

#### Basic usage

```javascript
// Initialize PubNub with demo keys

const channelMetadata = pubnub.channelMetadata('channel_1');
```

## Create an SDK user metadata entity

`userMetadata()` returns an SDK user metadata entity that represents the App Context metadata of a user in a PubNub client for JavaScript.

| Parameter | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| id | string | Yes | n/a | The ID of the user metadata object to observe. See [user metadata](https://www.pubnub.com/docs/data-storage/metadata/manage-user-metadata.md). |

### Examples for Create an SDK user metadata entity

#### Syntax

```typescript
pubnub.userMetadata(id: string): UserMetadata;
```

#### Basic usage

```javascript
// Initialize PubNub with demo keys

const userMetadata = pubnub.userMetadata('user_meta1');
```

## Event listeners

Event listeners are the single point through which your app receives all the messages, signals, and events of a PubNub client for JavaScript.

You can attach listeners to a subscription, a subscription set, and the PubNub client. A listener on the PubNub client receives the events of all its subscriptions. Attach the connection status listener to the PubNub client only. See [Add connection status listener](#add-connection-status-listener).

:::note No built-in event throttling
The PubNub SDK delivers every incoming event to your listener as it arrives. There is no built-in throttling or rate-limiting on the subscriber side. If you need to control how often your application processes events, wrap your listener callback with a throttle or debounce utility from your language or framework ecosystem.
To reduce the number of messages delivered to your client in the first place, use [Subscribe Filters](https://www.pubnub.com/docs/pub-sub/subscribe/subscribe-filter-expressions.md) to filter messages server-side before they reach your listener.
:::

## Add listeners

`addListener()` adds an event listener that receives messages and events through a subscription, subscription set, or PubNub client for JavaScript.

You can also assign an event-specific handler that receives only one type of event, such as `onMessage` or `onFile`. Each assignment replaces the previous handler of that type.

| Parameter | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| listener | Listener | Yes | n/a | An object whose properties are the handlers for each event type. Every handler is optional. |
| > message | function | Optional | n/a | Handles published messages. |
| > signal | function | Optional | n/a | Handles signals. |
| > presence | function | Optional | n/a | Handles presence events. A subscription delivers them when `receivePresenceEvents` is enabled. |
| > objects | function | Optional | n/a | Handles App Context events. |
| > messageAction | function | Optional | n/a | Handles message action events. |
| > file | function | Optional | n/a | Handles file sharing events. |
| > dataSync | function | Optional | n/a | Handles DataSync events. See [Add DataSync listener](#add-datasync-listener). |
| > status | function | Optional | n/a | Handles connection status changes. Only the PubNub client reports connection status, so you cannot attach this listener to a subscription or subscription set. See [Add connection status listener](#add-connection-status-listener). |

### Sample code

When you receive messages through listeners, the message object includes the sender's ID in the `publisher` field, along with the message content, channel name, timetoken, and other metadata.

### Returns

`addListener()` returns nothing.

### Examples for Add listeners

#### Syntax

```typescript
subscription.addListener(listener: Listener): void;
subscriptionSet.addListener(listener: Listener): void;
pubnub.addListener(listener: Listener): void;
```

#### Basic usage

```javascript
// create a subscription from a channel entity
const channel = pubnub.channel('channel_1');
const subscription = channel.subscription();

// Event-specific listeners
subscription.onMessage = (message) => {
  console.log('Message event: ', message);
};
subscription.onPresence = (presence) => {
  console.log('Presence event: ', presence);
};
subscription.onSignal = (signal) => {
  console.log('Signal event: ', signal);
};
subscription.onObjects = (objectsEvent) => {
  console.log('Objects event: ', objectsEvent);
};
subscription.onMessageAction = (messageActionEvent) => {
  console.log('Message Reaction event: ', messageActionEvent);
};
subscription.onFile = (fileEvent) => {
  console.log('File event: ', fileEvent);
};

// Generic listeners
subscription.addListener({
  // Messages
  message: function (m) {
    const channelName = m.channel; // Channel on which the message was published
    const channelGroup = m.subscription; // Channel group or wildcard subscription match (if exists)
    const pubTT = m.timetoken; // Publish timetoken
    const msg = m.message; // Message payload
    const publisher = m.publisher; // Message publisher
  },
  // Presence
  // requires a subscription with presence
  presence: function (p) {
    const action = p.action; // Can be join, leave, timeout, state-change, or interval
    const channelName = p.channel; // Channel to which the message belongs
    const channelGroup = p.subscription; //  Channel group or wildcard subscription match, if any
    const publishTime = p.timestamp; // Publish timetoken
    const timetoken = p.timetoken; // Current timetoken
  },
  // Signals
  signal: function (s) {
    const channelName = s.channel; // Channel to which the signal belongs
    const channelGroup = s.subscription; // Channel group or wildcard subscription match, if any
    const pubTT = s.timetoken; // Publish timetoken
    const msg = s.message; // Payload
    const publisher = s.publisher; // Message publisher
  },
  // App Context
  objects: (objectEvent) => {
    const channel = objectEvent.channel; // channel Id or a User Id of updated/set app context metadata object
    const channelGroup = objectEvent.subscription; // Channel group
    const timetoken = objectEvent.timetoken; // Event timetoken
    const event = objectEvent.message.data.type; // Event name
  },
  // Message Actions
  messageAction: function (ma) {
    const channelName = ma.channel; // Channel to which the message belongs
    const publisher = ma.data.uuid; // Message publisher
    const event = ma.event; // Message action added or removed
    const type = ma.data.type; // Message action type
    const value = ma.data.value; // Message action value
    const messageTimetoken = ma.data.messageTimetoken; // Timetoken of the original message
    const actionTimetoken = ma.data.actionTimetoken; // Timetoken of the message action
  },
  // File Sharing
  file: function (event) {
    const channelName = event.channel; // Channel to which the file belongs
    const channelGroup = event.subscription; // Channel group or wildcard subscription match (if exists)
    const publisher = event.publisher; // File publisher
    const timetoken = event.timetoken; // Event timetoken
    const message = event.message; // Optional message attached to the file
  },
});
```

```javascript
// create a subscription from a channel entity
const channel = pubnub.channel('channel_1');
const subscription1 = channel.subscription({ receivePresenceEvents: true });

// create a subscription set with multiple channels
const subscriptionSet1 = pubnub.subscriptionSet({ channels: ['ch1', 'ch2'] });

// add a status listener
pubnub.addListener({
  status: (s) => {
    console.log('Status', s.category);
  },
});

// add message and presence listeners
subscription1.addListener({
  // Messages
  message: (m) => {
    console.log('Received message', m);
  },
  // Presence
  presence: (p) => {
    console.log('Presence event', p);
  },
});

// add event-specific message actions listener
subscriptionSet1.onMessageAction = (p) => {
  console.log('Message action event:', p);
};

subscription1.subscribe();
subscriptionSet1.subscribe();
```

#### Basic usage (React)

In React, add listeners inside `useEffect` and remove them in the cleanup function. Update component state from within the listener callbacks to trigger re-renders.

```jsx
import React, { useState, useEffect } from 'react';
import PubNub from 'pubnub';

const pubnub = new PubNub({
  publishKey: 'YOUR_PUBLISH_KEY',
  subscribeKey: 'YOUR_SUBSCRIBE_KEY',
  userId: 'YOUR_USER_ID',
});

function Chat() {
  const [messages, setMessages] = useState([]);
  const [onlineCount, setOnlineCount] = useState(0);
  const [isConnected, setIsConnected] = useState(false);

  useEffect(() => {
    pubnub.addListener({
      message: (event) => {
        setMessages((prev) => [...prev, event.message]);
      },
      presence: (event) => {
        // event.action: 'join' | 'leave' | 'timeout' | 'interval' | 'state-change'
        // occupancy is present on join/leave/timeout/interval but not on state-change
        if (event.action !== 'state-change') setOnlineCount(event.occupancy);
      },
      status: (event) => {
        setIsConnected(event.category === 'PNConnectedCategory');
      },
    });

    const channel = pubnub.channel('my_channel');
    const subscription = channel.subscription({ receivePresenceEvents: true });
    subscription.subscribe();

    return () => {
      subscription.unsubscribe();
      pubnub.removeAllListeners();
    };
  }, []);

  return (
    <div>
      <p>{isConnected ? `Connected — ${onlineCount} online` : 'Connecting...'}</p>
      <ul>
        {messages.map((msg, i) => (
          <li key={i}>{typeof msg === 'object' ? JSON.stringify(msg) : msg}</li>
        ))}
      </ul>
    </div>
  );
}
```

## Add connection status listener

`addListener()` adds a listener that reports the connection status of a PubNub client for JavaScript.

Only the PubNub client reports connection status, so you cannot attach this listener to a subscription or subscription set.

| Parameter | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| status | function | Yes | n/a | The handler that the SDK calls each time the connection status changes, with the status object described under Returns. |

### Returns

The handler receives a status object. Only `category` is always present. The other properties depend on the category. For the list of status categories, see [SDK statuses](https://www.pubnub.com/docs/architecture/connection-management/overview.md).

| Property | Type | Description |
| --- | --- | --- |
| category | string | The status category, for example `PNConnectedCategory`. |
| operation | string | The operation that reported the status. |
| error | string, boolean | Information about the error. The value is `false` when there is no error. |
| affectedChannels | string[] | The channels that the status change affects. |
| affectedChannelGroups | string[] | The channel groups that the status change affects. |
| subscribedChannels | string[] | The channels that the client is subscribed to now. |
| lastTimetoken | string, number | The timetoken that the previous subscribe request used. |
| currentTimetoken | string, number | The timetoken that the current subscribe request uses. |
| statusCode | number | The REST API status code. Present on statuses that report a failed request. |
| errorData | object | The error details that the REST API returned. Present on statuses that report a failed request. |

### Examples for Add connection status listener

#### Syntax

```typescript
pubnub.addListener({ status: (status: Status | StatusEvent) => void }): void;
```

#### Basic usage

```javascript
// add a status listener
pubnub.addListener({
  status: (s) => {
    console.log('Status', s.category);
  },
});
```

## Add DataSync listener

`dataSync` is the listener for DataSync events, which a PubNub client for JavaScript gets when a DataSync object is created, updated, or deleted.

To receive these events, create a [DataSync SDK entity](#datasync-sdk-entities) for the object, subscribe to it, and attach a `dataSync` listener. The listener works on all three scopes: the PubNub client, a `subscription`, and a `subscriptionSet`.

DataSync events are off by default. You enable event publishing for each class in the [Admin Portal](https://admin.pubnub.com). See [enabling DataSync events](https://www.pubnub.com/docs/data-storage/structured-data/events.md#enable-datasync-events).

A relationship or membership change is delivered on the ids of the two objects it links, and never on a channel named after the relationship or membership id. A `create` for a user, channel, or entity is delivered only on its own `id`. An `update` or `delete` for a user, channel, or entity is also delivered on the `id` of every object connected to it at the time of the change. The connection can be a relationship or membership, in either direction.

See [Where each event is delivered](https://www.pubnub.com/docs/sdks/javascript/api-reference/datasync.md#where-each-event-is-delivered) for the full mapping.

An event is delivered once for each channel it fans out to, and each delivery carries only the fields that the channel's projection exposes. The plain (`__default__`) channel and a `__{projection}__{id}` channel each carry only the fields declared under their own projection. The service filters `status` the same way, through the class's declared projections for `/status`. The service always delivers `id`, `eTag`, `createdAt`, `updatedAt`, and `expiresAt` unfiltered and never filters `delete` events. See [DataSync projections](https://www.pubnub.com/docs/data-storage/structured-data/projections.md#what-projections-enforce).

| Parameter | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| event | DataSyncObject | Yes | n/a | The handler argument, which holds the event fields described below. |

The listener callback receives an event object with the following properties:

| Property | Type | Description |
| --- | --- | --- |
| channel | string | The concrete data channel on which this copy of the event arrived. The value is the changed object's ID, a connected entity's ID for a fanned-out event, or a named projection channel such as `__admin__product-sneaker-42`. Identify the changed object through `message.data.id`. |
| subscription | string \| null | The subscription that matched, for example the wildcard pattern you subscribed to. `null` when it is the same as `channel`. |
| timetoken | string | The event timetoken. |
| message | object | The parsed DataSync change. Its properties are described below. |

The `message` object contains the change details:

| Property | Type | Description |
| --- | --- | --- |
| version | string | The DataSync service payload version. May be absent. |
| event | string | The change type: `create`, `update`, or `delete`. |
| source | string | Always `data-sync` (hyphenated), the wire-format value of the service. It differs from the `dataSync` naming used elsewhere in the SDK (the listener, `onDataSync`, and Access Manager resource key). |
| type | string | The object kind as sent by the service: `user`, `channel`, `membership`, `entity`, or `relationship`. The built-in `User`, `Channel`, and `Membership` classes report their own kind, and a class you define reports the generic `entity` or `relationship`. |
| objectType | string | The normalized object kind, with the same five values as `type`. Against a current service the value equals `type`. The two differ only against an older service that reports the built-in classes under the generic `entity` or `relationship` kind. In that case the SDK derives the kind from `className` and `classLevel`. Read this one if you need to support both. |
| className | string | The class name of the changed object, as a plain name. May be absent. |
| classLevel | string | Where the class is defined: `Global` for the built-in `User`, `Channel`, and `Membership` classes, or `SubKey` for a class you defined on your own key set. May be absent. |
| classVersion | number | The class version of the changed object. May be absent. |
| data | object | The object state, which varies by event and type. See the descriptions below. |

`className`, `classLevel`, and `classVersion` are reported once on `message` and are not repeated inside `data`. There is no `data.entityClass` or `data.relationshipClass` on an event, unlike the objects returned by the [DataSync API](https://www.pubnub.com/docs/sdks/javascript/api-reference/datasync.md). Read `classLevel` alongside `className` when you need to tell a built-in class from one of your own that happens to share its name.

The shape of `data` depends on the object kind and the event:

* Entity events (users, channels, and custom entities) on `create` and `update` carry the current object state: `id`, `status`, `payload`, `createdAt`, `updatedAt`, `eTag`, and `expiresAt`.
* Relationship events (your own relationship classes) on `create` and `update` carry the same fields plus `entityAId` and `entityBId`.
* Membership events on `create` and `update` carry the same fields plus `channelId` and `userId`, the same names the [DataSync API](https://www.pubnub.com/docs/sdks/javascript/api-reference/datasync.md#memberships) uses. A membership event never carries `entityAId` or `entityBId`.
* Delete events carry only `id` and `deletedAt`, for every object kind.

Apart from `id`, every `data` field can be absent, so guard the access when you read one, for example `event.message.data.payload?.price`.

### Sample code

To keep a full local copy of the object, fetch it once with `pubnub.dataSync.getEntity()` for the current state, then apply events as they arrive. Filter by `type` and `data.id` first because the channel also receives relationship and connected-entity fan-out. Compare the `eTag` or `updatedAt` on create and update events against your local copy to detect stale updates. Use `id` and `deletedAt` for delete events.

When you filter on `type`, match the value for the kind you are tracking. A class of your own reports `entity` or `relationship`. The built-in classes report `user`, `channel`, and `membership`. A filter hardcoded to `entity` therefore drops every user and channel event.

For the fetch methods, see the [DataSync API](https://www.pubnub.com/docs/sdks/javascript/api-reference/datasync.md). For the concurrency pattern, see [ETags](https://www.pubnub.com/docs/data-storage/structured-data/data-operations.md#optimistic-concurrency-with-etags).

### Examples for Add DataSync listener

#### Syntax

```typescript
pubnub.addListener({ dataSync: (event: DataSyncObject) => void }): void;
pubnub.onDataSync = (event: DataSyncObject) => void;
subscription.onDataSync = (event: DataSyncObject) => void;
subscriptionSet.onDataSync = (event: DataSyncObject) => void;
```

#### Basic usage

```javascript
// Create a DataSync SDK entity for the object and attach the listener.
const dataSyncObjectId = 'product-sneaker-42';
const dataSyncListenerSubscription = pubnub.dataSyncEntity(dataSyncObjectId).subscription();

dataSyncListenerSubscription.onDataSync = (event) => {
  const change = event.message;

  // This channel can also receive relationship events and events about connected entities. Only
  // handle events for the observed product. `Product` is a class of your own, so its events
  // report `type: 'entity'`.
  if (change.type !== 'entity' || change.data.id !== dataSyncObjectId) return;

  switch (change.event) {
    case 'create':
      console.log('Product created:', change.data.id);
      break;
    case 'update': {
      // `payload` is typed as the generic SDK `Payload` union (it can be a string, number, array,
      // and so on for other message types), but a DataSync entity payload is always the JSON
      // object declared by its class, so it is safe to read it as a record here.
      const payload =
        'payload' in change.data ? (change.data.payload as Record<string, unknown> | undefined) : undefined;
      console.log('New price:', payload?.price);
      break;
    }
    case 'delete':
      console.log('Product deleted:', change.data.id);
      break;
  }
};

dataSyncListenerSubscription.subscribe();
```

## Remove listener

`removeListener()` removes an event listener from a subscription, subscription set, or PubNub client for JavaScript, so the listener stops receiving events.

The SDK identifies a listener by object, so pass the same object that you passed to `addListener()`. Removing an object that you never added has no effect. The SDK counts additions, so call `removeListener()` once for each time that you added that object.

| Parameter | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| listener | Listener | Yes | n/a | The listener object to remove. Pass the object that you passed to `addListener()`. |

### Returns

`removeListener()` returns nothing.

### Examples for Remove listener

#### Syntax

```typescript
subscription.removeListener(listener: Listener): void;
subscriptionSet.removeListener(listener: Listener): void;
pubnub.removeListener(listener: Listener): void;
```

## Remove all listeners

`removeAllListeners()` removes every event listener from a subscription, subscription set, or PubNub client for JavaScript.

The call also clears the event-specific handlers that you assigned, such as `onMessage`. Subscriptions and subscription sets stay subscribed.

`removeAllListeners()` takes no parameters.

### Returns

`removeAllListeners()` returns nothing.

### Examples for Remove all listeners

#### Syntax

```typescript
subscription.removeAllListeners(): void;
subscriptionSet.removeAllListeners(): void;
pubnub.removeAllListeners(): void;
```

## Unsubscribe

`unsubscribe()` stops a subscription or subscription set of a PubNub client for JavaScript from receiving real-time updates.

A channel stays subscribed while another active subscription or subscription set of the same PubNub client still uses it. If a subscription is subscribed only through a subscribed set, `unsubscribe()` on the subscription has no effect and the SDK logs a warning. Remove the subscription from the set instead.

`unsubscribe()` takes no parameters.

### Returns

`unsubscribe()` returns nothing.

### Examples for Unsubscribe

#### Syntax

```typescript
subscription.unsubscribe(): void;
subscriptionSet.unsubscribe(): void;
```

#### Basic usage

```javascript
// create a subscription from a channel entity
const channel1 = pubnub.channel('channel_1');
const subscription1 = channel1.subscription({ receivePresenceEvents: true });

// create a subscription set with multiple channels
const subscriptionSet1 = pubnub.subscriptionSet({ channels: ['ch1', 'ch2'] });

subscription1.subscribe();
subscriptionSet1.subscribe();

subscription1.unsubscribe();
subscriptionSet1.unsubscribe();
```

## Unsubscribe all

`unsubscribeAll()` unsubscribes every subscription and subscription set of a PubNub client for JavaScript at once.

Only the PubNub client has this method, not a subscription or subscription set.

`unsubscribeAll()` takes no parameters.

### Returns

`unsubscribeAll()` returns nothing.

### Examples for Unsubscribe all

#### Syntax

```typescript
pubnub.unsubscribeAll(): void;
```

#### Basic usage

```javascript
// create a subscription set with multiple channels
const subscriptionSet = pubnub.subscriptionSet({ channels: ['ch1', 'ch2'] });
subscriptionSet.subscribe();

// create a subscription from a channel entity
const channelGroup1 = pubnub.channelGroup('channelGroup_1');
const groupSubscription1 = channelGroup1.subscription({ receivePresenceEvents: true });
groupSubscription1.subscribe();

// unsubscribe all active subscriptions
pubnub.unsubscribeAll();
```

## Create a subscription set from subscriptions

`subscription.addSubscription()` combines two subscriptions into a new subscription set in a PubNub client for JavaScript.

The new set contains both subscriptions. If either subscription is already subscribed, the new set subscribes immediately.

| Parameter | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| subscription | Subscription | Yes | n/a | The subscription to combine with the receiver into a new set. |

### Examples for Create a subscription set from subscriptions

#### Syntax

```typescript
subscription.addSubscription(subscription: Subscription): SubscriptionSet;
```

#### Basic usage

```javascript
// create a subscription from a channel entity
const channel = pubnub.channel('channel_1');
const subscription1 = channel.subscription({ receivePresenceEvents: true });

// create a subscription from a channel group entity
const channelGroup = pubnub.channelGroup('channelGroup_1');
const subscription2 = channelGroup.subscription();

// add 2 subscriptions to create a subscription set
const subscriptionSet = subscription1.addSubscription(subscription2);

// add another subscription to the set
const subscription3 = pubnub.channel('channel_3').subscription({ receivePresenceEvents: false });
subscriptionSet.addSubscription(subscription3);

// remove a subscription from a subscription set
subscriptionSet.removeSubscription(subscription3);

subscriptionSet.subscribe();
```

## Modify a subscription set

`addSubscriptions()` and `removeSubscriptions()` change the subscriptions in a subscription set of a PubNub client for JavaScript.

If the subscription set is already subscribed, a change takes effect immediately.

| Parameter | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| subscription | Subscription | Yes | n/a | The subscription to add to or remove from the set. |
| subscriptions | Subscription[] | Yes | n/a | The subscriptions to add to or remove from the set. |

### Examples for Modify a subscription set

#### Syntax

```typescript
subscriptionSet.addSubscription(subscription: Subscription): void;
subscriptionSet.addSubscriptions(subscriptions: Subscription[]): void;
subscriptionSet.removeSubscription(subscription: Subscription): void;
subscriptionSet.removeSubscriptions(subscriptions: Subscription[]): void;
```

#### Basic usage

```javascript
// create a subscription set with multiple channels
const subscriptionSet1 = pubnub.subscriptionSet({ channels: ['ch1', 'ch2'] });

// subscribe to the set
// start receiving events from ch1 and ch2
subscriptionSet1.subscribe();

// create another subscription set with multiple channels
const subscriptionSet2 = pubnub.subscriptionSet({ channels: ['ch3', 'ch4'] });

// add the new set to the initial set
subscriptionSet1.addSubscriptionSet(subscriptionSet2);

// you're now receiving events from ch1, ch2, ch3, and ch4
// because the set has been subscribed to previously

// create and add another subscription to the set
const channelGroup = pubnub.channelGroup('channelGroup_1');
const subscription2 = channelGroup.subscription();
subscriptionSet1.addSubscription(subscription2);

// you're now receiving events from ch1, ch2, ch3, and ch4 and channelGroup_1
```

## Combine subscription sets

`addSubscriptionSet()` and `removeSubscriptionSet()` merge another subscription set into a subscription set of a PubNub client for JavaScript, or remove it again.

| Parameter | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| subscriptionSet | SubscriptionSet | Yes | n/a | The subscription set whose subscriptions the receiver adds or removes. |

### Examples for Combine subscription sets

#### Syntax

```typescript
subscriptionSet.addSubscriptionSet(subscriptionSet: SubscriptionSet): void;
subscriptionSet.removeSubscriptionSet(subscriptionSet: SubscriptionSet): void;
```

#### Basic usage

```javascript
// create a subscription set with multiple channels
const subscriptionSet1 = pubnub.subscriptionSet({ channels: ['ch1', 'ch2'] });

// create another subscription set with multiple channels and options
const subscriptionSet2 = pubnub.subscriptionSet({
  channels: ['ch3', 'ch4'],
  subscriptionOptions: { receivePresenceEvents: true },
});

// add a subscription set to another subscription set
subscriptionSet1.addSubscriptionSet(subscriptionSet2);

// remove a subscription set from another subscription set
subscriptionSet1.removeSubscriptionSet(subscriptionSet2);
```

## DataSync SDK entities

`dataSyncEntity()` and the other DataSync entity methods return SDK entities that observe DataSync objects in a PubNub client for JavaScript.

These methods are the subscribe-side counterpart to the `pubnub.dataSync.*` read and write methods. Call `subscription()` on the returned SDK entity to observe changes. Each method observes one kind of DataSync object:

* `dataSyncUser()`: a DataSync [user](https://www.pubnub.com/docs/sdks/javascript/api-reference/datasync.md#users)
* `dataSyncChannel()`: a DataSync [channel](https://www.pubnub.com/docs/sdks/javascript/api-reference/datasync.md#channels)
* `dataSyncEntity()`: a DataSync [entity](https://www.pubnub.com/docs/sdks/javascript/api-reference/datasync.md#entities)
* `dataSyncRelationship()`: a DataSync [relationship](https://www.pubnub.com/docs/sdks/javascript/api-reference/datasync.md#relationships)
* `dataSyncMembership()`: a DataSync [membership](https://www.pubnub.com/docs/sdks/javascript/api-reference/datasync.md#memberships)

A relationship change is delivered on the data channels of the two entities it links (`entityAId` and `entityBId`), and a membership change on those of its `userId` and `channelId`. The service never publishes either on a channel named after the relationship or membership id, so `dataSyncRelationship()` and `dataSyncMembership()` receive nothing for the link itself. To watch memberships appear and disappear, observe the linked user and channel with `dataSyncUser()` and `dataSyncChannel()` instead. See [Where each event is delivered](https://www.pubnub.com/docs/sdks/javascript/api-reference/datasync.md#where-each-event-is-delivered).

| Parameter | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| id | string | Yes | n/a | The ID of the DataSync object to observe. The SDK uses it verbatim, so a wildcard identifier such as `product.*` works as written. |

DataSync SDK entities accept every [`subscriptionOptions`](#subscriptionoptions) property plus one of their own, `projection`:

| Parameter | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| subscriptionOptions | DataSyncSubscriptionOptions | Optional | n/a | The subscription options, with the extra `projection` property. |
| > projection | string | Optional | n/a | The name of the DataSync [projection](https://www.pubnub.com/docs/data-storage/structured-data/projections.md) to observe. Omit it, or pass `default` or `__default__`, to observe the object itself. Any other name observes the projection on its own `__{projection}__{id}` channel. |

`receivePresenceEvents` is ignored, because a DataSync object is observed on a single data channel and has no presence channel.

The projection is chosen per subscription rather than per entity, so one entity can serve several projections at once. Each `(id, projection)` pair is subscribed and unsubscribed independently:

Both subscriptions receive their own copy of a change, and the projected one carries whatever extra fields the `admin` projection exposes. Unsubscribing one leaves the other subscribed.

The SDK passes the identifier through exactly as given. `dataSyncUser('__admin__u1').subscription({ projection: 'admin' })` therefore observes `__admin____admin__u1`, and the SDK does not collapse the repeated prefix.

### Examples for DataSync SDK entities

#### Syntax

```typescript
pubnub.dataSyncUser(id: string): DataSyncUser;
pubnub.dataSyncChannel(id: string): DataSyncChannel;
pubnub.dataSyncEntity(id: string): DataSyncEntity;
pubnub.dataSyncRelationship(id: string): DataSyncRelationship;
pubnub.dataSyncMembership(id: string): DataSyncMembership;
```

#### Syntax (2)

```typescript
dataSyncEntity.subscription(subscriptionOptions?: DataSyncSubscriptionOptions): Subscription;
```

#### Syntax (3)

```javascript
const user = pubnub.dataSyncUser('user-alice')

const base = user.subscription()                        // observes `user-alice`
const admin = user.subscription({ projection: 'admin' }) // observes `__admin__user-alice`
```

#### Basic usage

```javascript
// Observe one entity.
const entitySubscription = pubnub.dataSyncEntity('product-sneaker-42').subscription();

entitySubscription.onDataSync = (event) => {
  console.log(event.message.event, event.message.data);
};

entitySubscription.subscribe();
```

#### Observe every entity whose id matches a pattern

The SDK uses the identifier verbatim, so a wildcard identifier subscribes to the matching channel pattern and one subscription serves the whole set. In the event, `channel` reports the concrete delivery channel, while `subscription` reports the pattern that matched it. For a fanned-out event, the changed object's id can differ from the delivery channel, so identify it through `event.message.data.id`.

```javascript
// Because the identifier is used verbatim, a wildcard identifier subscribes to the matching
// channel pattern and one subscription serves the whole set. `event.channel` reports the concrete
// delivery channel, while `event.subscription` reports the pattern that matched it.
const patternSubscription = pubnub.dataSyncEntity('product.*').subscription({ projection: 'admin' });

patternSubscription.onDataSync = (event) => {
  // event.channel      -> '__admin__product.676'
  // event.subscription -> '__admin__product.*'
  console.log('changed:', event.message.data.id);
};

patternSubscription.subscribe();
```

#### Combine DataSync subscriptions with other subscriptions

A DataSync subscription is an ordinary `subscription`, so it composes into a set with any other subscription.

```javascript
// A DataSync subscription is an ordinary `subscription`, so it composes into a set with any other
// subscription.
const productsSubscription = pubnub.dataSyncEntity('product.*').subscription();
const aliceSubscription = pubnub.dataSyncUser('user-alice').subscription();

const dataSyncSubscriptionSet = productsSubscription.addSubscription(aliceSubscription);
dataSyncSubscriptionSet.onDataSync = (event) => console.log(event.message.objectType, event.message.event);
dataSyncSubscriptionSet.subscribe();
```

## Deprecated subscribe methods

Deprecated JavaScript subscribe methods still work, and each one has a current replacement.

The `pubnub.subscribe()`, `pubnub.unsubscribe()`, and `pubnub.unsubscribeAll()` methods that take `channels` and `channelGroups` are discouraged for new apps. Use [Subscribe](#subscribe), [Unsubscribe](#unsubscribe), and [Unsubscribe all](#unsubscribe-all) instead. The reference for apps that still use them is [Subscribe API: not recommended methods for JavaScript SDK](https://www.pubnub.com/docs/sdks/javascript/api-reference/subscribe-legacy.md).

Last updated at: 2026-11-09T13:29:01.000Z
