Initial Commit

This commit is contained in:
Luke Hagar
2023-03-24 08:40:02 -05:00
parent 0245850f4b
commit 83dd6a5357
42 changed files with 2530 additions and 0 deletions

0
Markdown/Accounts.md Normal file
View File

30
Markdown/Activities.md Normal file
View File

@@ -0,0 +1,30 @@
## Activities [/activities]
Activities are awesome. They provide a way to monitor and control asynchronous operations on the server. In order to receive real-time updates for activities, a client would normally subscribe via either EventSource or Websocket endpoints.
Activities are associated with HTTP replies via a special `X-Plex-Activity` header which contains the UUID of the activity.
Activities are optional cancellable. If cancellable, they may be cancelled via the `DELETE` endpoint. Other details:
- They can contain a `progress` (from 0 to 100) marking the percent completion of the activity.
- They must contain an `type` which is used by clients to distinguish the specific activity.
- They may contain a `Context` object with attributes which associate the activity with various specific entities (items, libraries, etc.)
- The may contain a `Response` object which attributes which represent the result of the asynchronous operation.
### Get all activities [GET /activities]
+ Response 200 (application/xml)
<MediaContainer size="1">
<Activity uuid="d6199ba1-fb5e-4cae-bf17-1a5369c1cf1e" cancellable="0" progress="7" subtitle="Downloaded 173 airings" title="Refreshing EPG" type="provider.epg.load" userID="1">
<Context name="value" />
<Response name="value" />
</Activity>
</MediaContainer>
### Cancel a running activity [DELETE /activities/{activity}]
+ Parameters
+ activity: `d6199ba1-fb5e-4cae-bf17-1a5369c1cf1e` - The UUID of the activity to cancel.
+ Response 200

37
Markdown/AutoUpdates.md Normal file
View File

@@ -0,0 +1,37 @@
## Auto-Updates [/updater]
This describes the API for searching and applying updates to the Plex Media Server.
Updates to the status can be observed via the Event API.
### Querying status of updates [GET /updater/status]
+ Response 200 (application/xml;charset=utf-8)
+ Body
<MediaContainer size="1" canInstall="0" autoUpdateVersion="1" checkedAt="1486011538" downloadURL="https://plex.tv/downloads/..." status="0">
<Release key="https://plex.tv/updater/releases/121" version="1.3.4.3285-b46e0ea" added="(Web) Updated Plex Web to 2.12.9.&#xD;&#xA;(Media Flags) Updated bundle to 2016-12-22 (#6033)" fixed="(DLNA) Crash browsing to certain photo library sections. (#5874)&#xD;&#xA;(Streaming Brain) Certain videos might transcode instead even when enough bandwidth was available to direct play. (#6085) (#6216)" downloadURL="https://plex.tv/downloads/latest/..." state="notify" />
</MediaContainer>
### Checking for updates [PUT /updater/check]
+ Parameters
+ download: `0` (bool, optional) - Indicate that you want to start download any updates found.
+ Response 200
### Applying updates [PUT /updater/apply{?tonight/skip}]
+ Parameters
+ tonight: `1` (bool, optional) - Indicate that you want the update to run during the next Butler execution. Omitting this or setting it to false indicates that the update should install immediately.
+ skip: `0` (bool, optional) - Indicate that the latest version should be marked as skipped. The <Release> entry for this version will have the `state` set to `skipped`.
Note that these two parameters are effectively mutually exclusive. The `tonight` parameter takes precedence and `skip` will be ignored if `tonight` is also passed.
+ Response 200
If the update process started correctly
+ Body
+ Response 500
If the update process failed to start
+ Body

53
Markdown/Butler.md Normal file
View File

@@ -0,0 +1,53 @@
## Group Butler [/butler]
### Starting all Butler tasks [POST /butler]
This endpoint will attempt to start all Butler tasks that are enabled in the settings. Butler tasks normally run automatically during a time window configured on the server's Settings page but can be manually started using this endpoint. Tasks will run with the following criteria:
1. Any tasks not scheduled to run on the current day will be skipped.
2. If a task is configured to run at a random time during the configured window and we are outside that window, the task will start immediately.
3. If a task is configured to run at a random time during the configured window and we are within that window, the task will be scheduled at a random time within the window.
4. If we are outside the configured window, the task will start immediately.
+ Response 200 (no data)
### Stopping all Butler tasks [DELETE /butler]
This endpoint will stop all currently running tasks and remove any scheduled tasks from the queue.
+ Response 200 (no data)
### Starting a single Butler task [POST /butler/{taskName}/]
This endpoint will attempt to start a specific Butler task by name.
This is the current list of tasks that can be used with this endpoint:
+ Parameters
+ taskName: `BackupDatabase` - the name of the task to be started.
+ Members
+ BackupDatabase
+ BuildGracenoteCollections
+ CheckForUpdates
+ CleanOldBundles
+ CleanOldCacheFiles
+ DeepMediaAnalysis
+ GenerateAutoTags
+ GenerateChapterThumbs
+ GenerateMediaIndexFiles
+ OptimizeDatabase
+ RefreshLibraries
+ RefreshLocalMedia
+ RefreshPeriodicMetadata
+ UpgradeMediaAnalysis
+ Response 200 (if the task was started. 202 if the task was already running.)
### Stopping a single Butler task [DELETE /butler/{taskName}/]
This endpoint will stop a currently running task by name, or remove it from the list of scheduled tasks if it exists. See the section above for a list of task names for this endpoint.
+ Parameters
+ taskName: `BackupDatabase` - the name of the task to be started.
+ Response 200 (if the task was stopped. 404 if the task was not running.)

10
Markdown/Client Guide.md Normal file
View File

@@ -0,0 +1,10 @@
## Group Client Guide
### Group Best Practices
This section is intended to cover some API best practices for Plex clients.
#### Group Pre-play screens

0
Markdown/Diagnostics.md Normal file
View File

View File

27
Markdown/Events.md Normal file
View File

@@ -0,0 +1,27 @@
## Events
The server can notify clients in real-time of a wide range of events, from library scanning, to preferences being modified, to changes to media, and many other things. This is also the mechanism by which activity progress is reported.
Two protocols for receiving the events are available: EventSource (also known as SSE), and WebSocket.
By default, all events except logs are sent. A rich filtering mechanism is provided to allow clients to opt into or out of each event type using the `filters` parameter. For example:
- `filters=-log`: All event types except logs (the default).
- `filters=foo,bar`: Only the foo and bar event types.
- `filters=`: All events types.
- `filters=-foo,bar`: All event types except foo and bar.
### Connect to WebSocket [GET /:/websocket/notifications{?filters}]
+ Parameters
+ filters: `log` - A comma-separated list of event types to send. If the first character is a `-`, then a comma-separated list of event types not to send.
+ Response 200 (application/octet-stream)
### Connect to EventSource [GET /:/eventsource/notifications{?filters}]
+ Parameters
+ filters: `log` - Same as above.
+ Response 200 (text/event-stream)

40
Markdown/Index.md Normal file
View File

@@ -0,0 +1,40 @@
FORMAT: 1A
HOST: http://localhost:32400
# Plex Server API
Welcome to the Plex Media Server API.
<!-- include(Overview.md) -->
<!-- include(Accounts.md) -->
<!-- include(Activities.md) -->
<!-- include(AutoUpdates.md) -->
<!-- include(Butler.md) -->
<!-- include(Client Guide.md) -->
<!-- include(Diagnostics.md) -->
<!-- include(Directory Browser.md) -->
<!-- include(Events.md) -->
<!-- include(Library/Introduction.md) -->
<!-- include(Library/All.md) -->
<!-- include(Library/Auto Complete.md) -->
<!-- include(Library/Common.md) -->
<!-- include(Library/Hubs.md) -->
<!-- include(Library/Ingest.md) -->
<!-- include(Library/Media Queries.md) -->
<!-- include(Library/Play Queues.md) -->
<!-- include(Library/Playlists.md) -->
<!-- include(Library/Search.md) -->
<!-- include(Library/Sections.md) -->
<!-- include(Library/Tags.md) -->
<!-- include(Media Providers/Client Guide.md) -->
<!-- include(Media Providers/DVR.md) -->
<!-- include(Media Providers/Devices.md) -->
<!-- include(Media Providers/EPG.md) -->
<!-- include(Media Providers/Media Grabbers.md) -->
<!-- include(Media Providers/Media Providers.md) -->
<!-- include(Media Providers/Media Subscriptions.md) -->
<!-- include(Log.md) -->
<!-- include(Now Playing.md) -->
<!-- include(Preferences.md) -->
<!-- include(Statistics.md) -->
<!-- include(Media Feedback.md) -->

121
Markdown/Library/All.md Normal file
View File

@@ -0,0 +1,121 @@
## All [/library/sections/{sectionId}/all{?type,filters}]
This resource represents the set of items matching the provided filter parameters.
### Get the filtered items [GET]
Description for GET method (action) placeholder.
+ Parameters
+ sectionId: 1 (number, required) - Section identifier
+ type: 1 (number, optional) - Item type
+ filters (string, optional) - This fake parameter stands in for the various filter parameters
+ Request title=Zoolander (text/xml)
+ Response 200 (text/xml;charset=utf-8)
+ body
<?xml version="1.0" encoding="UTF-8"?>
<MediaContainer allowSync="1" art="/:/resources/movie-fanart.jpg" identifier="com.plexapp.plugins.library" librarySectionID="26" librarySectionTitle="Movies" librarySectionUUID="70cb5089-b165-429b-809a-9e0a31493abf" mediaTagPrefix="/system/bundle/media/flags/" mediaTagVersion="1436742334" size="1" thumb="/:/resources/movie.png" title1="Movies" title2="All Movies" viewGroup="movie" viewMode="65592">
<Video addedAt="1408525217" art="/library/metadata/1049/art/1434341184" chapterSource="media" contentRating="PG-13" duration="5129000" key="/library/metadata/1049" originallyAvailableAt="2001-09-27" primaryExtraKey="/library/metadata/1073" rating="6.0" ratingKey="1049" studio="Paramount Pictures" summary="FunnyStuff" tagline="3% Body Fat. 1% Brain Activity." thumb="/library/metadata/1049/thumb/1434341184" title="Zoolander" type="movie" updatedAt="1434341184" year="2001">
<Media aspectRatio="1.78" audioChannels="6" audioCodec="ac3" bitrate="6564" container="mkv" duration="5129000" height="576" id="827" videoCodec="mpeg2video" videoFrameRate="PAL" videoResolution="576" width="720">
<Part container="mkv" duration="5129000" file="O:\fatboy\Media\Ripped\Movies\Zoolander (2001).mkv" id="827" key="/library/parts/827/file.mkv" size="4208219125" />
</Media>
<Genre tag="Comedy" />
<Writer tag="Drake Sather" />
<Writer tag="Ben Stiller" />
<Director tag="Ben Stiller" />
<Country tag="Australia" />
<Country tag="Germany" />
<Role tag="Ben Stiller" />
<Role tag="Owen Wilson" />
<Role tag="Christine Taylor" />
</Video>
</MediaContainer>
### Set the fields of the filtered items [PUT /library/sections/{sectionId}/all{?type,filters,field%2Evalue,field%2Elocked,title%2Evalue,artist%2Etitle%2Evalue,artist%2Etitle%2Eid,album%2Etitle%2Evalue,album%2Etitle%2Eid}]
N.B. `field` in a parameter, represents any valid field for an item.
- **Parameters, extra documentation**
- artist.title.value
- When used with track, both artist.title.value and album.title.value need to be specified
- title.value usage
- Summary
- Tracks always rename and never merge
- Albums and Artists
- if single item and item without title does not exist, it is renamed.
- if single item and item with title does exist they are merged.
- if multiple they are always merged.
- Tracks
- Works as expected will update the track's title
- Single track: `/library/sections/{id}/all?type=10&id=42&title.value=NewName`
- Multiple tracks: `/library/sections/{id}/all?type=10&id=42,43,44&title.value=NewName`
- All tracks: `/library/sections/{id}/all?type=10&title.value=NewName`
- Albums
- Functionality changes depending on the existence of an album with the same title
- Album exists
- Single album: `/library/sections/{id}/all?type=9&id=42&title.value=Album 2`
- Album with id 42 is merged into album titled "Album 2"
- Multiple/All albums: `/library/sections/{id}/all?type=9&title.value=Moo Album`
- All albums are merged into the existing album titled "Moo Album"
- Album does not exist
- Single album: `/library/sections/{id}/all?type=9&id=42&title.value=NewAlbumTitle`
- Album with id 42 has title modified to "NewAlbumTitle"
- Multiple/All albums: `/library/sections/{id}/all?type=9&title.value=NewAlbumTitle`
- All albums are merged into a new album with title="NewAlbumTitle"
- Artists
- Functionaly changes depending on the existence of an artist with the same title.
- Artist exists
- Single artist: `/library/sections/{id}/all?type=8&id=42&title.value=Artist 2`
- Artist with id 42 is merged into existing artist titled "Artist 2"
- Multiple/All artists: `/library/sections/{id}/all?type=8&title.value=Artist 3`
- All artists are merged into the existing artist titled "Artist 3"
- Artist does not exist
- Single artist: `/library/sections/{id}/all?type=8&id=42&title.value=NewArtistTitle`
- Artist with id 42 has title modified to "NewArtistTitle"
- Multiple/All artists: `/library/sections/{id}/all?type=8&title.value=NewArtistTitle`
- All artists are merged into a new artist with title="NewArtistTitle"
- **Notes**
- Technically square brackets are not allowed in an URI except the Internet Protocol Literal Address
- RFC3513: A host identified by an Internet Protocol literal address, version 6 [RFC3513] or later, is distinguished by enclosing the IP literal within square brackets ("[" and "]"). This is the only place where square bracket characters are allowed in the URI syntax.
- Escaped square brackets are allowed, but don't render well
- **Todo**
- Check if `tagtype[].tag.tag-` syntax is currently correct
- **Parameters not representable in Api Blueprint**
- **tagtype[idx].tag.tag** (string, optional) - Creates tag and adds it as a tagging on each item in the set. - [idx] links the.tag.tag and .tagging.* parameters together)
- **tagtype[idx].tagging.object** (string, optional) - `object` may be text/thumb/art/theme - Optionally used in conjunction with tag.tag, to update tagging info across the set.
- **tagtype[].tag.tag-** (string, optional) - Remove comma separated tags from the set of items
- **tagtype[].tag** (string, optional) - Remove all taggings of this type (e.g. genre) from the set of items
+ Parameters
+ sectionId: 1 (number, required) - Section identifier
+ type: 1 (number, required) - Item type
+ filters (string, optional) - This fake parameter stands in for the various filter parameters.
+ field%2Evalue (string, optional) - Updates `field` across the filtered set of items.
+ field%2Elocked: 1 (number, optional) - Updates the locked state of `field` across the set. Valid values: 0 or 1.
+ title%2Evalue (string, optional) - This field is treated specially by albums or artists and may be used for implicit reparenting.
+ artist%2Etitle%2Evalue (string, optional) - Reparents set of Tracks or Albums - used with album.title.* in the case of tracks
+ artist%2Etitle%2Eid (string, optional) - Reparents set of Tracks or Albums - used with album.title.* in the case of tracks
+ album%2Etitle%2Evalue (string, optional) - Reparents set of Tracks - Must be used in conjunction with artist.title.value or id
+ album%2Etitle%2Eid (string, optional) - Reparents set of Tracks - Must be used in conjunction with artist.title.value or id
+ Request Example put (text/xml)
Description for request placeholder.
+ body
+ Response 200 (text/html)
Description for response placeholder.
+ body
+ Response 400 (text/html)
<html><head><title>Bad Request</title></head><body><h1>400 Bad Request</h1></body></html>

View File

@@ -0,0 +1,72 @@
## Autocomplete [/library/sections/{sectionId}/autocomplete{?type,field%2Equery,filters}]
The field to autocomplete on is specified by the {field}.query parameter.
For example `genre.query` or `title.query`.
Returns a set of items from the filtered items whose {field} starts with {field}.query.
- Todo:
- As implemented the endpoint does not seem to be reflecting the tag type in the element at the moment
- Find all supported filters for autocomplete (We may have missing joins for some filters)
+ Parameters
+ sectionId: 1 (number, required) - Section identifier
+ type: 1 (number, required) - Item type
+ field%2Equery (string, required) - "field" stands in for any field, the value is a partial string for matching
+ filters (string, optional) - This fake parameter stands in for the various filter parameters
### Retrieve matching tags or items [GET]
+ Request With title.query=a (text/xml)
+ Response 200 (text/xml;charset=utf-8)
Example returning items
+ Body
<?xml version="1.0" encoding="UTF-8"?>
<MediaContainer allowSync="0" art="/:/resources/movie-fanart.jpg" content="secondary" identifier="com.plexapp.plugins.library" mediaTagPrefix="/system/bundle/media/flags/" mediaTagVersion="1436742334" size="2" thumb="/:/resources/movie.png" title1="Movies" viewGroup="secondary" viewMode="65592">
<Video addedAt="1408492156" art="/library/metadata/1024/art/1434341159" chapterSource="media" contentRating="R" duration="6627200" key="/library/metadata/1024" originallyAvailableAt="2002-12-06" primaryExtraKey="/library/metadata/1051" rating="7.1" ratingKey="1024" studio="Columbia Pictures" summary="A love-lorn script writer grows increasingly desperate in his quest to adapt the book 'The Orchid Thief'." tagline="Charlie Kaufman writes the way he lives... With Great Difficulty. His Twin Brother Donald Lives the way he writes... with foolish abandon. Susan writes about life... But can't live it. John's life is a book... Waiting to be adapted. One story... Four Lives... A million ways it can end." thumb="/library/metadata/1024/thumb/1434341159" title="Adaptation." title.queryRange="0,0" type="movie" updatedAt="1434341159" year="2002">
<Media aspectRatio="1.78" audioChannels="6" audioCodec="ac3" bitrate="5421" container="mkv" duration="6627200" height="576" id="802" videoCodec="mpeg2video" videoFrameRate="PAL" videoResolution="576" width="720">
<Part container="mkv" duration="6627200" file="O:\fatboy\Media\Ripped\Movies\Adaptation (2002).mkv" id="802" key="/library/parts/802/file.mkv" size="4490974984" />
</Media>
<Genre tag="Comedy" />
<Genre tag="Crime" />
<Writer tag="Charlie Kaufman" />
<Writer tag="Donald Kaufman" />
<Director tag="Spike Jonze" />
<Country tag="USA" />
<Role tag="Nicolas Cage" />
<Role tag="Meryl Streep" />
<Role tag="Chris Cooper" />
</Video>
<Video addedAt="1407669060" art="/library/metadata/1025/art/1434341158" chapterSource="media" duration="5165210" key="/library/metadata/1025" originalTitle="Neco z Alenky" originallyAvailableAt="1988-08-03" rating="6.9" ratingKey="1025" studio="Channel Four Films" summary="A memorably bizarre screen version of Lewis Carroll's novel 'Alice's Adventures in Wonderland'. The original story is followed reasonably faithfully, though those familiar with this director's other films won't be the least bit surprised by the numerous digressions into Svankmajer territory, living slabs of meat and all. As the opening narration says, it's a film made for children... perhaps?" thumb="/library/metadata/1025/thumb/1434341158" title="Alice" title.queryRange="0,0" type="movie" updatedAt="1434341158" year="1988">
<Media aspectRatio="1.33" audioChannels="2" audioCodec="ac3" bitrate="6672" container="mkv" duration="5165210" height="480" id="803" videoCodec="mpeg2video" videoFrameRate="NTSC" videoResolution="480" width="720">
<Part container="mkv" duration="5165210" file="O:\fatboy\Media\Ripped\Movies\Alice (1988).mkv" id="803" key="/library/parts/803/file.mkv" size="4308069440" />
</Media>
<Genre tag="Animation" />
<Genre tag="Fantasy" />
<Writer tag="Jan ?vankmajer" />
<Director tag="Jan ?vankmajer" />
<Country tag="Switzerland" />
<Country tag="Czech Republic" />
<Role tag="Krist?na Kohoutov?" />
</Video>
</MediaContainer>
+ Request With genre.query=a (text/xml)
+ Response 200 (text/xml;charset=utf-8)
Example returning tags
+ Headers
Accept: text/xml
+ Body
<?xml version="1.0" encoding="UTF-8"?>
<MediaContainer allowSync="0" art="/:/resources/movie-fanart.jpg" content="secondary" identifier="com.plexapp.plugins.library" mediaTagPrefix="/system/bundle/media/flags/" mediaTagVersion="1436742334" size="3" thumb="/:/resources/movie.png" title1="Movies" viewGroup="secondary" viewMode="65592">
<Directory id="190" tag="Action" tagType="1" />
<Directory id="98" tag="Adventure" tagType="1" />
<Directory id="135" tag="Animation" tagType="1" />
</MediaContainer>

View File

@@ -0,0 +1,62 @@
## Common [/library/sections/{sectionId}/common{?type,filters}]
Represents a "Common" item. It contains only the common
attributes of the items selected by the provided filter
+ Parameters
+ sectionId: 1 (number, required) - Section identifier
+ type: 1 (number, required) - Item type
+ filters (string, optional) - This fake parameter stands in for the various filter parameters
### Retrieve the common item [GET]
+ Request No common items in filter set (text/xml)
+ Response 200 (text/xml;charset=utf-8)
+ Body
<?xml version="1.0" encoding="UTF-8"?>
<MediaContainer allowSync="0" art="/:/resources/movie-fanart.jpg" content="secondary" identifier="com.plexapp.plugins.library" mediaTagPrefix="/system/bundle/media/flags/" mediaTagVersion="1436742334" size="1" thumb="/:/resources/movie.png" title1="Movies" title2="Common" viewGroup="secondary" viewMode="65592">
<Common guid="" index="1" mixedFields="title,ratingKey,titleSort,tagline,rating,summary,year,studio,originallyAvailableAt,originalTitle,contentRating" ratingCount="0" titleSort="" type="common">
</Common>
</MediaContainer>
+ Request All filtered items are common (text/xml)
+ Response 200 (text/xml;charset=utf-8)
+ Body
<?xml version="1.0" encoding="UTF-8"?>
<MediaContainer allowSync="0" art="/:/resources/movie-fanart.jpg" content="secondary" identifier="com.plexapp.plugins.library" mediaTagPrefix="/system/bundle/media/flags/" mediaTagVersion="1436742334" size="1" thumb="/:/resources/movie.png" title1="M
ovies" title2="Common" viewGroup="secondary" viewMode="65592">
<Common guid="" index="1" key="/library/metadata/1025/children" mixedFields="" originalTitle="Neco z Alenky" originallyAvailableAt="1988-08-03" rating="6.9" ratingCount="0" ratingKey="1025" studio="Channel Four Films" summary="A memorably bizarre
screen version of Lewis Carroll's novel 'Alice's Adventures in Wonderland'. The original story is followed reasonably faithfully, though those familiar with this director's other films won't be the least bit surprised by the numerous digressions int
o Svankmajer territory, living slabs of meat and all. As the opening narration says, it's a film made for children... perhaps?" title="Alice" titleSort="Alice" type="common" year="1988">
<Genre id="135" tag="Animation" />
<Genre id="136" tag="Fantasy" />
<Genre id="42" tag="Science Fiction" />
<Writer id="133" tag="Jan ?vankmajer" />
<Director id="132" tag="Jan ?vankmajer" />
<Country id="137" tag="Switzerland" />
<Country id="138" tag="Czech Republic" />
<Country id="130" tag="Germany" />
<Country id="139" tag="United Kingdom" />
<Role id="134" role="Alice" tag="Krist?na Kohoutov?" />
</Common>
</MediaContainer>
+ Response 400 (text/html)
In response to missing the type parameter.
+ Body
<html><head><title>Bad Request</title></head><body><h1>400 Bad Request</h1></body></html>
+ Response 404 (text/html)
In response to a non-existant sectionId.
+ Body
<html><head><title>Not Found</title></head><body><h1>404 Not Found</h1></body></html>

View File

@@ -0,0 +1,26 @@
## Hashes [/library/hashes{?url,type}]
This resource returns hash values for local files.
### Get the hash values [GET]
+ Parameters
+ url (string, required) - This is the path to the local file, must be prefixed by `file://`
+ type: 1 (number, required) - Item type
+ Request url=file://C:\Image.png&type=13 (text/xml)
+ Response 200 (text/xml;charset=utf-8)
+ body
<?xml version="1.0" encoding="UTF-8"?>
<MediaContainer size="1" identifier="com.plexapp.plugins.library" mediaTagPrefix="/system/bundle/media/flags/" mediaTagVersion="1519299020">
<Photo>
<Media>
<Part file="file://C:\Image.png" size="12038" hash="12038d462e114dbf98dc0b8feccdc134367540f1eb068"></Part>
</Media>
</Photo>
</MediaContainer>

24
Markdown/Library/Hubs.md Normal file
View File

@@ -0,0 +1,24 @@
## Group Hubs
Hubs are a structured two-dimensional container for media, generally represented by multiple horizontal rows. Hubs have the following attributes:
- `key`: The URL for the full list of items for the hub, used to page in more data, when available.
- `hubKey`: Represents the URL for the exact items returned in the hub request (used, e.g. as a key for generating a play queue). [Editor: is this right?]
- `type`: The type of the items in the hub (same format as metadata item type, e.g. `movie`). Can also be `mixed` to indicate heterogeneous types present.
- `hubIdentifier`: A unique identifier for the hub, used to distinguish it from all other hubs in the group.
- `size`: The number of items returned with the hub.
- `title`: The localized title of the hub.
- `more`: (0/1) Whether or not there are more items beyond those returned. If so, the `key` can be used to obtain them.
When requesting hubs, the following parameters are generally accepted. Note that other common library parameters may be used as well, e.g. `excludeFields`:
- `count`: The number of items to return with each hub.
- `onlyTransient`: Only return hubs which are "transient", meaning those which are prone to changing after media playback or addition (e.g. On Deck, or Recently Added)
### Get global hubs [GET /hubs]
+ Response 200
### Get library specific hubs [GET /hubs/sections/{section}]
+ Response 200

View File

@@ -0,0 +1,19 @@
## Group Ingest
### Ingest a transient item [POST /library/file{?url,computeHashes}]
This endpoint takes a file path specified in the `url` parameter, matches it using the UMP, downloads rich metadata, and then ingests the item as a transient item (without a library section). In the case where the file represents an episode, the entire tree (show, season, and episode) is added as transient items. At this time, movies and episodes are the only supported types, which are gleaned automatically from the file path.
Note that any of the parameters passed to the metadata details endpoint (e.g. `includeExtras=1`) work here.
+ Parameters
+ url: `file:///storage%2Femulated%2F0%2FArcher-S01E01.mkv` - The file of the file to ingest.
+ virtualFilePath: `/Avatar.mkv` - A virtual path to use when the url is opaque.
+ computeHashes: `1` (boolean, optional) - Whether or not to compute Plex and OpenSubtitle hashes for the file. Defaults to 0.
+ ingestNonMatches: `1` (boolean, optional) - Whether or not non matching media should be stored. Defaults to 0.
+ Response 200 (application/xml)
<MediaContainer size="1">
<Video ...>
</MediaContainer>

View File

@@ -0,0 +1,71 @@
## The Media Hierarchy
Plex uses a consistent media hierarchy across all media types, from photos to movies to TV shows.
**Metadata Item**: This is the root of the hierarchy, representing the metadata layer (as opposed to more media-focused details). In here, for example, we'll find the title and summary of the movie, episode number for a TV episode, etc.
**Media Item**: The metadata item can have 1 or more media items (unless it's a container type, read more below). Each of these represents an alternative source for the media. For example, a user might have 1080p and 720p versions of a movie. In the cloud, alternate items might be offered via HLS or direct MP4 download. The items are generally listed in quality order, with the highest quality one listed first.
**Media Part**: Each media item can have 1 or more media parts. Each of these represents a sequential piece of the media which must be played in sequence. For example an AVI split across two CD1/CD2 parts. Split parts are generally confined to video files. In the future, it's possible we may choose to allow things like pre-roll and post-roll clips via this mechanism as well.
**Media Stream**: Each media part can have 1 or more media streams. These represent the elementary components of a media file. There are a few types of streams (video, audio, subtitle, and lyric), and they can either represent streams internal to a media part, or "sidecar" files (e.g. an SRT subtitle file). Note that photos do not have streams (mostly as an optimization).
In some cases, metadata items themselves live in a hierarchy. For example artists have albums, and albums have tracks. TV shows have seasons, which have episodes. These container items are still metadata items, but they don't have any media items.
When items at other levels of the hierarchy are referred to, we generally use relative or absolute nomenclature. For example, "leaves" is used to refer to any item in the hierarchy which has media items (e.g. movies, episodes, audio tracks). At the show level, seasons are "children" and episodes are "grandchildren". At the episode level, seasons are "parents" and shows are "grandparents".
Depending on the set of items being passed back, they can have additional ancestor data. The general rule for this is whether or not the set of items is coming from mixed ancestors or not. For example, when returning a season's worth of episodes from the same show, the container itself would have references to parent and grandparent data. However, when returning a list of recently added episodes, these would _each_ contain references to ancestral data.
## Metadata and Media Attributes
In this section we'll examine the attributes present with each object in the media hierarchy, and discuss their format and purpose. Many of the attributes are common across the entire hierarchy from grandparents to grandchildren, which makes their consumption greatly simplified. Here is a list of the attributes in a metadata item:
- `key`: A URL (absolute, or relative) for obtaining item "details". In many cases, when you encounter a metadata item, it has less than full details, because those would be prohibitively expensive to retrieve and send back at all times. The details endpoint returns all data associated with the item (including some which is opted into via the various `includeXXX` query string options).
- `ratingKey`: This is an opaque string which is used to pass back to timeline, scrobble, and rating endpoints, to uniquely identify the item.
- `type`: A string representing the type of the item, with the following possible values: movie, show, season, episode, trailer, artist, album, track, photo, playlist, clip, directory.
- `title`: The title (e.g. "300" or "The Simpsons").
- `titleSort`: (optional) This is the string used for sorting the item. It's usually the title with any leading articles removed (e.g. "Simpsons").
- `originalTitle`: (optional) When present, used to indicate an item's original title, e.g. a movie's foreign title.
- `year`: (optional) The year associated with the item's release (e.g. release year for a movie).
- `index`: (optional) This represents the episode number for episodes, season number for seasons, or track number for audio tracks.
- `absoluteIndex` (optional): When present, contains the disc number for a track on multi-disc albums.
- `originallyAvailableAt`: (optional) In the format `YYYY-MM-DD [HH:MM:SS]` (the hours/minutes/seconds part is not always present). The air date, or a higher resolution release date for an item, depending on type. For example, episodes usually have air date like `1979-08-10` (we don't use epoch seconds because items can pre-date the epoch). In some cases, recorded over-the-air content has higher resolution air date which includes a time component. Albums and movies may have day-resolution release dates as well.
- `duration`: (Optional) The duration for the item, in units of milliseconds.
- `summary`: (optional) Extended textual information about the item (e.g. movie plot, artist biography, album review).
- `tagline`: (optional) Pithy one-liner about the item (usually only seen for movies).
- `thumb`: (optional) The URL for the poster or thumbnail for the item. When available for types like movie, it will be the poster graphic, but fall-back to the extracted media thumbnail.
- `art`: (optional) The URL for the background artwork for the item.
- `banner`: (optional) The URL for a banner graphic for the item.
- `hero`: (optional) The URL for a hero image for the item.
- `theme`: (optional) The URL for theme music for the item (usually only for TV shows).
- `composite`: (optional) When present, the URL for a composite image for descendent items (e.g. photo albums).
- `studio`: (optional) The studio or label which produced an item (e.g. movie studio for movies, record label for albums).
- `contentRating` (optional): If known, the content rating (e.g. MPAA) for an item.
- `rating` (optional): The rating, representing as a floating point number from 0 to 10 for the item. The exact meaning and representation depends on where the rating was sourced from.
- `ratingImage` (optional): When present, indicates an image to be shown with the rating. This is passed back as a small set of defined URI values, e.g. `rottentomatoes://image.rating.rotten`.
- `audienceRating` (optional): Some rating systems separate reviewer ratings from audience ratings. Expressed as a floating point number from 0 to 10.
- `audienceRatingImage`: (optional) A URI representing the image to be shown with the audience rating (e.g. `rottentomatoes://image.rating.spilled`).
- `userRating`: (optional) When the user has rated an item, this contains the user rating (floating point number from 0 to 10).
- `viewOffset`: (optional) When a user is in the process of viewing or listening to this item, this attribute contains the current offset, in units of milliseconds.
- `viewCount`: (optional) When a users has completed watched or listened to an item, this attribute contains the number of consumptions.
- `lastViewedAt`: (optional) When a user has watched or listened to an item, this contains a timestamp (epoch seconds) for that last consumption time.
- `addedAt`: (optional) In units of seconds since the epoch, returns the time at which the item was added to the library.
- `updatedAt`: (optional) In units of seconds since the epoch, returns the time at which the item was last changed (e.g. had its metadata updated).
- `chapterSource`: (optional) When present, indicates the source for the chapters in the media file. Can be `media` (the chapters were embedded in the media itself), `agent` (a metadata agent computed them), or `mixed` (a combination of the two).
- `primaryExtraKey`: (optional) Indicates that the item has a primary extra; for a movie, this is a trailer, and for a music track it is a music video. The URL points to the metadata details endpoint for the item.
- `skipChildren`: (optional) When found on a show item, indicates that the children (seasons) should be skipped in favor of the grandchildren (episodes). Useful for mini-series, etc.
- `skipParent`: (optional) When present on an episode or track item, indicates parent should be skipped in favor of grandparent (show).
- `leafCount`: For shows and seasons, contains the number of total episodes.
- `viewedLeafCount`: For shows and seasons, contains the number of viewed episodes.
### Ancestor Attributes
As explained above, items can contain ancestral attributes used to facilitate browsing up the tree as well as full display of an item without needing to request additional data. These can include: `parentKey`, `grandparentKey`, `parentRatingKey`, `grandparentRatingKey`, `parentThumb`, `grandparentThumb`, `grandparentArt`, `parentHero`, `grandparentHero`, `grandparentTheme`, `parentTitle`, `grandparentTitle`, `parentIndex`.
## Common Request Parameters
There are some common query string parameters which can be passed to almost all library endpoints. It is generally considered a hint to the server or media provider, and clients should not rely on the data being filtered from the response.
- `excludeFields`: This option is used to elide data in responses. The value is a comma-separated list of fields to avoid returning. The only supported fields are currently `summary`, `tagline` and `file`.
- `excludeElements`: This option is used to elide entire elements from the response. Supported values are `Media`, `Part`, `Mood`, and any tag fields (e.g. `Genre`, `Role`, or `Director`).

View File

@@ -0,0 +1,96 @@
### Get library matches [GET /library/matches{?type,includeFullMetadata,includeAncestorMetadata,includeAlternateMetadataSources}]
The matches endpoint is used to match content external to the library with content inside the library. This is done by passing a series of semantic "hints" about the content (its type, name, or release year). Each type (e.g. movie) has a canonical set of minimal required hints.
This ability to match content is useful in a variety of scenarios. For example, in the DVR, the EPG uses the endpoint to match recording rules against airing content. And in the cloud, the UMP uses the endpoint to match up a piece of media with rich metadata.
The endpoint response can including multiple matches, if there is ambiguity, each one containing a `score` from 0 to 100. For somewhat historical reasons, anything over 85 is considered a positive match (we prefer false negatives over false positives in general for matching).
The `guid` hint is somewhat special, in that it generally represents a unique identity for a piece of media (e.g. the IMDB `ttXXX`) identifier, in contrast with other hints which can be much more ambiguous (e.g. a title of `Jane Eyre`, which could refer to the 1943 or the 2011 version).
#### Movies
The following hints are allowed:
- `guid`: allowed for various URI schemes, to be defined.
- `title`: required if `path` is not specified.
- `year`: optional.
- `path`: the full path to the movie file, used for "cloud-scanning" an item.
#### Shows
The following hints are allowed:
- `guid`: for URI schemes to be defined.
- `title`: required if `guid` is not passed.
- `year`: optional.
#### Episodes
Episodes require either a season/episode pair, or an air date (or both). Either the path must be sent, or the show title. The following hints are allowed:
- `grandparentTitle`: the title of the show. Required if `path` isn't passed.
- `grandparentYear`: the year of the show.
- `parentIndex`: the season.
- `index`: the episode.
- `originallyAvailableAt`: in the format `YYYY-MM-DD`.
- `path`: the full path to the episode file, can be provided in lieu of all other hints.
#### Artists
The following hints are allowed:
- `guid`: for URI schemes to be defined.
- `title`: the artist name.
#### Albums
The following hints are allowed:
- `guid`: for URI schemes to be defined.
- `parentTitle`: the artist name.
- `title`: the album name.
- `year`: the album year.
#### Tracks
The following hints are required:
- `guid`: for URI schemes to be defined.
- `grandparentTitle`: the artist name.
- `parentTitle`: the album name.
- `title`: the track name.
- `index`: the track index.
- `parentIndex`: the disc index for multi-disc albums.
- `path`: the full path to the track, can be provided in lieu of all other hints.
#### Podcasts
The following hints is required:
- `url`: the URL for the podcast feed.
#### Podcast Episodes
The following hints are required:
- `url`: the URL for the podcast feed.
- `originallyAvailableAt`: The air date for the episode.
+ Parameters
+ type: `1` (integer) - The metadata type we're attempting to match.
+ includeFullMetadata: `1` (boolean, optional) - Whether or not to include full metadata on a positive match. When set, and the best match exceeds a score threshold of 85, metadata as rich as possible is sent back.
+ Default: `0`
+ includeAncestorMetadata: `1` (boolean, optional) - Whether or not to include metadata for the item's ancestor (e.g. show and season data for an episode).
+ Default: `0`
+ includeAlternateMetadataSources: `1` (boolean, optional) - Whether or not to return all sources for each metadata field, which results in a different structure being passed back.
+ Default: `0`
+ Response 200 (application/xml)
```
<MediaContainer size="1">
<Video score="100" ratingKey="667573" key="/library/metadata/667573" studio="Shamley Productions" type="movie" title="Psycho" />
</MediaContainer>
```

View File

@@ -0,0 +1,87 @@
# Media Queries
Media queries are a querystring-based filtering language used to select subsets of media. The language is rich, and can express complex expressions for media selection, as well as sorting and grouping.
### Fields
Queries reference fields, which can be of a few types:
* *integer*: numbers
* *boolean*: true/false
* *tag*: integers representing tag IDs.
* *string*: strings
* *date*: epoch seconds
* *language*: string in ISO639-2b format.
These fields are detailed in `Field` elements in the section description endpoint (e.g. `/library/sections/X?includeDetails=1`).
### Operators
Given that media queries are expressible using querystrings, the operator syntax might look a bit quirky, because a) they have to include the `=` character, and b) characters to the left of the equal sign usually have to be URI encoded.
Operators are defined per type:
* *integer*: `=` (equals), `!=` (not equals), `>>=` (greater than), `<<=` (less than), `<=` (less than or equals), `>=` (greater than or equals)
* *boolean*: `=0` (false) and `=1` (true)
* *tag*: `=` (is) and `!=` (is not)
* *string*: `=` (contains), `!=` (does not contain), `==` (equals), `!==` (does not equal), `<=` (begins with), `>=` (ends with)
* *date*: `=` (equals), `!=` (not equals), `>>=` (after), `<<=` (before)
* *language*: `=` (equals), `!=` (not equals)
### Relative Values and Units
For some types, values can be specified as relative. For dates, epoch seconds can be specified as relative to “now” as follows: `+N` (in N seconds from now and `-N` (N seconds ago).
In addition, the following unit suffixes can be used on date values:
* *m*: minutes
* *h*: hours
* *d*: days
* *w*: weeks
* *mon*: months
* *y*: years
For example, `>>=-3y` means “within the last 3 years”.
### Field Scoping
Some media is organized hierarchically (e.g. shows), and in those cases, many fields are common to different elements in the hierarchy (e.g. show title vs episode title). The following rules are used to resolve field references.
* A `type` parameter must be included to specify the result type.
* Any non-qualified field is defaulted to refer to the result type.
* In order to refer to other levels of the hierarchy, use the scoping operator, e.g. `show.title` or `episode.year`. A query may be comprised of multiple fields from different levels of the hierarchy.
* the `sourceType` parameter may be used to change the default level to which fields refer. For example, `type=4&sourceType=2&title==24` means “all episodes where the show title is 24”.
### Sorting
The `sort` parameter is used to indicate an ordering on results. Typically, the sort value is a field (including optional scoping). The `:` character is used to indicate additional features of the sort, and the `,` character is used to include multiple fields to the sort.
For example, `sort=title,index` means “sort first by title ascending, then by index”. Sort features are:
* *desc*: indicates a descending sort.
* *nullsLast*: indicates that null values are sorted last.
Sort features may be mixed and matched, e.g. `sort=title,index:desc`.
### Grouping
The `group` parameter is used to group results by a field, similar to the SQL feature `group by`. For example, when listing popular tracks, we use the query `type=10&sort=ratingCount:desc&group=title`, because we dont want multiple tracks with the same name (e.g. same track on different albums) showing up.
### Limits
The `limit` parameter is used to limit the number of results returned. Because its implemented on top of the SQL `limit` operator, it currently only operates at the level of the type returned. In other words, `type=10&limit=100` will return at most 100 tracks, but you cant select tracks from a limit of 10 _albums_.
### Boolean Operators
Given the nature of querystrings, it makes a lot of sense to interpret the `&` character as a boolean AND operator. For example `rating=10&index=5` means “rating is 10 AND index is 5”.
We leverage the `,` operator to signify the boolean OR operator. SO `rating=1,2,3` means “rating is 1 OR 2 OR 3. Given standard precedence rules, `rating=1,2,3&index=5` is parsed as `(rating = 1 or rating = 2 or rating = 3) and index = 5)`.
### Complex Expressions
Theres only so many expressions you can form using vanilla querystring-to-boolean mapping (essentially, “ANDs of ORs”). In order to fully represent complex boolean expressions, there are a few synthetic additions:
* *push=1* and *pop=1*: These are the equivalent of opening and closing parenthesis.
* *or=1*: These is an explicit OR operator.
As an example: `push=1&index=1&or=1&rating=2&pop=1&duration=10` parses into `(index = 1 OR rating = 2) AND duration = 10`. This could not be expressed by the simplified syntax above.
Happy query building!

View File

@@ -0,0 +1,154 @@
## Play queues [/playQueues]
A play queue represents the current list of media for playback. Although queues are persisted by the server, they should be regarded by the user as a fairly lightweight, an ephemeral list of items queued up for playback in a session.  There is generally one active queue for each type of media (music, video, photos) that can be added to or destroyed and replaced with a fresh queue.
Play Queues has a region, which we refer to in this spec (partially for historical reasons) as "Up Next". This region is defined by `playQueueLastAddedItemID` existing on the media container. This follows iTunes' terminology. It is a special region after the currently playing item but before the originally-played items. This enables "Party Mode" listening/viewing, where items can be added on-the-fly, and normal queue playback resumed when completed. 
You can visualize the play queue as a sliding window in the complete list of media queued for playback. This model is important when scaling to larger play queues (e.g. shuffling 40,000 audio tracks). The client only needs visibility into small areas of the queue at any given time, and the server can optimize access in this fashion.
All created play queues will have an empty "Up Next" area - unless the item is an album and no `key` is provided. In this case the "Up Next" area will be populated by the contents of the album. This is to allow queueing of multiple albums - since the 'Add to Up Next' will insert after all the tracks. This means that If you're creating a PQ from an album, you can only shuffle it if you set `key`. This is due to the above implicit queueing of albums when no `key` is provided as well as the current limitation that you cannot shuffle a PQ with an "Up Next" area.
The play queue window advances as the server receives timeline requests. The client needs to retrieve the play queue as the “now playing” item changes. There is no play queue API to update the playing item.
### Create a play queue [POST /playQueues{?uri,playlistID,type,key,shuffle,repeat,continuous,limit,extrasPrefixCount,recursive,ondeck}]
Makes a new play queue for a device. The source of the playqueue can either be a URI, or a playlist. The response is a media container with the initial items in the queue. Each item in the queue will be a regular item but with `playQueueItemID` - a unique ID since the queue could have repeated items with the same `ratingKey`.
The media container itself has a few special attributes:
- `playQueueID`: The ID of the play queue, which is used in subsequent requests.
- `playQueueSelectedItemID`: The queue item ID of the currently selected item.
- `playQueueSelectedItemOffset`: The offset of the selected item in the play queue, from the beginning of the queue.
- `playQueueSelectedMetadataItemID`: The metadata item ID of the currently selected item (matches `ratingKey` attribute in metadata item).
- `playQueueShuffled`: Whether or not the queue is shuffled.
- `playQueueSourceURI`: The original URI used to create the play queue.
- `playQueueTotalCount`: The total number of items in the play queue.
- `playQueueVersion`: The version of the play queue. It increments every time a change is made to the play queue to assist clients in knowing when to refresh.
- `playQueueLastAddedItemID`: Defines where the "Up Next" region starts
+ Parameters
+ uri: library://... (string) - the content URI for what we're playing.
+ playlistID: 123 (string, optional) - the ID of the playlist we're playing.
+ type: audio (string) - must be either `audio`, `video`, `photo`.
+ key: 1234 (string, optional) - the key of the first item to play, defaults to the first in the play queue.
+ shuffle: 0 (boolean, optional) - whether to shuffle the playlist, defaults to 0.
+ repeat: 0 (boolean, optional) - if the PQ is bigger than the window, fill any empty space with wraparound items, defaults to 0.
+ continuous: 0 (boolean, optional) - whether to create a continuous play queue (e.g. from an episode), defaults to 0.
+ extrasPrefixCount: 3 (optional) - number of trailers to prepend a movie with not including the pre-roll. If omitted the pre-roll will not be returned in the play queue. When resuming a movie `extrasPrefixCount` should be omitted as a parameter instead of passing 0.
+ recursive: 0 (boolean, optional) - only applies to queues of type photo, whether to retrieve all descendent photos from an album or section, defaults to 1.
+ onDeck: 0 (boolean, optional) - only applies to queues of type show or seasons,
whether to return a queue that is started on the On Deck episode if one exists.
Otherwise begins the play queue on the beginning of the show or season.
+ Response 200 (application/xml)
<MediaContainer size="21" playQueueID="9631" playQueueSelectedItemID="2211762" playQueueSelectedItemOffset="0" playQueueSelectedMetadataItemID="1941458" playQueueShuffled="0" playQueueSourceURI="library://2d8ea42e-7845-498b-b349-095ecaa3c451/item/%2Flibrary%2Fmetadata%2F1906642" playQueueTotalCount="22" playQueueVersion="1">
<Track playQueueItemID="2211762" />
</MediaContainer>
### Retrieve a play queue [GET /playQueues/{playQueue}{?own,center,window,includeBefore,includeAfter}]
Retrieves the play queue, centered at current item. This can be treated as a regular container by play queue-oblivious clients, but they may wish to request a large window onto the queue since they won't know to refresh.
+ Parameters
+ playQueue: 1023 (string) - the ID of the play queue.
+ own: 0 (boolean, optional) - if the server should transfer ownership to the requesting client (used in remote control scenarios).
+ center: 12345 (string, optional) - the play queue item ID for the center of the window - this doesn't change the current selected item.
+ window: 20 (optional) - how many items on each side of the center of the window
+ includeBefore: 1 (boolean, optional) - whether to include the items before the center (if 0, center is not included either), defaults to 1.
+ includeAfter: 1 (boolean, optional) - whether to include the items after the center (if 0, center is not included either), defaults to 1.
+ Response 200 (application/xml)
<MediaContainer size="21" playQueueID="9631" playQueueSelectedItemID="2211762" playQueueSelectedItemOffset="0" playQueueSelectedMetadataItemID="1941458" playQueueShuffled="0" playQueueSourceURI="library://2d8ea42e-7845-498b-b349-095ecaa3c451/item/%2Flibrary%2Fmetadata%2F1906642" playQueueTotalCount="22" playQueueVersion="1">
<Track playQueueItemID="2211762" />
...
</MediaContainer>
### Add a generator or playlist to a play queue [PUT /playQueues/{playQueue}{?uri,playlistID,next}]
Adds an item to a play queue (e.g. party mode). Increments the version of the play queue. Takes the following parameters (`uri` and `playlistID` are mutually exclusive). Returns the modified play queue.
+ Parameters
+ playQueue: 101 (string) - The ID of the play queue.
+ uri: library:// (string) The content URI for what we're adding to the queue.
+ playlistID: 100 (string, optional) - The ID of the playlist to add to the playQueue.
+ next: 0 (boolean, optional) - play this item next (defaults to 0 - queueing at the end of manually queued items).
+ Response 200 (application/xml)
<MediaContainer size="21" playQueueID="9631" playQueueSelectedItemID="2211762" playQueueSelectedItemOffset="0" playQueueSelectedMetadataItemID="1941458" playQueueShuffled="0" playQueueSourceURI="library://2d8ea42e-7845-498b-b349-095ecaa3c451/item/%2Flibrary%2Fmetadata%2F1906642" playQueueTotalCount="22" playQueueVersion="1">
<Track playQueueItemID="2211762" />
...
</MediaContainer>
### Delete an item from a play queue [DELETE /playQueues/{playQueue}/items/{playQueueItemID}]
Deletes an item in a play queue. Increments the version of the play queue. Returns the modified play queue.
+ Parameters
+ playQueue: 101 (string) - The ID of the play queue.
+ playQueueItemID: 123123 (string) - The play queue item ID to delete.
+ Response 200 (application/xml)
<MediaContainer size="21" playQueueID="9631" playQueueSelectedItemID="2211762" playQueueSelectedItemOffset="0" playQueueSelectedMetadataItemID="1941458" playQueueShuffled="0" playQueueSourceURI="library://2d8ea42e-7845-498b-b349-095ecaa3c451/item/%2Flibrary%2Fmetadata%2F1906642" playQueueTotalCount="22" playQueueVersion="1">
<Track playQueueItemID="2211762" />
...
</MediaContainer>
### Clear a play queue [DELETE /playQueues/{playQueue}/items]
Deletes all items in the play queue, and increases the version of the play queue.
+ Parameters
+ playQueue: 101 (string) - The ID of the play queue.
+ Response 200 (application/xml)
<MediaContainer size="0" playQueueID="9631" playQueueSelectedItemID="2211762" playQueueSelectedItemOffset="0" playQueueSelectedMetadataItemID="1941458" playQueueShuffled="0" playQueueTotalCount="0" playQueueVersion="1">
</MediaContainer>
### Move an item in a play queue [PUT /playQueues/{playQueue}/items/{playQueueItemID}/move{?after}]
Moves an item in a play queue, and increases the version of the play queue. Returns the modified play queue.
+ Parameters
+ playQueue: 101 (string) - The ID of the play queue.
+ playQueueItemID: 123123 (string) - The play queue item ID to delete.
+ after: 123 (string, optional) - the play queue item ID to insert the new item after. If not present, moves to the beginning.
+ Response 200 (application/xml)
<MediaContainer size="21" playQueueID="9631" playQueueSelectedItemID="2211762" playQueueSelectedItemOffset="0" playQueueSelectedMetadataItemID="1941458" playQueueShuffled="0" playQueueSourceURI="library://2d8ea42e-7845-498b-b349-095ecaa3c451/item/%2Flibrary%2Fmetadata%2F1906642" playQueueTotalCount="22" playQueueVersion="1">
<Track playQueueItemID="2211762" />
...
</MediaContainer>
### Shuffle a play queue [PUT /playQueues/{playQueue}/shuffle]
Shuffle a play queue (or reshuffles if already shuffled). The currently selected item is maintained. Note that this is currently only supported for play queues *without* an Up Next area. Returns the modified play queue.
+ Parameters
+ playQueue: 101 (string) - The ID of the play queue.
+ Response 200 (application/xml)
<MediaContainer size="21" playQueueID="9631" playQueueSelectedItemID="2211762" playQueueSelectedItemOffset="0" playQueueSelectedMetadataItemID="1941458" playQueueShuffled="0" playQueueSourceURI="library://2d8ea42e-7845-498b-b349-095ecaa3c451/item/%2Flibrary%2Fmetadata%2F1906642" playQueueTotalCount="22" playQueueVersion="1">
<Track playQueueItemID="2211762" />
...
</MediaContainer>
### Unshuffle a play queue [PUT /playQueues/{playQueue}/unshuffle]
Unshuffles a play queue and restores "natural order". Note that this is currently only supported for play queues *without* an Up Next area. Returns the modified play queue.
+ Parameters
+ playQueue: 101 (string) - The ID of the play queue.
+ Response 200 (application/xml)
<MediaContainer size="21" playQueueID="9631" playQueueSelectedItemID="2211762" playQueueSelectedItemOffset="0" playQueueSelectedMetadataItemID="1941458" playQueueShuffled="0" playQueueSourceURI="library://2d8ea42e-7845-498b-b349-095ecaa3c451/item/%2Flibrary%2Fmetadata%2F1906642" playQueueTotalCount="22" playQueueVersion="1">
<Track playQueueItemID="2211762" />
...
</MediaContainer>

View File

@@ -0,0 +1,165 @@
## Playlists [/playlists]
Playlists are ordered collections of media. They can be dumb (just a list of media) or smart (based on a media query, such as "all albums from 2017"). They can be organized in (optionally nesting) folders.
Retrieving a playlist, or its items, will trigger a refresh of its metadata. This may cause the duration and number of items to change.
### Retrieve Playlists [GET /playlists/all{?playlistType,smart}]
Gets a list of playlists and playlist folders for a user. General filters are permitted, such as `sort=lastViewedAt:desc`. A flat playlist list can be retrieved using `type=15` to limit the collection to just playlists. Special attributes returned are:
- `smart` (0/1) - whether or not the playlist is smart.
- `duration` (milliseconds) - the total duration of the playlist.
- `leafCount` - the number of items in the playlist.
- `composite` - a composite image for the playlist.
- `key` - leads to a list of items in the playlist.
- `playlistType` - the type of the playlist (audio/video/photo).
- `specialPlaylistType` - if this is a special playlist, this returns its type (e.g. favorites).
- `readOnly` - if we return this as true then this playlist cannot be altered or deleted directly by the client.
+ Parameters
+ playlistType: `audio` (string, optional) - limit to a type of playlist (`audio`, `video` or `photo`)
+ smart: `0` (boolean, optional) - optional, type of playlists to return (default is all).
+ Response 200 (application/xml)
<MediaContainer size="2">
<Playlist ratingKey="2561805" key="/playlists/2561805/items" type="playlist" title="Background videos" summary="" smart="0" playlistType="video" composite="/playlists/2561805/composite/1485900004" viewCount="8" lastViewedAt="1484680617" duration="1512000" leafCount="8" addedAt="1476942219" updatedAt="1485900004"></Playlist>
<Playlist ratingKey="1956389" key="/playlists/1956389/items" type="playlist" title="Fairly Recent" summary="" smart="1" playlistType="audio" composite="/playlists/1956389/composite/1486498661" duration="938507000" leafCount="3934" addedAt="1428993345" updatedAt="1486498661"></Playlist>
</MediaContainer>
### Create a Playlist [POST /playlists?{title,type,smart,uri,playQueueID}]
Create a new playlist. By default the playlist is blank. To create a playlist along with a first item, pass:
- `uri` - The content URI for what we're playing (e.g. `library://...`).
- `playQueueID` - To create a playlist from an existing play queue.
If you're creating a smart playlist, you must pass `smart=1` and use the `uri=...` form. Playlists are owned by the account associated with the request.
+ Parameters
+ title: `My Playlist` (string) - name of the playlist
+ type: `audio` (string) - type of the playlist (`video`/`audio`/`photo`)
+ smart: `0` (0/1) - whether the playlist is smart or not.
+ uri: `library://..` (string, optional) - the content URI for the playlist.
+ playQueueID: `123` (integer, optional) - the play queue to copy to a playlist.
+ Response 200 (application/xml)
<MediaContainer size="1">
<Playlist ratingKey="2561805" key="/playlists/2561805/items" type="playlist" title="Background videos" summary="" smart="0" playlistType="video" composite="/playlists/2561805/composite/1485900004" viewCount="8" lastViewedAt="1484680617" duration="1512000" leafCount="8" addedAt="1476942219" updatedAt="1485900004"></Playlist>
</MediaContainer>
### Retrieve Playlist [GET /playlists/{playlistID}]
Gets detailed metadata for a playlist. A playlist for many purposes (rating, editing metadata, tagging), can be treated like a regular metadata item:
Smart playlist details contain the `content` attribute. This is the content URI for the generator. This can then be parsed by a client to provide smart playlist editing.
+ Parameters
+ playlistID: `123` (integer) - the ID of the playlist.
+ Response 200 (application/xml)
<MediaContainer size="1">
<Playlist content="library://22d0bfe3-21ce-4a67-9065-ccaf470cb3c2/directory/%2Flibrary%2Fsections%2F1224%2Fall%3Ftrack%2EaddedAt%3E%3D-12mon%26album%2Egenre!%3DPodcast%26album%2Egenre!%3DBooks%2520%2526%2520Spoken%26artist%2Etitle!%3DAOL%2520Music" ratingKey="1956389" key="/playlists/1956389/items" guid="com.plexapp.plugins.itunes://9F7B78609597F45F" type="playlist" title="Fairly Recent" summary="" smart="1" playlistType="audio" composite="/playlists/1956389/composite/1486764293" duration="957684000" leafCount="4015" addedAt="1428993345" updatedAt="1486764293"></Playlist>
</MediaContainer>
### Retrieve Playlist Contents [GET /playlists/{playlistID}/items{?type}]
Gets the contents if a playlist. Should be paged by clients via standard mechanisms. By default leaves are returned (e.g. episodes, movies). In order to return other types you can use the `type` parameter. For example, you could use this to display a list of recently added albums vis a smart playlist. Note that for dumb playlists, items have a `playlistItemID` attribute which is used for deleting or moving items.
+ Parameters
+ playlistID: `123` (integer) - the ID of the playlist.
+ type: `8` (integer) - the metadata type of the item to return.
+ Response 200 (application/xml)
<MediaContainer size="100">
<Video ... playlistItemID="123" />
</MediaContainer>
### Delete a Playlist [DELETE /playlists/{playlistID}]
Deletes a playlist.
+ Parameters
+ playlistID: `123` (integer) - the ID of the playlist.
+ Response 200
### Editing a Playlist [PUT /library/metadata/{playlistID}]
Use the standard metadata item editing endpoint (tag a playlist! edit the title!). Just listing it here to illustrate the potential.
+ Parameters
+ playlistID: `123` (integer) - the ID of the playlist.
+ Response 200
### Editing a Playlist (PMS >= 1.9.1) [PUT /playlists/{playlistID}]
From PMS version 1.9.1 clients can also edit playlist metadata using this endpoint as they would via `PUT /library/metadata/{playlistID}`
+ Parameters
+ playlistID: `123` (integer) - the ID of the playlist.
+ Response 200
### Clearing a playlist [DELETE /playlists/{playlistID}/items]
Clears a playlist, only works with dumb playlists. Returns the playlist.
+ Parameters
+ playlistID: `123` (integer) - the ID of the playlist.
+ Response 200
<MediaContainer size="1">
<Playlist ratingKey="2561805" key="/playlists/2561805/items" type="playlist" title="Background videos" summary="" smart="0" playlistType="video" composite="/playlists/2561805/composite/1485900004" viewCount="8" lastViewedAt="1484680617" duration="1512000" leafCount="0" addedAt="1476942219" updatedAt="1485900004"></Playlist>
</MediaContainer>
### Adding to a Playlist [PUT /playlists/{playlistID}/items?{uri,playQueueID}]
Adds a generator to a playlist, same parameters as the POST above. With a dumb playlist, this adds the specified items to the playlist. With a smart playlist, passing a new `uri` parameter replaces the rules for the playlist. Returns the playlist.
+ Parameters
+ uri: `library://..` (string, optional) - the content URI for the playlist.
+ playQueueID: `123` (integer, optional) - the play queue to add to a playlist.
+ Response 200 (application/xml)
<MediaContainer size="1">
<Playlist ratingKey="2561805" key="/playlists/2561805/items" type="playlist" title="Background videos" summary="" smart="0" playlistType="video" composite="/playlists/2561805/composite/1485900004" viewCount="8" lastViewedAt="1484680617" duration="1512000" leafCount="8" addedAt="1476942219" updatedAt="1485900004"></Playlist>
</MediaContainer>
### Moving items in a playlist [PUT /playlists/{playlistID}/items/{playlistItemID}/move{?after}]
Moves an item in a playlist. Only works with dumb playlists.
+ Parameters
+ playlistID: `123` (integer) - the playlist ID.
+ playlistItemID: `1` (integer) - the playlist item ID to move.
+ after: `2` (integer, optional) - the playlist item ID to insert the new item after.
+ Response 200
### Delete a Generator [DELETE /playlists/{playlistID}/items/{playlistItemID}]
Deletes an item from a playlist. Only works with dumb playlists.
+ Parameters
+ playlistID: `123` (integer) - the playlist ID.
+ playlistItemID: `1` (integer) - the playlist item ID to move.
+ Response 200
### Upload Playlists [POST /playlists/upload{?path,force}]
Imports m3u playlists by passing a path on the server to scan for m3u-formatted playlist files, or a path to a single playlist file.
+ Parameters
+ path: `/home/barkley/playlist.m3u` - absolute path to a directory on the server where m3u files are stored, or the absolute path to a playlist file on the server. If the `path` argument is a directory, that path will be scanned for playlist files to be processed. Each file in that directory creates a separate playlist, with a name based on the filename of the file that created it. The GUID of each playlist is based on the filename. If the `path` argument is a file, that file will be used to create a new playlist, with the name based on the filename of the file that created it. The GUID of each playlist is based on the filename.
+ force: `1` - force overwriting of duplicate playlists. By default, a playlist file uploaded with the same path will overwrite the existing playlist. The `force` argument is used to disable overwriting. If the `force` argument is set to 0, a new playlist will be created suffixed with the date and time that the duplicate was uploaded.
+ Response 200

View File

@@ -0,0 +1,57 @@
## Group Search
### Perform a search [GET /hubs/search{?query,sectionId,limit}]
This endpoint performs a search across all library sections, or a single section, and returns matches as hubs, split up by type. It performs spell checking, looks for partial matches, and orders the hubs based on quality of results. In addition, based on matches, it will return other related matches (e.g. for a genre match, it may return movies in that genre, or for an actor match, movies with that actor).
In the response's items, the following extra attributes are returned to further describe or disambiguate the result:
- `reason`: The reason for the result, if not because of a direct search term match; can be either:
- `section`: There are multiple identical results from different sections.
- `originalTitle`: There was a search term match from the original title field (sometimes those can be very different or in a foreign language).
- `<hub identifier>`: If the reason for the result is due to a result in another hub, the source hub identifier is returned. For example, if the search is for "dylan" then Bob Dylan may be returned as an artist result, an a few of his albums returned as album results with a reason code of `artist` (the identifier of that particular hub). Or if the search is for "arnold", there might be movie results returned with a reason of `actor`
- `reasonTitle`: The string associated with the reason code. For a section reason, it'll be the section name; For a hub identifier, it'll be a string associated with the match (e.g. `Arnold Schwarzenegger` for movies which were returned because the search was for "arnold").
- `reasonID`: The ID of the item associated with the reason for the result. This might be a section ID, a tag ID, an artist ID, or a show ID.
This request is intended to be very fast, and called as the user types.
+ Parameters
+ query: `dog` - The query term.
+ sectionId: `1` (number, optional) - This gives context to the search, and can result in re-ordering of search result hubs.
+ limit: `5` (number, optional) - The number of items to return per hub.
+ Default: `3`
+ Response 200 (application/xml)
<MediaContainer size="12">
<Hub type="show" hubIdentifier="show" size="1" title="Shows" more="0">
<Directory title="The Simpsons" titleSort="Simpsons" type="show" ... />
</Hub>
<Hub type="movie" hubIdentifier="movie" size="1" title="Movies" more="0">
<Video type="movie" title="The Simpsons Movie" ... />
</Hub>
</MediaContainer>
### Perform a search tailored to voice input [GET /hubs/search/voice{?query,type,limit}]
This endpoint performs a search specifically tailored towards voice or other imprecise input which may work badly with the substring and spell-checking heuristics used by the `/hubs/search` endpoint. It uses a [Levenshtein distance](https://en.wikipedia.org/wiki/Levenshtein_distance) heuristic to search titles, and as such is much slower than the other search endpoint. Whenever possible, clients should limit the search to the appropriate type.
Results, as well as their containing per-type hubs, contain a `distance` attribute which can be used to judge result quality.
+ Parameters
+ query: `dead+poop` - The query term.
+ type: `8` (number, optional) - The type of thing to limit the search to.
+ limit: `5` (number, optional) - The number of items to return per hub.
+ Default: `3`
+ Response 200 (application/xml)
<MediaContainer size="2">
<Hub distance="3" type="movie" hubIdentifier="results.search.1" size="2" title="movie">
<Video distance="3" type="movie" title="Deadpool" />
<Video distance="4" type="movie" title="Dead Snow" />
</Hub>
<Hub distance="4" type="show" hubIdentifier="results.search.2" size="1" title="show">
<Directory distance="4" type="show" title="Deadwood" />
</Hub>
</MediaContainer>

View File

@@ -0,0 +1,77 @@
## Library Sections [/library/sections]
A library section (commonly referred to as just a library) is a collection of media. Libraries are typed, and depending on their type provide either a flat or a hierarchical view of the media. For example, a music library has an artist > albums > tracks structure, whereas a movie library is flat.
Libraries have features beyond just being a collection of media; for starters, they include information about supported types, filters and sorts. This allows a client to provide a rich interface around the media (e.g. allow sorting movies by release year).
### Get library section details [GET /library/sections/{section}{?includeDetails}]
Returns details for the library. This can be thought of as an interstitial endpoint because it contains information about the library, rather than content itself. These details are:
- A list of `Directory` objects: These used to be used by clients to build a menuing system. There are four flavors of directory found here:
- Primary: (e.g. all, On Deck) These are still used in some clients to provide "shortcuts" to subsets of media. However, with the exception of On Deck, all of them can be created by media queries, and the desire is to allow these to be customized by users.
- Secondary: These are marked with `secondary="1"` and were used by old clients to provide nested menus allowing for primative (but structured) navigation.
- Special: There is a By Folder entry which allows browsing the media by the underlying filesystem structure, and there's a completely obsolete entry marked `search="1"` which used to be used to allow clients to build search dialogs on the fly.
- A list of `Type` objects: These represent the types of things found in this library, and for each one, a list of `Filter` and `Sort` objects. These can be used to build rich controls around a grid of media to allow filtering and organizing. Note that these filters and sorts are optional, and without them, the client won't render any filtering controls. The `Type` object contains:
- `key`: This provides the root endpoint returning the actual media list for the type.
- `type`: This is the metadata type for the type (if a standard Plex type).
- `title`: The title for for the content of this type (e.g. "Movies").
- Each `Filter` object contains a description of the filter. Note that it is not an exhaustive list of the full media query language, but an inportant subset useful for top-level API.
- `filter`: This represents the filter name used for the filter, which can be used to construct complex media queries with.
- `filterType`: This is either `string`, `integer`, or `boolean`, and describes the type of values used for the filter.
- `key`: This provides the endpoint where the possible range of values for the filter can be retrieved (e.g. for a "Genre" filter, it returns a list of all the genres in the library). This will include a `type` argument that matches the metadata type of the Type element.
- `title`: The title for the filter.
- Each `Sort` object contains a description of the sort field.
- `defaultDirection`: Can be either `asc` or `desc`, and specifies the default direction for the sort field (e.g. titles default to alphabetically ascending).
- `descKey` and `key`: Contains the parameters passed to the `sort=...` media query for each direction of the sort.
- `title`: The title of the field.
+ Parameters
+ section: `1000` (string) - The section identifier.
+ includeDetails: `1` (boolean, optional) - Whether or not to include details for a section (types, filters, and sorts). Only exists for backwards compatibility, media providers other than the server libraries have it on always.
+ Default: `0`
+ Response 200 (application/xml)
<MediaContainer size="20" allowSync="0" art="/:/resources/movie-fanart.jpg" content="secondary" identifier="com.plexapp.plugins.library" librarySectionID="1" mediaTagPrefix="/system/bundle/media/flags/" mediaTagVersion="1484125920" sortAsc="1" thumb="/:/resources/movie.png" title1="Movies" viewGroup="secondary" viewMode="65592">
<Directory key="all" title="All Movies"/>
<Directory key="unwatched" title="Unwatched"/>
<Directory key="newest" title="Recently Released"/>
<Directory key="recentlyAdded" title="Recently Added"/>
<Directory key="recentlyViewed" title="Recently Viewed"/>
<Directory key="onDeck" title="On Deck"/>
<Directory secondary="1" key="collection" title="By Collection"/>
<Directory secondary="1" key="genre" title="By Genre"/>
<Directory secondary="1" key="year" title="By Year"/>
<Directory secondary="1" key="decade" title="By Decade"/>
<Directory secondary="1" key="director" title="By Director"/>
<Directory secondary="1" key="actor" title="By Starring Actor"/>
<Directory secondary="1" key="country" title="By Country"/>
<Directory secondary="1" key="contentRating" title="By Content Rating"/>
<Directory secondary="1" key="rating" title="By Rating"/>
<Directory secondary="1" key="resolution" title="By Resolution"/>
<Directory secondary="1" key="firstCharacter" title="By First Letter"/>
<Directory key="folder" title="By Folder"/>
<Directory prompt="Search Movies" search="1" key="search?type=1" title="Search..."/>
<Type key="/library/sections/1/all?type=1" type="1" title="Movies">
<Filter filter="genre" filterType="string" key="/library/sections/1/genre" title="Genre" type="filter"/>
<Filter filter="year" filterType="integer" key="/library/sections/1/year" title="Year" type="filter"/>
<Filter filter="decade" filterType="integer" key="/library/sections/1/decade" title="Decade" type="filter"/>
<Filter filter="contentRating" filterType="string" key="/library/sections/1/contentRating" title="Content Rating" type="filter"/>
<Filter filter="collection" filterType="string" key="/library/sections/1/collection" title="Collection" type="filter"/>
<Filter filter="director" filterType="string" key="/library/sections/1/director" title="Director" type="filter"/>
<Filter filter="actor" filterType="string" key="/library/sections/1/actor" title="Actor" type="filter"/>
<Filter filter="country" filterType="string" key="/library/sections/1/country" title="Country" type="filter"/>
<Filter filter="studio" filterType="string" key="/library/sections/1/studio" title="Studio" type="filter"/>
<Filter filter="resolution" filterType="string" key="/library/sections/1/resolution" title="Resolution" type="filter"/>
<Filter filter="unwatched" filterType="boolean" key="/library/sections/1/unwatched" title="Unwatched" type="filter"/>
<Filter filter="label" filterType="string" key="/library/sections/1/label" title="Labels" type="filter"/>
<Sort defaultDirection="desc" descKey="addedAt:desc" key="addedAt" title="Date Added"/>
<Sort defaultDirection="desc" descKey="originallyAvailableAt:desc" key="originallyAvailableAt" title="Release Date"/>
<Sort defaultDirection="desc" descKey="lastViewedAt:desc" key="lastViewedAt" title="Date Viewed"/>
<Sort default="asc" defaultDirection="asc" descKey="titleSort:desc" key="titleSort" title="Name"/>
<Sort defaultDirection="desc" descKey="rating:desc" key="rating" title="Rating"/>
<Sort defaultDirection="asc" descKey="mediaHeight:desc" key="mediaHeight" title="Resolution"/>
<Sort defaultDirection="desc" descKey="duration:desc" key="duration" title="Duration"/>
</Type>
</MediaContainer>

0
Markdown/Library/Tags.md Normal file
View File

33
Markdown/Log.md Normal file
View File

@@ -0,0 +1,33 @@
## Group Log (/log)
### Logging a single-line message to the Plex Media Server log (GET /log)
This endpoint will write a single-line log message, including a level and source to the main Plex Media Server log.
+ Parameters
+ level: An integer log level to write to the PMS log with.
+ Members
+ 0: Error
+ 1: Warning
+ 2: Info
+ 3: Debug
+ 4: Verbose
+ message: The text of the message to write to the log.
+ source: A string indicating the source of the message.
+ Response 200
### Logging a multi-line message to the Plex Media Server log (POST /log)
This endpoint will write multiple lines to the main Plex Media Server log in a single request. It takes a set of query strings as would normally sent to the above GET endpoint as a linefeed-separated block of POST data. The parameters for each query string match as above.
+ Response 200
### Enabling Papertrail (GET /log/networked)
This endpoint will enable all Plex Media Serverlogs to be sent to the Papertrail networked logging site for a period of time.
+ Parameters
+ minutes: The number of minutes logging should be sent to Papertrail
+ Response 200 (if papertrail could be enabled. 403 if the user was not signed in)

104
Markdown/Media Feedback.md Normal file
View File

@@ -0,0 +1,104 @@
## Media Feedback [/:/]
This group of endpoints correspond to client feedback around an item.
### Report media timeline [GET /:/timeline{?hasMDE,key,ratingKey,state,playQueueItemID,time,duration,continuing,updated,offline,timeToFirstFrame,timeStalled,bandwidth,bufferedTime,bufferedSize,location}]
This endpoint is hit during media playback for an item. It must be hit whenever the play state changes, or in the absense of a play state change, in a regular fashion (generally this means every 10 seconds on a LAN/WAN, and every 20 seconds over cellular).
In order to identify the client, the following headers are used:
- `X-Plex-Client-Identifier`: Required, unique per client.
- `X-Plex-Session-Identifier`: Optional, unique per client playback session.
Respones contains a `MediaContainer` top level XML element. This may contain a full decision result as seen in the `video/:/transcode/universal/decision` endpoint. If this is returned, client must stop playback and restart playback as directed by the decision.
Additional attributes include:
- `terminationCode` - Optional, a code describing why the session was terminated by the server. See `decision` endpoint for more details.
- `terminationText` - Optional, a user friendly and localized text describing why the session was terminated by the server.
Additional child elements include:
- `Bandwidths` - Optional, an element containing one or more `Bandwidth` elements.
- `Bandwidth` - Optional, an element containing the attribute `time` as the time of bandwidth change in milliseconds, `bandwidth` as the new bandwidth in Kbps, and `resolution` as a user presentable string indicating the new resolution.
+ Parameters
+ key: `/foo` - The details key for the item.
+ ratingKey: `xyz` - The rating key attribute for the item.
+ state: `playing` - The current state of the media.
+ Members
+ `stopped`
+ `buffering`
+ `playing`
+ `paused`
+ playQueueItemID: `123` (string, optional) - If playing media from a play queue, the play queue's ID.
+ time: `0` (milliseconds) - The current time offset of playback.
+ duration: `10000` (milliseconds) - The total duration of the item.
+ continuing: `1` - When state is `stopped`, a flag indicating whether or not the client is going to continue playing anothe item.
+ updated: `14200000` (epoch seconds) - Used when a sync client comes online and is syncing media timelines, holds the time at which the playback state was last updated.
+ offline: `1` - Also used by sync clients, used to indicate that a timeline is being synced from being offline, as opposed to being "live".
+ timeToFirstFrame: `1000` - Optional, time in seconds till first frame is displayed. Sent only on the first playing timeline request.
+ timeStalled: `1000` (number, optional) - Time in seconds spent buffering since last request.
+ bandwidth: `100` (number, optional) - Bandwidth in kbps as estimated by the client.
+ bufferedTime: `100` (number, optional) - Amount of time in seconds buffered by client. Omit if computed by `bufferedSize` below.
+ bufferedSize: `1024` (number, optional) - Size in kilobytes of data buffered by client. Omit if computed by `bufferedTime` above
+ Response 200 (text/xml;charset=utf-8)
+ Body
Normal response:
<MediaContainer size="0" />
Admin terminated session:
<MediaContainer size="0" terminationCode="2006" terminationText="Admin terminated playback with reason: Go Away" />
Bandwidth changes included:
<MediaContainer size="1">
<Bandwidths>
<Bandwidth time="0" bandwidth="15000" resolution="1080p" />
<Bandwidth time="1050008" bandwidth="12000" resolution="1080p" />
<Bandwidth time="1053011" bandwidth="8000" resolution="1080p" />
<Bandwidth time="1098014" bandwidth="4000" resolution="720p" />
<Bandwidth time="1101017" bandwidth="2000" resolution="SD" />
<Bandwidth time="1104020" bandwidth="1000" resolution="SD" />
<Bandwidth time="1107023" bandwidth="750" resolution="SD" />
<Bandwidth time="1110026" bandwidth="350" resolution="SD" />
<Bandwidth time="1113029" bandwidth="750" resolution="SD" />
<Bandwidth time="1116032" bandwidth="1000" resolution="SD" />
<Bandwidth time="1119035" bandwidth="4000" resolution="720p" />
<Bandwidth time="1122038" bandwidth="10000" resolution="1080p" />
</Bandwidths>
</MediaContainer>
### Marking items watched [GET /:/scrobble{?key,uri,identifier}]
This endpoint is used to mark items watched. It may be applied to ancestor items (e.g. show or a season), in which case all descendent items are marked watched as well. A general media URI specifier may be used in advanced cases (e.g. multi-select).
+ Parameters
+ key: `/foo` - The rating key for the item.
+ uri: `library://...` - The media URI specifier. Either `key` or `uri` must be used, but not both.
+ identifier: `com.something` - The identifier for the item's provider. Allows multiplexing between multiple providers at a single endpoint.
+ Response 200
### Marking items unwatched [GET /:/unscrobble{?key,uri,identifier}]
+ Parameters
+ key: `/foo` - The rating key for the item.
+ uri: `library://...` - The media URI specifier. Either `key` or `uri` must be used, but not both.
+ identifier: `com.something` - The identifier for the item's provider. Allows multiplexing between multiple providers at a single endpoint.
+ Response 200
### Rating items [GET /:/rate{?key,identifier,rating}]
+ Parameters
+ key: `/foo` - The rating key for the item.
+ identifier: `com.something` - The identifier for the item's provider.
+ rating: `2.4` - The rating for the item.
+ Response 200

View File

@@ -0,0 +1,28 @@
### Client Guide to Media Providers
The philosophy behind media providers in general is to allow clients to quickly support them, since the APIs are nearly identical to a normal server. However, there are several important differences, as well as some consolidation and improvements to the API which can be beneficial to take into account at the same time. Without further ado, here are the general guidelines:
##### Consume `/media/providers` instead of `/library/sections`
The new providers endpoint give you a list of all providers exported by a server and their features. Remember that the library itself is considered a (very rich) provider! This change will also require changing the client to not hardwire paths on the server, but rather read them from the feature keys directly (e.g. scrobble and rating endpoints).
##### Gate management functionality on the `manage` feature
Server libraries allow management (e.g. media deletion). The correct way to gate this functionality is via the manage feature.
##### Make sure key construction is correct for things like genre lists
For example, `/library/sections/x/genre` returns a relative key for each genre, but there's nothing which says that the `key` can't be an absolute URL. This is why servers pass back `fastKey` separately so as to not break clients which don't do key construction correctly. Media providers do not pass back `fastKey`, but assume clients will be doing correct key construction.
##### Don't call `/library/sections/X/filters|sorts`
You can get all that information (and more) in a single call by hitting `/library/sections/X?includeDetails=1`. Media providers include the extra information by default.
##### Respect the Type keys in `/library/sections/x`
The top-level type pivots have their own keys, which should be used over the old "just append /all to the path and add the type" approach. Not only is this more flexible, it also allows for "virtual" pivots, like music videos inside a music library.
##### Look for the skipChildren/skipParent attributes for shows
Because of things like Podcasts, single-season shows can now be made to skip seasons. This is indicated by a `skipChildren` attribute on the show, or a `skipParent` attribute on an episode. If this is set on a show, the client should use `/grandchildren` instead of `/children` in the show's key.

View File

@@ -0,0 +1,101 @@
## DVRs [/livetv/dvrs]
Once you have configured devices and picked a lineup, you can create a DVR.
### Create a DVR [POST /livetv/dvrs{?lineup,device,language}]
+ Parameters
+ lineup: `lineup://tv.plex.providers.epg.onconnect/USA-HI51418-DEFAULT` - The EPG lineup.
+ device: `device[]=device://tv.plex.grabbers.hdhomerun/1053C0CA` (array) - The device.
+ language: `eng` - The language.
+ Response 200
### Get DVRs [GET /livetv/dvrs]
+ Response 200 (application/xml)
<MediaContainer size="1">
<Dvr key="28" language="eng" lineup="lineup://tv.plex.providers.epg.onconnect/USA-HI51418-X" uuid="811e2e8a-f98f-4d1f-a26a-8bc26e4999a7">
<Device key="17" lastSeenAt="1463297728" make="Silicondust" model="HDHomeRun EXTEND" modelNumber="HDTC-2US" protocol="livetv" sources="0,1" state="1" status="1" tuners="2" uri="http://10.0.0.42" uuid="device://tv.plex.grabbers.hdhomerun/1053C0CA">
<ChannelMapping channelKey="5cc83d73af4a72001e9b16d7-5cab3c634df507001fefcad0" deviceIdentifier="46.3" enabled="1" lineupIdentifier="002" />
<ChannelMapping channelKey="5cc83d73af4a72001e9b16d7-5cab3d20d30eca001db32922" deviceIdentifier="48.1" enabled="1" lineupIdentifier="009" />
</Device>
</Dvr>
</MediaContainer>
### Get a single DVR [GET /livetv/dvrs/{dvr}]
+ Parameters
+ dvr: `1` - The ID of the DVR.
+ Response 200 (application/xml)
<MediaContainer size="1">
<Dvr />
</MediaContainer>
### Delete a DVR [DELETE /livetv/dvrs/{dvr}]
+ Parameters
+ dvr: `1` - The ID of the DVR.
+ Response 200 (application/xml)
### Add a device to an existing DVR [PUT /livetv/{dvr}/devices/{device}]
+ Parameters
+ dvr: `1` - The ID of the DVR.
+ device: `1223` - The ID of the device to add.
+ Response 200 (application/xml)
<MediaContainer size="1">
<Dvr />
</MediaContainer>
### Remove a device from an existing DVR [DELETE /livetv/dvrs/{dvr}/devices/{device}"]
+ Parameters
+ dvr: `1` - The ID of the DVR.
+ device: `1223` - The ID of the device to add.
+ Response 200 (application/xml)
<MediaContainer size="1">
<Dvr />
</MediaContainer>
### Set DVR preferences [PUT /livetv/dvrs/{dvr}/prefs{?name}]
+ Parameters
+ dvr: `1` - The ID of the DVR.
+ name: `value` - The preference names and values.
+ Response 200 (application/xml)
<MediaContainer size="1">
<Dvr key="28" language="eng" lineup="lineup://tv.plex.providers.epg.onconnect/USA-HI51418-X" uuid="811e2e8a-f98f-4d1f-a26a-8bc26e4999a7">
<Device key="17" lastSeenAt="1463896924" make="Silicondust" model="HDHomeRun EXTEND" modelNumber="HDTC-2US" parentID="28" protocol="livetv" sources="0,1" state="1" status="1" tuners="2" uri="http://10.0.0.42" uuid="device://tv.plex.grabbers.hdhomerun/1053C0CA">
<ChannelMapping deviceIdentifier="46.1" enabled="1" />
</Device>
</Dvr>
</MediaContainer>
### Tell a DVR to reload program guide [POST /livetv/dvrs/{dvr}/reloadGuide]
+ Parameters
+ dvr: `1` - The ID of the DVR.
+ Response 200
+ Headers
X-Plex-Activity: d391ddb0-b29b-4e20-a57a-46b15b4e4318
### Tell a DVR to stop reloading program guide [DELETE /livetv/dvrs/{dvr}/reloadGuide]
+ Parameters
+ dvr: `1` - The ID of the DVR.
+ Response 200

View File

@@ -0,0 +1,85 @@
## Group Device Endpoints
### Get device details [GET /media/grabbers/devices/{device}]
+ Parameters
+ device: `42` - the ID of the device.
+ Response 200 (application/xml)
<MediaContainer size="1">
<Device key="6" lastSeenAt="1461737032" make="Silicondust" model="HDHomeRun EXPAND" modelNumber="HDHR3-4DC" protocol="livetv" sources="Cable" state="1" status="1" tuners="4" uri="http://home.techconnect.nl:8822" uuid="141007E7">
<ChannelMapping channelKey="5cc83d73af4a72001e9b16d7-5cab3c634df507001fefcad0" deviceIdentifier="46.3" enabled="1" lineupIdentifier="002" />
<ChannelMapping channelKey="5cc83d73af4a72001e9b16d7-5cab3d20d30eca001db32922" deviceIdentifier="48.9" enabled="0" lineupIdentifier="004" />
<ChannelMapping channelKey="5cc83d73af4a72001e9b16d7-5cab3d07771bb2001ef88f72" deviceIdentifier="49.12" enabled="1" lineupIdentifier="011" />
<ChannelMapping channelKey="5cc83d73af4a72001e9b16d7-5cab3c63de29da001cf021c2" deviceIdentifier="49.3" enabled="0" lineupIdentifier="008" />
<ChannelMapping channelKey="5cc83d73af4a72001e9b16d7-5cab3c63e3ef4d001d05ba70" deviceIdentifier="10.4" enabled="1" />
</Device>
</MediaContainer>
### Enable or disable a device [PUT /media/grabbers/devices/{device}{?enabled}]
+ Parameters
+ device: `42` - The ID of the device.
+ enabled: `1` - Whether to enable the device.
+ Response 200 (application/xml)
<MediaContainer message="" size="0" status="0" />
### Set device preferences [PUT /media/grabbers/devices/{device}/prefs{?name}]
+ Parameters
+ device: `1` - The ID of the DVR.
+ name: `value` - The preference names and values.
+ Response 200 (application/xml)
### Get a device's channels [GET /media/grabbers/devices/{device}/channels]
+ Parameters
+ device: `42` - the ID of the device.
+ Response 200 (application/xml)
<MediaContainer size="48">
<DeviceChannel drm="0" hd="0" identifier="46.1" name="KPXO HD" />
<DeviceChannel drm="0" hd="0" identifier="46.3" name="KHON HD" />
</MediaContainer>
### Set a device's channel mapping [PUT /media/grabbers/devices/{device}/channelmap{?channelMapping,channelsEnabled}]
+ Parameters
+ device: `42` - the ID of the device.
+ channelMapping: `channelMapping[46.3]=002&channelMapping[48.9]=004` - the mapping of changes, passed as a map of device channel to lineup VCN.
+ channelMappingByKey: `channelMappingByKey[46.3]=5cc83d73af4a72001e9b16d7-5cab3c634df507001fefcad0&channelMappingByKey[48.9]=5cc83d73af4a72001e9b16d7-5cab3c63ec158a001d32db8d` - the mapping of changes, passed as a map of device channel to lineup key.
+ channelsEnabled: `46.1,44.1,45.1` - the channels which are enabled.
+ Response 200 (application/xml)
<MediaContainer message="" size="0" status="0" />
### Tell a device to scan for channels [POST /media/grabbers/devices/{device}/scan{?source}]
+ Parameters
+ device: `42` - the ID of the device.
+ source: `Cable` - a valid source for the scan.
+ Response 200 (application/xml)
+ Headers
X-Plex-Activity: 7e650c37-1639-4f60-9866-09b8eaf35a7a
+ Body
<MediaContainer message="" size="0" status="0" />
### Tell a device to stop scanning for channels [DELETE /media/grabbers/devices/{device}/scan]
+ Parameters
+ device: `42` - the ID of the device.
+ Response 200 (application/xml)
<MediaContainer message="" size="0" status="0" />

View File

@@ -0,0 +1,123 @@
## EPG Endpoints [/livetv/epg]
These endpoint detail the EPG portion of the interface.
### Get all countries [GET /livetv/epg/countries]
This endpoint returns a list of countries which EPG data is available for. There are three flavors, as specfied by the `flavor` attribute:
- `0`: The country is divided into regions, and following the key will lead to a list of regions.
- `1`: The county is divided by postal codes, and an example code is returned in `example`.
- `2`: The country has a single postal code, returned in `example`.
+ Response 200 (application/xml)
<MediaContainer size="3">
<Country key="aia/tv.plex.providers.epg.onconnect/lineups" type="country" title="Anguilla" code="aia" language="eng" languageTitle="English" example="AI-2640" flavor="2"/>
<Country key="atg/tv.plex.providers.epg.onconnect/lineups" type="country" title="Antigua and Barbuda" code="atg" language="eng" languageTitle="English" example="AG" flavor="2"/>
<Country key="arg/tv.plex.providers.epg.onconnect/lineups" type="country" title="Argentina" code="arg" language="spa" languageTitle="Español" example="A4190" flavor="1"/>
</MediaContainer>
### Get all languages [GET /livetv/epg/languages]
Returns a list of all possible languages for EPG data.
+ Response 200 (application/xml)
<MediaContainer size="3">
<Language code="aar" title="Afaraf"/>
<Language code="abk" title="аҧсуа"/>
<Language code="afr" title="Afrikaans"/>
</MediaContainer>
### Get regions for a country [GET /livetv/epg/countries/{country}/{epgIdentifier}/regions]
+ Parameters
+ country: `usa` - The ISO country code.
+ epgIdentifier: `tv.plex.providers.epg.eyeq` ~ The EPG identifier.
+ Response 200 (application/xml)
<MediaContainer size="2">
<Region key="132718/lineups" type="region" title="Bruxelles"/>
<Region key="116043/lineups" type="region" title="Région wallonne"/>
</MediaContainer>
### Get lineups for a region [GET /livetv/epg/countries/{country}/{epgIdentifier}/regions/{region}/lineups{?country,region}]
Returns the list of lineups for a given country, EPG provider, and region. There are four types of lineups returned in `lineupType`:
- `0`: Over the air
- `1`: Cable
- `2`: Satellite
- `3`: IPTV
- `4`: Virtual
+ Parameters
+ country: `bhr` - The ISO country code.
+ epgIdentifier: `tv.plex.providers.epg.eyeq` ~ The EPG identifier.
+ region: `134535`
+ Response 200 (application/xml)
<MediaContainer size="1" uuid="lineup-group://tv.plex.providers.epg.eyeq/bhr/134535">
<Lineup uuid="lineup://tv.plex.providers.epg.eyeq/410357488-CE9BE5630D077FE397F3B42E984AC8DD/bhr#OSN" type="lineup" title="OSN" lineupType="2"/>
</MediaContainer>
### Get lineups for a country via postal code [GET /livetv/epg/countries/{country}/{epgIdentifier}/lineups{?postalCode}]
Returns a list of lineups for a given country, EPG provider and postal code.
+ Parameters
+ postalCode: `AI-2640` - The postal code.
+ country: `aia` - The ISO country code.
+ epgIdentifier: `tv.plex.providers.epg.onconnect` ~ The EPG identifier.
+ Response 200 (application/xml)
<MediaContainer size="3" uuid="lineup-group://tv.plex.providers.epg.onconnect/aia/AI-2640">
<Lineup uuid="lineup://tv.plex.providers.epg.onconnect/AIA-0000040-DEFAULT#Caribbean%20Cable%20Communications%20-%20Anguilla" type="lineup" title="Caribbean Cable Communications - Anguilla" lineupType="1" location="The Valley"/>
<Lineup uuid="lineup://tv.plex.providers.epg.onconnect/AIA-0000040-X#Caribbean%20Cable%20Communications%20-%20Anguilla%20-%20Digital" type="lineup" title="Caribbean Cable Communications - Anguilla - Digital" lineupType="1" location="The Valley"/>
<Lineup uuid="lineup://tv.plex.providers.epg.onconnect/AIA-0002293-X#DirecTV%20Anguilla%20-%20Digital" type="lineup" title="DirecTV Anguilla - Digital" lineupType="1" location="The Valley"/>
</MediaContainer>
### Get channels for a lineup [GET /livetv/epg/channels{?lineup}]
+ Parameters
+ lineup: `lineup://tv.plex.providers.epg.onconnect/CAN-OTAV4R2G5` - The URI describing the lineup.
+ Response 200 (application/xml)
<MediaContainer size="2">
<Channel callSign="BBC1SCO" identifier="001" thumb="http://plex.tmsimg.com/h3/NowShowing/21439/s21439_h3_aa.png" />
<Channel callSign="BBC2SCO" identifier="002" />
</MediaContainer>
### Compute the best channel map, given device and lineup [GET /livetv/epg/channelmap{?device,lineup}]
+ Parameters
+ device: `device://tv.plex.grabbers.hdhomerun/1053C0CA` - The device.
+ lineup: `lineup://tv.plex.providers.epg.onconnect/USA-HI51418-DEFAULT` - The lineup.
+ Response 200 (application/xml)
<MediaContainer size="1">
<ChannelMapping channelKey="5cc83d73af4a72001e9b16d7-5cab3c634df507001fefcad0" deviceIdentifier="48.9" lineupIdentifier="103" />
</MediaContainer>
### Compute the best lineup, given lineup group and device [GET /livetv/epg/lineup{?device,lineupGroup}]
+ Parameters
+ device: `device://tv.plex.grabbers.hdhomerun/1053C0CA` - The device.
+ lineupGroup: `lineup-group://onconnect/usa/96708` - The lineup group.
+ Response 200 (application/xml)
+ Headers
X-Plex-Activity: 7e650c37-1639-4f60-9866-09b8eaf35a7a
+ Body
<MediaContainer />

View File

@@ -0,0 +1,89 @@
## Live TV
So you want to stream Live TV? You've come to the right place. Live TV sessions are handled by "rolling" subscriptions, which are like normal media subscriptions, except that they move over time. Live TV subscriptions start by allocating a 5 minute segment of time, and then every minute, extend by a minute. This means that you will learn about conflicts 5 minutes before they happen, and the user has the opportunity to kill/cancel something else before the subscription's grab operation (recording) is terminated.
### Start a live TV session [POST /livetv/dvrs/{dvr}/channels/{channel}/tune]
This requests kicks off a Live TV session, by creating a rolling subscription. If it cannot allocate at least 5 minutes of session time, it will return a subscription with conflicts. Otherwise, it will return the rolling subscription, which has a few special features returned:
- The `MediaGrabOperation`'s video contains a `Media` element which reflects the actual media characteristics of the live stream.
- A `Timeline` object which contains N `Video` elements, reflecting all of the metadata along the Live TV session, from the start, to the item airing next. Generally speaking there will be two items at the beginning (the currently airing item, and the thing next airing).
- An `AlsoAiring` object which contains N `Video` elements, reflecting the items currently aring on different channels.
The client is required to pass either `X-Plex-Session-Identifier` or `X-Plex-Client-Identifier` header to this request.
Note that when successfully started, the reply will also include an Activity header, to allow a client to easily track the Live TV rolling subscription. If a rolling subscription ever enters into conflict (with a 5 minute warning, as mentioned earlier), the Activity context will be updated with `conflicts: true`; if the item loses its conflict status (because something else is cancelled), the Activity will be updated again with the loss of the `conflicts` attribute.
+ Parameters
+ dvr: `324` - The ID of the DVR.
+ channel: `008` (string) - The channel identifier.
+ Response 200 (application/xml)
<MediaContainer size="1">
<MediaSubscription key="886" title="This Episode" type="4">
<MediaGrabOperation deviceID="334" grabberIdentifier="tv.plex.grabbers.hdhomerun" grabberProtocol="livetv" key="/media/grabbers/operations/005-555wew" mediaIndex="0" mediaSubscriptionID="886" rolling="1" status="inprogress">
<Video genuineMediaAnalysis="1" grandparentTitle="Live TV" key="/livetv/sessions/c1e26483-946b-4f8a-8120-bd498bd31386" live="1" title="Live Session 555wew">
<Media beginsAt="1493108074" channelIdentifier="005" container="mpegts" endsAt="1493108374" protocol="hls" uuid="c1e26483-946b-4f8a-8120-bd498bd31386">
<Part container="mpegts" key="/livetv/sessions/c1e26483-946b-4f8a-8120-bd498bd31386/555wew/index.m3u8" protocol="hls">
<Stream codec="h264" frameRate="29.970" height="1080" index="0" level="40" pixelAspectRatio="1:1" profile="high" scanType="interlaced" streamType="1" width="1920" />
<Stream audioChannelLayout="5.1(side)" bitrate="384" channels="6" codec="ac3" index="1" languageCode="eng" samplingRate="48000" streamType="2" />
</Part>
</Media>
</Video>
</MediaGrabOperation>
<Timeline>
<Video addedAt="1493065214" contentRating="TV-14" duration="1800000" grandparentKey="/library/metadata/301" grandparentRatingKey="301" grandparentThumb="/library/metadata/301/thumb/1493065214" grandparentTitle="2 Broke Girls" index="4" key="/library/metadata/303" originallyAvailableAt="2012-10-15" parentIndex="2" parentKey="/library/metadata/302" parentRatingKey="302" parentTitle="Season 2" ratingKey="303" summary="Max and Caroline audition to be on the reality show &quot;Cupcake Wars.&quot;" title="And the Cupcake War" type="episode" year="2012">
<Media audioChannels="2" beginsAt="1493107500" channelID="5" channelIdentifier="005" channelThumb="http://tmsimg.plex.tv/h3/NowShowing/51307/s51307_h3_aa.png" channelTitle="005 KFVE (MNT)" duration="1800000" endsAt="1493109300" id="116" onAir="1" protocol="livetv" videoResolution="576" />
</Video>
<Video addedAt="1493065214" contentRating="TV-PG" duration="1800000" grandparentKey="/library/metadata/304" grandparentRatingKey="304" grandparentThumb="/library/metadata/304/thumb/1493065214" grandparentTitle="Seinfeld" index="5" key="/library/metadata/306" originallyAvailableAt="1995-10-19" parentIndex="7" parentKey="/library/metadata/305" parentRatingKey="305" parentTitle="Season 7" ratingKey="306" summary="Jerry tries to ensure that Elaine's houseguest (Jeremiah Birkett) doesn't sleep through the New York Marathon." title="The Hot Tub" titleSort="Hot Tub" type="episode" year="1995">
<Media audioChannels="2" beginsAt="1493109300" channelID="5" channelIdentifier="005" channelThumb="http://tmsimg.plex.tv/h3/NowShowing/51307/s51307_h3_aa.png" channelTitle="005 KFVE (MNT)" duration="1800000" endsAt="1493111100" id="117" protocol="livetv" videoResolution="576" />
</Video>
</Timeline>
<AlsoAiring>
<Video addedAt="1493065214" duration="2100000" grandparentKey="/library/metadata/260" grandparentRatingKey="260" grandparentThumb="/library/metadata/260/thumb/1493065214" grandparentTitle="KHON2 News at 10" key="/library/metadata/262" originallyAvailableAt="2017-04-24" parentIndex="2017" parentKey="/library/metadata/261" parentRatingKey="261" parentTitle="Season 2017" ratingKey="262" summary="" title="Episode 04-24" type="episode" year="2017">
<Media audioChannels="2" beginsAt="1493107200" channelID="2" channelIdentifier="002" channelThumb="http://tmsimg.plex.tv/h3/NowShowing/10212/s10212_h3_aa.png" channelTitle="002 KHON (FOX)" duration="2100000" endsAt="1493109300" id="99" onAir="1" premiere="1" protocol="livetv" videoResolution="576" />
</Video>
<Video addedAt="1493065214" duration="3600000" grandparentKey="/library/metadata/281" grandparentRatingKey="281" grandparentThumb="/library/metadata/281/thumb/1493065214" grandparentTitle="KITV Island News at 10:00" key="/library/metadata/283" originallyAvailableAt="2017-04-24" parentIndex="2017" parentKey="/library/metadata/282" parentRatingKey="282" parentTitle="Season 2017" ratingKey="283" summary="" title="Episode 04-24" type="episode" year="2017">
<Media audioChannels="2" beginsAt="1493107200" channelID="4" channelIdentifier="004" channelThumb="http://tmsimg.plex.tv/h3/NowShowing/10003/s10003_h3_aa.png" channelTitle="004 KITV (ABC)" duration="3600000" endsAt="1493110800" id="107" onAir="1" premiere="1" protocol="livetv" videoResolution="576" />
</Video>
<Video addedAt="1493065214" duration="2040000" grandparentKey="/library/metadata/317" grandparentRatingKey="317" grandparentThumb="/library/metadata/317/thumb/1493065214" grandparentTitle="Hawaii News Now at Ten" key="/library/metadata/319" originallyAvailableAt="2017-04-24" parentIndex="2017" parentKey="/library/metadata/318" parentRatingKey="318" parentTitle="Season 2017" ratingKey="319" summary="" title="Episode 04-24" type="episode" year="2017">
<Media audioChannels="2" beginsAt="1493107200" channelID="7" channelIdentifier="008" channelThumb="http://tmsimg.plex.tv/h3/NowShowing/10991/s10991_h3_aa.png" channelTitle="008 KHNL (NBC)" duration="2040000" endsAt="1493109240" id="123" onAir="1" premiere="1" protocol="livetv" videoResolution="576" />
</Video>
<Video addedAt="1493065214" duration="2100000" grandparentKey="/library/metadata/339" grandparentRatingKey="339" grandparentThumb="/library/metadata/339/thumb/1493065214" grandparentTitle="Hawaii News Now at 10:00" key="/library/metadata/341" originallyAvailableAt="2017-04-24" parentIndex="2017" parentKey="/library/metadata/340" parentRatingKey="340" parentTitle="Season 2017" ratingKey="341" summary="" title="Episode 04-24" type="episode" year="2017">
<Media audioChannels="2" beginsAt="1493107200" channelID="8" channelIdentifier="009" channelThumb="http://tmsimg.plex.tv/h3/NowShowing/10098/s10098_h3_aa.png" channelTitle="009 KGMB (CBS)" duration="2100000" endsAt="1493109300" id="132" onAir="1" premiere="1" protocol="livetv" videoResolution="576" />
</Video>
</AlsoAiring>
</MediaSubscription>
</MediaContainer>
### Cancel an existing grab [DELETE /media/grabbers/operations/{uuid}]
This endpoint cancels an existing media grab (recording). It can be used to resolve a conflict which exists for a rolling subscription. N.B. this cancellation does not persist across a server restart, but neither does a rolling subscription itself, so hey.
+ Parameters
+ uuid: `1742b85795` - The UUID if the grab.
+ Response 200 (application/xml)
## Live sessions [/livetv/sessions]
### Get all sessions [GET /livetv/sessions]
+ Response 200 (application/xml)
<?xml version="1.0" encoding="UTF-8"?>
<MediaContainer size="1">
<Video genuineMediaAnalysis="1" live="1">
<Media uuid="dc30f95e-6379-44f7-8168-172ffc820496">
<Part>
<Stream codec="h264" frameRate="29.970" height="1080" index="0" level="40" pixelAspectRatio="1:1" profile="high" scanType="interlaced" streamType="1" width="1920" />
<Stream audioChannelLayout="5.1(side)" channels="6" codec="ac3" index="1" samplingRate="48000" streamType="2" />
</Part>
</Media>
</Video>
</MediaContainer>
### Get particular session [GET /livetv/sessions/{session}]
+ Response 200

View File

@@ -0,0 +1,169 @@
## Media Grabber Endpoints [/media/grabbers]
Media grabbers provide ways for media to be obtained for a given protocol. The simplest ones are `stream` and `download`. More complex grabbers can have associated devices.
### Get available grabbers [GET /media/grabbers{?protocol}]
+ Parameters
+ protocol: `livetv` (optional) - Only return grabbers providing this protocol.
+ Response 200 (application/xml)
<MediaContainer size="3">
<MediaGrabber identifier="tv.plex.grabbers.hdhomerun" protocol="livetv" title="HDHomerun" />
<MediaGrabber identifier="tv.plex.grabbers.stream" protocol="stream" title="Stream" />
<MediaGrabber identifier="tv.plex.grabbers.download" protocol="download" title="Download" />
</MediaContainer>
### Get all devices [GET /media/grabbers/devices]
+ Response 200 (application/xml)
<MediaContainer size="2">
<Device key="1053C0CA" lastSeenAt="1461450473" make="Silicondust" model="HDHomeRun EXTEND" modelNumber="HDTC-2US" protocol="livetv" tuners="2" sources="Antenna,Cable" uri="http://10.0.0.164" uuid="1053C0CA" />
<Device key="141007E7" lastSeenAt="1461450479" make="Silicondust" model="HDHomeRun EXPAND" modelNumber="HDHR3-4DC" protocol="livetv" tuners="4" sources="Cable" uri="http://home.techconnect.nl:8822" uuid="141007E7" />
</MediaContainer>
### Tell grabbers to discover devices [POST /media/grabbers/devices/discover]
+ Response 200 (application/xml)
<?xml version="1.0" encoding="UTF-8"?>
<MediaContainer size="1">
<Device key="1053C0CA" lastSeenAt="1461450473" make="Silicondust" model="HDHomeRun EXTEND" modelNumber="HDTC-2US" protocol="livetv" tuners="2" uri="http://10.0.0.164" uuid="1053C0CA" />
</MediaContainer>
### Add a device [POST /media/grabbers/devices{?uri}]
This endpoint adds a device to an existing grabber. The device is identified, and added to the correct grabber.
+ Parameters
+ uri: `http://10.0.0.5` - the URI of the device.
+ Response 200 (application/xml)
<MediaContainer size="1">
<Device key="1053C0CA" lastSeenAt="1461450473" make="Silicondust" model="HDHomeRun EXTEND" modelNumber="HDTC-2US" protocol="livetv" tuners="2" uri="http://10.0.0.5" uuid="1053C0CA" />
</MediaContainer>
### Remove a device [DELETE /media/grabbers/devices/{device}]
+ Parameters
+ device: `42` - the ID of the device.
+ Response 200 (application/xml)
<MediaContainer message="" size="0" status="0" />
+ Response 404
## Device Endpoints [/media/grabbers/devices]
### Get device details [GET /media/grabbers/devices/{device}]
+ Parameters
+ device: `42` - the ID of the device.
+ Response 200 (application/xml)
<MediaContainer size="1">
<Device key="6" lastSeenAt="1461737032" make="Silicondust" model="HDHomeRun EXPAND" modelNumber="HDHR3-4DC" protocol="livetv" sources="Cable" state="1" status="1" tuners="4" uri="http://home.techconnect.nl:8822" uuid="141007E7">
<ChannelMapping channelKey="5cc83d73af4a72001e9b16d7-5cab3c634df507001fefcad0" deviceIdentifier="46.3" enabled="1" lineupIdentifier="002" />
<ChannelMapping channelKey="5cc83d73af4a72001e9b16d7-5cab3d20d30eca001db32922" deviceIdentifier="48.9" enabled="0" lineupIdentifier="004" />
<ChannelMapping channelKey="5cc83d73af4a72001e9b16d7-5cab3d07771bb2001ef88f72" deviceIdentifier="49.12" enabled="1" lineupIdentifier="011" />
<ChannelMapping channelKey="5cc83d73af4a72001e9b16d7-5cab3c63de29da001cf021c2" deviceIdentifier="49.3" enabled="0" lineupIdentifier="008" />
<ChannelMapping channelKey="5cc83d73af4a72001e9b16d7-5cab3c63e3ef4d001d05ba70" deviceIdentifier="10.4" enabled="1" />
</Device>
</MediaContainer>
### Enable or disable a device [PUT /media/grabbers/devices/{device}{?enabled}]
+ Parameters
+ device: `42` - the ID of the device.
+ Response 200 (application/xml)
<MediaContainer message="" size="0" status="0" />
### Get a device's channels [GET /media/grabbers/devices/{device}/channels]
+ Parameters
+ device: `42` - the ID of the device.
+ Response 200 (application/xml)
<MediaContainer size="48">
<DeviceChannel drm="0" hd="0" identifier="46.1" name="KPXO HD" />
<DeviceChannel drm="0" hd="0" identifier="46.3" name="KHON HD" />
</MediaContainer>
### Get metadata item for tuned channel [GET /media/grabbers/devices/{device}/channels/{channel}]
This endpoint can be used with the transcoder start and decision endpoints.
+ Parameters
+ device: `42` - the ID of the device.
+ channel: `2.1` - the channel ID to retrieve
+ Response 200 (application/xml)
<?xml version="1.0" encoding="UTF-8"?>
<MediaContainer size="1">
<Video genuineMediaAnalysis="1" live="1">
<Media uuid="dc30f95e-6379-44f7-8168-172ffc820496">
<Part>
<Stream codec="h264" frameRate="29.970" height="1080" index="0" level="40" pixelAspectRatio="1:1" profile="high" scanType="interlaced" streamType="1" width="1920" />
<Stream audioChannelLayout="5.1(side)" channels="6" codec="ac3" index="1" samplingRate="48000" streamType="2" />
</Part>
</Media>
</Video>
</MediaContainer>
+ Response 404: Channel not currently tuned
### Tune a channel on a device [POST /media/grabbers/devices/{device}/channels/{channel}/tune]
+ Parameters
+ device: `42` - the ID of the device.
+ channel: `2.1` - the channel ID to tune
+ Response 200 (application/xml)
Identical to the GET above
+ Response 500: Tuning failed
### Set a device's channel mapping [PUT /media/grabbers/devices/{device}/channelmap{?channelMapping,channelsEnabled}]
+ Parameters
+ device: `42` - the ID of the device.
+ channelMapping: `channelMapping[46.3]=002&channelMapping[48.9]=004` - the mapping of changes, passed as a map.
+ channelsEnabled: `46.1,44.1,45.1` - the channels which are enabled.
+ Response 200 (application/xml)
<MediaContainer message="" size="0" status="0" />
### Tell a device to scan for channels [POST /media/grabbers/devices/{device}/scan{?source}]
+ Parameters
+ device: `42` - the ID of the device.
+ source: `Cable` - a valid source for the scan.
+ Response 200 (application/xml)
+ Headers
X-Plex-Activity: 7e650c37-1639-4f60-9866-09b8eaf35a7a
+ Body
<MediaContainer message="" size="0" status="0" />
### Tell a device to stop scanning for channels [DELETE /media/grabbers/devices/{device}/scan]
+ Parameters
+ device: `42` - the ID of the device.
+ Response 200 (application/xml)
<MediaContainer message="" size="0" status="0" />

View File

@@ -0,0 +1,139 @@
## Media Providers [/media/providers]
Media providers are general purpose entities which supply media to Plex clients. Their API is a subset of the full Plex server API, and the subset is defined via a set of features on the "root" endpoint of the provider. Media provider can be hosted by a media server (which can be very useful for development work) or in the cloud, linked to a specific Plex account. This section explains media providers generally, and then provides the specific server-hosted APIs around media providers.
The top level of a provider definition returns some basic information:
- `identifier`: A unique identifier for the provider, e.g. `tv.plex.podcast`.
- `title`: The title of the provider.
- `types`: This attribute contains a comma-separated list of the media types exposed by the provider (e.g. `video, audio`).
- `protocols`: A comma-separated list of default protocols for the provider, which can be:
- `stream`: The provider allows streaming media directly from the provider (e.g. for Vimeo).
- `download`: The provider allows downloading media for offline storage, sync, etc. (e.g. Podcasts).
- `livetv`: The provider provides live content which is only available on a schedule basis.
```xml
<MediaProvider identifier="tv.plex.awesome" title="Program Guide" types="video" protocols="livetv">
```
The list of supported features, along with the API endpoints each feature represents is shown in the following list. Note that each feature can define a custom endpoint URL, so it doesn't have to match the server API exactly.
- **search**: This feature implies that it supports the server `/hubs/search` endpoint.
- **metadata**: This feature implies that it supports the server endpoints: `/library/metadata/X`, `/library/metadata/X/children` and `/library/metadata/X/grandchildren`. This endpoint family allows browsing a hierarchical tree of media (e.g. show to episodes, or artist to tracks).
- **content**: This feature implies that the provider exposes a content catalog, in the form of libraries to browse (grid of content), or discover (via hubs). Each entry in the content feature can contain:
- `hubKey`: This implies it supports a discovery endpoint with hubs.
- `key`: This implies it supports a content catalog.
Each content feature can contain one or both of these keys, depending on the structure. More details on the various combinations are provided below.
- **match**: The match feature is used to match a piece of media to the provider's content catalog via a set of hints. As a specific example, you might pass in a title hint of "Attack of the 50 Foot Woman" and a year hint of 1958 for the movie type. The provider would then use all the hints to attempt to match to entries in its catalog).
- **manage**: The manage feature implies a whole host of endpoints around _changing_ data inside a library (e.g. editing fields, customizing artwork, etc.). This feature is generally only available on an actual server.
- **timeline**: The timeline feature implies that the provider wants to receive timeline (playback notifications) requests from a client as the server does under `/:/timeline`. The feature may additionally specify the `scrobbleKey` and `unscrobbleKey` attributes, which represent the server `/:/scrobble` and `/:/unscrobble` endpoints which allow marking a piece of media watched or unwatched.
- **rate**: This feature implies the provider supports the server `/:/rate` endpoint which allows rating content.
- **playqueue**: This feature implies the provider supports the play queue family of endpoints. The `flavor` attribute further specifies the subset; the only supported flavor is currently `full`.
- **playlist**: This feature implies the provider supports the playlist family of endpoints. If `readonly` is set, that means that the provider only allows listing and playing playlists (via play queue API), not actually creating or editing them.
- **subscribe**: This provider allows media subscriptions to be created, and subsequently used to "record" into a library.
- **promoted**: This feature allows the provider to supply an endpoint that will return a collection of "promoted" hubs that many clients show on a user's home screen.
- **continuewatching**: This feature allows the provider to supply an endpoint that will return a hub for merging into a global Continue Watching hub.
Here's a full example provider definition:
```xml
<MediaProvider identifier="tv.plex.providers.epg.onconnect:292" title="Program Guide" types="video" protocols="livetv">
<Feature type="content">
<Directory icon="/icons/foo.png" hubKey="/tv.plex.providers.epg.onconnect:292/hubs/discover" title="Discover"/>
<Directory icon="/icons/foo.png" key="/tv.plex.providers.epg.onconnect:292/sections/1" type="movie" title="Movies"/>
<Directory icon="/icons/foo.png" key="/tv.plex.providers.epg.onconnect:292/sections/4" type="show" title="News"/>
<Directory icon="/icons/foo.png" key="/tv.plex.providers.epg.onconnect:292/sections/2" type="show" title="Shows"/>
<Directory icon="/icons/foo.png" key="/tv.plex.providers.epg.onconnect:292/sections/3" type="show" title="Sports"/>
</Feature>
<Feature key="/tv.plex.providers.epg.onconnect:292/hubs/search" type="search"></Feature>
<Feature key="/tv.plex.providers.epg.onconnect:292/matches" type="match"></Feature>
<Feature key="/tv.plex.providers.epg.onconnect:292/metadata" type="metadata"></Feature>
<Feature type="subscribe"></Feature>
</MediaProvider>
```
The `content` directories describe the navigation structure for the provider. Each directory contains either a `hubKey`, a `key`, or both attributes.
- `hubKey`: Implies that following the key leads to a container of hubs.
- `key`: Implies that following the key leads to a browse container (the interstitial between a library and its content which contains types, filters, sorts, etc.).
- `icon`: Optional, specifies the icon used for a content directory.
Let's see how the `content` feature specifically can be used to define a wide variety of different media providers.
#### Home discovery and browsable libraries (e.g. EPG)
Shown in the example above, in this media provider the first content directory is an item with only `hubKey`, meaning it only providers discovery hubs. This is where we show airings which start soon, are in progress, and a few other hubs with recommendations, upcoming movies, etc. It's essentially "landing page" for the provider.
The subsequent directories have only a browse `key`, which means there is no discovery page associated for them, but instead, they provide a grid view of the content with options for filtering and sorting. We split these directories by type, so we have one for Movies, one for Shows, one for Sports, and one for News.
#### Home discovery and libraries with browse and discovery (e.g. "classic")
This is the hierarchy we have in a regular Plex server. There's a home screen (a content directory with just discovery) and then for each library, there's a content directory with both browse and discovery capabilities.
#### Minimal provider
There's no requirement to provide the content feature, given that there are two other ways to access content within a provider: search and match. The former can contribute to global search, whereas the latter is used for things like the DVR engine; once media subscriptions are set up, they look for matching content using the match feature, and examined using the metadata feature.
#### Deeper Hierarchies
If you examine an app like Spotify, you'll see many of the concepts here apply to their content hierarchy. Their content screens are either grids or hubs. But one notable difference is that the content hierarchy runs a bit deeper than the examples we've examined thus far. For example, one of the top-level selections is "Genres & Moods". Diving into one of the genres leads to a discovery area with different hubs for popular playlists, artists, and albums from the genre. Selecting a mood leads to a grid with popular playlists for the mood. In order to support this sort of hierarchy, we need an extension to the regular library, which is a *content directory*. This allows us to nest content, without losing any of the power and features—for example, the grid with popular playlists could list filters and sorts specific for that grid. This is power you simply don't have with the old channel architecture.
#### Extensions to regular libraries
This section examines extensions to plain libraries which content providers can use, and which clients need to be aware of.
- **Nested content directories**: In regular libraries, there are fixed types of directories (e.g. shows, or music albums). In content providers, we want to have the ability to display other types of things (e.g. stations, or moods, or genres) as first-class things in a grid or discovery layout. Here's an example of what a nested content directory looks like. Given the `type` of content, the client knows that this directory should be treated like a content directory feature entry.
```xml
<Directory key="foo" hubKey="foo2" type="content" aspectRatio="1:1" title="Genres and Moods" />
```
- **Aspect ratio hint**: Because the entities listed in content directories can be arbitrary, it's important to tell the client some information about how they should be displayed. The `thumb` attribute contains no information about aspect ratio, so clients make assumptions based upon known types (e.g. movies are 2:3, episode thumbs are 16:9, etc.). This attributes allows the provider to specify exactly the aspect ratio of the thing being displayed.
### Get all providers [GET /media/providers]
Returns a list of the available media providers. This endpoint can also be used as the "connection test" to check if the server can be reached.
+ Response 200 (application/xml)
```xml
<MediaContainer size="2" allowCameraUpload="1" allowChannelAccess="1" ... version="1.13.5.5291-6fa5e50a8" voiceSearch="1">
<MediaProvider ... />
<MediaProvider ... />
</MediaContainer>
```
### Add a media provider [POST /media/providers{?url}]
This endpoint registers a media provider with the server. Once registered, the media server acts as a reverse proxy to the provider, allowing both local and remote providers to work.
+ Parameters
+ url: `http://localhost:10000` - The URL of the media provider to add.
+ Response 200
### Refresh media providers [POST /media/providers/refresh]
Refresh all known media providers. This is useful in case a provider has updated features, e.g. during local development.
+ Response 200
### Delete a media provider [DELETE /media/providers/{provider}]
+ Parameters
+ provider: `47` (number) - The ID of the media provider to delete.
+ Response 200

View File

@@ -0,0 +1,122 @@
## Media Subscriptions [/media/subscriptions]
### Get the subscription template [GET /media/subscriptions/template{?type}]
+ Parameters
+ type: `2` - The type of the thing we're subscribing too (e.g. show, season).
+ Response 200 (application/xml)
<MediaContainer size="7">
<Setting id="newnessPolicy" label="" default="0" summary="" type="int" value="-1" hidden="0" advanced="0" group=""/>
<Setting id="replacementPolicy" label="" default="0" summary="" type="int" value="-1" hidden="0" advanced="0" group=""/>
<Setting id="minVideoQuality" label="" default="0" summary="" type="int" value="-1" hidden="0" advanced="0" group=""/>
<Setting id="lineupChannel" label="" default="" summary="" type="text" value="" hidden="0" advanced="0" group=""/>
<Setting id="startOffsetSeconds" label="" default="0" summary="" type="int" value="-1" hidden="0" advanced="0" group=""/>
<Setting id="endOffsetSeconds" label="" default="0" summary="" type="int" value="-1" hidden="0" advanced="0" group=""/>
<Setting id="recordPartials" label="" default="true" summary="" type="bool" value="false" hidden="0" advanced="0" group=""/>
</MediaContainer>
### Create a subscription [POST /media/subscriptions/{?targetLibrarySectionID,targetSectionLocationID,type,hints,prefs}]
+ Parameters
+ targetLibrarySectionID: `1` - The library section into which we'll grab the media. Not actually required when the subscription is to a playlist.
+ targetSectionLocationID: `3` (optional) - The section location into which to grab.
+ type: `2` - The type of the thing we're subscribing too (e.g. show, season).
+ hints: `hints[title]=Family+Guy` (array) - Hints describing what we're looking for. Note: The hint `ratingKey` is required for downloading from a PMS remote.
+ prefs: `prefs[minVideoQuality]=720` (array) - Subscription preferences.
+ params: (array) - Subscription parameters.
+ `params[mediaProviderID]=1` Required for downloads to indicate which MP the subscription will download into
+ `params[source]=server://0123456789abcdef0123456789abcdef01234567/com.plexapp.plugins.library`: Required for downloads to indicate the source of the downloaded content.
+ Response 200 (application/xml)
<MediaContainer size="1">
<MediaSubscription key="18" metadataType="2" targetLibrarySectionID="2" title="Family Guy">
<MediaGrabOperation beginsAt="1465814100" endsAt="1465815900" grandparentTitle="Family Guy" index="1" mediaSubscriptionID="19" parentIndex="1" status="1" title="Death Has a Shadow">
<Video addedAt="1464994517" contentRating="TV-14" duration="1800000" grandparentTitle="Family Guy" index="1" key="/tv.plex.providers.epg.onconnect-811e2e8a-f98f-4d1f-a26a-8bc26e4999a7/metadata/2214" originallyAvailableAt="1999-01-31" parentIndex="1" parentKey="/tv.plex.providers.epg.onconnect-811e2e8a-f98f-4d1f-a26a-8bc26e4999a7/metadata/2213" parentRatingKey="2213" ratingKey="com.gracenote.onconnect://episode/EP002960010001" summary="After Peter gets fired following a riotous bachelor party, he receives a check for $150,000 from the welfare department." title="Death Has a Shadow" type="episode" year="1999">
<Media audioChannels="2" beginsAt="1465814100" channelID="32" channelIdentifier="005" duration="1800000" endsAt="1465815900" id="2052" protocol="livetv" videoResolution="480">
<Part id="2052" key="/library/parts/2052/0/file">
</Part>
</Media>
</Video>
</MediaGrabOperation>
<Setting advanced="0" default="0" enumValues="0:all episodes|1:only new episodes" group="" hidden="0" id="newnessPolicy" label="Record" summary="" type="int" value="0" />
<Setting advanced="0" default="0" enumValues="0:never|1:with higher resolution recordings" group="" hidden="0" id="replacementPolicy" label="Replacement existing media" summary="" type="int" value="0" />
<Setting advanced="0" default="0" enumValues="0:none|720:HD" group="" hidden="0" id="minVideoQuality" label="Minimum resolution" summary="" type="int" value="720" />
<Setting advanced="0" default="" group="" hidden="0" id="lineupChannel" label="Channel to record from" summary="" type="text" value="" />
<Setting advanced="0" default="0" group="" hidden="0" id="startOffsetSeconds" label="Padding before show starts" summary="" type="int" value="0" />
<Setting advanced="0" default="0" group="" hidden="0" id="endOffsetSeconds" label="Padding after show ends" summary="" type="int" value="0" />
<Setting advanced="0" default="true" group="" hidden="0" id="recordPartials" label="Record partial media" summary="" type="bool" value="true" />
</MediaSubscription>
</MediaContainer>
### Get all subscriptions [GET /media/subscriptions/{?includeGrabs}]
+ Parameters
+ includeGrabs: `1` (optional) - Whether or not to include all the scheduled grabs for each subcription.
+ Response 200 (application/xml)
<MediaContainer size="1">
<MediaSubscription key="1" metadataType="2" targetLibrarySectionID="2" title="fresh off the boat">
<Setting advanced="0" default="0" enumValues="0:all episodes|1:only new episodes" group="" hidden="0" id="newnessPolicy" label="Record" summary="" type="int" value="0" />
</MediaSubscription>
</MediaContainer>
### Get a single subscription [GET /media/subscriptions/{subscription}{?includeGrabs}]
+ Parameters
+ subscription: `42` - The ID of the subscription.
+ includeGrabs: `1` (optional) - Whether or not to include all the scheduled grabs for each subcription.
+ Response 200 (application/xml)
<MediaContainer size="1">
<MediaSubscription key="1" metadataType="2" targetLibrarySectionID="2" title="fresh off the boat">
<Setting advanced="0" default="0" enumValues="0:all episodes|1:only new episodes" group="" hidden="0" id="newnessPolicy" label="Record" summary="" type="int" value="0" />
</MediaSubscription>
</MediaContainer>
### Delete a subscription [DELETE /media/subscriptions/{subscription}]
+ Parameters
+ subscription: `42` - The ID of the subscription.
+ Response 200
### Edit a subscription [PUT /media/subscriptions/{subscription?prefs}]
+ Parameters
+ prefs: `prefs[minVideoQuality]=720` (array) - Subscription preferences.
+ Response 200 (application/xml)
<MediaContainer size="1">
<MediaSubscription key="1" metadataType="2" targetLibrarySectionID="2" title="fresh off the boat">
<Setting advanced="0" default="0" enumValues="0:all episodes|1:only new episodes" group="" hidden="0" id="newnessPolicy" label="Record" summary="" type="int" value="0" />
</MediaSubscription>
</MediaContainer>
### Get all scheduled recordings [GET /media/subscriptions/scheduled]
+ Response 200 (application/xml)
<MediaContainer size="1">
<MediaGrabOperation beginsAt="1466060400" endsAt="1466062200" grandparentTitle="Fresh Off the Boat" index="5" mediaSubscriptionID="1" parentIndex="2" status="1" title="Miracle on Dead Street">
<Video addedAt="1464994564" contentRating="TV-PG" duration="1800000" grandparentTitle="Fresh Off the Boat" index="5" key="/tv.plex.providers.epg.onconnect-811e2e8a-f98f-4d1f-a26a-8bc26e4999a7/metadata/2543" originallyAvailableAt="2015-10-27" parentIndex="2" parentKey="/tv.plex.providers.epg.onconnect-811e2e8a-f98f-4d1f-a26a-8bc26e4999a7/metadata/2542" parentRatingKey="2542" ratingKey="com.gracenote.onconnect://episode/EP019218760019" summary="Louis wants to make his street a prime trick-or-treat destination." title="Miracle on Dead Street" type="episode" year="2015">
<Media audioChannels="2" beginsAt="1466060400" channelID="21" channelIdentifier="004" duration="1800000" endsAt="1466062200" id="2581" protocol="livetv" videoResolution="480">
<Part id="2581" key="/library/parts/2581/0/file">
</Part>
</Media>
</Video>
</MediaGrabOperation>
</MediaContainer>
### Process all subscriptions [POST /media/subscriptions/process]
+ Response 200
+ Headers
X-Plex-Activity: d391ddb0-b29b-4e20-a57a-46b15b4e4318

View File

@@ -0,0 +1,275 @@
## Remote Media Grabbers
This interface is used against remote media grabbers. Among others, the Plex Tuner Service implements this interface. Responses generally consist of a `MediaContainer` element, even when there is nothing to return, containing status and message in order to convey response codes and error messages. In order to manually make requests for any of these endpoints, you will need to know the port number for the device. This is generally conveyed in the SSDP data, as described at the end of this document.
```xml
<MediaContainer status="0" message="...">
```
### Media Grabber Identification [GET /]
Provides general information about the media grabber, including:
- `identifier`: A unique string used to distinguish different media grabbers, usually specified in reverse domain format.
- `title`: The friendly name of the media grabber.
- `icon`: (optional) An icon representing the grabber.
- `protocols`: The protocols supported by the grabber. This is used to match up media providers with media grabbers.
+ Response 200 (application/xml)
<MediaContainer>
<MediaGrabber identifier="tv.plex.dvblink" title="DVBLink" protocols="livetv">
</MediaContainer>
### Device Discovery [POST /devices/discover]
Devices with `livetv` protocol have devices associated with them. This endpoint requests the grabber attempt to discover any devices it can, and it returns zero or more devices.
The response consists of a list of devices, with the following attributes:
- `key`: The endpoint to request device details. This is the `devicekey` to be used in all other requests.
- `make`, `model`,` modelNumber` are optional and describe the device as best as possible (e.g. a make of `Silicondust`, model of `hdhomeruntc_atsc` and model number of `HDTC-2US`).
- `tuners` is the number of tuners the device has.
- `status` represents the known status of the device, and can either be `dead` or `alive`. If a grabber doesn't do any caching, this value will always be `alive` as it will only return devices it knows about.
- `protocol` is aways `livetv` for devices at the moment.
- `title` represents a user-friendly title for the device.
- `uri` (optional) represents the address of a network-accessible tuner.
- `uuid` holds the unique identifier for a device, in special URI format `device://com.vendor/xxx`. Note that in some cases, devices may not have serial numbers (which is usually the `xxx` part of the URI), and something appropriate must be synthesized based on PCI bus, USB identifier, etc. Care must be taken to ensure it's as universally unique as possible.
- `thumb` (optional) a path relative to the `uri` of an icon for the device. These icons will be displayed on the settings screen when creating a DVR. Icons should be in PNG format and be 560 pixels x 560 pixels in order to display correctly. The path to this file should be relative to the tuner, and be hosted by the tuner itself.
- `interface`: The physical interface that the device is connected to. This will be used to set a generic thumbnail for the tuner if a `thumb` attribute is not passed. Possible values are `usb`, `pcie`, and `network`.
- Devices can also provide device-specific preferences that can be set by the user. These are passed in `<Preference>` elements as part of a Device description, with the following attributes:
- `id`: A string identifier for the preference. No two Preference elements may have the same identifier since this is what is passed back when PMS returns the values via the `/device/key/prefs` endpoint.
- `label`: A string label that will be displayed on the device settings in the Plex DVR Setup UI.
- `summary`: (optional) A longer description of the setting that will be displayed below the preference on the Plex DVR Setup UI.
- `type`: The data type for the preference. Possible values are `int`, `bool`, and `text`.
- `value`: The current value for the preference. This will be one of the keys in the `enumValues` attribute.
- `enumValues`: A pipe-separated list of options for the preference. Each option is a colon-separated entry with the form of `value:display-string`.
+ Response 200 (application/xml)
<MediaContainer size="1">
<Device key="123123" make="Silicondust" model="HDHomeRun CONNECT" modelNumber="HDHR4-2DT"
protocol="livetv" status="alive" title="HDHomeRun CONNECT" tuners="1"
uri="http://192.168.1.30:80" uuid="device://tv.plex.grabbers.hdhomerun/1230984C"
thumb="url/to/thumb.png" interface=`usb`>
<Preference id="resolution" label="Stream Resolution"
summary="This is the video resolution returned by the tuner" type="int"
default="0" value="0" enumValues="0:720|1:1080" />
</Device>
</MediaContainer>
### Device Probe [POST /devices/probe{?uri}]
Probes a specific URI for a network device, and returns a device, if it exists at the given URI.
+ Parameters
+ uri: http://10.0.0.100:10000 (string) - URI for the device. Can be either HTTP or HTTPS.
+ Response 200 (application/xml)
<MediaContainer size="1">
<Device ... />
</MediaContainer>
### Get identity and capabilities [GET /devices/{devicekey}]
Returns the identity, capabilities, and current status of the devices and each of its tuners.
- Tuner status can be one of the following:
- `idle`: The device isn't doing anything.
- `streaming`: The device is currently streaming media.
- `scanning`: The device is scanning for channels.
- `networksScanned`: The device has scanned for networks and is awaiting being scanned for channels, given a specific network.
- `error`: The device is unhappy.
- If the status is `streaming`, the following attributes should be included:
- `signalStrength`: A signal strength metric normalized to a 0-100 scale.
- `signalQuality`: A signal quality metric normalized to a 0-100 scale.
- `symbolQuality`: (optional) A symbol quality metric normalized to a 0-100 scale.
- `channelIdentifier`: The identifier for the channel currently being tuned. This should be the same format as the identifiers in the `/devices/{devicekey}/channels` endpoint.
- `lock`: A 0 or 1 value denoting that the tuner has a signal lock.
- If the status is `scanning`, the following attributes should be included:
- `progress`: A percentage indicating how complete the scanning process is.
- `channelsFound`: The number of channels found so far.
+ Parameters
+ devicekey: 12323213 (string, required) - key referring to tuner device, as originally reported in the `/devices/discover` endpoint.
+ Response 200 (application/xml)
<MediaContainer size="1">
<Device key="dvb%23hdhr%230%23305174604" make="Silicondust" model="hdhomerun4_dvbt"
modelNumber="HDHR4-2DT" protocol="livetv" status="alive"
title="HDHomeRun 1230984C (192.168.1.30) - 0" tuners="1" uri="http://192.168.1.30:80"
uuid="device://tv.plex.grabbers.hdhomerun/1230984C">
<Tuner index="0" status="streaming" channelIdentifier="triplet://0:209:4" lock="1" signalStrength="40" signalQuality="91"/>
<Tuner index="1" status="idle"/>
<Tuner index="2" status="scanning" progress="50" channelsFound="10"/>
</Device>
</MediaContainer>
### Get a device's channels [GET /devices/{devicekey}/channels]
Returns the current channels. This list is updated after a complete channel scan, and should not be assumed to persist beyond that.
The response contains zero or more channels, with the following attributes:
- `drm`: If known, whether or not a channel contains Digital Rights Management. When enabled, these channels are mostly unusable by the media server.
- `channelIdentifier`: This is a unique identifier for the channel, represented by an URI. This can either be:
- `id://xxx`: The channel identifier is a channel number (e.g. 12 or 46.3).
- `tuple://x:y:z`: The channel identifier is a DVT tuple.
- `name`: The name for the channel. This is the string that will be displayed for the channel on the client.
- `origin`: (optional) This is the broadcaster that made this channel available on its TV distribution infrastructure. On DVB-C and DVB-T networks it is (usually) the same as the TV provider. The added value of this information is to help user during channel selection phase.
- `number`: (optional) is a suggested channel number in a guide lineup as sent by TV provider
- `type`: (optional) is either `tv` or `radio`.
- `param`: (optional) denotes channel tuning parameters that have to be passed back to `/media` endpoint.
- `signalStrength`: (optional) denotes the signal strength of the channel when it was scanned.
- `signalQuality`: (optional) denotes the signal quality of the channel when it was scanned.
+ Parameters
+ devicekey: 12323213 (string, required) - key referring to tuner device, as originally reported in the `/devices/discover` endpoint.
+ Response 200 (application/xml)
<MediaContainer size="1">
<Channel drm="0" channelIdentifier="triplet://10:1123:201" name="NOS 1 HD" origin="Canal Digitaal"
param="xxxxxxx" number="10" type="tv|radio" />
</MediaContainer>
### Get channel scan providers [GET /devices/{devicekey}/scanners{?type}]
Before scanning a device for channels, it must be queried to ascertain which type of scanners are supported. Each scanner may have custom configuration which is passed back in the form of preferences. These preferences must be shown the user, and the values round-tripped back when the scan is kicked off. The response includes one or more scanners, defined below.
If the response's media container has `simultaneousScanners="1"`, this implies that the device supports channels via multiple scanners simultaneously. HDHR devices, by contrast, can support either over-the-air or cable channels, for example, but not both simultaneously.
+ Parameters
+ devicekey: 12323213 (string, required) - key referring to tuner device, as originally reported in the `/devices/discover` endpoint.
+ type: 5 (string, optional) - The filter on broadcast standard type, which can be: `0` (atsc), `1` (cqam), `2` (dvb-s), `3` (iptv), `4` (virtual), `5` (dvb-t), `6` (dvb-c), `7` (isdbt)
+ Response 200 (application/xml)
<MediaContainer size="3" simultaneousScanners="1">
<Scanner type="dvb-t">
<Setting id="provider" enumValues="1:DVB-T Netherlands|2:Digitenne (DVB-T, Netherlands)..." />
</Scanner>
<Scanner type="dvb-c">
<Setting id="provider"enumValues="1:Ziggo (DVB-C, Netherlands)|2:Caiway (DVB-C, Netherlands)..." />
</Scanner>
<Scanner type="dvb-s">
<Setting id="provider" enumValues="190:Astra 19.0|230:Astra 23.5|047:Eutelsat 4.7..." />
<Setting id="diseqcType" enumValues="none:None|mini_a:Mini-,..." />
<Setting id="lnbType" enumValues="ku_linear:Ku-linear|ku_circular:Ku-circular..." />
</Scanner>
</MediaContainer>
#### Scanners
Defines a scanner that can be used to search for channels. They will have the following attributes:
- `type`: One of the broadcast standard types: `atsc`, `cqam`, `dvb-s`, `iptv`, `virtual`, `dvb-t`, `dvb-c`, `isdbt`
- `country`: (optional) Defines a scanner to use based on the country chosen by the user during DVR setup. If there isn't a scanner with the country chosen by user, PMS will prefer to use the scanner without a country defined.
Each `<Scanner>` element will have one or more `<Setting>` elements, which defines the settings for that particular scanner. These settings are displayed to the user when configuring the device before scanning for channels. At least one setting must exist with the `provider`. `<Setting>` elements have the following attributes:
- `id`: The ID of the setting to be displayed. This will be used internally by PMS.
- `type`: The type of the setting. This is used internally by PMS. The valid values for this attribute are `text`, `int`, `double`, and `bool`. This type should match the first element of each colon-separated value described below. Prefer `text` if in doubt.
- `enumValues`: A pipe-separated list of colon-separated items to show to the user for this type of setting. For example, for `provider` settings and cable/OTA scanners, this is list of networks that provide the scanning data. Each colon-separated item has two parts: a unique identifier and a label. The ID will be passed in the request to `/scan` as the `source` parameter and the label will be displayed to users on a preference panel during device setup.
### Get scanned networks [GET /devices/{devicekey}/networks]
In some cases, channel scanning is a two-step process, where the first stage consists of scanning for networks (this is called "fast scan"). This is communicated to the client by entering the `networksScanned` state after a scan is kicked off. When encountering this state, the client must call this endpoint to retrieve the list of networks to scan. The user-selected network is then passed back to a second `/scan` request to scan channels for this network with the `network` parameter set.
+ Parameters
+ devicekey: 12323213 (string, required) - key referring to tuner device, as originally reported in the `/devices/discover` endpoint.
+ Response 200 (application/xml)
<MediaContainer size="2">
<Network key="43136" title="Noord Holland" />
<Network key="43138" title="Flevoland" />
</MediaContainer>
### Start a channel scan for network [POST /devices/{devicekey}/scan{?network,source,provider}]
Starts a background channel scan. Updates are received via querying the device details endpoint (`/devices/x`). The response will have the following attributes:
- `status`: The current status of the scanning operation.
+ Parameters
+ devicekey: 12323213 (string, required) - key referring to tuner device, as originally reported in the `/devices/discover` endpoint.
+ network: 10 (string, optional) - only valid if the device is in the `networksScanned` state, and specifies the network to scan.
+ source: 1 (integer, optional) - only valid when not performing a network scan. Specifies the type of scanner, as noted above.
+ provider: 1 (integer) - the key of the scanner to use when scanning.
+ Response 200 (application/xml)
<MediaContainer status="0" message="...">
### Cancel channel scan [DELETE /devices/{devicekey}/scan]
Cancels an ongoing background channel scan.
+ Parameters
+ devicekey: 12323213 (string, required) - key referring to tuner device, as originally reported in the `/devices/discover` endpoint.
+ Response 200 (application/xml)
<MediaContainer status="0" message="..." />
### Stream media from a tuner [GET /devices/{devicekey}/media/{channel}{?param}]
+ Parameters
+ devicekey: 12323213 (string, required) - key referring to tuner device, as originally reported in the `/devices/discover` endpoint.
+ channel: 5.1 (string, required) - the channel identifier passed back with each channel.
+ param: parm (string, optional) - If params were passed back with the channel from the `/device/x/channels` endpoint, they should be round-tripped into this endpoint.
+ Response 200 (application/octet-stream)
Media
### Provide preference values to the tuner [PUT /devices/{devicekey}/prefs]
These preferences are originally provided by the device in the `/devices/discover` endpoint.
+ Parameters
+ devicekey: 12323213 (string, required) - key referring to tuner device, as originally reported in the `/devices/discover` endpoint.
+ Any number of key-value pairs corresponding to values set by the user for the preferences provided by the tuner.
+ Response 200 (no data)
### SSDP Discovery support
Network tuners can present themselves on the network using the Simple Service Discovery Protocol and Plex Media Server will discover them. The following XML is an example of the data returned from SSDP. The `deviceType`, `serviceType`, and `serviceId` values must remain as they are in the example in order for PMS to properly discover the device. Other less-obvious fields are described in the parameters section below.
+ Example SSDP output
<root xmlns="urn:schemas-upnp-org:device-1-0">
<specVersion>
<major>1</major>
<minor>0</minor>
</specVersion>
<device>
<deviceType>urn:plex-tv:device:Media:1</deviceType>
<friendlyName>Turing Hopper 3000</friendlyName>
<manufacturer>Plex, Inc.</manufacturer>
<manufacturerURL>https://plex.tv/</manufacturerURL>
<modelDescription>Turing Hopper 3000 Media Grabber</modelDescription>
<modelName>Plex Media Grabber</modelName>
<modelNumber>1</modelNumber>
<modelURL>https://plex.tv</modelURL>
<UDN>uuid:42fde8e4-93b6-41e5-8a63-12d848655811</UDN>
<serviceList>
<service>
<URLBase>http://10.0.0.5:8088</URLBase>
<serviceType>urn:plex-tv:service:MediaGrabber:1</serviceType>
<serviceId>urn:plex-tv:serviceId:MediaGrabber</serviceId>
</service>
</serviceList>
</device>
</root>
+ Parameters
+ UDN: (string) A UUID for the device. This should be unique across models of a device at minimum.
+ URLBase: (string) The base HTTP URL for the device from which all of the other endpoints are hosted.

0
Markdown/Now Playing.md Normal file
View File

2
Markdown/Overview.md Normal file
View File

@@ -0,0 +1,2 @@
# Overview

0
Markdown/Preferences.md Normal file
View File

32
Markdown/Security.md Normal file
View File

@@ -0,0 +1,32 @@
## Security
### Get Transient Tokens [GET /security/token{?type,scope}]
This endpoint provides the caller with a temporary token with the same access level as the caller's token. These tokens are valid for up to 48 hours and are destroyed if the server instance is restarted.
+ Parameters
+ type: `delegation` - This is the only supported `type` parameter.
+ scope: `all` - This is the only supported `scope` parameter.
+ Response 200 (application/xml)
<MediaContainer size="0" token="transient-90904684-f91a-4391-8bf7-e0dfa7240285"></MediaContainer>
### Get Source Connection Information [GET /security/resources{?source}]
If a caller requires connection details and a transient token for a source that is known to the server, for example a cloud media provider or shared PMS, then this endpoint can be called. This endpoint is only accessible with either an admin token or a valid transient token generated from an admin token.
Note: requires Plex Media Server >= 1.15.4.
+ Parameters
+ source: `server://client-identifier` or `provider://provider-identifier` - The source identifier with an included prefix.
+ Response 200 (application/xml)
<MediaContainer size="1">
<Device name="PlexCorp (plex-corp)" clientIdentifier="243b471948ace337a8f92f129ec97d1902fcb1df" accessToken="transient-fa75f159-b9d2-42b6-8fbd-1761c7a4195a">
<Connection protocol="https" address="10.0.2.123" uri="https://10-0-2-123.93b10b279ff8456686414add109854cd.plex.direct:32400" port="32400" local="1" />
<Connection protocol="https" address="64.71.188.222" uri="https://64-71-188-222.93b10b279ff8456686414add109854cd.plex.direct:32403" port="32403" local="0" />
<Connection protocol="https" address="139.162.158.105" uri="https://139-162-158-105.93b10b279ff8456686414add109854cd.plex.direct:8443" port="8443" local="0" relay="1" />
</Device>
</MediaContainer>

0
Markdown/Statistics.md Normal file
View File

0
Markdown/Sync.md Normal file
View File

View File

0
plex-api-spec.yaml Normal file
View File