VOICE / get-a-custom-voice-via-xai-api

Voice

Get a custom voice via the xAI API

Fetch metadata for one team-owned custom voice when you already know its voice_id and need labels, language, or created_at without paging the full list. Official Custom Voices documents GET https://api.x.ai/v1/custom-voices/{voice_id} with Bearer API-key auth. A successful response returns the same voice object shape as create (including voice_id, name, optional description and taxonomy fields, and created_at). Unknown ids and voices owned by another team return 404, which is the signal to stop retrying that id on this key.

What you need

An xAI API key for the team that owns the clone, and an eight-character lowercase alphanumeric voice_id from Create a custom voice, the console Copy Voice ID action, or List custom voices via the xAI API. Custom Voices availability is United States only, except Illinois, per the same docs. Neighboring jobs include Update custom voice metadata via the xAI API, Download custom voice reference audio, and Delete a custom voice via the xAI API. More voice jobs live on the Voice hub.

Request a single voice object

  1. Export the inference API key outside of source control:
export XAI_API_KEY="your_api_key"
export VOICE_ID="nlbqfwie"   # replace with your team voice_id
  1. GET the voice by path segment (no request body):
curl -s "https://api.x.ai/v1/custom-voices/${VOICE_ID}" \
  -H "Authorization: Bearer ${XAI_API_KEY}"
  1. Expect JSON matching the create response shape, for example:
{
  "voice_id": "nlbqfwie",
  "name": "Friendly Narrator",
  "description": "Warm, conversational tone for narration.",
  "gender": "female",
  "accent": "American",
  "age": "young",
  "language": "en",
  "use_case": "narration",
  "tone": "warm",
  "created_at": "2026-04-26T18:56:34.872993+00:00"
}
  1. Pass voice_id into unary POST /v1/tts as voice_id, into streaming TTS as the voice query parameter, or into Speech-to-Speech session.voice. Custom clones never appear on GET /v1/tts/voices; that list stays built-in only.
import os
import requests

voice_id = os.environ["VOICE_ID"]
response = requests.get(
    f"https://api.x.ai/v1/custom-voices/{voice_id}",
    headers={"Authorization": f"Bearer {os.environ['XAI_API_KEY']}"},
)
if response.status_code == 404:
    raise SystemExit("voice not found for this team")
response.raise_for_status()
voice = response.json()
print(voice["voice_id"], voice.get("name"), voice.get("tone"))

When to prefer GET over list

Use the dedicated GET in deploy checks and support tooling that already store a voice_id and only need to confirm the clone still exists with expected labels. Prefer List custom voices via the xAI API when you are discovering ids or paging the whole team inventory. This metadata GET does not return the reference audio bytes — use Download custom voice reference audio for the original clip stream.

Pitfalls

A 404 means the id is missing or belongs to another team; do not treat it as a transient 500. Metadata PATCH never changes the underlying audio — if the clone sounds wrong, delete and create again rather than expecting GET to show a new sample. Client-side calls that expose the API key remain unsupported; keep GETs on your backend.