Single TTS
Convert one text input into one audio file through `CreateBy`, then poll `Status` or use `CallbackUrl`.
🔒 Free tier data may be used to improve AI models. Upgrade Pro for 100% Privacy
REST API • Single TTS • Multi Voice • SRT to Speech
Explore the TTS For Free API — test the live demo or view ready-to-use code samples in multiple languages.
TTSForFree exposes an asynchronous TTS pipeline. Create jobs by REST, then get the final audio by polling or callback depending on the flow.
This page covers the public user-facing TTS APIs currently available in the backend.
Convert one text input into one audio file through `CreateBy`, then poll `Status` or use `CallbackUrl`.
Generate podcast or multi-speaker audio through `CreateMulti` with one `ConnectionId` and many blocks.
Generate dubbed audio from subtitle-style blocks with `StartMs` and `EndMs` through `CreateSrt`.
Some async flows return progress and final results over background processing, while the public docs below focus on the request and response contracts.
Fetch single-job history, voice history, or merged-job history for the authenticated user account.
See the latest public schemas in Swagger.
Send `X-API-Key` in every public request header.
To get your API key, open `/`. In the voice area there is a copy button you can use to copy the exact `Voice` value before calling the API. For history endpoints, also send `Authorization: Bearer YOUR_JWT` because those endpoints return the current user's own jobs.
X-API-Key: YOUR_API_KEYUse these endpoints before generation so the frontend can show the current language, voice, and max-length limits.
`Pitch` is provider-dependent. Do not assume every voice supports it.
curl -X GET "https://api.ttsforfree.com/api/Common/GetListLanguage" \
-H "X-API-Key: YOUR_API_KEY"curl -X GET "https://api.ttsforfree.com/api/Common/GetListVoice?lang=en&type=singlevoice" \
-H "X-API-Key: YOUR_API_KEY"curl -X GET "https://api.ttsforfree.com/api/Common/GetConfigMaxLength" \
-H "X-API-Key: YOUR_API_KEY"Use `CreateBy` for one text input and one voice. `Pitch` is optional. `CallbackUrl` is optional.
`CreateBy` public DTO does not require `ConnectionId`.
curl --location "https://api.ttsforfree.com/api/TTS/CreateBy" \
--header "X-API-Key: YOUR_API_KEY" \
--header "Content-Type: application/json" \
--data '{
"Texts": "Hello everybody",
"Voice": "v1:TldK3n9ei9wctuSlNYhG_cJ4UULVT8ZGjhxcuoaFow2hDTDsuTCuvaOYrVY",
"Pitch": 0,
"CallbackUrl": "https://your-app.com/api/tts/callback"
}'{
"Texts": "Hello everybody",
"Voice": "v1:TldK3n9ei9wctuSlNYhG_cJ4UULVT8ZGjhxcuoaFow2hDTDsuTCuvaOYrVY",
"Pitch": 0,
"CallbackUrl": "https://your-app.com/api/tts/callback"
}{
"Id": 12345,
"Message": "Proccessing",
"Status": "PENDING",
"Data": "",
"ExpectUrl": "https://cdn.ttsforfree.com/20250606/abc.mp3",
"ShareKey": "sha256..."
}Use the returned `Id` as your single-job id. Poll this endpoint if you are not using `CallbackUrl`.
If the request was served from cache, `Data` may already contain the final URL. Otherwise wait until `Status` becomes `SUCCESS`.
curl -X GET "https://api.ttsforfree.com/api/TTS/Status/12345" \
-H "X-API-Key: YOUR_API_KEY"{
"Id": 12345,
"Status": "SUCCESS",
"Data": "https://cdn.ttsforfree.com/20250606/abc.mp3"
}Use `CreateMulti` for podcast-style or multi-speaker output. `ConnectionId` is required.
curl --location "https://api.ttsforfree.com/api/TTS/CreateMulti" \
--header "X-API-Key: YOUR_API_KEY" \
--header "Content-Type: application/json" \
--data '{
"ConnectionId": "signalr-connection-id",
"MinSpeechRate": 0.95,
"MaxSpeechRate": 1.50,
"Blocks": [
{
"Texts": "Welcome to the show",
"Voice": "v1:host_voice",
"Volume": 1,
"Speed": 1,
"Pitch": 0,
"PauseAfterMs": 300
},
{
"Texts": "Thanks for inviting me",
"Voice": "v1:guest_voice",
"Volume": 1,
"Speed": 1,
"Pitch": 0,
"PauseAfterMs": 500
}
]
}'{
"ConnectionId": "signalr-connection-id",
"MinSpeechRate": 0.95,
"MaxSpeechRate": 1.50,
"Blocks": [
{
"Texts": "Welcome to the show",
"Voice": "v1:host_voice",
"Volume": 1,
"Speed": 1,
"Pitch": 0,
"PauseAfterMs": 300
},
{
"Texts": "Thanks for inviting me",
"Voice": "v1:guest_voice",
"Volume": 1,
"Speed": 1,
"Pitch": 0,
"PauseAfterMs": 500
}
]
}{
"Id": 6789,
"Message": "Success",
"ExpectUrl": "https://cdn.ttsforfree.com/audio_merge/3f9b5a35-9ac4-4d51-a8fe-2e4d91523a88.mp3"
}Use `CreateSrt` when each block already has subtitle timing. `ConnectionId` is required.
Gemini voices are currently not supported in SRT mode.
curl --location "https://api.ttsforfree.com/api/TTS/CreateSrt" \
--header "X-API-Key: YOUR_API_KEY" \
--header "Content-Type: application/json" \
--data '{
"ConnectionId": "signalr-connection-id",
"MinSpeechRate": 0.95,
"MaxSpeechRate": 1.50,
"Blocks": [
{
"Texts": "Hello everyone",
"Voice": "v1:voice_1",
"Volume": 1,
"Speed": 0.9,
"Pitch": 0,
"StartMs": 0,
"EndMs": 1800
},
{
"Texts": "Welcome back",
"Voice": "v1:voice_1",
"Volume": 1,
"Speed": 0.9,
"Pitch": 0,
"StartMs": 2200,
"EndMs": 4200
}
]
}'{
"ConnectionId": "signalr-connection-id",
"MinSpeechRate": 0.95,
"MaxSpeechRate": 1.50,
"Blocks": [
{
"Texts": "Hello everyone",
"Voice": "v1:voice_1",
"Volume": 1,
"Speed": 0.9,
"Pitch": 0,
"StartMs": 0,
"EndMs": 1800
},
{
"Texts": "Welcome back",
"Voice": "v1:voice_1",
"Volume": 1,
"Speed": 0.9,
"Pitch": 0,
"StartMs": 2200,
"EndMs": 4200
}
]
}{
"Id": 6790,
"Message": "Success",
"ExpectUrl": "https://cdn.ttsforfree.com/audio_merge/f0d4cb65-7d10-4f53-b930-1b231d2414d9.mp3"
}Use the returned merged job `Id` from `CreateMulti` or `CreateSrt`.
curl -X GET "https://api.ttsforfree.com/api/TTS/Multi/Status/6789" \
-H "X-API-Key: YOUR_API_KEY"{
"Id": 6789,
"Status": "SUCCESS",
"Data": "https://cdn.ttsforfree.com/audio_merge/3f9b5a35-9ac4-4d51-a8fe-2e4d91523a88.mp3"
}For multi voice and SRT jobs, this endpoint returns the merged job and every child block audio record.
Use `FinalAudioUrl` for the merged file and `Blocks[].FilePath` for each block file.
curl -X GET "https://api.ttsforfree.com/api/TTS/GetJobTTSDetail?jobId=6789" \
-H "X-API-Key: YOUR_API_KEY" \
-H "Authorization: Bearer YOUR_JWT"{
"Id": 1,
"Message": "Success",
"Data": {
"Id": 6789,
"TotalBlocks": 2,
"StatusId": 200,
"StatusName": "SUCCESS",
"FinalAudioUrl": "https://cdn.ttsforfree.com/audio_merge/3f9b5a35-9ac4-4d51-a8fe-2e4d91523a88.mp3",
"Blocks": [
{
"Id": 12345,
"Text": "Welcome to the show",
"Voice": "v1:host_voice",
"FilePath": "https://cdn.ttsforfree.com/20250606/block1.mp3",
"StatusId": 200
}
]
}
}History APIs are account-based. They return the authenticated user's own jobs, so include `Authorization: Bearer YOUR_JWT`.
Use `GetHistory` for single TTS jobs, `GetHistoryVoice` for a compact voice-focused history, and `GetHistoryMulti` for merged jobs. For SRT merged jobs, call `GetHistoryMulti` with `jobType=Srt`.
curl -X GET "https://api.ttsforfree.com/api/TTS/GetHistory?page=1&pageSize=10" \
-H "X-API-Key: YOUR_API_KEY" \
-H "Authorization: Bearer YOUR_JWT"curl -X GET "https://api.ttsforfree.com/api/TTS/GetHistoryVoice?page=1&pageSize=10" \
-H "X-API-Key: YOUR_API_KEY" \
-H "Authorization: Bearer YOUR_JWT"curl -X GET "https://api.ttsforfree.com/api/TTS/GetHistoryMulti?page=1&pageSize=10&jobType=Tts" \
-H "X-API-Key: YOUR_API_KEY" \
-H "Authorization: Bearer YOUR_JWT"curl -X GET "https://api.ttsforfree.com/api/TTS/GetHistoryMulti?page=1&pageSize=10&jobType=Srt" \
-H "X-API-Key: YOUR_API_KEY" \
-H "Authorization: Bearer YOUR_JWT"{
"Id": 1,
"Message": "Success",
"TotalRows": 1,
"Data": [
{
"Id": 6789,
"TotalBlocks": 2,
"StatusId": 150,
"StatusName": "MERGE_REQUESTED",
"FinalAudioUrl": "",
"Blocks": [
{
"Id": 12345,
"Text": "Welcome to the show",
"Voice": "v1:host_voice",
"FilePath": "https://cdn.ttsforfree.com/20250606/block1.mp3",
"StatusId": 200
}
]
}
]
}If you pass `CallbackUrl` in `CreateBy`, the server POSTs a completion payload to your URL when the single TTS job finishes.
Current public callback behavior is for `CreateBy`. For multi voice and SRT, rely on the create and status endpoints documented above.
POST https://your-app.com/api/tts/callback
Content-Type: application/json
{
"Id": 12345,
"Status": "SUCCESS",
"Action": "ResponseTTSNotification",
"FilePath": "https://cdn.ttsforfree.com/20250606/abc.mp3",
"Data": "https://cdn.ttsforfree.com/20250606/abc.mp3",
"Hash": "sha256...",
"CompletedAt": "2026-06-06T10:10:10Z"
}400 Bad Request // missing text, invalid block data, or invalid timeline
401 Unauthorized // missing or invalid API key or user token
403 Forbidden // quota exceeded or voice access not allowed
404 Not Found // job id not found
429 Too Many // rate limited
500 Server Error // transient issue, retry with backoffThese numeric values are the most important ones to explain in frontend docs when reading merged history or merged job detail data.
Job has been accepted and is still waiting or pending in the processing pipeline.
Blocks are already being prepared and the merged audio file is being requested or assembled.
The final audio is ready. At this point you can safely use `Data`, `ExpectUrl`, or `FinalAudioUrl`.
The job failed. Do not fetch the final audio URL until a new successful run is created.
A: For the public docs, prioritize polling. Use `Status` for single TTS and `Multi/Status` for multi voice or SRT jobs. A simple interval such as every 5 seconds is usually enough for most frontend integrations.
A: As a practical expectation, multi voice and SRT jobs for a long 2 to 3 hour video can often finish in around 5 minutes per job. Exact time still depends on block count, voice mix, and queue load.
A: If you are building longer workflows, start with `multi voice` and `srt` because they are the most flexible for long-form content. Split content into clean blocks, keep timing clear, and poll the job status instead of fetching output too early.
A: Free plans have lower limits per minute and per day. Paid plans have higher limits. The current limit policy can change by package, so handle 429 responses safely and contact the team if you need larger throughput.
A: Open the home page `/`. In the voice area there is a copy button for the voice key. You can test voices there first, then copy the exact `Voice` value into your API request.
Free usage is suitable for testing and prototyping. For commercial usage, redistribution, or larger quotas, contact [email protected].