---
source_url: https://www.pubnub.com/docs/chat/kotlin-chat-sdk/build/features/messages/moderation
title: Report offensive messages
updated_at: 2026-06-15T12:11:33.456Z
---

> 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


# Report offensive messages

Users can report offensive messages directly from your app. Reported messages publish to `PUBNUB_INTERNAL_MODERATION_{channel_id}` and emit [report events](https://www.pubnub.com/docs/chat/kotlin-chat-sdk/build/features/custom-events#chat-events).

Add custom logic using [emitted events](#listen-to-report-events) to handle reported messages (e.g., [delete them](https://www.pubnub.com/docs/chat/kotlin-chat-sdk/build/features/messages/delete)).

:::note Message Persistence
Enable Message Persistence in the [Admin Portal](https://admin.pubnub.com/).
:::

## Flag/Report messages

`report()` flags a message for admin review. Reports publish to `PUBNUB_INTERNAL_MODERATION_{channel_id}` (e.g., reporting on `support` sends to `PUBNUB_INTERNAL_MODERATION_support`).

### Method signature

This method takes the following parameters:

```kotlin
message.report(reason: String): PNFuture<PNPublishResult>
```

#### Input

| Parameter | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| reason | String | Yes |  | Reason for reporting/flagging a given message. |

#### Output

| Type | Description |
| --- | --- |
| `PNFuture<PNPublishResult>` | Returned object with a value of any type. |

### Sample code

Report the last message on the `support` channel as offensive.

```kotlin
// retrieve the "support" channel
chat.getChannel("support").async { channelResult ->
    channelResult.onSuccess { channel ->
        // get the last message from the channel’s history
        channel.getHistory(count = 1).async { historyResult ->
            historyResult.onSuccess { historyResponse ->
                val message = historyResponse.messages.firstOrNull()
                if (message != null) {
                    // report the last message as offensive
                    message.report("Offensive Content").async { reportResult ->
                        reportResult.onSuccess { pnPublishResult: PNPublishResult ->
                            println("Reported message successfully: ${pnPublishResult.timetoken}")
                        }.onFailure { throwable ->
                            println("Failed to report the message.")
                            throwable.printStackTrace()
                        }
                    }
                } else {
                    println("No messages found in the support channel.")
                }
            }.onFailure { throwable ->
                println("Failed to get history for the support channel.")
                throwable.printStackTrace()
            }
        }
    }.onFailure { throwable ->
        println("Failed to retrieve the support channel.")
        throwable.printStackTrace()
    }
}
```

## Get historical reported messages

`getMessageReportsHistory()` fetches reported message events for a channel with optional time and count filters.

### Method signature

This method takes the following parameters:

```kotlin
channel.getMessageReportsHistory(
  startTimetoken: Long?,
  endTimetoken: Long?,
  count: Int = 100,
): PNFuture<GetEventsHistoryResult>
```

#### Input

| Parameter | Description |
| --- | --- |
| `startTimetoken`Type: `Long`Default: n/a | The start timetoken for fetching the history of reported messages, which allows specifying the point in time where the history retrieval should begin. |
| `endTimetoken`Type: `Long`Default: n/a | The end time token for fetching the history of reported messages, which allows specifying the point in time where the history retrieval should end. |
| `count`Type: `Int`Default: `100` | The number of reported message events to fetch from the history. |

#### Output

| Type | Description |
| --- | --- |
| `PNFuture<GetEventsHistoryResult>` | Returned object containing these fields: `events` and `isMore`. |

### Sample code

Fetch historical messages reported on the `support` channel between the `1725100800000` (July 1, 2024, 00:00:00 UTC) and `1726780799000` (July 21, 2024, 23:59:59 UTC) timetokens.

```kotlin
// fefine timetokens for the message history period
val startTimetoken: Long = 1725100800000L // July 1, 2024, 00:00:00 UTC
val endTimetoken: Long = 1726780799000L // July 21, 2024, 23:59:59 UTC

// fetch historical messages reported on the `support` channel
chat.getChannel("support").async { channelResult ->
    channelResult.onSuccess { channel ->
        // fetch historical messages reported within the specified time frame
        channel.getMessageReportsHistory(
            startTimetoken = startTimetoken,
            endTimetoken = endTimetoken,
            count = 25
        ).async { historyResult ->
            historyResult.onSuccess { getEventsHistoryResult ->
                println("Fetched reported messages successfully.")
                getEventsHistoryResult.events.forEach { message ->
                    println("Message: ${message.entry}")
                }
            }.onFailure { throwable ->
                println("Failed to fetch reported messages.")
                throwable.printStackTrace()
            }
        }
    }.onFailure { throwable ->
        println("Failed to retrieve the support channel.")
        throwable.printStackTrace()
    }
}
```

## Listen to report events

`onMessageReported()` monitors report events on a channel. Use this for moderation dashboards to track reported messages in real time.

:::warning Deprecated method
`streamMessageReports()` is deprecated. Use `onMessageReported()` instead, which provides a typed `Report` object.
:::

:::tip Events documentation
To read more about the events of type `report`, refer to the [Chat events](https://www.pubnub.com/docs/chat/kotlin-chat-sdk/build/features/custom-events#events-for-reported-messages) documentation.
:::

### Method signature

This method has the following parameters:

```kotlin
channel.onMessageReported(callback: (report: Report) -> Unit): AutoCloseable
```

#### Input

| Parameter | Description |
| --- | --- |
| `callback` *Type: `(report: Report) -> Unit`Default: n/a | Function invoked with a `Report` event whenever a message is reported on this channel. |

The `Report` object contains:

| Property | Description |
| --- | --- |
| `reason`Type: `String` | The reason for reporting the message. |
| `text`Type: `String?` | The text of the reported message, if available. |
| `messageTimetoken`Type: `Long?` | The timetoken of the reported message. |
| `reportedMessageChannelId`Type: `String?` | The channel ID where the reported message was sent. |
| `reportedUserId`Type: `String?` | The user ID of the user who sent the reported message. |
| `autoModerationId`Type: `String?` | The auto-moderation ID associated with the report. |

#### Output

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

### Sample code

Print a notification for an offensive message reported on the `support` channel.

```kotlin
val channel: Channel
// ...

val subscription = channel.onMessageReported { report ->
    println("Message reported: reason=${report.reason}, by user=${report.reportedUserId}")
}

// stop listening:
// subscription.close()
```