Fish TTS API Integration Instructions

This interface is based on the Fish Audio Official TTS API, with differences only in the authentication method (using the platform token) and asynchronous callback (callback_url extension). The request body structure is consistent with the upstream. The address is POST https://api.acedata.cloud/fish/tts.

Application Process

To use the Fish TTS API, first go to the Ace Data Cloud Console to obtain your API Token for backup.

If you are not logged in or registered, you will be automatically redirected to the login page to invite you to register and log in. After completing this, you will be automatically returned to the current page.

One API Token can call all services on the platform, no need to apply separately for each service. The first application will grant a free quota for a trial experience; when the quota is insufficient, you can recharge the general balance in the console.

📘 Complete documentation: Fish TTS API →

Request Headers

Header Required Description
authorization Yes Bearer {token}, where {token} is the key applied for on this platform.
content-type Yes application/json.
accept No application/json.
model No TTS model, optional s1, s2-pro, or s2.1-pro, default is s2-pro. s2.1-pro is the latest generation, s2-pro has strong expressiveness; s1 is more stable and less prone to deviation with long texts. All three are priced the same.

Request Body Fields

Field Type Required Description
text string Yes The text to be synthesized, a non-empty string.
format string No Output audio format, optional mp3 (default), wav, pcm. Both wav and pcm return a WAV container. opus is not supported and will return 400 if passed.
reference_id string | string[] No Cloned voice ID (can be created by Fish Model API or retrieved in Fish Model Query).
references object[] No Inline reference samples, structured the same as upstream, each containing audio and text. One of reference_id or references must be provided.
sample_rate integer No Sample rate, commonly 16000, 22050, 44100. Default is 44100 for format=mp3.
mp3_bitrate integer No MP3 bitrate, optional 64, 128, 192. Only effective for format=mp3.
prosody object No Prosody overrides, supports speed (speech rate, 1.0 is normal speed) and volume (volume gain in dB). For example {"speed":1.2,"volume":0}.
chunk_length integer No Upstream chunk length, default determined by upstream.
temperature number No Sampling temperature, range approximately 0.0–1.0.
top_p number No Top-p sampling parameter.
latency string No normal or balanced, defaults to normal automatically filled by this interface (passing an empty string will be rejected by upstream).
normalize boolean No Whether to normalize the text.
callback_url string No Asynchronous callback address, see below "Asynchronous Callback". This is an extension relative to the official interface.

Field naming is completely consistent with upstream. Except for callback_url, the meanings and values of other fields refer to the Fish Official TTS Documentation.

Example 1: Minimum Request (text + format=mp3)

curl -X POST 'https://api.acedata.cloud/fish/tts' \
  -H 'authorization: Bearer {token}' \
  -H 'content-type: application/json' \
  -d '{
    "text": "Hello world.",
    "format": "mp3"
  }'

Response (actual test):

{
  "audio_url": "https://platform2.cdn.acedata.cloud/fish/e2ffcc06-18da-4a8c-b9aa-9337d0f9ec1d.mp3"
}

audio_url points to the platform CDN, which can be directly downloaded via GET or played in <audio>. The link is long-term available, but it is still recommended to keep a copy in your own storage.

Example 2: Using Cloned Voice reference_id

Below is a public Spanish voice on the Fish platform (the _id can be retrieved through Fish Model Query):

curl -X POST 'https://api.acedata.cloud/fish/tts' \
  -H 'authorization: Bearer {token}' \
  -H 'content-type: application/json' \
  -d '{
    "text": "Hermanos míos, hoy es un buen día.",
    "reference_id": "8d2c17a9b26d4d83888ea67a1ee565b2",
    "format": "mp3"
  }'

Response (actual test):

{
  "audio_url": "https://platform2.cdn.acedata.cloud/fish/b6f161f2-a100-4818-add2-47694f234659.mp3"
}

Example 3: Adjusting Speech Rate / Volume (prosody)

curl -X POST 'https://api.acedata.cloud/fish/tts' \
  -H 'authorization: Bearer {token}' \
  -H 'content-type: application/json' \
  -d '{
    "text": "Faster speech with prosody overrides.",
    "prosody": { "speed": 1.2, "volume": 0 },
    "format": "mp3"
  }'

Response (actual test):

{
  "audio_url": "https://platform2.cdn.acedata.cloud/fish/5ade0339-5f11-487e-aacc-06a908271706.mp3"
}

speed greater than 1 speeds up, less than 1 slows down; volume is in dB, 0 means no change, positive numbers indicate gain, negative numbers indicate attenuation.

Example 4: Switching Model + Controlling Bitrate

Switch to the stable model via HTTP header model: s1, add mp3_bitrate: 128 in the request body to control the MP3 bitrate:

curl -X POST 'https://api.acedata.cloud/fish/tts' \
  -H 'authorization: Bearer {token}' \
  -H 'content-type: application/json' \
  -H 'model: s1' \
  -d '{
    "text": "high bitrate mp3",
    "format": "mp3",
    "mp3_bitrate": 128
  }'

Response (actual measurement):

{
  "audio_url": "https://platform2.cdn.acedata.cloud/fish/7e7abf3d-3d72-4c9f-8eb6-8af932d7c96e.mp3"
}

Example 5: PCM Raw Waveform

For scenarios that require real-time stitching in the browser or subsequent processing (mixing, speed change) on the client side, it is recommended to use pcm:

curl -X POST 'https://api.acedata.cloud/fish/tts' \
  -H 'authorization: Bearer {token}' \
  -H 'content-type: application/json' \
  -d '{
    "text": "hi",
    "format": "pcm",
    "sample_rate": 16000
  }'

Response (actual measurement):

{
  "audio_url": "https://platform2.cdn.acedata.cloud/fish/64adc04b-c196-4a0f-9070-222ba101ce6c.wav"
}

The extension of the link follows the format in the request: mp3 gets .mp3, wav and pcm get .wav (WAV container, 16 bit PCM).

Asynchronous Callback (callback_url)

Synthesis of long texts may take several seconds to tens of seconds, and if the connection is interrupted, it needs to be retried. After passing callback_url in the request body, the interface will immediately return {task_id, started_at}, and when the upstream is truly completed, it will callback the complete result in POST JSON format to that URL, carrying the same task_id in the request body.

curl -X POST 'https://api.acedata.cloud/fish/tts' \
  -H 'authorization: Bearer {token}' \
  -H 'content-type: application/json' \
  -d '{
    "text": "The weather is really nice today, let's go for a walk together.",
    "format": "mp3",
    "callback_url": "https://webhook.site/4815f79f-a40f-4078-ac85-1cc126b6bb34"
  }'

Immediately returns (actual measurement):

{
  "task_id": "79d82713-2897-4eeb-9934-e7544d471aa7",
  "started_at": 1778462584.742
}

Later, callback_url will receive something like:

{
  "task_id": "79d82713-2897-4eeb-9934-e7544d471aa7",
  "audio_url": "https://platform2.cdn.acedata.cloud/fish/bd66b8c5-7543-4557-b684-baa72407e336.mp3"
}

You can also actively pull results by task_id using the Fish Tasks API, see that document for details.

Error Handling

  • 400 token_mismatched: Missing or invalid request parameters (most commonly text is empty, or format has a value other than mp3/wav/pcm).
  • 401 invalid_token: Authentication token does not exist or is invalid.
  • 429 too_many_requests: Triggered account rate limit.
  • 500 api_error: Internal server error.

Example of error response:

{
  "success": false,
  "error": {
    "code": "api_error",
    "message": "fetch failed"
  },
  "trace_id": "2cf86e86-22a4-46e1-ac2f-032c0f2a4e89"
}

Parameter validation errors will place the original pydantic error message from upstream in the message field, making it easier to locate which field is invalid, for example:

{
  "status": 400,
  "message": "[{\"type\":\"literal_error\",\"loc\":[\"format\"],\"msg\":\"Input should be 'pcm' or 'mp3'\",\"input\":\"wav\"}]"
}

Conclusion

The minimum cost of integrating Fish TTS is: replace the authentication in the existing code calling api.fish.audio/v1/tts with the platform token, and explicitly include format: "mp3" in the request body. For long text scenarios, it is recommended to use the callback_url asynchronous callback; for discovering cloned voice reference_id, please refer to Fish Model Query and Fish Model Get.