defineVoice configuration accepts, serve the curated list of text-to-speech voices for phone channels, synthesize a short preview of a voice, read text aloud as MP3, and transcribe an uploaded audio file. None of them is used by the CLI. The voice agents those models configure, their versions, outbound calls, and browser voice sessions are on Voice.
Verified against lua-cli 3.33.0.
Base URL and authentication
Every route sits underhttps://api.heylua.ai/developer and takes Authorization: Bearer <<YOUR_API_KEY>>. The preview and agent-scoped speak routes check telephony:write on the agent in the path; the catalog, voice list, transcription, and deprecated speak routes need only an authenticated key. Keys, scopes, and the error envelope are on the REST API overview.
Endpoints
GET /developer/voice-catalog
Returns the models and voices a voice configuration accepts: voice modes, TTS provider catalogs with live voice lists, realtime engines, and the hosted LLM and STT lists. Any authenticated key; cached for 60 seconds. Responseobject[]
Each
{ id: "livekit-lua-agent" | "livekit-inference" | "realtime", label, tagline, description, icon, badge?, persisted: { mode, llmSource? } }.object[]
Each
{ id: "elevenlabs" | "cartesia" | "deepgram-aura" | "livekit-inference", label, tagline, available, error?, models: [{ id, label, tagline, latencyMs?, status }], voices: [{ id, name, provider, gender?, accent?, language?, category?, previewUrl?, enginePrefix?, iconKey?, voiceBakedInModel? }] }. available is false when the provider’s key is missing or its last fetch failed with no cached fallback; error says why, and can also accompany available: true when live discovery failed and the curated list is served. gender is male, female, or neutral.object[]
Each
{ id, provider: "gemini" | "openai", label, tagline, status }; status is ga, preview, or alpha.object[]
Each
{ id, provider: "openai" | "google" | "xai" | "deepseek" | "kimi", label, tagline, tier: "fast" | "balanced" | "quality" }; id is the model code to send, for example openai/gpt-5-mini.object[]
Each
{ id, label, tagline, supportedLanguages? }; id for example deepgram/nova-3. An absent supportedLanguages means every language.object
Inline SVG strings keyed by
iconKey; absent when there are no hosted voices.string
ISO timestamp of the response.
GET /developer/voices
Returns the curated list of text-to-speech voices for phone channels. Any authenticated key. Response200 with { voices: [{ id, name, gender: "male" | "female", accent, category, previewUrl? }], count }.
POST /developer/voices/:agentId/preview
Synthesizes a short sample of a voice and returns it inline. Scopetelephony:write on the agent; previews count against vendor-spend limits.
string
required
An ElevenLabs voice ID, for example one from
GET /developer/voices; other catalog providers are not supported here. Sent in the body because IDs can contain /.string
Text to speak; at most 500 characters. Defaults to a greeting.
201 with { audioUrl, format: "mp3" }, where audioUrl is a data:audio/mpeg;base64,… URL.
POST /developer/voices/:agentId/speak
Reads text aloud and returns the audio. Scopetelephony:write on the agent.
string
required
At most 5,000 characters.
string
Voice to use. Defaults to a server voice.
200 with the MP3 bytes, Content-Type: audio/mpeg, and Content-Length.
POST /developer/voices/:agentId/speak/stream
Same request asspeak, but chunked so playback can start before synthesis finishes. It uses a lower-latency model, so the audio differs subtly from speak; once the first byte is sent, a failure ends the stream rather than changing the status.
POST /developer/voices/speak
Deprecated alias ofspeak without the agent in the path. Any authenticated key. Use POST /developer/voices/:agentId/speak.
POST /developer/voices/transcribe
Transcribes an audio file. Any authenticated key; counts against vendor-spend limits. Sendmultipart/form-data.
file
required
The audio file. Uploads over 64 MB are rejected; the server may configure a lower limit.
string
Language hint.
string
true for a stereo recording with the microphone on the left channel and system audio on the right; the transcript is then labeled You: and Others:. Non-stereo audio falls through to the plain path.string
1 or true to include word-level timings.201 with { text, languageCode, words? }: the transcript, the detected BCP-47 language code, and, with timestamps, words as { w, s, e } entries with start and end seconds.
Errors
Example
Read a sentence aloud with the server’s default voice and keep the MP3 bytes. No CLI command calls this route, so there is no CLI tab.See also
- Voice — voice agents, versions, dispatch, and browser voice sessions
- Voice calls — the phone channel these voices answer on
- About voice — voice definitions, phone numbers, and live voice sessions
lua voice— try a voice from the terminal, browser, or phonelua channels— bind a number to the voice that answers

