Call /v1/audio/speech with model, input, and optional voice

Speech synthesis is OpenAI-shaped: POST JSON with a model, the input text, and optional parameters. The voice list is model-specific -- each TTS model supports its own set, and voices cannot be mixed across models. When voice is omitted, the gateway applies the model's documented default.

curl
curl https://modelxing.com/v1/audio/speech \
  -H "Authorization: Bearer $NEXTMODEL_API_KEY" \
  -H "Content-Type: application/json" \
  -o speech.wav \
  -d '{
    "model": "qwen3-tts-instruct-flash",
    "input": "今天天气不错,适合出门走走。",
    "voice": "Cherry",
    "response_format": "wav"
  }'
Python
from openai import OpenAI

client = OpenAI(
    api_key="YOUR_API_KEY",
    base_url="https://modelxing.com/v1"
)

with client.audio.speech.with_streaming_response.create(
    model="qwen3-tts-instruct-flash",
    voice="Cherry",
    input="今天天气不错,适合出门走走。",
    response_format="wav",
) as response:
    response.stream_to_file("speech.wav")
modelTTS model id from the catalog (each family has its own voice set)
inputText to synthesize; must be within the voice's supported languages
voiceOptional; omitted means the model's documented default voice
response_formatOptional; wav, mp3, pcm where supported

Discover each model's voices and defaults machine-readably

GET /v1/models/{id} returns an invocation object for TTS models: the endpoint, the default voice applied when you omit one, the full curated voice list with labels, languages and feature flags (SSML, instruct, timestamps), response formats, and the official doc the list was captured from. The same contract powers the voice table on each model's detail page.

GET /v1/models/qwen3-tts-instruct-flashReturns the invocation contract with all 24 voices
GET /v1/models/cosyvoice-v3-flashCosyVoice family: long* voice ids, dialect-capable voices
GET /v1/models/qwen-audio-3.0-tts-flashQwen-Audio family: longan* ids plus 500+ clone base voices

Voice errors are self-describing

The voice list is advisory and can lag upstream docs, so an unknown voice is never rejected locally -- the request goes upstream, which is the final judge. When the upstream rejects a voice, the error message is annotated with the model's supported voice list and the model detail endpoint, so agents can correct the call without reading external documentation.

Clone and design flows replace static voice lists

Some models do not have a fixed voice set: cosyvoice-clone-v1 and qwen3-tts-vc use cloned voices, qwen3-tts-vd generates a voice from a text description, and the cosyvoice-v3.5 family accepts cloned voices only (no system voices exist, so voice is required on every call). For these, first create the voice asset via POST /v1/audio/assets, then synthesize with the returned voice id. Their invocation contract documents the flow instead of a voice table.