# Actions

## Submit Action

This is the most important endpoint in the moderation API. It allows moderators to take action on review queue items. Actions include deleting content, banning users, marking items as reviewed, restoring deleted content, and more.

`POST /api/v2/moderation/submit_action`

<Tabs>

```js label="Node"
await client.moderation.submitAction({
  action_type: "mark_reviewed",
  item_id: "review_queue_item_id",
  user_id: moderatorId,
});
```

```python label="Python"
client.moderation().submit_action(
    action_type="mark_reviewed",
    item_id="review_queue_item_id",
    user_id=moderator_id,
)
```

```go label="Go"
client.Moderation().SubmitAction(ctx, &getstream.SubmitActionRequest{
    ActionType: "mark_reviewed",
    ItemID:     getstream.PtrTo("review_queue_item_id"),
    UserID:     getstream.PtrTo(moderatorId),
})
```

```java label="Java"
client.moderation().submitAction(SubmitActionRequest.builder()
    .actionType("mark_reviewed")
    .itemId("review_queue_item_id")
    .userId(moderatorId)
    .build()).execute();
```

```php label="PHP"
$client->moderation()->submitAction(new SubmitActionRequest(
    actionType: 'mark_reviewed',
    itemId: 'review_queue_item_id',
    userId: $moderatorId,
));
```

```ruby label="Ruby"
client.moderation.submit_action(GetStream::Generated::Models::SubmitActionRequest.new(
  action_type: "mark_reviewed",
  item_id: "review_queue_item_id",
  user_id: moderator_id
))
```

```csharp label=".NET"
await client.Moderation.SubmitActionAsync(new SubmitActionRequest
{
    ActionType = "mark_reviewed",
    ItemId = "review_queue_item_id",
    UserId = moderatorId,
});
```

</Tabs>

### Request Parameters

| Key             | Required | Type   | Description                                                    |
| --------------- | -------- | ------ | -------------------------------------------------------------- |
| action_type     | true     | string | The action to take. See supported action types below.          |
| item_id         | false    | string | Review queue item ID. Required for most actions.               |
| user_id         | false    | string | User ID of the moderator performing the action.                |
| ban             | false    | object | Ban-specific parameters (used with `ban` action type).         |
| unban           | false    | object | Unban-specific parameters (used with `unban` action type).     |
| delete_message  | false    | object | Delete message parameters.                                     |
| delete_activity | false    | object | Delete activity parameters.                                    |
| restore         | false    | object | Restore parameters (used with `restore` action type).          |
| unblock         | false    | object | Unblock parameters (used with `unblock` action type).          |
| custom          | false    | object | Custom action parameters (used with `custom` action type).     |
| reject_appeal   | false    | object | Reject appeal parameters.                                      |
| appeal_id       | false    | string | Appeal ID (for appeal-related actions).                        |
| decision_reason | false    | string | Reason for the decision (shown to users for appeal decisions). |

### Response

| Key  | Type   | Description                    |
| ---- | ------ | ------------------------------ |
| item | object | The updated review queue item. |

### Supported Action Types

| Action Type     | Description                                                                       |
| --------------- | --------------------------------------------------------------------------------- |
| mark_reviewed   | Mark the item as reviewed without taking further action (content is safe).        |
| delete_message  | Delete a flagged chat message.                                                    |
| delete_activity | Delete a flagged activity (feeds).                                                |
| ban             | Ban the content creator. Supports channel-scoped, shadow, IP, and temporary bans. |
| unban           | Unban a previously banned user. Also accepts appeals automatically.               |
| restore         | Restore previously deleted content. Also accepts appeals automatically.           |
| unblock         | Unblock previously blocked content. Also accepts appeals automatically.           |
| escalate        | Escalate the item for higher-level review.                                        |
| de_escalate     | De-escalate a previously escalated item.                                          |
| shadow_block    | Shadow-block content (hidden from others but visible to the creator).             |
| end_call        | End an active video call.                                                         |
| reject_appeal   | Reject a user's appeal against a moderation decision.                             |
| custom          | Trigger a custom action (sends a webhook to your server).                         |

### Delete Message

Delete a flagged chat message from the review queue.

<Tabs>

```js label="Node"
await client.moderation.submitAction({
  action_type: "delete_message",
  item_id: "review_queue_item_id",
  user_id: moderatorId,
});
```

```python label="Python"
client.moderation().submit_action(
    action_type="delete_message",
    item_id="review_queue_item_id",
    user_id=moderator_id,
)
```

```go label="Go"
client.Moderation().SubmitAction(ctx, &getstream.SubmitActionRequest{
    ActionType: "delete_message",
    ItemID:     getstream.PtrTo("review_queue_item_id"),
    UserID:     getstream.PtrTo(moderatorId),
})
```

```java label="Java"
client.moderation().submitAction(SubmitActionRequest.builder()
    .actionType("delete_message")
    .itemId("review_queue_item_id")
    .userId(moderatorId)
    .build()).execute();
```

```php label="PHP"
$client->moderation()->submitAction(new SubmitActionRequest(
    actionType: 'delete_message',
    itemId: 'review_queue_item_id',
    userId: $moderatorId,
));
```

```ruby label="Ruby"
client.moderation.submit_action(GetStream::Generated::Models::SubmitActionRequest.new(
  action_type: "delete_message",
  item_id: "review_queue_item_id",
  user_id: moderator_id
))
```

```csharp label=".NET"
await client.Moderation.SubmitActionAsync(new SubmitActionRequest
{
    ActionType = "delete_message",
    ItemId = "review_queue_item_id",
    UserId = moderatorId,
});
```

</Tabs>

### Ban User

Ban the creator of flagged content. Supports channel-scoped bans, shadow bans, IP bans, and temporary bans with a timeout.

<Tabs>

```js label="Node"
await client.moderation.submitAction({
  action_type: "ban",
  item_id: "review_queue_item_id",
  ban: {
    reason: "Repeated harassment",
    timeout: 1440,
    channel_cids: ["messaging:general"],
  },
  user_id: moderatorId,
});
```

```python label="Python"
client.moderation().submit_action(
    action_type="ban",
    item_id="review_queue_item_id",
    ban={"reason": "Repeated harassment", "timeout": 1440, "channel_cids": ["messaging:general"]},
    user_id=moderator_id,
)
```

```go label="Go"
client.Moderation().SubmitAction(ctx, &getstream.SubmitActionRequest{
    ActionType: "ban",
    ItemID:     getstream.PtrTo("review_queue_item_id"),
    Ban: &getstream.BanActionRequest{
        Reason:      getstream.PtrTo("Repeated harassment"),
        Timeout:     getstream.PtrTo(1440),
        ChannelCids: []string{"messaging:general"},
    },
    UserID: getstream.PtrTo(moderatorId),
})
```

```java label="Java"
client.moderation().submitAction(SubmitActionRequest.builder()
    .actionType("ban")
    .itemId("review_queue_item_id")
    .ban(BanActionRequest.builder()
        .reason("Repeated harassment")
        .timeout(1440)
        .channelCids(List.of("messaging:general"))
        .build())
    .userId(moderatorId)
    .build()).execute();
```

```php label="PHP"
$client->moderation()->submitAction(new SubmitActionRequest(
    actionType: 'ban',
    itemId: 'review_queue_item_id',
    ban: new BanActionRequest(
        reason: 'Repeated harassment',
        timeout: 1440,
        channelCids: ['messaging:general'],
    ),
    userId: $moderatorId,
));
```

```ruby label="Ruby"
client.moderation.submit_action(GetStream::Generated::Models::SubmitActionRequest.new(
  action_type: "ban",
  item_id: "review_queue_item_id",
  ban: GetStream::Generated::Models::BanActionRequest.new(
    reason: "Repeated harassment",
    timeout: 1440,
    channel_cids: ["messaging:general"]
  ),
  user_id: moderator_id
))
```

```csharp label=".NET"
await client.Moderation.SubmitActionAsync(new SubmitActionRequest
{
    ActionType = "ban",
    ItemId = "review_queue_item_id",
    Ban = new BanActionRequest
    {
        Reason = "Repeated harassment",
        Timeout = 1440,
        ChannelCids = new List<string> { "messaging:general" },
    },
    UserId = moderatorId,
});
```

</Tabs>

### Ban from Future Channels

Set `ban_from_future_channels: true` on a `ban` action to also auto-apply the ban to any new channels created later by the same user who created the channel the target is being banned from. This is useful when a community owner repeatedly creates new channels and you want a known offender kept out without re-banning them every time. The ban is applied automatically as the channel creator opens additional channels and remains in effect until removed via an `unban` with `remove_future_channels_ban: true`.

<Tabs>

```js label="Node"
await client.moderation.submitAction({
  action_type: "ban",
  item_id: "review_queue_item_id",
  ban: {
    reason: "Repeated harassment",
    ban_from_future_channels: true,
  },
  user_id: moderatorId,
});
```

```python label="Python"
client.moderation().submit_action(
    action_type="ban",
    item_id="review_queue_item_id",
    ban={"reason": "Repeated harassment", "ban_from_future_channels": True},
    user_id=moderator_id,
)
```

```go label="Go"
client.Moderation().SubmitAction(ctx, &getstream.SubmitActionRequest{
    ActionType: "ban",
    ItemID:     getstream.PtrTo("review_queue_item_id"),
    Ban: &getstream.BanActionRequest{
        Reason:                getstream.PtrTo("Repeated harassment"),
        BanFromFutureChannels: getstream.PtrTo(true),
    },
    UserID: getstream.PtrTo(moderatorId),
})
```

```java label="Java"
client.moderation().submitAction(SubmitActionRequest.builder()
    .actionType("ban")
    .itemId("review_queue_item_id")
    .ban(BanActionRequest.builder()
        .reason("Repeated harassment")
        .banFromFutureChannels(true)
        .build())
    .userId(moderatorId)
    .build()).execute();
```

```php label="PHP"
$client->moderation()->submitAction(new SubmitActionRequest(
    actionType: 'ban',
    itemId: 'review_queue_item_id',
    ban: new BanActionRequest(
        reason: 'Repeated harassment',
        banFromFutureChannels: true,
    ),
    userId: $moderatorId,
));
```

```ruby label="Ruby"
client.moderation.submit_action(GetStream::Generated::Models::SubmitActionRequest.new(
  action_type: "ban",
  item_id: "review_queue_item_id",
  ban: GetStream::Generated::Models::BanActionRequest.new(
    reason: "Repeated harassment",
    ban_from_future_channels: true
  ),
  user_id: moderator_id
))
```

```csharp label=".NET"
await client.Moderation.SubmitActionAsync(new SubmitActionRequest
{
    ActionType = "ban",
    ItemId = "review_queue_item_id",
    Ban = new BanActionRequest
    {
        Reason = "Repeated harassment",
        BanFromFutureChannels = true,
    },
    UserId = moderatorId,
});
```

</Tabs>

To remove a previously applied future-channels ban, submit an `unban` action with `remove_future_channels_ban: true`:

<Tabs>

```js label="Node"
await client.moderation.submitAction({
  action_type: "unban",
  item_id: "review_queue_item_id",
  unban: {
    remove_future_channels_ban: true,
  },
  user_id: moderatorId,
});
```

```python label="Python"
client.moderation().submit_action(
    action_type="unban",
    item_id="review_queue_item_id",
    unban={"remove_future_channels_ban": True},
    user_id=moderator_id,
)
```

```go label="Go"
client.Moderation().SubmitAction(ctx, &getstream.SubmitActionRequest{
    ActionType: "unban",
    ItemID:     getstream.PtrTo("review_queue_item_id"),
    Unban: &getstream.UnbanActionRequest{
        RemoveFutureChannelsBan: getstream.PtrTo(true),
    },
    UserID: getstream.PtrTo(moderatorId),
})
```

```java label="Java"
client.moderation().submitAction(SubmitActionRequest.builder()
    .actionType("unban")
    .itemId("review_queue_item_id")
    .unban(UnbanActionRequest.builder()
        .removeFutureChannelsBan(true)
        .build())
    .userId(moderatorId)
    .build()).execute();
```

```php label="PHP"
$client->moderation()->submitAction(new SubmitActionRequest(
    actionType: 'unban',
    itemId: 'review_queue_item_id',
    unban: new UnbanActionRequest(
        removeFutureChannelsBan: true,
    ),
    userId: $moderatorId,
));
```

```ruby label="Ruby"
client.moderation.submit_action(GetStream::Generated::Models::SubmitActionRequest.new(
  action_type: "unban",
  item_id: "review_queue_item_id",
  unban: GetStream::Generated::Models::UnbanActionRequest.new(
    remove_future_channels_ban: true
  ),
  user_id: moderator_id
))
```

```csharp label=".NET"
await client.Moderation.SubmitActionAsync(new SubmitActionRequest
{
    ActionType = "unban",
    ItemId = "review_queue_item_id",
    Unban = new UnbanActionRequest
    {
        RemoveFutureChannelsBan = true,
    },
    UserId = moderatorId,
});
```

</Tabs>

### Restore Content

Restore previously deleted content. This is typically used when content was incorrectly flagged or removed. If the item has an associated appeal, the appeal is automatically accepted.

<Tabs>

```js label="Node"
await client.moderation.submitAction({
  action_type: "restore",
  item_id: "review_queue_item_id",
  restore: {},
  decision_reason: "Content was incorrectly flagged",
  user_id: moderatorId,
});
```

```python label="Python"
client.moderation().submit_action(
    action_type="restore",
    item_id="review_queue_item_id",
    restore={},
    decision_reason="Content was incorrectly flagged",
    user_id=moderator_id,
)
```

```go label="Go"
client.Moderation().SubmitAction(ctx, &getstream.SubmitActionRequest{
    ActionType:     "restore",
    ItemID:         getstream.PtrTo("review_queue_item_id"),
    Restore:        &getstream.RestoreActionRequest{},
    DecisionReason: getstream.PtrTo("Content was incorrectly flagged"),
    UserID:         getstream.PtrTo(moderatorId),
})
```

```java label="Java"
client.moderation().submitAction(SubmitActionRequest.builder()
    .actionType("restore")
    .itemId("review_queue_item_id")
    .restore(RestoreActionRequest.builder().build())
    .decisionReason("Content was incorrectly flagged")
    .userId(moderatorId)
    .build()).execute();
```

```php label="PHP"
$client->moderation()->submitAction(new SubmitActionRequest(
    actionType: 'restore',
    itemId: 'review_queue_item_id',
    restore: new RestoreActionRequest(),
    decisionReason: 'Content was incorrectly flagged',
    userId: $moderatorId,
));
```

```ruby label="Ruby"
client.moderation.submit_action(GetStream::Generated::Models::SubmitActionRequest.new(
  action_type: "restore",
  item_id: "review_queue_item_id",
  restore: GetStream::Generated::Models::RestoreActionRequest.new,
  decision_reason: "Content was incorrectly flagged",
  user_id: moderator_id
))
```

```csharp label=".NET"
await client.Moderation.SubmitActionAsync(new SubmitActionRequest
{
    ActionType = "restore",
    ItemId = "review_queue_item_id",
    Restore = new RestoreActionRequest(),
    DecisionReason = "Content was incorrectly flagged",
    UserId = moderatorId,
});
```

</Tabs>

### Custom Action

Trigger a custom action that sends a webhook to your server. Use this to integrate your own moderation workflows.

<Tabs>

```js label="Node"
await client.moderation.submitAction({
  action_type: "custom",
  item_id: "review_queue_item_id",
  custom: {
    custom_action_name: "notify_user",
    custom_data: { notification: "Your content has been reviewed" },
  },
  user_id: moderatorId,
});
```

```python label="Python"
client.moderation().submit_action(
    action_type="custom",
    item_id="review_queue_item_id",
    custom={
        "custom_action_name": "notify_user",
        "custom_data": {"notification": "Your content has been reviewed"},
    },
    user_id=moderator_id,
)
```

```go label="Go"
client.Moderation().SubmitAction(ctx, &getstream.SubmitActionRequest{
    ActionType: "custom",
    ItemID:     getstream.PtrTo("review_queue_item_id"),
    Custom: &getstream.CustomActionRequest{
        CustomActionName: "notify_user",
        CustomData: map[string]interface{}{
            "notification": "Your content has been reviewed",
        },
    },
    UserID: getstream.PtrTo(moderatorId),
})
```

```java label="Java"
client.moderation().submitAction(SubmitActionRequest.builder()
    .actionType("custom")
    .itemId("review_queue_item_id")
    .custom(CustomActionRequest.builder()
        .customActionName("notify_user")
        .customData(Map.of("notification", "Your content has been reviewed"))
        .build())
    .userId(moderatorId)
    .build()).execute();
```

```php label="PHP"
$client->moderation()->submitAction(new SubmitActionRequest(
    actionType: 'custom',
    itemId: 'review_queue_item_id',
    custom: new CustomActionRequest(
        customActionName: 'notify_user',
        customData: (object)['notification' => 'Your content has been reviewed'],
    ),
    userId: $moderatorId,
));
```

```ruby label="Ruby"
client.moderation.submit_action(GetStream::Generated::Models::SubmitActionRequest.new(
  action_type: "custom",
  item_id: "review_queue_item_id",
  custom: GetStream::Generated::Models::CustomActionRequest.new(
    custom_action_name: "notify_user",
    custom_data: { "notification" => "Your content has been reviewed" }
  ),
  user_id: moderator_id
))
```

```csharp label=".NET"
await client.Moderation.SubmitActionAsync(new SubmitActionRequest
{
    ActionType = "custom",
    ItemId = "review_queue_item_id",
    Custom = new CustomActionRequest
    {
        CustomActionName = "notify_user",
        CustomData = new Dictionary<string, object>
        {
            { "notification", "Your content has been reviewed" }
        },
    },
    UserId = moderatorId,
});
```

</Tabs>

## Bulk Submit Action

Submit multiple moderation actions in a single request. This is useful for batch operations such as approving or deleting multiple flagged items at once.

`POST /api/v2/moderation/bulk_submit_action`

<Tabs>

```js label="Node"
await client.moderation.bulkSubmitAction({
  actions: [
    {
      action_type: "mark_reviewed",
      item_id: "item_id_1",
      user_id: moderatorId,
    },
    {
      action_type: "delete_message",
      item_id: "item_id_2",
      user_id: moderatorId,
    },
    {
      action_type: "mark_reviewed",
      item_id: "item_id_3",
      user_id: moderatorId,
    },
  ],
});
```

```python label="Python"
client.moderation().bulk_submit_action(
    actions=[
        {"action_type": "mark_reviewed", "item_id": "item_id_1", "user_id": moderator_id},
        {"action_type": "delete_message", "item_id": "item_id_2", "user_id": moderator_id},
        {"action_type": "mark_reviewed", "item_id": "item_id_3", "user_id": moderator_id},
    ]
)
```

```go label="Go"
client.Moderation().BulkSubmitAction(ctx, &getstream.BulkSubmitActionRequest{
    Actions: []getstream.SubmitActionRequest{
        {ActionType: "mark_reviewed", ItemID: getstream.PtrTo("item_id_1"), UserID: getstream.PtrTo(moderatorId)},
        {ActionType: "delete_message", ItemID: getstream.PtrTo("item_id_2"), UserID: getstream.PtrTo(moderatorId)},
        {ActionType: "mark_reviewed", ItemID: getstream.PtrTo("item_id_3"), UserID: getstream.PtrTo(moderatorId)},
    },
})
```

```java label="Java"
client.moderation().bulkSubmitAction(BulkSubmitActionRequest.builder()
    .actions(List.of(
        SubmitActionRequest.builder().actionType("mark_reviewed").itemId("item_id_1").userId(moderatorId).build(),
        SubmitActionRequest.builder().actionType("delete_message").itemId("item_id_2").userId(moderatorId).build(),
        SubmitActionRequest.builder().actionType("mark_reviewed").itemId("item_id_3").userId(moderatorId).build()
    ))
    .build()).execute();
```

```php label="PHP"
$client->moderation()->bulkSubmitAction(new BulkSubmitActionRequest(
    actions: [
        new SubmitActionRequest(actionType: 'mark_reviewed', itemId: 'item_id_1', userId: $moderatorId),
        new SubmitActionRequest(actionType: 'delete_message', itemId: 'item_id_2', userId: $moderatorId),
        new SubmitActionRequest(actionType: 'mark_reviewed', itemId: 'item_id_3', userId: $moderatorId),
    ]
));
```

```ruby label="Ruby"
client.moderation.bulk_submit_action(
  GetStream::Generated::Models::BulkSubmitActionRequest.new(
    actions: [
      GetStream::Generated::Models::SubmitActionRequest.new(action_type: "mark_reviewed", item_id: "item_id_1", user_id: moderator_id),
      GetStream::Generated::Models::SubmitActionRequest.new(action_type: "delete_message", item_id: "item_id_2", user_id: moderator_id),
      GetStream::Generated::Models::SubmitActionRequest.new(action_type: "mark_reviewed", item_id: "item_id_3", user_id: moderator_id),
    ]
  )
)
```

```csharp label=".NET"
await client.Moderation.BulkSubmitActionAsync(new BulkSubmitActionRequest
{
    Actions = new List<SubmitActionRequest>
    {
        new() { ActionType = "mark_reviewed", ItemId = "item_id_1", UserId = moderatorId },
        new() { ActionType = "delete_message", ItemId = "item_id_2", UserId = moderatorId },
        new() { ActionType = "mark_reviewed", ItemId = "item_id_3", UserId = moderatorId },
    },
});
```

</Tabs>

### Request Parameters

| Key     | Required | Type  | Description                                                                               |
| ------- | -------- | ----- | ----------------------------------------------------------------------------------------- |
| actions | true     | array | List of action objects. Each object follows the same schema as the Submit Action request. |

### Response

| Key     | Type  | Description                                |
| ------- | ----- | ------------------------------------------ |
| results | array | List of results for each submitted action. |


---

This page was last updated at 2026-07-10T16:05:19.550Z.

For the most recent version of this documentation, visit [https://getstream.io/moderation/docs/dotnet-csharp/content-moderation/actions/](https://getstream.io/moderation/docs/dotnet-csharp/content-moderation/actions/).