API

Watched and My List APIs

Authenticated APIs for the user's watched movies and saved list

/api/watched and /api/mylist both use Supabase and the shared movies table. They expose hydrated movie cards on reads, but writes only need a TMDB ID.

Auth

  • Requires Authorization: Bearer <supabase_access_token>
  • User is resolved server-side from the token
  • Requests without a valid token return 401 Unauthorized

Current Tables

/api/watched

  • Storage table: user_watched_movies
  • Shape: one row per (user_id, tmdb_id)
  • Read path: joins watched IDs to movies so the client receives hydrated cards

/api/mylist

  • Storage table: user_my_list
  • Shape: one row per user with tmdb_ids integer[]
  • Write path: uses RPC functions append_my_list and remove_my_list
  • Read path: resolves tmdb_ids through movies

Accepted Write Payload

Both routes accept either of these request bodies:

{
  "tmdbId": 550
}

tmdbId must be a positive integer.

GET /api/watched

Returns the current user's watched list.

{
  "success": true,
  "movies": [
    {
      "tmdbId": 550,
      "title": "Fight Club",
      "year": 1999,
      "posterPath": "/path.jpg",
      "genres": ["Drama"],
      "runtime": 139
    }
  ]
}

If a movie exists in the relationship table but has not been hydrated in movies yet, the route returns a fallback item with empty display fields and the correct tmdbId.

POST /api/watched

Adds a watched row if it is not already present.

{
  "tmdbId": 550
}

DELETE /api/watched

Removes a movie from the watched list by tmdbId.

{
  "tmdbId": 550
}

GET /api/mylist

Returns the current user's saved list as hydrated movie cards.

{
  "success": true,
  "movies": [
    {
      "tmdbId": 157336,
      "title": "Interstellar",
      "year": 2014,
      "posterPath": "/path.jpg",
      "genres": ["Adventure", "Drama"],
      "runtime": 169
    }
  ]
}

POST /api/mylist

Adds a TMDB ID through the append_my_list RPC function.

{
  "success": true,
  "myListCount": null
}

DELETE /api/mylist

Removes a TMDB ID through the remove_my_list RPC function.

{
  "success": true,
  "myListCount": null
}

Error Codes

  • 400 invalid payload or invalid tmdbId
  • 401 missing or invalid bearer token
  • 409 movie is already in watched list when adding to /api/mylist
  • 405 unsupported method
  • 500 Supabase query, delete, upsert, or RPC failure
Copyright © 2026