# Deleting Channels

You can delete or truncate a channel to remove its contents. To remove only messages while preserving the channel, see [Truncate Channel](https://getstream.io/chat/docs/python/truncate-channel/).

## Deleting a Channel

You can delete a single Channel using the  `delete`  method. This marks the channel as deleted and hides all the messages.

```python label="Python"
# Get a channel
channel = client.chat.channel("messaging", "general")

channel.delete()
```

>
> **Info:** If you recreate this channel, it will show up empty. Recovering old messages is not supported, unless the channel was deleted with `skip_truncate` (see [Preserving message history](#preserving-message-history) below). Use the [disable method](https://getstream.io/chat/docs/python/disabling-channels/) if you want a fully reversible change.
>

## Preserving Message History

By default, deleting a channel hides its messages, so a channel later recreated with the same ID starts out empty. Set `skip_truncate` to `true` to preserve message history through the delete instead, so a channel later recreated with the same ID (for example with `GetOrCreateChannel`) restores the full message history.

This is useful for apps where the same pair of users can end up back in the same channel, for example a dating app where two users unmatch and later re-match.

>
> **Warning:** `skip_truncate` is server-side only and only supported on [distinct channels](https://getstream.io/chat/docs/python/creating-channels/#distinct-channels). It cannot be combined with `hard_delete`, and it cannot be used if the channel's messages were already hidden by an earlier delete or truncate.
>

```python label="Python"
channel = client.chat.channel("messaging", "general")

# Preserve history through the soft delete
channel.delete(skip_truncate=True)
```

## Deleting Many Channels

You can delete up to 100 channels and optionally all of their messages using this method. This can be a large amount of data to delete, so this endpoint processes asynchronously, meaning responses contain a `task ID` which can be polled using the [getTask endpoint](https://getstream.io/docs/platform/async-operations/) to check status of the deletions. Channels will be soft-deleted immediately so that channels no longer return from queries, but permanently deleting the channel and deleting messages takes longer to process.

By default, messages are soft deleted, which means they are removed from client but are still available via server-side export functions. You can also hard delete messages, which deletes them from everywhere, by setting `"hard_delete": true` in the request. Messages that have been soft or hard deleted cannot be recovered.

You can also set `skip_truncate` to `true` to preserve message history for every channel in the request, the same as for a [single channel delete](#preserving-message-history). If any of the given CIDs is not eligible (it isn't a distinct channel, or its messages were already hidden by an earlier delete or truncate), the entire request is rejected and none of the channels are deleted.

This is currently supported on the following SDK versions (or higher):

- Javascript 4.3.0, Python 3.14.0, Ruby 2.12.0, PHP 2.6.0, Go 3.13.0, Java 1.4.0, Unity 2.0.0 and .NET 0.22.0

```python label="Python"
# soft deletion
response = client.chat.delete_channels(cids=[cid1, cid2])
# hard deletion
response = client.chat.delete_channels(cids=[cid1, cid2], hard_delete=True)

task_response = client.get_task(id=response.data.task_id)
if task_response.data.status == "completed":
    # success!
    pass

# preserve history (distinct channels only)
response = client.chat.delete_channels(cids=[cid1, cid2], skip_truncate=True)
```

The  `deleteChannels`  response contain a taskID which can be polled using the [getTask endpoint](https://getstream.io/docs/platform/async-operations/) to check the status of the deletions.

## Finding and purging soft-deleted channels

A soft-deleted channel no longer appears in [query channels](https://getstream.io/chat/docs/python/query-channels/) results, but its channel record and messages are kept until the channel is hard deleted. To erase that data, for example to handle a GDPR erasure request, list the soft-deleted channels with `queryDeletedChannels`, then pass their CIDs to [delete many channels](#deleting-many-channels) with `hard_delete` set to `true`.

>
> **Info:** `queryDeletedChannels` is server-side only. Calls made with a user token are rejected with a `403`.
>

`filter_conditions` is optional. Omit it, or pass `{}`, to list every soft-deleted channel of your app. In a multi-tenant app, filter by `team` to list the soft-deleted channels of one tenant. See [Multi-tenancy](https://getstream.io/docs/platform/multi-tenancy/) for assigning channels to a `team`.

The example below purges every soft-deleted channel of the app. To purge a single tenant instead, use the commented `team` filter. Each page holds up to 100 channels, which is also the maximum number of CIDs a single delete call accepts, so every page maps to one delete call.

```python label="Python"
# Every soft-deleted channel of the app
filter_conditions = {}
# Only the soft-deleted channels of one team
# filter_conditions = {"team": "tenant-a"}

next_cursor = None

while True:
    response = client.chat.query_deleted_channels(
        filter_conditions=filter_conditions,
        limit=100,
        next=next_cursor,
    )

    cids = [channel.cid for channel in response.data.channels]
    if cids:
        client.chat.delete_channels(cids=cids, hard_delete=True)

    next_cursor = response.data.next
    if not next_cursor:
        break
```

Purge with the [delete many channels](#deleting-many-channels) endpoint, as above. The single-channel [delete](#deleting-a-channel) does not accept a channel that is already soft-deleted: it responds that the channel does not exist, so it cannot purge the channels that `queryDeletedChannels` returns.

Hard deletes are processed asynchronously, so a channel keeps appearing in `queryDeletedChannels` results until its deletion task completes. Follow the `next` cursor rather than starting again from the first page, and poll the returned task IDs with the [getTask endpoint](https://getstream.io/docs/platform/async-operations/) if you need to confirm that the deletions have finished.

### Request parameters

| Name                | Type    | Description                                                                                                                                                              | Default                                   | Optional |
| ------------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ----------------------------------------- | -------- |
| `filter_conditions` | object  | Filter for the soft-deleted channels to return. Omit it, or pass `{}`, to list every soft-deleted channel of the app. See [filterable fields](#filterable-fields) below. | `{}`                                      | Yes      |
| `sort`              | array   | Sort order. Only `created_at` is supported, ascending (`1`) or descending (`-1`).                                                                                        | `[{ field: "created_at", direction: 1 }]` | Yes      |
| `limit`             | integer | Number of channels per page, from 1 to 100.                                                                                                                              | `25`                                      | Yes      |
| `next`              | string  | Cursor for the next page, taken from the previous response.                                                                                                              |                                           | Yes      |
| `prev`              | string  | Cursor for the previous page, taken from the previous response. A request can set `next` or `prev`, not both.                                                            |                                           | Yes      |

The response contains `channels`, the soft-deleted channels matching the filter, plus the `next` and `prev` cursors. Each channel is returned as a channel object with `deleted_at` set. Messages, members and read state are not included.

### Filterable fields

| Field           | Operators                    | Notes                                |
| --------------- | ---------------------------- | ------------------------------------ |
| `team`          | `$eq`, `$in`                 | Narrows the list to one tenant.      |
| `cid`           | `$eq`, `$in`                 | `$in` accepts at most 100 CIDs.      |
| `type`          | `$eq`, `$in`                 |                                      |
| `created_by_id` | `$eq`, `$in`                 |                                      |
| `created_at`    | `$gt`, `$gte`, `$lt`, `$lte` | Use a range to split a large result. |
| `deleted_at`    | `$gt`, `$gte`, `$lt`, `$lte` |                                      |

Only fields that a soft delete leaves intact can be filtered on:

- **Custom fields are not supported.** Soft-deleting a channel clears its custom data, so a tenant identified only by a custom field cannot be found this way. Use `team` to identify tenants, or keep a record of the CIDs you delete.
- **Membership filters such as `members` are not supported.** Deleting a channel removes its members.

### Things to know

- **Errors:** the request is rejected with a `400` when the filter uses an unsupported field or operator (such as a custom field or `members`), when `sort` uses a field other than `created_at`, when a `cid` `$in` lists more than 100 CIDs, when `limit` is below 1, or when both `next` and `prev` are set. A page that takes too long to read returns a `408`. Narrow the filter with a `created_at` range, or query by `cid`, and retry.
- **Duplicate `channel.deleted` events:** hard-deleting a channel that was already soft-deleted sends the [`channel.deleted`](https://getstream.io/chat/docs/node/webhook-events/#channeldeleted) event again. Make your webhook handlers idempotent for this event.
- **Deleted channel types:** a soft-deleted channel whose channel type was deleted afterwards is still listed, with `config` set to `null`, and can still be hard deleted server-side. No `channel.deleted` event is sent when it is hard deleted.
- **Recreated channels:** if a listed channel is recreated with the same ID before you delete it, it is a live channel again, and passing its CID to the delete call deletes it again. Delete each page promptly after listing it.

---

For the most recent version of this documentation, visit [https://getstream.io/chat/docs/python/channel-delete/](https://getstream.io/chat/docs/python/channel-delete/).