Skip to navigation

API reference corrections for speech-to-text and text-to-speech

Several API reference pages described behaviour the API doesn’t have. They now match it.

Speech to text

  • Pulse Pro accepts audio by URL: send {"url": "…"} with Content-Type: application/json, the same as Pulse.
  • Webhook mode (webhook_url) works with pulse as well as pulse-pro.
  • Pulse Pro caps audio at 250 MB, or 50 MB with webhook_url, whether uploaded or fetched from a URL. Larger audio returns 413.
  • On the realtime WebSocket, model is optional and defaults to pulse; an invalid value returns 400 during the handshake.

Electron errors use one envelope, streams end with an error event

Electron chat completion errors that used to return {"error": "<message>"} now return the OpenAI-style object {"error": {"message", "type", "param", "code", "request_id"}}. This covers rate-limit and concurrency 429s, 403, credits-exhausted 400, 500 and 503. The OpenAI SDKs handle both; code that reads error as a string needs updating.

What changed

Electron running usage on every streamed chunk

Electron chat completions accept stream_options.continuous_usage_stats. With include_usage: true, every streamed chunk carries a usage block with the token counts so far, not just the last one. It has no effect without include_usage.

{ "stream_options": { "include_usage": true, "continuous_usage_stats": true } }

Text-to-Speech: Lightning v3.1 Pro checkpoint `lightning_v3.1_pro_10_26` in preview

A new Lightning v3.1 Pro checkpoint for English (en), Spanish with English code-switching (es) and Hindi with English code-switching (hi) is in preview until 2026-11-28. Try it by passing "model": "lightning_v3.1_pro_10_26" on any TTS endpoint. Every Pro voice works on it.

Only English, Spanish and Hindi change on 2026-11-28. On that date, the preview becomes the stable lightning_v3.1_pro for those three languages, including requests that omit language, so use "model": "lightning_v3.1_pro" from then on. lightning_v3.1_pro_10_26 remains available for 30 more days, until 2026-12-28. The other 28 languages and auto stay on their current checkpoints. The scheduled change is listed on Deprecation Notices.

Diarization benchmarks: independent VoiceArena verification added

The Diarization benchmarks page now includes independent, third-party results from VoiceArena’s Diarization Bench:

  • Pulse ranks #1 in the “with ASR” system-type category at 24.36% DER, ahead of Mistral Voxtral Mini Transcribe 3 (40.41%), ElevenLabs Scribe v2 (40.71%), and Deepgram Nova-3 (67.13%).
  • Scored on the same 139 human-verified English sessions (~22 hours) as every other system on the board, DIHARD scoring at a 0 ms collar.
  • Per-condition breakdown (in-person vs. online, speaker count, overlap) included alongside our existing internal DER benchmarks.

Short-lived access tokens now work in every region

Short-lived access tokens are now minted by POST https://api.smallest.ai/console/v1/auth/token, and one token works in every region: api.smallest.ai, api.india.smallest.ai (Mumbai) and api.us.smallest.ai (Oregon). Before, a token worked only in the region that minted it, so a client routed to another region got 401.

The request body, the 201 response, the 30 to 900 second TTL and the routes a token can call are unchanged. Clients still send the token as Authorization: Bearer <token>, or as the api_key query parameter on WebSocket connections.

STT: automatic language detection with `language=auto` (beta)

Pulse pre-recorded STT accepts language=auto. The spoken language is detected from a few short samples of the audio, and the file is transcribed with that language’s model.

The response adds detected_language, language_confidence and mixed_language_detected. One language is chosen per file; if a file mixes languages served by different models, the dominant one is used and mixed_language_detected is true.

Electron latency guide and `prompt_cache_key`

Electron chat completions accept prompt_cache_key, a string that groups the requests of one conversation so every turn reuses the cache. Create one key per conversation, send it on every turn, and never share it between conversations.

What changed

  • New Optimizing Latency guide: one prompt_cache_key per conversation, static content first, append-only history, streaming, and one reused client.
  • prompt_cache_key added to the chat completions API reference and the Supported Parameters page.
  • Prefix Caching and Best Practices link to the new guide.

Short-lived access tokens for TTS, STT and speech-to-speech

Browser and mobile clients no longer need your API key. Your server calls POST /waves/v1/auth/token with the key and gets back a short-lived access token (prefix wat_, 30 to 900 seconds, default 300). The client sends that token as Authorization: Bearer <token>, or as the api_key query parameter on WebSocket connections.

Tokens work on TTS, STT and speech-to-speech inference routes only: POST /waves/v1/stt/, POST /waves/v1/tts, POST /waves/v1/tts/live, the dedicated Lightning v3.1 routes, the TTS, STT and speech-to-speech WebSockets, and the voice-listing routes. Treat any route outside that list as unavailable to tokens. POST /waves/v1/pulse/get_text, LLM chat completions, voice cloning and minting another token return 403. Usage is billed to the key that minted the token.

Zero Data Retention page, and the expiry header on Electron

Enterprise plans only. A new Zero Data Retention page, in the Enterprise section of the Models tab, covers the three ways to limit how long request content is kept. Zero retention never stores content. A retention window, 24 hours to 90 days, stops content being retained once it ends. The per-request header x-expire-content: true gives a single request a 7 day window. The first two are set on your organization and need no code change. The usage row is kept in all three. On other plans the header is ignored and the request is processed normally.

WebSocket keep-alive frame is now documented

Every Waves WebSocket - Pulse STT and Lightning TTS - accepts an application-level keep-alive frame. Send {"type": "ping"} and the server resets the inactivity timer and replies {"type": "pong"}. keepalive, keep_alive, and keep-alive work as aliases.

The frame is handled at the API edge: it never reaches the model, does not affect the transcript or the synthesized audio, and carries no audio, so it is not billed.

Docs: fix five stale internal links after slug renames

Five internal links in the Models docs now point at the correct pages:

  • Electron model card API-reference link (electron-chat-completions)
  • LLM overview + quickstart migrate-from-openai link
  • Pulse STT realtime features age-and-gender-detection link
  • Lightning v3.1 Pro model card voice-cloning/how-to-vc-api link

Speech-to-Speech: Hydra V1.1 released, `?model=hydra` deprecated

Hydra V1.1 is the current release of the realtime speech-to-speech model. New integrations should connect with ?model=hydra-v1.1:

wss://api.smallest.ai/waves/v1/s2s?model=hydra-v1.1&api_key=<SMALLEST_API_KEY>

The session protocol (event catalog, session.configure shape, tool calling, interruption handling) is identical to the original hydra, so switching is a one-parameter change on the query string.

Pulse STT realtime overview: VAD Events, Endpointing, Age & Gender, and Emotion Detection cards

The Realtime features overview now surfaces four capabilities that had dedicated feature pages but were missing from the overview:

  • VAD Events. Acoustic speech_started / speech_ended frames interleaved with the transcription stream.
  • Endpointing. Tune the end-of-utterance silence timeout with eou_timeout_ms.
  • Age & Gender Detection. Optional per-speaker inference alongside the transcript.
  • Emotion Detection. Optional per-utterance classification alongside the transcript.

STT: new language `hi-dev` (Devanagari-only Hindi)

Pulse STT streaming supports a new Hindi language code, hi-dev, that transcribes Hindi audio using a pure-Hindi model and writes everything in Devanagari.

The existing hi code stays as the bilingual model: it transcribes Hindi speech but renders borrowed English words in Roman script, producing mixed-script output like मेरी email आईडी पर invoice भेज दीजिए.

Speech to Text: VAD events on the live WebSocket API reference

The Pulse STT live WebSocket now models the acoustic voice-activity events in the API reference: speech_started and speech_ended, emitted alongside transcription messages when the connection sets vad_events=true. See VAD events for the payloads and usage.

The events have been in production; this documents them on the WebSocket reference.

Waves: analytics endpoints on the API reference

Nine previously undocumented Waves analytics endpoints now render on the API reference under a new Analytics section:

  • GET /waves/v1/analytics/asr/logs: paginated STT request log
  • DELETE /waves/v1/analytics/asr/history/{request_id}: soft-delete a single STT entry
  • GET /waves/v1/analytics/asr/usage/timeseries: STT request count over time
  • GET /waves/v1/analytics/tts/logs: paginated TTS request log
  • GET /waves/v1/analytics/tts/usage/timeseries: TTS request count over time
  • GET /waves/v1/analytics/tts/usage/credits/timeseries: TTS credit spend over time
  • GET /waves/v1/analytics/tts/concurrency/timeseries: TTS peak concurrency over time
  • GET /waves/v1/analytics/tts/ws-connections/timeseries: open TTS WebSocket count over time
  • GET /waves/v1/analytics/webhooks/logs: webhook delivery log (e.g. asr.completed callbacks)

Speech: Post-Call Analysis and voice catalog endpoints on the API reference

Three previously undocumented Speech endpoints now render on the API reference:

Post-Call Analysis

  • POST /waves/v1/pca: extract disposition metrics (BOOLEAN, ENUM, INTEGER, STRING, SUMMARY) from a transcript, each with a value, confidence, and the transcript evidence
  • POST /waves/v1/pca/generate: single-prompt text generation (text in, text out)

STT API-ref: response examples now match the real API

Follow-up to yesterday’s word_timestamps clarification. That PR fixed the description but the response schema itself still drifted from what the live API returns. Postman side-by-side surfaced it.

Corrected on both endpoint schemas (/waves/v1/stt/ and legacy /waves/v1/pulse/get_text):

  • speaker is an integer, not a string. Real responses carry speaker: 0 (zero-indexed), not speaker: "speaker_0".
  • speaker_confidence field added to word entries. Present alongside speaker when diarize=true is set on Pulse.
  • Pulse metadata is {duration, fileSize} only. The old example claimed language, request_id, processing_time_ms, rtfx, and num_chunks on a Pulse response; those are Pulse Pro only.
  • Pulse Pro includes totalBytes, request_id, and language at the top level and richer metadata (processing_time_ms, rtfx, num_chunks). Also does not diarize, so words[] entries omit speaker and speaker_confidence, and there is no utterances[] field.
  • duration is seconds, not minutes. Description on the legacy Pulse endpoint schema said minutes; corrected.
  • Response examples split by scenario. The unified endpoint now shows three named examples: pulse-default (empty arrays), pulse-full (word_timestamps + diarize), and pulse-pro. The legacy endpoint shows two named examples: default and with word_timestamps + diarize.

STT API: clarify that words[] and utterances[] need word_timestamps=true

The STT API-ref example response showed populated words[] and utterances[] arrays, but a default request from the docs explorer or Postman returns both arrays empty (the transcription string is fine).

Both arrays are gated on the word_timestamps=true query parameter. The same flag turns on both. Without it, the API still transcribes but does not attach per-word timings or sentence-level segments.