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

# Quick Start

> Get started with KugelAudio in under 5 minutes

## Prerequisites

Before you begin, make sure you have:

* An API key from [kugelaudio.com](https://kugelaudio.com)
* Python 3.9+, Node.js 18+, Java 17+, or cURL

## Installation

<Tabs>
  <Tab title="Python">
    Install the Python SDK using pip or uv:

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

    Or with uv (recommended):

    ```bash theme={null}
    uv add kugelaudio
    ```
  </Tab>

  <Tab title="JavaScript/TypeScript">
    Install the JavaScript SDK using your preferred package manager:

    ```bash theme={null}
    npm install kugelaudio
    ```

    Or with yarn/pnpm:

    ```bash theme={null}
    yarn add kugelaudio
    # or
    pnpm add kugelaudio
    ```
  </Tab>

  <Tab title="Java">
    Add the dependency to your `pom.xml` (requires Java 17+):

    ```xml theme={null}
    <dependency>
      <groupId>com.kugelaudio</groupId>
      <artifactId>kugelaudio</artifactId>
      <version>0.1.0</version>
    </dependency>
    ```

    Or with Gradle:

    ```groovy theme={null}
    implementation 'com.kugelaudio:kugelaudio:0.1.0'
    ```
  </Tab>

  <Tab title="cURL">
    cURL comes pre-installed on macOS, Linux, and Windows 10+. No installation needed.

    Set your API key as an environment variable:

    ```bash theme={null}
    export KUGELAUDIO_API_KEY="your_api_key"
    ```
  </Tab>
</Tabs>

## Basic Usage

### Initialize the Client

<Tip>
  **Pre-connect at startup.** Without `client.connect()`, the first TTS request pays the WebSocket handshake; subsequent requests reuse the connection. Pre-connecting moves the handshake cost to application startup, where it doesn't affect user-perceived latency. See [Latency](/latency) for the numbers.
</Tip>

<Tabs>
  <Tab title="Python">
    ```python theme={null}
    from kugelaudio import KugelAudio

    # Initialize with your API key
    client = KugelAudio(api_key="your_api_key")

    # Pre-connect at startup (handshake happens here)
    client.connect()

    # Confirm connection is ready
    print(f"Connected: {client.is_connected()}")

    # First request is now fast — no handshake on the hot path
    ```
  </Tab>

  <Tab title="JavaScript">
    ```typescript theme={null}
    import { KugelAudio } from 'kugelaudio';

    // Initialize with your API key
    const client = new KugelAudio({ apiKey: 'your_api_key' });

    // Pre-connect at startup (handshake happens here)
    await client.connect();

    // Confirm connection is ready
    console.log(`Connected: ${client.isConnected()}`);

    // First request is now fast — no handshake on the hot path
    ```
  </Tab>

  <Tab title="Java">
    ```java theme={null}
    import com.kugelaudio.sdk.KugelAudio;
    import com.kugelaudio.sdk.KugelAudioOptions;

    KugelAudio client = new KugelAudio(
        KugelAudioOptions.builder("your_api_key").build()
    );

    // Pre-connect at startup (handshake happens here)
    client.connect();

    // Confirm connection is ready
    System.out.println("Connected: " + client.isConnected());

    // First request is now fast — no handshake on the hot path
    ```
  </Tab>

  <Tab title="cURL">
    No client initialization needed — just pass the API key in the `Authorization` header:

    ```bash theme={null}
    curl https://api.kugelaudio.com/v1/models \
      -H "Authorization: Bearer $KUGELAUDIO_API_KEY"
    ```
  </Tab>
</Tabs>

### Generate Speech

<Tip>
  Examples below use `kugel-3`, the canonical production model. Legacy IDs such as `kugel-2.5` and `kugel-2-turbo` are still accepted for backwards compatibility; see [Models](/models) for details.
</Tip>

<Tabs>
  <Tab title="Python">
    ```python theme={null}
    # Generate speech
    audio = client.tts.generate(
        text="Welcome to KugelAudio! This is high-quality text-to-speech.",
        model_id="kugel-3",
    )

    # Save to file
    audio.save("output.wav")

    # Or get the raw bytes
    wav_bytes = audio.to_wav_bytes()
    ```
  </Tab>

  <Tab title="JavaScript">
    ```typescript theme={null}
    // Generate speech
    const audio = await client.tts.generate({
      text: 'Welcome to KugelAudio! This is high-quality text-to-speech.',
      modelId: 'kugel-3',
    });

    // audio.audio is an ArrayBuffer with PCM16 data
    console.log(`Duration: ${audio.durationMs}ms`);
    ```
  </Tab>

  <Tab title="Java">
    ```java theme={null}
    import com.kugelaudio.sdk.GenerateRequest;
    import com.kugelaudio.sdk.AudioResponse;

    AudioResponse audio = client.tts().generate(
        GenerateRequest.builder("Welcome to KugelAudio! This is high-quality text-to-speech.")
            .modelId("kugel-3")
            .language("en")
            .build()
    );

    // Save to file
    audio.saveWav(java.nio.file.Path.of("output.wav"));
    ```
  </Tab>

  <Tab title="cURL">
    ```bash theme={null}
    curl -X POST https://api.kugelaudio.com/v1/tts/generate \
      -H "Authorization: Bearer $KUGELAUDIO_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{
        "text": "Welcome to KugelAudio! This is high-quality text-to-speech.",
        "model_id": "kugel-3"
      }' \
      --output output.pcm

    # Convert to WAV for playback
    ffmpeg -f s16le -ar 24000 -ac 1 -i output.pcm output.wav
    ```
  </Tab>
</Tabs>

### Stream Audio

For lower latency, stream audio chunks as they're generated:

<Tabs>
  <Tab title="Python">
    ```python theme={null}
    # Synchronous streaming
    for chunk in client.tts.stream(
        text="Hello, this is streaming audio.",
        model_id="kugel-3",
    ):
        if hasattr(chunk, 'audio'):
            # Process audio chunk immediately
            print(f"Chunk {chunk.index}: {len(chunk.audio)} bytes")
            # play_audio(chunk.audio)
    ```

    For async applications:

    ```python theme={null}
    import asyncio

    async def stream_audio():
        async for chunk in client.tts.stream_async(
            text="Async streaming example.",
            model_id="kugel-3",
        ):
            if hasattr(chunk, 'audio'):
                # Process chunk
                pass

    asyncio.run(stream_audio())
    ```
  </Tab>

  <Tab title="JavaScript">
    ```typescript theme={null}
    await client.tts.stream(
      {
        text: 'Hello, this is streaming audio.',
        modelId: 'kugel-3',
      },
      {
        onChunk: (chunk) => {
          console.log(`Chunk ${chunk.index}: ${chunk.samples} samples`);
          // Play or process the audio chunk
        },
        onFinal: (stats) => {
          console.log(`Total duration: ${stats.durationMs}ms`);
          console.log(`Generation time: ${stats.generationMs}ms`);
        },
      }
    );
    ```
  </Tab>

  <Tab title="Java">
    ```java theme={null}
    import com.kugelaudio.sdk.StreamCallbacks;
    import com.kugelaudio.sdk.AudioChunk;

    client.tts().stream(
        GenerateRequest.builder("Hello, this is streaming audio.")
            .modelId("kugel-3")
            .language("en")
            .build(),
        new StreamCallbacks() {
            @Override
            public void onChunk(AudioChunk chunk) {
                System.out.printf("Chunk %d: %d bytes%n",
                    chunk.getIndex(), chunk.getAudio().length);
                // playAudio(chunk.getAudio());
            }
        }
    );
    ```
  </Tab>

  <Tab title="cURL">
    The REST endpoint streams raw PCM bytes — pipe directly to `ffplay` for real-time playback:

    ```bash theme={null}
    curl -X POST https://api.kugelaudio.com/v1/tts/generate \
      -H "Authorization: Bearer $KUGELAUDIO_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{
        "text": "Hello, this is streaming audio.",
        "model_id": "kugel-3"
      }' \
      --no-buffer | ffplay -f s16le -ar 24000 -ac 1 -nodisp -
    ```

    <Note>
      For advanced streaming (WebSocket-based, token-by-token from LLMs), use the
      [Python, JavaScript, or Java SDK](/streaming/overview) or the
      [raw WebSocket API](/api-reference/raw-api).
    </Note>
  </Tab>
</Tabs>

## Working with Voices

<Tip>
  **Pick your voice deliberately.** Different voices have wildly different baseline energy, age, and warmth — a peppy DTC bot and a calm clinical agent should not share the same voice even with the same prompt. Listen to several before locking one in. Building an LLM-driven voice agent? See [Voice Agent Prompting](/guides/voice-prompting) for the prompt patterns that matter most.
</Tip>

### List Available Voices

<Tabs>
  <Tab title="Python">
    ```python theme={null}
    # List all voices
    result = client.voices.list()

    for voice in result.voices:
        print(f"{voice.id}: {voice.name}")
        print(f"  Languages: {', '.join(voice.supported_languages)}")
    print(f"Total: {result.total}")

    # Filter by language
    result = client.voices.list(language="de")
    ```
  </Tab>

  <Tab title="JavaScript">
    ```typescript theme={null}
    // List all voices
    const result = await client.voices.list();

    for (const voice of result.voices) {
      console.log(`${voice.id}: ${voice.name}`);
      console.log(`  Languages: ${voice.supportedLanguages.join(', ')}`);
    }
    console.log(`Total: ${result.total}`);

    // Filter by language
    const germanVoices = await client.voices.list({ language: 'de' });
    ```
  </Tab>

  <Tab title="Java">
    ```java theme={null}
    import com.kugelaudio.sdk.Voice;
    import com.kugelaudio.sdk.VoiceListResponse;

    VoiceListResponse result = client.voices().list();
    for (Voice voice : result.getVoices()) {
        System.out.printf("%d: %s%n", voice.getId(), voice.getName());
    }
    System.out.printf("Total: %d%n", result.getTotal());

    // Filter by language
    VoiceListResponse germanVoices = client.voices().list("de", null, null, null);
    ```
  </Tab>

  <Tab title="cURL">
    ```bash theme={null}
    # List all voices
    curl https://api.kugelaudio.com/v1/voices \
      -H "Authorization: Bearer $KUGELAUDIO_API_KEY"

    # Filter by language
    curl "https://api.kugelaudio.com/v1/voices?language=de" \
      -H "Authorization: Bearer $KUGELAUDIO_API_KEY"
    ```
  </Tab>
</Tabs>

### Use a Specific Voice

<Tabs>
  <Tab title="Python">
    ```python theme={null}
    audio = client.tts.generate(
        text="Hello with a specific voice!",
        model_id="kugel-3",
        voice_id=1071,  # Use a specific voice ID
    )
    ```
  </Tab>

  <Tab title="JavaScript">
    ```typescript theme={null}
    const audio = await client.tts.generate({
      text: 'Hello with a specific voice!',
      modelId: 'kugel-3',
      voiceId: 1071,  // Use a specific voice ID
    });
    ```
  </Tab>

  <Tab title="Java">
    ```java theme={null}
    AudioResponse audio = client.tts().generate(
        GenerateRequest.builder("Hello with a specific voice!")
            .modelId("kugel-3")
            .voiceId(1071)
            .language("en")
            .build()
    );
    ```
  </Tab>

  <Tab title="cURL">
    ```bash theme={null}
    curl -X POST https://api.kugelaudio.com/v1/tts/generate \
      -H "Authorization: Bearer $KUGELAUDIO_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{
        "text": "Hello with a specific voice!",
        "model_id": "kugel-3",
        "voice_id": 1071
      }' \
      --output output.pcm
    ```
  </Tab>
</Tabs>

## Next Steps

<CardGroup cols={2}>
  <Card title="Generate Speech" icon="play" href="/features/generate">
    All generation options and parameters
  </Card>

  <Card title="Streaming" icon="wave-pulse" href="/streaming/overview">
    Real-time audio streaming techniques
  </Card>

  <Card title="Using Voices" icon="microphone" href="/features/voices">
    Browse and filter available voices
  </Card>

  <Card title="Text Processing" icon="spell-check" href="/features/text-processing">
    Normalization and spell tags
  </Card>
</CardGroup>
