API Reference
AI Dubbing API
Dub video or audio from public URLs, signed S3/R2 URLs, supported social URLs, or a Subclip object key.
Subclip checks the duration-based AI credit requirement before it creates the job. For current costs, see API credit costs.
OpenAPI-style reference
API endpoints
Dub audio or video from public URLs, social URLs, Subclip object keys, or uploaded media.
/api/v1are auto-cleaned and do not count toward the user's storage quota./api/v1/dubbing/uploadsCreate source or SRT upload URL
Creates a signed upload URL for source media or transcript SRT.
Parameters
| Field | Type | Required | Details |
|---|---|---|---|
uploadType | source | transcript_srt | No | What the upload URL should accept |
fileName | string | Yes | File name body |
contentType | string | No | Audio, video, or SRT content type body |
fileSize | number | Yes | Declared size in bytes, max 5GB for source media body |
Examples
Request
{
"uploadType": "source",
"fileName": "source.mp4",
"contentType": "video/mp4",
"fileSize": 104857600
}Response
{
"uploadUrl": "https://...",
"method": "PUT",
"sourceObjectKey": "user_.../dubbing-api/sources/abc123-source.mp4",
"sourceMediaType": "video",
"expiresIn": 900
}Responses
| Status | Description |
|---|---|
200 | Request succeeded |
400 | Invalid request body or unsupported parameter |
401 | Missing, invalid, or revoked API key |
429 | Rate limit exceeded |
500 | Unexpected processing error |
/api/v1/dubbing/jobsStart AI dubbing
Starts a dubbing job. Duration is required because credits are checked before processing.
Parameters
| Field | Type | Required | Details |
|---|---|---|---|
sourceUrl | string | No | Public, signed, or supported social URL. Required unless sourceObjectKey is provided body |
sourceObjectKey | string | No | Subclip uploaded source object key. Required unless sourceUrl is provided |
sourceMediaType | video | audio | Yes | Source media type bodyDubbing options |
durationSeconds | number | Yes | Known source duration for credit preflight bodyDubbing options |
sourceLanguage | string | Yes | Source language code |
targetLanguage | string | Yes | Target language code |
multiSpeaker | boolean | No | Enable diarized multi-speaker dubbing |
cloneVoice | boolean | No | Clone voice. Required when multiSpeaker is true |
voiceId | string | No | Voice ID from GET /api/v1/media-render/voices when not cloning bodyVoice selection |
responseType | complete_media | chunks | No | Return merged media or per-chunk URLs |
transcriptSrtObjectKey | string | No | Optional uploaded SRT key. Not allowed for multiSpeaker jobs |
Examples
Request
{
"sourceUrl": "https://www.youtube.com/watch?v=...",
"sourceMediaType": "video",
"durationSeconds": 180,
"sourceLanguage": "en",
"targetLanguage": "es",
"multiSpeaker": false,
"cloneVoice": false,
"voiceId": "svoice_...",
"responseType": "complete_media"
}Response
{
"projectId": "dproj_...",
"status": "queued",
"runId": "run_...",
"estimatedCredits": 9,
"statusUrl": "/api/v1/.../jobs/dproj_...",
"downloadUrl": "/api/v1/.../jobs/dproj_.../download"
}Responses
| Status | Description |
|---|---|
200 | Request succeeded |
400 | Invalid request body or unsupported parameter |
401 | Missing, invalid, or revoked API key |
429 | Rate limit exceeded |
500 | Unexpected processing error |
/api/v1/dubbing/jobs/{projectId}Get dubbing job status
Returns dubbing progress, response type, chunks, and output metadata.
Parameters
| Field | Type | Required | Details |
|---|---|---|---|
projectId | string | Yes | Dubbing project ID path |
Examples
Response
{
"projectId": "dproj_...",
"status": "queued | processing | completed | failed",
"progress": 100,
"outputReady": true,
"creditsUsed": 9,
"errorMessage": null,
"updatedAt": "2026-06-19T14:20:00.000Z"
}Responses
| Status | Description |
|---|---|
200 | Request succeeded |
400 | Invalid request body or unsupported parameter |
401 | Missing, invalid, or revoked API key |
429 | Rate limit exceeded |
500 | Unexpected processing error |
/api/v1/dubbing/jobs/{projectId}/downloadCreate dubbed media download URL
Returns a signed download URL for complete_media jobs.
Parameters
| Field | Type | Required | Details |
|---|---|---|---|
projectId | string | Yes | Dubbing project ID path |
Examples
Response
{
"projectId": "dproj_...",
"downloadUrl": "https://signed-download-url...",
"expiresAt": "2026-06-19T15:00:00.000Z",
"expiresIn": 3600,
"contentType": "video/mp4",
"fileSize": 18345678
}Responses
| Status | Description |
|---|---|
200 | Request succeeded |
400 | Invalid request body or unsupported parameter |
401 | Missing, invalid, or revoked API key |
429 | Rate limit exceeded |
500 | Unexpected processing error |
Voices
When multiSpeaker is false and cloneVoice is false, choose a voice from the shared voices endpoint.
curl "https://www.subclip.app/api/v1/media-render/voices?language=es" \ -H "Authorization: Bearer $SUBCLIP_API_KEY"
Upload source media to Subclip
This step is optional. It is useful when you do not want to manage S3 storage infrastructure and want Subclip to handle direct client-side uploads.
1. Create an upload URL
curl -X POST https://www.subclip.app/api/v1/dubbing/uploads \
-H "Authorization: Bearer $SUBCLIP_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"uploadType": "source",
"fileName": "source-video.mp4",
"contentType": "video/mp4",
"fileSize": 104857600
}'{
"uploadUrl": "https://...",
"method": "PUT",
"sourceObjectKey": "user_.../dubbing-api/sources/abc123-source-video.mp4",
"sourceObjectName": "source-video.mp4",
"sourceObjectMimeType": "video/mp4",
"sourceMediaType": "video",
"expiresIn": 900
}2. Upload the file
curl -X PUT "$SOURCE_UPLOAD_URL" \ -H "Content-Type: video/mp4" \ -H "Content-Length: 104857600" \ --data-binary "@source-video.mp4"
3. Start the job with sourceObjectKey
curl -X POST https://www.subclip.app/api/v1/dubbing/jobs \
-H "Authorization: Bearer $SUBCLIP_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"sourceObjectKey": "user_.../dubbing-api/sources/abc123-source-video.mp4",
"sourceObjectName": "source-video.mp4",
"sourceObjectMimeType": "video/mp4",
"sourceMediaType": "video",
"durationSeconds": 180,
"sourceLanguage": "en",
"targetLanguage": "es",
"multiSpeaker": false,
"cloneVoice": false,
"voiceId": "svoice_...",
"responseType": "complete_media"
}'Start a job
durationSeconds is required because credits are checked before the job starts. Add transcriptSrtUrl when your single-speaker transcript is already available as a signed or public SRT URL.
curl -X POST https://www.subclip.app/api/v1/dubbing/jobs \
-H "Authorization: Bearer $SUBCLIP_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"sourceUrl": "https://www.youtube.com/watch?v=...",
"sourceMediaType": "video",
"durationSeconds": 180,
"sourceLanguage": "en",
"targetLanguage": "es",
"transcriptSrtUrl": "https://your-bucket.s3.amazonaws.com/source.srt?X-Amz-Signature=...",
"multiSpeaker": false,
"cloneVoice": false,
"voiceId": "svoice_...",
"responseType": "complete_media"
}'{
"projectId": "dproj_...",
"status": "queued",
"runId": "run_...",
"estimatedCredits": 9,
"statusUrl": "/api/v1/dubbing/jobs/dproj_...",
"downloadUrl": "/api/v1/dubbing/jobs/dproj_.../download"
}Upload an SRT transcript
If your single-speaker transcript is a local SRT file, upload it to Subclip storage first, then pass the returned transcriptSrtObjectKey when starting the job.
curl -X POST https://www.subclip.app/api/v1/dubbing/uploads \
-H "Authorization: Bearer $SUBCLIP_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"uploadType": "transcript_srt",
"fileName": "source.srt",
"contentType": "text/plain",
"fileSize": 18432
}'{
"uploadUrl": "https://...",
"method": "PUT",
"transcriptSrtObjectKey": "user_.../dubbing-api/transcripts/abc123-source.srt",
"expiresIn": 900
}curl -X PUT "$TRANSCRIPT_UPLOAD_URL" \ -H "Content-Type: text/plain" \ --data-binary "@source.srt"
Supported languages
Source language
sourceLanguage can be auto or one of these codes.
| Code | Language |
|---|---|
| auto | Auto Detect |
| en | English (US) |
| zh | Chinese (Simplified) |
| ko | Korean |
| ja | Japanese |
| ru | Russian |
| it | Italian |
| es | Spanish |
| pt | Portuguese (Brazil) |
| de | German |
| fr | French |
| ar | Arabic (Saudi) |
| pl | Polish |
| nl | Dutch |
| hi | Hindi |
| he | Hebrew |
Target language
targetLanguage must be one of these codes.
| Code | Language |
|---|---|
| en | English (US) |
| zh | Chinese (Simplified) |
| ko | Korean |
| ja | Japanese |
| ru | Russian |
| it | Italian |
| es | Spanish |
| pt | Portuguese (Brazil) |
| de | German |
| fr | French |
| ar | Arabic (Saudi) |
| pl | Polish |
| nl | Dutch |
| hi | Hindi |
| he | Hebrew |
Multi-speaker chunks
For multi-speaker dubbing, set cloneVoice to true. Do not pass transcript, transcriptSrtUrl, or transcriptSrtObjectKey; Subclip transcribes and diarizes the source internally. Set responseType to chunks to receive one signed audio URL per segment.
curl -X POST https://www.subclip.app/api/v1/dubbing/jobs \
-H "Authorization: Bearer $SUBCLIP_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"sourceUrl": "https://www.instagram.com/reel/...",
"sourceMediaType": "video",
"durationSeconds": 94,
"sourceLanguage": "en",
"targetLanguage": "hi",
"multiSpeaker": true,
"cloneVoice": true,
"responseType": "chunks"
}'Options
| Field | Required | Notes |
|---|---|---|
| sourceUrl | Yes, unless sourceObjectKey | Public/signed URL, YouTube, TikTok, Instagram, X, Facebook, or another downloadable HTTP(S) URL. |
| sourceObjectKey | Yes, unless sourceUrl | Object key returned by POST /api/v1/dubbing/uploads with uploadType source, or an existing Subclip object key owned by the API key user. |
| sourceMediaType | Yes | video or audio. Audio output uses FFmpeg merging, not Remotion. |
| durationSeconds | Yes | Used for required AI credit preflight before the job starts. |
| sourceLanguage | Yes | Source spoken language, for example en or auto. |
| targetLanguage | Yes | Target language code. |
| transcript | No | Optional single-speaker structured transcript segments. Not allowed for multiSpeaker. |
| transcriptSrtUrl | No | Public or signed HTTP(S) URL for a single-speaker SRT transcript. Not allowed for multiSpeaker. |
| transcriptSrtObjectKey | No | Object key returned by POST /api/v1/dubbing/uploads after uploading an SRT to Subclip storage. Not allowed for multiSpeaker. |
| multiSpeaker | No | Defaults to false. Requires cloneVoice true. Transcript inputs are rejected because Subclip must transcribe and diarize internally. |
| cloneVoice | No | Required true for multiSpeaker. If false, voiceId is required. |
| voiceId | Conditional | Use a voice from GET /api/v1/media-render/voices when cloneVoice is false. |
| responseType | No | complete_media or chunks. Defaults to complete_media. |
| includeChunks | No | Include chunk URLs alongside complete_media output. |
Poll status
Poll every 10 to 15 seconds. The output is ready when outputReady is true.
curl https://www.subclip.app/api/v1/dubbing/jobs/dproj_... \ -H "Authorization: Bearer $SUBCLIP_API_KEY"
Download
For complete_media, download the returned signed URL. For chunks, use each returned chunk URL.
DOWNLOAD_JSON=$(curl -s https://www.subclip.app/api/v1/dubbing/jobs/dproj_.../download \ -H "Authorization: Bearer $SUBCLIP_API_KEY") DOWNLOAD_URL=$(echo "$DOWNLOAD_JSON" | jq -r '.downloadUrl') curl -L "$DOWNLOAD_URL" -o dubbed.mp4