curl --location 'https://api.inworld.ai/voices/v1/voices:clone' \
--header "Authorization: Basic $INWORLD_API_KEY" \
--header 'Content-Type: application/json' \
--data '{
"displayName": "my_voice_clone_demo",
"languageCode": "en-US",
"voiceSamples": [
{
"audioData": "<base64-audio-data>",
"transcription": "Hello! This is a short voice sample for cloning."
}
],
"description": "Voice clone created from provided WAV sample.",
"tags": ["demo", "clone"],
"audioProcessingConfig": {
"removeBackgroundNoise": true
}
}'import requests
url = "https://api.inworld.ai/voices/v1/voices:clone"
headers = {
"Authorization": "Basic <api-key>",
"Content-Type": "application/json"
}
payload = {
"displayName": "my_voice_clone_demo",
"languageCode": "en-US",
"voiceSamples": [
{
"audioData": "<base64-audio-data>",
"transcription": "Hello! This is a short voice sample for cloning."
}
],
"description": "Voice clone created from provided WAV sample.",
"tags": ["demo", "clone"],
"audioProcessingConfig": {
"removeBackgroundNoise": True
}
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())const url = 'https://api.inworld.ai/voices/v1/voices:clone';
const response = await fetch(url, {
method: 'POST',
headers: {
'Authorization': 'Basic <api-key>',
'Content-Type': 'application/json',
},
body: JSON.stringify({
displayName: 'my_voice_clone_demo',
langCode: 'EN_US',
voiceSamples: [
{
audioData: '<base64-audio-data>',
transcription: 'Hello! This is a short voice sample for cloning.',
},
],
description: 'Voice clone created from provided WAV sample.',
tags: ['demo', 'clone'],
audioProcessingConfig: {
removeBackgroundNoise: true,
},
}),
});
const data = await response.json();
console.log(data);{
"audioSamplesValidated": [
{
"audioData": "<base64-wav-bytes>",
"errors": [],
"langCode": "EN_US",
"transcription": "Hello! This is a short voice sample for cloning.",
"warnings": []
}
],
"voice": {
"voiceId": "your_workspace_id__my_voice_clone_demo_20260218_223134z",
"langCode": "EN_US",
"displayName": "my_voice_clone_demo",
"description": "Voice clone created from provided WAV sample.",
"tags": [
"demo",
"clone"
],
"name": "workspaces/your_workspace_id/voices/my_voice_clone_demo_20260218_223134z",
"source": "IVC"
}
}{
"code": 7,
"message": "API key has insufficient access level for 'voices' in workspace 'your_workspace_id'. Current access level in API key: read (r). Required access level: write (rw).",
"details": []
}Clone a voice
Clone a voice from audio samples.
curl --location 'https://api.inworld.ai/voices/v1/voices:clone' \
--header "Authorization: Basic $INWORLD_API_KEY" \
--header 'Content-Type: application/json' \
--data '{
"displayName": "my_voice_clone_demo",
"languageCode": "en-US",
"voiceSamples": [
{
"audioData": "<base64-audio-data>",
"transcription": "Hello! This is a short voice sample for cloning."
}
],
"description": "Voice clone created from provided WAV sample.",
"tags": ["demo", "clone"],
"audioProcessingConfig": {
"removeBackgroundNoise": true
}
}'import requests
url = "https://api.inworld.ai/voices/v1/voices:clone"
headers = {
"Authorization": "Basic <api-key>",
"Content-Type": "application/json"
}
payload = {
"displayName": "my_voice_clone_demo",
"languageCode": "en-US",
"voiceSamples": [
{
"audioData": "<base64-audio-data>",
"transcription": "Hello! This is a short voice sample for cloning."
}
],
"description": "Voice clone created from provided WAV sample.",
"tags": ["demo", "clone"],
"audioProcessingConfig": {
"removeBackgroundNoise": True
}
}
response = requests.post(url, json=payload, headers=headers)
print(response.json())const url = 'https://api.inworld.ai/voices/v1/voices:clone';
const response = await fetch(url, {
method: 'POST',
headers: {
'Authorization': 'Basic <api-key>',
'Content-Type': 'application/json',
},
body: JSON.stringify({
displayName: 'my_voice_clone_demo',
langCode: 'EN_US',
voiceSamples: [
{
audioData: '<base64-audio-data>',
transcription: 'Hello! This is a short voice sample for cloning.',
},
],
description: 'Voice clone created from provided WAV sample.',
tags: ['demo', 'clone'],
audioProcessingConfig: {
removeBackgroundNoise: true,
},
}),
});
const data = await response.json();
console.log(data);{
"audioSamplesValidated": [
{
"audioData": "<base64-wav-bytes>",
"errors": [],
"langCode": "EN_US",
"transcription": "Hello! This is a short voice sample for cloning.",
"warnings": []
}
],
"voice": {
"voiceId": "your_workspace_id__my_voice_clone_demo_20260218_223134z",
"langCode": "EN_US",
"displayName": "my_voice_clone_demo",
"description": "Voice clone created from provided WAV sample.",
"tags": [
"demo",
"clone"
],
"name": "workspaces/your_workspace_id/voices/my_voice_clone_demo_20260218_223134z",
"source": "IVC"
}
}{
"code": 7,
"message": "API key has insufficient access level for 'voices' in workspace 'your_workspace_id'. Current access level in API key: read (r). Required access level: write (rw).",
"details": []
}/workspaces/{workspace} is no longer required in the path for simplicity and clarity. When omitted, the workspace is derived from your API key. The previous URL with the full path /voices/v1/workspaces/{workspace}/voices:clone would continue to be supported.gender, ageGroup, and categories. These cannot be set at clone time — sending them here (or putting them in tags) is silently ignored, and they come back empty on the response. After cloning, set them with UpdateVoice.Choosing the voice’s language
Set the language withlanguageCode — the canonical locale string, e.g. "en-US", "en-GB", "vi":
- Matching is forgiving — case- and separator-insensitive (
en-gb,EN_GB, anden-GBare equivalent). A bare language code with no region ("en","pt") selects the language’s default accent. - Accent is part of the locale — there is no separate accent field. To clone a British-accented voice, send
"en-GB"; for Australian,"en-AU". - Auto-detect — omit the field (or send
"auto") to detect the language from the audio samples. - Validation — values outside the supported catalog are rejected with
INVALID_ARGUMENT; nothing is silently coerced.
langCode. Older integrations set the language via the langCode enum (the locale with - replaced by _, uppercased — en-GB → EN_GB; AUTO = auto-detect). It remains accepted, and responses populate it alongside languageCode. Set at most one of the two on a request; use languageCode in new code.Authorizations
Your API key. Read permissions are required for GET endpoints. Write permissions are required for POST, PATCH, and DELETE endpoints.
For Basic authentication, please populate Basic $INWORLD_API_KEY. You can create a key in one command with the Inworld CLI: inworld workspace add-key.
Body
Request message for CloneVoice custom method.
The human-readable name shown anywhere the voice is listed or selected. Keep it short and distinctive so users can find it easily.
Voice samples used for cloning. For best results, provide clear audio and avoid speaking in multiple languages, whispering, or making non-verbal sounds like coughing. Instant voice cloning works best with a 10-15 sec audio clip; longer clips will be cutoff at 15sec, which can affect quality. See Voice Cloning Best Practices for guidance on how to generate a high-quality voice clone.
Show child attributes
Show child attributes
Legacy enum encoding of the voice's language. The full accepted set is much larger than the values listed here: every supported locale has an enum name (the locale with - replaced by _, uppercased — en-GB becomes EN_GB). Prefer the languageCode string field on new integrations. AUTO (or omitting the language entirely) auto-detects the language.
EN_US, ZH_CN, KO_KR, JA_JP, RU_RU, AUTO, IT_IT, ES_ES, PT_BR, DE_DE, FR_FR, AR_SA, PL_PL, NL_NL, HI_IN, HE_IL The voice's language as a canonical BCP-47-shaped locale string (e.g. en-US, en-GB, vi). Set at most one of languageCode or langCode — they are two encodings of the same value. Matching is case- and separator-insensitive (en-gb, EN_GB and en-GB are equivalent); a bare language code with no region (e.g. en, pt) selects the language's default accent. Omit both fields to auto-detect the language (equivalently: langCode: "AUTO" or languageCode: "auto"). Values outside the supported catalog are rejected with INVALID_ARGUMENT. See Languages for the supported set.
Longer blurb that explains the voice's tone, accent, use cases, or other relevant attributes. Helpful for search and selection.
Free-form labels for filtering, grouping, and discovery (e.g. ["british", "calm"]). This is not where gender or age go — those are separate fields set via UpdateVoice after cloning.
Audio processing config for voice cloning.
Show child attributes
Show child attributes
Response
A successful response.
Response message for CloneVoice custom method.
Voice resource representing a voice configuration.
Show child attributes
Show child attributes
{
"name": "workspaces/your_workspace_id/voices/my_voice_clone_demo_20260218_223134z",
"voiceId": "your_workspace_id__my_voice_clone_demo_20260218_223134z",
"langCode": "EN_US",
"displayName": "John",
"description": "Cloned voice for narrations.",
"tags": ["demo", "clone"],
"categories": [],
"source": "IVC",
"gender": "",
"ageGroup": "",
"promptLanguages": ["en-US"]
}
The list of validated samples.
Show child attributes
Show child attributes
Was this page helpful?