Fish Audio Docs
API ReferenceText to SpeechSynchronous Text to Speech

Synchronous Text to Speech v2

Synchronous HTTP TTS v2 compatibility contract for existing clients.

HTTP TTS v2 is maintained for existing clients. New integrations should use HTTP TTS v3, which provides a strict field contract, model capabilities, and recoverable asynchronous jobs.

Migration notice: The v2 synchronous endpoint remains available. No retirement date has been set. Existing clients should migrate and verify their requests using the migration guide; new clients should use v3. Changing the URL alone is insufficient because v3 rejects some legacy v2 fields.

Endpoint

POST /api/open/v2/speech/tts

Full URL:

https://fishaudio.org/api/open/v2/speech/tts

Authentication and request headers

Authorization: Bearer FISHAUDIO_API_KEY
Content-Type: application/json
X-Request-Id: YOUR_STABLE_REQUEST_ID

Keep the API key on a trusted server. Success is binary audio; errors are JSON.

Request

{
  "text": "Hello from Fish Audio.",
  "voiceId": "00a1b221-6137-4b73-ad62-b0cbce134167",
  "modelId": "fishaudio-s21pro-flash",
  "format": "mp3",
  "speed": 1,
  "volume": 0,
  "stability": 1,
  "similarity": 1
}
FieldTypeRequiredNotes
textstringYes1–10,000 characters
voiceIdstringYesPublic or personal voice ID
modelIdstringNoPublic engine model ID; omission uses voice/account defaults
formatstringNomp3, wav, or ogg; default mp3
speednumberNo0.5–2; default 1
volumenumberNo-20–20; default 0
pitchnumberNo-12–12
stabilitynumberNo0.5–1.5
similaritynumberNo0.5–1.5
languagestringNoLanguage hint
emotionstringNoGlobal emotion ID
instructionstringNoQwen style instruction, up to 1,600 characters
textNormalizationbooleanNoStructured-text pronunciation normalization

V2 also accepts historical fields such as engineModelId, version, qwenModel, and minimaxEmotion. They exist only for old clients. Do not use them in new code or mix them into v3 requests. V2 has no provider-neutral capability catalog.

curl example

curl "https://fishaudio.org/api/open/v2/speech/tts" \
  -H "Authorization: Bearer $FISHAUDIO_API_KEY" \
  -H "Content-Type: application/json" \
  -H "X-Request-Id: legacy-tts-001" \
  -d '{"text":"Hello","voiceId":"00a1b221-6137-4b73-ad62-b0cbce134167","modelId":"fishaudio-s21pro-flash","format":"mp3"}' \
  --output speech.mp3

Successful response

HTTP/1.1 200 OK
Content-Type: audio/mpeg
X-Request-Id: legacy-tts-001
X-OpenAPI-Quota-Remaining: 99994
X-OpenAPI-Credits-Used: 6

<binary audio data>

Errors and retries

Errors use a flat JSON shape:

{
  "code": "ERR_REQUEST_ID_CONFLICT",
  "message": "Request id was reused with a different request",
  "requestId": "legacy-tts-001"
}
StatusMeaning
400Invalid request or voice/model combination
401Invalid API key
402Insufficient API quota
409Request ID active, completed, or reused with different input
413HTTP request body exceeds the limit
429Rate limited; honor Retry-After
500Generation or settlement failure

Reuse X-Request-Id only for an identical retry. Lost synchronous audio cannot be replayed; workflows that require recovery should migrate to v3 Jobs.

Migrate to v3

Keep text, voiceId, and generic controls; remove historical provider fields. modelId is optional in v3; omitting it uses the default engine for the selected voice. See the migration guide for the complete mapping.