Realtime ASR
Stream low-latency speech-to-text over WebSocket.
Realtime ASR
Realtime ASR is available through the Open API for live captions, voice input, and meeting transcription.
- WebSocket:
wss://realtime.kittaai.com/v2/stt/live - Subprotocol:
realtime.stt.msgpack.v1 - Model:
kitta-asr-realtime-v1 - Audio: mono PCM16 at 16 kHz; send 3,200-byte chunks every 100 ms
- Maximum session: 600 seconds
- Price: 200 credits for each started minute
Call GET https://realtime.kittaai.com/v2/stt/capabilities for the current contract. The complete
Open API catalog remains available at GET /api/openapi.json.
Server integration
Servers can authenticate during the WebSocket handshake:
Authorization: Bearer KITTA_API_KEYimport { readFile } from 'node:fs/promises';
import WebSocket from 'ws';
const ws = new WebSocket('wss://realtime.kittaai.com/v2/stt/live', 'realtime.stt.msgpack.v1', {
headers: { Authorization: `Bearer ${process.env.KITTA_API_KEY}` },
});
const pcm = await readFile('speech-16khz-mono.pcm');
ws.on('open', () =>
ws.send(
JSON.stringify({
event: 'start',
request: {
model: 'kitta-asr-realtime-v1',
format: 'pcm',
sample_rate: 16000,
language_hints: ['en', 'zh'],
},
}),
),
);
ws.on('message', (raw) => {
const event = JSON.parse(raw.toString());
if (event.event === 'ready') {
for (let offset = 0; offset < pcm.length; offset += 3200)
ws.send(pcm.subarray(offset, offset + 3200));
ws.send(JSON.stringify({ event: 'stop' }));
}
if (event.event === 'transcript_partial') console.log('partial:', event.text);
if (event.event === 'transcript_final') console.log('final:', event.text);
if (event.event === 'usage') console.log('credits:', event.credits_used);
if (event.event === 'error') throw new Error(`${event.code}: ${event.message}`);
});Alternatively, omit the handshake authorization header and send the API key in the first JSON message:
{ "event": "auth", "token": "KITTA_API_KEY" }Browser integration
Never embed a long-lived API key in browser code. Have your backend call
POST https://realtime.kittaai.com/v2/stt/browser-tickets with the API key and the page's
Origin header. The response contains a short-lived, single-use ticket, websocket_url, and
subprotocol. After connecting, the browser sends the ticket in its first auth message, followed
by start, binary PCM audio, and stop.
Events and settlement
The server emits authenticated, ready, transcript_partial, transcript_final, usage, and
finish. Persist only transcript_final events or finish.transcript.
The gateway reserves the first billed minute before starting the provider and reserves each next
minute before accepting its audio. On a normal stop or disconnect, it derives duration from received
PCM bytes, settles credits server-side, and stores the transcript in history. A provider startup
failure refunds the reservation. Insufficient balance returns quota_exceeded.
Use HTTP Speech to Text when you do not need streaming results.