Collections API

A collection groups the movies of one franchise, such as a trilogy or a long running series of films. GET /3/collection/{collection_id} returns its name, overview, artwork and a parts array of movies in release order. Movies point back to their collection through belongs_to_collection, so you can move in both directions.

Get a collection

GET /3/collection/{collection_id} returns one franchise: its name, an overview, a poster, a backdrop and the parts array. Each part is a movie summary with the fields you need for a card, so one call can draw a whole franchise shelf.

The example loads collection 10, the Star Wars films, and prints its movies in release order.

curl -s "https://api.amodb.dev/3/collection/10?language=en-US" \
  -H "Authorization: Bearer $AMODB_KEY"
const url = 'https://api.amodb.dev/3/collection/10?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 collection = await res.json();
console.log(collection.name);
for (const p of collection.parts) console.log(p.release_date || 'not dated', p.title);
import os
import requests

r = requests.get(
    "https://api.amodb.dev/3/collection/10",
    params={"language": "en-US"},
    headers={"Authorization": f"Bearer {os.environ['AMODB_KEY']}"},
    timeout=10,
)
r.raise_for_status()
collection = r.json()
print(collection["name"])
for p in collection["parts"]:
    print(p.get("release_date") or "not dated", p["title"])
<?php
$url = 'https://api.amodb.dev/3/collection/10?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");
}
$collection = json_decode($body, true);
echo $collection['name'], PHP_EOL;
foreach ($collection['parts'] as $p) {
    echo $p['release_date'] ?: 'not dated', ' ', $p['title'], PHP_EOL;
}
package main

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

type Collection struct {
	Name  string `json:"name"`
	Parts []struct {
		Title       string `json:"title"`
		ReleaseDate string `json:"release_date"`
	} `json:"parts"`
}

func main() {
	url := "https://api.amodb.dev/3/collection/10?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 c Collection
	if err := json.NewDecoder(res.Body).Decode(&c); err != nil {
		panic(err)
	}
	fmt.Println(c.Name)
	for _, p := range c.Parts {
		date := p.ReleaseDate
		if date == "" {
			date = "not dated"
		}
		fmt.Println(date, p.Title)
	}
}

Parameters

ParameterInRequiredDescription
collection_idpathyesNumeric collection id, for example 10.
api_keyqueryone of twoYour key. Use this or the Authorization: Bearer header.
languagequerynoOne of the 14 served languages, for example en-US or fr-FR. Sets the language of each part's title and overview. Default en-US.

The collection's own name and overview come as stored and do not change with language. For some collections they are not in English.

Response fields

FieldTypeNotes
idintegerCollection id.
namestringFranchise name.
overviewstringShort description. Empty for some collections.
poster_path, backdrop_pathstring or nullAppend to https://img.amodb.dev/t/p/{size}. See images.
partsarrayMovie summaries, oldest release_date first.
parts[].idintegerMovie id. Pass it to movie details.
parts[].title, parts[].original_titlestringLocalized and original title.
parts[].overviewstringLocalized synopsis.
parts[].release_datestringYYYY-MM-DD, or an empty string for a film without a date. Those parts come last.
parts[].media_typestringAlways movie in a collection.
parts[].genre_idsarrayNumeric ids. Names come from genres.
parts[].adult, parts[].videobooleanadult is always false, because adult titles are not served.
parts[].original_languagestringTwo letter language code.
parts[].popularitynumberPopularity score.
parts[].poster_path, parts[].backdrop_pathstring or nullArtwork of the film.
parts[].vote_average, parts[].vote_countnumber, integerAggregate user score.

Example response

Two of the nine parts are shown.

JSON
{
  "id": 10,
  "name": "Star Wars Collection",
  "overview": "An epic space-opera theatrical film series, which depicts the adventures of various cha...",
  "poster_path": "/pWVLFh4OuejTpUaDQbB1C4zoS2p.jpg",
  "backdrop_path": "/iY2ujEY2m68OTTlPFTiHub9joHS.jpg",
  "parts": [
    {
      "adult": false,
      "backdrop_path": "/zqkmTXzjkAgXmEWLRsY4UpTWCeo.jpg",
      "genre_ids": [12, 28, 878],
      "id": 11,
      "original_language": "en",
      "original_title": "Star Wars",
      "overview": "Princess Leia is captured and held hostage by the evil Imperial forces in their effort...",
      "popularity": 70.481,
      "poster_path": "/fai0rspsNeJCS69wHNjOdWxcI7P.jpg",
      "release_date": "1977-05-25",
      "title": "Star Wars",
      "video": false,
      "vote_average": 8.207,
      "vote_count": 23025,
      "media_type": "movie"
    },
    {
      "adult": false,
      "backdrop_path": "/k9pshruhCpJAdH9RaGJO6jaWQ4X.jpg",
      "genre_ids": [12, 28, 878],
      "id": 1891,
      "original_language": "en",
      "original_title": "The Empire Strikes Back",
      "overview": "The epic saga continues as Luke Skywalker, in hopes of defeating the evil Galactic Empi...",
      "popularity": 29.9034,
      "poster_path": "/nNAeTmF4CtdSgMDplXTDPOpYzsX.jpg",
      "release_date": "1980-05-20",
      "title": "The Empire Strikes Back",
      "video": false,
      "vote_average": 8.393,
      "vote_count": 18990,
      "media_type": "movie"
    }
  ]
}

Long strings are cut with ... for this page. The real response holds the full text.

Find the collection of a movie

You rarely start from a collection id. You start from a movie, and the movie details record tells you where it belongs. The belongs_to_collection field is an object with id, name, poster_path and backdrop_path. It is null for a movie that is not part of a franchise, such as movie 550.

JSON
{
  "id": 11,
  "title": "Star Wars",
  "belongs_to_collection": {
    "id": 10,
    "name": "Star Wars Collection",
    "poster_path": "/pWVLFh4OuejTpUaDQbB1C4zoS2p.jpg",
    "backdrop_path": "/iY2ujEY2m68OTTlPFTiHub9joHS.jpg"
  }
}

The sample below follows that link from a movie to its franchise in two requests.

JavaScript
const base = 'https://api.amodb.dev/3';
const headers = { Authorization: `Bearer ${process.env.AMODB_KEY}` };

async function getJson(path) {
  const res = await fetch(`${base}${path}`, { headers });
  if (!res.ok) throw new Error(`${path} returned ${res.status}`);
  return res.json();
}

const movie = await getJson('/movie/11');
if (movie.belongs_to_collection) {
  const collection = await getJson(`/collection/${movie.belongs_to_collection.id}`);
  console.log(movie.title, 'is one of', collection.parts.length, 'films in', collection.name);
}

The poster and backdrop of a franchise are the poster_path and backdrop_path fields of the collection record. Build the file address from them as described on images. amodb does not offer the /collection/{collection_id}/images and /collection/{collection_id}/translations paths, so a collection has no list of alternate posters and no per language rows. Part titles follow the language parameter instead, and translations covers the paths that do return language rows.

To find a collection by name, use GET /3/search/collection?query=matrix, described on search. Each result has id, name, overview, poster_path, backdrop_path, original_language, original_name and adult.

Errors

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

See errors for the full list and rate limits for plan limits.

Practical notes

  • Collections group movies only. A movie holds at most one belongs_to_collection object, so one film maps to one franchise.
  • Parts arrive in release order. Films with an empty date come last, so label them as not dated yet.
  • The collection record is cached at the edge for 6 hours like other details, so a franchise page can reuse one response for that long.
  • A part carries summary fields only. Fetch runtime, credits and ratings per film through movie details when the user opens it.
  • Use parts[].id as your key for a film, not its position in the franchise. Orders and dates get corrected over time.
  • Check that name is in your display language before you show it. Some collections carry a name in another language, and language does not change it.