await client.moderation.flag({
entity_type: "stream:chat:v1:message",
entity_id: messageId,
entity_creator_id: creatorId,
reason: "spam",
custom: { user_comment: "This user is spamming the channel" },
user_id: moderatorId,
});Flag, Mute & Ban
Overview
Stream provides moderation APIs for flagging content, muting users, banning users, and blocking users. These actions integrate with the moderation review queue and dashboard. All endpoints use the v2 moderation API and are available through Stream's server-side SDKs.
Flag
Flagging allows users or moderators to report content for review. Flagged content is automatically added to the moderation review queue. You can flag messages, users, activities, reactions, or any custom entity type.
Flag Content
Use the flag method to report an entity for moderation review. You can attach a reason, custom metadata, and a moderation payload containing the content to be reviewed.
Request parameters
| key | required | type | description |
|---|---|---|---|
| entity_type | true | string | Type of entity being flagged. Examples: stream:chat:v1:message, stream:user, stream:feeds:v2:activity, stream:feeds:v2:reaction, or any custom type. |
| entity_id | true | string | Unique identifier of the entity being flagged. |
| entity_creator_id | false | string | User ID of the entity creator. |
| reason | false | string | Reason for flagging. Use a slug or keyword for easy filtering. |
| custom | false | object | Custom metadata to attach to the flag. |
| moderation_payload | false | object | Content to be reviewed (texts, images, videos). Displayed on the dashboard. |
| user_id | false | string | User ID of the person flagging (required for server-side usage). |
Response
| key | type | description |
|---|---|---|
| item_id | string | ID of the review queue item created by the flag. |
Flag a User
To flag a user rather than a message, set entity_type to stream:user and provide the target user's ID as entity_id.
await client.moderation.flag({
entity_type: "stream:user",
entity_id: targetUserId,
reason: "harassment",
user_id: moderatorId,
});Query Moderation Flags
Query flags with filtering, sorting, and pagination. This allows you to retrieve flags matching specific criteria.
const response = await client.moderation.queryModerationFlags({
filter: { entity_type: "stream:chat:v1:message" },
sort: [{ field: "created_at", direction: -1 }],
limit: 20,
});Request parameters
| key | required | type | description |
|---|---|---|---|
| filter | false | object | Filter conditions. |
| sort | false | array | Sort parameters. |
| limit | false | number | Maximum flags to return. |
| next | false | string | Pagination cursor. |
Mute
Muting allows users to silence other users. Muted users' messages are still delivered via WebSocket but not via push notifications (APN/Firebase). Implementing UI logic for muted users (hiding or displaying differently) is left to the developer.
Mute User
Mute one or more users. You can optionally set a timeout after which the mute automatically expires.
await client.moderation.mute({
target_ids: ["user_to_mute"],
user_id: mutingUserId,
timeout: 60,
});Request parameters
| key | required | type | description |
|---|---|---|---|
| target_ids | true | array | List of user IDs to mute. |
| user_id | false | string | User ID of the person performing the mute. |
| timeout | false | number | Mute duration in minutes. If not set, the mute has no expiration. |
Unmute User
Remove a mute from one or more users.
await client.moderation.unmute({
target_ids: ["user_to_unmute"],
user_id: unmutingUserId,
});Ban
Banning prevents a user from posting messages. Users can be banned from a specific channel or from the entire app. Bans support timeouts (temporary bans), shadow banning, IP banning, and optional message deletion.
Ban User
Ban a user from the entire app. You can optionally specify a timeout for temporary bans, a reason, and whether to delete the user's messages.
await client.moderation.ban({
target_user_id: "user_to_ban",
banned_by_id: moderatorId,
reason: "Repeated spam",
timeout: 1440,
});Request parameters
| key | required | type | description |
|---|---|---|---|
| target_user_id | true | string | User ID to ban. |
| banned_by_id | false | string | User ID of the moderator performing the ban. |
| channel_cid | false | string | Channel CID for channel-scoped bans (e.g., messaging:general). Omit for app-wide bans. |
| reason | false | string | Reason for the ban. |
| timeout | false | number | Ban duration in minutes. If not set, the ban is permanent. |
| shadow | false | boolean | When true, the user is shadow banned. Their messages are only visible to themselves. |
| ip_ban | false | boolean | When true, also bans the user's last known IP address. Automatically applies a 30-day timeout unless overridden. |
| delete_messages | false | string | Delete the user's messages. Values: soft (removes from client, retained on server) or hard (permanently deleted). |
Channel-Scoped Ban
Ban a user from a specific channel by providing the channel_cid parameter. The user will still be able to use the rest of the app.
await client.moderation.ban({
target_user_id: "user_to_ban",
banned_by_id: moderatorId,
channel_cid: "messaging:general",
reason: "Trolling in this channel",
timeout: 60,
});Shadow Ban
Shadow banning allows a user to continue posting, but their messages are only visible to themselves. Other users will not see the shadow-banned user's messages. This is useful for handling disruptive users without alerting them.
await client.moderation.ban({
target_user_id: "user_to_shadow_ban",
banned_by_id: moderatorId,
reason: "Disruptive behavior",
shadow: true,
});Unban User
Remove a ban from a user. For channel-scoped bans, provide the channel_cid parameter.
await client.moderation.unban({
target_user_id: "user_to_unban",
unbanned_by_id: moderatorId,
});Query Banned Users
List bans with the metadata that is intentionally not returned by queryUsers — the moderator who issued the ban (banned_by), the original reason, when it expires, and the channel CID for channel-scoped bans. Use this when you need to render a "who banned this user and why" view, build a moderation dashboard, or audit ban history.
queryUsers returns only the ban state (banned, ban_expires) on the user object — banned_by and reason are not part of the user payload by design. Use queryBannedUsers to retrieve them. This endpoint is part of the Chat product API; bans are app-wide, so it works for any app that has Chat enabled regardless of which product applied the ban.
// All app-wide bans
const response = await client.queryBannedUsers({
filter_conditions: { banned_by_id: { $eq: moderatorId } },
sort: [{ field: "created_at", direction: -1 }],
limit: 20,
exclude_expired_bans: true,
});
// Bans for a specific user
const userBans = await client.queryBannedUsers({
filter_conditions: { user_id: { $eq: "user_to_ban" } },
});
// Channel-scoped bans
const channelBans = await client.queryBannedUsers({
filter_conditions: { channel_cid: { $eq: "messaging:general" } },
});Request parameters
| key | required | type | description |
|---|---|---|---|
| filter_conditions | true | object | Filter conditions. Supported keys include user_id, banned_by_id, channel_cid, reason, created_at, expires. Operators: $eq, $in, $gt, $gte, $lt, $lte. |
| sort | false | array | Sort parameters (max 1). Typically sort by created_at. |
| limit | false | number | Number of records to return (max 300). |
| offset | false | number | Number of records to skip (max 10000). |
| exclude_expired_bans | false | boolean | When true, omits bans whose expires timestamp is in the past. |
| user_id | false | string | Server-side actor making the request. |
Response
| key | type | description |
|---|---|---|
| bans | array | List of bans. Each entry contains the fields described below. |
Each entry in bans:
| key | type | description |
|---|---|---|
| user | object | The banned user. |
| banned_by | object | The moderator who applied the ban (the answer to "who banned this user?"). |
| reason | string | Reason supplied when the ban was created. |
| expires | string | Expiration timestamp for temporary bans. Absent for permanent bans. |
| shadow | bool | true for shadow bans. |
| channel | object | Present for channel-scoped bans; contains the channel CID and metadata. |
| created_at | string | When the ban was applied. |
Block
Blocking allows a user to block another user. This is a server-side operation.
await client.moderation.block({
target_user_id: "user_to_block",
user_id: blockingUserId,
});Bypass Moderation
Enable or disable moderation bypass for a specific user, allowing them to skip content moderation checks. This is a server-side only operation intended for trusted users whose content should not be subject to automated moderation.
await client.moderation.bypass({
user_id: "trusted_user_id",
bypass: true,
});Request parameters
| key | required | type | description |
|---|---|---|---|
| user_id | true | string | User ID to enable/disable bypass for. |
| bypass | true | boolean | true to enable bypass, false to disable. |
User Moderation Report
Retrieve a comprehensive moderation report for a user, including their flags, bans, mutes, and other moderation actions.
const response = await client.moderation.getUserModerationReport({
user_id: "user_123",
});