---
title: Up Next, tracked shows & change detection
description: Read a user's computed Up Next queue, manage tracked shows, and poll for what changed.
section: Your data
order: 9
---

# Up Next, tracked shows & change detection

You read a signed-in user's computed Up Next queue, manage which shows they track, and detect what changed since your last sync.

> [!REQUIRED]
> Every endpoint on this page needs a credential. GETs need the `read` scope, mutations need the `write` scope. See [Authentication](/dev/authentication).

## Up Next

`GET /v3/sync/up_next` returns one entry per show the user has started or is currently watching, each carrying its next unwatched episode (when known) plus progress context. Unlike dropping a show from the site's own Up Next view, this endpoint always includes dropped shows and flags them with `dropped: true` instead of hiding them.

:::tabs
```bash
curl -H "Authorization: Bearer $TOKEN" \
  "https://flicklist.tv/api/v3/sync/up_next?limit=40"
```
```javascript
const res = await fetch('https://flicklist.tv/api/v3/sync/up_next?limit=40', {
  headers: { Authorization: `Bearer ${token}` },
});
const upNext = await res.json();
```
```python
import requests
r = requests.get(
    "https://flicklist.tv/api/v3/sync/up_next",
    params={"limit": 40},
    headers={"Authorization": f"Bearer {token}"},
)
up_next = r.json()
```
:::

```json
[
  {
    "title": "Severance",
    "media_type": "tv",
    "status": "Returning Series",
    "ids": { "fldb": "flt_4b8e12d7", "tmdb": 95396, "imdb": "tt11280740", "tvdb": null, "slug": "severance", "anilist": null },
    "next_season_number": 2,
    "next_episode_number": 4,
    "next_air_date": "2026-06-01",
    "awaiting_next_episode": false,
    "episode_available": true,
    "progress_percent": 62.5,
    "dropped": false
  }
]
```

Drop a show with `POST /v3/sync/up_next/drop`, restore it with `POST /v3/sync/up_next/undrop`. Both take a [single media identity](/dev/ids), no batch, and neither touches watch history. Undrop 404s if the resolved show isn't currently dropped.

## Tracked shows

Tracking is independent of watchlisting or watching a show. It's purely "notify me, and surface this in my calendar and Up Next." `GET /v3/sync/tracked` returns every tracked show, most-recently-tracked first, with no pagination (a tracked list is small by nature).

`POST /v3/sync/tracked` tracks a single show and is idempotent, tracking an already-tracked show still returns 200. `DELETE /v3/sync/tracked` untracks it and 404s if the show wasn't tracked.

```json
{ "tracked": true }
```

## Change detection with last_activities

> [!TIP]
> Poll `GET /v3/sync/last_activities` instead of re-fetching your collections on a timer. It returns one timestamp per data category, so you only refetch the categories that actually changed.

`GET /v3/sync/last_activities` returns per-domain timestamps: `movies` and `episodes` each split into `watched_at`, `paused_at`, `watchlisted_at`, plus `shows.watchlisted_at`, `lists.updated_at`, and `favorites`. An overall `all` field is the max of everything, the single value to compare against a cached "last synced at." Every timestamp defaults to the Unix epoch when the user has no data in that category yet, it's never `null`, so there's always something to compare against.

:::tabs
```bash
curl -H "Authorization: Bearer $TOKEN" \
  "https://flicklist.tv/api/v3/sync/last_activities"
```
```javascript
const res = await fetch('https://flicklist.tv/api/v3/sync/last_activities', {
  headers: { Authorization: `Bearer ${token}` },
});
const activities = await res.json();
```
```python
import requests
r = requests.get(
    "https://flicklist.tv/api/v3/sync/last_activities",
    headers={"Authorization": f"Bearer {token}"},
)
activities = r.json()
```
:::

```json
{
  "all": "2026-05-14T02:10:33.000Z",
  "movies": { "watched_at": "2026-05-14T02:10:33.000Z", "paused_at": "2026-05-01T00:00:00.000Z", "watchlisted_at": "2026-05-10T00:00:00.000Z" },
  "episodes": { "watched_at": "2026-05-13T20:00:00.000Z", "paused_at": "1970-01-01T00:00:00.000Z", "watchlisted_at": "1970-01-01T00:00:00.000Z" },
  "shows": { "watchlisted_at": "2026-05-09T00:00:00.000Z" },
  "lists": { "updated_at": "2026-05-14T02:10:33.000Z" },
  "favorites": "2026-04-20T00:00:00.000Z"
}
```

### Poll-then-fetch pattern

Store the `all` value locally after every sync. On your next poll, compare it and only refetch collections whose category timestamp advanced.

```javascript
const last = await fetch('https://flicklist.tv/api/v3/sync/last_activities', {
  headers: { Authorization: `Bearer ${token}` },
}).then((r) => r.json());

if (last.episodes.watched_at > cachedTimestamps.episodesWatchedAt) {
  // refetch episode watch history
}
if (last.lists.updated_at > cachedTimestamps.listsUpdatedAt) {
  // refetch /sync/lists
}
cachedTimestamps = last;
```

This keeps a long-running integration well under the rate ceiling instead of re-pulling every collection on every poll.
