Skip to navigation

Authentication and limits

Both speech APIs authenticate with an API key issued by HAMS. Send it as a bearer token in the WebSocket upgrade request, before any message:

GET /asr/ws HTTP/1.1
Host: voice.hams.ai
Upgrade: websocket
Connection: Upgrade
Authorization: Bearer YOUR_API_KEY

With the Python websockets package that is one argument on connect:

headers = {"Authorization": f"Bearer {os.environ['HAMS_STT_API_KEY']}"}
async with websockets.connect("wss://voice.hams.ai/asr/ws", additional_headers=headers) as ws:
...

websockets 12 and 13 call the argument extra_headers; 14 and later call it additional_headers. The examples in these docs use the newer name.

Keys are issued per service, so keep separate keys for speech-to-text and text-to-speech. Missing or invalid credentials are rejected during the handshake with 401.

Connection limit

A credential may hold up to five simultaneous WebSocket connections. Speech-to-text rejects a sixth handshake with 429; text-to-speech completes the handshake and immediately closes the socket with close code 1013 (Server at capacity). Use one connection per active stream or session, keep it open for the whole stream instead of reconnecting per message, and close it as soon as the stream ends so the slot is free for the next one.

Status codes

StatusMeaningWhat to do
HTTP 401The API key is missing or invalidFix the key; do not retry
HTTP 429Speech-to-text: five connections are already active for this credentialWait until one of them closes, then connect again
Close code 1013Text-to-speech: five connections are already activeWait until one of them closes, then connect again
HTTP 502 or 503The service is temporarily unavailableRetry with exponential backoff and jitter

Reconnect after transient failures with exponential backoff and jitter. When a connection drops mid-stream, open a new one and resume: for speech-to-text, resend audio from the last final result; for text-to-speech, resend the prompt that was in flight.

Keeping the key safe

The key must stay on a trusted server:

  • Store it in a secret manager or a protected environment variable.
  • Never commit it to source control.
  • Never put it in a URL, including the WebSocket URL.
  • Never ship it to browsers or mobile applications; if a client-side framework cannot set the header, connect from a server-side service instead.
  • Keep it out of client-side logs.

Contact HAMS to rotate a lost or exposed key.