> ## Documentation Index
> Fetch the complete documentation index at: https://docs.radion.app/llms.txt
> Use this file to discover all available pages before exploring further.

# Subscribe

> Subscribe, unsubscribe, and ping over the Radion WebSocket.

Send JSON messages after the socket opens. Each message has an `action`. You set the `id` yourself. Radion echoes it back in confirmations and event frames, so you can match incoming data to the subscription that made it.

## Subscribe

```json theme={null}
{
  "action": "subscribe",
  "id": "s1",
  "channel": "trading"
}
```

To narrow a channel, add a `filters` object:

```json theme={null}
{
  "action": "subscribe",
  "id": "wallet-activity",
  "channel": "wallets",
  "filters": {
    "wallets": ["0x0000000000000000000000000000000000000000"]
  }
}
```

If it works, the server sends back a [`subscribed` control frame](/websockets/frames#control-frames). If it fails, it sends an [`error` frame](/websockets/frames#error-frames). That can happen if the channel is unknown, a required filter is missing, or you are over your [subscription limit](/websockets/rate-limits).

If you subscribe again with an `id` you already use, the new subscription replaces the old one on that `id`.

## Confirmed vs pending

By default a subscription streams the confirmed on-chain feed — `confirmed` is `true`. Set `confirmed: false` to stream the pending feed of the same channel instead: pending transactions before they land in a block.

```json theme={null}
{
  "action": "subscribe",
  "id": "pending",
  "channel": "trading",
  "confirmed": false
}
```

Both feeds use the bare channel name. Each event frame carries a `confirmed` boolean, so you tell pending from confirmed by that flag and your subscription `id`, not by the channel name. See [Mempool](/websockets/mempool) for the pending frame shape.

## Unsubscribe

Unsubscribe with the same `id`:

```json theme={null}
{
  "action": "unsubscribe",
  "id": "wallet-activity"
}
```

The server sends back an `unsubscribed` control frame. If the `id` is unknown, nothing changes, but the server still acknowledges it.

## Ping

Send an app-level ping to check the socket is alive:

```json theme={null}
{ "action": "ping" }
```

The server sends back `{ "type": "pong" }`. This is not the same as the protocol-level WebSocket ping/pong that the server uses for [heartbeats](/websockets/connection-state#heartbeats).
