# 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

```js label="JavaScript"
const client = new FeedsClient("<API key>");

client.moderation;
```

## Auto-moderation and `force_moderation`

When a moderation policy is configured, activities and comments are moderated automatically on create and update. Server-side requests skip moderation by default; set `force_moderation: true` to moderate them.

>
> **Warning:** `force_moderation` is **server-side only** and ignored when sent from a client-side SDK.
>

See [Feeds moderation](https://getstream.io/moderation/docs/node/integrations/stream-feeds/) for policy setup and the `moderation` object returned in responses. That page also covers assigning a named policy with `feed.custom.moderation_policy`.

## User Moderation

### Ban Users

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

```js label="JavaScript"
await client.moderation.ban({
  target_user_id: "user-123",
  reason: "Violation of community guidelines",
  timeout: 3600, // 1 hour in seconds
  shadow: false,
  ip_ban: false,
});
```

**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.

```js label="JavaScript"
await client.blockUsers({
  blocked_user_id: "user-123",
});
```

### Unblock Users

Unblock a previously blocked user.

```js label="JavaScript"
await client.unblockUsers({
  blocked_user_id: "user-123",
});
```

### Get Blocked Users

Retrieve a list of users you have blocked.

```js label="JavaScript"
const response = await client.getBlockedUsers();
```

## Content Moderation

### Flag Content

Flag inappropriate content for moderation review.

```js label="JavaScript"
await client.moderation.flag({
  entity_type: "stream:feeds:v3:activity",
  entity_id: "activity_123",
  reason: "Inappropriate content",
});
```

**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.

```js label="JavaScript"
client.moderation.submitAction({
  // Action details for moderation
});
```

## Review Queue

### Query Review Queue

Retrieve items in the moderation review queue.

```js label="JavaScript"
client.moderation.queryReviewQueue({
  // Query parameters for filtering and pagination
});
```

## Configuration Management

### Upsert Moderation Configuration

Create or update moderation configuration settings.

```js label="JavaScript"
client.moderation.upsertConfig({
    key: 'feeds',
    block_list_config: {
        enabled: true,
        rules: [
        // Names of existing block lists
        { name: blocklistName, action: 'remove' },
        { name: flagBlocklistName, action: 'flag' },
        { name: shadowBlocklistName, action: 'shadow' },
        { name: bounceBlocklistName, action: 'bounce' },
        ],
    },
    ai_image_config: {
        enabled: true,
        rules: [{ label: 'Non-Explicit Nudity', action: 'remove', min_confidence: 0 }],
        ocr_rules: [{ label: 'Non-Explicit Nudity', action: 'remove' }],
    },
}),
```

### Get Moderation Configuration

Retrieve a specific moderation configuration.

```js label="JavaScript"
client.moderation.getConfig({
  key: "feeds",
});
```

**Parameters:**

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

### Delete Moderation Configuration

Remove a moderation configuration.

```js label="JavaScript"
client.moderation.deleteConfig({
  key: "feeds",
});
```

### Query Moderation Configurations

Search and filter moderation configurations.

```js label="JavaScript"
client.moderation.queryModerationConfigs({
  filter: {
    // Filter params
  },
});
```

#### 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:

```js label="JavaScript"
try {
  const response = await client.moderation.ban({
    target_user_id: "user-123",
    reason: "Violation of community guidelines",
    timeout: 3600, // 1 hour in seconds
    shadow: false,
    ip_ban: false,
  });

  console.log(`Banned successfully`);
} catch (e) {
  console.error(`Failed to ban user, error: ${e}`);
}
```

---

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