# Errores

> Identifica cada error de la API y de la transcripción. Revisa sus campos y cuándo tiene sentido reintentar.

Canonical: https://transcript1.com/es/docs/errors
Language: es
Last updated: 2026-11-05

Hay dos casos distintos: la API puede rechazar tu request, o puede aceptarlo y fallar más adelante al transcribir. En este último caso, el objeto de transcripción termina con `status` en `failed`.

## Cómo leer un error

Cuando `/v1` rechaza un request, la respuesta tiene esta estructura:

```json
{
  "error": {
    "code": "insufficient_minutes",
    "message": "Not enough minutes",
    "retryable": false,
    "action_url": "https://transcript1.com/dashboard/billing",
    "minutes_needed": 20,
    "minutes_remaining": 3
  }
}
```

Usa `code` para decidir qué debe hacer tu aplicación y `message` para mostrar la explicación al usuario. No dependas del texto de `message`: puede cambiar. Si `retryable` es `true`, puedes volver a enviar el mismo request más adelante.

Según el error, encontrarás otros campos junto a `retryable`:

| Campo | Aparece en | Qué indica |
|---|---|---|
| `action_url` | `insufficient_minutes`, `no_active_plan`, `topup_needs_user` | Enlace para contratar un plan o comprar minutos. |
| `minutes_needed`, `minutes_remaining` | `insufficient_minutes` | Minutos necesarios para el request y saldo disponible. El primero es `null` si aún no se sabe cuántos minutos necesita. |
| `reason`, `packs` | `topup_needs_user` | Por qué no se cobró a la tarjeta y cuántos paquetes se pidieron. |
| `supported_platforms` | `unsupported_platform` | Valores de plataforma admitidos: `["youtube", "x", "tiktok", "instagram", "facebook", "bluesky", "twitch", "dailymotion", "pinterest", "linkedin", "snapchat"]`. |
| `missing_chunks` | `upload_incomplete` | Índices de las partes del archivo que faltan por recibir. |
| `max_bytes` | `media_too_large` | Tamaño máximo de archivo que puedes enviar, en bytes. |
| `params` | `invalid_request` | Objeto que detalla el problema de cada campo al validar el cuerpo o los parámetros de la URL. |

## Cuando la API rechaza el request

| Código HTTP | `code` | ¿Reintentar? | Qué ocurrió |
|---|---|---|---|
| 400, 422 | `invalid_request` | No | Falta un campo o parámetro, su valor no es válido o el cuerpo no es JSON válido. También ocurre al combinar `diarize` con `source: "captions"`, o `reuse_recent` con `webhook_url`. |
| 422 | `invalid_url` | No | El enlace no se admite o no corresponde a `platform`. Usa YouTube, X, TikTok, Instagram, Facebook, Bluesky u otra plataforma de [Fuentes y opciones](https://transcript1.com/es/docs/sources-and-options). |
| 422 | `unsupported_platform` | No | El valor de `platform` no está entre los admitidos. |
| 422 | `unsupported_media` | No | La extensión del archivo no está admitida. |
| 401 | `unauthorized` | No | Falta la credencial, no es válida, venció o se revocó. También puede indicar que el token de subida no es válido o venció. |
| 403 | `insufficient_scope` | No | El token OAuth no tiene el permiso `transcriptions:read` o `transcriptions:write` necesario. |
| 403 | `email_not_verified` | No | Debes verificar tu correo antes de crear transcripciones o sesiones en vivo. |
| 402 | `insufficient_minutes` | No | Tu saldo disponible es 0, no alcanza para esta transcripción o es menor que un minuto iniciado de una sesión en vivo. Si la [recarga automática](https://transcript1.com/es/docs/billing-and-limits#auto-top-up) está activada, transcript1 intenta recargar primero. Compra minutos en `action_url`, o deja que un agente los compre con `POST /v1/topups` o la herramienta MCP `top_up`. |
| 402 | `no_active_plan` | No | No puedes comprar una recarga sin un plan de pago activo. Este error viene de `POST /v1/topups` y de los endpoints de facturación del panel, no de los endpoints de transcripción. |
| 402 | `topup_needs_user` | Solo con `pending` e `in_progress` | `POST /v1/topups` no cobró a la tarjeta. `reason` explica por qué: `not_allowed` (la credencial no puede comprar recargas o su persona no es admin del equipo), `cap_reached` (el límite mensual para agentes no tiene margen), `card_declined`, `authentication_required` o `no_card`. La persona puede comprar los paquetes en `action_url`. Con `pending` (el pago aún no se confirma) e `in_progress` (hay otra recarga en curso), el cobro todavía puede completarse: reintenta más tarde con el mismo `Idempotency-Key` en lugar de mandar a la persona a comprar. |
| 404 | `not_found` | No | No existe esa transcripción o es de otro equipo. |
| 409 | `upload_incomplete` | No | Faltan partes del archivo. Envíalas y vuelve a confirmar la subida. |
| 409 | `invalid_state` | No | La transcripción ya no espera una subida. No puedes enviar más partes ni confirmar que terminaste. |
| 409 | `session_ended` | No | La sesión en vivo ya terminó, así que `POST /v1/live/sessions/:id/token` no puede emitir un token. También llega como evento `error` por WebSocket. |
| 422 | `unsupported_language` | No | El `language` de la sesión en vivo no está admitido. |
| 422 | `unsupported_translation` | No | El idioma `translate_to` de la sesión en vivo no está admitido, o la traducción en vivo no está disponible. |
| 409 | `idempotency_conflict` | No | Usaste antes el mismo `Idempotency-Key` con parámetros diferentes. |
| 413 | `media_too_large` | No | El archivo pesa más de lo permitido. Revisa [Cómo subir archivos](https://transcript1.com/es/docs/uploads). |
| 413 | `invalid_request` | No | El cuerpo JSON supera 1 MB. Para archivos demasiado grandes, el código es `media_too_large`. |
| 429 | `rate_limited` | Sí | Superaste los requests por minuto. Espera el tiempo en segundos que indica `Retry-After`. |
| 429 | `too_many_active_jobs` | Sí | Llegaste al límite de transcripciones en curso o de subidas abiertas. Espera los segundos indicados en `Retry-After`. |
| 429 | `too_many_live_sessions` | Sí | Ya usas todas las sesiones en vivo simultáneas de tu plan. Espera los segundos indicados en `Retry-After` (30). |
| 500 | `internal_error` | Sí | Falló algo en transcript1. Espera un momento y vuelve a intentarlo. |
| 503 | `service_unavailable` | Sí | El servicio no está disponible por el momento. Prueba de nuevo más tarde. |
| 503 | `live_capacity` | Sí | Toda la capacidad en vivo está ocupada. Espera los segundos indicados en `Retry-After` (30) y vuelve a crear la sesión. |
| 503 | `live_unavailable` | No | La transcripción en vivo no está disponible por ahora. |

Si el navegador se autentica con una cookie de sesión en lugar de una credencial bearer, también se comprueba el origen. Un request desde otro sitio devuelve `403 forbidden_origin`. Esta comprobación no afecta a las llamadas que usan el header `Authorization`.

El header `Retry-After` aparece en todas las respuestas `429` e indica cuántos segundos debes esperar. Puedes consultar los límites de tu plan en [Facturación y límites](https://transcript1.com/es/docs/billing-and-limits).

## Cuándo volver a intentarlo

- Reenvía el request solo si `retryable` es `true`: `rate_limited`, `too_many_active_jobs`, `too_many_live_sessions`, `live_capacity`, `internal_error`, `service_unavailable`, y `topup_needs_user` con `reason` `pending` o `in_progress`. Si hay `Retry-After`, respétalo. Si no, aumenta la espera entre intentos.
- Si repites `POST /v1/transcriptions` o `POST /v1/topups`, conserva el mismo header `Idempotency-Key`. Así no pagas dos veces si el primer request sí se completó.
- Para los demás códigos, primero corrige lo que causó el error.

## Transcripción en vivo

`POST /v1/live/sessions` y los demás endpoints en vivo usan el mismo formato de error. A ellos también se aplican `invalid_request`, `unsupported_language`, `insufficient_minutes` y `email_not_verified`, junto con los códigos en vivo de la tabla anterior. Crear una sesión no es idempotente, así que reintentar tras `too_many_live_sessions` o `live_capacity` crea una sesión nueva.

Una vez que la sesión existe, los problemas llegan por el WebSocket como eventos `error` y códigos de cierre, no como errores HTTP. Consulta todos los eventos en [Transcripción en vivo](https://transcript1.com/es/docs/live#websocket-protocol).

| Código de cierre | Significado |
|---|---|
| `1000` | Cierre normal, después de `session.ended`. |
| `1011` | Error inesperado del servidor. Reanuda con un token nuevo. |
| `1012` | Reinicio del servidor, después de `reconnect`. Reanuda con un token nuevo. |
| `4001` | Token no válido, vencido o ya usado. |
| `4004` | La sesión no existe o ya terminó. |
| `4008` | Violación del protocolo: un fragmento de audio de longitud impar o demasiado grande. |
| `4010` | Reemplazada por una conexión más nueva a la misma sesión. |

Una sesión en vivo que termina por un motivo como `balance_exhausted` o `idle_timeout` no es un error: envía `session.ended` con el motivo del final y se guarda. Consulta [Motivos de finalización](https://transcript1.com/es/docs/live#end-reasons).

## Cuando falla la transcripción

Una transcripción puede fallar después de que la API haya respondido al request de creación. Si `status` es `failed`, encontrarás el motivo en `error: { "code", "message" }`. Comprueba `error` al consultar el estado o al recibir el [webhook](https://transcript1.com/es/docs/webhooks) `transcription.failed`. Si una traducción falla, se envía el webhook `transcription.translation.failed` y la transcripción nunca falla por ello.

| `error.code` | Qué ocurrió | ¿Qué puedes hacer? |
|---|---|---|
| `media_unavailable` | El video no existe o dejó de estar disponible. | No repitas el mismo envío; revisa la URL. |
| `media_private` | No se puede acceder porque el video es privado. | Usa una publicación pública o, en YouTube, un video público o no listado. |
| `login_required` | Hay que iniciar sesión en la plataforma para ver el video. | Es un fallo permanente; no se reintenta. |
| `no_audio` | El video no contiene una pista de audio. | Es un fallo permanente; no se reintenta. |
| `age_restricted` | La plataforma restringe el video por edad. | No repitas el enlace; sube el archivo. |
| `live_stream` | La transmisión sigue en vivo o todavía no empieza. | Espera a que termine para volver a enviarla. |
| `no_captions` | Pediste `captions` en `source`, pero no hay una pista de subtítulos que se pueda usar. | Cambia a `source: "auto"` o `"stt"`. |
| `media_too_long` | La grabación supera las 5 horas que admite voz a texto. | Divide la grabación antes de enviarla. |
| `unsupported_media` | No se puede leer el archivo o le falta una pista de audio. | Envía un archivo en un formato admitido. |
| `no_speech` | No se detectó habla. | No lo reintentes. |
| `unsupported_language` | El idioma de la grabación no está admitido. | Configura `language` con un código admitido o `"auto"` antes de volver a enviarla. |
| `insufficient_minutes` | El saldo se agotó antes de cobrar la transcripción y la recarga automática, si estaba activada, no pudo añadir más minutos. | Después de recargar minutos. |
| `fetch_failed` | No se pudo descargar la grabación después de varios intentos. | Puedes probar de nuevo más tarde. |
| `transcription_failed` | La transcripción de voz a texto falló después de varios intentos. | Puedes probar de nuevo más tarde. |

Si la transcripción falla o la cancelas, no pagas nada. Si ya se habían descontado minutos, vuelven a tu saldo.
