Endpoints
Endpoint Summary
| Method | Path | Description |
|---|---|---|
| GET | /api/v1/me | Your profile and credit balance |
| GET | /api/v1/dubs | List all your dubs (includes projectId) |
| GET | /api/v1/dubs//outputs | Signed download URLs for one dub's outputs |
| GET | /api/v1/projects//outputs | Outputs for every language in a project |
| POST | /api/v1/init-dub | Create one file (one language) and get an upload URL |
| POST | /api/v1/init-dub-group | One upload → many languages (shared project) |
| POST | /api/v1/start-dub | Start the dubbing pipeline for a file |
Output types
outputs is a map of { <type>: { url, downloadUrl } }. url is inline-viewable,
downloadUrl forces a file download. Both are presigned and expire after
expiresIn seconds (default 3600). The map is empty until the dub completes.
| Type | Meaning |
|---|---|
| translated_mp4 | Dubbed video (MP4) |
| translated | Dubbed video (pipeline format) |
| translated_mp3 | Dubbed audio (MP3) |
| translated_subtitle | Subtitles in the target language |
| original / original_mp4 | Original uploaded video |
| original_mp3 | Original audio |
| original_subtitle | Subtitles in the source language |
| poster | Thumbnail image |
Multi-language flow (one upload, many languages)
# 1. Create the group — one upload URL, N dubs sharing it
RESP=$(curl -s -X POST https://dublab.app/api/v1/init-dub-group \
-H "apikey: YOUR_API_KEY" -H "Content-Type: application/json" \
-d '{"fileType":"video/mp4","name":"talk.mp4","source_lang":"en","duration":120,"dest_langs":["tr","de","es"]}')
UPLOAD_URL=$(echo "$RESP" | jq -r '.uploadUrl')
PROJECT_ID=$(echo "$RESP" | jq -r '.projectId')
# 2. Upload the video ONCE
curl -X PUT -H "Content-Type: video/mp4" --data-binary @talk.mp4 "$UPLOAD_URL"
# 3. Start each returned fileId
for FID in $(echo "$RESP" | jq -r '.files[].fileId'); do
curl -s -X POST https://dublab.app/api/v1/start-dub \
-H "apikey: YOUR_API_KEY" -H "Content-Type: application/json" \
-d "{\"fileId\": \"$FID\"}"
done
# 4. Poll + download every language at once
curl -H "apikey: YOUR_API_KEY" \
https://dublab.app/api/v1/projects/$PROJECT_ID/outputs
Base URL
https://dublab.app/api/v1
All endpoints require the apikey header. See API Reference for full request/response details.
Workflow
init-dub → S3 upload → start-dub → poll dubs
- init-dub: Creates file record, returns presigned S3 URL
- Upload: PUT your video to the S3 URL
- start-dub: Triggers AI pipeline (RunPod for standard, SQS for studio)
- Poll: Check
GET /dubsuntilexternalStatusId = 5
Status Codes
| externalStatusId | Meaning |
|---|---|
| 1 | Uploading |
| 2 | In Queue |
| 3 | Processing |
| 4 | Failed |
| 5 | Completed |
The public status surface is 1–5 (the pipeline tracks a separate internal
status not returned by the API).
Error Handling
All errors return { "error": "message" } with appropriate HTTP status codes
(400, 401, 402, 403, 404, 409, 412, 500, 502).
Check the externalErrorMessage field on failed dubs for a user-facing reason.
Notes
- Billing: credits are charged once on completion, against the server-measured
output duration (
measuredDuration), not thedurationyou submit. - Each
init-dubcall creates an independent project (source: "api"). The internal/api/task-finishedcompletion callback is worker-only and not part of the public API.