API
Recommendations (Cached)
Main recommendation endpoint with per-user Supabase caching
GET /api/recommend is the primary recommendations endpoint used by the home feed. It combines watched history, My List-aware filtering, AI generation, and Supabase caching, reducing cost and latency by reusing valid recommendations for 7 days.
Endpoint
GET /api/recommend
Optional query flags:
?refresh=trueor?refresh=1?getNew=trueor?getNew=1
Auth
Requires Authorization: Bearer <supabase_access_token>.
Cache Strategy
The route stores and reuses recommendation sets in Supabase table recommendations.
| Field | Purpose |
|---|---|
user_id | Per-user cache key |
tmdb_ids | Cached recommendation TMDB IDs |
watched_hash | Hash of watched movies used to validate freshness (My List is applied during generation, not in this cache-key hash) |
expires_at | Cache expiration timestamp |
Cache TTL is 7 days.
Behavior by Mode
Default (/api/recommend)
- If cache is fresh and
watched_hashmatches current watched history: returns cached recommendations (cached: true) - Otherwise generates a new set and stores it (
cached: false)
Refresh (/api/recommend?refresh=true)
- Skips cache reuse
- Generates a fresh set and overwrites cache
Get New (/api/recommend?getNew=true)
- Skips cache reuse
- Loads previous cached recommendations and excludes them from the next AI generation round
- Generates a new set (still applying My List filtering rules) and stores it
Response Shape
{
"recommendations": [157336, 603],
"cached": false,
"stale": false,
"regenerationError": null,
"staleRecommendations": null
}
Successful responses return TMDB IDs only. The frontend hydrates details separately through GET /api/movies/:id.
Rate Limiting
Recommendation generation is limited to 20 requests/day per authenticated user.
Headers returned on generation requests:
X-RateLimit-LimitX-RateLimit-RemainingX-RateLimit-Reset
Error Codes
400no watched movies found401missing or invalid bearer token409recommendation request already in progress429daily recommendation limit reached500Supabase or internal failure502AI output could not be parsed, validated, or resolved into enough TMDB matches503no provider is configured, or all configured provider/model attempts are unavailable