curl -X GET "https://api.hooked.so/v1/voice/list?language=English&gender=Female" \
-H "x-api-key: your_api_key_here"
const response = await fetch('https://api.hooked.so/v1/voice/list?language=English&gender=Female', {
headers: { 'x-api-key': 'your_api_key_here' }
});
const { data } = await response.json();
const usable = data.voices.filter((voice) => !voice.unavailable);
import requests
response = requests.get(
'https://api.hooked.so/v1/voice/list',
params={'type': 'custom'},
headers={'x-api-key': 'your_api_key_here'}
)
voices = [v for v in response.json()['data']['voices'] if not v.get('unavailable')]
{
"success": true,
"data": {
"voices": [
{
"id": "tzX5paJ07p5hyWFcU3uG",
"voiceId": "tzX5paJ07p5hyWFcU3uG",
"name": "Jude",
"gender": "Male",
"language": "English",
"accent": "British",
"country": "GB",
"age": "young",
"templateUrl": "https://.../preview.mp3",
"thumbnail": "/images/voice-default.png",
"isCustom": false,
"source": "library",
"description": "Calm and clear"
},
{
"id": "cm2b3c4d5e6f7g8h9i0j1k2l3",
"voiceId": "Xb7hH8MSUJpSbSDYk0k2",
"name": "My cloned voice",
"gender": "Female",
"language": "English",
"country": "US",
"age": "unknown",
"templateUrl": "https://.../sample.mp3",
"isCustom": true,
"source": "custom",
"ownerProvider": "managed",
"unavailable": true,
"unavailableReason": "This voice was cloned in Hooked's ElevenLabs account and is unavailable while the team is in BYOK mode."
}
],
"total": 2,
"limit": 50,
"offset": 0
}
}
Voices
List Voices
Get the voices you can narrate with: the library plus your team’s cloned voices
GET
/
v1
/
voice
/
list
curl -X GET "https://api.hooked.so/v1/voice/list?language=English&gender=Female" \
-H "x-api-key: your_api_key_here"
const response = await fetch('https://api.hooked.so/v1/voice/list?language=English&gender=Female', {
headers: { 'x-api-key': 'your_api_key_here' }
});
const { data } = await response.json();
const usable = data.voices.filter((voice) => !voice.unavailable);
import requests
response = requests.get(
'https://api.hooked.so/v1/voice/list',
params={'type': 'custom'},
headers={'x-api-key': 'your_api_key_here'}
)
voices = [v for v in response.json()['data']['voices'] if not v.get('unavailable')]
{
"success": true,
"data": {
"voices": [
{
"id": "tzX5paJ07p5hyWFcU3uG",
"voiceId": "tzX5paJ07p5hyWFcU3uG",
"name": "Jude",
"gender": "Male",
"language": "English",
"accent": "British",
"country": "GB",
"age": "young",
"templateUrl": "https://.../preview.mp3",
"thumbnail": "/images/voice-default.png",
"isCustom": false,
"source": "library",
"description": "Calm and clear"
},
{
"id": "cm2b3c4d5e6f7g8h9i0j1k2l3",
"voiceId": "Xb7hH8MSUJpSbSDYk0k2",
"name": "My cloned voice",
"gender": "Female",
"language": "English",
"country": "US",
"age": "unknown",
"templateUrl": "https://.../sample.mp3",
"isCustom": true,
"source": "custom",
"ownerProvider": "managed",
"unavailable": true,
"unavailableReason": "This voice was cloned in Hooked's ElevenLabs account and is unavailable while the team is in BYOK mode."
}
],
"total": 2,
"limit": 50,
"offset": 0
}
}
Overview
Returns the voices available to your team for narration: the ElevenLabs library voices, followed by your team’s custom (cloned) voices. Use a voice’sid as voiceId in the create endpoints that narrate (Script to Video, Prompt to Video, Quiz, Reddit Story, Scenes, …).
A cloned voice lives in the ElevenLabs account it was cloned in. A voice cloned while your team used Hooked’s keys (managed) cannot be used while the team is on its own keys (BYOK), and the other way round. Such voices are still listed, with
unavailable: true and the reason in unavailableReason.limit (default 50, at most 100) and offset; you are done when offset + limit >= total.
curl -X GET "https://api.hooked.so/v1/voice/list?language=English&gender=Female" \
-H "x-api-key: your_api_key_here"
const response = await fetch('https://api.hooked.so/v1/voice/list?language=English&gender=Female', {
headers: { 'x-api-key': 'your_api_key_here' }
});
const { data } = await response.json();
const usable = data.voices.filter((voice) => !voice.unavailable);
import requests
response = requests.get(
'https://api.hooked.so/v1/voice/list',
params={'type': 'custom'},
headers={'x-api-key': 'your_api_key_here'}
)
voices = [v for v in response.json()['data']['voices'] if not v.get('unavailable')]
{
"success": true,
"data": {
"voices": [
{
"id": "tzX5paJ07p5hyWFcU3uG",
"voiceId": "tzX5paJ07p5hyWFcU3uG",
"name": "Jude",
"gender": "Male",
"language": "English",
"accent": "British",
"country": "GB",
"age": "young",
"templateUrl": "https://.../preview.mp3",
"thumbnail": "/images/voice-default.png",
"isCustom": false,
"source": "library",
"description": "Calm and clear"
},
{
"id": "cm2b3c4d5e6f7g8h9i0j1k2l3",
"voiceId": "Xb7hH8MSUJpSbSDYk0k2",
"name": "My cloned voice",
"gender": "Female",
"language": "English",
"country": "US",
"age": "unknown",
"templateUrl": "https://.../sample.mp3",
"isCustom": true,
"source": "custom",
"ownerProvider": "managed",
"unavailable": true,
"unavailableReason": "This voice was cloned in Hooked's ElevenLabs account and is unavailable while the team is in BYOK mode."
}
],
"total": 2,
"limit": 50,
"offset": 0
}
}
Errors
| Status | When |
|---|---|
| 401 | Missing or invalid API key (code: "not_authenticated") |
| 403 | The team does not have the Hooked app product (code: "entitlement_required") |
| 500 | { "success": false, "message": "Failed to fetch voices" } |
If the voice provider cannot be reached, the library part comes back empty instead of failing. The call is free and safe to retry.
Authorizations
Query Parameters
library (library voices only), custom (your team's cloned voices only) or all (both).
Available options:
library, custom, all Only voices in this language, case-insensitive exact match (for example English, Spanish).
Only voices of this gender, case-insensitive exact match (for example Male, Female).
Page size, 1 to 100. Larger values are capped at 100; missing or invalid values fall back to 50.
Required range:
1 <= x <= 100Rows to skip. Missing or invalid values fall back to 0. You are done when offset + limit >= total.
Required range:
x >= 0