When you build a streaming app detail page, you pull catalog info (synopsis, images, release date) fromDocumentation Index
Fetch the complete documentation index at: https://docs.discovr.media/llms.txt
Use this file to discover all available pages before exploring further.
getMedia(). But that’s only half the story. You also need to know: Has this user already watched it? Did they like it? Can they resume?
That’s what getMediaProfileMeta() does. It’s the viewer’s relationship with a specific title—what list it’s on, how far they got, whether they’ve seen it before, and optionally where to watch it.
Think of it as layering user state on top of catalog facts. Your title sheet merges:
- Catalog (via
getMedia) — synopsis, images, cast, runtime - User state (via
getMediaProfileMeta) — liked/watchlist status, resume position, watch history
This endpoint requires an active profile session (start with
selectProfile()). The profile is determined
automatically from your session, so you only need to pass the mediaId.
See Sessions, Profiles & Sign Out for setup. Code samples use TypeScript / Kotlin / Swift.Four pieces of user state
getMediaProfileMeta() gives you four signals about how the viewer relates to this title:
List membership — liked, disliked, super_liked, watchlist are booleans. true means the user has added it to that list. Use these to show which buttons are “active” (full heart, solid thumbs up).
Playback — Is the user in the middle of watching? The playback object tells you whether they can resume and, if so, how far they got. For movies, it’s a simple percentage (0–100%). For TV, you also get the season and episode. This is what powers your “Resume from 45%” button.
History — A simple true or false that says whether the user has watched this title before. Use it for “Previously watched” badges, not as a substitute for playback position.
Providers (optional) — If you pass providers: true in your request, you’ll also get where-to-watch info (logos, links to streaming services). Skip this if your UI doesn’t need it—it costs extra on the backend.
How playback decides your button
The playback object has a simple contract: checkinlist first. If it’s false, there’s nothing to resume—show “Play”. If it’s true, check whether data is present to decide between “Resume at X%” and “Play”.
playback.inlist | Has data? | What it means | Your button |
|---|---|---|---|
false | — | Not watching this | ”Play” |
true | ✓ | Partially watched | ”Resume at X%” (show progress bar) |
true | ✗ | Started but not fully hydrated | ”Play” (fallback) |
data also includes season and episode so you can show “Resume Season 2, Episode 5” instead of just a percentage. For movies, it’s just a progress percentage.
Pro tip: Always check inlist before using data. A missing or stale data object with inlist: true is rare but possible—your fallback button should be “Play”.
Building your detail page
Fetching in parallel keeps your title sheet fast. When the user taps a title card:- Fetch
getMedia()for catalog (synopsis, images, cast) - Fetch
getMediaProfileMeta()for user state (resume position, lists) - Merge them into your view model
- Show your primary button based on
playback.inlistandplayback.data(Resume vs Play) - Wire your like/dislike/watchlist buttons to the booleans
- Show a “Previously watched” badge if
historyis true
getMediaProfileMeta() again to keep your UI in sync. For changes during playback, see Tracking Playback with Scrobbling.
When switching profiles — If your app supports multiple profiles, call selectProfile() to mint a new session JWT for the new profile, then refetch getMediaProfileMeta(). The catalog can stay cached; only the user state changes.
Example: Resume vs Play plus liked
The snippet shows playback.inlist gating Resume versus Play, alongside a trivial liked read.
Related reading
- Profile context — Overview of lists, playback, and syncing
- Tracking Playback with Scrobbling — How to keep watch history in sync as users watch
- Media details — Catalog info (
getMedia) - API Reference:
getMediaProfileMeta()·getMediaImages()