OtherGuides

Migrate WebSocket authentication

How to move from api_key in the start message to sending the key with the connection, with before-and-after code.

What's changing

api_key in the first message (the Speech-to-Text start request or the Text-to-Speech config message) is deprecated. Send the key with the connection instead, in the Authorization header or the protocols list. The old way works until 15 January 2027. From that date a connection that does not send its key with the connection is refused.

See WebSocket authentication for the full description of the new way.


Update your code

Remove api_key from the start message and send the key when you connect.

Add the Authorization header with websockets.

from websockets.sync.client import connect

config = {
    "api_key": api_key,  
    "model": "stt-rt-v5",
    "audio_format": "auto",
}

with connect(SONIOX_WEBSOCKET_URL) as ws:  
with connect(  
    SONIOX_WEBSOCKET_URL,  
    additional_headers={"Authorization": f"Bearer {api_key}"},  
) as ws:  
    ws.send(json.dumps(config))

Add the Authorization header with ws.

import WebSocket from "ws";

const config = {
  api_key: apiKey, 
  model: "stt-rt-v5",
  audio_format: "auto",
};

const ws = new WebSocket(SONIOX_WEBSOCKET_URL); 
const ws = new WebSocket(SONIOX_WEBSOCKET_URL, { 
  headers: { Authorization: `Bearer ${apiKey}` }, 
}); 

ws.on("open", () => {
  ws.send(JSON.stringify(config));
});

Pass soniox-api-key and a temporary API key in the protocols list.

const ws = new WebSocket(url); 
const ws = new WebSocket(url, ["soniox-api-key", temporaryApiKey]); 

ws.onopen = () => {
  ws.send(
    JSON.stringify({
      api_key: temporaryApiKey, 
      model: "stt-rt-v5",
      audio_format: "auto",
    }),
  );
};

On Text-to-Speech the change is the same, only the URL differs: send the key when you connect to wss://tts-rt.soniox.com/tts-websocket and leave api_key out of every config message. See the Text-to-Speech example.


What else changes

The connection is authenticated the moment it opens, which changes these rules:

api_key in the start message (deprecated)Key sent with the connection
Deadline to startSpeech-to-Text: the start request must arrive within 20 seconds of connecting. Text-to-Speech: the first config message must arrive within about 10 seconds. Otherwise the connection is closed with WebSocket status 1001.None. Open the connection early and start when you are ready.
Keepalive before the start messageSpeech-to-Text: not accepted. The first message is read as the start request and rejected with a 400 error frame. Text-to-Speech: does not authenticate the connection.Works. Send one at least every 40 seconds, or the connection is closed as idle with WebSocket status 1001. See connection timeouts.
Connection limitThe connection is counted from its start message. Over the limit, it gets the 429 max_concurrent_connections_reached error frame in response to that message: on Speech-to-Text it is then closed, on Text-to-Speech only that stream is refused.The connection is counted about one second after it opens. Over the limit, it gets the 429 error frame and is closed.
api_key in the start messageRequired.Omit it, or repeat the same key. A different key is refused with a 400 invalid_request error frame: on Speech-to-Text the connection is then closed, on Text-to-Speech only that stream is refused and the connection stays open.
Temporary keysA key in the older temp: format works. On Text-to-Speech, a fresh single-use key in each config message works.Keys that start with snx_temp_ work in the Authorization header and in the protocols list. A temp: key works only in the Authorization header. A single-use key allows one stream on the connection.

After 15 January 2027

A connection that does not send its key with the connection is refused with a 401 unauthenticated error frame and closed:

{
  "error_code": 401,
  "error_type": "unauthenticated",
  "error_message": "Missing API key. Send it with the connection: the Authorization header \"Bearer <api_key>\", or soniox-api-key and the key in the WebSocket protocols list."
}

If you see this error, go to Update your code.