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

# Python SDK

> Install and use the official Typeless Python SDK

The official Python SDK wraps the [transcription API](/reference/transcribe) and
[streaming API](/reference/transcribe-stream) with typed clients, structured
exceptions, and automatic retries.

## Installation

Requires Python 3.10 or later.

```bash theme={null}
pip install typeless
```

## Quickstart

<Steps>
  <Step title="Create an API key">
    Sign in to the [Typeless Console](https://platform.typelessapi.com) and create an
    API key. The key is shown **only once** at creation — store it somewhere safe.
  </Step>

  <Step title="Set your API key">
    The SDK reads the key from the `TYPELESS_API_KEY` environment variable when you
    do not pass one explicitly.

    ```bash theme={null}
    export TYPELESS_API_KEY="tls_sk_..."
    ```
  </Step>

  <Step title="Transcribe an audio file">
    Send a `wav`, `ogg`, or `webm` file (up to 50 MB / 5 minutes):

    ```python theme={null}
    from typeless import TypelessClient

    client = TypelessClient()  # reads TYPELESS_API_KEY from the environment

    result = client.transcribe("meeting.wav", model="typeless-1.0-pro")

    print(result.transcript)
    print(result.detected_language)
    print(result.usage.billed_audio_seconds)
    print(result.request_id)
    ```

    The `model` parameter is required on every request. Available tiers:
    `typeless-1.0-lite`, `typeless-1.0-pro`, and `typeless-1.0-max`.
  </Step>
</Steps>

`transcribe()` accepts a file path, in-memory `bytes`, or a readable binary file
object:

```python theme={null}
# in-memory bytes
result = client.transcribe(audio_bytes, model="typeless-1.0-max")

# binary file object
with open("recording.wav", "rb") as audio_file:
    result = client.transcribe(audio_file, model="typeless-1.0-max")

# optional language hint
result = client.transcribe("recording.wav", model="typeless-1.0-max", language="zh")
```

## Async client

```python theme={null}
import asyncio
from typeless import AsyncTypelessClient

async def main() -> None:
    async with AsyncTypelessClient() as client:
        results = await asyncio.gather(
            client.transcribe("a.wav", model="typeless-1.0-max"),
            client.transcribe("b.wav", model="typeless-1.0-max"),
        )
        for result in results:
            print(result.transcript)

asyncio.run(main())
```

## Streaming

Use `stream()` for real-time raw PCM16 audio such as microphone capture. For
offline files, use `transcribe()` instead. See the
[streaming guide](/guides/streaming) for the underlying protocol.

```python theme={null}
from typeless import TypelessClient, AudioReceived, StreamResult
from typeless.exceptions import TypelessError

client = TypelessClient()

with client.stream(model="typeless-1.0-max", sample_rate=16000, channels=1) as conn:
    conn.send(pcm_chunk_bytes)  # raw 16-bit signed little-endian PCM
    conn.finish()

    try:
        for msg in conn:
            if isinstance(msg, AudioReceived):
                print(f"processed {msg.duration_seconds}s")
            elif isinstance(msg, StreamResult):
                print(msg.transcript)
    except TypelessError as exc:
        print(f"stream failed: [{exc.code}] {exc.message}")
```

The SDK sends keep-alive messages automatically while the connection is open.

## Error handling

Every API error maps to a typed exception. See [Errors](/reference/errors) for the
full list of error codes.

```python theme={null}
from typeless.exceptions import (
    AuthenticationError,
    InvalidRequestError,
    RateLimitError,
    InsufficientBalanceError,
    TypelessError,
)

try:
    result = client.transcribe("audio.wav", model="typeless-1.0-max")
except AuthenticationError:
    print("invalid api key")
except RateLimitError as exc:
    print(f"rate limited, retry after {exc.retry_after}s")
except InsufficientBalanceError:
    print("insufficient account balance")
except InvalidRequestError as exc:
    print(f"invalid request: {exc.message}")
except TypelessError as exc:
    print(f"[{exc.code}] {exc.message} (req_id={exc.request_id})")
```

## Configuration

```python theme={null}
client = TypelessClient(
    api_key="tls_sk_...",                       # or TYPELESS_API_KEY
    base_url="https://api.typelessapi.com",     # or TYPELESS_BASE_URL
    timeout=300.0,
    max_retries=3,
)
```

Reuse a single client across requests so the HTTP connection pool can reuse TCP
connections, and close it when done:

```python theme={null}
with TypelessClient() as client:
    result = client.transcribe("audio.wav", model="typeless-1.0-max")
```

## Changelog

### 0.1.0

* HTTP file transcription via `TypelessClient.transcribe()`.
* WebSocket real-time PCM16 streaming via `stream()` with automatic keep-alive.
* `AsyncTypelessClient` mirroring the synchronous API.
* Automatic retry with exponential backoff for transient HTTP failures.
* Structured exception types mapped from API error codes.
* Full type hints and `py.typed` marker (PEP 561).

## Support

Email [hello@typeless.com](mailto:hello@typeless.com) and include the `request_id`
from any failed response.
