API Documentation
Add DubVoice.ai voice, video, image and music generation to your own product with one REST API and one credit balance.
This page is the overview. The full reference, with every model, field, price and code sample, is in your dashboard under API Docs.
Quick Start
1. Create a speech job. The call returns at once with a task_id; the audio is rendered in the background.
curl -X POST "https://www.dubvoice.ai/api/v1/tts" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"text": "Hello, welcome to DubVoice!",
"voice_id": "LB3SchLS4lHotJg4GcZW"
}'
# {"task_id":"8f2c...","status":"pending","characters":27}2. Poll until it completes. result is the audio URL.
curl "https://www.dubvoice.ai/api/v1/tts/TASK_ID" \
-H "Authorization: Bearer YOUR_API_KEY"
# {"task_id":"8f2c...","status":"completed","result":"https://.../audio.mp3", ...}Prefer not to poll? Send a webhook_url with the job and the result is posted to it.
Authentication
Create an API key in your dashboard and send it with every request, in either header:
Authorization: Bearer YOUR_API_KEY X-API-Key: YOUR_API_KEY
Keep your key on the server. Never ship it in client-side code or a public repository. The base URL is https://www.dubvoice.ai.
Endpoints
| Method | Path | What it does |
|---|---|---|
| POST | /api/v1/tts | Create a text-to-speech job (ElevenLabs, Vbee, Fish Audio voices) |
| GET | /api/v1/tts/{task_id} | Status and result of one job |
| GET | /api/v1/voices | Voice library, filterable by provider, language and gender |
| GET | /api/v1/me | Your email, credit balance and credits used |
| POST | /api/v1/translate | Translate text (36 languages) |
| POST | /api/v1/video | AI video: Veo 3.1, Omni Flash, Google Vids, Meta AI |
| POST | /api/v1/stock-video | Turn a script into a stock-footage video |
| POST | /api/v1/stt | Speech to text |
| POST | /api/v1/voice-changer | Re-voice a recording with an ElevenLabs voice |
| POST | /api/v1/dubbing | Dub an audio file into another language |
| POST | /api/v1/dialogue | Multi-voice dialogue in one file |
| POST | /api/image-generate | AI images: Nano Banana 2.1, Pro, Lite, Google Pics, GPT Image 2, Grok, Meta AI |
| POST | /api/music-generate | AI music |
Core endpoints
/api/v1/ttsCreate a text-to-speech job. Credits are charged when the job is created and refunded if it fails.
| Field | Type | Required | Description |
|---|---|---|---|
text | string | Yes | The text to speak, up to 500,000 characters. |
voice_id | string | Yes | An ElevenLabs voice id (15-25 letters and digits), or a vbee_ / fishaudio_ id from GET /api/v1/voices. |
model_id | string | No | ElevenLabs model, e.g. "eleven_v4", "eleven_v4_turbo", "eleven_multilingual_v2". Applied while the extended ElevenLabs model set is enabled; GET /api/tts/backend lists the models currently accepted. |
language | string | No | Language hint such as "en", "tr" or "es". Leave it out to detect from the text. |
voice_settings | object | No | speed (0.5-1.5), stability and similarity_boost (0-1, extended model set), with_transcript (also returns an SRT), context_chaining (+50% credits). |
webhook_url | string | No | Public https URL that receives the result when the job completes or fails. |
Response
{ "task_id": "8f2c...", "status": "pending", "characters": 27 }/api/v1/tts/{task_id}Status moves through pending, processing and ends at completed or failed.
{
"task_id": "8f2c...",
"status": "completed",
"result": "https://<storage>/tts-audio/....mp3",
"srt_url": null,
"error": null,
"characters": 27,
"created_at": "2026-10-19T09:00:00Z",
"completed_at": "2026-10-19T09:00:06Z"
}/api/v1/voicesQuery parameters: provider (elevenlabs by default, minimax, vbee, fishaudio, or all for ElevenLabs and Minimax), search, language, gender, page, page_size (default 30, at most 100).
{
"voices": [
{
"voice_id": "LB3SchLS4lHotJg4GcZW",
"name": "Aaden - Friendly, Warm and Confident",
"gender": "male",
"accent": "american",
"language": "en",
"category": "professional",
"description": "...",
"preview_url": "https://..."
}
],
"total": 15106,
"page": 1,
"page_size": 30,
"has_more": true,
"total_pages": 504,
"provider": "elevenlabs"
}/api/v1/translateTranslate text into one of 36 languages. 1 credit per 10 characters of input (rounded up), up to 100,000 characters. GET /api/v1/translate lists the language names.
| Field | Type | Required | Description |
|---|---|---|---|
text | string | Yes | The text to translate. |
target_language | string | Yes | Language name, e.g. "Spanish", "French", "Turkish". |
source_language | string | No | Language of the text. Defaults to "English"; it is not detected automatically. |
Response
{
"success": true,
"original_length": 27,
"translated_length": 31,
"target_language": "Spanish",
"source_language": "English",
"chunks_processed": 1,
"credits_used": 3,
"remaining_credits": 49997,
"translated_text": "Hola, bienvenido a DubVoice."
}/api/v1/meThe account the key belongs to.
{ "email": "you@example.com", "credits": 50000, "total_used": 12000 }Errors
Errors return JSON with an error message; some also carry a machine-readable code.
| Status | Code | Meaning |
|---|---|---|
400 | — | Missing or invalid field (the message says which). |
400 | VOICE_NOT_FOUND | The voice no longer exists or is not in the active list. Nothing is charged. |
401 | INVALID_API_KEY | Missing, invalid or inactive API key. |
402 | — | Not enough credits. The body carries required and available. |
404 | — | Task not found (or it belongs to another account). |
429 | — | Too many requests. Wait for the Retry-After header, then retry. |
503 | SERVICE_MAINTENANCE / FEATURE_MAINTENANCE | Temporarily under maintenance. |
500 | — | Server error. Charged credits are refunded automatically. |
Rate limits
- Text to speech: 240 requests per minute per key, and up to 30 jobs in progress at once.
- Translate: 10 requests per minute per key.
- Images: 10 requests per minute, 3 in progress at once.
- Voices: no limit.
A 429 response carries Retry-After and X-RateLimit-Reset headers.
Code examples
JavaScript / Node.js
const BASE = 'https://www.dubvoice.ai'
const headers = { 'Authorization': 'Bearer ' + process.env.DUBVOICE_API_KEY, 'Content-Type': 'application/json' }
const create = await fetch(BASE + '/api/v1/tts', {
method: 'POST',
headers,
body: JSON.stringify({ text: 'Hello, welcome to DubVoice!', voice_id: 'LB3SchLS4lHotJg4GcZW' }),
})
const { task_id } = await create.json()
let job
do {
await new Promise(r => setTimeout(r, 3000))
job = await (await fetch(BASE + '/api/v1/tts/' + task_id, { headers })).json()
} while (job.status === 'pending' || job.status === 'processing')
if (job.status === 'completed') console.log('audio:', job.result)
else console.error('failed:', job.error)Python
import os, time, requests
BASE = "https://www.dubvoice.ai"
H = {"Authorization": f"Bearer {os.environ['DUBVOICE_API_KEY']}"}
task = requests.post(f"{BASE}/api/v1/tts", headers=H, json={
"text": "Hello, welcome to DubVoice!",
"voice_id": "LB3SchLS4lHotJg4GcZW",
}).json()
while True:
job = requests.get(f"{BASE}/api/v1/tts/{task['task_id']}", headers=H).json()
if job["status"] in ("completed", "failed"):
break
time.sleep(3)
print(job["result"] if job["status"] == "completed" else job["error"])Ready to get started?
Create a free account to get your API key, then open the full reference in your dashboard.