MAKEUGC PLATFORM API · DOCS V2
Custom Voice & Text to Speech
Clone or design a reusable voice, then turn scripts into audio.
Workflow
- For cloning: prepare an upload, POST the audio to storage, then call clone.
- For design: generate previews, choose one and save its preview_token.
- Poll until voice_id is available, or choose a stock voice from /video/voices.
- Call /speech/generate with that voice_id and a script.
Example IDs and media URLs are placeholders. Replace them with values from your account and accessible media files.
Prepare an audio upload #
/custom-voices/upload
Create an owned upload and obtain presigned multipart POST instructions for a voice sample.
Request body
No request parameters.
Request example
curl --fail-with-body --max-time 120 -X POST "https://app.makeugc.ai/api/platform/custom-voices/upload" \
-H "X-Api-Key: $MAKEUGC_API_KEY" \
-H "Content-Type: application/json" \
--data '{}'
// Run on your server with Node.js 20+.
const apiKey = process.env.MAKEUGC_API_KEY;
if (!apiKey) throw new Error("Set MAKEUGC_API_KEY first");
const response = await fetch("https://app.makeugc.ai/api/platform/custom-voices/upload", {
method: "POST",
headers: {
"X-Api-Key": apiKey,
"Content-Type": "application/json",
},
body: JSON.stringify({}),
signal: AbortSignal.timeout(120000),
});
const text = await response.text();
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${text} (request ${response.headers.get("x-request-id")})`);
}
const result = JSON.parse(text);
console.log(result);
# Install the requests package before running.
import os
import requests
payload = {
}
response = requests.post(
"https://app.makeugc.ai/api/platform/custom-voices/upload",
headers={"X-Api-Key": os.environ["MAKEUGC_API_KEY"]},
json=payload,
timeout=120,
)
if not response.ok:
raise RuntimeError(f"HTTP {response.status_code}: {response.text} "
f"(request {response.headers.get('x-request-id')})")
print(response.json())
200 response example
{
"status": true,
"data": {
"id": "upload_123",
"presigned": {
"url": "https://your-upload-bucket.example",
"fields": {
"key": "uploads/sample.mp3",
"policy": "SIGNED_POLICY"
}
}
}
}
All requests require X-Api-Key. See
errors & retries for unsuccessful
responses.
Clone an uploaded voice #
/custom-voices/clone
Process a sample uploaded through /custom-voices/upload. Save data.id to track voice availability.
Request body
| Parameter | Description |
|---|---|
upload_id
string
Required
|
upload id input.
Allowed: |
voice_name
string
Required
|
voice name input.
Allowed: |
Request example
curl --fail-with-body --max-time 120 -X POST "https://app.makeugc.ai/api/platform/custom-voices/clone" \
-H "X-Api-Key: $MAKEUGC_API_KEY" \
-H "Content-Type: application/json" \
--data '{
"upload_id": "upload_123",
"voice_name": "My brand voice"
}'
// Run on your server with Node.js 20+.
const apiKey = process.env.MAKEUGC_API_KEY;
if (!apiKey) throw new Error("Set MAKEUGC_API_KEY first");
const response = await fetch("https://app.makeugc.ai/api/platform/custom-voices/clone", {
method: "POST",
headers: {
"X-Api-Key": apiKey,
"Content-Type": "application/json",
},
body: JSON.stringify({
"upload_id": "upload_123",
"voice_name": "My brand voice"
}),
signal: AbortSignal.timeout(120000),
});
const text = await response.text();
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${text} (request ${response.headers.get("x-request-id")})`);
}
const result = JSON.parse(text);
console.log(result);
# Install the requests package before running.
import os
import requests
payload = {
"upload_id": "upload_123",
"voice_name": "My brand voice"
}
response = requests.post(
"https://app.makeugc.ai/api/platform/custom-voices/clone",
headers={"X-Api-Key": os.environ["MAKEUGC_API_KEY"]},
json=payload,
timeout=120,
)
if not response.ok:
raise RuntimeError(f"HTTP {response.status_code}: {response.text} "
f"(request {response.headers.get('x-request-id')})")
print(response.json())
200 response example
{
"status": true,
"data": {
"id": "upload_123",
"status": "processing",
"credits_charged": 1
}
}
All requests require X-Api-Key. See
errors & retries for unsuccessful
responses.
Preview a designed voice #
/custom-voices/design
Create voice previews from a description or reference image. Choose a preview before saving it.
Request body
| Parameter | Description |
|---|---|
prompt
string
Optional
|
prompt input.
Allowed: |
image_url
string
Optional
|
Public HTTP(S) media URL. Private addresses, credentials and data URIs are not accepted. |
Request example
curl --fail-with-body --max-time 120 -X POST "https://app.makeugc.ai/api/platform/custom-voices/design" \
-H "X-Api-Key: $MAKEUGC_API_KEY" \
-H "Content-Type: application/json" \
--data '{
"prompt": "Warm, confident adult voice with a natural conversational delivery."
}'
// Run on your server with Node.js 20+.
const apiKey = process.env.MAKEUGC_API_KEY;
if (!apiKey) throw new Error("Set MAKEUGC_API_KEY first");
const response = await fetch("https://app.makeugc.ai/api/platform/custom-voices/design", {
method: "POST",
headers: {
"X-Api-Key": apiKey,
"Content-Type": "application/json",
},
body: JSON.stringify({
"prompt": "Warm, confident adult voice with a natural conversational delivery."
}),
signal: AbortSignal.timeout(120000),
});
const text = await response.text();
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${text} (request ${response.headers.get("x-request-id")})`);
}
const result = JSON.parse(text);
console.log(result);
# Install the requests package before running.
import os
import requests
payload = {
"prompt": "Warm, confident adult voice with a natural conversational delivery."
}
response = requests.post(
"https://app.makeugc.ai/api/platform/custom-voices/design",
headers={"X-Api-Key": os.environ["MAKEUGC_API_KEY"]},
json=payload,
timeout=120,
)
if not response.ok:
raise RuntimeError(f"HTTP {response.status_code}: {response.text} "
f"(request {response.headers.get('x-request-id')})")
print(response.json())
200 response example
{
"status": true,
"data": {
"text": "A short voice preview.",
"previews": [
{
"audio_url": "https://your-cdn.example/voice-preview.mp3",
"preview_token": "SIGNED_PREVIEW_TOKEN"
}
]
}
}
All requests require X-Api-Key. See
errors & retries for unsuccessful
responses.
Save a designed voice #
/custom-voices/save
Save a selected preview as a reusable custom voice.
Request body
| Parameter | Description |
|---|---|
preview_token
string
Required
|
Owner-bound token returned by /custom-voices/design; expires after one hour.
Allowed: |
voice_name
string
Required
|
voice name input.
Allowed: |
Request example
curl --fail-with-body --max-time 120 -X POST "https://app.makeugc.ai/api/platform/custom-voices/save" \
-H "X-Api-Key: $MAKEUGC_API_KEY" \
-H "Content-Type: application/json" \
--data '{
"preview_token": "SIGNED_PREVIEW_TOKEN",
"voice_name": "My designed voice"
}'
// Run on your server with Node.js 20+.
const apiKey = process.env.MAKEUGC_API_KEY;
if (!apiKey) throw new Error("Set MAKEUGC_API_KEY first");
const response = await fetch("https://app.makeugc.ai/api/platform/custom-voices/save", {
method: "POST",
headers: {
"X-Api-Key": apiKey,
"Content-Type": "application/json",
},
body: JSON.stringify({
"preview_token": "SIGNED_PREVIEW_TOKEN",
"voice_name": "My designed voice"
}),
signal: AbortSignal.timeout(120000),
});
const text = await response.text();
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${text} (request ${response.headers.get("x-request-id")})`);
}
const result = JSON.parse(text);
console.log(result);
# Install the requests package before running.
import os
import requests
payload = {
"preview_token": "SIGNED_PREVIEW_TOKEN",
"voice_name": "My designed voice"
}
response = requests.post(
"https://app.makeugc.ai/api/platform/custom-voices/save",
headers={"X-Api-Key": os.environ["MAKEUGC_API_KEY"]},
json=payload,
timeout=120,
)
if not response.ok:
raise RuntimeError(f"HTTP {response.status_code}: {response.text} "
f"(request {response.headers.get('x-request-id')})")
print(response.json())
200 response example
{
"status": true,
"data": {
"id": "design:SIGNED_STATUS_TOKEN",
"voice_id": "voice_123",
"status": "completed",
"credits_charged": 1
}
}
All requests require X-Api-Key. See
errors & retries for unsuccessful
responses.
Get custom voice availability #
/custom-voices/status
Resolve an upload ID or a design status ID to a reusable MakeUGC voice_id.
Parameters
| Parameter | Description |
|---|---|
id
string · query
Required
|
id input.
Allowed: |
Request example
curl --fail-with-body --max-time 120 -X GET "https://app.makeugc.ai/api/platform/custom-voices/status?id=ID" \
-H "X-Api-Key: $MAKEUGC_API_KEY"
// Run on your server with Node.js 20+.
const apiKey = process.env.MAKEUGC_API_KEY;
if (!apiKey) throw new Error("Set MAKEUGC_API_KEY first");
const response = await fetch("https://app.makeugc.ai/api/platform/custom-voices/status?id=ID", {
method: "GET",
headers: {
"X-Api-Key": apiKey,
},
signal: AbortSignal.timeout(120000),
});
const text = await response.text();
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${text} (request ${response.headers.get("x-request-id")})`);
}
const result = JSON.parse(text);
console.log(result);
# Install the requests package before running.
import os
import requests
response = requests.get(
"https://app.makeugc.ai/api/platform/custom-voices/status?id=ID",
headers={"X-Api-Key": os.environ["MAKEUGC_API_KEY"]},
timeout=120,
)
if not response.ok:
raise RuntimeError(f"HTTP {response.status_code}: {response.text} "
f"(request {response.headers.get('x-request-id')})")
print(response.json())
200 response example
{
"status": true,
"data": {
"id": "upload_123",
"status": "completed",
"voice_id": "voice_123"
}
}
All requests require X-Api-Key. See
errors & retries for unsuccessful
responses.
Generate speech audio #
/speech/generate
Synthesize a script with a stock voice or a custom voice owned by your account. Returns an audio URL synchronously.
Request body
| Parameter | Description |
|---|---|
script
string
Required
|
script input.
Allowed: |
voice_id
string
Required
|
MakeUGC voice id from GET /video/voices, not the provider voiceId.
Allowed: |
model
string
Optional
|
model input.
Allowed:
Default: |
settings
object
Optional
|
settings input. |
settings.stability
number
Optional
|
stability input.
Allowed:
Default: |
settings.similarity_boost
number
Optional
|
similarity boost input.
Allowed:
Default: |
settings.style
number
Optional
|
style input.
Allowed:
Default: |
settings.use_speaker_boost
boolean
Optional
|
use speaker boost input.
Default: |
settings.speed
number
Optional
|
speed input.
Allowed:
Default: |
Request example
curl --fail-with-body --max-time 120 -X POST "https://app.makeugc.ai/api/platform/speech/generate" \
-H "X-Api-Key: $MAKEUGC_API_KEY" \
-H "Content-Type: application/json" \
--data '{
"script": "Meet your new everyday coffee companion.",
"voice_id": "voice_123",
"model": "eleven_v4",
"settings": {
"stability": 0.5,
"similarity_boost": 0.75
}
}'
// Run on your server with Node.js 20+.
const apiKey = process.env.MAKEUGC_API_KEY;
if (!apiKey) throw new Error("Set MAKEUGC_API_KEY first");
const response = await fetch("https://app.makeugc.ai/api/platform/speech/generate", {
method: "POST",
headers: {
"X-Api-Key": apiKey,
"Content-Type": "application/json",
},
body: JSON.stringify({
"script": "Meet your new everyday coffee companion.",
"voice_id": "voice_123",
"model": "eleven_v4",
"settings": {
"stability": 0.5,
"similarity_boost": 0.75
}
}),
signal: AbortSignal.timeout(120000),
});
const text = await response.text();
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${text} (request ${response.headers.get("x-request-id")})`);
}
const result = JSON.parse(text);
console.log(result);
# Install the requests package before running.
import os
import requests
payload = {
"script": "Meet your new everyday coffee companion.",
"voice_id": "voice_123",
"model": "eleven_v4",
"settings": {
"stability": 0.5,
"similarity_boost": 0.75
}
}
response = requests.post(
"https://app.makeugc.ai/api/platform/speech/generate",
headers={"X-Api-Key": os.environ["MAKEUGC_API_KEY"]},
json=payload,
timeout=120,
)
if not response.ok:
raise RuntimeError(f"HTTP {response.status_code}: {response.text} "
f"(request {response.headers.get('x-request-id')})")
print(response.json())
200 response example
{
"status": true,
"data": {
"audio_url": "https://your-cdn.example/speech.mp3",
"voice_id": "voice_123"
}
}
All requests require X-Api-Key. See
errors & retries for unsuccessful
responses.