Voices
List, create, update, publish, and manage voices and their reference audio
Choosing a voice and the catalog are covered in Voices; cloning
and speaker consent in Voice cloning. Pass numeric voice
IDs. To use a voice handle, resolve it with
GET /v1/voices/{handle} and use the returned id.
List available voices
# List voices (returns VoiceListResponse)
result = client.voices.list()
for voice in result.voices:
print(f"{voice.id}: {voice.name}")
print(f" Category: {voice.category}")
print(f" Languages: {', '.join(voice.supported_languages)}")
print(f"Showing {len(result.voices)} of {result.total}")
# Paginate
page2 = client.voices.list(limit=10, offset=10)
print(f"Page 2: {len(page2.voices)} voices (total: {page2.total})")
# Only voices that speak German
german = client.voices.list(language="de")
print(f"{german.total} German voices")// List voices (returns VoiceListResponse)
const result = await client.voices.list();
for (const voice of result.voices) {
console.log(`${voice.id}: ${voice.name}`);
console.log(` Category: ${voice.category}`);
console.log(` Languages: ${voice.supportedLanguages.join(', ')}`);
}
console.log(`Showing ${result.voices.length} of ${result.total}`);
// Paginate
const page2 = await client.voices.list({ limit: 10, offset: 10 });
console.log(`Page 2: ${page2.voices.length} voices (total: ${page2.total})`);
// Only voices that speak German
const german = await client.voices.list({ language: 'de' });
console.log(`${german.total} German voices`);import com.kugelaudio.sdk.Voice;
import com.kugelaudio.sdk.VoiceListResponse;
// List all available voices (returns VoiceListResponse)
VoiceListResponse result = client.voices().list();
for (Voice voice : result.getVoices()) {
System.out.println(voice.getId() + ": " + voice.getName());
System.out.println(" Sex: " + voice.getSex());
System.out.println(" Quality: " + voice.getQuality());
}
System.out.printf("Showing %d of %d%n", result.getVoices().size(), result.getTotal());
// Paginate: list(language, includePublic, limit, offset)
VoiceListResponse page = client.voices().list(null, null, 10, 0);
// Only voices that speak German
VoiceListResponse german = client.voices().list("de", null, 100, 0);
System.out.printf("%d German voices%n", german.getTotal());use kugelaudio::VoiceListOptions;
// List voices (returns VoiceListResponse)
let result = client.voices().list(&VoiceListOptions::default()).await?;
for voice in &result.voices {
println!("{}: {}", voice.id, voice.name);
println!(" Category: {:?}", voice.category);
println!(" Languages: {}", voice.supported_languages.join(", "));
}
println!("Showing {} of {}", result.voices.len(), result.total);
// Paginate
let page2 = client
.voices()
.list(&VoiceListOptions::default().limit(10).offset(10))
.await?;
println!("Page 2: {} voices (total: {})", page2.voices.len(), page2.total);
// Only voices that speak German
let german = client.voices().list(&VoiceListOptions::default().language("de")).await?;
println!("{} German voices", german.total);// List voices (returns VoiceListResponse)
kugelaudio::VoiceListResponse result = client.voices().list();
for (const auto& voice : result.voices) {
std::cout << voice.id << ": " << voice.name << '\n';
std::cout << " Category: " << voice.category.value_or("") << '\n';
std::cout << " Languages:";
for (const auto& language : voice.supported_languages) std::cout << ' ' << language;
std::cout << '\n';
}
std::cout << "Showing " << result.voices.size() << " of " << result.total << '\n';
// Paginate
kugelaudio::VoiceListOptions page_options;
page_options.limit = 10;
page_options.offset = 10;
kugelaudio::VoiceListResponse page2 = client.voices().list(page_options);
// Only voices that speak German
kugelaudio::VoiceListOptions german_options;
german_options.language = "de";
kugelaudio::VoiceListResponse german = client.voices().list(german_options);
std::cout << german.total << " German voices\n";// List voices (returns VoiceListResponse)
final result = await client.voices.list();
for (final voice in result.voices) {
print('${voice.id}: ${voice.name}');
print(' Category: ${voice.category?.value}');
print(' Languages: ${voice.supportedLanguages.join(', ')}');
}
print('Showing ${result.voices.length} of ${result.total}');
// Paginate
final page2 = await client.voices.list(limit: 10, offset: 10);
print('Page 2: ${page2.voices.length} voices (total: ${page2.total})');
// Only voices that speak German
final german = await client.voices.list(language: 'de');
print('${german.total} German voices');The listing returns every voice available to you, page by page (limit and offset).
The language filter matches the voices' BCP-47 language tags, case-insensitively:
de matches every German accent (de-DE, de-AT, de-CH), de-AT only Austrian
German. The total and the pages count the filtered set. Every SDK also accepts an
include-public argument (include_public, includePublic) for compatibility; it has
no effect.
Get a specific voice
voice = client.voices.get(voice_id=1071)
print(f"Voice: {voice.name}")
print(f"Category: {voice.category}")const voice = await client.voices.get(1071);
console.log(`Voice: ${voice.name}`);
console.log(`Category: ${voice.category}`);import com.kugelaudio.sdk.VoiceDetail;
VoiceDetail voice = client.voices().get(1071);
System.out.println("Voice: " + voice.getName());
System.out.println("Quality: " + voice.getQuality());let voice = client.voices().get(1071).await?;
println!("Voice: {}", voice.name);
println!("Category: {:?}", voice.category);kugelaudio::VoiceDetail voice = client.voices().get(1071);
std::cout << "Voice: " << voice.name << '\n';
std::cout << "Category: " << voice.category.value_or("") << '\n';final voice = await client.voices.get(1071);
print('Voice: ${voice.name}');
print('Category: ${voice.category?.value}');get() returns the same fields as the listing (the catalog shape). The public,
verified, pending-verification and sample-text fields are only populated by
create(), update() and publish(); in Java, isPublic() is always false and
getReferences() is empty on get(), so use listReferences(...) for references.
Create a voice
Create a new voice with optional reference audio files:
voice = client.voices.create(
name="My Custom Voice",
sex="female",
speaker_consent=True,
description="A warm, conversational voice",
category="conversational",
reference_files=["reference1.wav", "reference2.wav"],
)
print(f"Created voice: {voice.id}")// Browser: use File objects from an <input type="file">
const fileInput = document.getElementById('audio-upload') as HTMLInputElement;
const files = Array.from(fileInput.files!);
const voice = await client.voices.create({
name: 'My Custom Voice',
sex: 'female',
speakerConsent: true,
description: 'A warm, conversational voice',
category: 'conversational',
referenceFiles: files,
});
console.log(`Created voice: ${voice.id}`);import java.nio.file.Path;
import java.util.List;
VoiceDetail myVoice = client.voices().create(
"My Custom Voice",
"female",
"en", // required by this SDK signature; see the Java tab below
List.of(Path.of("reference1.wav"), Path.of("reference2.wav")),
true // speakerConsent, required
);
int myVoiceId = myVoice.getId();
System.out.println("Created voice: " + myVoiceId);use kugelaudio::{ReferenceFile, VoiceCreate};
// VoiceCreate::new(name, sex, speaker_consent)
let voice = client
.voices()
.create(
&VoiceCreate::new("My Custom Voice", "female", true)
.description("A warm, conversational voice")
.category("conversational")
.reference_file(ReferenceFile::from_path("reference1.wav")?)
.reference_file(ReferenceFile::from_path("reference2.wav")?),
)
.await?;
println!("Created voice: {}", voice.id);kugelaudio::VoiceCreateRequest request;
request.name = "My Custom Voice";
request.sex = "female";
request.speaker_consent = true;
request.description = "A warm, conversational voice";
request.category = kugelaudio::voice_category::kConversational;
request.reference_files = {"reference1.wav", "reference2.wav"};
kugelaudio::VoiceDetail voice = client.voices().create(request);
std::cout << "Created voice: " << voice.id << '\n';import 'package:kugelaudio/io.dart';
final voice = await client.voices.create(
name: 'My Custom Voice',
sex: 'female',
speakerConsent: true,
description: 'A warm, conversational voice',
category: 'conversational',
referenceFiles: [
await loadAudioFile('reference1.wav'),
await loadAudioFile('reference2.wav'),
],
);
print('Created voice: ${voice.id}');Speaker consent is required on create() and on adding a reference. Pass true
to confirm the speaker consent; any
other value is rejected by the API with SPEAKER_CONSENT_REQUIRED.
speaker_consent is a required keyword argument on create() and
add_reference(). The reference_files parameter accepts file paths (str or
Path) whose extensions are WAV, MP3, OGG, M4A, or FLAC.
speakerConsent is required on create() and addReference(). In Node.js, wrap the
file in a File so the multipart upload retains its filename extension:
import { readFileSync } from 'fs';
import { File } from 'node:buffer';
const buf = readFileSync('reference.wav');
const file = new File([new Uint8Array(buf)], 'reference.wav', { type: 'audio/wav' });
const voice = await client.voices.create({
name: 'My Custom Voice',
sex: 'female',
speakerConsent: true,
referenceFiles: [file],
});The last argument of create(...) and addReference(...) is speakerConsent.
The current Java SDK serializes its language argument under the legacy
language key, while the API accepts supported_languages. Voice creation
still succeeds, but that argument does not set the returned voice's language
list; use the REST endpoint when you need to set supported_languages.
Update, delete, reference, and publish calls need a voice you own, so the Java
examples below use myVoiceId from this step.
VoiceCreate::new(name, sex, speaker_consent) takes the consent as its third
argument, and add_reference() takes it as an argument too. Recordings are
ReferenceFiles: ReferenceFile::from_path(path)? reads a file, and
ReferenceFile::new(filename, bytes) wraps bytes you already have. The other
fields are builder methods: .description, .category, .age, .quality,
.supported_languages, .is_public, .sample_text, .reference_file.
VoiceCreateRequest::speaker_consent defaults to false; set it to true.
reference_files are paths to WAV files, and add_reference() takes the consent as
an argument. supported_languages defaults to {"en"}.
speakerConsent is required on create() and addReference(). Recordings are
Audio objects: loadAudioFile(path) from package:kugelaudio/io.dart reads a
file, and Audio(bytes, filename: 'reference.wav') wraps bytes you already have,
for example a Flutter asset or a picked file.
Update a voice
voice = client.voices.update(
voice_id=1071,
name="Updated Name",
description="New description",
)const voice = await client.voices.update(1071, {
name: 'Updated Name',
description: 'New description',
});import java.util.Map;
// The map carries API field names
VoiceDetail updated = client.voices().update(myVoiceId, Map.of(
"name", "Updated Name"
));use kugelaudio::VoiceUpdate;
let voice = client
.voices()
.update(1071, &VoiceUpdate::new().name("Updated Name").description("New description"))
.await?;kugelaudio::VoiceUpdate update;
update.name = "Updated Name";
update.description = "New description";
kugelaudio::VoiceDetail voice = client.voices().update(1071, update);final voice = await client.voices.update(
1071,
name: 'Updated Name',
description: 'New description',
);The current update endpoint (PATCH /v1/voices/{voice_id}) does not accept the
public flag, even though the Python, TypeScript, Rust, C++ and Dart SDKs send one
when you set it. To make a voice public, call publish()
below. The API's generative_voice_description field is not exposed by the SDKs'
create and update methods; use the Voice API reference
when you need it.
Delete a voice
client.voices.delete(voice_id=1071)await client.voices.delete(1071);client.voices().delete(myVoiceId);client.voices().delete(1071).await?;client.voices().remove(1071);await client.voices.delete(1071);Manage reference audio
# List references
for ref in client.voices.list_references(voice_id=1071):
print(f"{ref.id}: {ref.reference_text}")
# Add a new reference (file is positional; accepts a str or Path)
ref = client.voices.add_reference(
voice_id=1071,
file="new_reference.wav",
speaker_consent=True,
reference_text="Optional transcript of the audio.",
)
# Delete a reference
client.voices.delete_reference(voice_id=1071, reference_id=456)// List references
const refs = await client.voices.listReferences(1071);
for (const r of refs) {
console.log(`${r.id}: ${r.referenceText}`);
}
// Add a new reference; audioFile is a File or Blob, built as in "Create a voice"
const ref = await client.voices.addReference(1071, audioFile, {
speakerConsent: true,
referenceText: 'Optional transcript.',
});
// Delete a reference
await client.voices.deleteReference(1071, 456);import com.kugelaudio.sdk.VoiceReference;
// List references
List<VoiceReference> refs = client.voices().listReferences(myVoiceId);
for (VoiceReference ref : refs) {
System.out.println(ref.getId() + ": " + ref.getReferenceText());
}
// Add a new reference
VoiceReference ref = client.voices().addReference(
myVoiceId,
Path.of("new_reference.wav"),
"Optional transcript of the audio.",
true // speakerConsent, required
);
// Delete a reference
client.voices().deleteReference(myVoiceId, ref.getId());use kugelaudio::ReferenceFile;
// List references
for reference in client.voices().list_references(1071).await? {
println!("{}: {:?}", reference.id, reference.reference_text);
}
// Add a new reference: file, speaker_consent, optional transcript
let reference = client
.voices()
.add_reference(
1071,
&ReferenceFile::from_path("new_reference.wav")?,
true,
Some("Optional transcript of the audio."),
)
.await?;
// Delete a reference
client.voices().delete_reference(1071, 456).await?;// List references
for (const auto& reference : client.voices().list_references(1071)) {
std::cout << reference.id << ": " << reference.reference_text << '\n';
}
// Add a new reference: file, speaker_consent, optional transcript
kugelaudio::VoiceReference reference = client.voices().add_reference(
1071, "new_reference.wav", /*speaker_consent=*/true, "Optional transcript of the audio.");
// Delete a reference
client.voices().remove_reference(1071, 456);import 'package:kugelaudio/io.dart';
// List references
for (final reference in await client.voices.listReferences(1071)) {
print('${reference.id}: ${reference.referenceText}');
}
// Add a new reference
final reference = await client.voices.addReference(
1071,
await loadAudioFile('new_reference.wav'),
speakerConsent: true,
referenceText: 'Optional transcript of the audio.',
);
// Delete a reference
await client.voices.deleteReference(1071, 456);The current Java VoiceReference model maps id and reference_text correctly,
but its legacy filename property is not populated by the current API response. See
Voice types for the other legacy voice model fields.
Generate a sample
Generate a preview sample from the voice's sample text (or a default). The voice needs at least one uploaded reference.
# Returns a GeneratedSample: sample_s3_path and a signed, time-limited sample_url
# (None when the server could not sign one)
sample = client.voices.generate_sample(voice_id=1071)
print(f"Sample: {sample.sample_url}")// Returns a VoiceDetail whose sampleUrl points at the new sample
const sample = await client.voices.generateSample(1071);
console.log(`Sample: ${sample.sampleUrl}`);// Only getSampleUrl() is populated; the response carries no other voice fields
VoiceDetail sample = client.voices().generateSample(myVoiceId);
System.out.println("Sample: " + sample.getSampleUrl());// Returns a GeneratedSample: sample_s3_path and a signed, time-limited sample_url
// (None when the server could not sign one)
let sample = client.voices().generate_sample(1071).await?;
println!("Sample: {:?}", sample.sample_url);// Returns a GeneratedSample: sample_s3_path and a signed, time-limited sample_url
// (std::nullopt when the server could not sign one)
kugelaudio::GeneratedSample sample = client.voices().generate_sample(1071);
std::cout << "Sample: " << sample.sample_url.value_or("") << '\n';// Returns a GeneratedSample: sampleS3Path and a signed, time-limited sampleUrl
// (null when the server could not sign one)
final sample = await client.voices.generateSample(1071);
print('Sample: ${sample.sampleUrl}');Publish a voice
Request that your voice be made publicly available. This sets
pending_verification: true on the voice; an admin review decides whether it
becomes visible to others. The call does not change the public flag itself.
voice = client.voices.publish(voice_id=1071)
print(f"Pending verification: {voice.pending_verification}")const voice = await client.voices.publish(1071);
console.log(`Pending verification: ${voice.pendingVerification}`);// The Java VoiceDetail does not expose pending_verification;
// check the state with the REST endpoint.
client.voices().publish(myVoiceId);let voice = client.voices().publish(1071).await?;
println!("Pending verification: {}", voice.pending_verification);kugelaudio::VoiceDetail voice = client.voices().publish(1071);
std::cout << "Pending verification: " << voice.pending_verification << '\n';final voice = await client.voices.publish(1071);
print('Pending verification: ${voice.pendingVerification}');Next steps
- Types and errors:
Voice,VoiceDetail,VoiceReference, and the create/update options - Generate speech: use a voice by its ID
- Voice API reference: the REST response shapes, samples, and avatars