Translations API

The translations endpoints return every language version of a record in one response: title or name, overview, tagline and homepage for movies and series, name and overview for episodes. Each row carries iso_639_1, iso_3166_1 and english_name. Use it to read languages that the language parameter does not serve or to build a fallback chain.

Get translations for a movie

GET /3/movie/{movie_id}/translations returns one row per language that has text for the movie. Each row holds a data object with the translated fields. The call takes no language parameter, because the whole point is to see all languages at once.

The example finds the Russian row and prints its title and the start of its overview.

curl -s "https://api.amodb.dev/3/movie/550/translations" \
  -H "Authorization: Bearer $AMODB_KEY"
const url = 'https://api.amodb.dev/3/movie/550/translations';
const res = await fetch(url, { headers: { Authorization: `Bearer ${process.env.AMODB_KEY}` } });
if (!res.ok) throw new Error(`amodb returned ${res.status}`);
const { translations } = await res.json();
const ru = translations.find((t) => t.iso_639_1 === 'ru');
console.log(ru ? `${ru.data.title}: ${ru.data.overview.slice(0, 80)}` : 'no Russian row');
import os
import requests

r = requests.get(
    "https://api.amodb.dev/3/movie/550/translations",
    headers={"Authorization": f"Bearer {os.environ['AMODB_KEY']}"},
    timeout=10,
)
r.raise_for_status()
ru = next((t for t in r.json()["translations"] if t["iso_639_1"] == "ru"), None)
print(f"{ru['data']['title']}: {ru['data']['overview'][:80]}" if ru else "no Russian row")
<?php
$ch = curl_init('https://api.amodb.dev/3/movie/550/translations');
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");
}
foreach (json_decode($body, true)['translations'] as $t) {
    if ($t['iso_639_1'] === 'ru') {
        echo $t['data']['title'], ': ', mb_substr($t['data']['overview'], 0, 80), PHP_EOL;
        exit;
    }
}
echo 'no Russian row', PHP_EOL;
package main

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

type Translations struct {
	Translations []struct {
		ISO6391 string `json:"iso_639_1"`
		Data    struct {
			Title    string `json:"title"`
			Overview string `json:"overview"`
		} `json:"data"`
	} `json:"translations"`
}

func main() {
	req, _ := http.NewRequest("GET", "https://api.amodb.dev/3/movie/550/translations", 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 t Translations
	if err := json.NewDecoder(res.Body).Decode(&t); err != nil {
		panic(err)
	}
	for _, row := range t.Translations {
		if row.ISO6391 == "ru" {
			text := []rune(row.Data.Overview)
			if len(text) > 80 {
				text = text[:80]
			}
			fmt.Printf("%s: %s\n", row.Data.Title, string(text))
			return
		}
	}
	fmt.Println("no Russian row")
}

Parameters

ParameterInRequiredDescription
movie_idpathyesNumeric movie id, for example 550.
api_keyqueryone of twoYour key. Use this or the Authorization: Bearer header.

Response fields

FieldTypeNotes
idintegerThe movie id.
translationsarrayOne row per language that has text, sorted by language code. Movie 550 returns 50 rows.
translations[].iso_3166_1stringCountry code that goes with the language, such as US for en or BR for pt. For languages outside the 14 served ones it repeats the language code in capitals.
translations[].iso_639_1stringLanguage code such as ru or pt. Unique in the array.
translations[].namestringThe language written in that language.
translations[].english_namestringThe language name in English.
translations[].dataobjectThe translated fields. Keys depend on the resource, see the table below.

Example response

Two of the 50 rows are shown, and the overviews are cut.

JSON
{
  "id": 550,
  "translations": [
    {
      "iso_3166_1": "US",
      "iso_639_1": "en",
      "name": "English",
      "english_name": "English",
      "data": {
        "title": "Fight Club",
        "overview": "A ticking-time-bomb insomniac and a slippery soap salesman channel primal male aggression into a shocking new form of therapy....",
        "homepage": "https://www.20thcenturystudios.com/movies/fight-club",
        "tagline": "Mischief. Mayhem. Soap.",
        "runtime": 0
      }
    },
    {
      "iso_3166_1": "RU",
      "iso_639_1": "ru",
      "name": "Русский",
      "english_name": "Russian",
      "data": {
        "title": "Бойцовский клуб",
        "overview": "Сотрудник страховой компании страдает хронической бессонницей и отчаянно пытается вырваться из мучительно скучной жизни. Однажд...",
        "homepage": "https://www.20thcenturystudios.com/movies/fight-club",
        "tagline": "«Интриги. Хаос. Мыло»",
        "runtime": 0
      }
    }
  ]
}

In amodb runtime is always 0 in a translation row. Read the runtime from the movie details record.

Translation endpoints and their data keys

All paths share the base https://api.amodb.dev/3. Every one returns id and a translations array of the row shape above. Only the keys inside data change.

Method and pathdata keys
GET /movie/{movie_id}/translationstitle, overview, homepage, tagline, runtime (always 0)
GET /tv/{series_id}/translationsname, overview, homepage, tagline
GET /tv/{series_id}/season/{season_number}/translationsnone, the array is always empty
GET /tv/{series_id}/season/{season_number}/episode/{episode_number}/translationsname, overview

Series records list about as many languages as movies. Episode rows cover only the served languages that have text for that episode, from 2 to 14 in the samples checked. Treat a missing key like an empty value, and ignore keys you do not know. See TV series for the parent records.

amodb does not offer translations for people or collections. A person biography follows the language parameter of the person details call, and a collection overview comes as stored.

Fall back when text is missing

A title can exist in 14 languages and still have an empty overview in the one your user picked. Walk a chain of languages, take the first non-empty value and remember which language it came from.

JavaScript
function pickText(translations, wanted, field) {
  for (const code of [...wanted, 'en']) {
    const row = translations.find((t) => t.iso_639_1 === code);
    const value = row?.data?.[field];
    if (value) return { code, value };
  }
  return null;
}

// Prefer Ukrainian, then Russian, then English.
// const hit = pickText(translations, ['uk', 'ru'], 'overview');

For a series, pass 'name' as the field instead of 'title'. Mark text from a fallback language in your interface, so the user knows why a Ukrainian page shows an English synopsis.

Translations or the language parameter

NeedUse
Show one language to one userlanguage on the details call
List all languages of a title in an editorThis endpoint
Read a language that language does not serve, such as jaThis endpoint, pick the row by iso_639_1
Check which of the 14 served languages have textThis endpoint, compare iso_639_1
Build alternate language links for a pageThis endpoint, read the codes present

For the tags language accepts, see languages. Any other tag falls back to English on a details call.

Errors

HTTPstatus_codeWhen
4017The key is missing or wrong.
40236The plan period has ended.
40434No season or episode with that id, or an id that is not a number.
40537You used a write method on a translations path.
42925You went over your requests per minute. Wait for the Retry-After seconds.

A movie or series id that does not exist is not an error on this path: it answers 200 with "translations": [], while the details path answers 404. More on errors and rate limits.

Practical notes

  • One call replaces up to 14 details calls. Use it when you need more than two languages of the same title.
  • The rows are sorted by language code, which is not a priority order. Pick rows by iso_639_1, never by array position.
  • Details-type calls are cached at the edge for 6 hours, so a client cache of the same length costs nothing in freshness.
  • Original titles in other scripts, such as Japanese or Korean, are always available in original_title and original_name on the details record.
  • To add translations to a details call, pass append_to_response=translations and read the same array from the reply. It works for movies, series and episodes. The appended block has no id.