Text to Speech
POST https://api.mafdet.ai/v1/audio/speech
Turn text into natural speech with the Gemini TTS models. The endpoint is
OpenAI-compatible, so any OpenAI SDK works by pointing base_url at
https://api.mafdet.ai/v1. The response body is the audio file itself
(binary), not JSON.
| Model | Quality | Text input | Audio output |
|---|---|---|---|
gemini-2.5-flash-tts | Fast, everyday narration | $0.60 / 1M tokens | $12 / 1M tokens |
gemini-2.5-pro-tts | Highest quality | $1.20 / 1M tokens | $24 / 1M tokens |
Both are Gemini 2.5 preview TTS models served through Vertex AI.
Request fields
| Field | Type | Description |
|---|---|---|
model | string | gemini-2.5-flash-tts or gemini-2.5-pro-tts |
input | string | The text to speak — up to 5,000 characters |
voice | string | One of Kore, Puck, Charon, Fenrir, Aoede |
response_format | string | Optional: wav (default) or pcm |
These are Gemini voices — OpenAI voice names (alloy, nova, …) are
rejected with TTS_VOICE_NOT_ALLOWED.
Response
The raw audio bytes: 24 kHz, 16-bit, mono. With wav you get a standard
RIFF/WAVE file; pcm returns the bare samples.
Billing
TTS is billed on tokens, both directions: the text input tokens plus the
audio output tokens, at the per-model rates above. A short sentence typically
produces 40–80 audio output tokens (well under a tenth of a cent). Audio output
is capped at 4,000 tokens per request. A rejected request (bad voice, text
too long, …) returns 400 before the provider is called and is never
billed; a failed provider call releases its reservation in full.
curl
curl https://api.mafdet.ai/v1/audio/speech \
-H "Authorization: Bearer $MAFDET_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gemini-2.5-flash-tts",
"input": "Hello from Mafdet AI.",
"voice": "Kore",
"response_format": "wav"
}' \
--output speech.wav
Python (OpenAI SDK)
from openai import OpenAI
client = OpenAI(
base_url="https://api.mafdet.ai/v1",
api_key="sk-mafdet-xxxxxxxxxxxxxxxx",
)
audio = client.audio.speech.create(
model="gemini-2.5-flash-tts",
input="Hello from Mafdet AI.",
voice="Kore",
response_format="wav",
)
audio.write_to_file("speech.wav")
Node.js
const res = await fetch("https://api.mafdet.ai/v1/audio/speech", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.MAFDET_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
model: "gemini-2.5-flash-tts",
input: "Hello from Mafdet AI.",
voice: "Kore",
response_format: "wav",
}),
});
const buf = Buffer.from(await res.arrayBuffer());
await import("node:fs/promises").then((fs) => fs.writeFile("speech.wav", buf));
Error codes
| Code | Meaning |
|---|---|
TTS_INPUT_REQUIRED | input is missing or empty |
TTS_INPUT_TOO_LONG | input exceeded 5,000 characters |
TTS_VOICE_REQUIRED | voice is missing |
TTS_VOICE_NOT_ALLOWED | Voice not in the model's allowlist (the response echoes the allowed voices) |
TTS_FORMAT_NOT_ALLOWED | response_format not wav / pcm |
All of the above return 400 before the provider is called, so a rejected
request is never billed.