> This is a page from the ElevenLabs documentation. For a complete page index, fetch https://elevenlabs.io/docs/llms.txt. For the full documentation in a single file, fetch https://elevenlabs.io/docs/llms-full.txt.

# Crear proyecto de doblaje

POST https://api.elevenlabs.io/v1/dubbing/project
Content-Type: multipart/form-data

Crea un proyecto de doblaje a partir de un archivo subido (`file`) o una URL de origen (`source_url`).

Devuelve el resultado en cuanto existe el registro del proyecto, antes de recuperar el origen: el proyecto comienza en estado `queued` y pasa a `ready` cuando se ha transcrito su origen. Añade un idioma de destino por cada idioma que quieras, o pasa `target_language` para poner el primero en cola aquí.

La creación de un proyecto conlleva un cargo mínimo de un idioma: se te cobrará el doblaje de al menos un idioma al crear el proyecto, antes de que exista ningún resultado. Este cargo paga por adelantado el primer idioma de destino —el primer destino que añadas o el que pongas en cola mediante `target_language` lo consumirá— y cada idioma adicional se cobra por separado.

La preparación puede tardar varios minutos si el origen es largo, por lo que recomendamos pasar `webhook_ids` para recibir una notificación cuando el proyecto pase a `ready` o `failed`, en lugar de consultarlo periódicamente.

Reference: https://elevenlabs.io/docs/api-reference/dubbing/create-project

## Servers

- `https://api.elevenlabs.io` (Production, default)
- `https://api.us.elevenlabs.io` (Production US)
- `https://api.eu.residency.elevenlabs.io` (Production EU)
- `https://api.in.residency.elevenlabs.io` (Production India)
- `https://api.sg.residency.elevenlabs.io` (Production Singapore)

## Request

### Body (multipart/form-data)

This endpoint expects a multipart form with multiple files.

- `file` (file, optional) — El archivo multimedia de origen que se va a doblar: un archivo de audio o vídeo de hasta 3 GiB. Proporciona este o `source_url`, pero no ambos.
- `source_url` (string, optional) — URL HTTP(S) pública desde la que se obtiene el archivo multimedia de origen en el servidor, sujeta a los mismos límites de tamaño y formato que una subida. Proporciona esta o `file`, pero no ambas.
- `reference` (string, optional) — Cadena opcional de formato libre (como máximo 500 caracteres) para identificar el proyecto por tu parte. Se almacena y devuelve literalmente; no afecta al doblaje.
- `source_language` (string, optional) — Etiqueta de idioma BCP-47 del contenido multimedia de origen; debe ser un idioma compatible con el modelo de transcripción. Se ignora cualquier subetiqueta de región o escritura, ya que la transcripción se realiza por idioma. Omítela para detectarlo automáticamente.
- `model_id` (V1DubbingProjectPostRequestBodyContentMultipartFormDataSchemaModelId, optional) — Modelo de doblaje (`dubbing_v1` o `dubbing_v2`) con el que se doblan todos los idiomas de destino de este proyecto. El valor predeterminado es `dubbing_v2`. Se fija al crear el proyecto: la fuente se prepara para este modelo, por lo que ni el proyecto ni un destino individual pueden cambiarlo después.
- `keyterms` (list of string, optional) — Términos clave para orientar la transcripción y la traducción hacia ellos, como nombres de productos o marcas. Se permiten como máximo 1000 términos; cada término puede tener como máximo 50 caracteres y 5 palabras; no se permiten los caracteres `<>{}[]\`. Los términos se recortan y se eliminan los duplicados. Repite el campo una vez por término o pasa un único array JSON.
- `webhook_ids` (list of string, optional) — ID de los webhooks del espacio de trabajo que se notificarán a medida que avance este proyecto; es la alternativa al sondeo y la que recomendamos. Cada uno recibe un evento `dubbing_project_ready` o `dubbing_project_failed` para el proyecto, y un evento `dubbing_language_completed` o `dubbing_language_failed` para cada idioma incluido; `dubbing_language_completed` contiene las URL de descarga de salida. Como máximo 3 ID, cada uno ya configurado en tu espacio de trabajo; consulta [Webhooks](https://elevenlabs.io/docs/eleven-api/resources/webhooks) para saber cómo crear uno y verificar su firma. Repite el campo una vez por cada ID o proporciona una única matriz JSON o una cadena separada por comas. La entrega se realiza según el mejor esfuerzo y puede repetirse, por lo que recomendamos gestionar los eventos de forma idempotente.
- `target_language` (string, optional) — Atajo opcional: crea también un idioma de destino en este idioma BCP-47, que se pondrá en cola para iniciarse cuando el proyecto esté listo; equivale a crear el proyecto y después crear un idioma de destino. Debe ser uno de los [idiomas compatibles con el modelo de doblaje](https://elevenlabs.io/docs/help-center/product/dubbing/which-languages-are-supported-in-dubbing), y una etiqueta con región debe ser uno de los dialectos compatibles. Como es el primer idioma de destino, consume el cargo mínimo del proyecto en lugar de añadirse a él. Su ID se devuelve en `language_ids`.
- `transcript` (file, optional) — Solo Enterprise. Transcripción JSON opcional que se utilizará en lugar de transcribir el contenido de origen: un documento `{"segments": [...]}` con un máximo de 20.000 segmentos y 4 MiB. Consulta [Usa tu propia transcripción](https://elevenlabs.io/docs/eleven-api/guides/how-to/dubbing/bring-your-own-transcript) para conocer los campos de los segmentos y sus restricciones. Se requiere `source_language` siempre que se proporcione una transcripción. Si algún segmento incluye una `translation`, se requiere `target_language` y todos los segmentos deben incluir una; esas traducciones inicializan el destino creado mediante `target_language`, que entonces omite la traducción automática.

## Response

### 201

Respuesta correcta.

- `project_id` (string, required) — Identificador único del proyecto de doblaje.
- `status` (enum, required) — Estado del ciclo de vida del proyecto: `queued` antes de que se procese la fuente, `preparing` mientras se transcribe, `ready` cuando finaliza la transcripción y pueden iniciarse los idiomas de destino, o `failed`. Un proyecto nunca se indica como `processing`: ese valor corresponde a los idiomas de destino.
  - Allowed values: `queued`, `preparing`, `processing`, `ready`, `failed`
- `revision` (integer, required) — Contador monotónico que aumenta cada vez que se edita la transcripción de origen (al añadir, editar o eliminar segmentos).
- `created_at` (string, required) — Cuándo se creó el proyecto.
- `updated_at` (string, required) — Cuándo se actualizó por última vez el proyecto.
- `reference` (string, optional, nullable) — La cadena de texto libre que proporcionaste como `reference` al crear el proyecto, o null si no proporcionaste ninguna.
- `source_language` (string, optional, nullable) — Etiqueta de idioma BCP-47 del contenido multimedia de origen (null si se detecta automáticamente).
- `model_id` (string, optional, nullable) — Modelo de doblaje con el que se doblan todos los idiomas de destino de este proyecto. Se fija al crear el proyecto y no se puede seleccionar por idioma.
- `media` (DubbingSourceMediaInfo, optional, nullable) — Metadatos del contenido multimedia de origen, que se rellenan una vez que el origen se ha obtenido y descodificado (poco después de crear el proyecto y antes de que esté `ready`); null hasta entonces.
- `language_ids` (list of string, optional, default: []) — Identificadores de los idiomas de destino de este proyecto. Se rellenan al recuperar un proyecto individual y al crear uno cuando `target_language` crea uno. Siempre están vacíos en las respuestas de lista; muestra en su lugar los idiomas de destino del proyecto.
- `webhook_ids` (list of string, optional, default: []) — ID de los webhooks del espacio de trabajo que se notificarán cuando este proyecto y sus idiomas alcancen el estado `ready`, `completed` o `failed`.
- `error` (DubbingError, optional, nullable) — Por qué falló el proyecto; null salvo que `status` sea `failed`. También es null para los pocos proyectos que fallaron antes de que se introdujera el informe de errores.
- `warnings` (list of VoicesNotPermittedWarning, optional) — Condiciones no críticas detectadas al preparar la fuente; vacío si no hay ninguna. Refleja la preparación más reciente. Las condiciones detectadas durante el doblaje de un idioma concreto se notifican en ese idioma.

## Errors

### 422 Unprocessable Entity Error

Error de validación

- `detail` (list of ValidationError, optional)

## Types

### DubbingSourceMediaInfo

Metadatos sobre el contenido multimedia de origen del proyecto.

- `filename` (string, optional, nullable) — Nombre de archivo original del archivo multimedia de origen subido (null para fuentes URL).
- `duration_s` (double, optional, nullable) — Duración del contenido multimedia de origen, en segundos.
- `has_video` (boolean, optional, nullable) — Indica si el archivo multimedia de origen contiene una secuencia de vídeo.
- `mime_type` (string, optional, nullable) — Tipo MIME del contenido multimedia de origen subido (null para fuentes URL).

### DubbingError

- `message_type` ("error", required)
- `error` (string, required)

### VoicesNotPermittedWarning

- `type` ("voices_not_permitted", required) — Identifica esta advertencia; úsalo para consultar los demás campos.
- `speaker_ids` (list of string, required) — Hablantes cuyas voces no estaban autorizadas para clonación. El doblaje utilizó una voz de sustitución para cada uno de ellos; los demás hablantes no se ven afectados.
- `message` (string, required) — Descripción legible de la advertencia para mostrar. El texto puede cambiar en cualquier momento, por lo que recomendamos crear ramificaciones según `type`.

### ValidationError

- `loc` (list of ValidationErrorLocItems, required)
- `msg` (string, required)
- `type` (string, required)

### ValidationErrorLocItems

## Examples

**Request**

```json
{
  "file": "<file: <file1>>",
  "reference": "Q3 marketing video",
  "source_language": "en",
  "source_url": "https://example.com/promo.mp4",
  "transcript": "<file: <file1>>"
}
```

**Response**

```json
{
  "project_id": "proj_1601kwkyxp0hfzvtmyxwqxx6mcy3",
  "status": "queued",
  "revision": 0,
  "created_at": "2026-07-03T10:15:30Z",
  "updated_at": "2026-07-03T10:15:30Z",
  "reference": "Q3 marketing video",
  "source_language": "en",
  "model_id": "dubbing_v2",
  "language_ids": [],
  "webhook_ids": [],
  "warnings": []
}
```

**SDK Code**

```python
import requests

url = "https://api.elevenlabs.io/v1/dubbing/project"

files = {
    "file": "open('<file1>', 'rb')",
    "transcript": "open('<file1>', 'rb')"
}
payload = {
    "keyterms": ,
    "model_id": ,
    "reference": "Q3 marketing video",
    "source_language": "en",
    "source_url": "https://example.com/promo.mp4",
    "target_language": ,
    "webhook_ids": 
}

response = requests.post(url, data=payload, files=files)

print(response.json())
```

```javascript
const url = 'https://api.elevenlabs.io/v1/dubbing/project';
const form = new FormData();
form.append('file', '<file1>');
form.append('keyterms', '');
form.append('model_id', '');
form.append('reference', 'Q3 marketing video');
form.append('source_language', 'en');
form.append('source_url', 'https://example.com/promo.mp4');
form.append('target_language', '');
form.append('transcript', '<file1>');
form.append('webhook_ids', '');

const options = {method: 'POST'};

options.body = form;

try {
  const response = await fetch(url, options);
  const data = await response.json();
  console.log(data);
} catch (error) {
  console.error(error);
}
```

```go
package main

import (
	"fmt"
	"strings"
	"net/http"
	"io"
)

func main() {

	url := "https://api.elevenlabs.io/v1/dubbing/project"

	payload := strings.NewReader("-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"file\"; filename=\"<file1>\"\r\nContent-Type: application/octet-stream\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"keyterms\"\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"model_id\"\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"reference\"\r\n\r\nQ3 marketing video\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"source_language\"\r\n\r\nen\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"source_url\"\r\n\r\nhttps://example.com/promo.mp4\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"target_language\"\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"transcript\"; filename=\"<file1>\"\r\nContent-Type: application/octet-stream\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"webhook_ids\"\r\n\r\n\r\n-----011000010111000001101001--\r\n")

	req, _ := http.NewRequest("POST", url, payload)

	res, _ := http.DefaultClient.Do(req)

	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)

	fmt.Println(res)
	fmt.Println(string(body))

}
```

```ruby
require 'uri'
require 'net/http'

url = URI("https://api.elevenlabs.io/v1/dubbing/project")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Post.new(url)
request.body = "-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"file\"; filename=\"<file1>\"\r\nContent-Type: application/octet-stream\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"keyterms\"\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"model_id\"\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"reference\"\r\n\r\nQ3 marketing video\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"source_language\"\r\n\r\nen\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"source_url\"\r\n\r\nhttps://example.com/promo.mp4\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"target_language\"\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"transcript\"; filename=\"<file1>\"\r\nContent-Type: application/octet-stream\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"webhook_ids\"\r\n\r\n\r\n-----011000010111000001101001--\r\n"

response = http.request(request)
puts response.read_body
```

```java
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

HttpResponse<String> response = Unirest.post("https://api.elevenlabs.io/v1/dubbing/project")
  .body("-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"file\"; filename=\"<file1>\"\r\nContent-Type: application/octet-stream\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"keyterms\"\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"model_id\"\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"reference\"\r\n\r\nQ3 marketing video\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"source_language\"\r\n\r\nen\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"source_url\"\r\n\r\nhttps://example.com/promo.mp4\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"target_language\"\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"transcript\"; filename=\"<file1>\"\r\nContent-Type: application/octet-stream\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"webhook_ids\"\r\n\r\n\r\n-----011000010111000001101001--\r\n")
  .asString();
```

```php
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('POST', 'https://api.elevenlabs.io/v1/dubbing/project', [
  'multipart' => [
    [
        'name' => 'file',
        'filename' => '<file1>',
        'contents' => null
    ],
    [
        'name' => 'reference',
        'contents' => 'Q3 marketing video'
    ],
    [
        'name' => 'source_language',
        'contents' => 'en'
    ],
    [
        'name' => 'source_url',
        'contents' => 'https://example.com/promo.mp4'
    ],
    [
        'name' => 'transcript',
        'filename' => '<file1>',
        'contents' => null
    ]
  ]
]);

echo $response->getBody();
```

```csharp
using RestSharp;

var client = new RestClient("https://api.elevenlabs.io/v1/dubbing/project");
var request = new RestRequest(Method.POST);
request.AddParameter("undefined", "-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"file\"; filename=\"<file1>\"\r\nContent-Type: application/octet-stream\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"keyterms\"\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"model_id\"\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"reference\"\r\n\r\nQ3 marketing video\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"source_language\"\r\n\r\nen\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"source_url\"\r\n\r\nhttps://example.com/promo.mp4\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"target_language\"\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"transcript\"; filename=\"<file1>\"\r\nContent-Type: application/octet-stream\r\n\r\n\r\n-----011000010111000001101001\r\nContent-Disposition: form-data; name=\"webhook_ids\"\r\n\r\n\r\n-----011000010111000001101001--\r\n", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
```

```swift
import Foundation
let parameters = [
  [
    "name": "file",
    "fileName": "<file1>"
  ],
  [
    "name": "keyterms",
    "value": 
  ],
  [
    "name": "model_id",
    "value": 
  ],
  [
    "name": "reference",
    "value": "Q3 marketing video"
  ],
  [
    "name": "source_language",
    "value": "en"
  ],
  [
    "name": "source_url",
    "value": "https://example.com/promo.mp4"
  ],
  [
    "name": "target_language",
    "value": 
  ],
  [
    "name": "transcript",
    "fileName": "<file1>"
  ],
  [
    "name": "webhook_ids",
    "value": 
  ]
]

let boundary = "---011000010111000001101001"

var body = ""
var error: NSError? = nil
for param in parameters {
  let paramName = param["name"]!
  body += "--\(boundary)\r\n"
  body += "Content-Disposition:form-data; name=\"\(paramName)\""
  if let filename = param["fileName"] {
    let contentType = param["content-type"]!
    let fileContent = String(contentsOfFile: filename, encoding: String.Encoding.utf8)
    if (error != nil) {
      print(error as Any)
    }
    body += "; filename=\"\(filename)\"\r\n"
    body += "Content-Type: \(contentType)\r\n\r\n"
    body += fileContent
  } else if let paramValue = param["value"] {
    body += "\r\n\r\n\(paramValue)"
  }
}

let request = NSMutableURLRequest(url: NSURL(string: "https://api.elevenlabs.io/v1/dubbing/project")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "POST"
request.httpBody = postData as Data

let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
  if (error != nil) {
    print(error as Any)
  } else {
    let httpResponse = response as? HTTPURLResponse
    print(httpResponse)
  }
})

dataTask.resume()
```