> ## Documentation Index
> Fetch the complete documentation index at: https://docs.punchplay.tv/llms.txt
> Use this file to discover all available pages before exploring further.

# Native App API

> Build the core PunchPlay movie and TV experience for iOS, Android, desktop, or TV.

The Platform API covers the core native PunchPlay experience: account identity and editing, preferences, title discovery data, seasons and episodes, history, ratings, favourites, watch statuses, lists, collection, calendar, Continue Watching, notifications, trophies, community stats, and live playback.

All protected endpoints use a scoped bearer token:

```http theme={null}
Authorization: Bearer ACCESS_TOKEN
Accept: application/json
```

Title `type` values are `movie` or `show`. Title IDs are TMDB source IDs.

## Recommended scope set

For a full native movie and TV client, request:

```text theme={null}
profile:read profile:write playback:read playback:write events:read history:read history:write lists:read lists:write ratings:read ratings:write collection:read collection:write notifications:read notifications:write trophies:read
```

Account email is not exposed to developer apps. Use the stable user ID from
`GET /api/platform/v1/me` for account linking. Existing users must approve
newly requested scopes and receive a new access token before the corresponding
endpoints become available.

## Endpoint map

| Client feature                            | Method and path                                                               | Required scope                                 |
| ----------------------------------------- | ----------------------------------------------------------------------------- | ---------------------------------------------- |
| Account and profile                       | `GET /api/platform/v1/me`                                                     | `profile:read`                                 |
| Profile settings                          | `GET` or `PATCH /api/platform/v1/me/profile`                                  | `profile:read` or `profile:write`              |
| App preferences                           | `GET` or `PATCH /api/platform/v1/me/preferences`                              | `profile:read` or `profile:write`              |
| Community stats                           | `GET` or `POST /api/platform/v1/me/community-stats`                           | `profile:read`, `history:read`, `ratings:read` |
| Calendar                                  | `GET /api/platform/v1/calendar?month=YYYY-MM`                                 | `profile:read`, `history:read`, `lists:read`   |
| Title details                             | `GET /api/platform/v1/title/{type}/{id}`                                      | `profile:read`                                 |
| Season details                            | `GET /api/platform/v1/title/show/{id}/season/{season}`                        | `profile:read`                                 |
| Episode details                           | `GET /api/platform/v1/title/show/{id}/season/{season}/episode/{episode}`      | `profile:read`                                 |
| Continue Watching                         | `GET /api/platform/v1/me/continue-watching`                                   | `playback:read`                                |
| Show progress                             | `GET /api/platform/v1/me/continue-watching/{showId}`                          | `playback:read`                                |
| In-progress playback                      | `GET /api/platform/v1/playback/in-progress`                                   | `playback:read`                                |
| Dismiss progress                          | `DELETE /api/platform/v1/playback/in-progress/{id}`                           | `playback:write`                               |
| Playback lifecycle                        | `POST /api/platform/v1/playback/{action}`                                     | `playback:write`                               |
| Watch history                             | `GET /api/platform/v1/me/history`                                             | `history:read`                                 |
| Log or clear a movie                      | `POST` or `DELETE /api/platform/v1/title/movie/{id}/history`                  | `history:write`                                |
| Log or clear episodes                     | `POST` or `DELETE /api/platform/v1/title/show/{id}/season/{season}/watch`     | `history:write`                                |
| Edit or delete one watch                  | `PATCH` or `DELETE /api/platform/v1/watch-history/{id}`                       | `history:write`                                |
| Ratings, favourites, statuses             | `GET /api/platform/v1/me/ratings`, `/favourites`, or `/watch-status`          | `ratings:read`                                 |
| Change interaction state                  | `PATCH /api/platform/v1/title/{type}/{id}/interact`                           | `ratings:write`                                |
| List summaries and details                | `GET /api/platform/v1/me/lists` and `/lists/{id}`                             | `lists:read`                                   |
| Manage lists                              | `POST /api/platform/v1/lists`; `PATCH` or `DELETE /lists/{id}`                | `lists:write`                                  |
| Manage list items                         | `GET` or `POST /lists/{id}/items`; `DELETE /lists/{id}/items/{itemId}`        | `lists:read` or `lists:write`                  |
| Collection                                | `GET /api/platform/v1/me/collection`                                          | `collection:read`                              |
| Manage collection                         | `POST /api/platform/v1/collection`; `DELETE /collection/{id}`                 | `collection:write`                             |
| Notifications                             | `GET /api/platform/v1/me/notifications` and `/unread-count`                   | `notifications:read`                           |
| Mark notifications read                   | `POST /api/platform/v1/me/notifications/read`                                 | `notifications:write`                          |
| Notification preferences                  | `GET` or `PATCH /api/platform/v1/me/notification-preferences`                 | `notifications:read` or `notifications:write`  |
| PunchPlay push devices (first-party only) | `GET` or `POST /api/platform/v1/me/push-devices`; `DELETE /push-devices/{id}` | `notifications:read` or `notifications:write`  |
| Trophies                                  | `GET /api/platform/v1/me/trophies`                                            | `trophies:read`                                |

## Pagination

Collection-style reads return a bounded page and an opaque `nextCursor`. Pass
that value back as `cursor` to fetch the next page; `null` means you have
reached the end.

```json theme={null}
{ "items": [], "nextCursor": "eyJpZCI6NDJ9" }
```

| Endpoint                                | Default | Maximum |
| --------------------------------------- | ------- | ------- |
| `GET /api/platform/v1/me/history`       | 25      | 100     |
| `GET /api/platform/v1/me/notifications` | 30      | 100     |
| `GET /api/platform/v1/me/collection`    | 100     | 200     |
| `GET /api/platform/v1/me/lists`         | 50      | 100     |

Treat cursors as meaningless strings — do not parse or build them — and keep
every other query parameter identical while paging through one result set.

`GET /api/platform/v1/me/ratings`, `/favourites`, and `/watch-status` use
page-number pagination instead, taking `page` and returning `total`, `page`,
`pageSize`, and `hasMore`. `GET /api/platform/v1/me/trophies` returns a fixed
catalogue and is not paginated.

<Note>
  `me/collection` and `me/lists` previously returned the entire set in one
  response. They are now paged, so a client that reads only `items` will see
  the first page rather than everything. Follow `nextCursor` if you need the
  full set.
</Note>

## Title, season, and episode details

Fetch a movie or show by TMDB ID:

```bash theme={null}
curl "https://punchplay.tv/api/platform/v1/title/movie/550" \
  -H "Authorization: Bearer ACCESS_TOKEN"
```

The response includes title metadata and returns private interaction fields only when the token also has their corresponding read scopes. Season zero is valid for specials; episode numbers start at one.

## History

Log a movie watch:

```bash theme={null}
curl -X POST "https://punchplay.tv/api/platform/v1/title/movie/550/history" \
  -H "Authorization: Bearer ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"title":"Fight Club","year":1999,"watchedAt":"2026-07-18T20:00:00.000Z"}'
```

Log one episode through the season-watch endpoint. Include `allowRewatches: true` only when the user explicitly chooses to log it again:

```bash theme={null}
curl -X POST "https://punchplay.tv/api/platform/v1/title/show/100/season/2/watch" \
  -H "Authorization: Bearer ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "title":"Example Show",
    "year":2026,
    "watchedAt":"2026-07-18T20:00:00.000Z",
    "allowRewatches":true,
    "episodes":[{"episodeNumber":4,"name":"Episode 4","runtime":48,"airDate":"2026-07-10"}]
  }'
```

Watch dates cannot be in the future. Use `PATCH /api/platform/v1/watch-history/{id}` with a `watchedAt` body to edit a date, or `DELETE` to remove that entry.

## Ratings, favourites, and watch status

One interaction request can change any combination of rating, favourite state, or show status:

```bash theme={null}
curl -X PATCH "https://punchplay.tv/api/platform/v1/title/show/100/interact" \
  -H "Authorization: Bearer ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"rating":9,"isFavourite":true,"showStatus":"PLANNING"}'
```

Use the optional `scope`, `season`, and `episode` query parameters when the interaction targets a series, season, or episode rather than the title itself.

## Lists

Create a private list and add a title:

```bash theme={null}
curl -X POST "https://punchplay.tv/api/platform/v1/lists" \
  -H "Authorization: Bearer ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"name":"Weekend watches","description":"Films for Saturday night","isPublic":false}'

curl -X POST "https://punchplay.tv/api/platform/v1/lists/7/items" \
  -H "Authorization: Bearer ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"kind":"movie","sourceId":550,"title":"Fight Club"}'
```

List names are limited to 100 characters and descriptions to 500. Both reject links and inappropriate language.

List summaries include `externalSource`. Treat a non-null value as externally managed and read-only. Dynamic lists are also read-only for item changes. A watchlist cannot be renamed or deleted, but its items can be added and removed. Collaborators can change items on ordinary lists; only the owner can rename or delete the list.

For anime, send the normal routable `kind` (`movie` or `show`) and the source
identity. `isAnime: true` remains an optional compatibility hint. When alias
resolution selects a canonical TVDB identity, PunchPlay derives the anime
category automatically even if the hint is omitted.

## Collection

Add a physical or digital edition:

```bash theme={null}
curl -X POST "https://punchplay.tv/api/platform/v1/collection" \
  -H "Authorization: Bearer ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"kind":"movie","sourceId":550,"title":"Fight Club","year":1999,"format":"4k_bluray"}'
```

Valid formats are `4k_bluray`, `bluray`, `hd_dvd`, `dvd`, and `digital`. Adding the same title, season, and format again is idempotent and returns the existing item ID.

Reading the collection is paged — see [Pagination](#pagination). Follow
`nextCursor` when you need the user's whole collection rather than one screen.

## Continue Watching

Read the user's movie and episode progress:

```bash theme={null}
curl "https://punchplay.tv/api/platform/v1/me/continue-watching" \
  -H "Authorization: Bearer ACCESS_TOKEN"
```

Use `GET /api/platform/v1/me/continue-watching/{showId}` to resolve a show's current season and episode progress. Use `DELETE /api/platform/v1/playback/in-progress/{id}` when the user dismisses an item.

## Notifications

Developer apps can use the notification endpoints for an in-app inbox, unread badge, mark-read actions, and per-user notification preferences.

The `/me/push-devices` routes are reserved for first-party PunchPlay clients. Third-party apps must not register their device tokens with PunchPlay; use your own notification delivery service. PunchPlay's native push delivery requires a native iOS build and APNs credentials managed by PunchPlay.

## Current boundary

The versioned Platform API covers the core movie, TV, and anime experience, including notifications, trophies, profile editing, preferences, and authenticated community stats. Stable public discovery and community overview routes live under `/api/public/v1`.

Password changes, email changes, connected services, imports, and account deletion remain secure web experiences.

Anime is a PunchPlay category rather than a routable title kind. Titles retain a `movie` or `show` kind and TMDB identity, while mapped anime series use TVDB enrichment and official episode ordering.

See the generated API Reference in the Reference navigation for parameters and response contracts, and [Playback API](/playback-api) for lifecycle behavior.
