The POST /v1/tts endpoint
On this page
Updated November 3, 2026, based on the xAI Text to Speech page, Voice API reference, and Pricing page. Sources: Text to Speech · Voice API · Pricing.
Turn text into audio with the Grok API
The xAI Text-to-Speech API turns any text into natural-sounding audio with a single HTTP call. The main entry point is POST /v1/tts, which takes your text and returns a binary audio file directly.
Request structure
You send a POST to https://api.x.ai/v1/tts with a JSON body. Here’s a minimal example with curl:
curl -X POST "https://api.x.ai/v1/tts" \
-H "Authorization: Bearer $XAI_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"text": "Hello, and welcome to Corsen Academy.",
"voice_id": "eve",
"language": "en"
}' \
--output audio.mp3
The server responds with the binary audio file directly in the response body. There’s no JSON envelope around it: you get the raw bytes of the audio file.
Authentication
As with every xAI API endpoint, include your API key in the Authorization header in Bearer format:
Authorization: Bearer xai-your-api-key
Request body
The JSON body revolves around four main parameters:
text(required): the text to convert, up to 60,000 characters. It supports the expressive tags you’ll learn about in the next lessonsvoice_id(optional): the voice ID. Defaults toeve. Values are case-insensitivelanguage(required): the language code in BCP-47 format (en,fr,de, …) orautofor automatic detectionoutput_format(optional): an object that configures the codec, sample rate, and bit rate
Other settings, all optional, round out the request: speed (playback speed, from 0.7 to 1.5, 1.0 by default), replace (a table of substitutions that fixes how a word is pronounced without changing the text you send), with_timestamps (per-character timestamps), text_normalization (spelling out numbers, abbreviations, and symbols before synthesis), and optimize_streaming_latency ("1" to shorten the wait before the first chunk of audio, at the cost of a slight quality loss at the joins).
The HTTP response
On success (status 200), the server returns the audio file with the content type that matches the requested format:
audio/mpegfor MP3 (default)audio/wavfor WAVaudio/pcmfor raw PCMaudio/basicfor G.711 μ-law (mulaw)audio/alawfor G.711 A-law (alaw)
The response carries no metadata, only audio bytes. The one exception is with_timestamps: the response then becomes a JSON object that holds the audio in base64, its duration, and the timestamp of each character. You can write the response straight to a file or stream it to an audio player.
Python example
import requests
response = requests.post(
"https://api.x.ai/v1/tts",
headers={"Authorization": f"Bearer {api_key}"},
json={
"text": "Here's an example of speech synthesis.",
"voice_id": "rex",
"language": "en"
}
)
with open("output.mp3", "wb") as f:
f.write(response.content)
JavaScript example (Node.js)
const response = await fetch("https://api.x.ai/v1/tts", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.XAI_API_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
text: "Here's an example of speech synthesis.",
voice_id: "rex",
language: "en"
})
});
const buffer = await response.arrayBuffer();
fs.writeFileSync("output.mp3", Buffer.from(buffer));
Pricing
TTS costs $15 per million characters (xAI pricing as of November 3, 2026). You’re billed for the characters you send in text, expressive tags included; a replace table doesn’t change that count. With an average of 1,000 characters per request, that comes to about $0.015 per call.
Key takeaways
- The
POST /v1/ttsendpoint is the main entry point for speech synthesis - The response is a binary audio file, not JSON
- Text is limited to 60,000 characters per HTTP request; WebSocket has no total limit
- You authenticate with the
Authorization: Bearerheader - It costs $15 per million characters