---
title: History
description: Read, add, and remove individual watch events for an account.
section: Your data
order: 2
---

# History

Read individual watch events, add new ones in bulk, and remove them without touching the rest of the account.

> [!REQUIRED]
> `GET /v3/sync/history` needs the `read` scope. The `POST` and `DELETE` variants need `write`. See [Authentication](/dev/authentication).

## Reading history

`GET /v3/sync/history` returns one row per watch event, newest first. A rewatch produces a second row, unlike [Watched shows & movies](/dev/sync/watched), which rolls episodes up into a single entry per show.

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

The response carries `X-FlickList-Page`, `X-FlickList-Limit`, `X-FlickList-Page-Count`, and `X-FlickList-Item-Count` headers. See [Pagination](/dev/pagination) for how to page through everything.

```json
[
  {
    "id": 88213,
    "type": "episode",
    "title": "Breaking Bad",
    "year": 2008,
    "season_number": 1,
    "episode_number": 1,
    "episode_name": "Pilot",
    "watched_at": "2026-05-14T02:10:33.000Z",
    "ids": { "fldb": "flt_9f2c8a1b", "slug": "breaking-bad", "tmdb": 1396, "imdb": "tt0903747", "tvdb": 81189, "anilist": null }
  }
]
```

## Adding history

`POST /v3/sync/history` marks up to 1000 items watched in one batch. Build each item's `ids` block per [The ids object](/dev/ids): FlickList resolves `fldb` first, then `tmdb`, then `imdb`, then `tvdb`, whichever key appears first on the item.

```json
{
  "items": [
    { "ids": { "tmdb": 1396 }, "media_type": "show", "season": 1, "episode": 1 }
  ]
}
```

An item whose `ids` don't resolve, or whose `season`/`episode` doesn't match a real episode, lands in the response's `not_found` array instead of failing the whole batch. `watched_at` defaults to now. A timestamp more than 5 minutes in the future fails the entire request with a 400.

```json
{ "added": 1, "existing": 0, "not_found": [] }
```

> [!TIP]
> Always send an explicit `watched_at`, and reuse the exact same value if you retry a timed-out request. Writes are idempotent per item and timestamp: a retried event lands in the response's `existing` count instead of being recorded twice. Omit `watched_at` and each retry gets stamped with a new arrival time, which records a second play.

## Removing history

`DELETE /v3/sync/history` takes the same body shape and hides the matching events instead of adding them.

```json
{ "removed": 1, "not_found": [] }
```

> [!WARNING]
> Unmarking hides history events. It never deletes account data, and there's no separate undo call, so review a large removal batch before sending it. Batches are capped at 1000 items per request either way.
