Skip to navigation

Generate speech

Send text, receive audio, and understand request limits and usage.
View as Markdown

POST https://api.narilabs.com/v1/audio/speech converts complete text into speech. Set stream: true for progressive audio delivery, or omit it to receive the complete response.

Prepare your text

Use normal capitalization and punctuation. All-lowercase text or text without punctuation can severely degrade speech quality.

Capitalize sentence starts and proper nouns, and include commas and sentence-ending punctuation where appropriate. The server does not automatically restore capitalization or missing punctuation. This is a speech-quality guideline, not an additional input validation requirement.

RecommendedAvoid
Hello, how are you? I'm glad you're here.hello how are you i'm glad you're here

Make a request

With your API key in NARI_API_KEY, run:

curl --fail --silent --show-error \
https://api.narilabs.com/v1/audio/speech \
-H "Authorization: Bearer $NARI_API_KEY" \
-H "Content-Type: application/json" \
--data '{
"model": "qwen3-tts",
"input": "Your order has shipped.",
"voice": "diana",
"language": "en",
"response_format": "wav",
"stream": false
}' \
--dump-header response-headers.txt \
--output speech.wav
FieldHow to use it
modelRequired. Select a Standard or Fast model.
inputRequired. Send all text to synthesize in this request, with normal capitalization and punctuation.
voiceRequired and case-sensitive. Use an exact ID such as diana or leon from List voices for the same model.
languageOmit or use auto to use the voice’s assigned language. If specified, it must match the voice’s returned language code, such as en or es.
response_formatwav (default) or raw pcm.
seedOptional integer from 0 through 4294967295. Defaults to 0 when omitted.
streamfalse (default) for a complete response; true for progressive delivery.

Omit optional fields to use their defaults. Unknown fields, explicit null values, and incorrect field types are rejected with 400.

The API reference defines field types, validation, and error responses.

Read the response

A successful request returns HTTP 200 with binary audio, rather than JSON or an audio URL. The example saves it to speech.wav, ready to open in an audio player.

HeaderMeaning
Content-Typeaudio/wav for WAV, or audio/pcm for raw PCM.
x-nari-seedSeed used to generate the audio, including when the default 0 was used.
x-request-idRequest identifier for tracing failures and support.

Both formats contain 24 kHz, signed PCM16 little-endian, mono audio. WAV includes a container header; PCM requires you to configure the playback format. Streaming audio covers playback and progressive delivery.

Errors detected before response headers are sent return a non-2xx status with a JSON body. Check the status before treating the body as audio; Errors and troubleshooting explains error codes and how to inspect them with cURL.

Input limits

LimitValue
Text length1–2,048 Unicode code points after trimming surrounding whitespace
Complete JSON body64 KiB (65,536 bytes), including keys, values, and escaping

The body size limit applies before trimming. Whitespace-only input or text longer than 2,048 characters after trimming returns 400 INVALID_SPEECH_REQUEST. An oversized body returns 413 REQUEST_TOO_LARGE. Split longer text at sentence boundaries.

Surrounding whitespace is removed before synthesis and usage measurement.

Usage and billing

TTS usage is measured by input characters. Successful requests debit credits; failed and cancelled requests do not. Usage and billing explains character counting, pricing, and credits.

Rate limits

Speech requests share an organization TTS concurrency limit across Standard and Fast models, API keys, and Playground activity. Rate limits lists current limits and retry behavior for each 429 error.

Request another variation

To generate another variation, resend your request with a different seed:

retry_request = {**original_request, "seed": 42}

If omitted, seed defaults to 0. The response’s x-nari-seed header reports the seed used.