Speech
Voices
List the voices you can speak with, clone one from a recording, design one from a description, and edit or delete your own.
A voice is what voice_id names on text to speech, stored audio and an agent. You can speak with three kinds:
kind |
What it is | Who can change it |
|---|---|---|
builtin |
default, a female English voice. Always available, even when nothing else is. |
nobody |
platform |
Voices the platform provides to every organisation. | nobody, through the API |
org |
Your organisation’s own: cloned from a recording, or designed from a description. Only your organisation sees them. | you, with voices:write |
Reading needs tts; changing needs voices:write. A key that may speak cannot delete the voices your organisation made. See Authentication.
List voices
Section titled “List voices”curl https://api.lumavox.ai/v1/voices \ -H "Authorization: Bearer $API_KEY"{ "data": [ { "id": "default", "name": "Default", "description": "Female English voice (ElevenLabs' Sarah). Built into the platform; always available.", "kind": "builtin", "status": "ready", "duration_seconds": null, "provider": "elevenlabs", "models": ["eleven_flash_v2_5", "eleven_multilingual_v2", "eleven_v3"], "samples": [], "created_at": null }, { "id": "voi_q1W2e3R4t5Y6u7I8", "name": "Narrator", "description": "Warm, measured, British.", "kind": "org", "status": "ready", "duration_seconds": 42.7, "provider": "elevenlabs", "models": ["eleven_flash_v2_5", "eleven_multilingual_v2", "eleven_v3"], "samples": [ {"model": "eleven_flash_v2_5", "ready": true, "error": null, "url": "https://…"}, {"model": "eleven_multilingual_v2", "ready": true, "error": null, "url": "https://…"}, {"model": "eleven_v3", "ready": false, "error": null, "url": null} ], "created_at": "2026-10-20T14:02:11.000Z" } ], "next_cursor": null}- Every voice is in one page:
next_cursoris alwaysnull(Conventions). The built-in voice is always first. idis what you send asvoice_id.nameis a label and is not unique.statusisreadyfor every voice that can speak; only a voice your organisation is adding can bependingorfailed.modelsis what the voice can be spoken with — send one of them asmodel.samplesholds one spoken sample per model, generated or not yet. A sample’surlis temporary: read it from a fresh response rather than storing it.duration_secondsis the length of the recording a voice was cloned from, andnullfor one that was not.
Read one of your voices
Section titled “Read one of your voices”GET /v1/voices/{voice_id} returns one of your organisation’s voices in full. A platform voice or the built-in voice is a 404 here; they are in the list.
curl https://api.lumavox.ai/v1/voices/voi_a1B2c3D4e5F6g7H8 \ -H "Authorization: Bearer $API_KEY"status |
Meaning |
|---|---|
pending |
Being cloned. It cannot speak yet. |
ready |
Usable. |
failed |
The clone failed. error says why. Retry it, or delete it. |
{ "id": "voi_a1B2c3D4e5F6g7H8", "name": "Narrator", "description": "Warm, measured, British.", "kind": "org", "status": "ready", "error": null, "source": "upload", "design_prompt": null, "duration_seconds": 42.7, "samples": [ {"model": "eleven_flash_v2_5", "ready": true, "error": null, "url": "https://…"}, {"model": "eleven_multilingual_v2", "ready": true, "error": null, "url": "https://…"}, {"model": "eleven_v3", "ready": true, "error": null, "url": "https://…"} ], "provider": "elevenlabs", "external_voice_id": "pNInz6obpgDQGcFmaJgB", "models": ["eleven_flash_v2_5", "eleven_multilingual_v2", "eleven_v3"], "provider_defaults": { "stability": 0.6, "similarity_boost": null, "style": null, "use_speaker_boost": null, "speed": null }, "created_at": "2026-10-20T14:02:11.000Z", "created_by_clerk_user_id": null, "created_by_api_key_id": "0193a8c2-51f0-7d2e-8b6a-4c1e9f3d2a70"}Beyond the list’s fields, the detail has error, source (upload or design), design_prompt (what a designed voice was described as), external_voice_id (the provider’s own id, null until it is cloned), provider_defaults (the settings it speaks with unless a request overrides them, each null where it keeps the provider’s) and who added it — created_by_clerk_user_id for a person in the console, created_by_api_key_id for a key, the other null.
Clone a voice from a recording
Section titled “Clone a voice from a recording”Cloning takes three calls: ask where to upload, upload the file, then create the voice. The recording goes straight to storage and never passes through the API.
1. Ask for an upload URL, naming the recording’s type:
curl https://api.lumavox.ai/v1/voices/upload-url \ -H "Authorization: Bearer $API_KEY" \ -H "Content-Type: application/json" \ -d '{"content_type": "audio/mpeg"}'{ "upload_id": "voi_a1B2c3D4e5F6g7H8", "url": "https://…", "content_type": "audio/mpeg", "expires_at": "2026-10-24T09:45:00.000Z"}Accepted types: audio/wav, audio/x-wav, audio/wave, audio/vnd.wave, audio/mpeg, audio/mp3, audio/mp4, audio/x-m4a, audio/aac, audio/ogg, audio/opus, audio/webm, audio/flac and audio/x-flac. Anything else is a 422.
2. PUT the recording to url, with exactly the Content-Type you named and no Authorization header — the URL carries its own signature. It stops accepting the recording at expires_at, fifteen minutes after you asked. Its size is at most the platform’s limits.uploads.voice_bytes (Limits).
curl -X PUT "<url>" \ -H "Content-Type: audio/mpeg" \ --data-binary @narrator.mp33. Create the voice from the upload:
curl https://api.lumavox.ai/v1/voices \ -H "Authorization: Bearer $API_KEY" \ -H "Content-Type: application/json" \ -d '{ "upload_id": "voi_a1B2c3D4e5F6g7H8", "name": "Narrator", "description": "Warm, measured, British.", "consent": true }'consent: true is required. It confirms you have the right to clone this voice; without it the create is refused with a 422.
It answers 202 with the voice in status: pending. It cannot speak yet: poll GET /v1/voices/{voice_id} until it is ready, or failed with the reason in error. The clone happens after the create answers, so a recording the provider refuses shows up as failed, not as an error on this call.
A cloned voice can be spoken with every model: eleven_flash_v2_5, eleven_multilingual_v2 and eleven_v3.
Design a voice from a description
Section titled “Design a voice from a description”Describe a voice in words and listen to candidates before you keep one.
1. Design:
curl https://api.lumavox.ai/v1/voices/design \ -H "Authorization: Bearer $API_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "Ship AI", "prompt": "A calm, slightly synthetic female voice, mid-thirties, precise diction, like a starship computer." }'name is 1–120 characters and prompt 10–1,000.
{ "previews": [ { "id": "<a preview id>", "audio_base64": "SUQzBAAAAAAA…", "media_type": "audio/mpeg", "duration_seconds": 19.4, "long_enough": true } ], "description": "A calm, precise female voice in her thirties…", "script": "Systems nominal. Course plotted for the outer ring…", "improved": true}previewsare candidates, as base64 audio. How many come back can vary.long_enoughisfalsefor a preview under 18 seconds — too short to judge a voice by. It can still be kept.descriptionis the brief the previews were designed from. Your prompt may have been rewritten into a fuller one;improvedsays whether it was.scriptis what the previews say.
Nothing is saved by this call, and it is billed per design, whether or not you keep a candidate.
To listen to a preview:
curl … | jq -r '.previews[0].audio_base64' | base64 --decode > preview.mp32. Keep one:
curl https://api.lumavox.ai/v1/voices/design/save \ -H "Authorization: Bearer $API_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "Ship AI", "preview_id": "<a preview id>", "prompt": "A calm, slightly synthetic female voice, mid-thirties, precise diction, like a starship computer." }'It answers 202 with the voice already ready — you can speak with it at once. Its spoken samples follow. Keeping is not billed; the design was. An optional description (up to 500 characters) is stored with it.
Edit a voice
Section titled “Edit a voice”PATCH /v1/voices/{voice_id} changes only the fields you send:
| Field | Effect |
|---|---|
name |
Rename it. 1–120 characters; cannot be null. |
description |
Up to 500 characters. null clears it; it reads back as "". |
models |
Which models it may be spoken with. Each must be one the provider offers, or it is a 422 at models. |
provider_defaults |
The settings it speaks with by default: stability, similarity_boost, style, use_speaker_boost, speed — the same fields as provider_options. |
curl -X PATCH https://api.lumavox.ai/v1/voices/voi_a1B2c3D4e5F6g7H8 \ -H "Authorization: Bearer $API_KEY" \ -H "Content-Type: application/json" \ -d '{"name": "Narrator (warm)", "provider_defaults": {"stability": 0.6}}'There is no way to replace the recording. Clone a new voice and delete the old one.
Retry a voice, or regenerate its samples
Section titled “Retry a voice, or regenerate its samples”POST /v1/voices/{voice_id}/sample:
- on a
failedvoice, runs the clone again — the voice ispendinguntil it finishes; - on a
readyvoice, regenerates its spoken samples; - on a
pendingvoice, answers 409: it is already being processed.
Delete a voice
Section titled “Delete a voice”curl -X DELETE https://api.lumavox.ai/v1/voices/voi_a1B2c3D4e5F6g7H8 \ -H "Authorization: Bearer $API_KEY"It answers 204, with no body. The voice, its samples and the voice made for it at the provider are removed. A speech request naming it afterwards is a 404.
Limits
Section titled “Limits”- Each organisation may keep a number of voices set by its plan. Over it, uploading, creating and keeping a design answer 409. Delete a voice, or ask for a higher limit. Your plan is at
GET /v1/plan— see Credits and usage. - The platform’s own capacity for custom voices can fill up. Then new voices are refused with a 409 that says so, whatever your plan allows.
- Uploading, creating, designing, keeping and retrying count against your rate limit, like a generation. Reading, editing and deleting do not.
Errors
Section titled “Errors”The common envelope is described in Errors and limits. The ones specific to voices:
| Status | When |
|---|---|
| 400 | The body is not valid JSON. |
| 402 | The organisation is out of credits (on the calls that spend: uploading, creating, designing, keeping, retrying). |
| 404 | The voice is unknown, not your organisation’s, or a platform or built-in voice (for read, edit, delete and retry). |
| 409 | The plan’s voice limit is reached; the platform’s voice capacity is full; the upload never arrived, or was already used; or a retry of a voice that is still pending. |
| 422 | A content type that is not accepted; consent not true; a stored file that is empty, over the platform’s size for a recording, or not audio; a missing name; a models entry the provider does not offer; an unknown field. issues names the field. |
| 429 | Over your organisation’s rate limit. |
| 502 | The designer failed, or a preview could not be kept. The message says why. |
| 503 | Voice storage, the designer or the jobs that clone voices are not available on this deployment; or, on the list, your voices could not be looked up — the list never answers the built-in voice alone. Retry shortly. |
Related
Section titled “Related”- Text to speech — speaking with a voice.
- Agents — giving an agent a voice.
- Reference: voices