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 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"
}'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")| model | TTS model id from the catalog (each family has its own voice set) |
| input | Text to synthesize; must be within the voice's supported languages |
| voice | Optional; omitted means the model's documented default voice |
| response_format | Optional; 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-flash | Returns the invocation contract with all 24 voices |
| GET /v1/models/cosyvoice-v3-flash | CosyVoice family: long* voice ids, dialect-capable voices |
| GET /v1/models/qwen-audio-3.0-tts-flash | Qwen-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.