APIMODELSAPIMODELS
Документация API

apimodels.app

Voices · TTS

Voices & Voice Cloning API

Look up MiniMax, ElevenLabs and Fish Audio preset voices, clone your own from a short sample, or design a brand-new voice from a text description — then use it in any TTS call. Covers the public voice catalog, Minimax (clone / design / system voices) and ElevenLabs custom voices.

Browse all preset voices

One public endpoint lists the preset voices of all three providers: every MiniMax system voice, the ElevenLabs official presets and full shared voice library, and Fish Audio's licensed catalogue plus a large set of community voices. No API key is needed and browsers can call it directly (CORS enabled). The catalog refreshes daily; responses are cached for 5 minutes.

Open the voice library
Search and page through voices
GET https://api.apimodels.app/v1/voices/catalog
Totals and breakdowns
GET https://api.apimodels.app/v1/voices/catalog/manifest
# Public endpoint: no API key, CORS enabled, cached for 5 minutes.

# ElevenLabs: English female voices, most-used first
curl "https://api.apimodels.app/v1/voices/catalog?provider=elevenlabs&language=en&gender=female&page_size=20"

# Fish Audio: licensed Japanese voices
curl "https://api.apimodels.app/v1/voices/catalog?provider=fish&source=licensed&language=ja"

# MiniMax: Cantonese system voices (Cantonese is "yue"), A-Z
curl "https://api.apimodels.app/v1/voices/catalog?provider=minimax&language=yue&sort=name"

# Totals per provider, plus counts by source and by language
curl "https://api.apimodels.app/v1/voices/catalog/manifest"

Query parameters

FieldRequiredTypeDescription
providerrecommendedstringminimax | elevenlabs | fish
sourcenostringminimax: system; elevenlabs: premade (official presets) | professional | library (shared voice library); fish: licensed | community
languagenostringISO 639-1 code such as en, ja or es; Cantonese is yue
gendernostringfemale | male | neutral (MiniMax voices are tagged only where the name makes it clear; Fish voices carry no gender)
qnostringSearches name, ID, description, accent and use case
sortnostringpopular (default, by usage) | name
pagenointegerPage number, starting at 1
page_sizenointegerItems per page, default 50, at most 100

Response fields

FieldRequiredTypeDescription
data.total—integerNumber of voices matching the filters
data.page / page_size / has_more—int / int / boolPaging; while has_more is true, request page + 1
data.items[].id—stringVoice ID: send as voice_id (MiniMax, ElevenLabs) or reference_id (Fish Audio)
data.items[].name / provider / source—stringDisplay name, provider and source
data.items[].languages—string[]ISO 639-1 language codes; may be empty
data.items[].gender / age / accentoptionalstringGender, age group and accent (mostly ElevenLabs)
data.items[].description / use_caseoptionalstringDescription and suggested use case
data.items[].preview_urloptionalstringSample audio to audition the voice before you generate (ElevenLabs and Fish Audio; MiniMax system voices have none)
data.items[].uses / likesoptionalintegerUsage and like counts on the provider's own platform; popular sort uses them
data.generated_at—stringWhen the catalog was built (UTC)
data.usage—objectWhich request field takes the ID, per provider

The manifest returns { version, generated_at, providers: { minimax | elevenlabs | fish: { total, by_source, by_language } }, usage }.

Sample response (trimmed to one voice)

{
  "code": 200,
  "msg": "success",
  "data": {
    "total": 3739,
    "page": 1,
    "page_size": 20,
    "has_more": true,
    "items": [
      {
        "id": "tnSpp4vdxKPjI9w0GnoV",
        "name": "Hope - upbeat and clear",
        "provider": "elevenlabs",
        "source": "library",
        "languages": ["en", "fr", "es", "de", "pt"],
        "gender": "female",
        "age": "young",
        "accent": "american",
        "description": "upbeat",
        "use_case": "social_media",
        "preview_url": "https://storage.googleapis.com/eleven-public-prod/custom/voices/tnSpp4vdxKPjI9w0GnoV/LiIyxRT1qFJ1QJPr8sWl.mp3",
        "uses": 1413857
      }
    ],
    "generated_at": "2026-10-29T15:25:41.771Z",
    "usage": {
      "minimax": "Pass id as voice_id (or voice_setting.voice_id) to any minimax-speech-* model on /v1/audio/generations",
      "elevenlabs": "Pass id as voice_id to any ElevenLabs TTS model on /v1/audio/generations",
      "fish": "Pass id as reference_id to fish-s2.1-pro / fish-drama-3 on /v1/audio/generations. ..."
    }
  }
}

Use the id in a TTS request

ElevenLabs and MiniMax take the id as voice_id (voice_setting.voice_id on /v1/minimax/tts); Fish Audio takes it as reference_id. Fish licensed voices are billed at a higher rate: twice on S2.1 Pro, 2.5 times on Drama 3. Community voices are user uploads and some imitate real people, so check the rights before commercial use.

# Take an item's "id" straight into a TTS request.

# ElevenLabs -> voice_id
curl -X POST https://api.apimodels.app/v1/audio/generations \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "model": "eleven-tts-v3", "text": "Hello from the voice library.", "voice_id": "tnSpp4vdxKPjI9w0GnoV" }'

# Fish Audio -> reference_id
curl -X POST https://api.apimodels.app/v1/audio/generations \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "model": "fish-s2.1-pro", "text": "こんにちは。", "reference_id": "297a6fd278df47c3b9da9bfdf55ac89a" }'

# MiniMax -> voice_id on /v1/audio/generations, or voice_setting.voice_id on /v1/minimax/tts
curl -X POST https://api.apimodels.app/v1/minimax/tts \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "model": "minimax-speech-2.8-turbo", "text": "歡迎收聽。", "voice_setting": { "voice_id": "Cantonese_GentleLady" } }'

Find a voice, then speak with it (Python / Node)

cURL

# 1) Find a voice (no API key)
curl "https://api.apimodels.app/v1/voices/catalog?provider=elevenlabs&language=en&gender=female&page_size=20"

# 2) Speak with it (items[0].id -> voice_id)
curl -X POST https://api.apimodels.app/v1/audio/generations \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "model": "eleven-tts-v3", "text": "Hello from the voice library.", "voice_id": "tnSpp4vdxKPjI9w0GnoV" }'

Python

import os, requests

CATALOG = "https://api.apimodels.app/v1/voices/catalog"
API = "https://api.apimodels.app/v1"
H = {"Authorization": f"Bearer {os.environ['API_KEY']}", "Content-Type": "application/json"}

# 1) Find a voice. The catalog needs no API key.
data = requests.get(CATALOG, params={
    "provider": "elevenlabs", "language": "en", "gender": "female", "page_size": 20,
}).json()["data"]
voice = data["items"][0]
print(data["total"], voice["name"], voice["id"])
print("audition first:", voice.get("preview_url"))  # ElevenLabs and Fish; MiniMax has none

# 2) Speak with it. ElevenLabs and MiniMax take the id as voice_id, Fish Audio as reference_id.
task = requests.post(f"{API}/audio/generations", headers=H, json={
    "model": "eleven-tts-v3",
    "text": "Hello from the voice library.",
    "voice_id": voice["id"],
}).json()
print(task["data"]["taskId"])

# Fish Audio:  {"model": "fish-s2.1-pro", "text": "...", "reference_id": voice["id"]}
# MiniMax:     {"model": "minimax-speech-2.8-turbo", "text": "...", "voice_id": voice["id"]}

Node.js

const CATALOG = "https://api.apimodels.app/v1/voices/catalog";
const API = "https://api.apimodels.app/v1";
const H = { Authorization: `Bearer ${process.env.API_KEY}`, "Content-Type": "application/json" };

// 1) Find a voice. The catalog needs no API key.
const qs = new URLSearchParams({ provider: "fish", source: "licensed", language: "ja" });
const { data } = await fetch(`${CATALOG}?${qs}`).then((r) => r.json());
const voice = data.items[0];
console.log(data.total, voice.name, voice.id, voice.preview_url);

// 2) Speak with it. Fish Audio takes the id as reference_id.
const task = await fetch(`${API}/audio/generations`, {
  method: "POST",
  headers: H,
  body: JSON.stringify({ model: "fish-s2.1-pro", text: "こんにちは。", reference_id: voice.id }),
}).then((r) => r.json());
console.log(task.data.taskId);

Endpoints at a glance

All preset voices (public)
GET /voices/catalog · /voices/catalog/manifest
List system voices
GET /minimax/voices · /audio/voices
List my voices
GET /voices?source=account
Upload sample
POST /minimax/files
Clone voice
POST /minimax/voice/clone
Design voice
POST /minimax/voice/design
Custom voice (EL)
POST /audio/voices/custom

⚠️ Billing: voice cloning is $1.41 per voice, voice design is $15.80 per voice (both charged only on success — failures are auto-refunded). Using system preset voices incurs no extra fee.

1. List voices

Grab a voice_id and drop it into a TTS call. System voices are free and ready to use; source=account returns the voices you cloned / designed / created. To search every preset voice across providers, preview URLs included, use the public catalog above.

# Minimax system voices (optionally filter by language)
curl "https://api.apimodels.app/v1/minimax/voices?language=English" \
  -H "Authorization: Bearer $API_KEY"

# ElevenLabs / preset voices
curl "https://api.apimodels.app/v1/audio/voices?pageNum=1&pageSize=30" \
  -H "Authorization: Bearer $API_KEY"

# Voices on your own account (cloned / designed / custom)
curl "https://api.apimodels.app/v1/voices?source=account" \
  -H "Authorization: Bearer $API_KEY"

Response (Minimax example)

{
  "voices": [
    { "voice_id": "English_Graceful_Lady", "name": "Graceful Lady", "language": "English" },
    { "voice_id": "male-qn-qingse", "name": "Qingse", "language": "Chinese" }
  ],
  "total": 2
}

2. Clone a voice (3 steps)

Prepare a clean voice sample (10s-5min, no background noise). Upload to get a file_id → clone into your chosen voice_id → use it in TTS.

Step 1: upload the sample

# Step 1 — upload your voice sample (10s-5min clean audio)
curl -X POST https://api.apimodels.app/v1/minimax/files \
  -H "Authorization: Bearer $API_KEY" \
  -F "purpose=voice_clone" \
  -F "file=@my-voice-sample.mp3"   # mp3 / m4a / wav, <= 20MB
# -> { "file": { "file_id": 123456789, ... } }

Step 2: clone

# Step 2 — clone it. voice_id is optional (generated if omitted); if you set one: 8-256 chars, starts with a letter, letters/digits/-/_ only, must not end with - or _
curl -X POST https://api.apimodels.app/v1/minimax/voice/clone \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "file_id": 123456789,
    "voice_id": "myBrandVoice01"
  }'
FieldRequiredTypeDescription
file_idone ofnumberThe file ID returned by the step-1 upload (sample must be mp3 / m4a / wav, <= 20MB)
voice_urlone ofstringPublic URL of the sample audio, instead of file_id
voice_idnostringID for the new voice; omit it and one is generated and returned. If you set one: 8-256 chars, starts with a letter, letters/digits/-/_ only, must not end with - or _
textnostringOptional preview text; when set, model is required and the response also carries demo_audio
modelwith textstringTTS model for the preview, e.g. minimax-speech-02-hd; omit it when text is omitted

Step 3: synthesize with the cloned voice

# Step 3 — use the cloned voice in TTS
curl -X POST https://api.apimodels.app/v1/minimax/tts \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "minimax-speech-02-turbo",
    "text": "This sentence is spoken in my own cloned voice.",
    "voice_setting": { "voice_id": "myBrandVoice01", "speed": 1.0 }
  }'

Full 3-step flow (Python / Node)

cURL

# Step 2 — clone it. voice_id is optional (generated if omitted); if you set one: 8-256 chars, starts with a letter, letters/digits/-/_ only, must not end with - or _
curl -X POST https://api.apimodels.app/v1/minimax/voice/clone \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "file_id": 123456789,
    "voice_id": "myBrandVoice01"
  }'

Python

import os, requests

API = "https://api.apimodels.app/v1"
H = {"Authorization": f"Bearer {os.environ['API_KEY']}"}

# 1) Upload the sample
file_id = requests.post(
    f"{API}/minimax/files",
    headers=H,
    data={"purpose": "voice_clone"},
    files={"file": open("my-voice-sample.mp3", "rb")},
).json()["file"]["file_id"]

# 2) Clone -> your new voice_id
requests.post(
    f"{API}/minimax/voice/clone",
    headers={**H, "Content-Type": "application/json"},
    json={"file_id": file_id, "voice_id": "myBrandVoice01"},
)

# 3) Speak with it
audio = requests.post(
    f"{API}/minimax/tts",
    headers={**H, "Content-Type": "application/json"},
    json={
        "model": "minimax-speech-02-turbo",
        "text": "This sentence is spoken in my own cloned voice.",
        "voice_setting": {"voice_id": "myBrandVoice01"},
    },
)
print(audio.json())

Node.js

const API = "https://api.apimodels.app/v1";
const H = { Authorization: `Bearer ${process.env.API_KEY}` };
import fs from "node:fs";

// 1) Upload the sample
const form = new FormData();
form.append("purpose", "voice_clone");
form.append("file", new Blob([fs.readFileSync("my-voice-sample.mp3")]), "sample.mp3");
const { file } = await fetch(`${API}/minimax/files`, { method: "POST", headers: H, body: form })
  .then((r) => r.json());

// 2) Clone -> your new voice_id
await fetch(`${API}/minimax/voice/clone`, {
  method: "POST",
  headers: { ...H, "Content-Type": "application/json" },
  body: JSON.stringify({ file_id: file.file_id, voice_id: "myBrandVoice01" }),
});

// 3) Speak with it
const audio = await fetch(`${API}/minimax/tts`, {
  method: "POST",
  headers: { ...H, "Content-Type": "application/json" },
  body: JSON.stringify({
    model: "minimax-speech-02-turbo",
    text: "This sentence is spoken in my own cloned voice.",
    voice_setting: { voice_id: "myBrandVoice01" },
  }),
}).then((r) => r.json());
console.log(audio);

3. Design a voice (no sample)

Generate a brand-new voice from a text description alone — handy when you have no recording. You get a voice_id back to use in TTS.

# Create a brand-new voice from a text description (no sample needed)
curl -X POST https://api.apimodels.app/v1/minimax/voice/design \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "prompt": "A warm, calm middle-aged male narrator with a slight British accent",
    "preview_text": "Welcome to the evening news.",
    "voice_id": "designedVoice01"
  }'
FieldRequiredTypeDescription
promptyesstringText description of the target voice (gender, age, accent, tone…)
preview_textnostringText used to render a preview
voice_idyesstringYour new voice ID

4. Custom voice (ElevenLabs)

Create an ElevenLabs custom voice from a public audio URL (or upload first via the Files API). Provide either voice_url or video_id.

# ElevenLabs-style custom voice from a hosted audio URL (or video_id)
curl -X POST https://api.apimodels.app/v1/audio/voices/custom \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "voice_name": "My Narrator",
    "voice_url": "https://r2.apimodels.app/uploads/.../sample.mp3"
  }'
FieldRequiredTypeDescription
voice_nameyesstringDisplay name for the voice
voice_urlone ofstringPublic URL of the sample audio
video_idone ofstringID of previously uploaded media (instead of voice_url)
callback_urlnostringWebhook called when ready

FAQ

How do I get a list of ElevenLabs, MiniMax or Fish Audio voice IDs?

Call GET https://api.apimodels.app/v1/voices/catalog with provider=elevenlabs, minimax or fish. It needs no API key, supports language, gender, source, q and sort filters, and pages up to 100 voices at a time. GET /v1/voices/catalog/manifest returns the totals. The same data is browsable at apimodels.app/voices.

Which request field takes the voice ID?

voice_id for MiniMax and ElevenLabs models on /v1/audio/generations (voice_setting.voice_id on /v1/minimax/tts), and reference_id for fish-s2.1-pro and fish-drama-3. Each catalog response also carries a usage object that says this per provider.

Can I hear a voice before generating with it?

Yes for ElevenLabs and Fish Audio: each catalog item carries a preview_url with sample audio. MiniMax publishes no samples for its system voices, so generate a short line on the model page instead.