Move your Fish Audio TTS API to Cartesia

Cartesia reads the model and the voice from the JSON body, where Fish Audio splits them between a request header and reference_id.

Why migrate from Fish Audio now

Dated changes on the Fish Audio side, each linked to the page that announces it.

S1 retires

Fish Audio lists s1 as deprecated. Requests that send model: s1 need a new model before the end of the year either way.

Fish Audio models overview

Migrate from Fish Audio with your coding agent

Paste this into Claude Code, Cursor or Codex in the repo that calls Fish Audio. It carries the field mapping, the Cartesia request and a rollout that keeps Fish Audio behind a flag until you switch.

12 fields mapped, with a rollback plan

Prompt

Connect MCP
Move this codebase from Fish Audio to Cartesia for text to speech. Keep Fish Audio working behind a flag until I switch over.

December 31, 2026: S1 retires. Fish Audio lists `s1` as deprecated. Requests that send `model: s1` need a new model before the end of the year either way. (https://docs.fish.audio/developer-guide/models-pricing/models-overview)

## 1. Find the calls
Search for `api.fish.audio` or `FISH_API_KEY`. The request to replace is `POST https://api.fish.audio/v1/tts`. List every call site before you edit anything.

## 2. Target
- Request: `POST https://api.cartesia.ai/tts/bytes`
- Model: `model_id: "sonic-3.6"`
- Headers: `X-API-Key` read from the `CARTESIA_API_KEY` environment variable, and `Cartesia-Version: 2026-08-14`
- Auth swap: Fish Audio sends the key in `Authorization: Bearer` token from `FISH_API_KEY`. Replace it with `X-API-Key` from `CARTESIA_API_KEY` on the Cartesia path only, and keep `FISH_API_KEY` for the Fish Audio path. Fish Audio shows a new key once, on its developer page. Copy it before you close the dialog.
- Add `CARTESIA_API_KEY` wherever the project documents its environment (`.env.example`, README, deploy config). Never hardcode the key.
- Concurrency: Fish Audio allows 5 concurrent requests under $100 paid, 15 from $100, 50 from $1,000. Look up the Cartesia plan's concurrent request limit at https://www.cartesia.ai/pricing, cap parallel requests at it, and retry rate-limit errors with backoff.
- Voice IDs don't carry over. Keep each voice ID in one named constant or config value, put a placeholder where each Fish Audio voice was, and list them for me so I can pick replacements at https://www.cartesia.ai/voices.
- Suggested starting points to put in those placeholders, for me to confirm by ear: Expressive narrator for video content → `a33f7a4c-100f-41cf-a1fd-5822e8fc253f` (Lauren - Lively Narrator); Upbeat promo or ad read → `710feaa3-b550-42f3-b3eb-6f37f2a7cc0a` (Tanner - Upbeat Assistant); Friendly in-game companion → `6ccbfb76-1fc6-48f7-b71d-91ac6298247b` (Tessa - Kind Companion); Slow, calm long-form read → `98a34ef2-2140-4c28-9c71-663dc4dd7022` (Clyde - Calm Narrator).

## 3. Field mapping, Fish Audio → Cartesia
- `POST https://api.fish.audio/v1/tts` → `POST /tts/bytes`
- `Authorization: Bearer $FISH_API_KEY` → `X-API-Key` and `Cartesia-Version: 2026-08-14`
- `model` header: `s2.1-pro`, `s2-pro`, `s1` or `drama-3` → `model_id`: `sonic-3.6` in the body
- `text` → `transcript`
- `reference_id` → `voice`: `{"id": "<voice id>"}`. Fish Audio voice models don't export. Pick a library voice or clone the source recording.
- `format`: `wav`, `pcm` or `mp3` → `output_format`: `container` `wav`, `raw` or `mp3`. Fish Audio's `pcm` is 16-bit mono. Set `raw` with `pcm_s16le` to match it.
- `sample_rate` → `output_format.sample_rate`
- `mp3_bitrate`: 64, 128 or 192 → `output_format.bit_rate`: 32000 to 192000. Cartesia counts bits per second, so 128 becomes 128000.
- `prosody.speed` (0.5 to 2.0) → `generation_config.speed` (0.6 to 1.5). Cap anything under 0.6 or over 1.5 at the nearest end.
- `prosody.volume` (decibels) → `generation_config.volume` (0.5 to 2.0). Cartesia uses a multiplier, not decibels. Match loudness by listening.
- Emotion tags in the text, `[happy]` on S2 or `(happy)` on S1 → `generation_config.emotion`, or an `emotion` tag in the transcript. Cartesia accepts a fixed list of emotions. Free-form cues such as `[whispers sweetly]` need rewording.
- `pronunciation_dictionary` (up to 3) → `pronunciation_dict_id` (one dictionary). Merge your dictionaries into one before uploading.

## 4. Fish Audio fields with no Cartesia equivalent
- `references`: inline audio and transcript, MessagePack only. What to do: Clone the clip once with `client.voices.clone(clip=..., language=..., name=...)` and reuse the ID.
- `format`: `opus`. What to do: Request `mp3` or raw PCM and transcode to Opus.
- `latency`, `chunk_length`, `temperature`, `top_p`. What to do: Drop them.
- `<|speaker:0|>` multi-speaker tags. What to do: Send each speaker's lines as their own request and join the audio.

## 5. Reference request
Match the language and HTTP client the codebase already uses. This is the same request in Python:
```python
import os
import requests

text = "Your character reached level ten. A new quest is waiting at the harbor."
VOICE_ID = "6ccbfb76-1fc6-48f7-b71d-91ac6298247b"  # from /voices

response = requests.post(
    "https://api.cartesia.ai/tts/bytes",
    headers={
        "X-API-Key": os.environ["CARTESIA_API_KEY"],
        "Cartesia-Version": "2026-08-14",
    },
    json={
        "model_id": "sonic-3.6",
        "transcript": text,
        "voice": {"id": VOICE_ID},
        "language": "en",
        "output_format": {
            "container": "wav",
            "encoding": "pcm_s16le",
            "sample_rate": 44100,
        },
    },
)
response.raise_for_status()
open("out.wav", "wb").write(response.content)
```

## 6. Roll out
1. Choose Fish Audio or Cartesia per request from one config flag, defaulting to Fish Audio.
2. Run the same scripts through both and save the clips side by side for me to listen to. Check that the container, encoding and sample rate match what downstream code expects.
3. Leave the Fish Audio client, call and key in place so rollback is flipping the flag. Don't delete them in this change.
4. Run the existing tests, and add one that checks the Cartesia request body.

## Docs
- Fish Audio text-to-speech API reference: https://docs.fish.audio/api-reference/endpoint/openapi-v1/text-to-speech
- Fish Audio quickstart: https://docs.fish.audio/developer-guide/getting-started/quickstart
- Fish Audio voice cloning best practices: https://docs.fish.audio/developer-guide/best-practices/voice-cloning
- Fish Audio emotion tags: https://docs.fish.audio/developer-guide/core-features/emotions
- Cartesia TTS bytes API reference: https://docs.cartesia.ai/api-reference/tts/bytes
- Cartesia SSML tags: https://docs.cartesia.ai/build-with-cartesia/capability-guides/ssml-tags

When you're done, tell me which files changed, which fields you couldn't map, and how to flip the flag.

Every Fish Audio field, mapped to Cartesia

The prompt carries this table. Each row is a field in your Fish Audio request and the Cartesia field that replaces it.

  1. Fish Audio

    POST https://api.fish.audio/v1/tts

    Cartesia
    POST /tts/bytes
  2. Fish Audio

    Authorization: Bearer $FISH_API_KEY

    Cartesia
    X-API-Key and Cartesia-Version: 2026-08-14
  3. Fish Audio

    model header: s2.1-pro, s2-pro, s1 or drama-3

    Cartesia
    model_id: sonic-3.6 in the body
  4. Fish Audio

    text

    Cartesia
    transcript
  5. Fish Audio

    reference_id

    Cartesia
    voice: {"id": "<voice id>"}
    Note
    Fish Audio voice models don't export. Pick a library voice or clone the source recording.
  6. Fish Audio

    format: wav, pcm or mp3

    Cartesia
    output_format: container wav, raw or mp3
    Note
    Fish Audio's pcm is 16-bit mono. Set raw with pcm_s16le to match it.
  7. Fish Audio

    sample_rate

    Cartesia
    output_format.sample_rate
  8. Fish Audio

    mp3_bitrate: 64, 128 or 192

    Cartesia
    output_format.bit_rate: 32000 to 192000
    Note
    Cartesia counts bits per second, so 128 becomes 128000.
  9. Fish Audio

    prosody.speed (0.5 to 2.0)

    Cartesia
    generation_config.speed (0.6 to 1.5)
    Note
    Cap anything under 0.6 or over 1.5 at the nearest end.
  10. Fish Audio

    prosody.volume (decibels)

    Cartesia
    generation_config.volume (0.5 to 2.0)
    Note
    Cartesia uses a multiplier, not decibels. Match loudness by listening.
  11. Fish Audio

    Emotion tags in the text, [happy] on S2 or (happy) on S1

    Cartesia
    generation_config.emotion, or an emotion tag in the transcript
    Note
    Cartesia accepts a fixed list of emotions. Free-form cues such as [whispers sweetly] need rewording.
  12. Fish Audio

    pronunciation_dictionary (up to 3)

    Cartesia
    pronunciation_dict_id (one dictionary)
    Note
    Merge your dictionaries into one before uploading.

Fish Audio API key and auth, mapped to Cartesia

Cartesia reads the key from the X-API-Key header and pins the API version with Cartesia-Version on every request.

  1. Fish Audio

    Authorization: Bearer token

    Cartesia
    X-API-Key plus Cartesia-Version: 2026-08-14
    Note
    Fish Audio shows a new key once, on its developer page. Copy it before you close the dialog.
  2. Fish Audio

    FISH_API_KEY

    Cartesia
    CARTESIA_API_KEY

Fish Audio API pricing per 1,000 characters

List prices per 1,000 characters from the vendor's own pricing page. Plans, regions and volume discounts change what you pay.

  1. Model or plan

    s2.1-pro, s2-pro and s1

    Fish Audio
    $0.015
    Note
    $15 per million UTF-8 bytes. English text is one byte per character; Chinese, Japanese and Korean are three.
  2. Model or plan

    s2.1-pro-free

    Fish Audio
    $0
    Note
    Fair-use limits, no latency guarantee
  3. Model or plan

    drama-3

    Fish Audio
    $0.05
    Note
    $50 per million bytes; $10 promotional price until November 12, 2026

On Cartesia, usage draws from your plan's credits: 20,000 credits a month on the Free plan (about 20,000 characters). Enterprise pricing is custom.

Cartesia plans and pricing

Sources

Prices read from each company's pricing page in November 2026.

Fish Audio limits compared with Cartesia

Published limits from both companies. Plans change them, so check both pages before you size a rollout.

  1. Limit

    Free tier

    Cartesia
    20,000 credits a month on the Free plan (about 20,000 characters)
    Fish Audio
    No API credit for new accounts; s2.1-pro-free costs nothing under fair-use limits
  2. Limit

    Languages

    Cartesia
    44 languages for text to speech
    Fish Audio
    83 languages on S2.1-Pro

Cartesia's figures come from its pricing page and voice library.

Cartesia pricing and plan limits

Sources

Limits read from each company's documentation in November 2026.

What you get on Cartesia

What changes once the Fish Audio call is gone.

Billed per character, not per byte

Fish Audio meters text in UTF-8 bytes, so each Chinese, Japanese or Korean character counts as three. Cartesia charges 1 credit per character.

Clone once, then send an ID

Fish Audio's inline references carry audio inside each request and require MessagePack. On Cartesia you upload a clip once, from 10 seconds, and every TTS call stays plain JSON with a voice ID.

How to migrate from Fish Audio to Cartesia

The same changes the prompt makes, if you'd rather make them yourself.

  1. Create a Cartesia API key and store it next to FISH_API_KEY.

  2. For each reference_id you call, pick a library voice by role, or clone the original recording. Fish Audio asks for at least 10 seconds of audio, which is also Cartesia's instant-clone minimum.

  3. Move the model from the header into model_id, rename text to transcript and nest the format fields under output_format.

  4. Rewrite bracketed emotion cues as Cartesia emotions, and split multi-speaker scripts into one request per speaker.

  5. Ship behind a flag for a share of traffic and compare the same lines on both before you drop the Fish Audio path.

Frequently asked questions

Where do I get a Fish Audio API key, and what replaces it?

Fish Audio creates the key in one click on its developer page and shows it once; its docs read it from FISH_API_KEY and send it as a Bearer token. On Cartesia, create a key in the dashboard, keep it in CARTESIA_API_KEY, and send it as X-API-Key with a Cartesia-Version header.

Is the Fish Audio API free?

Partly. New API accounts start with no credit, and paid models return 402 until you add some. The s2.1-pro-free model costs nothing under fair-use limits, with no latency guarantee. Fish Audio's consumer plans are billed separately from the API.

Can I bring my Fish Audio voice to Cartesia?

Not the reference_id. Clone the original recording, if you have it and permission to use it: Cartesia's instant clone takes 10 seconds of audio on a Pro plan or higher, and Sonic 3.6 learns from up to 60 seconds.

What doesn't carry over from Fish Audio?

Free-form bracket cues, multi-speaker tags, Opus output and the latency, chunk_length, temperature and top_p controls. Speed narrows to 0.6 to 1.5, and you get one pronunciation dictionary per request where Fish Audio takes three.

How do I move traffic over without a big switch?

Wrap both request builders behind one function and route by a percentage flag. Start with the voices that have the closest Cartesia match, log which vendor rendered each line, and set the flag back to zero for any voice that players report.

Get started today

Talk to an expert.

Connect with a member of our team and learn how Cartesia can help you build world-class voice experiences.

Contact Sales

Start building.

Create an API key, then hand your coding agent the migration prompt and a few of your own scripts.

Try Cartesia