Text-to-Speech API
Stream text to the Krisp Text-to-Speech WebSocket endpoint and receive synthesized speech as it is generated.
Beta: Text-to-Speech is in beta. Models, messages and limits may change before general availability.
Stream text to Krisp over a WebSocket and receive synthesized speech as it is generated. Audio starts arriving before you finish sending text, which makes it a good fit for voice agents and other low-latency voice output.
See Authentication for how to generate a session token, and the API overview for the session protocol shared by all endpoints.
Try it
Paste an API key from the Developers Portal, pick a language and voice, and press Speak. The demo creates a short-lived session token from your key and streams the text to wss://streaming.krisp.ai/tts. Audio plays as it arrives. Sessions count toward your usage.
Connecting
- URL:
wss://streaming.krisp.ai/tts - Auth: a session token generated from your API key, sent as the
Authorization: api-key SESSION_TOKENheader, or as theauthorizationquery parameter if headers can't be set. Do not send your API key (master token) on the WebSocket. See Authentication for how to generate a session token. - First message: the client hello as a JSON text message, within 15 seconds of connecting. Wait for
readybefore sending text. - Sending text: after
ready, send JSON text messages:
| Message | Meaning |
|---|---|
{"type": "text", "text": "..."} | A piece of text to speak. You can stream a sentence in small pieces (the example clients send 4 words at a time). |
{"type": "end_of_sentence"} | Marks a sentence boundary between two sentences. |
{"type": "end"} | No more text will be sent in this session. |
- Receiving audio: synthesized audio arrives as binary messages. The Krisp example clients play and save these frames as 16-bit mono PCM at 24 kHz.
- Finishing: after
end, wait for theDonemessage, then close the WebSocket.
Output format: TTS audio is always 16-bit mono PCM at 24 kHz.
Client hello
TTSClientHello
TTSClientHelloThe first message sent by the client to initiate a TTS connection.
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
model | string | yes | Model ID: krisp-tts-v1. | |
voice | string | yes | Name of a voice from the Krisp voice registry. | |
language | string | no | en-US | Spoken language of the synthesized audio. |
speed | number | no | the voice's speed | Playback speed multiplier. |
metadata | object | no | User-provided metadata (max 4KB when JSON-encoded) |
Constraints:
modelmust bekrisp-tts-v1(see Supported models).voice, if set, must not be empty.metadatamust not exceed 4,096 bytes when JSON-encoded. It is echoed back inready.
Rules for krisp-tts-v1. The hello is validated as follows:
| Field | Rule |
|---|---|
voice | Required. The name of a voice from the Krisp voice registry (case-insensitive). List the available voices with GET /v2/sdk/tts/voices in the Krisp SDK API. |
language | One of en-US, fr-FR, es-ES, es-US, de-DE, ru-RU (case-insensitive). Default: en-US. The voice must support the language. |
speed | One of 0.9, 0.95, 1.0, 1.05, 1.1. If omitted, the voice's own configured speed is used (1.0 if it has none). |
Example:
{
"model": "krisp-tts-v1",
"voice": "YOUR_VOICE_NAME",
"language": "en-US",
"speed": 1.0,
"metadata": {"call_id": "abc-123"}
}Server messages
TTSGatewayServerHello (ready)
TTSGatewayServerHello (ready)The first response sent by the server to the client. For krisp-tts-v1 it echoes the settings the model applied, which can differ from the request when the model substituted a value.
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
type | string | no | "ready" | Response type |
request_id | string | null | no | null | Request ID if available |
tracks_ms | array of integer | null | no | null | Delays in ms of the decoders producing partial results. Each partial word's src is one of these values. |
voice | string | null | no | null | Applied voice |
language | string | null | no | null | Applied language |
speed | number | null | no | null | Applied speed |
warning | any | null | no | null | Why the applied settings differ from the request |
metadata | object | null | no | null | User-provided metadata, echoed back. Omitted entirely when the service's ClientHello carries no metadata field. |
ErrorResponse (error)
ErrorResponse (error)Error response schema following the standard format.
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
type | string | no | "error" | Response type |
request_id | string | null | no | null | Request ID if available |
error | ErrorInfo | yes | Error information |
ErrorInfo
ErrorInfoError information structure.
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
code | string | yes | Error code identifier | |
status_code | integer | yes | HTTP status code | |
message | string | yes | Human-readable error message | |
details | object | null | no | null | Optional error details (e.g., {'hint': '...'}) |
Synthesis messages
After ready, everything the model sends is forwarded to you unchanged:
| Message | Meaning |
|---|---|
| binary frame | A chunk of synthesized audio. |
{"type": "end_of_sentence", ...} | End-of-sentence marker from the model. |
{"type": "Done", ...} | Synthesis is complete; no more audio follows. |
Supported models
| Model | Notes |
|---|---|
krisp-tts-v1 | Voices come from the Krisp voice registry. voice is required, and language and speed are validated (see Rules for krisp-tts-v1). |
Errors
Besides the common errors, these are specific to /tts:
error.code | status_code | When |
|---|---|---|
invalid_client_hello | 400 | Unknown model, a missing or empty voice, a language that is not in the supported list, an unsupported speed, or metadata larger than 4 KB. details.errors names the field. |
invalid_voice | 400 | The requested voice does not exist. details.hint points to GET /v2/sdk/tts/voices. |
invalid_language | 400 | The language is supported, but the requested voice does not support it. details.hint lists the languages the voice supports. |
internal_server_error | 500 | The voice registry is temporarily unavailable. Retry after a few seconds. |
These errors are sent before ready, and the connection is then closed with close code 1008.
Example
Streams two pieces of text and saves the audio to output.wav. Requires pip install "websockets>=14".
import asyncio
import json
import wave
import websockets
SESSION_TOKEN = "YOUR_SESSION_TOKEN" # see the Authentication page
URL = "wss://streaming.krisp.ai/tts"
async def main() -> None:
headers = {"Authorization": f"api-key {SESSION_TOKEN}"}
async with websockets.connect(URL, additional_headers=headers) as ws:
await ws.send(json.dumps({
"model": "krisp-tts-v1",
"voice": "YOUR_VOICE_NAME",
"language": "en-US",
}))
hello = json.loads(await ws.recv())
if hello["type"] != "ready":
raise RuntimeError(hello)
for piece in ["Hello! This is a streaming ", "text-to-speech test."]:
await ws.send(json.dumps({"type": "text", "text": piece}))
await ws.send(json.dumps({"type": "end"}))
audio = bytearray()
async for message in ws:
if isinstance(message, bytes):
audio.extend(message)
continue
event = json.loads(message)
if event.get("type") == "error":
raise RuntimeError(event)
if event.get("type") == "Done":
break
with wave.open("output.wav", "wb") as wf:
wf.setnchannels(1)
wf.setsampwidth(2)
wf.setframerate(24000)
wf.writeframes(bytes(audio))
asyncio.run(main())Changelog
- 2026-10-01: Authentication now uses a session token; see Authentication.
- 2026-10-01: Public model list limited to
krisp-tts-v1. - 2026-10-01: Page created: client hello with
krisp-tts-v1rules, text and audio messages, supported models.
Updated 2 days ago

