Audio / Speech API
There are two ways to do text-to-speech: the synchronous, OpenAI-compatible POST /v1/audio/speech (Turkish ema/ema-lightning, free beta; below) and asynchronous generation with ElevenLabs TTS models (POST /v1/audio/generate; 29 languages including Turkish). For speech-to-text: use the POST /v1/audio/transcriptions endpoint with a :tr speech recognition model (multipart form), or send openai/gpt-audio or google/gemini-2.5-flash to /v1/chat/completions with input_audio. Audio output (synchronous): on the chat endpoint send modalities: ["text","audio"] + audio: {"voice":"alloy","format":"pcm16"} with stream: true; supported by openai/gpt-audio and openai/gpt-audio-mini. Audio arrives base64-encoded in the SSE stream under delta.audio.data. Note: in this mode format must be pcm16 and stream: true is required.
Synchronous Text-to-Speech: POST /v1/audio/speech (Free Beta)
/v1/audio/speech
OpenAI-compatible text-to-speech endpoint. The response is the audio file itself: a binary body with the correct Content-Type and Content-Length headers; no task id or status polling is needed. The OpenAI SDK's audio.speech.create call works by changing only the base_url.
EMA Lightning: Turkish text-to-speech, free beta
ema/ema-lightning is an 8.6M-parameter Turkish text-to-speech model developed by Canberk Aslan and released under the Apache-2.0 license (single voice, 48 kHz). It runs on servers operated by Onysoft; your text is not sent to any external AI API. It is free during the beta, with daily request, character and audio duration quotas. On user keys, the beta is open to accounts with a verified email address (signed in with Google or GitHub) or at least one paid balance top-up; other accounts receive 403 tts_beta_not_eligible. Once pricing starts it will be published on this page and in the model catalog.
Parameters
| Parameter | Required | Description |
|---|---|---|
model | Yes | Model id: ema/ema-lightning. |
input | Yes | The text to synthesize, at most 4096 characters. Numbers, dates, amounts of money, abbreviations and symbols are spelled out and read in Turkish, so a text full of numbers or symbols can become much longer when read aloud. A single request produces at most 20 minutes of audio (longer requests get <code>400 input_too_long</code>). |
voice | No | Accepted but ignored, because the model has a single voice (e.g. "ema"). You can send it for compatibility with OpenAI clients. |
response_format | No | Output format, default mp3. See the table below. |
speed | No | Speaking speed between 0.25 and 4.0; default 1.0. |
instructions | No | Accepted, ignored by this model. |
Output Formats
response_format | Content-Type | Description |
|---|---|---|
mp3 | audio/mpeg | MP3 (default) |
opus | audio/ogg; codecs=opus | Opus in an Ogg container; low bandwidth |
aac | audio/aac | AAC (ADTS) |
flac | audio/flac | Lossless FLAC |
wav | audio/wav | Uncompressed WAV |
pcm | audio/pcm | Headerless raw PCM: 24 kHz, 16-bit signed (little-endian), mono |
ulaw_8000 | audio/basic | G.711 μ-law, 8 kHz mono, headerless; for PBX and call-center use (extension, not in OpenAI) |
alaw_8000 | audio/x-alaw-basic | G.711 A-law, 8 kHz mono, headerless; for PBX and call-center use (extension, not in OpenAI) |
Examples
curl https://api.onysoft.com/v1/audio/speech \
-H "Authorization: Bearer sk-ony-YOUR-KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "ema/ema-lightning",
"input": "Merhaba, siparişiniz yola çıktı ve yarın teslim edilecek.",
"voice": "ema",
"response_format": "mp3"
}' \
--output konusma.mp3
from openai import OpenAI
client = OpenAI(base_url="https://api.onysoft.com/v1", api_key="sk-ony-YOUR-KEY")
with client.audio.speech.with_streaming_response.create(
model="ema/ema-lightning",
voice="ema",
input="Randevunuz 15 Ekim saat 14:30 için onaylandı.",
response_format="wav",
) as yanit:
yanit.stream_to_file("randevu.wav")
Quotas and Limits
- Free beta quota (default) per identity: 100 requests, 100,000 characters and 120 minutes of audio per day. Identity: the account for user keys (all keys of the account share it), the key itself for project and partner keys. All customer and project keys of one partner can produce at most 6 hours of audio per day in total. The free beta also has a limited server-wide daily capacity. Quotas reset at 00:00 Turkey time.
- Successful responses carry the remaining quota in headers:
X-Quota-Requests-Remaining,X-Quota-Characters-Remaining,X-Quota-Audio-Seconds-RemainingandX-Quota-Reset(Unix time). These headers,Retry-AfterandX-Request-Idare also readable from browser JavaScript viaAccess-Control-Expose-Headers. - When a quota is used up you get
429 tts_daily_limitwith aRetry-Afterheader holding the seconds until midnight andX-Should-Retry: false(SDKs do not retry immediately). Counted against the quota: successful requests, and requests that timed out (504 tts_timeout) or failed (500 tts_generation_failed) after synthesis started. Validation errors,429 rate_limitedresponses and503responses while the service is down are not counted. - At most 2 requests per identity (the account for user keys, the key for project and partner keys) are processed at the same time; extra requests get
429 rate_limited. Contact support for a higher quota or concurrency. - Read-aloud limit: the text is measured with numbers and symbols spelled out. A request whose estimated audio exceeds 20 minutes gets
400 input_too_longwithout waiting in the queue; thespoken_characters,estimated_audio_secondsandmax_audio_secondsfields show how much to split it. Such requests do not count against the quota. limit_typevalues:tts_daily_requests,tts_daily_characters,tts_daily_audio_seconds,tts_partner_daily_audio_seconds,tts_global_daily_audio_seconds(429tts_daily_limit);tts_concurrency,tts_busy(429rate_limited).
Error Codes
| Code | code | Description |
|---|---|---|
| 400 | invalid_request | Invalid parameter (the param field names it) or text longer than 4096 characters. |
| 400 | input_too_long | Read aloud, the text alone exceeds the audio a single request may produce (20 minutes) or your daily character / audio quota; split the text or increase the speed. Not counted against the quota. |
| 400 | unsupported_model | The model does not exist or is not available on this endpoint. |
| 400 | wrong_endpoint | The model belongs to another endpoint, e.g. POST /v1/audio/generate for asynchronous audio models. |
| 402 | insufficient_balance | Insufficient balance (only once pricing has started). |
| 403 | model_not_allowed | Your API key's model restriction does not allow this model. |
| 403 | tts_not_allowed | No text-to-speech quota is assigned to this key (daily limit 0); contact support. |
| 413 | payload_too_large | The request body exceeds 256 KB. |
| 429 | tts_daily_limit | A daily request, character or audio duration quota, the partner's total audio quota or the free beta's total daily capacity is used up; the limit_type field tells which. |
| 429 | rate_limited | The per-identity concurrency limit is reached or the speech service is busy (limit_type: tts_concurrency or tts_busy); wait for Retry-After seconds and retry. |
| 500 | tts_generation_failed | Synthesis started but no audio could be produced. Resending the same text will most likely fail again (X-Should-Retry: false); counted against the quota. |
| 503 | service_unavailable | The speech service is temporarily not responding; retry shortly. |
| 504 | tts_timeout | Speech generation exceeded the time limit. Split the text or increase the speed instead of retrying the same request (X-Should-Retry: false); counted against the quota. |
Privacy: the request text is not stored in usage logs; only its character count and a keyed (HMAC) fingerprint that cannot be turned back into the text are kept.
Model: EMA Lightning, © Canberk Aslan, Apache License 2.0 (model card). Onysoft runs the model unmodified.
ElevenLabs voice models are not served on this endpoint; use the asynchronous Audio Generation flow below.
This page is the audio part of the Content Generation API.
All generation endpoints (video, image, audio, voice, music) use the same backend. /v1/audio/generate and /v1/voice/generate are semantic aliases for audio models — for the full voice list, parameters and details, see video-api → Audio Models.
Audio Generation (TTS)
/v1/voice/generate
Generates speech from text (asynchronous). Equivalent: POST /v1/audio/generate or POST /v1/video/generate.
Quick Example (Turkish TTS, Rachel)
curl -X POST https://api.onysoft.com/v1/voice/generate \
-H "Authorization: Bearer sk-ony-YOUR-KEY" \
-d '{
"model": "elevenlabs/text-to-speech-multilingual-v2",
"prompt": "Merhaba, ben Rachel. Onysoft AI üzerinden konuşuyorum.",
"voice": "Rachel"
}'
Supported Voices (case-sensitive)
Female: Rachel (default), Alice, Aria, Charlotte, Jessica, Laura, Lily, Matilda, Sarah
Male: Brian, Bill, Callum, Charlie, Chris, Daniel, Eric, George, Liam, Roger, Will
The voice value is case-sensitive
If you send "rachel" or "RACHEL", the API returns a 500 "This voice is not within the range of allowed options" error. Capitalize the first letter. A name outside the list gives the same error.
Audio Models
| Model | Type | Price (USD) |
|---|---|---|
elevenlabs/text-to-speech-multilingual-v2 | Multilingual TTS | $0.090 |
elevenlabs/text-to-speech-turbo-2-5 | Low-latency TTS* | $0.045 |
* ElevenLabs models may have temporary errors on the generation service side; failed generations are not charged. For Turkish text-to-speech you can also use the synchronous POST /v1/audio/speech endpoint.
Status Lookup
curl https://api.onysoft.com/v1/audio/status/vtask_xyz789 \
-H "Authorization: Bearer sk-ony-YOUR-KEY"
For all parameters (stability, similarity_boost, style) and TTS documentation, see video-api → Audio Models.