curl --location --request PATCH 'https://api.inworld.ai/voices/v1/voices/<voice-id>' \
--header "Authorization: Basic $INWORLD_API_KEY" \
--header 'Content-Type: application/json' \
--data '{
"displayName": "John",
"description": "Cloned voice for narrations.",
"tags": ["demo", "clone"]
}'import requests
voice_id = "<voice-id>"
url = f"https://api.inworld.ai/voices/v1/voices/{voice_id}"
headers = {
"Authorization": "Basic <api-key>",
"Content-Type": "application/json"
}
payload = {
"displayName": "John",
"description": "Cloned voice for narrations.",
"tags": ["demo", "clone"]
}
response = requests.patch(url, json=payload, headers=headers)
print(response.json())const voiceId = '<voice-id>';
const url = `https://api.inworld.ai/voices/v1/voices/${voiceId}`;
const response = await fetch(url, {
method: 'PATCH',
headers: {
'Authorization': 'Basic <api-key>',
'Content-Type': 'application/json',
},
body: JSON.stringify({
displayName: 'John',
description: 'Cloned voice for narrations.',
tags: ['demo', 'clone'],
}),
});
const data = await response.json();
console.log(data);{
"voiceId": "your_workspace_id__my_voice_clone_demo_20260218_223134z",
"langCode": "EN_US",
"displayName": "John",
"description": "Cloned voice for narrations.",
"tags": [
"demo",
"clone"
],
"name": "workspaces/your_workspace_id/voices/my_voice_clone_demo_20260218_223134z",
"source": "IVC"
}{
"code": 123,
"message": "<string>",
"details": [
{
"@type": "<string>"
}
]
}Update a voice
curl --location --request PATCH 'https://api.inworld.ai/voices/v1/voices/<voice-id>' \
--header "Authorization: Basic $INWORLD_API_KEY" \
--header 'Content-Type: application/json' \
--data '{
"displayName": "John",
"description": "Cloned voice for narrations.",
"tags": ["demo", "clone"]
}'import requests
voice_id = "<voice-id>"
url = f"https://api.inworld.ai/voices/v1/voices/{voice_id}"
headers = {
"Authorization": "Basic <api-key>",
"Content-Type": "application/json"
}
payload = {
"displayName": "John",
"description": "Cloned voice for narrations.",
"tags": ["demo", "clone"]
}
response = requests.patch(url, json=payload, headers=headers)
print(response.json())const voiceId = '<voice-id>';
const url = `https://api.inworld.ai/voices/v1/voices/${voiceId}`;
const response = await fetch(url, {
method: 'PATCH',
headers: {
'Authorization': 'Basic <api-key>',
'Content-Type': 'application/json',
},
body: JSON.stringify({
displayName: 'John',
description: 'Cloned voice for narrations.',
tags: ['demo', 'clone'],
}),
});
const data = await response.json();
console.log(data);{
"voiceId": "your_workspace_id__my_voice_clone_demo_20260218_223134z",
"langCode": "EN_US",
"displayName": "John",
"description": "Cloned voice for narrations.",
"tags": [
"demo",
"clone"
],
"name": "workspaces/your_workspace_id/voices/my_voice_clone_demo_20260218_223134z",
"source": "IVC"
}{
"code": 123,
"message": "<string>",
"details": [
{
"@type": "<string>"
}
]
}/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/{voice} would continue to be supported.Setting gender, age group, and categories on a cloned voice
These fields can’t be set at clone time — CloneVoice accepts onlydisplayName, langCode, voiceSamples, description, tags, and audioProcessingConfig. To populate them, PATCH the voice after cloning.
The updateMask query parameter controls which fields actually get applied — any field in the body but missing from the mask is silently ignored. Mask paths use snake_case field names (e.g. age_group), even though the request body uses camelCase (ageGroup). Passing the camelCase form (?updateMask=gender,ageGroup) silently fails for multi-word fields.
curl -X PATCH \
"https://api.inworld.ai/voices/v1/voices/<voice-id>?updateMask=gender,age_group,categories" \
-H "Authorization: Basic $INWORLD_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"gender": "female",
"ageGroup": "young",
"categories": ["companions"]
}'
<voice-id> is the voiceId returned by CloneVoice, in the format {workspace}__{voice}.
Response (200):
{
"name": "workspaces/{workspace}/voices/{voice}",
"voiceId": "{workspace}__{voice}",
"langCode": "EN_US",
"displayName": "John",
"description": "Cloned voice for narrations.",
"tags": ["demo", "clone"],
"source": "IVC",
"gender": "female",
"ageGroup": "young",
"categories": ["companions"],
"promptLanguages": ["en-US"]
}
gender:"male","female","neutral"ageGroup:"young","middle_aged","elderly"categories:"companions","developer_assistants","education_training","enterprise","healthcare","interactive_media"
gender and ageGroup (which are silently dropped if you misuse the mask), an invalid categories value returns HTTP 400 and rejects the entire request — including any valid categories in the same list.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.
Path Parameters
Voice ID containing the voice to update. Expected format: {workspace}__{voice}.
[^/]+Query Parameters
Comma-separated list of fields to update. Paths use snake_case field names, even though the request body uses camelCase. Supported paths: display_name, description, tags, gender, age_group, categories. Fields present in the body but omitted from updateMask are ignored.
"gender,age_group"
Body
The voice resource to update
The human-readable name shown anywhere the voice is listed or selected. Keep it short and distinctive so users can find it easily.
Description of the voice, such as 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"]). Structured metadata like gender and age has dedicated fields — see gender, ageGroup, and categories below.
Voice gender. Include gender in updateMask to apply this field.
male, female, neutral Age group of the voice. Include age_group (snake_case) in updateMask to apply this field.
young, middle_aged, elderly Use-case categories the voice belongs to. Include categories in updateMask to apply this field. An invalid value returns HTTP 400 and rejects the whole request (all-or-nothing), unlike gender/ageGroup which are silently dropped when the mask is wrong.
companions, developer_assistants, education_training, enterprise, healthcare, interactive_media Response
A successful response.
Voice resource representing a voice configuration.
Voice ID. SYSTEM voices use a simple name (e.g. Alex); IVC voices are workspace-prefixed ({workspace}__{voice}).
Primary language of the voice in upper-snake format (e.g. EN_US). Note that when filtering via lang_code, you can pass BCP-47 (en-US), underscore form (en_US), or a language prefix (en) — but the response always returns upper-snake.
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 human-readable name shown anywhere the voice is listed or selected.
Longer blurb that explains the voice's tone, accent, use cases, or other relevant attributes.
Free-form labels for filtering, grouping, and discovery (e.g. british, calm).
Resource name. Format: workspaces/{workspace}/voices/{voice}.
Origin of the voice:
SYSTEM: Built-in voice provided by Inworld, visible to all workspaces.IVC: Voice cloned from audio or created via Voice Design — owned by your workspace only.PVC: Professional Voice Clone.
SYSTEM, IVC, PVC Voice gender (male, female, neutral). Empty string if unspecified. Voices with no gender are excluded when filtering with an explicit gender = predicate.
male, female, neutral, Age group of the voice (young, middle_aged, elderly). Empty string if unspecified.
young, middle_aged, elderly, Use-case categories the voice belongs to. Filterable with the : (has) operator.
Supported values: companions, enterprise, education_training, developer_assistants, healthcare, interactive_media.
companions, enterprise, education_training, developer_assistants, healthcare, interactive_media Languages the voice can handle, in BCP-47 format (e.g. en-US). May differ from langCode for multilingual voices.