# Bandas sonoras

> GET /3/movie/{movie_id}/soundtracks y GET /3/tv/{tv_id}/soundtracks devuelven el álbum de banda sonora de un título en una lista results. Cada álbum trae fuente, nombre, artista, fecha de lanzamiento, enlace y una lista tracks con disco, número, título, artista y duración. Añade append_to_response=soundtracks para incorporarlo a los detalles.

## Endpoint

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

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

Respuesta:

```json
{
  "id": 155,
  "results": [
    {
      "source": "musicbrainz",
      "album": "The Dark Knight",
      "artist": "Hans Zimmer & James Newton Howard",
      "released": "2008-07-15",
      "url": "https://musicbrainz.org/release/814b2f7b-c27c-451e-abac-a316d2e6cea9",
      "track_count": 14,
      "tracks": [
        {
          "disc": 1,
          "number": 1,
          "title": "Why So Serious?",
          "artist": "Hans Zimmer",
          "duration_ms": 554000
        },
        {
          "disc": 1,
          "number": 2,
          "title": "I'm Not a Hero",
          "artist": "Hans Zimmer",
          "duration_ms": 395000
        },
        {
          "disc": 1,
          "number": 3,
          "title": "Harvey Two-Face",
          "artist": "James Newton Howard",
          "duration_ms": 377000
        }
      ]
    }
  ]
}
```

## Obtén la banda sonora de una película

`GET /3/movie/{movie_id}/soundtracks` devuelve el álbum de banda sonora de una película. La respuesta incluye el `id` de la película y un array `results`. Cada entrada es un álbum con sus datos y una lista `tracks`.

El ejemplo carga The Dark Knight (id 155) e imprime el álbum y una línea por pista.

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

```js
const res = await fetch('https://api.amodb.dev/3/movie/155/soundtracks', {
  headers: { Authorization: `Bearer ${process.env.AMODB_KEY}` },
});
if (!res.ok) throw new Error(`amodb returned ${res.status}`);
const { results } = await res.json();
if (results.length === 0) console.log('no soundtrack album known');
for (const album of results) {
  console.log(`${album.album} by ${album.artist} (${album.track_count} tracks)`);
  for (const t of album.tracks) {
    console.log(`${t.number}. ${t.title} by ${t.artist}`);
  }
}
```

```python
import os
import requests

r = requests.get(
    "https://api.amodb.dev/3/movie/155/soundtracks",
    headers={"Authorization": f"Bearer {os.environ['AMODB_KEY']}"},
    timeout=10,
)
r.raise_for_status()
results = r.json()["results"]
if not results:
    print("no soundtrack album known")
for album in results:
    print(f"{album['album']} by {album['artist']} ({album['track_count']} tracks)")
    for t in album["tracks"]:
        print(f"{t['number']}. {t['title']} by {t['artist']}")
```

```php
<?php
$ch = curl_init('https://api.amodb.dev/3/movie/155/soundtracks');
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");
}
$results = json_decode($body, true)['results'];
if (!$results) {
    echo 'no soundtrack album known', PHP_EOL;
}
foreach ($results as $album) {
    echo $album['album'], ' by ', $album['artist'] ?? 'unknown', ' (', $album['track_count'], ' tracks)', PHP_EOL;
    foreach ($album['tracks'] as $t) {
        echo $t['number'], '. ', $t['title'], ' by ', $t['artist'], PHP_EOL;
    }
}
```

```go
package main

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

type Track struct {
	Disc       int    `json:"disc"`
	Number     int    `json:"number"`
	Title      string `json:"title"`
	Artist     string `json:"artist"`
	DurationMs int    `json:"duration_ms"`
}

type Album struct {
	Source     string  `json:"source"`
	Album      string  `json:"album"`
	Artist     string  `json:"artist"`
	Released   string  `json:"released"`
	URL        string  `json:"url"`
	TrackCount int     `json:"track_count"`
	Tracks     []Track `json:"tracks"`
}

func main() {
	req, _ := http.NewRequest("GET", "https://api.amodb.dev/3/movie/155/soundtracks", 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 body struct {
		Results []Album `json:"results"`
	}
	if err := json.NewDecoder(res.Body).Decode(&body); err != nil {
		panic(err)
	}
	if len(body.Results) == 0 {
		fmt.Println("no soundtrack album known")
	}
	for _, a := range body.Results {
		fmt.Printf("%s by %s (%d tracks)\n", a.Album, a.Artist, a.TrackCount)
		for _, t := range a.Tracks {
			fmt.Printf("%d. %s by %s\n", t.Number, t.Title, t.Artist)
		}
	}
}
```

### Parámetros

| Parámetro  | En       | Obligatorio    | Descripción                                                 |
| ---------- | -------- | -------------- | ----------------------------------------------------------- |
| `movie_id` | ruta     | sí             | ID numérico de la película, por ejemplo `155`.              |
| `api_key`  | consulta | uno de los dos | Tu clave. Usa esta o el encabezado `Authorization: Bearer`. |

### Campos de la respuesta

| Campo                            | Tipo         | Notas                                                                          |
| -------------------------------- | ------------ | ------------------------------------------------------------------------------ |
| `id`                             | entero       | ID de la película. No aparece cuando usas `append_to_response`.                |
| `results`                        | array        | Álbumes. Vacío cuando no se conoce ningún álbum. Hoy contiene como máximo uno. |
| `results[].source`               | texto        | De dónde viene el álbum: `musicbrainz` o `deezer`.                             |
| `results[].album`                | texto        | Título del álbum.                                                              |
| `results[].artist`               | texto o null | Artista del álbum, por ejemplo `Hans Zimmer & James Newton Howard`.            |
| `results[].released`             | texto o null | Fecha de lanzamiento como `YYYY-MM-DD`.                                        |
| `results[].url`                  | texto o null | Enlace a la página del álbum en la fuente.                                     |
| `results[].track_count`          | entero       | Número de pistas del álbum.                                                    |
| `results[].tracks`               | array        | Pistas en el orden del álbum.                                                  |
| `results[].tracks[].disc`        | entero       | Número de disco, a partir de 1.                                                |
| `results[].tracks[].number`      | entero       | Número de pista en el disco.                                                   |
| `results[].tracks[].title`       | texto        | Título de la pista.                                                            |
| `results[].tracks[].artist`      | texto        | Artista de la pista.                                                           |
| `results[].tracks[].duration_ms` | entero       | Duración en milisegundos.                                                      |

Lee por nombre las claves que uses e ignora las demás.

### Ejemplo de respuesta

```json
{
  "id": 155,
  "results": [
    {
      "source": "musicbrainz",
      "album": "The Dark Knight",
      "artist": "Hans Zimmer & James Newton Howard",
      "released": "2008-07-15",
      "url": "https://musicbrainz.org/release/814b2f7b-c27c-451e-abac-a316d2e6cea9",
      "track_count": 14,
      "tracks": [
        { "disc": 1, "number": 1, "title": "Why So Serious?", "artist": "Hans Zimmer", "duration_ms": 554000 },
        { "disc": 1, "number": 2, "title": "I'm Not a Hero", "artist": "Hans Zimmer", "duration_ms": 395000 },
        { "disc": 1, "number": 3, "title": "Harvey Two-Face", "artist": "James Newton Howard", "duration_ms": 377000 }
      ]
    }
  ]
}
```

La lista de pistas se recortó a 3 de 14. Un título sin álbum conocido, como Fight Club (id 550), responde con una lista vacía:

```json
{
  "id": 550,
  "results": []
}
```

## Obtén la banda sonora de una serie

`GET /3/tv/{tv_id}/soundtracks` devuelve la misma estructura para una serie. Pasa el id de la serie, por ejemplo `1396`. Breaking Bad no tiene ningún álbum conocido, así que su array `results` está vacío.

| Método y ruta                       | Devuelve                                | Parámetros                                   |
| ----------------------------------- | --------------------------------------- | -------------------------------------------- |
| `GET /movie/{movie_id}/soundtracks` | `id` y `results`                        | `movie_id`                                   |
| `GET /tv/{tv_id}/soundtracks`       | `id` y `results`                        | `tv_id`                                      |
| `append_to_response=soundtracks`    | Los mismos `results` bajo `soundtracks` | Se añade a los detalles de películas o de TV |

Para obtener el álbum mientras cargas la página de una película, añádelo a los detalles:

```bash
curl -sf "https://api.amodb.dev/3/movie/155?append_to_response=credits,soundtracks" \
  -H "Authorization: Bearer $AMODB_KEY"
```

El bloque añadido queda bajo la clave `soundtracks` del registro. Contiene `results` y no tiene `id` propio. Cuenta como una sola solicitud.

## Crea una lista de música de la película

Ordena por `disc` y `number`, muestra el título y el artista, y oculta el bloque cuando `results` esté vacío. Las funciones siguientes devuelven líneas de texto plano que puedes colocar en un elemento de lista.

```js
function clock(ms) {
  const s = Math.round(ms / 1000);
  return `${Math.floor(s / 60)}:${String(s % 60).padStart(2, '0')}`;
}

function musicLines(results) {
  const album = results[0];
  if (!album) return [];
  return [...album.tracks]
    .sort((a, b) => a.disc - b.disc || a.number - b.number)
    .map((t) => `${t.title} by ${t.artist} (${clock(t.duration_ms)})`);
}
```

Algunas ideas de interfaz que no necesitan datos adicionales:

| Idea                 | Cómo                                                                                            |
| -------------------- | ----------------------------------------------------------------------------------------------- |
| Lista numerada       | Usa `number` como número de la lista y agrupa por `disc` cuando haya varios discos.             |
| Enlace al álbum      | Enlaza el nombre del álbum con `url` cuando no sea null.                                        |
| Duración total       | Suma `duration_ms` de todas las pistas.                                                         |
| Combinación con mood | Muestra la lista junto a los [medidores de mood](https://amodb.dev/es/moods/) del mismo título. |

## Errores

Todo fallo devuelve `success` en false con un `status_code` numérico, como hace TMDB.

| HTTP | status_code | Cuándo                                                                                |
| ---- | ----------- | ------------------------------------------------------------------------------------- |
| 401  | 7           | Falta la clave o es incorrecta.                                                       |
| 402  | 36          | El periodo del plan ha terminado.                                                     |
| 429  | 25          | Superaste tus solicitudes por minuto. Espera los segundos indicados en `Retry-After`. |

El endpoint de soundtracks no responde 404 ante un id desconocido. Responde 200 con un array `results` vacío. Cuando se añade a los detalles, un id desconocido da un 404 en la llamada de detalles. Consulta [errores](https://amodb.dev/es/errors/) para ver todos los códigos y [límites de solicitudes](https://amodb.dev/es/rate-limits/) para los encabezados.

## Notas prácticas

- Como los demás datos de detalles, las bandas sonoras se guardan en la caché perimetral 6 horas. Una caché de cliente más corta no aporta nada.
- Usa `append_to_response=soundtracks` en una página de detalles que ya cargas. Ahorra una solicitud de tus 20, 40 o 120 solicitudes por minuto.
- No des por hecho que existe un álbum. Oculta el bloque de música cuando `results` esté vacío.
- Algunos álbumes vienen de MusicBrainz y otros de Deezer. La película 27205 (Inception) tiene un álbum de Deezer. La estructura es la misma, así que comprueba `source` solo si lo muestras.
- Los nombres de pistas y artistas son textos simples y pueden contener cualquier carácter. Guárdalos como UTF-8 y escápalos al colocarlos en HTML.
- Para el tráiler del mismo título, consulta [vídeos y tráilers](https://amodb.dev/es/videos-trailers/).

## Preguntas y respuestas

### ¿Qué contiene una entrada de banda sonora?

Un objeto de álbum. Trae la fuente, el nombre del álbum, el artista, la fecha de lanzamiento, un enlace y track_count. Su array tracks lista cada pista con disc, number, title, artist y duration_ms. La respuesta también incluye el id del título.

### ¿Obtengo archivos de audio o enlaces de streaming?

No hay audio. El campo url enlaza a la página del álbum en MusicBrainz o Deezer, y puede ser null. Para que los usuarios escuchen, busca el álbum en el servicio de música que ya uses y ábrelo desde tu propia interfaz.

### ¿Hay banda sonora para todos los títulos?

No. Muchos títulos, Fight Club entre ellos, no tienen ningún álbum conocido, y la respuesta es un array results vacío. Hoy un título tiene como máximo un álbum. Diseña el bloque de música para que se oculte cuando no haya nada que mostrar.

### ¿Puedo obtener la banda sonora de una serie?

Sí. Llama a GET /3/tv/{tv_id}/soundtracks con el id de la serie. La respuesta tiene la misma estructura que la del endpoint de películas, así que un solo parser cubre ambos.

## 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.
- [Medidores de mood](https://amodb.dev/es/moods/): API de moods con medidores de 0 a 10 por título. Lee los moods de una película o serie, únelos con append_to_response=moods y crea insignias o filtros.
- [API de vídeos y tráilers](https://amodb.dev/es/videos-trailers/): API de vídeos de películas con rutas TMDB v3: lista tráilers, teasers, clips y reportajes de una película o serie, y filtra por tipo e idioma en tu código.
- [Puntuaciones de películas y series](https://amodb.dev/es/ratings/): API de puntuaciones de películas: IMDb, Kinopoisk, Metacritic, Rotten Tomatoes y TMDB de un título en una sola llamada, con null si falta una fuente.
- [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/soundtracks/
