# Cómo subir archivos

> Sube hasta 95 MB en un request. Para archivos de hasta 2 GB, envíalos por partes y continúa la subida si se interrumpe.

Canonical: https://transcript1.com/es/docs/uploads
Language: es
Last updated: 2026-10-14

Si tienes un archivo de audio o video, súbelo para transcribirlo con IA. Los archivos solo aceptan `auto` o `stt` en `source`. Para configurar `language` y `diarize`, revisa [Fuentes y opciones](https://transcript1.com/es/docs/sources-and-options).

## Formatos y tamaños admitidos

Comprueba la extensión antes de subir el archivo. Debe ser `mp3`, `wav`, `m4a`, `flac`, `ogg`, `opus`, `mp4`, `mov`, `webm` o `mkv`; cualquier otra devuelve `422 unsupported_media`. También necesita una pista de audio. Si no la tiene, la transcripción falla con `unsupported_media`.

| Tipo de subida o límite | Máximo |
|---|---|
| Archivo completo en un request (`multipart/form-data`) | 95 MB |
| Archivo enviado por partes | 2 GB (2,000,000,000 bytes), o menos según tu plan. |
| Subidas por partes que un equipo puede tener abiertas | 20 |

Si el archivo pesa más de lo permitido, recibirás `413 media_too_large`. El campo `max_bytes` del error indica tu límite.

## Sube el archivo en un request

Hasta 95 MB, basta con un request `multipart/form-data` a `POST /v1/transcriptions`. Adjunta el archivo en la parte `file`. Si los necesitas, agrega estos campos al formulario: `language`, `diarize` (`true` o `false`), `source` (`auto` o `stt`) y `webhook_url`.

```bash
curl -X POST "https://api.transcript1.com/v1/transcriptions?wait=60" \
  -H "Authorization: Bearer $TRANSCRIPT1_API_KEY" \
  -F file=@interview.m4a \
  -F language=en \
  -F diarize=true
```

Recibirás el objeto de transcripción con `source.platform` en `upload`. Igual que al enviar un enlace, el código HTTP es `202` mientras sigue en proceso y `200` cuando llega a un estado final. Si envías un archivo vacío, recibirás `422 invalid_request`.

## Sube archivos grandes por partes

Para archivos grandes, envía cada parte por separado. Así no tienes que empezar de nuevo si se corta la conexión. El proceso tiene cuatro pasos.

### 1. Reserva la subida

Primero envía un JSON con el nombre y el tamaño del archivo. Puedes incluir `mime_type`, pero no es obligatorio. Usa el header `Idempotency-Key` para que, si repites este request, no se cree otra transcripción:

```bash
curl -X POST "https://api.transcript1.com/v1/transcriptions" \
  -H "Authorization: Bearer $TRANSCRIPT1_API_KEY" \
  -H "Idempotency-Key: interview-2026-10-13" \
  -H "Content-Type: application/json" \
  -d '{"upload":{"filename":"interview.m4a","size":48210334,"mime_type":"audio/mp4"},"language":"auto","diarize":true}'
```

La API responde con `201`, deja la transcripción en `awaiting_upload` e incluye los datos para subirla en `upload`:

```json
{
  "id": "tr_8fK2Lm0PqRsTuVwXyZaBcD",
  "object": "transcription",
  "status": "awaiting_upload",
  "upload": {
    "chunk_url_template": "https://api.transcript1.com/v1/transcriptions/tr_8fK2Lm0PqRsTuVwXyZaBcD/upload/chunks/{index}",
    "headers": { "X-Upload-Token": "t1u_..." },
    "expires_at": "2026-10-13T10:30:00.000Z",
    "chunks": [
      { "index": 0, "offset": 0, "size": 8388608 },
      { "index": 1, "offset": 8388608, "size": 8388608 }
    ]
  }
}
```

El servidor divide el archivo en partes de unos 8 MiB (8,388,608 bytes) y te indica cuáles enviar en `chunks`; la lista del ejemplo está abreviada. El token `X-Upload-Token` es secreto, sirve solo para esta subida y vence al cabo de 1 hora. Consulta su vencimiento en `expires_at`.

### 2. Envía las partes

Por cada parte, haz un `PUT` a `chunk_url_template` y sustituye `{index}` por su `index`. Lee el archivo desde `offset` y envía exactamente `size` bytes en el cuerpo, con `application/octet-stream`. Para autenticar este request usa el header `X-Upload-Token`, sin `Authorization`.

```bash
curl -X PUT "https://api.transcript1.com/v1/transcriptions/tr_8fK2Lm0PqRsTuVwXyZaBcD/upload/chunks/0" \
  -H "X-Upload-Token: t1u_..." \
  -H "Content-Type: application/octet-stream" \
  --data-binary @chunk-0.bin
```

Al recibir una parte, la API responde con `{ "object": "upload_chunk", "index": 0, "size": 8388608 }`. Puedes enviarla de nuevo: reemplazará la anterior. Si su tamaño no coincide o el índice no está en la lista prevista, recibirás `422 invalid_request`. Si falta el token o ya venció, recibirás `401 unauthorized`.

### 3. Continúa una subida interrumpida

Consulta `GET /v1/transcriptions/:id/upload` para saber qué partes recibió el servidor:

```json
{
  "object": "upload",
  "status": "awaiting_upload",
  "total_bytes": 48210334,
  "uploaded_bytes": 16777216,
  "received_chunks": [0, 1],
  "chunks": [ { "index": 0, "offset": 0, "size": 8388608 } ],
  "expires_at": "2026-10-13T10:30:00.000Z"
}
```

Compara la lista prevista con `received_chunks` y envía solo las partes que falten. Si el token ya venció, repite el request del paso 1 con el mismo `Idempotency-Key` y los mismos parámetros. Obtendrás la misma transcripción y un nuevo token para continuar.

### 4. Confirma que terminaste

```bash
curl -X POST "https://api.transcript1.com/v1/transcriptions/tr_8fK2Lm0PqRsTuVwXyZaBcD/upload/complete" \
  -H "Authorization: Bearer $TRANSCRIPT1_API_KEY"
```

Con `POST /v1/transcriptions/:id/upload/complete`, el servidor comprueba que llegaron todas las partes con el tamaño previsto, une el archivo y pone la transcripción en cola. La respuesta es `202` e incluye el objeto de transcripción.

Si faltan partes, recibirás `409 upload_incomplete`: `missing_chunks` contiene los índices que debes volver a enviar. Si la subida ya terminó o la cancelaste, recibirás `409 invalid_state`. Una vez confirmada, consulta el progreso con `GET /v1/transcriptions/:id?wait=60` o espera un [webhook](https://transcript1.com/es/docs/webhooks).

### Ejemplo completo en Python

```python
import os
import requests

API = "https://api.transcript1.com"
auth = {"Authorization": f"Bearer {os.environ['TRANSCRIPT1_API_KEY']}"}
path = "interview.m4a"

created = requests.post(
    f"{API}/v1/transcriptions",
    headers={**auth, "Idempotency-Key": "interview-2026-10-13"},
    json={"upload": {"filename": os.path.basename(path), "size": os.path.getsize(path)}},
)
created.raise_for_status()
transcription = created.json()
upload = transcription["upload"]

with open(path, "rb") as file:
    for chunk in upload["chunks"]:
        file.seek(chunk["offset"])
        url = upload["chunk_url_template"].replace("{index}", str(chunk["index"]))
        response = requests.put(
            url,
            data=file.read(chunk["size"]),
            headers={**upload["headers"], "Content-Type": "application/octet-stream"},
        )
        response.raise_for_status()

done = requests.post(f"{API}/v1/transcriptions/{transcription['id']}/upload/complete", headers=auth)
done.raise_for_status()
print(done.json()["status"])
```

## Límites y cuánto tiempo se guardan los archivos

- Cada equipo puede tener hasta 20 subidas en `awaiting_upload` al mismo tiempo. Si intentas abrir otra, la API devuelve `429 too_many_active_jobs` con el header `Retry-After`.
- Tienes 24 horas desde la creación para completar la subida. Después se cancela y se borran las partes que enviaste.
- El audio o video se borra 24 horas después de que la transcripción llegue a `completed`, `failed` o `canceled`. El texto se conserva hasta que lo elimines con `DELETE /v1/transcriptions/:id`.
- Si la transcripción falla o la cancelas, no pagas nada. Cuando se conoce la duración del archivo, se cobran los minutos de grabación redondeados hacia arriba. Consulta [Facturación y límites](https://transcript1.com/es/docs/billing-and-limits).
