Browse the voice library
Return one page of voices to choose from for the agent. Send the chosen voiceId as tts.voiceId when you create or update the agent.
GET
AuthBearer token (console user)Rate limitNot documentedProcessingSynchronous; each filter-and-page combination is cached for 24 hours
Voices come from the voice provider's shared library. ElevenLabs is the only provider today. The list is always limited to professional, conversational voices. Nothing is stored.
Auth: Bearer token of a signed-in user, checked with the identity service. Rate limit: not documented. Processing: synchronous. Each filter-and-page combination is cached for 24 hours.
Before you call it
- No identifiers are needed.
- To filter by language, call List voice languages first. Language values can be internal
languageIdvalues or ISO codes. - Several languages are ANDed, so each voice returned supports all of them.
- Unknown query parameters are rejected with 400.
Query parameters
Optionalcan be left out
| Parameter | Type | Required | Description |
|---|---|---|---|
provider | string | Optional | Voice catalog. Only 11labs is accepted. Default: 11labs. |
search | string | Optional | Free-text search. |
language | string or list | Optional | Comma-separated list or repeated parameter. Each value is a languageId or an ISO code. All languages must be supported (AND). |
gender | string | Optional | male or female. |
age | string | Optional | young, middle_aged or old. |
accent | string | Optional | Accent label, for example american. Not case-sensitive. |
sort | string | Optional | relevance, trending, newest or most_used. Default: most_used. |
page | integer | Optional | Zero-based page index. Minimum 0. Default: 0. |
pageSize | integer | Optional | 1 to 100. Default: 30. The console UI sends page=0 and pageSize=30. |
Sample request
curl -G "https://api.spyne.ai/conversation/tts/voices/library" \
-H "Authorization: Bearer YOUR_TOKEN" \
--data-urlencode "language=en" \
--data-urlencode "gender=female" \
--data-urlencode "page=0" \
--data-urlencode "pageSize=30"import requests
res = requests.get(
"https://api.spyne.ai/conversation/tts/voices/library",
headers={"Authorization": "Bearer YOUR_TOKEN"},
params={"language": "en", "gender": "female", "page": 0, "pageSize": 30},
)
print(res.status_code, res.json())const params = new URLSearchParams({ language: 'en', gender: 'female', page: '0', pageSize: '30' });
const res = await fetch(`https://api.spyne.ai/conversation/tts/voices/library?${params}`, {
headers: { Authorization: 'Bearer YOUR_TOKEN' },
});
console.log(res.status, await res.json());Sample response
{
"provider": "11labs",
"voices": [
{
"voiceId": "<voiceId>",
"name": "Example Voice",
"accent": "american",
"gender": "female",
"age": "middle_aged",
"language": "en",
"previewUrl": "https://example.com/preview.mp3",
"verifiedLanguages": [
{ "language": "en", "modelId": "<modelId>", "accent": "american", "previewUrl": "https://example.com/preview.mp3" }
]
}
],
"hasMore": true,
"total": 1200,
"nextCursor": null
}{
"statusCode": 400,
"message": ["gender must be one of the following values: male, female"],
"errorCode": "BAD_REQUEST",
"timestamp": "2026-10-12T10:00:00.000Z",
"requestId": "req_1760263200000_abc123xyz",
"context": {},
"path": "/conversation/tts/voices/library?gender=other",
"method": "GET"
}{
"statusCode": 401,
"message": "Authentication failed: Authorization header is required",
"errorCode": "AUTHENTICATION_ERROR",
"timestamp": "2026-10-12T10:00:00.000Z",
"requestId": "req_1760263200000_abc123xyz",
"context": { "reason": "Authorization header is required" },
"path": "/conversation/tts/voices/library",
"method": "GET"
}{
"statusCode": 500,
"message": "Internal server error",
"errorCode": "INTERNAL_SERVER_ERROR",
"timestamp": "2026-10-12T10:00:00.000Z",
"requestId": "req_1760263200000_abc123xyz",
"context": { "originalError": "Request failed with status code 503" },
"path": "/conversation/tts/voices/library",
"method": "GET"
}Response parameters (200)
| Parameter | Type | Description |
|---|---|---|
provider | string | 11labs. |
voices[] | array | Voices on this page. |
voices[].voiceId | string | Send this as tts.voiceId when you save the agent. |
voices[].name | string | Display name. |
voices[].accent, gender, age, descriptive, useCase, category, language, locale, description | string | Voice attributes, when the provider sends them. |
voices[].previewUrl | string | Sample audio clip. |
voices[].verifiedLanguages[] | array | Language and model variants: language, modelId, accent, locale, previewUrl. |
voices[].usageCharacterCount1y, usageCharacterCount7d, playApiUsageCharacterCount1y, clonedByCount | number | Popularity figures from the provider, when present. |
hasMore | boolean | More pages exist. |
total | number | Total matches, when the provider reports it. |
nextCursor | string or null | Provider sort cursor. The console UI pages with page instead. |
Errors
| Status | Reason | When it happens |
|---|---|---|
400 | Validation failed | A query value is out of range or not allowed, or an unknown query parameter was sent. message lists each rule that failed. |
401 | Authentication failed | No token, a token without the Bearer prefix, or a token the identity service rejects. |
500 | Internal server error | The voice provider call failed. |
If the provider API key is not configured on the server, the call returns 200 with an empty page instead of an error.
What happens next
Show the voices. Send the chosen voiceId as tts.voiceId in Create an agent or Update an agent.
Updated about 2 hours ago
Did this page help you?
