# Medidores de mood

> GET /3/movie/{movie_id}/moods y GET /3/tv/{tv_id}/moods devuelven un source y una lista results. Cada resultado tiene el nombre de un mood, como fear o humor, un avg en una escala de 0 a 10 y los valores que lo respaldan. Añade append_to_response=moods a una llamada de detalles para unir los medidores sin una segunda solicitud.

## Endpoint

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

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

Respuesta:

```json
{
  "id": 155,
  "source": "measured",
  "results": [
    {
      "name": "action",
      "avg": 3.9,
      "values": [
        3.6,
        3.4,
        4.2
      ]
    },
    {
      "name": "fear",
      "avg": 5.2,
      "values": [
        3.6,
        6,
        4.8
      ]
    },
    {
      "name": "humor",
      "avg": 0.9,
      "values": [
        2.4,
        1.8,
        0.4
      ]
    }
  ]
}
```

## Obtener los medidores de mood de una película

`GET /3/movie/{movie_id}/moods` devuelve los medidores de mood (clima emocional) de una película. Un medidor de mood es un nombre y un promedio en una escala de 0 a 10. La respuesta incluye el `id` de la película, un `source` y un array `results`. Cada resultado contiene `name`, `avg` y `values`.

El ejemplo carga los medidores de The Dark Knight (id 155) y los imprime del más fuerte al más débil.

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

```js
const res = await fetch('https://api.amodb.dev/3/movie/155/moods', {
  headers: { Authorization: `Bearer ${process.env.AMODB_KEY}` },
});
if (!res.ok) throw new Error(`amodb returned ${res.status}`);
const { source, results } = await res.json();
console.log('source:', source);
for (const m of [...results].sort((a, b) => b.avg - a.avg)) {
  console.log(m.name.padEnd(10), m.avg);
}
```

```python
import os
import requests

r = requests.get(
    "https://api.amodb.dev/3/movie/155/moods",
    headers={"Authorization": f"Bearer {os.environ['AMODB_KEY']}"},
    timeout=10,
)
r.raise_for_status()
data = r.json()
print("source:", data.get("source"))
for m in sorted(data["results"], key=lambda m: m["avg"], reverse=True):
    print(f"{m['name']:<10} {m['avg']}")
```

```php
<?php
$ch = curl_init('https://api.amodb.dev/3/movie/155/moods');
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");
}
$data = json_decode($body, true);
echo 'source: ', $data['source'] ?? 'none', PHP_EOL;
$results = $data['results'];
usort($results, fn ($a, $b) => $b['avg'] <=> $a['avg']);
foreach ($results as $m) {
    printf("%-10s %.1f\n", $m['name'], $m['avg']);
}
```

```go
package main

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

type Mood struct {
	Name   string    `json:"name"`
	Avg    float64   `json:"avg"`
	Values []float64 `json:"values"`
}

func main() {
	req, _ := http.NewRequest("GET", "https://api.amodb.dev/3/movie/155/moods", 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 {
		Source  string `json:"source"`
		Results []Mood `json:"results"`
	}
	if err := json.NewDecoder(res.Body).Decode(&body); err != nil {
		panic(err)
	}
	fmt.Println("source:", body.Source)
	sort.Slice(body.Results, func(i, j int) bool { return body.Results[i].Avg > body.Results[j].Avg })
	for _, m := range body.Results {
		fmt.Printf("%-10s %.1f\n", m.Name, m.Avg)
	}
}
```

### 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.                                                                                                          |
| `source`           | texto o null     | `measured` para datos de espectadores, `estimated` cuando se deriva de los géneros, `null` cuando el título no tiene datos. |
| `results`          | array            | Medidores de mood ordenados por `name`. Vacío cuando no se sabe nada.                                                       |
| `results[].name`   | texto            | Palabra corta en minúsculas, como `fear`.                                                                                   |
| `results[].avg`    | número           | Media en una escala de 0 a 10. Un decimal en los títulos medidos, un número entero en los estimados.                        |
| `results[].values` | array de números | Hasta 24 lecturas en la misma escala de 0 a 10. Los títulos medidos que hemos visto tienen 6, los estimados tienen 5.       |

Los nombres vistos hoy son `action`, `fear`, `humor`, `pace`, `profanity`, `romance`, `sadness`, `sex` y `violence`. No todos los títulos tienen los nueve, así que muestra los nombres a partir de los datos y no de una lista fija.

### Ejemplo de respuesta

```json
{
  "id": 155,
  "source": "measured",
  "results": [
    { "name": "action", "avg": 3.9, "values": [3.6, 3.4, 4.2, 4.2, 4.8, 3] },
    { "name": "fear", "avg": 5.2, "values": [3.6, 6, 4.8, 6.4, 6.4, 3.8] },
    { "name": "humor", "avg": 0.9, "values": [2.4, 1.8, 0.4, 0.4, 0, 0.5] }
  ]
}
```

La lista se recorta a 3 de los 9 resultados.

### Títulos medidos y estimados

Fight Club (id 550) aún no tiene datos de espectadores, así que sus medidores se derivan de sus géneros. Todos los `avg` son números enteros y `values` tiene 5 entradas.

```json
{
  "id": 550,
  "source": "estimated",
  "results": [
    { "name": "action", "avg": 4, "values": [3, 4, 5, 4, 3] },
    { "name": "fear", "avg": 7, "values": [6, 7, 8, 7, 6] }
  ]
}
```

Revisa `source` si quieres tratar los medidores estimados de forma distinta a los medidos.

## Obtener los medidores de mood de una serie

`GET /3/tv/{tv_id}/moods` tiene la misma forma de respuesta, con el id de la serie en `id`. Para Breaking Bad usa `1396`.

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

```bash
curl -sf "https://api.amodb.dev/3/tv/1396?append_to_response=moods" -H "Authorization: Bearer $AMODB_KEY"
```

Cuando añades `moods` a una llamada de detalles, la clave `moods` queda en el nivel superior del registro, junto a `title` o `name`. Contiene `source` y `results` y no tiene un `id` propio. Cuesta una solicitud, mientras que dos llamadas separadas cuestan dos.

## Cómo leer la escala

El campo `avg` es una intensidad de 0 a 10. Un número más alto significa que el mood es más fuerte en el título.

| Rango   | Lectura                        |
| ------- | ------------------------------ |
| 0 a 2.9 | El mood es débil o no aparece. |
| 3 a 5.9 | El mood está presente.         |
| 6 a 7.9 | El mood es claro.              |
| 8 a 10  | El mood define el título.      |

Los rangos son una sugerencia para tu interfaz, no un campo de la respuesta. El array `values` contiene las lecturas detrás del promedio, en la misma escala.

## Crear insignias y filtros

Los moods encajan en tres patrones habituales de interfaz. Elige umbrales que se ajusten a tu catálogo y afínalos.

| Patrón           | Regla                                                     | Notas                                             |
| ---------------- | --------------------------------------------------------- | ------------------------------------------------- |
| Insignia         | Muestra hasta 3 moods con `avg` de 6 o más                | Ordena primero por `avg`.                         |
| Barra de medidor | Fija el ancho de la barra en `avg` por 10 como porcentaje | La escala es de 0 a 10.                           |
| Chip de filtro   | Coincide con los títulos donde el mood elegido es 7 o más | Obtén los medidores por título y filtra en local. |

```js
function topMoods(results, min = 6, limit = 3) {
  return results
    .filter((m) => m.avg >= min)
    .sort((a, b) => b.avg - a.avg)
    .slice(0, limit)
    .map((m) => m.name);
}

function matchesMood(results, name, min = 7) {
  return results.some((m) => m.name === name && m.avg >= min);
}
```

Un array `results` vacío debe mostrarse como ninguna insignia, no como un error.

## Errores

El cuerpo del error tiene `success`, `status_code` y `status_message`, los mismos campos que usa TMDB.

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

El endpoint de moods no responde 404 ante un id desconocido. Responde 200 con un array `results` vacío, y `source` es `null` o falta. Si se añade a los detalles, un id desconocido produce un 404 de la llamada de detalles. La lista completa está en [errores](https://amodb.dev/es/errors/) y los límites en [límites de solicitudes](https://amodb.dev/es/rate-limits/).

## Notas prácticas

- Como otros datos de detalles, los medidores de mood se guardan en la caché perimetral durante 6 horas. Pedirlos con más frecuencia devuelve el mismo cuerpo.
- Una lista de 20 títulos necesita 20 solicitudes de mood. Si ya llamas a los detalles de cada título, añade `moods` y ahorra la segunda llamada.
- Revisa `source` antes de comparar títulos. Los medidores medidos y estimados usan la misma escala, pero no la misma precisión.
- Guarda `name` y `avg` junto con el id del título en tu propia base de datos si filtras a menudo. Un filtro local es mejor que una solicitud por título.
- Combina los medidores con las [puntuaciones](https://amodb.dev/es/ratings/) para obtener una nota y con las [bandas sonoras](https://amodb.dev/es/soundtracks/) para la música del mismo título.

## Preguntas y respuestas

### ¿Qué significa un valor de mood?

El campo avg es una intensidad en una escala de 0 a 10, con un decimal en los títulos medidos. Un avg de 7 en fear significa que el título da miedo, y 0 significa que el mood no aparece. No es un porcentaje ni una puntuación de reseñas.

### ¿La lista de nombres de mood es fija?

No lo asumas. Los nombres vistos hoy son action, fear, humor, pace, profanity, romance, sadness, sex y violence, y un título puede tener menos de nueve. Muestra las cadenas de nombre que recibas para que un nombre nuevo también aparezca.

### ¿Qué significan measured y estimated en source?

Measured indica que los medidores provienen de datos de espectadores y llevan decimales. Estimated indica que se derivan de los géneros del título, así que avg es un número entero. Un título sin datos tiene un array results vacío y un source con valor null.

### ¿Cómo filtro una lista de títulos por mood?

Obtén los medidores de cada título de tu lista, con el endpoint de moods o con append_to_response en los detalles, y conserva los títulos cuyo mood elegido supere tu umbral. El filtro se ejecuta en tu código.

### ¿Las series de TV también tienen moods?

Sí. Usa GET /3/tv/{tv_id}/moods, por ejemplo con el id de serie 1396. La respuesta tiene la misma forma que la del endpoint de películas.

## 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.
- [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.
- [Bandas sonoras](https://amodb.dev/es/soundtracks/): API de banda sonora de películas que devuelve el álbum de una película o serie con sus pistas. Llama al endpoint o añade append_to_response=soundtracks.
- [API Discover](https://amodb.dev/es/discover/): API Discover con los mismos filtros que TMDB v3. Lista películas y series por género, reparto, productora, palabra clave, año, nota, duración y plataforma.
- [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/moods/
