POST /v1/audio/speech

The exact contract for Flux text to speech: JSON request fields, the rules for each speech model, the streamed audio response and its content types, receipt headers and every error code.

Turns text into spoken audio, streamed back as it is made. For a guided introduction, see Text to speech.

EndpointPOST https://api.fluxrouter.ai/v1/audio/speech
Requestapplication/json
ResponseAudio bytes, streamed (chunked)
AuthAuthorization: Bearer <your Flux key>
PlanPaid
StatusRolling out

The same route also answers at /audio/speech, without the /v1. Until speech is switched on for your account, it answers 404.

Request fields

FieldRequiredTypeNotes
modelnostringflux-voice-speak (the default) or flux-voice-speak-hd.
inputyesstringThe text to say. Not empty, up to 4,096 characters.
voiceyesstringA voice id that belongs to model. Read them from GET /v1/audio/voices.
response_formatnostringmp3 (the default), opus, aac, flac, wav or pcm.
speednonumberFrom 0.25 to 4. 1 is normal speed.
instructionsnostringDirection for tone and delivery. flux-voice-speak only. Up to 4,096 characters.
stream_formatnostringLeave it out, or send audio. sse is refused.

Rules for each model

flux-voice-speakflux-voice-speak-hd
VoicesEvery voice listed for italloy, ash, coral, echo, fable, nova, onyx, sage, shimmer
response_formatAll sixAll six
speedFull rangeFull range
instructionsYesRefused with 400 if not empty
Billed charactersInput length; divided by speed when speed is below 1, rounded upInput length

The voice list can also carry voices on other speech models. Those models are not covered here yet.

Response

A 200 streams the audio as it is made, in chunks, with no Content-Length. The headers arrive with the first chunk.

response_formatContent-TypeNotes
mp3audio/mpeg
opusaudio/oggOpus in an Ogg container.
aacaudio/aac
flacaudio/flac
wavaudio/wav
pcmaudio/pcmRaw samples, no header: 24 kHz, 16-bit, signed little-endian, mono.

If audio stops arriving for more than 30 seconds partway through, the stream ends early. The status and headers have already been sent by then, so check that the clip is complete if that matters to you.

Response headers

HeaderMeaning
x-flux-routed-modelThe model id that served
x-flux-billed-charsThe characters billed; see the table above
x-flux-cost-usdWhat this request cost, in US dollars
cache-controlno-store

Billing happens when the first byte of audio arrives. Anything that fails before that is not billed; once audio has started, the charge stands even if the client disconnects.

Limits

LimitValue
input4,096 characters
instructions4,096 characters
Wait for the first audio30 seconds, then 504
Gap between chunks30 seconds
Requests60 requests a minute per account
Audio36,000 seconds of audio an hour per account, shared with transcription; speech counts an estimate from its length

Errors

Errors are JSON, never audio, in this envelope:

json
{
  "error": {
    "message": "voice for flux-voice-speak-hd must be one of [...]",
    "type": "invalid_request_error",
    "param": "voice"
  }
}

code and param are present only when they apply.

StatuscodeMeaningBilled
400none, param setA field is wrong: model, input, voice, response_format, speed, instructions, stream_format or body. param names it and the message says what is allowed.No
400invalid_request_errorThe speech service refused the request after it passed our checks. Change the text or voice and retry.No
401noneThe key was missing or not accepted, or the model is not on the key's model list.No
402premium_lockedThe key's plan does not include speech.No
402credit_unresolvedYour credit balance could not be checked. Retry shortly.No
402another codeA spend cap or prepaid balance stopped the request. See Spend caps.No
404noneSpeech is not switched on for your account yet.No
429rate_limit_errorOver the per-account rate or hourly audio budget, or the speech service is busy. Wait, then retry.No
502capability_unavailableSpeech failed, or no audio came back. Retry.No
504capability_unavailableNo audio arrived in time. Retry.No

Fixes for each are on Text to speech problems.

Example requests

bash
curl https://api.fluxrouter.ai/v1/audio/speech \
  -H "Authorization: Bearer sk-YOUR-FLUX-KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "flux-voice-speak",
    "input": "Your build finished. All tests passed.",
    "voice": "nova",
    "response_format": "mp3"
  }' \
  --output done.mp3

Low-latency pcm, with the receipt headers printed and the audio saved:

bash
curl -sS -D - https://api.fluxrouter.ai/v1/audio/speech \
  -H "Authorization: Bearer $FLUX_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "flux-voice-speak",
    "input": "Three new messages. The first is from Priya.",
    "voice": "coral",
    "response_format": "pcm",
    "speed": 1.1,
    "instructions": "Friendly and quick, like a helpful assistant."
  }' \
  --output reply.pcm

With TypeScript's fetch, streaming to a file:

ts
import fs from "node:fs";
import { Readable } from "node:stream";
import { pipeline } from "node:stream/promises";

const res = await fetch("https://api.fluxrouter.ai/v1/audio/speech", {
  method: "POST",
  headers: {
    Authorization: "Bearer sk-YOUR-FLUX-KEY",
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    model: "flux-voice-speak",
    input: "Your report is ready.",
    voice: "nova",
    response_format: "opus",
  }),
});

if (!res.ok) throw new Error(JSON.stringify(await res.json()));
console.log(res.headers.get("x-flux-cost-usd"));
await pipeline(Readable.fromWeb(res.body!), fs.createWriteStream("report.ogg"));