Voices
Three catalogs with different schemas, different gender values, and different pagination bases. How to find a voice_id and what to do with it next.
Çeviri hazırlanıyor
Voices come from three independent sources and are not normalized to a common shape: different
item schemas, different gender values, different list wrappers, and different page numbering
bases. They share two things: the voices.read scope and the outcome — an ID that goes into a
template. These three catalogs are read-only: a LumVoice voice cannot be created with an API key.
Voice clones are created with a key in the reference, in the Cartesia and Fish Audio groups
(voices.write scope).
Three catalogs and when to use which
| Source | Operations |
|---|---|
| LumVoice — the platform's internal voices | GET /voices, /voices/library, /voices/public, /voices/tags, /voices/{voice} |
| ElevenLabs — the public Voice Library, provider objects as is | GET /voices/elevenlabs/library |
| HeyGen — the provider's catalog with its own filter vocabulary | GET /voices/heygen, /voices/heygen/filters |
Within LumVoice, the lists serve different purposes. GET /voices returns your voices in
any state, including those not fully cloned and those rejected by moderation: it is the worst
list for picking a voice for an order. GET /voices/library is what you can voice with right
now: your own ready voices plus those added from the catalog, with a nickname and an
available flag. GET /voices/public is the shared catalog, filtered so that any voice taken
from it is guaranteed to be usable.
Pagination: two incompatible bases
This is the most common cause of an “empty response” with a working key. The internal LumVoice
lists put the familiar items + current_page / last_page / per_page / total into
data and number pages from 1. The external catalogs return their own wrapper, voices +
total / page / page_size / has_more, and number pages from 0: page=1 there is the
second page. Full details are in the Pagination guide.
Tuzak
total means different things in the two external catalogs: in ElevenLabs it is the number
of voices on the current page (the spec explicitly warns: “rely on has_more, not on
total”), in HeyGen it is how many voices match the filters across all pages. You cannot build
a common loop exit condition on total — use has_more.
gender values differ across all three
| Catalog | Allowed values |
|---|---|
GET /voices/public (LumVoice) | male, female, neutral |
GET /voices/elevenlabs/library | male, female |
GET /voices/heygen | male, female, unknown |
Only HeyGen has unknown: the provider returns some voices without a gender. You cannot build a
common “gender” filter across the three catalogs. A related pitfall: in ElevenLabs, age is a
strict enum — young, middle_aged, old — with an underscore; middle-aged returns
422.
How to make sure a LumVoice voice is usable for an order
The check depends on where the voice came from; the status alone is not enough.
| Source | What to check |
|---|---|
GET /voices/public | Nothing: the catalog is filtered by voice_status and allow_usage_in_orders |
GET /voices/library | available; if false, the reason is in unavailable_reason |
GET /voices (your own) | languages[]: an order is possible in a language whose clone has completed |
voice_status: "ready" means the voice is fully usable. partially_ready means some languages
were cloned and some failed, while the working languages are available: what decides is not the
overall status but the language's state in languages[] (status; the failure reason is in
failure_reason).
Not
Sources disagree: llm.md describes partially_ready as a real state, but the enum of the
voice_status parameter of GET /voices has five values — pending_clone, cloning,
ready, clone_failed, archived. Read the value from responses, but do not filter by it.
publication_status and allow_usage_in_orders are about visibility in the catalog, not about
eligibility for orders; the second flag does not affect your own voices. For users who had
already added the voice to their library, the entry becomes available: false with an
unavailable_reason (author_unpublished, admin_force_removed, author_deleted,
owner_deleted).
Public Voices Catalog
HeyGen: the engine is a property of both the service and the voice
GET /templates/config-options?service=heygen lists the engines the service supports;
which ones a specific voice supports is in the catalog item's voice_engines field. You need a
value that is in both lists at once: of 2330 voices, 1947 support elevenLabs, and 383 support
none of the listed ones. A mismatched “voice + engine” pair is rejected with 422 — and on the
config.tts_settings.voice_id field, not on the engine field.
language, accent, and voice_engine values use the provider's spelling (English,
en-US); GET /voices/heygen/filters returns the list with counts — call it first.
What to do with the ID you found
It goes into a template for the same service, and only there: there is no orders.voice_id
field.
{
"service_key": "elevenlabs",
"name": "Narrator EN",
"config": { "tts_settings": { "model_id": "eleven_multilingual_v2", "voice_id": "<VOICE_ID>" } }
}For ElevenLabs and HeyGen, the value is in the item's voice_id, and the template's
service_key is elevenlabs or heygen; for LumVoice, it is in the item's id. To swap the
voice once without a new template, use the order's config_override; for building the config,
see the Templates guide.
Tuzak
Three OpenAPI field descriptions give the path as config.voice_id — this short form is wrong.
The working path is config.tts_settings.voice_id: that is how it appears in the description
of the GET /voices operation itself, in the minimal valid config, and in all working examples.
Small things that trip you up silently
preview_urlslive for about a minute. It is a “language code → signed URL ornull” map, and you must not cache it for long; the external catalogs' equivalent ispreview_url.- Tag names are localized. Filter by
tag_ids[]and compare bycode:namecomes in the key's language. - A LumVoice ID is an opaque string. The schema calls it a UUID, but in examples it is a
short key like
k3nH9vRt2Lw7ZpXb: do not validate it as a UUID on the client. - ElevenLabs depends on an external API — it is the only catalog that returns
503. - Someone else's non-public voice returns
403; a nonexistent one returns404.
ElevenLabs Voice Library
Bu sayfayı yapay zekâya verin
Güncellendi: 04.09.2026 · spesifikasyon 0.0.1