---
source_url: https://www.pubnub.com/docs/chat/sdks/users/setup
title: Setup and event listeners (deprecated)
updated_at: 2026-05-29T11:08:36.217Z
---

> 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


# Setup and event listeners (deprecated)

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

All chat applications have a notion of a user. It's important to be able to uniquely identify users as they interact with the PubNub Network. Usually, a user is a human end user—a person using an app to interact with a system (via a laptop, phone, tablet, or kiosk).

You use a [User ID](https://www.pubnub.com/docs/general/setup/users-and-devices#user-id-usage) to uniquely identify each user on the system. Users can connect from multiple devices, such as phones, tablets, desktops, etc., using the same User ID. If a user is connected from multiple devices simultaneously, they will receive the same messages on each device.

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

## Setup

Start by initializing a PubNub object with `publishKey`, `subscribeKey`, and `userId` as required fields. The `userId` is a string of maximum 92 characters that represents a user in your application.

Your publish and subscribe keys are available in your PubNub Account. Go to the [Admin Portal](https://admin.pubnub.com/) to create your free account.

:::note userId is required
Setting the `userId` parameter is required to establish a connection to PubNub, ensure that your billing is accurate, and for other features like presence and storage to work as expected.
:::

###### JavaScript

```js
const pubnub = new PubNub({
  subscribeKey: "mySubscribeKey",
  publishKey: "myPublishKey",
  userId: "john-doe",
  autoNetworkDetection: true, // enable for non-browser environment automatic reconnection
  restore: true, // enable catchup on missed messages
});
```

###### Java

```java
PNConfiguration.Builder configBuilder = PNConfiguration.builder(new UserId("yourUserId"), "yourSubscribeKey");
configBuilder.publishKey("myPublishKey");
PubNub pubNub = PubNub.create(configBuilder.build());
```

###### Swift

```swift
let config = PubNubConfiguration(
  publishKey: "myPublishKey",
  subscribeKey: "mySubscribeKey",
  userId: "john-doe"
)

let pubnub = PubNub(configuration: config)
```

###### Objective-C

```objectivec
PNConfiguration *pnconfig = [PNConfiguration configurationWithPublishKey:@"myPublishKey"
                                             subscribeKey:@"mySubscribeKey"];
pnconfig.uuid = "john-doe";
self.pubnub = [PubNub clientWithConfiguration:pnconfig];
```

## Add event listeners

Events are received in your app using listeners. These listeners allows a single point to receive messages, signals, and presence events. Each event type has its own handler to receive them where you implement your custom app logic to perform actions on events.

The following handlers are available to you:

| Handler | Description |
| --- | --- |
| Status | Receives events when the client successfully connects (subscribes), or reconnects (in case of connection issues) to channels. |
| Message | Receives all messages published to all the channels subscribed by the client. The event payload will contain the published message data, publish timetoken, the User ID of the client that published the message and more. |
| Signal | Receives all *signals* that are sent to any channels subscribed by the client. The event payload will contain the signal data, signal timetoken, the User ID of the client that published the message and more. |
| Presence | Receives all *presence events* that are triggered on any channels subscribed by the client. The event payload will contain the presence event type (`join`, `leave`, `timeout`, `state-change`), timetoken of the action, the User ID of the client that caused the event, state data (if applicable) and more. This handler only fires if [subscribe with Presence](https://www.pubnub.com/docs/chat/sdks/users/presence#subscribe-with-presence) is enabled. A regular subscribe does not deliver presence events. |
| MessageAction | Receives all events when existing messages are annotated (by an action) for any channels *subscribed* by the client. The event payload will contain the User ID that acted on the message, message reaction type (such as an emoji reaction), timetoken of the annotated message, timetoken of the action, action value and more. |
| Objects | Receives all *objects* events that are emitted when a channel, channel membership, or user metadata is created, updated or removed. |

### JavaScript

```javascript
pubnub.addListener({
    message: function(m) {
        // handle message
        var channelName = m.channel; // The channel to which the message was published
        var channelGroup = m.subscription; // The channel group or wildcard subscription match (if exists)
        var pubTT = m.timetoken; // Publish timetoken
        var msg = m.message; // The Payload
        var publisher = m.publisher; //The Publisher
    },
    presence: function(p) {
        // handle presence
        var action = p.action; // Can be join, leave, state-change, or timeout
        var channelName = p.channel; // The channel to which the message was published
        var occupancy = p.occupancy; // Number of users subscribed to the channel
        var state = p.state; // User State
        var channelGroup = p.subscription; //  The channel group or wildcard subscription match (if exists)
        var publishTime = p.timestamp; // Publish timetoken
        var timetoken = p.timetoken;  // Current timetoken
        var uuid = p.uuid; // UUIDs of users who are subscribed to the channel
    },
    signal: function(s) {
        // handle signal
        var channelName = s.channel; // The channel to which the signal was published
        var channelGroup = s.subscription; // The channel group or wildcard subscription match (if exists)
        var pubTT = s.timetoken; // Publish timetoken
        var msg = s.message; // The Payload
        var publisher = s.publisher; //The Publisher
    },
    objects: (objectEvent) => {
        var channel = objectEvent.channel; // The channel
        var channelGroup = objectEvent.subscription; // The channel group
        var timetoken = objectEvent.timetoken; // The event timetoken
        var publisher = objectEvent.publisher; // The User ID that triggered this event
        var event = objectEvent.event; // The event name that occurred
        var type = objectEvent.type; // The event type that occurred
        var data = objectEvent.data; // The event data that occurred
    },
    messageAction: function(ma) {
        // handle message reaction
        var channelName = ma.channel; // The channel to which the message was published
        var publisher = ma.publisher; //The Publisher
        var event = ma.message.event; // message reaction added or removed
        var type = ma.message.data.type; // message reaction type
        var value = ma.message.data.value; // message reaction value
        var messageTimetoken = ma.message.data.messageTimetoken; // The timetoken of the original message
        var actionTimetoken = ma.message.data.actionTimetoken; // The timetoken of the message reaction
    },
    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
        const fileId = event.file.id; // File unique id
        const fileName = event.file.name;// File name
        const fileUrl = event.file.url; // File direct URL
    },
    status: function(s) {
        var affectedChannelGroups = s.affectedChannelGroups; // The channel groups affected in the operation, of type array.
        var affectedChannels = s.affectedChannels; // The channels affected in the operation, of type array.
        var category = s.category; //Returns PNConnectedCategory
        var operation = s.operation; //Returns PNSubscribeOperation
        var lastTimetoken = s.lastTimetoken; //The last timetoken used in the subscribe request, of type long.
        var currentTimetoken = s.currentTimetoken; //The current timetoken fetched in the subscribe response, which is going to be used in the next request, of type long.
        var subscribedChannels = s.subscribedChannels; //All the current subscribed channels, of type array.
    },
});
```

### Java

```java
pubnub.addListener(new StatusListener() {
    // PubNub status
    @Override
    public void status(PubNub pubnub, PNStatus status) {
            switch (status.getCategory()) {
                /* handle various statuses */
            }
        }
    });

pubnub.addListener(new EventListener() {
    // Messages
    @Override
    public void message(PubNub pubnub, PNMessageResult message) {
        String messagePublisher = message.getPublisher();
        System.out.println("Message publisher: " + messagePublisher);
        System.out.println("Message Payload: " + message.getMessage());
        System.out.println("Message Subscription: " + message.getSubscription());
        System.out.println("Message Channel: " + message.getChannel());
        System.out.println("Message timetoken: " + message.getTimetoken());
    }

    // Presence
    @Override
    public void presence(@NotNull PubNub pubnub, @NotNull PNPresenceEventResult presence) {
        System.out.println("Presence Event: " + presence.getEvent());
        // Can be join, leave, state-change or timeout

        System.out.println("Presence Channel: " + presence.getChannel());
        // The channel to which the message was published

        System.out.println("Presence Occupancy: " + presence.getOccupancy());
        // Number of users subscribed to the channel

        System.out.println("Presence State: " + presence.getState());
        // User state

        System.out.println("Presence UUID: " + presence.getUserId());
        // User ID to which this event is related

        presence.getJoin();
        // List of users that have joined the channel (if event is 'interval')

        presence.getLeave();
        // List of users that have left the channel (if event is 'interval')

        presence.getTimeout();
        // List of users that have timed-out off the channel (if event is 'interval')

        presence.getHereNowRefresh();
        // Indicates to the client that it should call 'hereNow()' to get the
        // complete list of users present in the channel.
    }

    // Signals
    @Override
    public void signal(PubNub pubnub, PNSignalResult pnSignalResult) {
        System.out.println("Signal publisher: " + signal.getPublisher());
        System.out.println("Signal payload: " + signal.getMessage());
        System.out.println("Signal subscription: " + signal.getSubscription());
        System.out.println("Signal channel: " + signal.getChannel());
        System.out.println("Signal timetoken: " + signal.getTimetoken());
    }

    // Message reaction
    @Override
    public void messageAction(PubNub pubnub, PNMessageActionResult pnActionResult) {
        PNMessageAction pnMessageAction = pnActionResult.getAction();
        System.out.println("Message reaction type: " + pnMessageAction.getType());
        System.out.println("Message reaction value: " + pnMessageAction.getValue());
        System.out.println("Message reaction User ID: " + pnMessageAction.getUserId());
        System.out.println("Message reaction actionTimetoken: " + pnMessageAction.getActionTimetoken());
        System.out.println("Message reaction messageTimetoken: " + pnMessageAction.getMessageTimetoken());]
        System.out.println("Message reaction subscription: " + pnActionResult.getSubscription());
        System.out.println("Message reaction channel: " + pnActionResult.getChannel());
        System.out.println("Message reaction timetoken: " + pnActionResult.getTimetoken());
    }

    // File Sharing
    @Override
    public void file(PubNub pubnub, PNFileEventResult pnFileEventResult) {
        System.out.println("File channel: " + pnFileEventResult.getChannel());
        System.out.println("File publisher: " + pnFileEventResult.getPublisher());
        System.out.println("File message: " + pnFileEventResult.getMessage());
        System.out.println("File timetoken: " + pnFileEventResult.getTimetoken());
        System.out.println("File file.id: " + pnFileEventResult.getFile().getId());
        System.out.println("File file.name: " + pnFileEventResult.getFile().getName());
        System.out.println("File file.url: " + pnFileEventResult.getFile().getUrl());
    }
});
```

### Swift

```swift
// Create a new listener instance
let listener = SubscriptionListener()

// Add listener event callbacks
listener.didReceiveSubscription = { event in
  switch event {
  case let .messageReceived(message):
    print("Message Received: \(message) Publisher: \(message.publisher ?? "defaultUserID")")
  case let .connectionStatusChanged(status):
    print("Status Received: \(status)")
  case let .presenceChanged(presence):
    print("Presence Received: \(presence)")
  case let .subscribeError(error):
    print("Subscription Error \(error)")
  default:
    break
  }
}

// Start receiving subscription events
pubnub.add(listener)
```

### Objective-C

```objectivec
// Listener's class should conform to `PNEventsListener` protocol
// in order to have access to available callbacks.

// Adding listener.
[pubnub addListener:self];

// Callbacks listed below.

- (void)client:(PubNub *)pubnub didReceiveMessage:(PNMessageResult *)message {
    NSString *channel = message.data.channel; // Channel on which the message has been published
    NSString *subscription = message.data.subscription; // Wild-card channel or channel on which PubNub client actually subscribed
    NSNumber *timetoken = message.data.timetoken; // Publish timetoken
    id msg = message.data.message; // Message payload
    NSString *publisher = message.data.publisher; // Message publisher
}

- (void)client:(PubNub *)pubnub didReceiveSignal:(PNSignalResult *)signal {
    NSString *channel = message.data.channel; // Channel on which the signal has been published
    NSString *subscription = message.data.subscription; // Wild-card channel or channel on which PubNub client actually subscribed
    NSNumber *timetoken = message.data.timetoken; // Signal timetoken
    id msg = message.data.message; // Signal payload
    NSString *publisher = message.data.publisher; // Signal publisher
}

- (void)client:(PubNub *)pubnub didReceiveMessageAction:(PNMessageActionResult *)action {
    NSString *channel = action.data.channel; // Channel on which the message has been published
    NSString *subscription = action.data.subscription; // Wild-card channel or channel on which PubNub client actually subscribed
    NSString *event = action.data.event; // Can be: added or removed
    NSString *type = action.data.action.type; // Message reaction type
    NSString *value = action.data.action.value; // Message reaction value
    NSNumber *messageTimetoken = action.data.action.messageTimetoken; // Timetoken of the original message
    NSNumber *actionTimetoken = action.data.action.actionTimetoken; // Timetoken of the message reaction
    NSString *uuid = action.data.action.uuid; // UUID of user which added / removed message reaction
}

- (void)client:(PubNub *)pubnub didReceivePresenceEvent:(PNPresenceEventResult *)event {
    NSString *channel = message.data.channel; // Channel on which presence changes
    NSString *subscription = message.data.subscription; // Wild-card channel or channel on which PubNub client actually subscribed
    NSString *presenceEvent = event.data.presenceEvent; // Can be: join, leave, state-change, timeout or interval
    NSNumber *occupancy = event.data.presence.occupancy; // Number of users subscribed to the channel (not available for state-change event)
    NSNumber *timetoken = event.data.presence.timetoken; // Presence change timetoken
    NSString *uuid = event.data.presence.uuid; // UUID of user for which presence change happened

    // Only for 'state-change' event
    NSDictionary *state = event.data.presence.state; // User state (only for state-change event)

    // Only for 'interval' event
    NSArray<NSString *> *join = event.data.presence.join; // UUID of users which recently joined channel
    NSArray<NSString *> *leave = event.data.presence.leave; // UUID of users which recently leaved channel
    NSArray<NSString *> *timeout = event.data.presence.timeout; // UUID of users which recently timed out on channel
}

- (void)client:(PubNub *)pubnub didReceiveObjectEvent:(PNObjectEventResult *)event {
    NSString *channel = event.data.channel; // Channel to which the event belongs
    NSString *subscription = event.data.subscription; // Wild-card channel or channel on which PubNub client actually subscribed
    NSString *event = event.data.event; // Can be: set or delete
    NSString *type = event.data.type; // Entity type: channel, uuid or membership
    NSNumber *timestamp = event.data.timestamp; // Event timestamp

    PNChannelMetadata *channelMetadata = event.data.channelMetadata; // Updated channel metadata (only for channel entity type)
    PNUUIDMetadata *uuidMetadata = event.data.uuidMetadata; // Updated channel metadata (only for uuid entity type)
    PNMembership *membership = event.data.membership; // Updated channel metadata (only for membership entity type)
}

- (void)client:(PubNub *)pubnub didReceiveFileEvent:(PNFileEventResult *)event {
    NSString *channel = event.data.channel; // Channel to which file has been uploaded
    NSString *subscription = event.data.subscription; // Wild-card channel or channel on which PubNub client actually subscribed
    id message = event.data.message; // Message added for uploaded file
    NSString *publisher = event.data.publisher; // UUID of file uploader
    NSURL *fileDownloadURL = event.data.file.downloadURL; // URL which can be used to download file
    NSString *fileIdentifier = event.data.file.identifier; // Unique file identifier
    NSString *fileName = event.data.file.name; // Name with which file has been stored remotely
}

- (void)client:(PubNub *)pubnub didReceiveStatus:(PNStatus *)status {
    PNStatusCategory category = status.category; // One of PNStatusCategory fields to identify status of operation processing
    BOOL isError = status.isError; // Whether any kind of error happened.
    NSInteger statusCode = status.statusCode; // Related request processing status code
    BOOL isTLSEnabled = status.isTLSEnabled; // Whether secured connection enabled
    NSString *uuid = status.uuid; // UUID which configured for passed client
    NSString *authKey = status.authKey; // Auth token configured for passed client
    NSString *origin = status.origin; // Origin against which request has been sent
    NSURLRequest *clientRequest = status.clientRequest; // Request which has been used to send last request (may be nil)
    BOOL willAutomaticallyRetry = status.willAutomaticallyRetry; // Whether client will try to perform automatic retry

    // Following is available when operation == PNSubscribeOperation,
    // because status is PNSubscribeStatus instance in this case
    PNSubscribeStatus *subscribeStatus = (PNSubscribeStatus *)status;
    NSNumber *currentTimetoken = subscribeStatus.currentTimetoken; // Timetoken which has been used for current subscribe request
    NSNumber *lastTimeToken = subscribeStatus.lastTimeToken; // Timetoken which has been used for previous subscribe request
    NSArray<NSString *> *subscribedChannels = subscribeStatus.subscribedChannels; // List of channels on which client currently subscribed
    NSArray<NSString *> *subscribedChannelGroups = subscribeStatus.subscribedChannelGroups; // List of channel groups on which client currently subscribed
    NSString *channel = subscribeStatus.data.channel; // Name of channel to which status has been received
    NSString *subscription = subscribeStatus.data.subscription; // Wild-card channel or channel on which PubNub client actually subscribed
    NSNumber *timetoken = subscribeStatus.data.timetoken; // Timetoken at which event arrived
    NSDictionary *userMetadata = subscribeStatus.data.userMetadata; // Metadata / envelope which has been passed along with event

    // Following is available when isError == YES,
    // because status is PNErrorStatus instance in this case
    PNErrorStatus *errorStatus = (PNErrorStatus *)status;
    id associatedObject = errorStatus.associatedObject; // Data which may contain related information (not decrypted message for example)
    NSArray<NSString *> *erroredChannels = errorStatus.errorData.channels; // List of channels for which error reported (mostly because of Access Manager)
    NSArray<NSString *> *erroredChannelGroups = errorStatus.errorData.channelGroups; // List of channel groups for which error reported (mostly because of Access Manager)
    NSString *errorInformation = errorStatus.errorData.information; // Stringified information about error
    id errorData = errorStatus.errorData.data; // Additional error information from PubNub service
}
```

### Unity

```csharp
pubnub.SubscribeCallback += SubscribeCallbackHandler;

//Handler
void SubscribeCallbackHandler(object sender, EventArgs e) {
    SubscribeEventEventArgs mea = e as SubscribeEventEventArgs;

    if (mea.Status != null) {
        switch (mea.Status.Category) {
            case PNStatusCategory.PNUnexpectedDisconnectCategory:
            case PNStatusCategory.PNTimeoutCategory:
                pubnub.Publish()
                    .Channel("my_channel")
                    .Message("Hello from the PubNub Unity SDK")
                    .Async((result, status) => {
                        if(!status.Error){
                            Debug.Log(string.Format("DateTime {0}, In Publish Example, Timetoken: {1}", DateTime.UtcNow , result.Timetoken));
                        } else {
                            Debug.Log(status.Error);
                            Debug.Log(status.ErrorData.Info);
                        }
                    });
            break;
        }
    }
    if (mea.MessageResult != null) {
        Debug.Log("Channel" + mea.MessageResult.Channel);
        Debug.Log("Payload" + mea.MessageResult.Payload);
        Debug.Log("Publisher Id: " + mea.MessageResult.IssuingClientId);
    }
    if (mea.PresenceEventResult != null) {
        Debug.Log("SubscribeCallback in presence" + mea.PresenceEventResult.Channel + mea.PresenceEventResult.Occupancy + mea.PresenceEventResult.Event);
    }
    if (mea.SignalEventResult != null) {
        Debug.Log ("SubscribeCallback in SignalEventResult" + mea.SignalEventResult.Channel + mea.SignalEventResult.Payload);
    }
    if (mea.UserEventResult != null) {
        Debug.Log(mea.UserEventResult.Name);
        Debug.Log(mea.UserEventResult.Email);
        Debug.Log(mea.UserEventResult.ExternalID);
        Debug.Log(mea.UserEventResult.ProfileURL);
        Debug.Log(mea.UserEventResult.UserID);
        Debug.Log(mea.UserEventResult.ETag);
        Debug.Log(mea.UserEventResult.ObjectsEvent);
    }
    if (mea.SpaceEventResult != null) {
        Debug.Log(mea.SpaceEventResult.Name);
        Debug.Log(mea.SpaceEventResult.Description);
        Debug.Log(mea.SpaceEventResult.SpaceID);
        Debug.Log(mea.SpaceEventResult.ETag);
        Debug.Log(mea.SpaceEventResult.ObjectsEvent);
    }
    if (mea.MembershipEventResult != null) {
        Debug.Log(mea.MembershipEventResult.UserID);
        Debug.Log(mea.MembershipEventResult.Description);
        Debug.Log(mea.MembershipEventResult.SpaceID);
        Debug.Log(mea.MembershipEventResult.ObjectsEvent);
    }
    if (mea.MessageActionsEventResult != null) {
        Debug.Log(mea.MessageActionsEventResult.Channel);
        if(mea.MessageActionsEventResult.Data!=null){
            Debug.Log(mea.MessageActionsEventResult.Data.ActionTimetoken);
            Debug.Log(mea.MessageActionsEventResult.Data.ActionType);
            Debug.Log(mea.MessageActionsEventResult.Data.ActionValue);
            Debug.Log(mea.MessageActionsEventResult.Data.MessageTimetoken);
            Debug.Log(mea.MessageActionsEventResult.Data.UUID);
        }
        Debug.Log(mea.MessageActionsEventResult.MessageActionsEvent);
        Debug.Log(mea.MessageActionsEventResult.Subscription);
    }
}
```