
List TTS voices via the xAI API
Pull the live built-in Text to Speech voice catalog from the API when product pickers, deploy checks, or docs must show the ids the service accepts today instead of a hard-coded shortlist. Official Voice REST reference documents GET https://api.x.ai/v1/tts/voices with Bearer API-key auth and a JSON voices array of objects that each carry voice_id, name, and optional language. The Text to Speech guide points to the same list endpoint for programmatic discovery and notes that voice ids are case-insensitive when you later pass them as voice_id on unary TTS or as voice on streaming TTS and Speech to Speech sessions.
What you need
An xAI inference API key for the team that will synthesize audio. This list is the built-in roster only: team-owned clones stay on GET https://api.x.ai/v1/custom-voices, covered by List custom voices via the xAI API. Neighboring jobs include Get a TTS voice via the API, Pick built-in voices for the Grok Voice API, and Convert text to speech with the Voice API. More voice jobs live on the Voice hub.
Call the list endpoint
Export the key outside of source control, then GET the collection with no query parameters required:
export XAI_API_KEY="your_api_key"
curl -s https://api.x.ai/v1/tts/voices \
-H "Authorization: Bearer ${XAI_API_KEY}"
import json
import os
import requests
response = requests.get(
"https://api.x.ai/v1/tts/voices",
headers={"Authorization": f"Bearer {os.environ['XAI_API_KEY']}"},
)
response.raise_for_status()
payload = response.json()
for voice in payload.get("voices", []):
print(voice["voice_id"], voice.get("name"), voice.get("language"))
Expect objects shaped like {"voice_id":"eve","name":"Eve","language":"en"}. Persist voice_id values for later unary or streaming calls; display name in UI labels. Refresh the list in CI or at app boot when you refuse to ship a stale enum that omits newly published built-ins.
Use an id after listing
Pass a listed voice_id on unary TTS:
curl -X POST https://api.x.ai/v1/tts \
-H "Authorization: Bearer ${XAI_API_KEY}" \
-H "Content-Type: application/json" \
-d '{"text":"Welcome.","voice_id":"eve","language":"en"}' \
--output welcome.mp3
On streaming TTS, the same id becomes the voice query parameter. Custom clones never appear in this response; if your inventory must include clones, call the Custom Voices list in parallel and merge in your own UI with a clear built-in versus custom badge.
Pitfalls
Treating a marketing table of five classic names as the complete catalog misses additional built-ins that only show up on this GET. Looking for custom clones here and concluding the team has none is the wrong endpoint — use List custom voices via the xAI API. Caching the list forever without a refresh leaves pickers offering retired or renamed ids after the service updates the roster. Case tricks such as Eve versus eve usually work at synthesize time, but store the lowercase voice_id from the list response so logs and allowlists stay consistent.