Migrate from the OpenAI speech endpoint.
Two changes in your client code: a new base URL and a new key. The rest of the OpenAI SDK call shape stays the same. This page covers the exact substitutions and the small differences.
The two-line change
The OpenAI Python SDK accepts a custom base_url. Point it at the Gandr endpoint and swap the key. The rest of your code is unchanged.
# Python, OpenAI SDK
# Before
from openai import OpenAI
client = OpenAI(api_key="sk-...")
# After
from openai import OpenAI
client = OpenAI(
api_key="gnd_...",
base_url="https://tts.gandr.ai/v1",
)
# Your existing call works as-is:
response = client.audio.speech.create(
model="tts-1",
voice="gandr-mia", # see voice mapping below
input="The quick brown fox jumps over the lazy dog.",
)
response.stream_to_file("output.mp3")
# ---
# Node (OpenAI SDK)
# const client = new OpenAI({ apiKey: "gnd_...", baseURL: "https://tts.gandr.ai/v1" })
# const response = await client.audio.speech.create({ model: "tts-1", voice: "gandr-mia", input: "..." })
# ---
# Raw HTTP (works identically to the OpenAI endpoint)
# curl -X POST https://tts.gandr.ai/v1/audio/speech \
# -H "Authorization: Bearer gnd_..." \
# -H "Content-Type: application/json" \
# -d '{"model":"tts-1","input":"Hello world.","voice":"gandr-mia","response_format":"mp3"}' \
# -o output.mp3
The API key comes from your Gandr account. Free tier includes 50,000 tokens. One token is one character.
What changes
What it takes
| base_url | https://tts.gandr.ai/v1 |
| api_key | gnd_... from your Gandr account |
| voice | see voice mapping table in the section below |
| model | tts-1 works as-is |
Voice mapping
Gandr ships six voices. The table below maps the six OpenAI voice names to Gandr voices by character. These are suggestions: listen to all six and pick the ones that fit your use case.
- alloy -> gandr-mia (clear, neutral female)
- echo -> gandr-leo (measured male)
- fable -> gandr-lewis (warmer male, storytelling)
- onyx -> gandr-dane (deep, authoritative male)
- nova -> gandr-jenny (bright female)
- shimmer -> gandr-ava (soft female)
Differences from the OpenAI endpoint
Most call shapes are identical. These are the points where the two endpoints behave differently.
- Character cap: 2000 characters per request. Split longer text at sentence boundaries and send multiple requests.
- Formats: mp3 (default), wav, pcm. mp3 and wav behave the same as on the OpenAI endpoint. pcm is headerless s16le mono 24000 Hz, no WAV container.
- Unit: one token is one character. Usage and billing are in tokens.
- Voices: six Gandr voices (see table above). Passing an OpenAI voice name returns an error; update the voice parameter.
- Languages: 23 languages across all voices.
- Watermarking: every render is watermarked.
- Speed parameter: pass speed in the request body (0.25 to 4.0) as with the OpenAI endpoint.
PCM format detail
If you use response_format pcm, note that Gandr PCM is headerless signed 16-bit little-endian mono at 24000 Hz, streaming as a plain chunked HTTP body. There is no WAV header and no container. If your pipeline expects a different sample rate, resample after receiving the bytes.
Free tier
The free tier is 50,000 tokens. One token is one character. There is no time limit on the free tier.
Notes
Do I need to change the model name?
No. tts-1 is accepted as-is.
What happens if I pass an OpenAI voice name?
The API returns an error. Update the voice parameter to one of the six Gandr voice names: gandr-mia, gandr-ava, gandr-jenny, gandr-dane, gandr-leo, gandr-lewis.
Is the response streaming?
Yes. The response body streams over plain HTTP the same way the OpenAI endpoint does. SDK methods like stream_to_file and iter_bytes work without changes.
What is the per-request character limit?
2000 characters. If your existing code sends longer strings, add a split step before calling the API.
How do I get an API key?
Keys are available from your Gandr account. The free tier includes 50,000 tokens with no expiry.
Is the response_format parameter the same?
Supported formats are mp3, wav, and pcm. The default is mp3. The tts-1-hd model variant is not available; tts-1 is the model to use.
Two lines changed and your existing code works against the Gandr endpoint.
Get a keyFull API reference , gandr.ai/docs