openapi: 3.0.1 info: title: Lightning V3.1 API description: 'API for the Lightning V3.1 text-to-speech model. Features improved speech synthesis with support for English and Hindi languages. ' version: 3.1.0 servers: - url: https://api.smallest.ai description: Waves API server x-fern-server-name: waves paths: /waves/v1/lightning-v3.1/get_speech: post: tags: - Lightning V3.1 operationId: synthesizeLightningV31Speech summary: Generate speech from text (Lightning V3.1) description: | **Endpoint scheduled for retirement.** This URL will stop accepting requests **60 days from the Lightning v3.1 Pro launch (2026-05-15)** — i.e. on **2026-07-14**. The Lightning v3.1 model itself is current and stays. Migrate to [`POST /waves/v1/tts`](/waves/api-reference/api-reference/text-to-speech/synthesize-speech) and select Lightning v3.1 via the `model` body field (default). Synthesize speech from text in a single request. The simplest way to get audio when you have the full text up front — pass `text` + `voice_id`, get back binary audio. ## When to use this - **Use this** for short utterances you can render before playback (notifications, prompts, batch jobs, audio file generation). - **Use the SSE streaming endpoint** when you want playback to start before the full audio is ready (long passages, latency-sensitive apps). - **Use the WebSocket endpoint** when text arrives incrementally (LLM token streams, live captioning). ## Key features - 44 kHz natural, expressive synthesis - Cloned voice IDs (`voice_*`) work — same param as catalog voices - 12 documented languages — see the model card for the full list - Output formats: `pcm`, `mp3`, `wav`, `ulaw`, `alaw` - Sample rates: 8 kHz – 44.1 kHz - Speed: 0.5× – 2× - Per-call pronunciation dictionaries via `pronunciation_dicts` ## Examples **cURL** ```bash curl -X POST "https://api.smallest.ai/waves/v1/lightning-v3.1/get_speech" \ -H "Authorization: Bearer $SMALLEST_API_KEY" \ -H "Content-Type: application/json" \ -H "Accept: audio/wav" \ -d '{ "text": "Hello from Lightning v3.1.", "voice_id": "magnus", "sample_rate": 24000, "output_format": "wav" }' --output speech.wav ``` **Python** (`pip install smallestai>=4.4.0`) ```python from smallestai import SmallestAI client = SmallestAI(api_key="YOUR_API_KEY") with open("speech.wav", "wb") as f: for chunk in client.waves.synthesize_lightning_v3_1( text="Hello from Lightning v3.1.", voice_id="magnus", sample_rate=24000, output_format="wav", # Optional: cloned voice support # voice_id="voice_FlPKRWI7DX", # Optional: pin pronunciations for specific words # pronunciation_dicts=[""], ): f.write(chunk) ``` **JavaScript / TypeScript** (using `fetch`) ```typescript const res = await fetch("https://api.smallest.ai/waves/v1/lightning-v3.1/get_speech", { method: "POST", headers: { Authorization: `Bearer ${process.env.SMALLEST_API_KEY}`, "Content-Type": "application/json", Accept: "audio/wav", }, body: JSON.stringify({ text: "Hello from Lightning v3.1.", voice_id: "magnus", sample_rate: 24000, output_format: "wav", }), }); const audio = Buffer.from(await res.arrayBuffer()); require("node:fs").writeFileSync("speech.wav", audio); ``` ## Common gotchas - **Set `Accept: audio/wav`.** Omitting it can return an empty or unplayable response. - **Cloned voices** (`voice_*` from `add_voice`) work on this endpoint and support `pronunciation_dicts`. - **`pronunciation_dicts` validates IDs at request time.** Passing an unknown ID returns `Invalid input data` — create the dict first via the pronunciation-dicts endpoint and save the returned `id`. - **Pronunciation matching is case-sensitive.** Add both `Synopsis` and `synopsis` if your text uses both casings. - **44.1 kHz output** is supported but most playback environments are happy with 24 kHz — drop the sample rate if bandwidth matters. - **JavaScript / TypeScript**: the official `smallestai` npm package predates Lightning v3.1, so call this endpoint with `fetch` or `axios` as shown above. parameters: - name: Accept in: header required: true schema: type: string enum: - audio/wav default: audio/wav description: Must be `audio/wav` to receive binary audio. Required for proper playback. security: - bearerAuth: [] requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/LightningV31Request' example: text: Hey i am your a text to speech model voice_id: daniel output_format: mp3 sample_rate: 44100 speed: 1.0 responses: '200': description: Synthesized speech retrieved successfully. headers: X-Session-Id: schema: type: string description: Internal session identifier (system-generated UUID). X-Request-Id: schema: type: string description: Internal request identifier (system-generated UUID). X-External-Session-Id: schema: type: string description: Echoed client-provided session_id (empty if not provided). X-External-Request-Id: schema: type: string description: Echoed client-provided request_id (empty if not provided). content: audio/wav: schema: type: string format: binary description: A PCM int16 WAV file at the specified sample rate. '400': description: Bad request. content: application/json: schema: type: object properties: error: type: string description: Error type. message: type: string description: Error message. example: error: InvalidRequest message: The 'text' field is required. '401': description: Unauthorized. content: application/json: schema: type: object properties: error: type: string description: Error type. message: type: string description: Error message. example: error: Unauthorized message: Bearer token is missing or invalid. '500': description: Server error occurred. content: application/json: schema: type: object properties: error: type: string description: Error type. message: type: string description: Error message. example: error: InternalServerError message: An unexpected error occurred. /waves/v1/lightning-v3.1/stream: post: tags: - Lightning V3.1 operationId: streamLightningV31Speech summary: Stream speech from text (Lightning V3.1) description: | **Endpoint scheduled for retirement.** This URL will stop accepting requests **60 days from the Lightning v3.1 Pro launch (2026-05-15)** — i.e. on **2026-07-14**. The Lightning v3.1 model itself is current and stays. Migrate to [`POST /waves/v1/tts/live`](/waves/api-reference/api-reference/text-to-speech/synthesize-speech-sse) and select Lightning v3.1 via the `model` body field (default). Synthesize speech and stream the audio back over Server-Sent Events. The body and parameters are identical to the sync `/get_speech` endpoint — the difference is the response is a stream of base64-encoded PCM chunks instead of one binary blob. ## When to use this - **Use this** when you want playback to start before synthesis is complete — long passages, latency-sensitive UI, live narration. - **Use sync `/get_speech`** when total latency doesn't matter and you'd rather get one buffer. - **Use the WebSocket endpoint** when the *text* arrives incrementally (LLM token stream). SSE assumes you have the full text up front. ## How it works 1. POST your text + voice settings — same payload as `/get_speech`. 2. The response is `Content-Type: text/event-stream`. Each chunk frame is `event: audio\n` followed by `data: {"audio": ""}\n\n`. 3. Decode each chunk's `audio` field with base64 and feed the PCM bytes to your audio pipeline (browser `MediaSource`, ffmpeg pipe, raw PCM player, etc.). 4. A final `data: {"done": true}\n\n` frame marks end of stream. ## Examples **cURL** ```bash curl -N -X POST "https://api.smallest.ai/waves/v1/lightning-v3.1/stream" \ -H "Authorization: Bearer $SMALLEST_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "text": "Streaming this paragraph chunk by chunk so playback can start sooner.", "voice_id": "magnus", "sample_rate": 24000, "output_format": "pcm" }' ``` **Python** (`pip install smallestai>=4.4.0`) ```python import base64 from smallestai import SmallestAI client = SmallestAI(api_key="YOUR_API_KEY") with open("stream.pcm", "wb") as f: for chunk in client.waves.synthesize_sse_lightning_v3_1( text="Streaming this paragraph chunk by chunk so playback can start sooner.", voice_id="magnus", sample_rate=24000, output_format="pcm", ): # Each chunk is `{"audio": ""}`. # Decode and pipe to your audio pipeline. if chunk.get("audio"): f.write(base64.b64decode(chunk["audio"])) ``` **JavaScript / TypeScript** (using `fetch` + a reader) ```typescript const res = await fetch("https://api.smallest.ai/waves/v1/lightning-v3.1/stream", { method: "POST", headers: { Authorization: `Bearer ${process.env.SMALLEST_API_KEY}`, "Content-Type": "application/json", }, body: JSON.stringify({ text: "Streaming this paragraph chunk by chunk so playback can start sooner.", voice_id: "magnus", sample_rate: 24000, output_format: "pcm", }), }); const reader = res.body!.getReader(); const decoder = new TextDecoder(); let buf = ""; let finished = false; while (!finished) { const { value, done } = await reader.read(); if (done) break; buf += decoder.decode(value); const events = buf.split("\n\n"); buf = events.pop() ?? ""; for (const ev of events) { // SSE frames are "event: audio\ndata: {json}" or just "data: {json}". // We only care about the data line — pull it out and parse. const dataLine = ev.split("\n").find((l) => l.startsWith("data:")); if (!dataLine) continue; const payload = JSON.parse(dataLine.slice(5).trim()); if (payload.done) { finished = true; break; } if (payload.audio) { const pcm = Buffer.from(payload.audio, "base64"); // … hand pcm to your audio pipeline } } } ``` ## Common gotchas - **Use a streaming-friendly client.** `curl -N`, Python `iter_lines`, or a `fetch` `ReadableStream` reader. Buffering clients will hide the latency win. - **Audio is base64 inside the event payload**, not the raw event bytes. Decode the `data.audio` field per event. - **`output_format=pcm`** gives the lowest overhead for streaming playback. `wav`/`mp3` work but add per-chunk framing bytes. - **First-chunk latency** depends on model warm-up + network distance. Use `output_format=pcm` and a streaming-friendly client to minimize what you can control. - **JavaScript / TypeScript**: the official `smallestai` npm package predates Lightning v3.1, so call this endpoint with `fetch` as shown above. security: - bearerAuth: [] requestBody: required: true content: application/json: schema: $ref: '#/components/schemas/LightningV31Request' responses: '200': description: Synthesized speech retrieved successfully. headers: X-Session-Id: schema: type: string description: Internal session identifier (system-generated UUID). X-Request-Id: schema: type: string description: Internal request identifier (system-generated UUID). X-External-Session-Id: schema: type: string description: Echoed client-provided session_id (empty if not provided). X-External-Request-Id: schema: type: string description: Echoed client-provided request_id (empty if not provided). content: text/event-stream: example: data: 'event: chunk data: done: false ' '400': description: Bad request. content: application/json: schema: type: object properties: error: type: string description: Error type. message: type: string description: Error message. example: error: InvalidRequest message: The 'text' field is required. '401': description: Unauthorized. content: application/json: schema: type: object properties: error: type: string description: Error type. message: type: string description: Error message. example: error: Unauthorized message: Bearer token is missing or invalid. '500': description: Server error occurred. content: application/json: schema: type: object properties: error: type: string description: Error type. message: type: string description: Error message. example: error: InternalServerError message: An unexpected error occurred. components: schemas: LightningV31Request: type: object required: - text - voice_id properties: text: type: string description: The text to convert to speech. default: Hey i am your a text to speech model voice_id: type: string description: The voice identifier to use for speech generation. default: daniel model: type: string description: | TTS model to route the request to. - `lightning_v3.1` (default) — standard Lightning v3.1 pool. - `lightning_v3.1_pro` — Lightning v3.1 Pro pool with a curated voice catalog. See the [Pro model card](/waves/model-cards/text-to-speech/lightning-v-3-1-pro). New integrations should use the unified `/waves/v1/tts` route instead of this endpoint, but the `model` field is supported here for backwards-compatible Pro opt-in. enum: - lightning_v3.1 - lightning_v3.1_pro default: lightning_v3.1 sample_rate: type: integer description: The sample rate for the generated audio. enum: - 8000 - 16000 - 24000 - 44100 default: 44100 speed: type: number description: The speed of the generated speech. minimum: 0.5 maximum: 2 default: 1.0 language: type: string description: | Language code for synthesis. Influences pronunciation, number/date normalization, and phoneme selection. - **Indian:** `en`, `hi`, `mr` (Marathi), `kn` (Kannada), `ta` (Tamil), `bn` (Bengali), `gu` (Gujarati), `te` (Telugu), `ml` (Malayalam), `pa` (Punjabi), `or` (Odia) - **European:** `es` (Spanish) default: en enum: - en - hi - mr - kn - ta - bn - gu - te - ml - pa - or - es number_pronunciation_language: type: string description: | Optional. Sets the language used to read out numeric content — numbers, currency amounts, times, and the numeric parts of dates and years — independently of the synthesis voice. Ordinary words are not translated. - If you **omit `language`**, this value also becomes the synthesis language: model selection and voice routing follow it. - If you **set `language` explicitly**, `language` always wins for synthesis and `number_pronunciation_language` only changes how numeric content is normalized. It works both ways — read numbers in Hindi under an English voice, or in English under a Hindi voice (tuned for Indian, often mixed-script, use cases). - Omit this field to keep the existing behaviour — normalization follows `language`. Note: only numeric tokens are re-spoken; the words around them stay in the text language. On a cross-language request names may also render in the target script (e.g. "Smith" → "स्मिथ"), which is generally the desired reading for native-language voices. Accepts the same language codes as `language`. enum: - en - hi - mr - kn - ta - bn - gu - te - ml - pa - or - es output_format: type: string description: 'Format of the returned audio. `pcm` is the lowest-latency option but requires a decoder to play; `mp3` and `wav` are directly playable in browsers and most media players. The server default is `pcm` when the field is omitted — the API playground uses `mp3` so the generated audio is directly playable. ' default: pcm example: mp3 enum: - mp3 - pcm - wav - ulaw - alaw pronunciation_dicts: type: array items: type: string description: The ID of the pronunciation dictionary to use for speech generation. description: The IDs of the pronunciation dictionaries to use for speech generation. session_id: type: string description: Optional client-provided session identifier for correlation. Only alphanumeric characters, hyphens, underscores, and dots are allowed. Max 128 characters. Echoed back in response headers as `X-External-Session-Id`. maxLength: 128 pattern: ^[a-zA-Z0-9_\-.]+$ request_id: type: string description: Optional client-provided request identifier for correlation. Only alphanumeric characters, hyphens, underscores, and dots are allowed. Max 128 characters. Echoed back in response headers as `X-External-Request-Id`. maxLength: 128 pattern: ^[a-zA-Z0-9_\-.]+$ securitySchemes: bearerAuth: type: http scheme: bearer bearerFormat: JWT