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

MethodPathWhat it does
POST/api/v1/ttsCreate 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/voicesVoice library, filterable by provider, language and gender
GET/api/v1/meYour email, credit balance and credits used
POST/api/v1/translateTranslate text (36 languages)
POST/api/v1/videoAI video: Veo 3.1, Omni Flash, Google Vids, Meta AI
POST/api/v1/stock-videoTurn a script into a stock-footage video
POST/api/v1/sttSpeech to text
POST/api/v1/voice-changerRe-voice a recording with an ElevenLabs voice
POST/api/v1/dubbingDub an audio file into another language
POST/api/v1/dialogueMulti-voice dialogue in one file
POST/api/image-generateAI images: Nano Banana 2.1, Pro, Lite, Google Pics, GPT Image 2, Grok, Meta AI
POST/api/music-generateAI music

Core endpoints

POST/api/v1/tts

Create a text-to-speech job. Credits are charged when the job is created and refunded if it fails.

FieldTypeRequiredDescription
textstringYesThe text to speak, up to 500,000 characters.
voice_idstringYesAn ElevenLabs voice id (15-25 letters and digits), or a vbee_ / fishaudio_ id from GET /api/v1/voices.
model_idstringNoElevenLabs 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.
languagestringNoLanguage hint such as "en", "tr" or "es". Leave it out to detect from the text.
voice_settingsobjectNospeed (0.5-1.5), stability and similarity_boost (0-1, extended model set), with_transcript (also returns an SRT), context_chaining (+50% credits).
webhook_urlstringNoPublic https URL that receives the result when the job completes or fails.

Response

{ "task_id": "8f2c...", "status": "pending", "characters": 27 }
GET/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"
}
GET/api/v1/voices

Query 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"
}
POST/api/v1/translate

Translate 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.

FieldTypeRequiredDescription
textstringYesThe text to translate.
target_languagestringYesLanguage name, e.g. "Spanish", "French", "Turkish".
source_languagestringNoLanguage 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."
}
GET/api/v1/me

The 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.

StatusCodeMeaning
400—Missing or invalid field (the message says which).
400VOICE_NOT_FOUNDThe voice no longer exists or is not in the active list. Nothing is charged.
401INVALID_API_KEYMissing, 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.
503SERVICE_MAINTENANCE / FEATURE_MAINTENANCETemporarily 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.