# Moderation

Stream Feeds has support for moderation, allowing you to manage user interactions, content moderation, and platform safety. It's accessible through the `client.moderation` property.

## Overview

```dart label="Dart"
final client = StreamFeedsClient(apiKey: apiKey, user: user, tokenProvider: token);
final moderation = client.moderation;
```

## User Moderation

### Ban Users

Ban a user from the platform with various options including timeout, shadow bans, and IP bans.

```dart label="Dart"
const banRequest = BanRequest(
  targetUserId: 'user-123',
  reason: 'Violation of community guidelines',
  timeout: 3600, // 1 hour in seconds
  shadow: false,
  ipBan: false,
);

final response = await client.moderation.ban(banRequest: banRequest);
print('User banned for: ${response.getOrThrow().duration}');
```

**Parameters:**

- `targetUserId`: The ID of the user to ban
- `reason`: Optional reason for the ban
- `timeout`: Optional timeout in seconds (null for permanent ban)
- `shadow`: Whether to perform a shadow ban (user doesn't know they're banned)
- `ipBan`: Whether to ban the user's IP address
- `bannedBy`: Optional user who performed the ban
- `deleteMessages`: Whether to delete user's messages

To reverse a ban, see [Unban User](https://getstream.io/moderation/docs/node/content-moderation/flag-mute-ban/#unban-user) in the Moderation docs. The user object returned by `queryUsers` only exposes the ban _state_ (`banned`, `ban_expires`) — it does not include `banned_by` or the ban `reason`. To retrieve that metadata, use [Query Banned Users](https://getstream.io/moderation/docs/node/content-moderation/flag-mute-ban/#query-banned-users).

### Mute Users

Mute is **not supported in Feeds**. Muting a user does not hide their activities from feed reads.

To hide another user's activities in Feeds, use [Block Users](#block-users) instead.

### Block Users

Block a user. Blocking is **bidirectional**:

- Neither user sees the other's activities in feeds
- Neither can follow the other

This replaces the v2 `discard_actors` option. Instead of sending blocked user IDs on every feed read, call `blockUsers` once — Stream filters those activities automatically.

```dart label="Dart"
const blockRequest = BlockUsersRequest(blockedUserId: 'user-123');
final response = await client.moderation.blockUsers(blockUsersRequest: blockRequest);
```

### Unblock Users

Unblock a previously blocked user.

```dart label="Dart"
const unblockRequest = UnblockUsersRequest(blockedUserId: 'user-123');
final response = await client.moderation.unblockUsers(unblockUsersRequest: unblockRequest);
```

### Get Blocked Users

Retrieve a list of users you have blocked.

```dart label="Dart"
final blockedUsers = await client.moderation.getBlockedUsers();
for (final user in blockedUsers.getOrThrow().blocks) {
  print('Blocked user: ${user.blockedUserId}');
}
```

## Content Moderation

### Flag Content

Flag inappropriate content for moderation review.

```dart label="Dart"
const flagRequest = FlagRequest(
  entityId: 'activity-123',
  entityType: 'activity',
  reason: 'Inappropriate content',
  entityCreatorId: 'user-456',
);

final response = await client.moderation.flag(flagRequest: flagRequest);
```

**Parameters:**

- `entityId`: The ID of the content to flag
- `entityType`: The type of content (e.g., "stream:feeds:v3:activity", "stream:feeds:v3:comment")
- `reason`: Optional reason for flagging
- `entityCreatorId`: Optional ID of the content creator
- `custom`: Optional custom data for the flag

### Submit Moderation Actions

Submit moderation actions for flagged content.

```dart label="Dart"
const actionRequest = SubmitActionRequest(
  // Action details for moderation
);

final response = await client.moderation.submitAction(submitActionRequest: actionRequest);
```

## Review Queue

### Query Review Queue

Retrieve items in the moderation review queue.

```dart label="Dart"
const queryRequest = QueryReviewQueueRequest(
    // Query parameters for filtering and pagination
    );

final reviewQueue = await client.moderation
    .queryReviewQueue(queryReviewQueueRequest: queryRequest);
```

## Configuration Management

### Upsert Moderation Configuration

Create or update moderation configuration settings.

```dart label="Dart"
const upsertRequest = UpsertConfigRequest(
  // Configuration details for moderation
);

final response = await client.moderation.upsertConfig(upsertRequest);
```

### Get Moderation Configuration

Retrieve a specific moderation configuration.

```dart label="Dart"
final config = await client.moderation.getConfig(key: 'feeds');
```

**Parameters:**

- `key`: The configuration key to retrieve
- `team`: Optional team identifier

### Delete Moderation Configuration

Remove a moderation configuration.

```dart label="Dart"
final response = await client.moderation.deleteConfig(key: 'feeds');
```

### Query Moderation Configurations

Search and filter moderation configurations.

```dart label="Dart"
const queryRequest = ModerationConfigsQuery(
    // Query parameters for filtering and pagination
    );

final configs = await client.moderation
    .queryModerationConfigs(queryModerationConfigsRequest: queryRequest);
```

#### Moderation Config Queryable Built-In Fields

| name         | type                                              | description                                       | supported operations                                                                  | example                                               |
| ------------ | ------------------------------------------------- | ------------------------------------------------- | ------------------------------------------------------------------------------------- | ----------------------------------------------------- |
| `key`        | string or list of strings                         | The configuration key identifier                  | `$eq`, `$ne`, `$gt`, `$gte`, `$lt`, `$lte`, `$in`, `$nin`, `$exists`, `$autocomplete` | `{ key: { $autocomplete: 'spam' } }`                  |
| `team`       | string or list of strings                         | The team identifier for multi-tenant applications | `$eq`, `$ne`, `$gt`, `$gte`, `$lt`, `$lte`, `$in`, `$nin`, `$exists`                  | `{ team: { $eq: 'team_123' } }`                       |
| `created_at` | string, must be formatted as an RFC3339 timestamp | The time the configuration was created            | `$eq`, `$gt`, `$gte`, `$lt`, `$lte`                                                   | `{ created_at: { $gte: '2023-12-04T09:30:20.45Z' } }` |
| `updated_at` | string, must be formatted as an RFC3339 timestamp | The time the configuration was last updated       | `$eq`, `$gt`, `$gte`, `$lt`, `$lte`                                                   | `{ updated_at: { $gte: '2023-12-04T09:30:20.45Z' } }` |

## Error Handling

All moderation methods can throw errors. [Error handling](https://getstream.io/docs/platform/error-handling/) documents the exception classes and their fields for each backend SDK, and [API error codes](https://getstream.io/docs/platform/api-error-codes/) explains what the codes mean. Handle them appropriately:

```dart label="Dart"
final response = await client.moderation.ban(banRequest: banRequest);

switch (response) {
  case Success(data: final banResponse):
    print('User banned for: ${banResponse.duration}');
  case Failure(error: final error):
    print('Error banning user: $error');
}
```


---

This page was last updated at 2026-08-11T17:18:53.016Z.

For the most recent version of this documentation, visit [https://getstream.io/activity-feeds/docs/flutter/moderation/](https://getstream.io/activity-feeds/docs/flutter/moderation/).