Text to speech API
Add natural speech to your product with one HTTP request. The SaydiVoice API exposes an OpenAI-compatible speech endpoint plus voice listing and voice cloning, so you can generate audio in 32 languages without running your own model.
What the TTS API gives you
What is a text to speech API?
A text to speech API lets your software turn text into audio over HTTP instead of through a web interface. You send a request containing the text and the voice you want, and the service returns synthesized speech as an audio file or stream. That makes it possible to add narration to an app, generate audio for user content, build accessibility features or produce voiceovers at scale without installing a speech model or managing the GPUs behind it. SaydiVoice exposes this as a REST API with an OpenAI-compatible speech endpoint, so an existing client can often be pointed at a new base URL and keep working.
Make your first request
The speech endpoint takes JSON and returns audio bytes, so the request is one POST and the response is the file itself. Authenticate with a Bearer token from your account; the response headers report the characters charged (X-OV-Chars), which is what per-key metering is reconciled against.
The request shape follows the OpenAI audio/speech API, so a client already written against that interface usually works after pointing its base URL at https://voice.saydi.ai/api.
export SAYDI_API_KEY="sv_live_REPLACE_WITH_YOUR_KEY"
curl -sS -X POST "https://voice.saydi.ai/api/v1/audio/speech" \
-H "Authorization: Bearer $SAYDI_API_KEY" \
-H "Content-Type: application/json" \
-d '{"model":"tts-1","voice":"vi-adam","input":"Xin chào, đây là API của SaydiVoice."}' \
--output hello.mp3
# -D - prints the response headers, including X-OV-Chars (characters charged).The same call in Python and Node.js
Nothing about the request is cURL-specific: it is a POST with a Bearer token and a JSON body. Both examples below write the returned audio to hello.mp3 and print the characters charged.
import os, requests
API_KEY = os.environ["SAYDI_API_KEY"]
BASE = "https://voice.saydi.ai/api"
r = requests.post(
f"{BASE}/v1/audio/speech",
headers={"Authorization": f"Bearer {API_KEY}"},
json={
"model": "tts-1",
"voice": "vi-adam",
"input": "Xin chào, đây là API của SaydiVoice.",
},
timeout=120,
)
r.raise_for_status()
open("hello.mp3", "wb").write(r.content)
print("chars charged:", r.headers.get("X-OV-Chars"))const API_KEY = process.env.SAYDI_API_KEY;
const BASE = "https://voice.saydi.ai/api";
const res = await fetch(`${BASE}/v1/audio/speech`, {
method: "POST",
headers: {
Authorization: `Bearer ${API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
model: "tts-1",
voice: "vi-adam",
input: "Xin chào, đây là API của SaydiVoice.",
}),
});
if (!res.ok) throw new Error(`HTTP ${res.status}: ${await res.text()}`);
await writeFile("hello.mp3", Buffer.from(await res.arrayBuffer()));List the voices available to your key
Voice ids are stable and language-scoped, so you can build a picker once and store the id a user chose rather than the display name.
curl -sS "https://voice.saydi.ai/api/v1/models" \
-H "Authorization: Bearer $SAYDI_API_KEY"
# One entry per voice, with its language and id. The id is the value you pass
# as "voice" in a speech request:
# {"data":[{"id":"vi-adam","language":"vi","name":"Adam"}, ...]}Clone a voice, then speak with it
Cloning is a two-step flow: upload a short sample to register the voice, then reference the returned id in any later speech request. The cloned voice is available in the studio as well, and counts against the clone slots of your plan.
# 1. Register the voice (multipart). consent=true asserts you have the
# speaker's permission; see the voice consent policy.
curl -sS -X POST "https://voice.saydi.ai/api/v1/voices" \
-H "Authorization: Bearer $SAYDI_API_KEY" \
-F "file=@my-recording.m4a" \
-F "name=My voice" \
-F "language=vi" \
-F "consent=true"
# -> {"id":"vc_9f2c...","status":"ready"}
# 2. Speak with it - the cloned id replaces a catalogue voice id.
curl -sS -X POST "https://voice.saydi.ai/api/v1/audio/speech" \
-H "Authorization: Bearer $SAYDI_API_KEY" \
-H "Content-Type: application/json" \
-d '{"model":"tts-1","voice":"vc_9f2c...","input":"Hello from my own voice."}' \
--output hello.mp3Formats, limits and error handling
Two things are worth handling in client code: the per-key rate limit, and the fact that a failed request returns a JSON error body rather than audio. Check the status code before writing the response to a file - a 4xx body written as .mp3 produces a corrupt file that is easy to misdiagnose later.
| Status | Meaning | What to do |
|---|---|---|
| 200 | Audio bytes returned; X-OV-Chars reports usage | Write the body to a file with the extension you requested |
| 401 | Missing, revoked or malformed Bearer token | Check the key and that the Authorization header is present |
| 402 / 403 | Plan has no API access, or the quota is exhausted | Check the API row on the pricing page, then top up or upgrade |
| 429 | Rate limit (60/min) or concurrency exceeded | Back off and retry; raise concurrency by moving to Pro or Business |
| 5xx | Generation failed upstream | Retry with backoff; the request was not charged |
Pick a voice to turn your text into speech
70 English AI voices to preview for free before you generate. Each has its own page with a sample line and accent details.
How to make your first request
- Create an API key in your account and copy the Bearer token.
- POST your text to /v1/audio/speech with the voice and format you want.
- Read the returned audio, or switch to /tts/file to receive a downloadable file.
API questions
Which plans include API access?
API access is included on the Pro, Custom and Business plans. The free, Starter and Creator plans do not include API keys, because API traffic uses a separate concurrency allowance from the web studio. The pricing page lists the API row per plan.
Is the API OpenAI-compatible?
Yes. The speech endpoint follows the OpenAI audio/speech shape, so a client already written against that interface can usually be repointed at the SaydiVoice base URL. Native endpoints are also available when you want file output or direct control over the response format.
How is API usage metered?
Requests are authenticated with a Bearer token tied to your account and metered against the character allowance of your plan, so API generation and studio generation draw on the same quota. Each key is metered individually, which makes it possible to attribute usage per integration or per customer.
Which audio formats can the API return?
The API returns MP3 and WAV audio, and the file endpoint returns a downloadable result rather than an inline body. That covers the usual cases of embedding audio in a player, saving it to storage, or passing it to a video pipeline.
Can I clone a voice and use it through the API?
Yes. A cloned voice is registered to your account and can then be referenced by later speech requests, so the same voice is available in the studio and through the API. Voice cloning is subject to the plan's clone slot limit and to the consent rules in the voice consent policy.
Is there a rate limit?
Each API key is limited to 60 requests per minute. Concurrency beyond that depends on the plan: the Pro plan reserves 5 concurrent API requests and Business reserves 10, while plans without API access are not issued keys at all.