---
source_url: https://www.pubnub.com/docs/chat/kotlin-chat-sdk/build/features/users/updates
title: Manage user updates
updated_at: 2026-06-15T12:11:37.823Z
---

> 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


# Manage user updates

Update user details and receive real-time update events.

:::note Requires App Context
Enable [App Context](https://youtu.be/9UEoSlngpYI) in the [Admin Portal](https://admin.pubnub.com/) to store user data.
:::

## Update user details

Edit user metadata with `update()` or `updateUser()`.

* `update()` - call on a `User` object (no ID needed)
* `updateUser()` - call on a `Chat` object (requires user ID)

:::warning Update and overwrite vs synchronize
The `User` interface offers two methods to update metadata:
* Overwrite: Directly set and replace user fields like name, email, and status with new values on the server.
* Synchronize: Use the updateAction function for conditional updates in sync with the latest server data. This method adapts to server changes and may repeat until successful.
Choose based on whether you need to overwrite data or synchronize with server updates.
:::

### Method signature

These methods take the following parameters:

* update() and overwrite 1user.update(2 name: String?,3 externalId: String?,4 profileUrl: String?,5 email: String?,6 custom: CustomObject?,7 status: String?,8 type: String?,9): PNFuture<User>
* update() and synchronize 1user.update(2 updateAction: UpdatableValues.(3 user: User4 ) -> Unit5): PNFuture<User>
* updateUser() 1chat.updateUser(2 id: String,3 name: String?,4 externalId: String?,5 profileUrl: String?,6 email: String?,7 custom: CustomObject?,8 status: String?,9 type: String?,10): PNFuture<User>

#### Input

| Parameter | Required in update() (overwrite) | Required in update() (synchronize) | Required in updateUser() | Description |
| --- | --- | --- | --- | --- |
| id | String | Optional |  | No | No | Yes | [Unique user identifier](https://www.pubnub.com/docs/general/setup/users-and-devices#user-id-usage). |
| name | String | Optional |  | No | No | No | Display name for the user (must not be empty or consist only of whitespace characters). |
| externalId | String | Optional |  | No | No | No | User's identifier in an external system. You can use it to match `id` with a similar identifier from an external database. |
| profileUrl | String | Optional |  | No | No | No | URL of the user's profile picture. |
| email | String | Optional |  | No | No | No | User's email address. |
| custom | CustomObject | Optional |  | No | No | No | JSON providing custom data about the user. Values must be scalar only; arrays or objects are not supported. [Filtering App Context data](https://www.pubnub.com/docs/general/metadata/filtering) through the `custom` property is not recommended in SDKs. |
| status | String | Optional |  | No | No | No | Tag that lets you categorize your app users by their current state. The tag choice is entirely up to you and depends on your use case. For example, you can use `status` to mark users in your chat app as `invited`, `active`, or `archived`. |
| type | String | Optional |  | No | No | No | Tag that lets you categorize your app users by their functional roles. The tag choice is entirely up to you and depends on your use case. For example, you can use `type` to group users by their roles in your app, such as `moderator`, `player`, or `support-agent`. |
| updateAction | Lambda | Optional |  | No | Yes | No | A lambda function with a receiver of type `UpdatableValues`. If new values are fetched from the server, the function may run more than once. This function takes a `User` object as its parameter. Inside this function, you can compute new values for the user's fields and assign them to the properties of the `UpdatableValues` receiver: name, externalId, profileUrl, email, custom, status, type |

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

#### Output

| Type | Description |
| --- | --- |
| `PNFuture<User>` | Returned object containing the updated user metadata. |

### Sample code

Change the link to the user's `support_agent_15` LinkedIn profile to `https://www.linkedin.com/mkelly_vp2`.

* update() and overwrite 1// reference the "chat" object and invoke the "getUser()" method2chat.getUser("support_agent_15").async { result ->3 result.onSuccess { user ->4 // handle success: update the "linkedInUrl" custom field5 user.update(6 custom = mapOf(7 "linkedInUrl" to "https://www.linkedin.com/mkelly_vp2"8 )9 ).async { updateResult ->10 updateResult.onSuccess {11 // handle success12 }.onFailure {13 // handle failure14 }15 }16 }.onFailure {17 // handle failure18 }19}
* update() and synchronize 1// reference the "chat" object and invoke the "getUser()" method2chat.getUser("support_agent_15").async { result ->3 result.onSuccess { user ->4 // handle success: update using an updateAction5 user.update { 6 this.custom = buildMap {7 user.custom?.let { putAll(it) }8 put("linkedInUrl", "https://www.linkedin.com/mkelly_vp2")9 }10 11 }.async { updateResult ->12 updateResult.onSuccess {13 // handle success14 }.onFailure {15 // handle failure16 }17 }18 }.onFailure {19 // handle failure20 }21}
* updateUser() 1// reference the "chat" object and invoke the "updateUser()" method2chat.updateUser(3 id = "support_agent_15",4 custom = mapOf(5 "linkedInUrl" to "https://www.linkedin.com/mkelly_vp2"6 )7).async { result ->8 result.onSuccess {9 // handle success10 }.onFailure {11 // handle failure12 }13}

## Get user updates

Receive real-time notifications when user metadata changes or a user is deleted:

* `onUpdated()` - fires when user metadata is modified
* `onDeleted()` - fires when the user is deleted

### Method signature

These methods take the following parameters:

* onUpdated() 1user.onUpdated(callback: (user: User) -> Unit): AutoCloseable
* onDeleted() 1user.onDeleted(callback: () -> Unit): AutoCloseable

#### Input

| Parameter | Description |
| --- | --- |
| `callback` (in `onUpdated`) *Type: `(user: User) -> Unit`Default: n/a | Function that receives the updated `User` object when metadata changes. |
| `callback` (in `onDeleted`) *Type: `() -> Unit`Default: n/a | Function invoked when the user is deleted. |

#### Output

| Type | Description |
| --- | --- |
| `AutoCloseable` | Interface that lets you stop receiving user-related updates by invoking the `close()` method. |

### Sample code

Get updates when `support_agent_15` metadata changes.

```kotlin
val user: User
// ...

val subscription = user.onUpdated { updatedUser ->
    println("Updated user: $updatedUser")
}

// stop receiving updates:
// subscription.close()
```

Get notified when a user is deleted.

```kotlin
val user: User
// ...

val subscription = user.onDeleted {
    println("User was deleted")
}

// stop receiving updates:
// subscription.close()
```

## Get user updates (deprecated)

:::warning Deprecated methods
`streamUpdates()` is deprecated. Use [onUpdated()](#get-user-updates) and [onDeleted()](#get-user-updates) instead. `streamUpdatesOn()` remains supported.
:::

Receive updates when [User objects](https://www.pubnub.com/docs/chat/kotlin-chat-sdk/learn/chat-entities/user) are edited or removed:

* `streamUpdates()` - monitors a single user
* `streamUpdatesOn()` - monitors multiple users

:::note Callback behavior
* `streamUpdates()`: returns updated `User` object (or `null` if deleted)
* `streamUpdatesOn()`: returns complete list of monitored users on any change
:::

### Method signature

These methods take the following parameters:

* streamUpdates() 1user.streamUpdates(callback: (user: User?) -> Unit): AutoCloseable
* streamUpdatesOn() 1class User {2 companion object {3 fun streamUpdatesOn(4 users: Collection<User>,5 callback: (users: Collection<User>) -> Unit6 ): AutoCloseable7 }8}

#### Input

| Parameter | Required in `streamUpdates()` | Required in `streamUpdatesOn()` | Description |
| --- | --- | --- | --- |
| `users`Type: `Collection<User>`Default: n/a | No | Yes | A collection of [User objects](https://www.pubnub.com/docs/chat/kotlin-chat-sdk/learn/chat-entities/channel) for which you want to get updates. |
| `callback`Type: `(user: User?) -> Unit`Default: n/a | Yes | No | Function that takes a single `User` object. It defines the custom behavior to be executed when detecting user changes. |
| `callback`Type: `(users: Collection<User>) -> Unit`Default: n/a | No | Yes | Function that takes a set of `User` objects. It defines the custom behavior to be executed when detecting user changes. |

#### Output

| Type | Description |
| --- | --- |
| `AutoCloseable` | Interface that lets you stop receiving channel-related updates (`objects` events) by invoking the `close()` method. |

### Sample code

Get updates on `support_agent_15`.

* streamUpdates() 1// fetch a user by their ID2chat.getUser("support_agent_15").async { result ->3 result.onSuccess { user ->4 user?.streamUpdates { updatedUser ->5 // The callback receives the entire updated User object each time a change occurs.6 if (updatedUser != null) {7 println("Updated user: $updatedUser")8 } else {9 println("User was deleted")10 }11 }12 }13}

Get updates on `support_agent_15` and `support-manager`.

* streamUpdatesOn() 1// fetch users by their IDs2val supportAgentUser = chat.getUser("support_agent_15")3val supportManagerUser = chat.getUser("support-manager")4 5// collect the users you want to stream updates for6val usersToMonitor = listOf(supportAgentUser, supportManagerUser)7 8// stream updates for the specified users9val autoCloseable = User.streamUpdatesOn(users = usersToMonitor) { updatedUsers ->10 // The callback receives the complete list of all users you're monitoring11 // each time any change occurs.12 println("Updated users: $updatedUsers")13}

### Other examples

Stop listening to updates on `support_agent_15`.

* streamUpdates() 1class MyActivity : AppCompatActivity() {2 private lateinit var autoCloseable: AutoCloseable3 4 override fun onCreate(savedInstanceState: Bundle?) {5 super.onCreate(savedInstanceState)6 // fetch a user by their ID7 val supportAgentUser = chat.getUser("support_agent_15")8 9 // start streaming updates for the specified user10 autoCloseable = supportAgentUser.streamUpdates { updatedUser ->11 // The callback receives the entire updated User object each time a change occurs.12 if (updatedUser != null) {13 println("Updated user: $updatedUser")14 } else {15 println("User was deleted")16 }17 }18 }19 20 override fun onDestroy() {21 super.onDestroy()22 // stop listening to updates when the activity is destroyed23 autoCloseable.close()24 }25}

Stop listening to updates on `support_agent_15` and `support-manager`.

* streamUpdatesOn() 1class MyActivity : AppCompatActivity() {2 private lateinit var autoCloseable: AutoCloseable3 4 override fun onCreate(savedInstanceState: Bundle?) {5 super.onCreate(savedInstanceState)6 // fetch users by their IDs7 val supportAgentUser = chat.getUser("support_agent_15")8 val supportManagerUser = chat.getUser("support_manager")9 10 val users = listOf(supportAgentUser, supportManagerUser)11 12 // start streaming updates for the specified users13 autoCloseable = User.streamUpdatesOn(users = users) { updatedUsers ->14 // The callback receives the complete list of all users you're monitoring15 // each time any change occurs.16 updatedUsers.forEach { updatedUser ->17 if (updatedUser != null) {18 println("Updated user: $updatedUser")19 } else {20 println("User was deleted")21 }22 }23 }24 }25 26 override fun onDestroy() {27 super.onDestroy()28 // stop listening to updates when the activity is destroyed29 autoCloseable.close()30 }31}