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

# Text to Speech (WebSocket)

> Real-time streaming TTS via WebSocket for low-latency voice applications.

## Overview

The WebSocket endpoint enables real-time audio streaming with low-latency. Unlike the REST API, audio chunks are delivered as they're generated, making it ideal for:

* Live voice assistants
* Real-time call center applications
* Interactive voice response (IVR) systems
* Any application requiring immediate audio feedback

## Authentication

Pass your API key in the `Authorization` header as a Bearer token when establishing the WebSocket connection.

<CodeGroup>
  ```javascript JavaScript theme={null}
  const ws = new WebSocket('wss://api.tts.timepay.ai/api/v1/get_speech', {
    headers: {
      'Authorization': 'Bearer YOUR_API_KEY'
    }
  });
  ```
</CodeGroup>

<Warning>
  Always use `wss://` (secure WebSocket) in production environments.
</Warning>

## Concurrency Model

<Info>
  Users can open **multiple connections**. The concurrency limit only applies when actively processing speech requests.
</Info>

For example, if your plan allows 5 concurrent requests:

* You can maintain 10 open connections
* Only 5 can generate speech simultaneously
* Additional requests will throw 429 rate limit error

## Request Format

<ParamField body="type" type="string" required>
  Must be `"speech"` for TTS requests.
</ParamField>

<ParamField body="text" type="string" required>
  The text to convert to speech.
</ParamField>

<ParamField body="voice_id" type="string" required>
  The specific voice ID to use for synthesis. See available voices below.
</ParamField>

<ParamField body="language" type="string" default="en">
  ISO language code for the speech output.

  **Supported languages:** `en`, `hi`, `mr`, `ta`, `te`, `gu`, `kn`, `ml`, `bn`, `pa`, `od`, `as`
</ParamField>

<ParamField body="add_wav_header" type="boolean" default={true}>
  If `true`, adds a WAV header to the audio stream for immediate playback.
</ParamField>

<ParamField body="sample_rate" type="number" default={24000}>
  Audio sample rate in Hz.

  **Supported values:** `8000`, `16000`, `24000`
</ParamField>

<ParamField body="speed" type="number" default={1.0}>
  Playback speed multiplier. Range: `0.5` to `2.0`, where `1.0` is normal speed.
</ParamField>

<ParamField body="request_id" type="string">
  Optional custom identifier for tracking requests. Auto-generated if not provided.
</ParamField>

### Available Voices

| Voice Name | Voice ID               |
| ---------- | ---------------------- |
| Kartik     | `Ogbs15oBevLzXsUuTtA1` |
| Rahul      | `Owbs15oBevLzXsUurdA_` |
| Nisha      | `PAbs15oBevLzXsUu4dCi` |
| Tulsi      | `PQbt15oBevLzXsUuNtD3` |
| Seema      | `Pgbt15oBevLzXsUubdA6` |

```json Example Request theme={null}
{
  "type": "speech",
  "request_id": "req_12345",
  "text": "Hello, welcome to Vox.",
  "voice_id": "Ogbs15oBevLzXsUuTtA1",
  "language": "en",
  "add_wav_header": true,
  "sample_rate": 24000,
  "speed": 1.0
}
```

```json Minimal Request theme={null}
{
  "type": "speech",
  "text": "Hello, welcome to Vox.",
  "voice_id": "PAbs15oBevLzXsUu4dCi"
}
```

## Response Messages

The server sends multiple message types during a speech generation request:

### Connection Established

Sent immediately after successful authentication.

<ResponseField name="type" type="string">
  Always `"connected"`
</ResponseField>

<ResponseField name="connection_id" type="string">
  Unique identifier for this WebSocket connection.
</ResponseField>

```json theme={null}
{
  "type": "connected",
  "connection_id": "conn_abc123",
  "message": "Connected successfully"
}
```

### Audio Chunks

Streamed audio data. Multiple chunks are sent per request.

<ResponseField name="type" type="string">
  Always `"audio_chunk"`
</ResponseField>

<ResponseField name="request_id" type="string">
  The request identifier.
</ResponseField>

<ResponseField name="chunk_index" type="integer">
  Zero-indexed position in the audio stream.
</ResponseField>

<ResponseField name="data" type="string">
  Base64-encoded audio data (PCM 16-bit, 24kHz mono by default).
</ResponseField>

```json theme={null}
{
  "type": "audio_chunk",
  "request_id": "req_12345",
  "chunk_index": 0,
  "data": "UklGRiQAAABXQVZFZm10IBAAAAABAAEAQB8AAEAfAAABAAgA..."
}
```

### Request Complete

Signals all audio has been sent.

<ResponseField name="type" type="string">
  Always `"complete"`
</ResponseField>

<ResponseField name="request_id" type="string">
  The request identifier.
</ResponseField>

<ResponseField name="total_chunks" type="integer">
  Total number of audio chunks sent.
</ResponseField>

<ResponseField name="characters" type="integer">
  Characters processed (for billing verification).
</ResponseField>

```json theme={null}
{
  "type": "complete",
  "request_id": "req_12345",
  "total_chunks": 15,
  "characters": 47
}
```

### Error

Indicates a problem with the request.

<ResponseField name="type" type="string">
  Always `"error"`
</ResponseField>

<ResponseField name="request_id" type="string">
  The request identifier (if available).
</ResponseField>

<ResponseField name="error" type="string">
  Error code for programmatic handling.
</ResponseField>

<ResponseField name="message" type="string">
  Human-readable error description.
</ResponseField>

```json theme={null}
{
  "type": "error",
  "request_id": "req_12345",
  "error": "concurrency_limit_exceeded",
  "message": "Maximum concurrent requests (5) exceeded"
}
```

#### Error Codes

| Code                         | Description                               |
| ---------------------------- | ----------------------------------------- |
| `invalid_request`            | Malformed JSON or missing required fields |
| `invalid_voice`              | Specified voice not found                 |
| `invalid_language`           | Unsupported language code                 |
| `text_too_long`              | Text exceeds maximum character limit      |
| `concurrency_limit_exceeded` | Too many simultaneous requests            |
| `insufficient_credits`       | Account balance too low                   |
| `internal_error`             | Server-side processing error              |

## Complete Example

<CodeGroup>
  ```python Python theme={null}
  import websockets

  async def connect():
      headers = {
          'Authorization': 'Bearer YOUR_API_KEY'
      }
      async with websockets.connect(
          'wss://api.tts.timepay.ai/api/v1/get_speech',
          extra_headers=headers
      ) as ws:
          # Your code here
          pass
  ```

  ```javascript Node.js theme={null}
  const WebSocket = require('ws');

  const ws = new WebSocket('wss://api.tts.timepay.ai/api/v1/get_speech', {
    headers: {
      'Authorization': 'Bearer YOUR_API_KEY'
    }
  });
  ```
</CodeGroup>

## Best Practices

<AccordionGroup>
  <Accordion title="Connection Management">
    * Reuse WebSocket connections for multiple requests
    * Implement automatic reconnection with exponential backoff
    * Send periodic pings to keep connections alive (every 30 seconds)
    * Close connections gracefully when no longer needed
  </Accordion>

  <Accordion title="Audio Handling">
    * Buffer audio chunks before playback for smoother experience
    * Default audio format: PCM 16-bit, 24kHz, mono
    * Use Web Audio API for browser playback
    * Consider using a streaming audio player for real-time playback
  </Accordion>

  <Accordion title="Error Handling">
    * Always handle the `error` message type
    * Implement request timeouts (recommended: 30 seconds)
    * Queue requests when concurrency limit is reached
    * Log `request_id` for debugging and support
  </Accordion>
</AccordionGroup>
