# Moderation Tools

Moderation tools are features you can use to moderate a channel by detecting unwanted content and restricting the users that create the unwanted content.

## Flagging a Message or a User

Any user is allowed to flag a message or a user. Flagging does not perform any particular action on the chat. The API will only trigger the related webhook event and make the message appear on your _Dashboard Chat Moderation_ view.

```kotlin
client.flagMessage("message-id").enqueue { result ->
    if (result.isSuccess) {
        // Message was flagged
        val flag: Flag = result.data()
    } else {
        // Handle result.error()
    }
}

client.flagUser("user-id").enqueue { result ->
    if (result.isSuccess) {
        // User was flagged
        val flag: Flag = result.data()
    } else {
        // Handle result.error()
    }
}
```

## Muting a User

Any user is allowed to mute another user. Mutes are stored at user level and returned with the rest of the user information when `connectUser` is called. A user will be muted until the user is `unmuted` or the mute is expired.

```kotlin
client.muteUser("user-id").enqueue { result ->
    if (result.isSuccess) {
        // User was muted
        val mute: Mute = result.data()
    } else {
        // Handle result.error()
    }
}

// Mute user for 60 minutes
client.muteUser("user-id", timeout = 60)
    .enqueue { result: Result<Unit> ->
        if (result.isSuccess) {
            // User was muted
            val mute: Mute = result.data()
        } else {
            // Handle result.error()
        }
    }

client.unmuteUser("user-id").enqueue { result ->
    if (result.isSuccess) {
        // User was unmuted
    } else {
        // Handle result.error()
    }
}
```

After muting a user messages will still be delivered via web-socket. Implementing business logic such as hiding messages from muted users or display them differently is left to the developer to implement.

<admonition type="note">

Messages from muted users are not delivered via push (APN/Firebase)

</admonition>

## Banning Users

Users can be banned from an app entirely or just from a single channel. When a user is banned, they will not be allowed to post messages until the ban is removed or expired but they will be able to connect to Chat and to channels as before.

<admonition type="note">

In most cases, only admins or moderators are allowed to ban other users from a channel.

</admonition>

| Name    | Type   | Description                                                    | Default  | Optional |
| :------ | :----- | :------------------------------------------------------------- | :------- | :------- |
| timeout | Int    | The timeout in minutes until the ban is automatically expired. | no limit | &check;  |
| reason  | String | The reason that the ban was created.                           |          | &check;  |

<admonition type="note">

Banning a user from all channels can only be done using server-side auth.

</admonition>

```kotlin
// Ban user for 60 minutes from a channel
channelClient.banUser(targetId = "user-id", reason = "Bad words", timeout = 60).enqueue { result ->
    if (result.isSuccess) {
        // User was banned
    } else {
        // Handle result.error()
    }
}

channelClient.unBanUser(targetId = "user-id").enqueue { result ->
    if (result.isSuccess) {
        // User was unbanned
    } else {
        // Handle result.error()
    }
}
```

### Shadow Banning a User

Users can be shadow banned from an app entirely or just from a single channel. When a user is shadow banned, they will still be allowed to post messages, but any message sent during, will have `shadowed: true` field.

<admonition type="note">

It's up to the client-side implementation to handle `shadowed` messages appropriately.

</admonition>

```kotlin
// Shadow ban user for 60 minutes from a channel
channelClient.shadowBanUser(targetId = "user-id", reason = "Bad words", timeout = 60).enqueue { result ->
     if (result.isSuccess) {
         // User was shadow banned
     } else {
         // Handle result.error()
     }
}

channelClient.removeShadowBan("user-id").enqueue { result ->
    if (result.isSuccess) {
        // Shadow ban was removed
    } else {
        // Handle result.error()
    }
}
```

<admonition type="note">

Administrators can view shadow banned user status in `queryChannels()`, `queryMembers()` and `queryUsers()`.

</admonition>

### Retrieving Banned Users

Banned users can be retrieved in different ways:

1. Using the dedicated query bans endpoint
2. User Search: you can add the `banned:true` condition to your search. Please note that this will only return users that were banned at the app-level and not the ones that were banned only in channels.

```kotlin
// retrieve the list of banned users
client.queryUsers(
    QueryUsersRequest(
        filter = Filters.eq("banned", true),
        offset = 0,
        limit = 10,
    )
).enqueue { result ->
    if (result.isSuccess) {
       val users: List<User> = result.data()
   } else {
       // Handle result.error()
   }
}

// Query for banned members from one channel
client.queryBannedUsers(filter = Filters.eq("channel_cid", "ChannelType:ChannelId")).enqueue { result ->
    if (result.isSuccess) {
        val bannedUsers: List<BannedUser> = result.data()
    } else {
        // Handle result.error()
    }
}
```

### Retrieving Banned Users From Specific Channels

You can list banned users from a specific channel using the query banned users endpoint which allows you to get paginated results:

```kotlin
// Get the bans for channel livestream:123 in descending order
channelClient.queryBannedUsers(
    sort = QuerySort.desc(BannedUsersSort::createdAt),
).enqueue { result ->
    if (result.isSuccess) {
        val bannedUsers: List<BannedUser> = result.data()
    } else {
        // Handle result.error()
   }
}

// Get the page of bans which where created before or equal date for the same channel
client.queryBannedUsers(
    filter = Filters.eq("channel_cid", "livestream:123"),
    sort = QuerySort.desc(BannedUsersSort::createdAt),
    createdAtBeforeOrEqual = Date(),
).enqueue { result ->
    if (result.isSuccess) {
        val bannedUsers: List<BannedUser> = result.data()
    } else {
        // Handle result.error()
    }
}
```

You can also use `in` filter to query banned users from multiple channels:

```kotlin
client.queryBannedUsers(
    filter = Filters.`in`("channel_cid", listOf("livestream:123", "livestream:456")),
    sort = QuerySort.desc(BannedUsersSort::createdAt),
    createdAtBeforeOrEqual = Date(),
).enqueue { result ->
    if (result.isSuccess) {
        val bannedUsers: List<BannedUser> = result.data()
    } else {
        // Handle result.error()
    }
}
```


---

This page was last updated at 2026-03-05T19:01:42.320Z.

For the most recent version of this documentation, visit [https://getstream.io/chat/docs/sdk/android/v5/client/moderation-tools/](https://getstream.io/chat/docs/sdk/android/v5/client/moderation-tools/).