Voice Clone (MiniMax)
curl --request POST \
--url https://kymaapi.com/v1/audio/voice-clone \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"name": "<string>",
"model": "<string>"
}
'import requests
url = "https://kymaapi.com/v1/audio/voice-clone"
payload = {
"name": "<string>",
"model": "<string>"
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({name: '<string>', model: '<string>'})
};
fetch('https://kymaapi.com/v1/audio/voice-clone', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://kymaapi.com/v1/audio/voice-clone",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'name' => '<string>',
'model' => '<string>'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://kymaapi.com/v1/audio/voice-clone"
payload := strings.NewReader("{\n \"name\": \"<string>\",\n \"model\": \"<string>\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://kymaapi.com/v1/audio/voice-clone")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"name\": \"<string>\",\n \"model\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://kymaapi.com/v1/audio/voice-clone")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"name\": \"<string>\",\n \"model\": \"<string>\"\n}"
response = http.request(request)
puts response.read_bodyVoice Clone (MiniMax)
Clone a voice from a 10-second to 5-minute reference recording. Returns a voice_id usable in /v1/audio/speech with any MiniMax HD or Turbo SKU.
POST
/
v1
/
audio
/
voice-clone
Voice Clone (MiniMax)
curl --request POST \
--url https://kymaapi.com/v1/audio/voice-clone \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"name": "<string>",
"model": "<string>"
}
'import requests
url = "https://kymaapi.com/v1/audio/voice-clone"
payload = {
"name": "<string>",
"model": "<string>"
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({name: '<string>', model: '<string>'})
};
fetch('https://kymaapi.com/v1/audio/voice-clone', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://kymaapi.com/v1/audio/voice-clone",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'name' => '<string>',
'model' => '<string>'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://kymaapi.com/v1/audio/voice-clone"
payload := strings.NewReader("{\n \"name\": \"<string>\",\n \"model\": \"<string>\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://kymaapi.com/v1/audio/voice-clone")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"name\": \"<string>\",\n \"model\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://kymaapi.com/v1/audio/voice-clone")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"name\": \"<string>\",\n \"model\": \"<string>\"\n}"
response = http.request(request)
puts response.read_bodyVoice cloning is paused. As of 2026-09-12 no voice-clone model is being served — no customer jobs in the preceding 30 days. The endpoint still exists; a request returns
404 model_not_found. Nothing was deleted. The live TTS voices on /v1/audio/voices are unaffected. This page is no longer in the docs navigation; it records how the endpoint behaves.voice_id you can pass to /v1/audio/speech on any MiniMax voice model.
curl -X POST https://kymaapi.com/v1/audio/voice-clone \
-H "Authorization: Bearer $KYMA_API_KEY" \
-F file=@reference.mp3 \
-F name="brand-narrator"
Request
multipart/form-data body.
file
required
Reference audio. MP3, WAV, or M4A. Max 10 MB. Duration must be 10 seconds to 5 minutes. Kyma does not check the length itself: the voice model rejects an out-of-range clip, and that error comes back to you uncharged. Longer clips don’t improve clone quality and waste upload bandwidth.
string
Optional human-readable label, max 64 chars. Surfaced in the response and stored alongside the ownership row for your reference.
string
default:"minimax-voice-clone"
Voice clone SKU. Currently only
minimax-voice-clone is supported.Response
200 OK JSON.
{
"voice_id": "kyma_3f8e2a1b4c9d7e60",
"name": "brand-narrator",
"model": "minimax-voice-clone",
"cost_usd": 2.00,
"balance_usd": 48.00
}
| Field | What |
|---|---|
voice_id | Use this in /v1/audio/speech voice_id field. Namespaced as kyma_<rand>. |
name | Echo of the label you sent (or null). |
cost_usd | Flat charge applied ($2.00). |
balance_usd | Remaining balance after settle. |
X-Kyma-Model, X-Kyma-Cost-USD, and X-Kyma-Balance-USD headers are also set.
Pricing
Flat $2.00 per cloned voice. One-time charge — once cloned, thevoice_id is reusable in unlimited TTS calls.
Ownership
Cloned voice IDs are gated per Kyma user. If user A passes user B’svoice_id to /v1/audio/speech, the request returns 403 voice_not_owned. Voice IDs that aren’t on file are assumed to be MiniMax system voices (browseable by everyone).
Errors
| Status | error.code | When |
|---|---|---|
400 | not_a_voice_clone_model | model is not a clone SKU |
400 | invalid_request | missing file, invalid form data |
402 | insufficient_credits | balance below $2.00 |
413 | invalid_request | audio file > 10 MB |
415 | unsupported_audio_type | audio format not MP3/WAV/M4A |
500 | ownership_write_failed | clone succeeded but ownership row insert failed (no charge applied; safe to retry) |
502 | provider_error | upstream MiniMax failure |
See also
POST /v1/audio/voice-design— generate a voice from a written description (no reference audio)POST /v1/audio/speech— use the cloned voice