API Reference
Base URL https://api.vocallab.ai. Every request needs Authorization: Bearer vl_live_... (see API Keys).
GET /api/v1/ping
Connection + auth test. Returns your points balance.
{ "ok": true, "points": 12345, "unit": "points (1 pt ≈ 1 second of audio)" }
GET /api/v1/voices
Voices you can use — the public catalog plus your own cloned and designed voices. Use a returned id as the voice for generation. Catalog voices also accept their slug.
{ "voices": [
{ "id": "Ashley", "slug": "warm-natural-female-explainer-voice-for-youtube-podcasts",
"name": "Warm Natural Female Explainer Voice for YouTube & Podcasts",
"type": "preset", "languages": ["en"], "category": "Narration" },
{ "id": "default-abc123__my-voice", "name": "My Narrator", "type": "clone", "languages": ["en"] }
] }
GET /api/v1/models
The selectable speech models. Pass a key as model on POST /api/v1/tts (default v-pro). API keys can use all three. See Voice Models for the differences.
{ "default": "v-pro", "models": [
{ "key": "v-studio", "label": "VocalLab Studio", "steerable": true, "costMultiplier": 1 },
{ "key": "v-pro", "label": "VocalLab Pro", "steerable": false, "costMultiplier": 1 },
{ "key": "v-lite", "label": "VocalLab Lite", "steerable": false, "costMultiplier": 0.5 }
] }
POST /api/v1/tts
Generate speech.
| Field | Required | Notes |
|---|---|---|
text | yes | Up to 2,000 characters. Each call is synthesized as a single request — for longer scripts, split the text and make multiple calls |
voice | yes | A voice id from /api/v1/voices |
model | no | v-studio (newest, steerable, 200+ languages), v-pro (default — highest fidelity, 15 languages), or v-lite (fast, ½ points). See GET /api/v1/models |
speed | no | Number 0.5–1.5 (step 0.05). Defaults to the voice preset |
temperature | no | Number 0.7–1.5 (step 0.05). Higher = more expressive & variable. Defaults to the voice preset |
format | no | One of MP3 (default), WAV, FLAC, OGG_OPUS, LINEAR16, PCM, ALAW, MULAW |
bit_rate | no | Integer 32000–320000. MP3 & OGG_OPUS only — ignored for other formats |
sample_rate | no | One of 8000, 16000, 22050, 24000, 32000, 44100, 48000 (Hz) |
curl -X POST https://api.vocallab.ai/api/v1/tts \
-H "Authorization: Bearer vl_live_..." \
-H "Content-Type: application/json" \
-d '{"text":"Hello from VocalLab","voice":"Ashley"}'
Returns the audio inline (base64) plus an id. The hosted URL appears once the upload finishes — poll GET /api/v1/tts/:id for it.
Each request is capped at 2,000 characters and maps to exactly one speech synthesis — there's no hidden splitting or fan-out, so cost and latency per call stay predictable. Requests are metered against your points balance and run through a fair-use queue, so heavy automation never blocks the app. To narrate a longer script, break it into ≤ 2,000-character pieces and send them as separate calls (respecting the 60 requests/minute rate limit).
{ "id": "...", "status": "pending", "audio_base64": "data:audio/mp3;base64,...",
"audio_url": null, "format": "MP3", "model": "v-pro", "points_used": 12 }
Model & cost.
v-litebills at half the points ofv-pro/v-studio(points = ⌈ characters ÷ 30 ⌉instead of÷ 15).v-studiois the only model that follows expression/steering instructions — see Voice Models and Voice Steering.
Pauses
Insert a silence of an exact length anywhere in text with a self-closing <break /> tag:
curl -X POST https://api.vocallab.ai/api/v1/tts \
-H "Authorization: Bearer vl_live_..." \
-H "Content-Type: application/json" \
-d '{"text":"Let me think <break time=\"1.5s\" /> Yes, I have thought about it.","voice":"Ashley"}'
- Seconds or milliseconds —
<break time="1.5s" />and<break time="1500ms" />are identical. - Up to 20 break tags per request, in every supported language.
- Tag names are case-insensitive, but the tag must be well-formed and self-closing.
- Break tags count toward the 2,000-character limit and are stripped from captions/SRT.
- Softer pacing needs no tag: commas, periods, em dashes (—) and blank lines all shape delivery. See Voice Steering.
GET /api/v1/tts/:id
Generation status and the hosted audio URL once ready.
{ "id": "...", "status": "ready", "audio_url": "https://...", "format": "MP3" }
GET /api/v1/me
Your points balance and plan.
Errors
| Status | Meaning |
|---|---|
401 | Missing or invalid API key |
402 | Not enough points |
403 | Plan doesn't include API access (requires Pro or higher) |
413 | Text too long |
429 | Rate limit reached (60 / minute per key) |
Errors are shaped { "error": { "code": "...", "message": "..." } }.
Pricing
Generations are billed from your points balance, calculated from the text length (not the final audio duration):
points = ⌈ characters ÷ 15 ⌉ (API rate — about 15 characters per point)
⌈ ⌉ rounds up to the next whole point. The web app uses 17 characters per point, so the API carries a small (~13%) premium. Points are metered before the upstream call — a request that would exceed your balance returns 402 and is never generated. Each response includes the exact points_used. Because speech averages ~15–17 characters/second, 1 point ≈ 1 second of audio, but the exact charge always follows the formula above. See Credits & Minutes for more.


