Developer API · v1
Automate Creator Voice Studio from your own apps
The desktop app runs a REST API on your computer. Use it to list voices, queue voiceover renders, and download the audio — from scripts, pipelines, or applications running on the same machine.
The basics
| Base URL | http://127.0.0.1:8765/api/v1 |
|---|---|
| Availability | Creator Voice Studio must be running (it starts the engine automatically). The API accepts connections from your computer only — it is never exposed to the network. |
| Authentication | Send your API key in the X-API-Key header (or as a Bearer token). Find and copy it in the app under Settings → Developer API. |
| Format | JSON in, JSON out. Audio downloads are WAV (24 kHz). |
| Interactive docs | With the app running, open http://127.0.0.1:8765/docs for a live OpenAPI explorer. |
Endpoints
| Method & path | What it does |
|---|---|
GET /health | Liveness check (no auth). Returns service info and the current processing mode. |
GET /voices | Lists your voice profiles: id, name, language, gender. |
POST /speech | Queues a render. Body: voice_id, text (up to 20,000 chars), optional title, delivery, speed_mode, silence_ms. Returns a job_id. |
GET /jobs/{job_id} | Job status: queued → running → complete (or failed). Includes progress (0–100) and, when complete, duration and the audio URL. |
GET /jobs/{job_id}/audio | Downloads the finished WAV file. Returns 409 while the job is still running. |
POST /jobs/{job_id}/cancel | Cancels a queued or running job after the current render step. |
Delivery presets are the same ones as in the app — e.g. "Neutral narration", "Cinematic storyteller" (default), "YouTube explainer", "Calm audiobook", "True crime". GET /health returns the full current list; unknown values fall back to the default. Renders queue one at a time; poll the job until it completes.
Quick start (curl)
# 1. Find a voice
curl http://127.0.0.1:8765/api/v1/voices -H "X-API-Key: $CVS_API_KEY"
# 2. Queue a render
curl -X POST http://127.0.0.1:8765/api/v1/speech \
-H "X-API-Key: $CVS_API_KEY" -H "Content-Type: application/json" \
-d '{"voice_id":"VOICE_ID","text":"Hello from the API.","title":"My first render"}'
# → {"job_id":"abc123","status":"queued","poll":"/api/v1/jobs/abc123"}
# 3. Poll until complete
curl http://127.0.0.1:8765/api/v1/jobs/abc123 -H "X-API-Key: $CVS_API_KEY"
# → {"status":"complete","progress":100,"filename":"my-first-render.wav", ...}
# 4. Download the audio
curl -o voiceover.wav http://127.0.0.1:8765/api/v1/jobs/abc123/audio \
-H "X-API-Key: $CVS_API_KEY"Python example
import time, requests
BASE = "http://127.0.0.1:8765/api/v1"
HEADERS = {"X-API-Key": "YOUR_API_KEY"} # Settings → Developer API
voice = requests.get(f"{BASE}/voices", headers=HEADERS).json()[0]
job = requests.post(f"{BASE}/speech", headers=HEADERS, json={
"voice_id": voice["id"],
"text": "Chapter one. The signal came at midnight.",
"delivery": "Cinematic storyteller",
}).json()
while True:
status = requests.get(f"{BASE}/jobs/{job['job_id']}", headers=HEADERS).json()
if status["status"] in ("complete", "failed", "canceled"):
break
time.sleep(2)
if status["status"] == "complete":
audio = requests.get(f"{BASE}/jobs/{job['job_id']}/audio", headers=HEADERS)
open("chapter-1.wav", "wb").write(audio.content)Node.js example
const BASE = 'http://127.0.0.1:8765/api/v1';
const HEADERS = { 'X-API-Key': process.env.CVS_API_KEY, 'Content-Type': 'application/json' };
const [voice] = await (await fetch(`${BASE}/voices`, { headers: HEADERS })).json();
const job = await (await fetch(`${BASE}/speech`, {
method: 'POST',
headers: HEADERS,
body: JSON.stringify({ voice_id: voice.id, text: 'Hello from Node.' })
})).json();
let status;
do {
await new Promise((r) => setTimeout(r, 2000));
status = await (await fetch(`${BASE}/jobs/${job.job_id}`, { headers: HEADERS })).json();
} while (!['complete', 'failed', 'canceled'].includes(status.status));
if (status.status === 'complete') {
const audio = await fetch(`${BASE}/jobs/${job.job_id}/audio`, { headers: HEADERS });
const fs = await import('node:fs');
fs.writeFileSync('voiceover.wav', Buffer.from(await audio.arrayBuffer()));
}Errors
| Status | Meaning |
|---|---|
401 | Invalid or missing API key. Copy it from Settings → Developer API (regenerating the key invalidates the old one). |
404 | Unknown voice_id or job_id. |
409 | Audio requested before the job finished — keep polling the job endpoint. |
422 | Invalid request body (e.g. text too long, unknown field values). |
| Connection refused | The app is not running, or the engine is still starting. Open Creator Voice Studio and wait for "Ready". |
Good to know
- Local means local: the API binds to 127.0.0.1 and is intended for software running on the same computer as the app.
- Renders are processed one at a time in a queue — submit many jobs and poll each; long texts are chunked automatically.
- All API renders carry the same inaudible watermark as in-app renders, and appear in the app's Audio Assets.
- The consent rule applies to API usage too: only generate with voices you own or have written permission to use.
Need the app first?
The API ships with every copy of Creator Voice Studio — no extra tier, no metering.
Download Creator Voice Studio