---
source_url: https://www.pubnub.com/docs/chat/kotlin-chat-sdk/build/features/users/moderation-user
title: Moderate misbehaving users
updated_at: 2026-06-04T11:09:26.966Z
---

> 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


# Moderate misbehaving users

Regular chat users (without admin `secretKey`) can hide messages from undesirable users using a mute list.

The mute list is soft-limited to 200 users and persists only for the session duration by default. Enable `syncMutedUsers` during initialization to persist the list (32 KiB server limit applies).

:::warning Mute list user limit
A persisted mute list can hold roughly up to 200 users (32 KiB of data). If the size of the list exceeds that limit, the Chat SDK throws an HTTP 413 error and the list won't be persisted. The users will still be muted for the duration of the session.
:::

All events and messages originating from a muted user are still received by the client, but are ignored. The mute list affects the following means of message delivery:

* [channel.onMessageReceived()](https://www.pubnub.com/docs/chat/kotlin-chat-sdk/build/features/channels/watch)
* [channel.join()](https://www.pubnub.com/docs/chat/kotlin-chat-sdk/build/features/channels/join)
* [channel.getHistory()](https://www.pubnub.com/docs/chat/kotlin-chat-sdk/build/features/messages/history)
* [channel.onCustomEvent()](https://www.pubnub.com/docs/chat/kotlin-chat-sdk/build/features/custom-events#receive-current-events), [user.onMentioned()](https://www.pubnub.com/docs/chat/kotlin-chat-sdk/build/features/users/mentions#show-notifications-for-mentions), [user.onInvited()](https://www.pubnub.com/docs/chat/kotlin-chat-sdk/build/features/channels/invite#listen-to-invite-events)
* [chat.getEventsHistory()](https://www.pubnub.com/docs/chat/kotlin-chat-sdk/build/features/custom-events#get-historical-events)

:::note Requires App Context
To mute users, you must [enable App Context](https://youtu.be/9UEoSlngpYI) for your app's keyset in the [Admin Portal](https://admin.pubnub.com/).
:::

## Mute users as a regular chat user

As a regular chat user, you can mute a specific user on all channels.

### Method signature

```kotlin
Chat.MutedUsersManager.muteUser(userId: String): PNFuture<Unit>
```

#### Input

| Parameter | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| userId | string | Yes |  | [User ID](https://www.pubnub.com/docs/general/setup/users-and-devices) of the user you want to mute. |

#### Output

This method returns a `PNFuture<Unit>` that succeeds when the data has been synced with the server. If [syncMutedUsers](https://www.pubnub.com/docs/chat/kotlin-chat-sdk/build/configuration#sync-muted-users) is not enabled, the `PNFuture<Unit>` always succeeds.

#### Errors

If the size of the mute list exceeds 32 KiB (roughly 200 users), you'll get the `HTTP 413 (Request Entity Too Large)` error.

### Sample code

```kotlin
import com.pubnub.chat.Chat
import com.pubnub.chat.config.ChatConfiguration

val chat = Chat.init(
    ChatConfiguration(),
    PNConfiguration.builder(UserId("myUniqueUserId"), subscribeKey = "demo").apply {
        publishKey = "demo"
    }.build()
)

val userToMute = "user_1905"

chat.mutedUsersManager.muteUser(userToMute).await()
```

## Unmute users as a regular chat user

You can unmute a specific user on all channels. This removes the user from the mute list, allowing the client to see all messages and events originating from the user again.

### Method signature

```kotlin
Chat.MutedUsersManager.unmuteUser(userId: String): PNFuture<Unit>
```

#### Input

| Parameter | Description |
| --- | --- |
| `userId` *Type: `string` | [User ID](https://www.pubnub.com/docs/general/setup/users-and-devices) of the user you want to unmute. |

#### Output

This method returns a `PNFuture<Unit>` that succeeds when the data has been synced with the server. If [syncMutedUsers](https://www.pubnub.com/docs/chat/kotlin-chat-sdk/build/configuration#sync-muted-users) is not enabled, the `PNFuture<Unit>` always succeeds.

### Sample code

```kotlin
import com.pubnub.chat.Chat
import com.pubnub.chat.config.ChatConfiguration

val chat = Chat.init(
    ChatConfiguration(),
    PNConfiguration.builder(UserId("myUniqueUserId"), subscribeKey = "demo").apply {
        publishKey = "demo"
    }.build()
)

val userToUnmute = "user_1905"

chat.mutedUsersManager.unmuteUser(userToUnmute).await()
```

## Check muted users

You can check which users have been muted by inspecting the items in the mute list.

### Method signature

```kotlin
Chat.MutedUsersManager.mutedUsers
```

#### Output

This property returns a `Set<String>` where each `String` is a user ID of a muted user.

### Sample code

```kotlin
import com.pubnub.chat.Chat
import com.pubnub.chat.config.ChatConfiguration

val chat = Chat.init(
    ChatConfiguration(),
    PNConfiguration.builder(UserId("myUniqueUserId"), subscribeKey = "demo").apply {
        publishKey = "demo"
    }.build()
)

val userToMute = "user_1905"

// Mute the user
chat.mutedUsersManager.muteUser(userToMute).await()

// Once the user is muted, get the list of muted users
val mutedUsers = mutedUsersManager.mutedUsers

println("Muted users: $mutedUsers")
```

## Persist the mute list

By default, the mute list is only persisted for the duration of the user session. You can save and retrieve the mute list during client initialization, effectively persisting the mute list by setting the `syncMutedUsers` parameter to `true` during [client initialization](https://www.pubnub.com/docs/chat/kotlin-chat-sdk/build/configuration#initialize-pubnub).

:::warning Mute list and Access Manager
If you use Access Manager for [user moderation](https://www.pubnub.com/docs/chat/kotlin-chat-sdk/build/features/users/moderation) within your chat app and `syncMutedUsers` is enabled, you must grant the Chat SDK user the following permissions:
* `read` permission to the `PN_PRV.$currentUserId.mute1` channel.
* `update`, `delete`, and `get` permissions for the `PN_PRV.$currentUserId.mute1` user.
Make sure to change `$currentUserId` to the user ID of the chat user that will use the mute list functionality.
:::

## Check restrictions

You can check if the chat administrator imposed any `mute` or `ban` restrictions for the following scenarios. Refer to the linked sections for more information.

* [For a single user on a single channel](https://www.pubnub.com/docs/chat/kotlin-chat-sdk/build/features/users/moderation#one-user-on-one-channel)
* [For a single user on all channels](https://www.pubnub.com/docs/chat/kotlin-chat-sdk/build/features/users/moderation#one-user-on-all-channels)
* [For all users on a single channel](https://www.pubnub.com/docs/chat/kotlin-chat-sdk/build/features/users/moderation#all-users-on-one-channel)

#### Sample code

##### Single user on a single channel

```kotlin
// reference the "chat" object and invoke the "getUser()" method
chat.getUser("support_agent_15").async { userResult ->
    userResult.onSuccess { user ->
        if (user != null) {
            // get the "support" channel
            chat.getChannel("support").async { channelResult ->
                channelResult.onSuccess { channel ->
                    if (channel != null) {
                        // get the channel restrictions for the user
                        user.getChannelRestrictions(channel).async { restrictionResult ->
                            restrictionResult.onSuccess { restriction ->
                                // handle the restriction object
                            }.onFailure {
                                // handle failure
                            }
                        }
                    } else {
                        // handle null channel
                    }
                }.onFailure {
                    // handle failure to get the channel
                }
            }
        } else {
            // handle null user
        }
    }.onFailure {
        // handle failure to get the user
    }
}
```

##### All users on a single channel

```kotlin
// reference the "chat" object and invoke the "getChannel()" method
chat.getChannel("support").async { result ->
    result.onSuccess { channel ->
        if (channel != null) {
            // fetch the user restrictions for the channel
            channel.getUsersRestrictions().async { restrictionsResult ->
                restrictionsResult.onSuccess { getRestrictionsResponse ->
                    // process the returned restrictions
                    for (restriction in getRestrictionsResponse.restrictions) {
                        if (restriction.mute || restriction.ban) {
                            // handle the restriction object (either muted or banned)
                            println("User ${restriction.userId} is restricted in channel ${channel.id}: mute=${restriction.mute}, ban=${restriction.ban}")
                        }
                    }
                }.onFailure {
                    // handle the failure of getting restrictions
                    println("Failed to get user restrictions: ${it.message}")
                }
            }
        } else {
            // handle null channel
            println("Channel is not found.")
        }
    }.onFailure {
        // handle failure
    }
}
```

##### Single user on all channels

```kotlin
// reference the "chat" object and invoke the "getUser()" method
chat.getUser("support_agent_15").async { result ->
    result.onSuccess { user ->
        if (user != null) {
            // fetch the channel restrictions for the user
            user.getChannelsRestrictions().async { restrictionsResult ->
                restrictionsResult.onSuccess { getRestrictionsResponse ->
                    // process the returned restrictions
                    for (restriction in getRestrictionsResponse.restrictions) {
                        if (restriction.mute || restriction.ban) {
                            // handle the restriction object (either muted or banned)
                            println("User is restricted on channel ${restriction.channelId}: mute=${restriction.mute}, ban=${restriction.ban}")
                        }
                    }
                }.onFailure {
                    // handle the failure of getting restrictions
                    println("Failed to get channel restrictions: ${it.message}")
                }
            }
        } else {
            // handle null user
            println("User is not found.")
        }
    }.onFailure {
        // handle failure
    }
}
```

## Secure moderation

Client-side restrictions can be bypassed without [server-side logic](https://www.pubnub.com/docs/chat/kotlin-chat-sdk/build/features/users/moderation#server-side-restrictions) using Access Manager. Add [client-side error handling](https://www.pubnub.com/docs/chat/kotlin-chat-sdk/build/features/users/moderation#client-side-restrictions) to inform users of their restrictions.

### Client-side restrictions

Once you enable and define [server-side permissions](https://www.pubnub.com/docs/chat/kotlin-chat-sdk/build/features/users/moderation#server-side-restrictions) with Access Manager, you can be sure that your muting and banning restrictions are always enforced.

[Read moderation restrictions](https://www.pubnub.com/docs/chat/kotlin-chat-sdk/build/features/users/moderation#check-restrictions) on the frontend to notify users of restrictions before they attempt prohibited actions.

Listen to moderation events to react to permission changes in real-time:

1. Listen for moderation events. Set up a listener using user.onRestrictionChanged() to react to restriction changes ("banned," "muted," or "lifted") in real-time. 1val subscription = user.onRestrictionChanged { restriction ->2 handleModerationEvent(restriction)3}4 5// Remove the moderation event listener on cleanup6// subscription.close()
2. Act on moderation events. Update permissions in response to moderation events and generate new tokens if necessary. 1fun handleModerationEvent(restriction: Restriction) {2 val channelId = restriction.channelId3 val reason = restriction.reason4 5 when {6 restriction.ban -> {7 println("User ${chat.currentUser.id} is banned on channel $channelId. Reason: ${reason ?: "N/A"}")8 // Revoke access rights specific to banning logic here9 }10 restriction.mute -> {11 println("User ${chat.currentUser.id} is muted on channel $channelId. Reason: ${reason ?: "N/A"}")12 // Revoke access rights specific to muting logic here13 }14 else -> {15 println("User ${chat.currentUser.id} restrictions lifted on channel $channelId")16 // Grant access rights back17 }18 }19 20 // Call your backend method to issue a new token after any moderation event21}
3. Remove the event listener. 1// remember to call close when you're done2subscription.close()