Desktop API
Runs inside the desktop app on your own computer at 127.0.0.1:8100, with no API key. Also covers subtitles, clips and audiobooks.
OpenAPI spec · Base URL http://127.0.0.1:8100
HTTP API for voice cloning, voice design, text-to-speech, transcription, audiobooks, dubbing, clips and AI Cut.
Base URL
The API runs on your computer at http://127.0.0.1:8100. Change the port in Settings or start the app with --api-port. Every route starts with /api/v1/, except the OpenAI-compatible POST /v1/audio/speech. Requests to an unknown path return the app's HTML page, not a 404.
Authentication
No key is needed unless you set one in Settings or start the app with --api-key. Once set, send it as X-API-Key: <key>, Authorization: Bearer <key> or ?api_key=<key>. GET /api/v1/health and GET /api/v1/system/version never need a key.
Quick Start Workflow
- Check health:
GET /api/v1/health - Pick a model:
GET /api/v1/modelslists the models and what each supports - Generate speech using one of:
POST /api/v1/tts/generateto use a built-in speaker voicePOST /api/v1/generation/cloneto clone a voice from reference audio or a saved voicePOST /api/v1/generation/designto create a voice from a text descriptionPOST /api/v1/conversion/convertto convert existing speech to another voice
- Get audio: Pass
?sync=trueto get audio in the response, or pollGET /api/v1/generation/progressthenGET /api/v1/generation/result
The requested model loads automatically, so the first request after a model switch takes longer. POST /api/v1/model/load loads one ahead of time.
Sync vs Async
All generation and transcription endpoints accept ?sync=true. In sync mode, the request blocks until completion and returns the result directly. Generation has a hard 600s cap; transcription uses a 300s inactivity timeout (resets while progress events are flowing) so long audio can finish even if it takes longer than 5 minutes wall-clock. In async mode (default), the request returns immediately and you poll for progress/results.
Streaming
For real-time audio streaming, use the /stream variants (e.g. POST /api/v1/generation/clone/stream). These return a session_id. Connect to GET /api/v1/streaming/{session_id}/audio to receive a chunked WAV stream as audio is generated. Call POST /api/v1/streaming/{session_id}/finalize when done to collect the complete audio as base64.
Audio Format
All audio input/output uses base64-encoded WAV unless otherwise noted. The streaming audio endpoint returns raw WAV (PCM 16-bit mono). The output audio format can be changed via PUT /api/v1/settings/audio-format.
Models
Multiple TTS models are available, each with different capabilities.
Query GET /api/v1/models to list all models, or GET /api/v1/models/active
for the current model's capabilities.
Models differ in:
- Supported modes: clone, design, and/or TTS (built-in speakers)
- Languages: varies by model and variant
- Quality tiers: each model has its own set of variants
- Generation parameters: model-specific tuning knobs (temperature, exaggeration, etc.)
Pass model_family on generation requests to target a specific model, or omit it
to use the currently configured model.
Validation
All requests are validated against the target model's capabilities. Invalid languages, quality tiers, or generation parameters return a 400 error listing the valid options.
Agents
POST /api/v1/speak speaks text out loud in a saved voice. POST /v1/audio/speech accepts OpenAI text-to-speech requests, so OpenAI clients work by pointing their base URL at this server. An MCP server for AI agents runs at /mcp.
Live avatars
Connect a WebSocket to /api/v1/talking-head/live (pass the key as ?api_key= when one is set) to get a talking face back in real time. Send JSON messages and audio, and receive video frames with their audio.
- Start:
{"type": "start", "avatar_id": "av_..."}, or"stock_id", or"image_base64". Optional:"model"(litedefault, orpro),"size"(512, or 1024 withpro),"idle"(loopdefault,liveornone),"pace"(realtimedefault, orfastto get frames as quickly as they render),"framing"(facedefault for a square close-up, orphotofor the whole photo with the face blended back in, up to 1280 px on its long side;readygiveswidthandheight) and"voice","language","tts_model"and"tts_quality"(a quality tier such ashigher_qualityorfaster, the app setting if left out) as defaults forsay. The voice model loads during start so the firstsayis quick. Send"warm_tts": falseif you only send your own audio. The server answers withloadingmessages while models download and load, thenready. - Speak:
{"type": "say", "id": "m1", "text": "...", "voice": "Morgan", "language": "English"}speaks in a saved voice.tts_modelandtts_qualitycan also be set persay. Or send your own speech:{"type": "audio_begin", "id": "a1", "sample_rate": 24000}, then binary messages of 16-bit mono PCM, then{"type": "audio_end"}. - Receive: binary frames, plus
startedanddonemessages for eachid. Each frame is a 20-byte little-endian header (kindu8 with 1 for speech and 2 for idle,id_lengthu8, reserved u16,epochu32,indexu32,audio_offsetu32,jpeg_lengthu32), then the id, then a JPEG, then 40 ms of 16-bit mono PCM at thesample_ratefromready. Idle frames carry no audio. - Control:
{"type": "interrupt"}stops the current speech and drops queued speech,{"type": "clear"}drops only the queue, and{"type": "played", "samples": N, "epoch": E}reports how many speech samples you have played in the current epoch. Withrealtimepace the server stays about one second ahead of what you report, or of the clock if you never report.
After an interrupt the server sends interrupted with a new epoch. Drop any frames with an older epoch. One live session runs at a time.
Endpoints
Health
System
Setup
Settings
- Get output audio format GET
- Set output audio format PUT
- Get emotional clone engine GET
- Set emotional clone engine PUT
- Get TTS model quality GET
- Set TTS model quality PUT
- Get generation mode GET
- Set generation mode PUT
- Get a UI preference GET
- Set a UI preference PUT
- Get low VRAM mode GET
- Set low VRAM mode PUT
- Get ROCm flash attention GET
- Set ROCm flash attention PUT
- Get HuggingFace endpoint mode GET
- Set HuggingFace endpoint mode PUT
- Get UI language GET
- Set UI language PUT
- Get ASR models GET
- Set ASR model PUT
- Get speaker detection engines GET
- Set speaker detection engine PUT
- Get mic PTT shortcut GET
- Set mic PTT shortcut PUT
- Get HTTP API settings GET
- Enable/disable HTTP API PUT
- Set HTTP API port PUT
- Get MCP agent-voice settings GET
- Set default agent voice PUT
- Set or clear the API key PUT
- Set default agent model PUT
Model
Generation
Clone
Design
TTS
Transcription
Streaming
Voices
History
Cache
GPU Install
Conversion
Audio
Translation
YouTube
Audiobook
- List all audiobook projects GET
- Create a new audiobook project POST
- Detect speakers in pasted script text POST
- Get an audiobook project GET
- Delete an audiobook project DELETE
- Library voices this project designed GET
- Rename an audiobook project PUT
- Lightweight live-batch progress (counts + currently-generating segment) GET
- Stitch/encode progress for the ongoing combine or export GET
- OCR ingestion progress GET
- Cancel an in-progress OCR ingestion POST
- Would a Preview / Export actually do work? GET
- Signal an in-flight combine/export to stop POST
- Clear the persisted batch_in_progress flag POST
- Get the project's cover image (custom overrides EPUB-derived) GET
- Upload a custom cover image POST
- Batch generate audio for segments POST
- Cancel an in-flight generate_batch POST
- Reset segments stuck in 'generating' status POST
- Combine all segment audio into a single file POST
- Get the combined audiobook file (rebuilds if stale) GET
- Get segment boundaries within the combined audiobook GET
- Resolve combined audio URL + boundaries in one call (rebuilds if stale) GET
- Export the audiobook project POST
- Download the previously-exported audiobook file GET
- Update project settings PUT
- Re-parse source file with current settings (destructive) POST
- Sanitize every segment's text in a project POST
- Invalidate all generated audio in a project (archives to history) POST
- Reset audio for a specific list of segments POST
- Append a new segment to a project POST
- Delete a segment DELETE
- Update a segment PUT
- Reorder a segment within its scope POST
- Split a segment at offset POST
- Merge two adjacent segments POST
- Delete multiple segments at once POST
- Merge N adjacent segments into one POST
- Regenerate audio for a single voice_span POST
- Generate audio for a segment POST
- Get segment audio file GET
- Get generation history for a segment GET
- Promote a historical generation to current POST
- Get a single take's audio file (no-suffix alias) GET
- Rename a take (set or clear its custom display name) PATCH
- Delete a historical generation DELETE
- Get a single take's audio file GET
- Upload a WAV file as a new take in segment history POST
- Sanitize a single segment's text POST
- List lexicon entries GET
- Add a lexicon entry POST
- Delete a lexicon entry DELETE
- Update a lexicon entry PUT
- Import lexicon entries from elsewhere POST
- Get lexicon staleness for generated segments GET
- Find first sentence containing a phrase GET
- Add a voice to a project POST
- Remove a voice from a project DELETE
- Update a project voice PUT
- Set the default voice for a project PUT
- Create a section POST
- Delete a section (optionally with its segments) DELETE
- Rename a section PUT
- Get the audiobook LLM config (api_key masked) GET
- Set the audiobook LLM config PUT
- Set the model used for speaker detection PUT
- List available models for the configured LLM provider GET
- Estimate tokens and cost for speaker detection GET
- Start speaker detection for a project POST
- Poll speaker detection progress GET
- Cancel the running speaker detection or dramatization POST
- Cancel this project's running speaker detection POST
- Identify speakers and emotions for one segment POST
- Design and assign a voice for every uncast character POST
- Poll voice design progress GET
- Cancel the running voice design POST
- Start rewriting a project as a dramatized script POST
- Poll dramatization progress GET
Dubbing
- List dubbing projects GET
- Create a dubbing project POST
- Languages a dub can translate into GET
- Get a dubbing project GET
- Delete a dubbing project DELETE
- Assign a voice to a speaker PUT
- Rename a speaker PUT
- Add a speaker POST
- Remove a speaker, reassigning their segments POST
- Delete a segment DELETE
- Update a segment PUT
- Run the auto-dub pipeline POST
- Stop a running dub POST
- Save the subtitle style PUT
- Save the glossary PUT
- Save the export format PUT
- Export the dubbed video POST
- Run lip sync on a finished dub POST
- Regenerate one segment POST
- Mark a segment's source text as edited since translation POST
- Clear a segment's source-edited mark DELETE
- Rename a dubbing project PUT
- Create a dubbing project from a YouTube URL POST
- Stream a project's video, segment clip, or speaker reference GET
- Playable URL for the dubbed video GET
- URL for the dubbed audio track GET
- Playable URL for the lip-synced video GET
- Playable URL for the source video GET
- Playable URL for a segment's clip GET
- Playable URL for a speaker's clone reference GET
- Merge a segment with the next one POST
- Split a segment before a word POST
- Replace a speaker's trimmed clone reference POST
- Use one of the speaker's segments as the clone reference POST
- Dubbing Auto Tag Words POST
- Dubbing List Custom Fonts GET
- Dubbing Delete Custom Font DELETE
Clips
- List clips projects GET
- Create a clips project POST
- Create a clips project from a YouTube link POST
- Start an async YouTube import POST
- Read a YouTube link's title, thumbnail and available heights POST
- Poll YouTube import progress GET
- Get a clips project GET
- Delete a clips project DELETE
- Get a playable URL for the source video GET
- Resolve the source video's path on disk GET
- Get a playable URL for a rendered clip GET
- Get a playable URL for the raw reframed clip GET
- Resolve the reframed clip path for a dubbing handoff GET
- Download a rendered clip, optionally re-encoded POST
- Update clips project settings PUT
- Delete a clip DELETE
- Run the clips pipeline POST
- Discard clips and return to setup POST
- Poll clips job progress GET
- Cancel a running clips job POST
- Rerender one clip POST
- Apply the current style to all done clips POST
- Get the clips LLM config (api_key masked) GET
- Set the clips LLM config PUT
- Set the model used by the clips feature PUT
- List available models for the configured LLM provider GET
AI Cut
- List AI Cut projects GET
- Create an AI Cut project POST
- Get an AI Cut project and its analysis GET
- Update name, settings, script or overrides PATCH
- Delete an AI Cut project DELETE
- Start analysis POST
- Render the cut list to MP4 POST
- Re-voice selected words POST
- Playable URL for an overdub GET
- Cancel the running op POST
- Progress of the running op GET
- Playable URL for the source video GET
- Playable URL for the last render GET
- How the last render framed the video GET
- Get the AI Cut LLM config (api_key masked) GET
- Set the AI Cut LLM config PUT
- Set the model used by AI Cut PUT
- List models for the AI Cut LLM GET
Subtitles
Images
Agent
Avatars
- Whether this machine can make avatar videos GET
- Video models and whether this machine can run them GET
- List avatar videos GET
- Start an avatar video POST
- Create an empty avatar project POST
- Check that a photo shows one clear face POST
- Update the setup of an avatar project that has not started PATCH
- Delete an avatar video DELETE
- Rename an avatar project PUT
- Start generating an avatar project from its saved setup POST
- Make a finished avatar video again with the same setup and a new seed POST
- Progress of an avatar video GET
- Cancel an avatar video POST
- Playable URL for an avatar video file GET
- Save caption style for an avatar video PUT
- Time the words of an avatar video for its subtitles POST
- Save the effects timeline for an avatar video PUT
- Save the start and end an avatar video exports with PUT
- Save the hook text card for an avatar video PUT
- Save the caption word edits for an avatar video PUT
- Start exporting an avatar video, with captions when they are on POST
- What would stop an upscaled export from using the sharpest upscale POST
- Progress of an avatar export GET
- Stop an avatar export POST
- Download a finished avatar export GET