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

# Connection pre-warming

Sync STT is a single request/response: your application sends audio to `/transcribe` and gets the transcript back in the same HTTP exchange. That makes connection setup part of your latency budget — if the HTTPS connection isn't open yet, the very first thing your request does is negotiate one, and your audio doesn't start uploading until that negotiation finishes.

The `GET /warm` endpoint exists to take that setup off the critical path. Calling it as soon as you know audio is coming — typically the moment recording starts — establishes the connection in the background, so the eventual `/transcribe` request starts uploading audio immediately.

## What a cold request pays for

Before an HTTPS client can send the first byte of a request to a host it isn't connected to, three things happen in sequence:

1. **DNS resolution** — the client resolves `sync.assemblyai.com` to an IP address. Usually fast (often cached), but a cold resolver lookup adds a round trip of its own.
2. **TCP handshake** — the client and server exchange SYN / SYN-ACK / ACK to open the socket. This costs **one network round trip**.
3. **TLS handshake** — the encrypted session is negotiated on top of the socket. The client sends a `ClientHello` with its supported cipher suites and key share; the server responds with its certificate and its own key share; the client verifies the certificate chain and both sides derive the session keys. On TLS 1.3 this costs **one additional round trip** (TLS 1.2 needs two).

Only after all three complete does the actual `POST /transcribe` — headers, then audio — go on the wire. None of this work depends on your audio; it's pure connection plumbing, but it sits in front of every cold request.

The cost scales directly with your network distance to the endpoint: each step is measured in round trips, so the farther you are from the serving region, the more the handshake costs. For a client near the serving region the total is typically a few tens of milliseconds; for a distant or intercontinental client it can add well over 100 ms — a meaningful fraction of the transcription itself for short clips.

## How `/warm` works

`GET /warm` is an unauthenticated no-op:

```json theme={null}
{ "warm": "toasty" }
```

The response body is irrelevant — the value of the call is entirely on the wire. Making any request forces your HTTP client to resolve DNS, open the TCP socket, and complete the TLS handshake. The resulting connection goes into your client's connection pool, and a `/transcribe` request sent shortly afterward through the **same client** reuses it as-is: no DNS, no TCP handshake, no TLS handshake — the request headers and audio bytes start flowing immediately.

Include the same `X-AAI-Model` header you'll use for transcription, so the warmed path matches the one your `/transcribe` request will take. No API key is required.

## Why "right before" matters

Pooled connections don't live forever:

* **Client-side pool expiry** — HTTP clients evict idle connections from their pool, some aggressively (for example, `httpx` drops idle connections after 5 seconds by default).
* **Server-side idle timeout** — the endpoint closes connections that stay idle for a few minutes.

If the connection has been evicted or closed by the time you call `/transcribe`, the request silently opens a fresh one and pays the full handshake anyway — the warm-up bought nothing.

So the ideal moment to call `/warm` is when you *know* audio is coming but don't have it yet — in a voice application, that's the moment the user starts speaking. The handshake then runs concurrently with recording, and by the time the utterance ends the connection is open and fresh. `/warm` is idempotent and extremely cheap, so calling it again to refresh an aging connection is fine.

<Note>
  Pre-warming only helps if the `/warm` and `/transcribe` requests share a connection pool. Use the same client object (a `requests.Session` in Python, the same process in Node.js) for both calls, and the same base URL — a connection warmed against one [endpoint](/sync-stt/endpoints-and-data-zones) doesn't help a request sent to another.
</Note>

## How to use it

<Tabs>
  <Tab title="Python" language="python">
    ```python theme={null}
    import requests

    session = requests.Session()

    # Call as soon as you know audio is coming (e.g. recording starts).
    # The handshake completes while the audio is still being captured.
    session.get(
        "https://sync.assemblyai.com/warm",
        headers={"X-AAI-Model": "universal-3-5-pro"},
        timeout=10,
    )

    # ... recording finishes ...

    with open("sample.wav", "rb") as f:
        audio = f.read()

    # Same session -> reuses the warmed connection; no handshake here.
    response = session.post(
        "https://sync.assemblyai.com/transcribe",
        headers={
            "Authorization": "<YOUR_API_KEY>",
            "X-AAI-Model": "universal-3-5-pro",
        },
        files={
            "audio": ("sample.wav", audio, "audio/wav"),
        },
        timeout=60,
    )
    response.raise_for_status()
    print(response.json()["text"])
    ```
  </Tab>

  <Tab title="JavaScript" language="javascript">
    ```javascript theme={null}
    import { readFileSync } from "fs";

    // Call as soon as you know audio is coming (e.g. recording starts).
    // Node's fetch keeps the connection alive in its pool by default.
    await fetch("https://sync.assemblyai.com/warm", {
      headers: { "X-AAI-Model": "universal-3-5-pro" },
    });

    // ... recording finishes ...

    const audio = readFileSync("sample.wav");
    const form = new FormData();
    form.append("audio", new Blob([audio], { type: "audio/wav" }), "sample.wav");

    // Same process -> reuses the warmed connection; no handshake here.
    const response = await fetch("https://sync.assemblyai.com/transcribe", {
      method: "POST",
      headers: {
        Authorization: "<YOUR_API_KEY>",
        "X-AAI-Model": "universal-3-5-pro",
      },
      body: form,
    });

    const result = await response.json();
    console.log(result.text);
    ```
  </Tab>

  <Tab title="cURL" language="bash">
    ```bash theme={null}
    # Each curl process opens its own connection, so a separate warm-up call
    # doesn't help a later invocation. Chain both requests in one invocation
    # with --next to share the connection:
    curl https://sync.assemblyai.com/warm \
      -H 'X-AAI-Model: universal-3-5-pro' \
      --next \
      -X POST https://sync.assemblyai.com/transcribe \
      -H 'Authorization: <YOUR_API_KEY>' \
      -H 'X-AAI-Model: universal-3-5-pro' \
      -F 'audio=@sample.wav;type=audio/wav'
    ```
  </Tab>
</Tabs>

<Tip>
  The Python SDK exposes this directly as `SyncTranscriber.warm()` — call it when recording starts, then call `transcribe()` as usual on the same transcriber.
</Tip>
