API

Movie Details & Caching

Fetch enriched movie metadata with Supabase-backed caching

The Movie Details endpoint fetches enriched metadata for a single movie by its TMDB ID. Results are cached server-side in the Supabase movies table for about 3 months to avoid redundant TMDB API calls.

Endpoint

GET /api/movies/:id

How It Works

  1. Client requests /api/movies/:id with a TMDB movie ID
  2. Server checks movies for a cached row
  3. Cache hit - returns the cached record immediately, no TMDB call made
  4. Cache miss or stale/incomplete row - fetches from TMDB (/movie/:id?append_to_response=credits,videos), upserts the movie row in Supabase, and returns the normalized response

Example Usage

const response = await fetch('/api/movies/550')
const movie = await response.json()

Path Parameter

ParameterTypeDescription
idnumberTMDB movie ID (positive integer)

Returns 400 if the ID is missing or not a positive integer.

Response Format

{
  "id": 550,
  "title": "Fight Club",
  "poster": "https://image.tmdb.org/t/p/w500/path/to/poster.jpg",
  "rating": 8.4,
  "year": 1999,
  "duration": "2h 19m",
  "runtime": 139,
  "genres": ["Drama", "Thriller"],
  "actors": ["Brad Pitt", "Edward Norton", "Helena Bonham Carter", "Meat Loaf", "Zach Grenier"],
  "directors": ["David Fincher"],
  "description": "A ticking-time-bomb insomniac...",
  "trailer": "https://www.youtube.com/watch?v=SUXWAEX2jlg"
}
FieldTypeNotes
idnumberTMDB ID
titlestringMovie title
posterstringFull image URL (w500). Empty string if no poster
ratingnumbervote_average rounded to 1 decimal place
yearnumberRelease year parsed from release_date
durationstringFormatted as 2h 19m. "N/A" if runtime is unknown
runtimenumberRaw runtime in minutes, or null when unavailable
genresstring[]Genre names
actorsstring[]Top 5 cast members
directorsstring[]Director names
descriptionstringMovie overview
trailerstringYouTube link or null

Caching Details

PropertyValue
Cache storeSupabase movies table
TTL~3 months (90 days)
Cache keytmdb_id
Trailer selectionMost recent official YouTube trailer (type = "Trailer", official = true)

Cache freshness is checked via the cached_at timestamp column. A record is also refreshed when required detail fields are still empty.

Error Handling

StatusCause
400id is missing or not a positive integer
404TMDB returned no movie for that ID
500TMDB API or Supabase failure
Copyright © 2026