Skip to content

VoiceLab API ​

Generate text and speech, transcribe or clean up audio, clone your voice, and stream realtime audio.

Keep your API key on your server. Product endpoints use API keys; account management uses a signed-in user's JWT.

Latest STT update ​

October 9, 2026: STT now accepts 33 languages, including Chinese and Azerbaijani, plus language=auto for automatic detection in uploaded recordings and realtime requests. See the language codes, timing behavior, and availability notes. Existing API routes and request formats are unchanged.

Base URL ​

text
https://api.voicelab.uz

The public developer API uses the /v1 prefix. For example:

text
POST https://api.voicelab.uz/v1/tts

Choose the right credential ​

CredentialUsed forExample
User access JWTVoiceLab website and API-key managementAuthorization: Bearer eyJ...
Developer API keyYour application calling LLM, TTS, STT, Voice Isolator, Meeting AI, voices, and realtime ticket endpointsAuthorization: Bearer vlk_...
Realtime ticketOne short-lived WebSocket connection?ticket=eyJ...

Do not send a user JWT to /v1/tts, /v1/stt, or /v1/voices. Do not send a long-lived API key in a WebSocket URL. The only value allowed in that URL is a short-lived ticket returned by POST /v1/ticket.

Voice Isolator developer requests use an API key at /v1/voice-isolations. The dashboard routes at /api/v1/voice-isolations require a user JWT.

Meeting AI developer requests use a personal workspace API key at /v1/meetings. The dashboard routes at /api/v1/meetings require a user JWT.

Endpoints ​

Create and manage keys with the signed-in dashboard:

MethodEndpointCredential
GET/api/v1/account/api-key-permissionsUser JWT
GET/api/v1/account/api-key-scopesUser JWT
POST/api/v1/account/api-keysUser JWT
GET/api/v1/account/api-keysUser JWT
PATCH/api/v1/account/api-keys/{key_id}User JWT
POST/api/v1/account/api-keys/{key_id}/revokeUser JWT
DELETE/api/v1/account/api-keys/{key_id}User JWT

Use the generated key for application services:

FeatureEndpointsPermission
LLM modelsGET /v1/modelsllm:read
Chat completionPOST /v1/chat/completionsllm:write
LLM request statusGET /v1/llm/requests/{id}llm:read
LLM filesPOST, GET /v1/files, GET, DELETE /v1/files/{file_id}llm:read for reads, llm:write for upload/delete
TTS capabilitiesGET /v1/tts/languagesTTS read
VoicesGET /v1/voices?language={code}Voices read
Clone discovery/stateGET /v1/voice-enrollments/capabilities, GET /v1/voice-enrollments/{id}voices:read
Verified voice enrollmentPOST /v1/voice-enrollments, then /{id}/transcript, /{id}/challenge, /{id}/verifyvoices:write
Clone metadataGET /v1/voices/{id}voices:read
Edit/delete own clonePATCH /v1/voices/{id}, DELETE /v1/voices/{id}voices:write
TTS generationPOST /v1/ttsTTS write
Background TTSPOST /v1/tts/asyncTTS write; TTS read for polling
TTS historyGET /v1/tts/generations, GET /v1/tts/generations/{id}TTS read
Delete TTS audioDELETE /v1/tts/generations/{id}TTS write
STT transcriptionPOST /v1/sttSTT write
STT credit preflightGET /v1/stt/preflightSTT write
STT history and filesGET /v1/stt/transcriptions...STT read
Edit or delete STTPATCH, PUT, DELETE /v1/stt/transcriptions/{id}STT write
Voice isolationPOST /v1/voice-isolations, POST /v1/voice-isolations/batchaudio_isolation:write
Isolation history and resultsGET /v1/voice-isolations, GET /v1/voice-isolations/{id}audio_isolation:read
Hide isolationDELETE /v1/voice-isolations/{id}audio_isolation:write
Create isolation exportPOST /v1/voice-isolations/{id}/exportsaudio_isolation:write
Get isolation exportGET /v1/voice-isolations/{id}/exports/{format}audio_isolation:read
Meeting AI capabilitiesGET /v1/meetings/capabilitiesmeetings:read
Create meetingPOST /v1/meetingsmeetings:write
Meeting history and resultsGET /v1/meetings, GET /v1/meetings/{id}meetings:read
Rename or delete meetingPATCH, DELETE /v1/meetings/{id}meetings:write
Regenerate meeting notesPOST /v1/meetings/{id}/notes/generationsmeetings:write
Realtime TTSPOST /v1/ticket, then GET /v1/tts/streamTTS realtime
Realtime STTPOST /v1/ticket, then GET /v1/stt/streamSTT realtime
Webhooks and deliveries/v1/webhooks...; see complete referencewebhooks:write, including reads

Grant Voice Isolator → Access for the complete upload, polling, and export workflow. This enables both isolation scopes. Existing restricted keys need this permission added explicitly. See Voice Isolator.

Grant Meeting AI → Access to upload recordings, poll results, and manage meetings. This enables both meeting scopes. Only personal workspace keys can use Meeting AI. See Meeting AI.

Grant llm: access for model discovery, completions, and request status. Developer LLM requests use API keys and token-based credits. Ask's /api/v1/llm/* and /api/v1/chats/* routes remain JWT-only and uncharged. See LLM API.

Grant Voices → Access for the verified Voice Cloning workflow and owner-only editing/deletion. All active paid plans qualify; consent, a fresh live recording and both verification checks are required.

Analytics and request logs are dashboard views. They use a user JWT and show only traffic authenticated with developer API keys; website JWT traffic is not included. See Analytics and logs.

Quick start ​

1. Create an API key ​

Use a user access JWT from the VoiceLab dashboard to create a key. The secret is returned only in this response.

bash
curl -X POST 'https://api.voicelab.uz/api/v1/account/api-keys' \
  -H 'Authorization: Bearer USER_ACCESS_JWT' \
  -H 'Content-Type: application/json' \
  -d '{
    "name": "My production integration",
    "permissions": {
      "text_to_speech": "access",
      "speech_to_text": "access",
      "voices": "read"
    },
    "expires_at": null,
    "restrict_key": true,
    "auto_disable_if_leaked": true
  }'

Save data.secret immediately. It cannot be recovered later.

2. Store the key on your server ​

bash
export VOICELAB_API_KEY='vlk_replace_with_the_secret_from_creation'

For production, use your deployment secret manager instead of a shell file.

3. Generate speech ​

bash
tts_http_status=$(curl -fS -w '%{http_code}' 'https://api.voicelab.uz/v1/tts' \
  -H "Authorization: Bearer $VOICELAB_API_KEY" \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: hello-world-001' \
  -d '{
    "text": "Hello from VoiceLab.",
    "language": "en",
    "voice_id": "voice_01J9NEUTRAL0000000000000001",
    "speed": 1
  }' \
  -o tts-response)
case "$tts_http_status" in
  200) mv tts-response hello.wav ;;
  202) cat tts-response ;; # Poll the returned status_url before downloading audio
  *) cat tts-response >&2; exit 1 ;;
esac

Output is mono 24 kHz WAV. Fetch available models and languages from /v1/tts/languages. If generation is pending, the response is 202 JSON instead of audio. See TTS polling.

4. Transcribe audio ​

bash
curl -fS 'https://api.voicelab.uz/v1/stt' \
  -H "Authorization: Bearer $VOICELAB_API_KEY" \
  -H 'Idempotency-Key: 550e8400-e29b-41d4-a716-446655440000' \
  -F 'audio=@meeting.wav;type=audio/wav' \
  -F 'language=en' \
  -F 'include_speakers=false'

See Speech to Text for upload limits and polling.

Common response rules ​

  • JSON responses use Content-Type: application/json.
  • Resource timestamps are RFC 3339 UTC strings, for example 2026-08-16T12:30:00Z. LLM completion created and file created_at/expires_at use Unix seconds; model created is 0.
  • IDs, cursors, tickets, and URLs are opaque. Do not parse or construct them.
  • Standard resource responses include request_id. LLM success bodies use their own shapes; completion headers include X-LLM-Request-ID. LLM streaming uses SSE. See LLM response formats.
  • TTS returns WAV audio or pending-job JSON. STT exports return files. Voice Isolator returns JSON with signed download URLs.
  • Private audio URLs are short-lived signed URLs. Do not store them as permanent links.

Error response ​

Standard JSON errors use this shape:

json
{
  "message": "This API key is not allowed to perform this operation.",
  "error": {
    "code": "insufficient_scope"
  },
  "request_id": "req_01J..."
}

LLM handler errors put the message in error.message and include error.type. Shared authentication errors can still use the standard shape shown above. Handle both envelopes when integrating LLM endpoints.

Some validation errors also contain error.fields:

json
{
  "message": "Check the highlighted fields.",
  "error": {
    "code": "validation_error",
    "fields": {
      "language": "Choose a supported language."
    }
  },
  "request_id": "req_01J..."
}

Always log request_id in your application. Never log an API key, realtime ticket, audio bytes, or signed audio URL.

Documents ​