# ElevenLabs v4 (audio) > Text-to-speech on ElevenLabs Eleven v4, with 21 preset voices and 415 ElevenLabs Voice Library voices. It is best at clean, expressive voice-over for ad scripts. The model id stays `elevenlabs-v3`. Status: roasOS API v1.1. Catalog `model-catalog@2026-10-06.v5`, pricing `customer-pricing@2026-11-05.v15`. The endpoint `POST /v1/audio/elevenlabs-v3` is live. `POST /v1/generations` stays for one minor version as a deprecated alias (see "Today"). ## Endpoint POST https://api.roasos.com/v1/audio/elevenlabs-v3 Auth: Authorization: Bearer roasos_sk_… (scope api:write). Idempotency-Key required. quote_only / quote_id / webhook_url as in https://docs.roasos.com/llms.txt. ## Good at Voice-over for a UGC script, a product explainer, or a hook line. The 21 presets cover calm, warm, deep, British, Scottish, narrator, and documentary reads. `voice` takes a preset name, such as `Rachel`, or a voice id from the roasOS snapshot of the ElevenLabs Voice Library (415 voices, taken on 2026-10-04). Another id answers `400`. Set `language_code` to force a language when the text is not English. `similarity_boost` sets how closely the take follows the voice. `timestamps: true` answers `400`: the result does not store word timing yet. It does not clone a voice, and `voice_id` is not a field: send a library id in `voice`. It does not accept media of any kind. ## Pricing Unit: characters. Pricing key: `elevenlabs-v3`. | request | credits | |---|---| | `1000_characters` | 1 | | `2000_characters` | 2 | | `5000_characters` | 5 | Credits come from the roasOS pricing table (`MODEL_COSTS`) through the catalog. No other field changes the price. ## Modes - `text-to-speech` Provider endpoints: `fal-ai/elevenlabs/tts/eleven-v4`. ## Request fields | field | type | required | default | rule | |---|---|---|---|---| | `apply_text_normalization` | enum | no | `auto` | `auto`, `on`, `off` | | `language_code` | string | no | — | matches `^[a-z]{2}$` | | `quote_id` | string | no | — | UUID | | `quote_only` | boolean | no | `false` | — | | `similarity_boost` | number | no | `0.75` | 0–1 | | `stability` | number | no | `0.5` | 0–1 | | `text` | string | yes | — | ≥ 1 character; ≤ 5,000 characters | | `timestamps` | boolean | no | `false` | — | | `voice` | string | no | `Rachel` | — | | `wait_timeout_seconds` | integer | no | `0` | 0–60 | | `webhook_url` | string | no | — | https URL; ≤ 4,096 characters | The schema is strict: a field that is not in this table returns `400 unsupported_option`. Field names are the roasOS role names, one name per role across every family. ## Media The endpoint accepts no media. Every media role below is refused. - Refused: `avatar_id`, `elements`, `product_id`, `product_images`, `references`, `reference_images`, `image_url`, `end_image_url`, `scene_id`, `scene_image`, `video_urls`, `video_url`, `audio_urls`, `audio_url`, `voice_id`. A refused role returns `400 unsupported_option`. - Every URL must be an immutable object on `https://cdn.roasos.com/…` that your workspace owns; any other URL is `400 reference_media_not_workspace_owned`. Upload with `POST /v1/uploads` (direct POST of the bytes to `put_url`, or a `source_url` import), then use the returned CDN URL. ## Prompt `text` is the script. Limit 5,000 characters. roasOS adds no wrapper. - Write the words as they must be spoken. Spell out abbreviations that the voice must read as words. - Use punctuation for pacing. A comma is a short beat; a full stop is a longer beat; an ellipsis is a pause. - Keep one sentence per idea. Long compound sentences make the read flat. - Lower `stability` (0.3) for a more expressive read; raise it (0.7) for a steady announcer read. - Keep `similarity_boost` at its default (0.75). Raise it to stay closer to the voice; a high value can sound less natural. - Set `apply_text_normalization: "on"` when the text has prices, dates, or phone numbers. - Set `language_code` when the text is not English, so the model does not guess. ## Not exposed - `speed`: not accepted by this public endpoint. - `style`: not accepted by this public endpoint. - `pitch`: not accepted by this public endpoint. - `output_format`: pinned to `mp3_44100_128`. - `seed`: not accepted by this public endpoint. ## Result Result kind `audio`. Always present: `url`. Present when the run produces it: `timestamps`. ```json { "data": { "id": "gen_…", "kind": "audio", "model": "elevenlabs-v3", "status": "completed", "result": {"timestamps":[{}],"url":"https://cdn.roasos.com/workspaces/ws_01/result"} } } ``` Files live on `https://cdn.roasos.com` and are immutable; a result URL can be a media input to the next call. Poll `GET /v1/jobs/{id}/status` → `{ id, status, updated_at }`, then `GET /v1/jobs/{id}/result` (`409 run_not_completed` until the job is `completed`, `failed` or `canceled`). Statuses: `queued → processing → completed | failed | canceled`. ## Example ```bash # 1. quote — nothing is spent curl -X POST https://api.roasos.com/v1/audio/elevenlabs-v3 \ -H "Authorization: Bearer roasos_sk_live_…" \ -H "Idempotency-Key: 0f1c9e2a-elevenlabs-v3-0001" \ -H "Content-Type: application/json" \ -d '{"quote_only":true,"text":"Two drops, morning and night. That is the whole routine."}' # → 200 { "data": { "kind": "quote", "quote_id": "q_7Hk…", "credits": 1, "expires_at": "…", "confirmation": { "model": "elevenlabs-v3", "example": "1000_characters" } } } # 2. run — the same body and the same Idempotency-Key, quote_id instead of quote_only curl -X POST https://api.roasos.com/v1/audio/elevenlabs-v3 \ -H "Authorization: Bearer roasos_sk_live_…" \ -H "Idempotency-Key: 0f1c9e2a-elevenlabs-v3-0001" \ -H "Content-Type: application/json" \ -d '{"quote_id":"q_7Hk…","text":"Two drops, morning and night. That is the whole routine."}' # → 201 { "data": { "id": "gen_…", "kind": "audio", "model": "elevenlabs-v3", "status": "queued", "credits_reserved": 1, "links": { "status": "/v1/jobs/gen_…/status", "result": "/v1/jobs/gen_…/result" } } } # 3. poll curl https://api.roasos.com/v1/jobs/gen_…/status -H "Authorization: Bearer roasos_sk_live_…" curl https://api.roasos.com/v1/jobs/gen_…/result -H "Authorization: Bearer roasos_sk_live_…" ``` ## Today `POST /v1/generations` with `{ "type": "audio", "model": "elevenlabs-v3", "prompt": "", "options": { "voice": "Charlotte", "stability": 0.4, "language": "en" } }`. Today the script goes in `prompt`, not `text`. `POST /v1/audio/elevenlabs-v3` takes `similarity_boost` (0 to 1) and `apply_text_normalization` (`auto`, `on`, `off`). `options.speed` must be 1 and `options.pitch` must be 0. `timestamps` is not returned yet. ## See also https://docs.roasos.com/models/audio/elevenlabs-v3 · https://api.roasos.com/v1/catalog/audio/elevenlabs-v3 · fal-ai/elevenlabs/tts/eleven-v4