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": "…"}withContent-Type: application/json, the same as Pulse. - Webhook mode (
webhook_url) works withpulseas well aspulse-pro. - Pulse Pro caps audio at 250 MB, or 50 MB with
webhook_url, whether uploaded or fetched from a URL. Larger audio returns413. - On the realtime WebSocket,
modelis optional and defaults topulse; an invalid value returns400during 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.
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_keyper conversation, static content first, append-only history, streaming, and one reused client. prompt_cache_keyadded 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-openailink - Pulse STT realtime features
age-and-gender-detectionlink - Lightning v3.1 Pro model card
voice-cloning/how-to-vc-apilink
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:
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_endedframes 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 logDELETE /waves/v1/analytics/asr/history/{request_id}: soft-delete a single STT entryGET /waves/v1/analytics/asr/usage/timeseries: STT request count over timeGET /waves/v1/analytics/tts/logs: paginated TTS request logGET /waves/v1/analytics/tts/usage/timeseries: TTS request count over timeGET /waves/v1/analytics/tts/usage/credits/timeseries: TTS credit spend over timeGET /waves/v1/analytics/tts/concurrency/timeseries: TTS peak concurrency over timeGET /waves/v1/analytics/tts/ws-connections/timeseries: open TTS WebSocket count over timeGET /waves/v1/analytics/webhooks/logs: webhook delivery log (e.g.asr.completedcallbacks)
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 evidencePOST /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):
speakeris an integer, not a string. Real responses carryspeaker: 0(zero-indexed), notspeaker: "speaker_0".speaker_confidencefield added to word entries. Present alongsidespeakerwhendiarize=trueis set on Pulse.- Pulse metadata is
{duration, fileSize}only. The old example claimedlanguage,request_id,processing_time_ms,rtfx, andnum_chunkson a Pulse response; those are Pulse Pro only. - Pulse Pro includes
totalBytes,request_id, andlanguageat the top level and richermetadata(processing_time_ms,rtfx,num_chunks). Also does not diarize, sowords[]entries omitspeakerandspeaker_confidence, and there is noutterances[]field. durationis 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), andpulse-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.