List your cloned voices
/v1/custom-voicesList your organization's cloned voices across all projects, newest first by default. Deleted voices are excluded. Each result contains a voice ID in voice.id, for example AM:@narrator. Use that ID as voice when generating speech.
Pagination
Request up to 100 voices with page_size (default 30). When has_more is true, copy next_cursor into cursor in the next request. Stop when has_more is false.
Authorization
BearerAuth Tenant key supplied as the Authorization Bearer token.
In: header
Query Parameters
Voices per page, 1–100. Defaults to 30.
Copy next_cursor from the previous response. Omit for the first page.
desc (default) returns newest first; asc returns oldest first.
"desc"Value in
- "asc"
- "desc"
Response Body
application/json
application/json
application/json
application/json
application/json
const voicesById = new Map();let cursor;do { const url = new URL("https://api.allmodels.io/v1/custom-voices"); url.searchParams.set("page_size", "30"); url.searchParams.set("sort_direction", "desc"); if (cursor) url.searchParams.set("cursor", cursor); const response = await fetch(url, { headers: { Authorization: "Bearer " + process.env.ALLMODELS_API_KEY } }); if (!response.ok) throw new Error(await response.text()); const page = await response.json(); for (const entry of page.voices) { const entries = voicesById.get(entry.voice.id) ?? []; entries.push(entry); voicesById.set(entry.voice.id, entries); } cursor = page.has_more ? page.next_cursor : null;} while (cursor);console.log([...voicesById.keys()]);import osimport requestsvoices_by_id = {}params = {"page_size": 30, "sort_direction": "desc"}while True: response = requests.get( "https://api.allmodels.io/v1/custom-voices", headers={"Authorization": f"Bearer {os.environ['ALLMODELS_API_KEY']}"}, params=params, timeout=30, ) response.raise_for_status() page = response.json() for entry in page["voices"]: voices_by_id.setdefault(entry["voice"]["id"], []).append(entry) if not page["has_more"]: break params["cursor"] = page["next_cursor"]print(list(voices_by_id))# First pagecurl --fail-with-body "https://api.allmodels.io/v1/custom-voices?page_size=30&sort_direction=desc" \ -H "Authorization: Bearer $ALLMODELS_API_KEY"# When has_more is true, set NEXT_CURSOR to the returned next_cursor.curl --fail-with-body --get "https://api.allmodels.io/v1/custom-voices" \ -H "Authorization: Bearer $ALLMODELS_API_KEY" \ --data-urlencode "page_size=30" \ --data-urlencode "sort_direction=desc" \ --data-urlencode "cursor=$NEXT_CURSOR"{ "voices": [ { "model": { "id": "soniox/tts-rt-v2", "name": "Soniox tts-rt-v2" }, "voice": { "id": "AM:@narrator", "name": "narrator", "description": null, "category": { "id": "cloned", "name": "Cloned" }, "languages": [], "scope": { "type": "organization" }, "status": "active", "fee_credits": 0, "first_seen_at": "2026-09-11T02:00:00.000Z", "last_seen_at": "2026-09-11T02:00:05.000Z" }, "providers": [ { "id": "soniox", "name": "Soniox", "provider_model_id": "tts-rt-v2", "status": "active", "failure_reason": null } ] } ], "total_count": 1, "has_more": false, "next_cursor": null}{ "error": "invalid_api_key"}{ "error": "tenant_disabled"}{ "error": "custom_voices_failed", "message": "The request could not be completed. Try again; if you were creating or deleting a voice, check its status first."}{ "error": "custom_voices_unavailable"}Fetch a cloning sample with a signed grant GET
Serve the audio sample of a voice being cloned, to a provider that clones from a URL it fetches itself. The token is issued by AllModels for a single clone, expires after ten minutes, and is the only thing that authorizes the read — there is no other way to address a sample, and a voice ID cannot be turned into one. Every failure, expiry included, answers `404`.
Clone a voice POST
Clone a voice from a recording and use its voice ID to generate speech.
