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

# Speech-to-Text quickstart

> Stream audio to Telnyx Speech-to-Text and see live transcripts in under 5 minutes with this end-to-end Python and JavaScript quickstart.

## Prerequisites

* A Telnyx account — [sign up here](https://telnyx.com/sign-up)
* An API key — create one in the [portal](https://portal.telnyx.com/#/app/api-keys)

That's it. No other setup required.

<Tabs>
  <Tab title="WebSocket Streaming">
    Real-time transcription over a persistent connection. Send audio, get partial and final transcripts back as they happen.

    <Tabs>
      <Tab title="Python">
        **Install:**

        ```bash theme={null}
        pip install "websockets>=14"
        ```

        **`main.py`:**

        ```python theme={null}
        import asyncio
        import json
        import urllib.request
        import websockets

        API_KEY = "YOUR_TELNYX_API_KEY"
        STREAM_URL = "https://kexp-mp3-128.streamguys1.com/kexp128.mp3"

        async def transcribe():
            url = (
                "wss://api.telnyx.com/v2/speech-to-text/transcription"
                "?transcription_engine=Deepgram"
                "&model=nova-3"
                "&input_format=mp3"
                "&interim_results=true"
            )
            headers = {"Authorization": f"Bearer {API_KEY}"}

            async with websockets.connect(
                url, additional_headers=headers
            ) as ws:
                # Listen for transcripts
                async def listen():
                    async for message in ws:
                        data = json.loads(message)
                        transcript = data.get("transcript", "")
                        if not transcript:
                            continue
                        prefix = "FINAL" if data.get("is_final") else "partial"
                        print(f"[{prefix}] {transcript}")

                listener = asyncio.create_task(listen())

                # Stream audio from KEXP Radio
                req = urllib.request.urlopen(STREAM_URL)
                try:
                    while chunk := req.read(4096):
                        await ws.send(chunk)
                        await asyncio.sleep(0.05)
                except KeyboardInterrupt:
                    pass

                await ws.send(json.dumps({"type": "CloseStream"}))
                listener.cancel()

        asyncio.run(transcribe())
        ```

        **Run it:**

        ```bash theme={null}
        python main.py
        ```
      </Tab>

      <Tab title="Node.js">
        **Install:**

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

        **`index.js`:**

        ```javascript theme={null}
        const WebSocket = require("ws");
        const https = require("https");

        const API_KEY = "YOUR_TELNYX_API_KEY";
        const STREAM_URL = "https://kexp-mp3-128.streamguys1.com/kexp128.mp3";

        const url = new URL("wss://api.telnyx.com/v2/speech-to-text/transcription");
        url.searchParams.set("transcription_engine", "Deepgram");
        url.searchParams.set("model", "nova-3");
        url.searchParams.set("input_format", "mp3");
        url.searchParams.set("interim_results", "true");

        const ws = new WebSocket(url.toString(), {
          headers: { Authorization: `Bearer ${API_KEY}` },
        });

        ws.on("open", () => {
          console.log("Connected. Streaming KEXP Radio...\n");

          https.get(STREAM_URL, (stream) => {
            stream.on("data", (chunk) => {
              if (ws.readyState === WebSocket.OPEN) {
                ws.send(chunk);
              }
            });
          });
        });

        ws.on("message", (data) => {
          const msg = JSON.parse(data);
          const transcript = msg.transcript || "";
          if (!transcript) return;
          const prefix = msg.is_final ? "FINAL" : "partial";
          console.log(`[${prefix}] ${transcript}`);
        });

        ws.on("error", (err) => console.error("Error:", err.message));
        ```

        **Run it:**

        ```bash theme={null}
        node index.js
        ```
      </Tab>
    </Tabs>

    ### Example output

    ```
    Connected. Streaming KEXP Radio...

    [partial] the latest news from
    [partial] the latest news from the BBC
    [FINAL] The latest news from the KEXP Radio.
    [partial] tensions continue
    [partial] tensions continue to rise in the
    [FINAL] Tensions continue to rise in the region as diplomatic talks stall.
    ```
  </Tab>

  <Tab title="File Upload">
    Upload an audio file and get the full transcript back. The endpoint is OpenAI SDK compatible — swap `base_url` and `api_key` and your existing code works.

    <Tabs>
      <Tab title="Python">
        **Install:**

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

        **`main.py`:**

        ```python theme={null}
        from openai import OpenAI

        client = OpenAI(
            api_key="YOUR_TELNYX_API_KEY",
            base_url="https://api.telnyx.com/v2",
        )

        result = client.audio.transcriptions.create(
            model="openai/whisper-large-v3-turbo",
            file=open("audio.mp3", "rb"),
        )

        print(result.text)
        ```

        **Run it:**

        ```bash theme={null}
        python main.py
        ```
      </Tab>

      <Tab title="Node.js">
        **Install:**

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

        **`index.js`:**

        ```javascript theme={null}
        const OpenAI = require("openai");
        const fs = require("fs");

        const client = new OpenAI({
          apiKey: "YOUR_TELNYX_API_KEY",
          baseURL: "https://api.telnyx.com/v2",
        });

        (async () => {
          const result = await client.audio.transcriptions.create({
            model: "openai/whisper-large-v3-turbo",
            file: fs.createReadStream("audio.mp3"),
          });

          console.log(result.text);
        })();
        ```

        **Run it:**

        ```bash theme={null}
        node index.js
        ```
      </Tab>

      <Tab title="cURL">
        ```bash theme={null}
        curl -X POST https://api.telnyx.com/v2/ai/audio/transcriptions \
          -H "Authorization: Bearer YOUR_TELNYX_API_KEY" \
          -F model="openai/whisper-large-v3-turbo" \
          -F file=@audio.mp3
        ```

        Or transcribe from a URL (no file upload needed):

        ```bash theme={null}
        curl -X POST https://api.telnyx.com/v2/ai/audio/transcriptions \
          -H "Authorization: Bearer YOUR_TELNYX_API_KEY" \
          -F model="openai/whisper-large-v3-turbo" \
          -F file_url="https://example.com/audio.mp3"
        ```
      </Tab>
    </Tabs>

    ### Example response

    ```json theme={null}
    {
      "text": "The latest news from the KEXP Radio. Tensions continue to rise in the region as diplomatic talks stall."
    }
    ```

    For segment- or word-level timestamps, use `model="deepgram/nova-3"` with `response_format=verbose_json`. The Whisper models (`openai/whisper-large-v3-turbo`, `openai/whisper-tiny`) return text only.
  </Tab>
</Tabs>

## What's next

* [Models & Engines](/docs/voice/stt/models) — pick the right engine and model for your use case
* [WebSocket Parameters](/docs/voice/stt/websocket-streaming/parameters) — interim results, keyword boosting, endpointing, redaction
* [REST API Parameters](/docs/voice/stt/rest-api/parameters) — all request body fields for file-based transcription
* [In-Call Transcription](/docs/voice/stt/in-call-transcription) — enable STT during live voice calls
