curl --request POST \
--url https://api.fish.audio/v1/tts \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--header 'model: <model>' \
--data '
{
"text": "<string>",
"temperature": 0.7,
"top_p": 0.7,
"references": [
{
"audio": "<string>",
"text": "<string>"
}
],
"reference_id": "<string>",
"prosody": {
"speed": 1,
"volume": 0
},
"chunk_length": 300,
"normalize": true,
"format": "mp3",
"sample_rate": 123,
"mp3_bitrate": 128,
"opus_bitrate": -1000,
"latency": "normal",
"max_new_tokens": 1024,
"repetition_penalty": 1.2,
"min_chunk_length": 50,
"condition_on_previous_chunks": true,
"early_stop_threshold": 1
}
'import requests
url = "https://api.fish.audio/v1/tts"
payload = {
"text": "<string>",
"temperature": 0.7,
"top_p": 0.7,
"references": [
{
"audio": "<string>",
"text": "<string>"
}
],
"reference_id": "<string>",
"prosody": {
"speed": 1,
"volume": 0
},
"chunk_length": 300,
"normalize": True,
"format": "mp3",
"sample_rate": 123,
"mp3_bitrate": 128,
"opus_bitrate": -1000,
"latency": "normal",
"max_new_tokens": 1024,
"repetition_penalty": 1.2,
"min_chunk_length": 50,
"condition_on_previous_chunks": True,
"early_stop_threshold": 1
}
headers = {
"model": "<model>",
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {
model: '<model>',
Authorization: 'Bearer <token>',
'Content-Type': 'application/json'
},
body: JSON.stringify({
text: '<string>',
temperature: 0.7,
top_p: 0.7,
references: [{audio: '<string>', text: '<string>'}],
reference_id: '<string>',
prosody: {speed: 1, volume: 0},
chunk_length: 300,
normalize: true,
format: 'mp3',
sample_rate: 123,
mp3_bitrate: 128,
opus_bitrate: -1000,
latency: 'normal',
max_new_tokens: 1024,
repetition_penalty: 1.2,
min_chunk_length: 50,
condition_on_previous_chunks: true,
early_stop_threshold: 1
})
};
fetch('https://api.fish.audio/v1/tts', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.fish.audio/v1/tts",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'text' => '<string>',
'temperature' => 0.7,
'top_p' => 0.7,
'references' => [
[
'audio' => '<string>',
'text' => '<string>'
]
],
'reference_id' => '<string>',
'prosody' => [
'speed' => 1,
'volume' => 0
],
'chunk_length' => 300,
'normalize' => true,
'format' => 'mp3',
'sample_rate' => 123,
'mp3_bitrate' => 128,
'opus_bitrate' => -1000,
'latency' => 'normal',
'max_new_tokens' => 1024,
'repetition_penalty' => 1.2,
'min_chunk_length' => 50,
'condition_on_previous_chunks' => true,
'early_stop_threshold' => 1
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json",
"model: <model>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.fish.audio/v1/tts"
payload := strings.NewReader("{\n \"text\": \"<string>\",\n \"temperature\": 0.7,\n \"top_p\": 0.7,\n \"references\": [\n {\n \"audio\": \"<string>\",\n \"text\": \"<string>\"\n }\n ],\n \"reference_id\": \"<string>\",\n \"prosody\": {\n \"speed\": 1,\n \"volume\": 0\n },\n \"chunk_length\": 300,\n \"normalize\": true,\n \"format\": \"mp3\",\n \"sample_rate\": 123,\n \"mp3_bitrate\": 128,\n \"opus_bitrate\": -1000,\n \"latency\": \"normal\",\n \"max_new_tokens\": 1024,\n \"repetition_penalty\": 1.2,\n \"min_chunk_length\": 50,\n \"condition_on_previous_chunks\": true,\n \"early_stop_threshold\": 1\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("model", "<model>")
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.fish.audio/v1/tts")
.header("model", "<model>")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"text\": \"<string>\",\n \"temperature\": 0.7,\n \"top_p\": 0.7,\n \"references\": [\n {\n \"audio\": \"<string>\",\n \"text\": \"<string>\"\n }\n ],\n \"reference_id\": \"<string>\",\n \"prosody\": {\n \"speed\": 1,\n \"volume\": 0\n },\n \"chunk_length\": 300,\n \"normalize\": true,\n \"format\": \"mp3\",\n \"sample_rate\": 123,\n \"mp3_bitrate\": 128,\n \"opus_bitrate\": -1000,\n \"latency\": \"normal\",\n \"max_new_tokens\": 1024,\n \"repetition_penalty\": 1.2,\n \"min_chunk_length\": 50,\n \"condition_on_previous_chunks\": true,\n \"early_stop_threshold\": 1\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.fish.audio/v1/tts")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["model"] = '<model>'
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"text\": \"<string>\",\n \"temperature\": 0.7,\n \"top_p\": 0.7,\n \"references\": [\n {\n \"audio\": \"<string>\",\n \"text\": \"<string>\"\n }\n ],\n \"reference_id\": \"<string>\",\n \"prosody\": {\n \"speed\": 1,\n \"volume\": 0\n },\n \"chunk_length\": 300,\n \"normalize\": true,\n \"format\": \"mp3\",\n \"sample_rate\": 123,\n \"mp3_bitrate\": 128,\n \"opus_bitrate\": -1000,\n \"latency\": \"normal\",\n \"max_new_tokens\": 1024,\n \"repetition_penalty\": 1.2,\n \"min_chunk_length\": 50,\n \"condition_on_previous_chunks\": true,\n \"early_stop_threshold\": 1\n}"
response = http.request(request)
puts response.read_body{
"status": 123,
"message": "<string>"
}{
"status": 123,
"message": "<string>"
}[
{
"loc": [
"<string>"
],
"type": "<string>",
"msg": "<string>",
"ctx": "<string>",
"in": "path"
}
]Text to Speech
Convert text to speech
curl --request POST \
--url https://api.fish.audio/v1/tts \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--header 'model: <model>' \
--data '
{
"text": "<string>",
"temperature": 0.7,
"top_p": 0.7,
"references": [
{
"audio": "<string>",
"text": "<string>"
}
],
"reference_id": "<string>",
"prosody": {
"speed": 1,
"volume": 0
},
"chunk_length": 300,
"normalize": true,
"format": "mp3",
"sample_rate": 123,
"mp3_bitrate": 128,
"opus_bitrate": -1000,
"latency": "normal",
"max_new_tokens": 1024,
"repetition_penalty": 1.2,
"min_chunk_length": 50,
"condition_on_previous_chunks": true,
"early_stop_threshold": 1
}
'import requests
url = "https://api.fish.audio/v1/tts"
payload = {
"text": "<string>",
"temperature": 0.7,
"top_p": 0.7,
"references": [
{
"audio": "<string>",
"text": "<string>"
}
],
"reference_id": "<string>",
"prosody": {
"speed": 1,
"volume": 0
},
"chunk_length": 300,
"normalize": True,
"format": "mp3",
"sample_rate": 123,
"mp3_bitrate": 128,
"opus_bitrate": -1000,
"latency": "normal",
"max_new_tokens": 1024,
"repetition_penalty": 1.2,
"min_chunk_length": 50,
"condition_on_previous_chunks": True,
"early_stop_threshold": 1
}
headers = {
"model": "<model>",
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {
model: '<model>',
Authorization: 'Bearer <token>',
'Content-Type': 'application/json'
},
body: JSON.stringify({
text: '<string>',
temperature: 0.7,
top_p: 0.7,
references: [{audio: '<string>', text: '<string>'}],
reference_id: '<string>',
prosody: {speed: 1, volume: 0},
chunk_length: 300,
normalize: true,
format: 'mp3',
sample_rate: 123,
mp3_bitrate: 128,
opus_bitrate: -1000,
latency: 'normal',
max_new_tokens: 1024,
repetition_penalty: 1.2,
min_chunk_length: 50,
condition_on_previous_chunks: true,
early_stop_threshold: 1
})
};
fetch('https://api.fish.audio/v1/tts', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.fish.audio/v1/tts",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'text' => '<string>',
'temperature' => 0.7,
'top_p' => 0.7,
'references' => [
[
'audio' => '<string>',
'text' => '<string>'
]
],
'reference_id' => '<string>',
'prosody' => [
'speed' => 1,
'volume' => 0
],
'chunk_length' => 300,
'normalize' => true,
'format' => 'mp3',
'sample_rate' => 123,
'mp3_bitrate' => 128,
'opus_bitrate' => -1000,
'latency' => 'normal',
'max_new_tokens' => 1024,
'repetition_penalty' => 1.2,
'min_chunk_length' => 50,
'condition_on_previous_chunks' => true,
'early_stop_threshold' => 1
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json",
"model: <model>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.fish.audio/v1/tts"
payload := strings.NewReader("{\n \"text\": \"<string>\",\n \"temperature\": 0.7,\n \"top_p\": 0.7,\n \"references\": [\n {\n \"audio\": \"<string>\",\n \"text\": \"<string>\"\n }\n ],\n \"reference_id\": \"<string>\",\n \"prosody\": {\n \"speed\": 1,\n \"volume\": 0\n },\n \"chunk_length\": 300,\n \"normalize\": true,\n \"format\": \"mp3\",\n \"sample_rate\": 123,\n \"mp3_bitrate\": 128,\n \"opus_bitrate\": -1000,\n \"latency\": \"normal\",\n \"max_new_tokens\": 1024,\n \"repetition_penalty\": 1.2,\n \"min_chunk_length\": 50,\n \"condition_on_previous_chunks\": true,\n \"early_stop_threshold\": 1\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("model", "<model>")
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.fish.audio/v1/tts")
.header("model", "<model>")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"text\": \"<string>\",\n \"temperature\": 0.7,\n \"top_p\": 0.7,\n \"references\": [\n {\n \"audio\": \"<string>\",\n \"text\": \"<string>\"\n }\n ],\n \"reference_id\": \"<string>\",\n \"prosody\": {\n \"speed\": 1,\n \"volume\": 0\n },\n \"chunk_length\": 300,\n \"normalize\": true,\n \"format\": \"mp3\",\n \"sample_rate\": 123,\n \"mp3_bitrate\": 128,\n \"opus_bitrate\": -1000,\n \"latency\": \"normal\",\n \"max_new_tokens\": 1024,\n \"repetition_penalty\": 1.2,\n \"min_chunk_length\": 50,\n \"condition_on_previous_chunks\": true,\n \"early_stop_threshold\": 1\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.fish.audio/v1/tts")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["model"] = '<model>'
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"text\": \"<string>\",\n \"temperature\": 0.7,\n \"top_p\": 0.7,\n \"references\": [\n {\n \"audio\": \"<string>\",\n \"text\": \"<string>\"\n }\n ],\n \"reference_id\": \"<string>\",\n \"prosody\": {\n \"speed\": 1,\n \"volume\": 0\n },\n \"chunk_length\": 300,\n \"normalize\": true,\n \"format\": \"mp3\",\n \"sample_rate\": 123,\n \"mp3_bitrate\": 128,\n \"opus_bitrate\": -1000,\n \"latency\": \"normal\",\n \"max_new_tokens\": 1024,\n \"repetition_penalty\": 1.2,\n \"min_chunk_length\": 50,\n \"condition_on_previous_chunks\": true,\n \"early_stop_threshold\": 1\n}"
response = http.request(request)
puts response.read_body{
"status": 123,
"message": "<string>"
}{
"status": 123,
"message": "<string>"
}[
{
"loc": [
"<string>"
],
"type": "<string>",
"msg": "<string>",
"ctx": "<string>",
"in": "path"
}
]application/json and application/msgpack.For best results, upload reference audio using the create model before using this one. This improves speech quality and reduces latency.To upload audio clips directly, without pre-uploading, serialize the request body with MessagePack as per the instructions.- WAV / PCM
- Sample Rate: 8kHz, 16kHz, 24kHz, 32kHz, 44.1kHz
- Default Sample Rate: 44.1kHz
- 16-bit, mono
- MP3
- Sample Rate: 32kHz, 44.1kHz
- Default Sample Rate: 44.1kHz
- mono
- Bitrate: 64kbps, 128kbps (default), 192kbps
- Opus
- Sample Rate: 48kHz
- Default Sample Rate: 48kHz
- mono
- Bitrate: -1000 (auto), 24kbps, 32kbps (default), 48kbps, 64kbps
Authorizations
Bearer authentication header of the form Bearer <token>, where <token> is your auth token.
Headers
Specify which TTS model to use. We recommend s1
s1, speech-1.6, speech-1.5 Body
Request body for text-to-speech synthesis.
Text to convert to speech.
Controls expressiveness. Higher is more varied, lower is more consistent.
0 <= x <= 1Controls diversity via nucleus sampling.
0 <= x <= 1Inline voice references for zero-shot cloning. Requires MessagePack (not JSON). Ignored if reference_id is provided.
Show child attributes
Show child attributes
Voice model ID from the Fish Audio library or your custom models.
Speed and volume adjustments for the output.
Show child attributes
Show child attributes
Text segment size for processing.
100 <= x <= 300Normalizes text for English and Chinese, improving stability for numbers.
Output audio format.
wav, pcm, mp3, opus Audio sample rate in Hz. When null, uses the format's default (44100 Hz for most formats, 48000 Hz for opus).
MP3 bitrate in kbps. Only applies when format is mp3.
64, 128, 192 Opus bitrate in bps. -1000 for automatic. Only applies when format is opus.
-1000, 24, 32, 48, 64 Latency-quality trade-off. normal: best quality, balanced: reduced latency, low: lowest latency.
low, normal, balanced Maximum audio tokens to generate per text chunk.
Penalty for repeating audio patterns. Values above 1.0 reduce repetition.
Minimum characters before splitting into a new chunk.
0 <= x <= 100Use previous audio as context for voice consistency.
Early stopping threshold for batch processing.
0 <= x <= 1Response
Request fulfilled, document follows
Was this page helpful?

