Subclip Logo

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 v1 storage handling: files uploaded or generated through /api/v1are auto-cleaned and do not count toward the user's storage quota.
POST/api/v1/dubbing/uploads

Create source or SRT upload URL

Creates a signed upload URL for source media or transcript SRT.

Bearer auth

Parameters

FieldTypeRequiredDetails
uploadTypesource | transcript_srtNo
What the upload URL should accept
bodydefault: transcript_srtUpload source and SRT
fileNamestringYes
File name
body
contentTypestringNo
Audio, video, or SRT content type
body
fileSizenumberYes
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

StatusDescription
200Request succeeded
400Invalid request body or unsupported parameter
401Missing, invalid, or revoked API key
429Rate limit exceeded
500Unexpected processing error
POST/api/v1/dubbing/jobs

Start AI dubbing

Starts a dubbing job. Duration is required because credits are checked before processing.

Bearer auth

Parameters

FieldTypeRequiredDetails
sourceUrlstringNo
Public, signed, or supported social URL. Required unless sourceObjectKey is provided
body
sourceObjectKeystringNo
Subclip uploaded source object key. Required unless sourceUrl is provided
sourceMediaTypevideo | audioYes
Source media type
durationSecondsnumberYes
Known source duration for credit preflight
sourceLanguagestringYes
Source language code
targetLanguagestringYes
Target language code
multiSpeakerbooleanNo
Enable diarized multi-speaker dubbing
bodydefault: falseMulti-speaker rules
cloneVoicebooleanNo
Clone voice. Required when multiSpeaker is true
bodydefault: falseMulti-speaker rules
voiceIdstringNo
Voice ID from GET /api/v1/media-render/voices when not cloning
responseTypecomplete_media | chunksNo
Return merged media or per-chunk URLs
bodydefault: complete_mediaMulti-speaker chunks
transcriptSrtObjectKeystringNo
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

StatusDescription
200Request succeeded
400Invalid request body or unsupported parameter
401Missing, invalid, or revoked API key
429Rate limit exceeded
500Unexpected processing error
GET/api/v1/dubbing/jobs/{projectId}

Get dubbing job status

Returns dubbing progress, response type, chunks, and output metadata.

Bearer auth

Parameters

FieldTypeRequiredDetails
projectIdstringYes
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

StatusDescription
200Request succeeded
400Invalid request body or unsupported parameter
401Missing, invalid, or revoked API key
429Rate limit exceeded
500Unexpected processing error
GET/api/v1/dubbing/jobs/{projectId}/download

Create dubbed media download URL

Returns a signed download URL for complete_media jobs.

Bearer auth

Parameters

FieldTypeRequiredDetails
projectIdstringYes
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

StatusDescription
200Request succeeded
400Invalid request body or unsupported parameter
401Missing, invalid, or revoked API key
429Rate limit exceeded
500Unexpected 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.

CodeLanguage
autoAuto Detect
enEnglish (US)
zhChinese (Simplified)
koKorean
jaJapanese
ruRussian
itItalian
esSpanish
ptPortuguese (Brazil)
deGerman
frFrench
arArabic (Saudi)
plPolish
nlDutch
hiHindi
heHebrew

Target language

targetLanguage must be one of these codes.

CodeLanguage
enEnglish (US)
zhChinese (Simplified)
koKorean
jaJapanese
ruRussian
itItalian
esSpanish
ptPortuguese (Brazil)
deGerman
frFrench
arArabic (Saudi)
plPolish
nlDutch
hiHindi
heHebrew

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

FieldRequiredNotes
sourceUrlYes, unless sourceObjectKeyPublic/signed URL, YouTube, TikTok, Instagram, X, Facebook, or another downloadable HTTP(S) URL.
sourceObjectKeyYes, unless sourceUrlObject key returned by POST /api/v1/dubbing/uploads with uploadType source, or an existing Subclip object key owned by the API key user.
sourceMediaTypeYesvideo or audio. Audio output uses FFmpeg merging, not Remotion.
durationSecondsYesUsed for required AI credit preflight before the job starts.
sourceLanguageYesSource spoken language, for example en or auto.
targetLanguageYesTarget language code.
transcriptNoOptional single-speaker structured transcript segments. Not allowed for multiSpeaker.
transcriptSrtUrlNoPublic or signed HTTP(S) URL for a single-speaker SRT transcript. Not allowed for multiSpeaker.
transcriptSrtObjectKeyNoObject key returned by POST /api/v1/dubbing/uploads after uploading an SRT to Subclip storage. Not allowed for multiSpeaker.
multiSpeakerNoDefaults to false. Requires cloneVoice true. Transcript inputs are rejected because Subclip must transcribe and diarize internally.
cloneVoiceNoRequired true for multiSpeaker. If false, voiceId is required.
voiceIdConditionalUse a voice from GET /api/v1/media-render/voices when cloneVoice is false.
responseTypeNocomplete_media or chunks. Defaults to complete_media.
includeChunksNoInclude 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