Docsapiauthentication

API Reference

Authentication

All API requests require an API key passed in the apikey header (lowercase):

curl -H "apikey: YOUR_API_KEY" \
  https://dublab.app/api/v1/me

Note: The header name is apikey, not Authorization: Bearer. Keep this in mind when integrating.

Creating an API Key

  1. Log into your DubLab account
  2. Go to Account Settings
  3. Scroll to the API Keys section
  4. Click Create API Key
  5. Copy and save your key — it won't be shown again

Endpoints

GET /api/v1/me

Returns your user profile, credits, and subscription info.

Request:

curl -H "apikey: YOUR_API_KEY" \
  https://dublab.app/api/v1/me

Response (200):

{
  "id": "bc6276da-fb68-40a2-...",
  "email": "you@example.com",
  "name": "Your Name",
  "username": "you@example.com",
  "firstName": null,
  "lastName": null,
  "seconds": 32955,
  "defaultDubLang": "de",
  "subscriptionStatus": "active",
  "subscriptionPlan": "hobby",
  "createdAt": "2025-04-28T01:10:53.359Z"
}

The seconds field is your available credit balance (one credit = one second of output). subscriptionStatus and subscriptionPlan are null for users without an active subscription. firstName/lastName may be null.


GET /api/v1/dubs

Returns all your dubbed files with status and metadata.

Request:

curl -H "apikey: YOUR_API_KEY" \
  https://dublab.app/api/v1/dubs

Response (200):

[
  {
    "id": "ec2a9095-6f35-...",
    "name": "my-video.mp4",
    "type": "video/mp4",
    "sourceLang": "auto",
    "destLang": "tr",
    "externalStatusId": 5,
    "progressPercentage": 100,
    "externalErrorMessage": null,
    "duration": 143,
    "measuredDuration": 142,
    "isStudioQuality": false,
    "source": "web",
    "createdAt": "2026-04-12T17:20:40.611Z"
  }
]

duration is the value you supplied at init-dub; measuredDuration is the server-measured length (seconds) and is what your credits are billed on. It is null until the dub completes.

Status IDs (externalStatusId):

externalStatusIdMeaning
1Uploading
2In Queue
3Processing
4Failed
5Completed

The public status surface is 15. The pipeline also tracks a separate internal status that is not returned by the API.


POST /api/v1/init-dub

Creates a file record and returns a presigned S3 upload URL. You upload your video to this URL before starting the dub.

Request:

curl -X POST https://dublab.app/api/v1/init-dub \
  -H "apikey: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "fileType": "video/mp4",
    "name": "my-video.mp4",
    "source_lang": "auto",
    "dest_lang": "tr",
    "duration": 67,
    "isStudioQuality": false
  }'

Parameters:

FieldTypeRequiredDescription
fileTypestringYesMIME type: video/mp4, video/quicktime, audio/mpeg, etc.
namestringYesOriginal filename
source_langstringYesSource language code or "auto" for auto-detection
dest_langstringYesTarget language code (tr, de, es, fr, ja, etc.)
durationnumberNoVideo duration in seconds
isStudioQualitybooleanNotrue for ElevenLabs studio quality (2x credits)

Response (200):

{
  "file": {
    "id": "ce14fea7-9c5b-...",
    "name": "my-video.mp4",
    "source": "api",
    "externalStatusId": 1,
    "internalStatusId": 1
  },
  "uploadUrl": "https://s3.eu-central-1.amazonaws.com/dublab-app-1/...?X-Amz-Algorithm=..."
}

Upload your file to the presigned URL:

curl -X PUT \
  -H "Content-Type: video/mp4" \
  --data-binary @my-video.mp4 \
  "PRESIGNED_UPLOAD_URL"

POST /api/v1/start-dub

Starts the AI dubbing pipeline for an uploaded file. The file must already be uploaded to S3.

Request:

curl -X POST https://dublab.app/api/v1/start-dub \
  -H "apikey: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"fileId": "ce14fea7-9c5b-..."}'

Response (200):

{
  "success": true,
  "fileId": "ce14fea7-9c5b-..."
}

After this, the file enters the processing queue. Poll GET /api/v1/dubs to check the progressPercentage and externalStatusId.

Possible errors: 402 (no credits), 404 (file not found), 403 (not your file), 409 (already in progress or completed), 412 (file not uploaded to S3 yet), 502 (dispatch failed).

Billing: credits are charged once, when the dub completes, against the server-measured duration (measuredDuration) — not the duration you sent. start-dub only checks that your balance is above zero.


Full Workflow Example

Here's a complete example dubbing a video from English to Turkish using curl:

# 1. Create file record and get upload URL
RESPONSE=$(curl -s -X POST https://dublab.app/api/v1/init-dub \
  -H "apikey: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "fileType": "video/mp4",
    "name": "presentation.mp4",
    "source_lang": "en",
    "dest_lang": "tr",
    "duration": 120
  }')

FILE_ID=$(echo $RESPONSE | jq -r '.file.id')
UPLOAD_URL=$(echo $RESPONSE | jq -r '.uploadUrl')

# 2. Upload the video to S3
curl -X PUT \
  -H "Content-Type: video/mp4" \
  --data-binary @presentation.mp4 \
  "$UPLOAD_URL"

# 3. Start dubbing
curl -X POST https://dublab.app/api/v1/start-dub \
  -H "apikey: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d "{\"fileId\": \"$FILE_ID\"}"

# 4. Check status (poll until externalStatusId = 5)
curl -H "apikey: YOUR_API_KEY" \
  https://dublab.app/api/v1/dubs

Error Responses

All errors return JSON with an error field:

{ "error": "Invalid API key" }
StatusMeaning
400Bad request — missing or invalid parameters
401Unauthorized — missing or invalid API key
402Payment required — insufficient credit balance
403Forbidden — file belongs to another user
404Not found — file or user doesn't exist
409Conflict — dub already in progress or completed
412Precondition failed — source file not uploaded yet
502Bad gateway — processing backend unavailable
500Internal server error

Supported Languages

dest_lang accepts any of the 90+ supported codes below (powered by the OmniVoice engine). source_lang accepts the same codes or "auto" (auto-detect) — auto is a source-only option, not a dub target.

The authoritative, always-current list is served by GET /api/langs. Current set:

English (en), Spanish (es), French (fr), German (de), Chinese (zh), Japanese (ja), Russian (ru), Portuguese (pt), Arabic (ar), Hindi (hi), Bengali (bn), Punjabi (pa), Vietnamese (vi), Korean (ko), Italian (it), Persian (fa), Turkish (tr), Dutch (nl), Hebrew (he), Indonesian (id), Polish (pl), Ukrainian (uk), Romanian (ro), Greek (el), Hungarian (hu), Thai (th), Swedish (sv), Czech (cs), Danish (da), Finnish (fi), Norwegian (no), Bulgarian (bg), Slovak (sk), Croatian (hr), Serbian (sr), Malay (ms), Tamil (ta), Urdu (ur), Telugu (te), Marathi (mr), Gujarati (gu), Malayalam (ml), Afrikaans (af), Basque (eu), Catalan (ca), Esperanto (eo), Galician (gl), Georgian (ka), Haitian Creole (ht), Icelandic (is), Irish (ga), Kannada (kn), Latin (la), Latvian (lv), Lithuanian (lt), Luxembourgish (lb), Macedonian (mk), Maltese (mt), Mongolian (mn), Nepali (ne), Northern Sami (se), Sinhala (si), Estonian (et), Tagalog (tl), Burmese (my), Kazakh (kk), Bosnian (bs), Swahili (sw), Amharic (am), Azerbaijani (az), Belarusian (be), Uzbek (uz), Khmer (km), Lao (lo), Sindhi (sd), Welsh (cy), Frisian (fy), Yoruba (yo), Hausa (ha), Igbo (ig), Zulu (zu), Xhosa (xh), Shona (sn), Faroese (fo), Chichewa (ny), Kinyarwanda (rw), Southern Sotho (st), Tswana (tn), Tsonga (ts), Swati (ss), Venda (ve), Twi (tw)