Voices
APIEvery voice you can speak with, in one collection: the ready-made Neurall catalog, plus the voices you clone yourself. Cloning posts here rather than to generations, because what comes back is a reusable id and not a file.
Generated from the live contract. The same page as markdown, and the whole surface as openapi.json.
In this collection
List Voices
GET /v3/voices
Every voice this project can speak with: its own cloned voices first (`owner: project`), then the Neurall catalog (`owner: neurall`), which is ready-made and identical for every caller. Filter with `?owner=`.
Pass a voice's `id` (or a catalog `slug`, the stable handle worth hardcoding) as `args.voiceId` in an audio/voiceover or video/avatar generation. `preview` is a presigned audition clip on catalog voices and expires after ~6 hours; a clone carries a `status` instead, until it is `done`.
curl -X GET "https://api.neurall.io/v3/voices" \
-H "Authorization: nl-YOUR_API_KEY"Query
owner'neurall' | 'project'- `project` for this project's own clones, `neurall` for the ready-made catalog. Omit for both. Anything else is a 400. `tag` and `locale` describe catalog rows only, so they are ignored on clones rather than silently hiding them.
tagstring[]- Only voices carrying ALL of these tags. May repeat (?tag=female&tag=warm). Tags are lowercase descriptors: gender, age, accent, style, plus the category (narration, conversational, character, creature).
localestring- Only voices recorded for one locale, matched exactly against the voice's own `locale` (e.g. `en-US`). It is not a prefix: `en` returns nothing.
Responses
200 This project's clones, then the published catalog
voicesobject[]- A voice this project can speak with. `owner: neurall` is a catalog voice, ready to use and identical for every caller. `owner: project` is one of the project's own clones, which carries the same status lifecycle as a Generation while it trains. A voice's own id is what goes in `args.voiceId`.
Example
{
"voices": [
{
"id": "d77c4b2e-5a90-4f13-b8c6-1e2f3a4b5c6d",
"owner": "project",
"status": "done",
"name": "Founder voice"
},
{
"id": "5b3a9d10-2c47-4e8f-a6b1-9d0c3e7f2a84",
"owner": "neurall",
"slug": "aria",
"name": "Aria",
"tags": [
"female",
"warm",
"narration"
],
"locale": "en-US",
"favorite": false,
"preview": "https://cdn.neurall.io/…/aria-preview.mp3"
}
]
}401 Unauthorized
Clone a Voice
POST /v3/voices
Clone a voice from an audio sample: upload about thirty seconds of clean speech to /v3/files/upload, then POST its file id here. Returns immediately with `status: running`; poll GET /v3/voices/{id} until it is `done`, or pass `webhookUrl` and be told.
The id you get back IS the voiceId, usable in `args.voiceId` on audio/voiceover and video/avatar. Charged on submit like a generation, refunded on error or timeout. An organization may have 5 voices training at once.
curl -X POST "https://api.neurall.io/v3/voices" \
-H "Authorization: nl-YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "<name>",
"audio": "<audio>",
"description": "<description>",
"webhookUrl": "<webhookUrl>"
}'Body
namestringrequired- Name for the voice.
audiostringrequired- File id of the audio sample, from POST /v3/files/upload. MP3, WAV, M4A, OGG, FLAC or WebM, holding a real audio stream.
descriptionstringwebhookUrlstring- Optional https URL to POST the finished voice to (`voice.done` / `voice.error`), signed exactly like a generation webhook.
Responses
200 The voice, still training
voiceobject- A voice this project can speak with. `owner: neurall` is a catalog voice, ready to use and identical for every caller. `owner: project` is one of the project's own clones, which carries the same status lifecycle as a Generation while it trains. A voice's own id is what goes in `args.voiceId`.
Example
{
"voice": {
"id": "d77c4b2e-5a90-4f13-b8c6-1e2f3a4b5c6d",
"owner": "project",
"status": "running",
"name": "Founder voice",
"requestDate": "2026-08-25T17:04:12.000Z"
}
}400 Missing name or audio, or the sample is too short
401 Unauthorized
402 Insufficient balance
429 Too many voices training at once (Retry-After header)
Get Voice
GET /v3/voices/{id}
Resolves ONE voice without pulling the whole list: a catalog voice by uuid or by slug, or one of this project's own clones by its id. The shapes cannot collide, so a caller holding a voiceId never has to know which kind it is holding.
On a clone this is the poll: after POST /v3/voices it answers `status: running` until the voice is `done` (or `error`), which is the same loop a generation uses.
On a catalog voice there are two reasons to reach for it. First, `preview` is a presigned audition clip that expires after about 6 hours, so this is how you refresh the sample for a voice your app already knows about and lets a user play. Second, it is the cheap way to confirm a slug you hardcoded is still published: a retired voice answers 404 here rather than failing later, inside a generation you have already paid for.
curl -X GET "https://api.neurall.io/v3/voices/<id>" \
-H "Authorization: nl-YOUR_API_KEY"Path
idstringrequired- A catalog voice's uuid or slug, or one of this project's clone ids.
Responses
200 The voice
voiceobject- A voice this project can speak with. `owner: neurall` is a catalog voice, ready to use and identical for every caller. `owner: project` is one of the project's own clones, which carries the same status lifecycle as a Generation while it trains. A voice's own id is what goes in `args.voiceId`.
Example
{
"voice": {
"id": "d77c4b2e-5a90-4f13-b8c6-1e2f3a4b5c6d",
"owner": "project",
"status": "done",
"name": "Founder voice",
"requestDate": "2026-08-25T17:04:12.000Z",
"responseDate": "2026-08-25T17:09:35.000Z"
}
}401 Unauthorized
404 Voice not found
Delete a Voice
DELETE /v3/voices/{id}
Delete one of this project's cloned voices. It stops resolving everywhere, so anything still passing that id as `args.voiceId` starts failing, and there is no undelete: cloning again is a new generation. Catalog voices are not deletable.
curl -X DELETE "https://api.neurall.io/v3/voices/<id>" \
-H "Authorization: nl-YOUR_API_KEY"Path
idstringrequired
Responses
200 Deleted
successboolean
Example
{
"success": true
}401 Unauthorized
404 Not one of this project's cloned voices