Docs / Live API / Client secrets

Live API

Client secrets

A client secret lets a browser open one Live session without your API key. Create it on your server, then pass its value to the browser.

Create a client secret

POST
https://api.dotwave.ai/v1/live/client_secretsAuthenticate with your API key.
curl https://api.dotwave.ai/v1/live/client_secrets \
  -H "Authorization: Bearer $DOTWAVE_API_KEY" \
  -H "Content-Type: application/json" \
  --data '{
    "expires_after": {"anchor": "created_at", "seconds": 60},
    "session": {
      "type": "live",
      "model": "nemotron-voicechat",
      "audio": {
        "input": {"format": {"type": "audio/pcm", "rate": 24000}},
        "output": {
          "format": {"type": "audio/pcm", "rate": 24000},
          "encoding": "base64"
        }
      }
    }
  }'
expires_after.seconds
How long the secret stays valid: 60 by default, 600 at most. expires_after.anchor is created_at.
session.type
live.
session.model
The model the session opens, such as nemotron-voicechat.
session.audio
The audio formats, 24 kHz PCM16 in and out, and the output encoding, base64 or binary.
metadata
Your own string keys, kept with the session’s record: up to 16, and 512 bytes in all.

The response

{"value": "…", "expires_at": 1790000000,
 "session": {"id": "sess_…", "type": "live", "model": "nemotron-voicechat",
             "live_url": "wss://api.dotwave.ai/v1/live/sessions"}}
value
The secret. Give only this to the browser.
expires_at
When the secret expires, in Unix seconds.
session.id
The session the secret opens. Look it up later with GET /v1/sessions/{session_id}.
session.live_url
The socket to open.

Connect from a browser

Browsers cannot set headers on a WebSocket, so pass the secret as the token query parameter. The browser still sends session.start first. A client that can set headers sends Authorization: Bearer <value> instead.

// `secret` is the `value` and `liveUrl` the `session.live_url`
// your server received.
const ws = new WebSocket(`${liveUrl}?token=${encodeURIComponent(secret)}`);

ws.onopen = () => {
  // session.start must be the first event, or the socket refuses it.
  ws.send(JSON.stringify({
    type: 'session.start',
    session: { model: 'nemotron-voicechat' },
  }));
};

ws.onmessage = ({ data }) => {
  const event = JSON.parse(data);
  if (event.type === 'session.output_audio.delta') play(event.delta);
};

A secret opens one session. An unused secret counts toward your concurrency limit until it expires, so create it just before the browser connects.

Errors

Refusals use the error envelope. A field the model does not support, such as custom instructions or tools, is refused with 400 invalid_parameter. At zero credit, the call returns 403 insufficient_credit. Past your project’s limits it returns 429, and when the model is at capacity 503, both with Retry-After.