# Getting a Channel

The Get Channel API fetches a single channel by its type and ID **without creating it**. It is the read-only counterpart to [creating a channel](/chat/docs/javascript/creating-channels/): when the channel does not exist (or has been deleted), the API responds with `404 Not Found` instead of creating it. This makes the same call work as an efficient existence check.

```text
GET /channels/{type}/{id}
```

Before this endpoint, the only ways to fetch or check one known channel were a [Query Channels](/chat/docs/javascript/query-channels/) call with a single-CID filter, which runs the full filter and sort query path, or watching/querying the channel, which creates it when it is missing. Get Channel uses a cache-first lookup, so it can skip the database entirely when the channel is already cached.

> **SDK support:** dedicated SDK methods for this endpoint are rolling out. Until your SDK exposes one, call the REST endpoint directly (examples below) or use your SDK's low-level request helper.

## When to use it

| You want to                                                              | Use                                                                                                     |
| ------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------- |
| Fetch one channel whose type and ID you already know                     | **Get Channel**                                                                                         |
| Check whether a channel exists, without creating it                      | **Get Channel** (a `404` means it does not exist)                                                       |
| Fetch a channel, creating it when missing                                | [Creating a channel](/chat/docs/javascript/creating-channels/) (`channel.create()` / `channel.query()`) |
| Find channels by member set, filters, or sorting                         | [Query Channels](/chat/docs/javascript/query-channels/)                                                 |
| Receive live [events](/chat/docs/javascript/event-object/) for a channel | Watch the channel (`channel.watch()`), which also creates it when missing                               |

## Best practices

- **Prefer Get Channel over a single-CID Query Channels call.** Querying with `{ "cid": { "$eq": ... } }` (or a `type` + `id` filter) runs the full query machinery to return one known channel. Get Channel serves the same data from a cache-first path, which is cheaper for you (rate limits) and faster for your users.
- **Treat `404` as a normal outcome, not an error.** For existence checks (for example, checking for a buyer-to-seller conversation before offering a "start chat" button), a `404` is the expected negative answer. Do not log it as a failure or retry it.
- **Stay on the cheap path unless you need messages.** By default the response contains the channel, its configuration, and its members. Only pass `state=true` when you actually need messages, read state, or watchers hydrated.
- **Distinct channels are not covered.** Channels created [by member list](/chat/docs/javascript/creating-channels/) get a generated ID, so their CID is not known up front. To find those, keep using Query Channels with a `members` filter, or create-or-get them with `channel.create()`.

## Making the request

Request options are passed JSON-encoded in the `payload` query parameter, like other Stream `GET` endpoints. The `payload` parameter is required: pass `{}` for the defaults.

Fetching a channel (cheap default path):

```bash
curl -G "https://chat.stream-io-api.com/channels/${CHANNEL_TYPE}/${CHANNEL_ID}" \
  --data-urlencode "api_key=${API_KEY}" \
  --data-urlencode 'payload={}' \
  -H "Authorization: ${TOKEN}" \
  -H "stream-auth-type: jwt"
```

Existence check (create only when missing):

```bash
status=$(curl -sG -o /dev/null -w "%{http_code}" \
  "https://chat.stream-io-api.com/channels/${CHANNEL_TYPE}/${CHANNEL_ID}" \
  --data-urlencode "api_key=${API_KEY}" \
  --data-urlencode 'payload={}' \
  -H "Authorization: ${TOKEN}" \
  -H "stream-auth-type: jwt")

if [ "$status" = "404" ]; then
  # channel does not exist; create it (or skip, depending on your flow)
  echo "channel is missing"
fi
```

Fetching full channel state (messages, read state, watchers):

```bash
curl -G "https://chat.stream-io-api.com/channels/${CHANNEL_TYPE}/${CHANNEL_ID}" \
  --data-urlencode "api_key=${API_KEY}" \
  --data-urlencode 'payload={"state": true, "messages_limit": 25, "watchers_limit": 10}' \
  -H "Authorization: ${TOKEN}" \
  -H "stream-auth-type: jwt"
```

The endpoint works with both authentication modes:

- **Server-side** (API secret signed token): no user is required. Add `"user_id": "<id>"` to the payload to resolve membership and capabilities for a specific user.
- **Client-side** (user token): the calling user needs the [`ReadChannel` permission](/chat/docs/javascript/chat-permission-policies/) on the channel, typically granted through membership.

### Request options

All options are optional.

| Option           | Type    | Default | Description                                                                                                                                                      |
| ---------------- | ------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `state`          | boolean | `false` | When `true`, also hydrate messages, read state, watchers, and threads, like a channel query. When `false`, return only the channel, its config, and its members. |
| `messages_limit` | integer | `100`   | Maximum number of messages to return. Applies only when `state` is `true`.                                                                                       |
| `members_limit`  | integer | `100`   | Maximum number of members to return. Applies only when `state` is `true`; the default path returns the channel's cached members without truncation.              |
| `watchers_limit` | integer | `0`     | Maximum number of watchers to return. Watchers are omitted unless this is set to a positive value together with `state=true`.                                    |

### Response

The response has the same shape as a channel query response (`channel`, `members`, `membership`, `messages`, `read`, `watchers`, ...), so existing deserialization code can be reused. With `state=false` the `messages`, `read`, and `watchers` arrays are empty.

Because the endpoint performs no writes, it emits no events and does not affect unread counts, watchers, or presence.

### Errors

| Status | Condition                                                                                       |
| ------ | ----------------------------------------------------------------------------------------------- |
| `400`  | The `payload` query parameter is missing or not valid JSON.                                     |
| `403`  | The user lacks the `ReadChannel` permission, or the channel is disabled (client-side requests). |
| `404`  | The channel does not exist or has been deleted.                                                 |

## Rate limits

Get Channel shares the same high [rate limit](/chat/docs/javascript/rate-limits/) tier as Query Channels, so replacing single-CID Query Channels calls with Get Channel never lowers your available request budget.


---

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

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