List Voices
List TTS voices available to the current workspace.
Every filter accepts repeat-key OR semantics:
?gender=female&gender=neutral&category=narration&source=platform&source=workspace.
Filters combine across fields with AND; within a field, values OR.
Hybrid search: when search is a non-empty string, semantic search is enabled
for the deployment (VOICE_SEMANTIC_SEARCH_ENABLED), and the text embedder is
available, search runs a hybrid of SEMANTIC relevance — meaning, not keywords, so
“cheerful” also surfaces “bright/upbeat” voices, over the platform voices that carry a
profile embedding — AND a keyword arm that matches the voice NAME (plus descriptor/tags),
which also surfaces voices with no embedding and workspace-owned voices in scope, so a
voice literally named by the query is found. Both arms honor the same filters and are
fused into one ranking. In that mode sort/order are IGNORED (relevance order wins).
If semantic search is disabled, the embedder is
unavailable, or the embed call fails, search transparently falls back to the
lexical name/tag/descriptor match described below — the response shape
(ApiCountedListResponse[VoiceOut]) is identical either way.
language matches a voice when any of its declared locales matches any
requested value. A voice with no declared locales matches NO language
filter — it must positively declare a locale to surface under it. This holds
for platform and user-uploaded voices alike: an unclassified platform voice
(catalog gap) is not treated as general-use, and a user-uploaded/cloned voice
with no locale stays “language unknown” pending clone-flow detection.
Passing language also fills language_sample_url on every row that has a clip
in it — the same audio GET /voices/{voice_id}/preview?language= serves, so a
caller auditioning a shortlist can play the locale-correct take straight from the
list instead of a request per voice. language_sample_locale reports the region
actually served. Both are null without the filter; sample_url is unaffected and
still does not follow it.
Platform voices are restricted to the officially supported locales: a platform
voice that declares no official locale is not returned, and the locale arrays on
the voices that are returned (supported_languages,
model_capabilities[].supported_languages, preview_locales) list only official
locales. A bare family code counts as official when the family is supported
(ko qualifies because ko-kr is), matching the language filter above. Voices
your workspace owns — imported, recorded, or uploaded — are exempt from both the
exclusion and the narrowing: they routinely carry no declared locale at all, and
hiding them would remove a customer’s own voices from their own list.
Multi-sort: sort and order are parallel lists. ?sort=uses_count&sort=name&order=desc&order=asc
orders primarily by uses_count DESC, secondarily by name ASC. When order
is shorter than sort, missing entries default per-field:
name=asc, created_at=desc, uses_count=desc. When sort is omitted, list
defaults to newest-first (or most-recently-favorited-first if
favorites_only=true). Every sort path appends Voice.id ASC as a
deterministic tiebreaker for pagination stability.
Authentication
Onepin live API key (op_live_...). Test and public keys are reserved in Phase 1.
Headers
Query parameters
Maximum number of results to return (1–100).
Repeat for OR across scopes: platform for system-provided voices, workspace for workspace-owned voices.
Searches name, tags, and the voice's summary-derived descriptor text (closely tracks the served description; summary beyond 200 chars is not searched).
Repeat for multi-sort. Pairs with order index-wise.
Parallel to sort[]; shorter is padded with per-field defaults.
Repeat for OR, e.g. ?provider=elevenlabs&provider=rime
Repeat for OR. Filters platform voices by TTS model, e.g. ?model=arcana&model=sonic-2
Repeat for OR, e.g. ?language=en-us&language=ko-kr

