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
| Parameter | In | Required | Description |
|---|---|---|---|
collection_id | path | yes | Numeric collection id, for example 10. |
api_key | query | one of two | Your key. Use this or the Authorization: Bearer header. |
language | query | no | One 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
| Field | Type | Notes |
|---|---|---|
id | integer | Collection id. |
name | string | Franchise name. |
overview | string | Short description. Empty for some collections. |
poster_path, backdrop_path | string or null | Append to https://img.amodb.dev/t/p/{size}. See images. |
parts | array | Movie summaries, oldest release_date first. |
parts[].id | integer | Movie id. Pass it to movie details. |
parts[].title, parts[].original_title | string | Localized and original title. |
parts[].overview | string | Localized synopsis. |
parts[].release_date | string | YYYY-MM-DD, or an empty string for a film without a date. Those parts come last. |
parts[].media_type | string | Always movie in a collection. |
parts[].genre_ids | array | Numeric ids. Names come from genres. |
parts[].adult, parts[].video | boolean | adult is always false, because adult titles are not served. |
parts[].original_language | string | Two letter language code. |
parts[].popularity | number | Popularity score. |
parts[].poster_path, parts[].backdrop_path | string or null | Artwork of the film. |
parts[].vote_average, parts[].vote_count | number, integer | Aggregate user score. |
Example response
Two of the nine parts are shown.
{
"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.
{
"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.
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);
}Artwork and search
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
| HTTP | status_code | When |
|---|---|---|
| 401 | 7 | The key is missing or wrong. |
| 402 | 36 | The plan period has ended. |
| 404 | 34 | No collection with that id, or an id that is not a number. |
| 405 | 37 | You used a write method on a collection path. |
| 429 | 25 | You 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_collectionobject, 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[].idas your key for a film, not its position in the franchise. Orders and dates get corrected over time. - Check that
nameis in your display language before you show it. Some collections carry a name in another language, andlanguagedoes not change it.