# API de vídeos y tráilers

> Los endpoints de vídeos listan los tráilers, teasers, clips y reportajes asociados a una película o serie. Cada entrada trae el servidor, una clave de vídeo, un tipo, una marca oficial, un tamaño y una fecha de publicación. Las rutas de temporada y episodio existen pero no devuelven vídeos. Filtra por idioma y tipo en tu código.

## Endpoint

`GET /3/movie/{movie_id}/videos`

```bash
curl "https://api.amodb.dev/3/movie/550/videos" \
  -H "Authorization: Bearer $AMODB_KEY"
```

Respuesta:

```json
{
  "id": 550,
  "results": [
    {
      "iso_639_1": "en",
      "iso_3166_1": "US",
      "name": "Theatrical Trailer (HD Fan Remaster)",
      "key": "6JnN1DmbqoU",
      "site": "YouTube",
      "size": 1080,
      "type": "Trailer",
      "official": false,
      "published_at": "2015-02-26T03:19:25Z",
      "id": "6JnN1DmbqoU"
    },
    {
      "iso_639_1": "en",
      "iso_3166_1": "US",
      "name": "#TBT Trailer",
      "key": "BdJKm16Co6M",
      "site": "YouTube",
      "size": 1080,
      "type": "Trailer",
      "official": true,
      "published_at": "2014-10-02T19:20:22Z",
      "id": "BdJKm16Co6M"
    },
    {
      "iso_639_1": "en",
      "iso_3166_1": "US",
      "name": "20th Anniversary Trailer",
      "key": "dfeUzm6KF4g",
      "site": "YouTube",
      "size": 1080,
      "type": "Trailer",
      "official": true,
      "published_at": "2019-10-15T18:59:47Z",
      "id": "dfeUzm6KF4g"
    }
  ]
}
```

## Obtén los vídeos de una película

`GET /3/movie/{movie_id}/videos` devuelve los registros de vídeo asociados a una película. Un registro son solo metadatos: un nombre, el servidor que sirve el vídeo, la clave del vídeo en ese servidor, un tipo y unas pocas marcas. amodb no devuelve archivos de vídeo.

El ejemplo imprime el primer tráiler oficial en inglés y, si no existe, cualquier tráiler en inglés.

```bash
curl -s "https://api.amodb.dev/3/movie/550/videos" \
  -H "Authorization: Bearer $AMODB_KEY"
```

```js
const url = 'https://api.amodb.dev/3/movie/550/videos';
const res = await fetch(url, { headers: { Authorization: `Bearer ${process.env.AMODB_KEY}` } });
if (!res.ok) throw new Error(`amodb returned ${res.status}`);
const { results } = await res.json();
const trailers = results.filter((v) => v.type === 'Trailer' && v.iso_639_1 === 'en');
const pick = trailers.find((v) => v.official) ?? trailers[0];
console.log(pick ? `${pick.name} (${pick.site}, key ${pick.key})` : 'no trailer');
```

```python
import os
import requests

r = requests.get(
    "https://api.amodb.dev/3/movie/550/videos",
    headers={"Authorization": f"Bearer {os.environ['AMODB_KEY']}"},
    timeout=10,
)
r.raise_for_status()
trailers = [v for v in r.json()["results"] if v["type"] == "Trailer" and v["iso_639_1"] == "en"]
official = [v for v in trailers if v["official"]]
pick = (official or trailers or [None])[0]
print(f"{pick['name']} ({pick['site']}, key {pick['key']})" if pick else "no trailer")
```

```php
<?php
$url = 'https://api.amodb.dev/3/movie/550/videos';
$ch = curl_init($url);
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_TIMEOUT => 10,
    CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('AMODB_KEY')],
]);
$body = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if ($status !== 200) {
    throw new RuntimeException("amodb returned $status");
}
$trailers = array_values(array_filter(
    json_decode($body, true)['results'],
    fn($v) => $v['type'] === 'Trailer' && $v['iso_639_1'] === 'en'
));
$official = array_values(array_filter($trailers, fn($v) => $v['official']));
$pick = $official[0] ?? $trailers[0] ?? null;
echo $pick ? "{$pick['name']} ({$pick['site']}, key {$pick['key']})" : 'no trailer', PHP_EOL;
```

```go
package main

import (
	"encoding/json"
	"fmt"
	"net/http"
	"os"
	"time"
)

type Videos struct {
	Results []struct {
		Name     string `json:"name"`
		Key      string `json:"key"`
		Site     string `json:"site"`
		Type     string `json:"type"`
		Language string `json:"iso_639_1"`
		Official bool   `json:"official"`
	} `json:"results"`
}

func main() {
	url := "https://api.amodb.dev/3/movie/550/videos"
	req, _ := http.NewRequest("GET", url, nil)
	req.Header.Set("Authorization", "Bearer "+os.Getenv("AMODB_KEY"))
	client := &http.Client{Timeout: 10 * time.Second}
	res, err := client.Do(req)
	if err != nil {
		panic(err)
	}
	defer res.Body.Close()
	if res.StatusCode != http.StatusOK {
		panic(res.Status)
	}
	var v Videos
	if err := json.NewDecoder(res.Body).Decode(&v); err != nil {
		panic(err)
	}
	for _, r := range v.Results {
		if r.Type == "Trailer" && r.Language == "en" && r.Official {
			fmt.Printf("%s (%s, key %s)\n", r.Name, r.Site, r.Key)
			return
		}
	}
	fmt.Println("no official trailer")
}
```

### Parámetros

| Parámetro                            | En       | Obligatorio    | Descripción                                                                                                                 |
| ------------------------------------ | -------- | -------------- | --------------------------------------------------------------------------------------------------------------------------- |
| `movie_id`                           | ruta     | sí             | ID numérico de la película, por ejemplo `550`.                                                                              |
| `api_key`                            | consulta | uno de los dos | Tu clave. Usa esta o el encabezado `Authorization: Bearer`.                                                                 |
| `language`, `include_video_language` | consulta | no             | Se aceptan pero se ignoran. La respuesta siempre contiene todos los vídeos del título. Filtra por `iso_639_1` en tu código. |

### Campos de la respuesta

| Campo                                         | Tipo     | Notas                                                                                                    |
| --------------------------------------------- | -------- | -------------------------------------------------------------------------------------------------------- |
| `id`                                          | entero   | El ID de la película.                                                                                    |
| `results`                                     | array    | Registros de vídeo, sin ordenar por tipo ni por fecha. Vacío cuando no se conoce ninguno.                |
| `results[].iso_639_1`, `results[].iso_3166_1` | texto    | Idioma y país del vídeo, por ejemplo `en` y `US`.                                                        |
| `results[].name`                              | texto    | Título del vídeo, por ejemplo `#TBT Trailer`.                                                            |
| `results[].key`                               | texto    | ID del vídeo en ese servidor.                                                                            |
| `results[].site`                              | texto    | Nombre del servidor de vídeo. Hoy siempre `YouTube`.                                                     |
| `results[].size`                              | entero   | Resolución vertical. Hoy siempre `1080`.                                                                 |
| `results[].type`                              | texto    | `Trailer`, `Teaser`, `Clip`, `Featurette`, `Behind the Scenes`, `Bloopers`, `Opening Credits` o `Recap`. |
| `results[].official`                          | booleano | True cuando lo publicó el estudio o el titular de los derechos.                                          |
| `results[].published_at`                      | texto    | Marca de tiempo ISO 8601, con o sin milisegundos.                                                        |
| `results[].id`                                | texto    | ID del registro de vídeo. Igual a `key`.                                                                 |

### Ejemplo de respuesta

Se muestran tres de los 19 registros de la película 550.

```json
{
  "id": 550,
  "results": [
    {
      "iso_639_1": "en",
      "iso_3166_1": "US",
      "name": "Theatrical Trailer (HD Fan Remaster)",
      "key": "6JnN1DmbqoU",
      "site": "YouTube",
      "size": 1080,
      "type": "Trailer",
      "official": false,
      "published_at": "2015-02-26T03:19:25Z",
      "id": "6JnN1DmbqoU"
    },
    {
      "iso_639_1": "en",
      "iso_3166_1": "US",
      "name": "#TBT Trailer",
      "key": "BdJKm16Co6M",
      "site": "YouTube",
      "size": 1080,
      "type": "Trailer",
      "official": true,
      "published_at": "2014-10-02T19:20:22Z",
      "id": "BdJKm16Co6M"
    },
    {
      "iso_639_1": "en",
      "iso_3166_1": "US",
      "name": "Mark Kermode introduces Fight Club | Film4 Interview",
      "key": "tiWCNtGDGEY",
      "site": "YouTube",
      "size": 1080,
      "type": "Featurette",
      "official": true,
      "published_at": "2015-05-08T15:59:05Z",
      "id": "tiWCNtGDGEY"
    }
  ]
}
```

## Tipos de vídeo

El campo `type` te dice qué es un vídeo. Compáralo de forma exacta, con las mayúsculas indicadas.

| Tipo                | Para qué usarlo                                             |
| ------------------- | ----------------------------------------------------------- |
| `Trailer`           | La promoción principal. Muéstralo en una página de detalle. |
| `Teaser`            | Un anuncio corto que llega antes del tráiler.               |
| `Clip`              | Una escena tomada de la película o del episodio terminado.  |
| `Featurette`        | Una pieza breve sobre cómo se hizo el título.               |
| `Behind the Scenes` | Imágenes del rodaje y entrevistas.                          |
| `Bloopers`          | Tomas falsas y recopilaciones de gags.                      |
| `Opening Credits`   | La secuencia de títulos de una serie.                       |
| `Recap`             | Un resumen de episodios anteriores.                         |

Con el tiempo pueden aparecer otros valores, así que trata un `type` desconocido como un extra genérico y no falles por él.

## Elige el vídeo adecuado

Usa el mismo orden para todos los títulos. Prueba tus idiomas en orden. Dentro de un idioma, primero van los tráilers oficiales, luego cualquier tráiler, después los teasers y por último los clips. Dentro de un grupo ordena por `published_at`: el orden ascendente da el primer tráiler y el descendente da el más reciente.

```js
function pickVideo(results, langs = ['en']) {
  const order = ['Trailer', 'Teaser', 'Clip'];
  for (const lang of langs) {
    for (const type of order) {
      const group = results
        .filter((v) => v.iso_639_1 === lang && v.type === type)
        .sort((a, b) => Number(b.official) - Number(a.official) || Date.parse(a.published_at) - Date.parse(b.published_at));
      if (group.length > 0) return group[0];
    }
  }
  return null;
}

// Russian first, English as the fallback.
// const video = pickVideo(results, ['ru', 'en']);
```

## Idiomas

`language` y `include_video_language` no cambian la respuesta, así que una sola llamada te da todos los vídeos del título. Cada registro trae `iso_639_1` e `iso_3166_1`. La película 550 tiene vídeos etiquetados como `fr`, `en`, `es`, `pt`, `it`, `cs`, `pl` y `ru`. Filtra por `iso_639_1` en tu código como se muestra arriba, y luego indica al usuario en qué idioma va a escuchar el vídeo. Un título puede no tener ningún vídeo en el idioma que quieres, así que conserva un respaldo en inglés o en cualquier idioma. Los 14 idiomas que se sirven están en [idiomas](https://amodb.dev/es/languages/).

## Otros endpoints de vídeo

Las rutas siguientes devuelven la misma estructura de `id` y `results`.

| Método y ruta                                                                | Devuelve                          |
| ---------------------------------------------------------------------------- | --------------------------------- |
| `GET /tv/{series_id}/videos`                                                 | Vídeos de una serie.              |
| `GET /tv/{series_id}/season/{season_number}/videos`                          | Siempre un array `results` vacío. |
| `GET /tv/{series_id}/season/{season_number}/episode/{episode_number}/videos` | Siempre un array `results` vacío. |

También puedes añadir `append_to_response=videos` a una llamada de detalles de película o serie. El bloque añadido contiene `results` y no `id`. Las páginas de series y temporadas se describen en [series de TV](https://amodb.dev/es/tv-series/) y [temporadas y episodios](https://amodb.dev/es/tv-seasons-episodes/).

## Errores

| HTTP | status_code | Cuándo                                                                                |
| ---- | ----------- | ------------------------------------------------------------------------------------- |
| 401  | 7           | Falta la clave o es incorrecta.                                                       |
| 402  | 36          | El periodo del plan ha terminado.                                                     |
| 404  | 34          | No existe la temporada o el episodio con ese id, o el id no es un número.             |
| 405  | 37          | Usaste un método de escritura en una ruta de vídeos.                                  |
| 429  | 25          | Superaste tus solicitudes por minuto. Espera los segundos indicados en `Retry-After`. |

Un id de película o serie que no existe no es un error aquí: la ruta de vídeos responde 200 con `"results": []`, igual que un título conocido sin vídeos. La ruta de detalles responde 404 ante un id desconocido. Más información en [errores](https://amodb.dev/es/errors/) y [límites de solicitudes](https://amodb.dev/es/rate-limits/).

## Notas prácticas

- Guarda con el título el `site` y la `key` elegidos, no una dirección completa, para poder cambiar el reproductor más adelante.
- Las listas de vídeos siguen la caché de detalles de 6 horas en la caché perimetral. Una caché de cliente de unas pocas horas encaja con ella.
- `size` es 1080 en todos los registros hoy, así que no te dice qué clip es ligero. Deja que el reproductor elija la calidad.
- No des por hecho que existe un tráiler. Oculta el botón de reproducir cuando tu función de selección devuelva null.
- El orden de `results` no significa nada. Ordena en tu código.
- Para los archivos de póster y de imagen de fondo, consulta [imágenes](https://amodb.dev/es/images-api/). Para la vista del caso de uso, consulta la [API de tráilers de películas](https://amodb.dev/es/movie-trailer-api/).

## Preguntas y respuestas

### ¿Cómo obtengo solo el tráiler oficial?

Filtra el array results por type igual a Trailer y official igual a true. Si quedan varios, ordena por published_at para tomar el más antiguo o el más reciente.

### ¿Cómo obtengo vídeos en mi idioma?

El endpoint devuelve todos los vídeos del título e ignora language e include_video_language. Filtra results por iso_639_1 en tu código, por ejemplo ru primero y en como respaldo. Muchos títulos no tienen vídeo en un idioma concreto.

### ¿Cómo reproduzco un vídeo de la respuesta?

Usa el campo site para elegir el reproductor y el campo key como id del vídeo en ese servidor. En los datos que se sirven hoy site es siempre YouTube. Construye la dirección de inserción o de visionado con el patrón propio de ese servidor. amodb devuelve metadatos, no archivos de vídeo.

### ¿Las temporadas y los episodios tienen sus propios vídeos?

No. Las rutas de vídeos de temporada y episodio responden 200 con un array results vacío. Solo las películas y las series tienen registros de vídeo.

## Páginas relacionadas

- [API de detalles de película](https://amodb.dev/es/movies/): API de detalles de película con rutas y JSON de TMDB v3. Obtén una película por id y añade créditos, puntuaciones y moods con append_to_response, en 14 idiomas.
- [API de series de TV](https://amodb.dev/es/tv-series/): API de series de TV con las mismas rutas y JSON que TMDB v3. Obtén una serie con temporadas, cadenas y próximo episodio, más clasificaciones y plataformas.
- [API de temporadas y episodios de TV](https://amodb.dev/es/tv-seasons-episodes/): API de temporadas y episodios de TV con las mismas rutas y JSON que TMDB v3. Lee una temporada con todos sus episodios, o un episodio con fecha y duración.
- [API de tráilers de películas](https://amodb.dev/es/movie-trailer-api/): API de tráilers de películas en el endpoint de vídeos de TMDB v3. Ordena tráilers, teasers y clips por tipo, indicador oficial e idioma en una solicitud.
- [API de imágenes y host de imágenes](https://amodb.dev/es/images-api/): API de imágenes de películas con rutas TMDB v3: lista pósters, fondos, logos y fotogramas por título y cárgalos desde img.amodb.dev en 10 tamaños sin clave.
- [Inicio rápido](https://amodb.dev/es/quickstart/): Haz tu primera llamada a amodb: consigue una clave, pide los detalles de una película en curl, JavaScript, Python, PHP o Go y carga el póster. En 2 minutos.

Actualizado: 2026-10-18. Source: https://amodb.dev/es/videos-trailers/
