Genres and lookup lists

Genre and lookup endpoints return small reference lists you load once: movie and TV genre ids with names in 14 languages, plus countries, languages, crew jobs, age certifications and streaming providers. They use TMDB v3 paths and shapes, need no paging, and change rarely, so cache them for a day.

Get the movie genre list

GET /3/genre/movie/list returns every movie genre as an id and a name. The ids are the numbers that genre_ids carries on list items and that with_genres expects in discover. The names follow the language parameter.

The example loads the list and builds an id to name map, the first thing most apps need.

curl -s "https://api.amodb.dev/3/genre/movie/list?language=en-US" \
  -H "Authorization: Bearer $AMODB_KEY"
const url = 'https://api.amodb.dev/3/genre/movie/list?language=en-US';
const res = await fetch(url, { headers: { Authorization: `Bearer ${process.env.AMODB_KEY}` } });
if (!res.ok) throw new Error(`amodb returned ${res.status}`);
const { genres } = await res.json();
const names = new Map(genres.map((g) => [g.id, g.name]));
console.log(names.get(878), names.size);
import os
import requests

r = requests.get(
    "https://api.amodb.dev/3/genre/movie/list",
    params={"language": "en-US"},
    headers={"Authorization": f"Bearer {os.environ['AMODB_KEY']}"},
    timeout=10,
)
r.raise_for_status()
names = {g["id"]: g["name"] for g in r.json()["genres"]}
print(names[878], len(names))
<?php
$url = 'https://api.amodb.dev/3/genre/movie/list?language=en-US';
$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");
}
$names = [];
foreach (json_decode($body, true)['genres'] as $g) {
    $names[$g['id']] = $g['name'];
}
echo $names[878], ' ', count($names), PHP_EOL;
package main

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

type Genres struct {
	Genres []struct {
		ID   int    `json:"id"`
		Name string `json:"name"`
	} `json:"genres"`
}

func main() {
	url := "https://api.amodb.dev/3/genre/movie/list?language=en-US"
	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 g Genres
	if err := json.NewDecoder(res.Body).Decode(&g); err != nil {
		panic(err)
	}
	names := map[int]string{}
	for _, x := range g.Genres {
		names[x.ID] = x.Name
	}
	fmt.Println(names[878], len(names))
}

Parameters

ParameterInRequiredDescription
api_keyqueryone of twoYour key. Use this or the Authorization: Bearer header.
languagequerynoTMDB tag such as en-US, ru-RU or pt-BR. Names are returned in this language. Default en-US.

Response fields

FieldTypeNotes
genresarrayThe whole list in one response, no paging.
genres[].idintegerStable genre id.
genres[].namestringGenre name in the requested language.

Example response

JSON
{
  "genres": [
    { "id": 12, "name": "Adventure" },
    { "id": 14, "name": "Fantasy" },
    { "id": 16, "name": "Animation" },
    { "id": 18, "name": "Drama" }
  ]
}

The reply holds 27 genres sorted by id. This one is cut to the first 4.

Genre ids

Both genre paths return these 27 genres, sorted by id. The names below are the English ones. Other languages return the same ids with translated names.

IdName
12Adventure
14Fantasy
16Animation
18Drama
27Horror
28Action
35Comedy
36History
37Western
53Thriller
80Crime
99Documentary
878Science Fiction
9648Mystery
10402Music
10749Romance
10751Family
10752War
10759Action & Adventure
10762Kids
10763News
10764Reality
10765Sci-Fi & Fantasy
10766Soap
10767Talk
10768War & Politics
10770TV Movie

TV genre list

GET /3/genre/tv/list takes the same language parameter and returns the identical list, so one id to name map covers movies and TV. In list data, ids 10759 and 10762 to 10768 appear on TV items only, and ids such as 28, 12 and 878 appear on movie items. When you filter TV in discover, use the TV ids, for example 10765 for Sci-Fi and Fantasy.

Lookup lists

These paths return reference data for forms, filters and settings screens. All take the key; none take page.

Method and pathParametersEach item or shape
GET /configuration/countriesnoneArray of { iso_3166_1, english_name, native_name }
GET /configuration/languagesnoneArray of { iso_639_1, english_name, name }
GET /configuration/primary_translationsnoneArray of 14 strings such as ru-RU
GET /configuration/jobsnoneArray of { department, jobs } where jobs lists job titles
GET /certification/movie/listnone{ certifications } keyed by country code, 10 countries
GET /certification/tv/listnone{ certifications } keyed by country code, one key per country in the catalog
GET /watch/providers/regionslanguage{ results } of { iso_3166_1, english_name, native_name }
GET /watch/providers/movielanguage, watch_region{ results } of providers
GET /watch/providers/tvlanguage, watch_region{ results } of providers

/configuration/countries and /configuration/languages ignore language and always return the same names. native_name in the regions list follows language. amodb does not offer /configuration/timezones.

A certification entry names the rating, what it means and its sort order. Entries are grouped by country code, so one call covers every market. The movie list has the rating texts. On the TV list meaning is an empty string.

JSON
{
  "certifications": {
    "US": [
      { "certification": "PG", "meaning": "Some material may not be suitable for children under 10.", "order": 3 },
      { "certification": "R", "meaning": "Under 17 requires accompanying parent or adult guardian.", "order": 5 }
    ]
  }
}

The example is cut to 2 of the 6 US entries. The movie list covers AU, BR, CA, DE, ES, FR, GB, IT, RU and US.

A provider entry has provider_id, provider_name, logo_path, display_priority and display_priorities, a map of country code to priority. Without watch_region you get every provider. With watch_region=US you keep only providers that serve that country. An unknown region returns an empty results array. Pass a code from /watch/providers/regions. Provider logos load from the image host, see images.

JSON
{
  "display_priorities": { "AT": 1, "DE": 1, "GB": 1, "JP": 1, "US": 3 },
  "display_priority": 3,
  "logo_path": "/gMZdpavHmxFNnLpMHwVxfqeux2g.png",
  "provider_name": "Amazon Prime Video",
  "provider_id": 9
}

This is one entry from /watch/providers/movie?watch_region=US.

Errors

HTTPstatus_codeWhen
4017The key is missing or wrong.
40236The plan period has ended.
40434The path does not exist, for example /genre/book/list.
40537You used a write method on a lookup path.
42925You went over your requests per minute. Wait for the Retry-After seconds.

Details for every code are on errors. Plan limits are on rate limits.

Practical notes

  • Load the lists once per language at startup and keep them in memory or a file. The edge caches the /configuration paths for 24 hours, so a daily refresh on your side is enough.
  • Store genre ids in your database, not names. A name changes with the language, an id does not.
  • Both genre paths return the same 27 entries, so one map covers movies and TV. Ids 10759 and 10762 to 10768 appear on TV items only.
  • with_genres=28,12 in discover means Action and Adventure together. with_genres=28|12 means either one.
  • Genre names follow the language parameter. A tag outside the 14 base languages in languages falls back to English, and a few names stay in English in some languages, for example 10759 in Italian.