> ## 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.

# Python

> The radion Python package — async-first, fully typed.

[`radion-sdk`](https://pypi.org/project/radion-sdk/) is the Python SDK (you import it as `radion`). It is async-first and built on `asyncio`. It has few dependencies — just `websockets` and `msgspec`. Needs Python 3.10+.

```bash theme={null}
uv add radion-sdk
# or: pip install radion-sdk
```

## Usage

```python theme={null}
import asyncio
import os

from radion import Radion, Subscription


async def main() -> None:
    radion = Radion(api_key=os.getenv("RADION_API_KEY"))

    await radion.realtime.connect()
    await radion.realtime.subscribe(Subscription(id="trading", channel="trading"))

    @radion.realtime.on_channel("trading")
    async def handle(event):
        print(event.id, event.channel, event.data)

    await asyncio.sleep(60)
    await radion.realtime.close()


asyncio.run(main())
```

## Handlers

`on_channel`, `on_any_channel`, and `on_lifecycle` are decorators. Your handlers can be **sync or async** — the SDK awaits both for you. Use `on_channel(name)` for one channel, `on_any_channel()` for every channel event, or `on_lifecycle(event)` for a lifecycle event (`open`, `close`, `reconnect`, `error`).

```python theme={null}
@radion.realtime.on_any_channel()
async def on_any(event):
    print(event.channel, event.data)


@radion.realtime.on_lifecycle("error")
def on_error(err):  # sync is fine too
    print(err)
```

## Standalone realtime client

```python theme={null}
from radion import RealtimeClient

client = RealtimeClient(api_key="sk_...")
await client.connect()
```

## Exports

| Export                                                      | Kind     |
| ----------------------------------------------------------- | -------- |
| `Radion`, `RealtimeClient`                                  | classes  |
| `RadionError`, `RadionConnectionError`, `RadionServerError` | errors   |
| `Subscription`, `ChannelFilters`, `ChannelEvent`            | models   |
| `CHANNELS`, `Channel`, `is_channel`                         | channels |
| `RadionConfig`, `DEFAULT_BASE_URL`, `DEFAULT_WS_URL`        | config   |

`ChannelEvent` is generic over its payload (`ChannelEvent[T]`), and defaults to `Any`. The package ships a `py.typed` marker, so types work right away.
