Needs keys Creates a voice from one or more audio samples and adds it to your workspace's voices. Real cloning needs the chosen vendor's key (ELEVENLABS_API_KEY, FISH_API_KEY or MINIMAX_API_KEY).
Without that key, or with TRIED_MOCK_PROVIDERS=1, Tried stores the voice with a mock_ provider ID so you can build and test agents end to end.
Request#
Send multipart/form-data with the fields below and one or more audio file parts. A JSON body is also accepted (see JSON form).
| Field | Type | Required | Description |
|---|---|---|---|
voice_name |
string | Yes | Name of the new voice. 1 to 100 characters. |
description |
string | No | Up to 500 characters. Sent to ElevenLabs and Fish Audio. |
provider |
string | No | elevenlabs (default), fishaudio or minimax. |
files |
file | Yes | Audio samples. Send at least one. All samples together can be at most 25 MB. MiniMax uses only the first file. |
JSON form#
For scripts, send application/json with the same fields and the samples as base64:
{
"voice_name": "Front desk (Sydney)",
"provider": "elevenlabs",
"files": [
{ "filename": "sample.mp3", "mimetype": "audio/mpeg", "content_base64": "SUQzBAAAAAAA..." }
]
}filename defaults to sample.mp3 and mimetype to audio/mpeg. The whole JSON body is limited to 25 MB.
Example request#
curl -X POST https://api.tried.com.au/clone-voice \
-H "Authorization: Bearer $TRIED_API_KEY" \
-F voice_name="Front desk (Sydney)" \
-F provider=elevenlabs \
-F files=@sample1.mp3 \
-F files=@sample2.mp3import { readFile } from "node:fs/promises";
const form = new FormData();
form.append("voice_name", "Front desk (Sydney)");
form.append("provider", "elevenlabs");
form.append("files", new Blob([await readFile("sample1.mp3")], { type: "audio/mpeg" }), "sample1.mp3");
const res = await fetch("https://api.tried.com.au/clone-voice", {
method: "POST",
headers: { Authorization: `Bearer ${process.env.TRIED_API_KEY}` },
body: form,
});
const voice = await res.json();import os, requests
with open("sample1.mp3", "rb") as f:
res = requests.post(
"https://api.tried.com.au/clone-voice",
headers={"Authorization": f"Bearer {os.environ['TRIED_API_KEY']}"},
data={"voice_name": "Front desk (Sydney)", "provider": "elevenlabs"},
files=[("files", ("sample1.mp3", f, "audio/mpeg"))],
)
voice = res.json()Response#
201 Created
{
"voice_id": "custom_voice_137bcfa732ab6e2df5d2b815",
"voice_name": "Front desk (Sydney)",
"provider": "elevenlabs",
"provider_voice_id": "mock_9f060d81a4d8df9b04ca",
"gender": "female",
"accent": "Custom",
"age": "middle_aged",
"preview_audio_url": null
}| Field | Type | Description |
|---|---|---|
voice_id |
string | Starts with custom_voice_. Set it as an agent's voice_id. |
provider_voice_id |
string | The vendor's voice ID. In mock mode it starts with mock_. For MiniMax it is an ID Tried picks, starting with Tried. |
gender |
string | Always female for cloned voices. |
accent |
string | Always Custom. |
age |
string | Always middle_aged. |
preview_audio_url |
null | Always null. |
Errors#
| Status | When |
|---|---|
400 |
A field fails validation (for example voice_name missing), At least one audio sample (files) is required, Audio samples are limited to 25 MB in total, or the vendor rejects the clone (ElevenLabs voice clone failed (<status>): ..., and the same for Fish Audio and MiniMax). |
401 |
Missing or invalid API key. |
403 |
The key's IP allowlist or scopes reject the request (this route needs the agents scope), or the caller is a read-only dashboard member. |
413 |
A single file is over 50 MB, or the JSON body is over 25 MB. |
429 |
Rate limit exceeded. See Rate limits. |
See Errors for the body format.
Retell compatibility#
Same path and method as Retell, and both take multipart voice_name plus files. The provider field differs: Tried reads provider with values elevenlabs, fishaudio and minimax, and defaults to elevenlabs.