├── .gitignore ├── LICENSE ├── README.md ├── api.mustache ├── babel.config.js ├── blog ├── Announcment.md └── Plex API Resources.md ├── docs └── legacy │ └── plex │ ├── Activities.md │ ├── AutoUpdates.md │ ├── Butler.md │ ├── Events.md │ ├── Library │ ├── All.md │ ├── Auto Complete.md │ ├── Common.md │ ├── Hashes.md │ ├── Hubs.md │ ├── Ingest.md │ ├── Introduction.md │ ├── Matches.md │ ├── Media Queries.md │ ├── Play Queues.md │ ├── Playlists.md │ ├── Search.md │ └── Sections.md │ ├── Log.md │ ├── Media Feedback.md │ ├── Media Providers │ ├── Client Guide.md │ ├── DVR.md │ ├── Devices.md │ ├── EPG.md │ ├── Live.md │ ├── Media Grabbers.md │ ├── Media Providers.md │ ├── Media Subscriptions.md │ └── Remote Media Grabbers.md │ └── Security.md ├── docusaurus.config.js ├── package.json ├── sidebars.js ├── src ├── components │ └── HomepageFeatures │ │ ├── index.js │ │ └── styles.module.css ├── css │ └── custom.css └── pages │ ├── index.js │ ├── index.module.css │ ├── sdk-docs.js │ └── sdk-docs.module.css ├── static ├── .nojekyll ├── img │ ├── Open-Graph-Image.png │ ├── favicon.ico │ ├── logo.svg │ ├── undraw_docusaurus_mountain.svg │ ├── undraw_docusaurus_react.svg │ └── undraw_docusaurus_tree.svg ├── plex-media-server-spec-dereferenced.yaml └── plex-tv-spec-dereferenced.yaml └── yarn.lock /.gitignore: -------------------------------------------------------------------------------- 1 | # Dependencies 2 | /node_modules 3 | 4 | # Production 5 | /build 6 | 7 | # Generated files 8 | .docusaurus 9 | .cache-loader 10 | 11 | # Misc 12 | .DS_Store 13 | .env.local 14 | .env.development.local 15 | .env.test.local 16 | .env.production.local 17 | 18 | npm-debug.log* 19 | yarn-debug.log* 20 | yarn-error.log* 21 | 22 | 23 | docs/plex 24 | docs/plex-media-server 25 | docs/plex-tv -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Luke Hagar 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Website 2 | 3 | This website is built using [Docusaurus 2](https://docusaurus.io/), a modern static website generator. 4 | 5 | ### Installation 6 | 7 | ``` 8 | $ yarn 9 | ``` 10 | 11 | ### Local Development 12 | 13 | ``` 14 | $ yarn start 15 | ``` 16 | 17 | This command starts a local development server and opens up a browser window. Most changes are reflected live without having to restart the server. 18 | 19 | ### Build 20 | 21 | ``` 22 | $ yarn build 23 | ``` 24 | 25 | This command generates static content into the `build` directory and can be served using any static contents hosting service. 26 | 27 | ### Deployment 28 | 29 | Using SSH: 30 | 31 | ``` 32 | $ USE_SSH=true yarn deploy 33 | ``` 34 | 35 | Not using SSH: 36 | 37 | ``` 38 | $ GIT_USER= yarn deploy 39 | ``` 40 | 41 | If you are using GitHub pages for hosting, this command is a convenient way to build the website and push to the `gh-pages` branch. 42 | -------------------------------------------------------------------------------- /api.mustache: -------------------------------------------------------------------------------- 1 | --- 2 | id: {{{id}}} 3 | {{^api}} 4 | sidebar_label: Introduction 5 | {{/api}} 6 | {{#api}} 7 | sidebar_label: {{{title}}} 8 | {{/api}} 9 | {{^api}} 10 | sidebar_position: 0 11 | {{/api}} 12 | hide_title: true 13 | {{#api}} 14 | hide_table_of_contents: true 15 | {{/api}} 16 | {{#json}} 17 | api: {{{json}}} 18 | {{/json}} 19 | {{#api.method}} 20 | sidebar_class_name: "{{{api.method}}} api-method" 21 | {{/api.method}} 22 | {{#infoPath}} 23 | info_path: {{{infoPath}}} 24 | {{/infoPath}} 25 | --- 26 | 27 | {{{markdown}}} -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [require.resolve('@docusaurus/core/lib/babel/preset')], 3 | }; 4 | -------------------------------------------------------------------------------- /blog/Announcment.md: -------------------------------------------------------------------------------- 1 | Howdy everyone! 2 | 3 | My Name is Luke, 4 | 5 | I've been a big fan of Plex and the Plex Ecosystem for some time now. I started my journey with a simple MacBook with an external hardrive, and I've slowly migrated to a dedicated unraid server with ~90TB of space. 6 | 7 | I've been learning a lot in my professional career, and decided to try applying some of it to aid the Plex Developer Community in its pursuits. 8 | 9 | So this website is my first attempt at fully open source API documentation for Plex.tv and Plex Media Server. 10 | 11 | This [website](https://github.com/LukeHagar/plex-docs) is dynamically generated from an [open source OpenAPI Specification](https://github.com/LukeHagar/plex-api-spec), and is rebuilt via github actions and redeployed to vercel everytime that specification is updated. 12 | 13 | I have some [legacy format documentation](/docs/legacy) that was very kindly provided to me by the incredible Elan, CTO at Plex. This documentation is what I am currently working on converting to the OpenAPI specification format. 14 | 15 | There is still many endpoints, parameters, examples, and schemas missing from the OpenAPI Spec and I invite anyone in the community to contribute anything they can or want towards the documentation or the site. 16 | 17 | I hope you find this site useful, and I wish everyone a easier and more pleasing time developing with Plex. 18 | 19 | Cheers :) 20 | 21 | Luke Hagar 22 | [Website](https://lukehagar.com/) 23 | [LinkedIn](https://www.linkedin.com/in/lukehagar/) 24 | [GitHub](https://github.com/LukeHagar) 25 | -------------------------------------------------------------------------------- /blog/Plex API Resources.md: -------------------------------------------------------------------------------- 1 | This is just a collection of existing API Documentation that I am slowly adding to the specification: 2 | 3 | https://github.com/Arcanemagus/plex-api/wiki/Plex-Web-API-Overview 4 | https://github.com/Arcanemagus/plex-api/wiki 5 | https://github.com/jc21/plex-api/blob/master/docs/Filter.md 6 | https://www.plexopedia.com/plex-media-server/api/ 7 | https://www.plexopedia.com/plex-media-server/api/filter/ -------------------------------------------------------------------------------- /docs/legacy/plex/Activities.md: -------------------------------------------------------------------------------- 1 | ## Activities [/activities] 2 | 3 | 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. 4 | 5 | Activities are associated with HTTP replies via a special `X-Plex-Activity` header which contains the UUID of the activity. 6 | 7 | Activities are optional cancellable. If cancellable, they may be cancelled via the `DELETE` endpoint. Other details: 8 | 9 | - They can contain a `progress` (from 0 to 100) marking the percent completion of the activity. 10 | - They must contain an `type` which is used by clients to distinguish the specific activity. 11 | - They may contain a `Context` object with attributes which associate the activity with various specific entities (items, libraries, etc.) 12 | - The may contain a `Response` object which attributes which represent the result of the asynchronous operation. 13 | 14 | ### Get all activities [GET /activities] 15 | 16 | + Response 200 (application/xml) 17 | ```xml 18 | 19 | 20 | 21 | 22 | 23 | 24 | ``` 25 | ### Cancel a running activity [DELETE /activities/{activity}] 26 | 27 | + Parameters 28 | + activity: `d6199ba1-fb5e-4cae-bf17-1a5369c1cf1e` - The UUID of the activity to cancel. 29 | 30 | + Response 200 -------------------------------------------------------------------------------- /docs/legacy/plex/AutoUpdates.md: -------------------------------------------------------------------------------- 1 | ## Auto-Updates [/updater] 2 | 3 | This describes the API for searching and applying updates to the Plex Media Server. 4 | Updates to the status can be observed via the Event API. 5 | 6 | ### Querying status of updates [GET /updater/status] 7 | 8 | - Response 200 (application/xml;charset=utf-8) 9 | 10 | - Body 11 | 12 | ```xml 13 | 14 | 15 | 16 | ``` 17 | 18 | ### Checking for updates [PUT /updater/check] 19 | 20 | - Parameters 21 | 22 | - download: `0` (bool, optional) - Indicate that you want to start download any updates found. 23 | 24 | - Response 200 25 | 26 | ### Applying updates [PUT /updater/apply{?tonight/skip}] 27 | 28 | - Parameters 29 | - 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. 30 | - skip: `0` (bool, optional) - Indicate that the latest version should be marked as skipped. The entry for this version will have the `state` set to `skipped`. 31 | 32 | Note that these two parameters are effectively mutually exclusive. The `tonight` parameter takes precedence and `skip` will be ignored if `tonight` is also passed. 33 | 34 | - Response 200 35 | If the update process started correctly 36 | 37 | - Body 38 | 39 | - Response 500 40 | If the update process failed to start 41 | - Body 42 | -------------------------------------------------------------------------------- /docs/legacy/plex/Butler.md: -------------------------------------------------------------------------------- 1 | ## Group Butler [/butler] 2 | 3 | ### Starting all Butler tasks [POST /butler] 4 | 5 | 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: 6 | 7 | 1. Any tasks not scheduled to run on the current day will be skipped. 8 | 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. 9 | 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. 10 | 4. If we are outside the configured window, the task will start immediately. 11 | 12 | + Response 200 (no data) 13 | 14 | ### Stopping all Butler tasks [DELETE /butler] 15 | 16 | This endpoint will stop all currently running tasks and remove any scheduled tasks from the queue. 17 | 18 | + Response 200 (no data) 19 | 20 | ### Starting a single Butler task [POST /butler/{taskName}/] 21 | 22 | This endpoint will attempt to start a specific Butler task by name. 23 | 24 | This is the current list of tasks that can be used with this endpoint: 25 | 26 | + Parameters 27 | + taskName: `BackupDatabase` - the name of the task to be started. 28 | + Members 29 | + BackupDatabase 30 | + BuildGracenoteCollections 31 | + CheckForUpdates 32 | + CleanOldBundles 33 | + CleanOldCacheFiles 34 | + DeepMediaAnalysis 35 | + GenerateAutoTags 36 | + GenerateChapterThumbs 37 | + GenerateMediaIndexFiles 38 | + OptimizeDatabase 39 | + RefreshLibraries 40 | + RefreshLocalMedia 41 | + RefreshPeriodicMetadata 42 | + UpgradeMediaAnalysis 43 | 44 | + Response 200 (if the task was started. 202 if the task was already running.) 45 | 46 | ### Stopping a single Butler task [DELETE /butler/{taskName}/] 47 | 48 | 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. 49 | 50 | + Parameters 51 | + taskName: `BackupDatabase` - the name of the task to be started. 52 | 53 | + Response 200 (if the task was stopped. 404 if the task was not running.) 54 | -------------------------------------------------------------------------------- /docs/legacy/plex/Events.md: -------------------------------------------------------------------------------- 1 | ## Events 2 | 3 | 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. 4 | 5 | Two protocols for receiving the events are available: EventSource (also known as SSE), and WebSocket. 6 | 7 | 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: 8 | 9 | - `filters=-log`: All event types except logs (the default). 10 | - `filters=foo,bar`: Only the foo and bar event types. 11 | - `filters=`: All events types. 12 | - `filters=-foo,bar`: All event types except foo and bar. 13 | 14 | ### Connect to WebSocket [GET /:/websocket/notifications{?filters}] 15 | 16 | + Parameters 17 | + 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. 18 | 19 | + Response 200 (application/octet-stream) 20 | 21 | ### Connect to EventSource [GET /:/eventsource/notifications{?filters}] 22 | 23 | + Parameters 24 | + filters: `log` - Same as above. 25 | 26 | + Response 200 (text/event-stream) 27 | 28 | -------------------------------------------------------------------------------- /docs/legacy/plex/Library/All.md: -------------------------------------------------------------------------------- 1 | ## All [/library/sections/{sectionId}/all{?type,filters}] 2 | 3 | This resource represents the set of items matching the provided filter parameters. 4 | 5 | 6 | 7 | ### Get the filtered items [GET] 8 | Description for GET method (action) placeholder. 9 | 10 | + Parameters 11 | + sectionId: 1 (number, required) - Section identifier 12 | + type: 1 (number, optional) - Item type 13 | + filters (string, optional) - This fake parameter stands in for the various filter parameters 14 | 15 | + Request title=Zoolander (text/xml) 16 | 17 | + Response 200 (text/xml;charset=utf-8) 18 | 19 | + body 20 | ```xml 21 | 22 | 23 | 37 | 38 | ``` 39 | ### 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}] 40 | 41 | N.B. `field` in a parameter, represents any valid field for an item. 42 | 43 | - **Parameters, extra documentation** 44 | - artist.title.value 45 | - When used with track, both artist.title.value and album.title.value need to be specified 46 | - title.value usage 47 | - Summary 48 | - Tracks always rename and never merge 49 | - Albums and Artists 50 | - if single item and item without title does not exist, it is renamed. 51 | - if single item and item with title does exist they are merged. 52 | - if multiple they are always merged. 53 | - Tracks 54 | - Works as expected will update the track's title 55 | - Single track: `/library/sections/{id}/all?type=10&id=42&title.value=NewName` 56 | - Multiple tracks: `/library/sections/{id}/all?type=10&id=42,43,44&title.value=NewName` 57 | - All tracks: `/library/sections/{id}/all?type=10&title.value=NewName` 58 | - Albums 59 | - Functionality changes depending on the existence of an album with the same title 60 | - Album exists 61 | - Single album: `/library/sections/{id}/all?type=9&id=42&title.value=Album 2` 62 | - Album with id 42 is merged into album titled "Album 2" 63 | - Multiple/All albums: `/library/sections/{id}/all?type=9&title.value=Moo Album` 64 | - All albums are merged into the existing album titled "Moo Album" 65 | - Album does not exist 66 | - Single album: `/library/sections/{id}/all?type=9&id=42&title.value=NewAlbumTitle` 67 | - Album with id 42 has title modified to "NewAlbumTitle" 68 | - Multiple/All albums: `/library/sections/{id}/all?type=9&title.value=NewAlbumTitle` 69 | - All albums are merged into a new album with title="NewAlbumTitle" 70 | - Artists 71 | - Functionaly changes depending on the existence of an artist with the same title. 72 | - Artist exists 73 | - Single artist: `/library/sections/{id}/all?type=8&id=42&title.value=Artist 2` 74 | - Artist with id 42 is merged into existing artist titled "Artist 2" 75 | - Multiple/All artists: `/library/sections/{id}/all?type=8&title.value=Artist 3` 76 | - All artists are merged into the existing artist titled "Artist 3" 77 | - Artist does not exist 78 | - Single artist: `/library/sections/{id}/all?type=8&id=42&title.value=NewArtistTitle` 79 | - Artist with id 42 has title modified to "NewArtistTitle" 80 | - Multiple/All artists: `/library/sections/{id}/all?type=8&title.value=NewArtistTitle` 81 | - All artists are merged into a new artist with title="NewArtistTitle" 82 | 83 | - **Notes** 84 | - Technically square brackets are not allowed in an URI except the Internet Protocol Literal Address 85 | - 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. 86 | - Escaped square brackets are allowed, but don't render well 87 | 88 | - **Todo** 89 | - Check if `tagtype[].tag.tag-` syntax is currently correct 90 | 91 | 92 | - **Parameters not representable in Api Blueprint** 93 | - **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) 94 | - **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. 95 | - **tagtype[].tag.tag-** (string, optional) - Remove comma separated tags from the set of items 96 | - **tagtype[].tag** (string, optional) - Remove all taggings of this type (e.g. genre) from the set of items 97 | 98 | + Parameters 99 | + sectionId: 1 (number, required) - Section identifier 100 | + type: 1 (number, required) - Item type 101 | + filters (string, optional) - This fake parameter stands in for the various filter parameters. 102 | + field%2Evalue (string, optional) - Updates `field` across the filtered set of items. 103 | + field%2Elocked: 1 (number, optional) - Updates the locked state of `field` across the set. Valid values: 0 or 1. 104 | + title%2Evalue (string, optional) - This field is treated specially by albums or artists and may be used for implicit reparenting. 105 | + artist%2Etitle%2Evalue (string, optional) - Reparents set of Tracks or Albums - used with album.title.* in the case of tracks 106 | + artist%2Etitle%2Eid (string, optional) - Reparents set of Tracks or Albums - used with album.title.* in the case of tracks 107 | + album%2Etitle%2Evalue (string, optional) - Reparents set of Tracks - Must be used in conjunction with artist.title.value or id 108 | + album%2Etitle%2Eid (string, optional) - Reparents set of Tracks - Must be used in conjunction with artist.title.value or id 109 | 110 | 111 | + Request Example put (text/xml) 112 | Description for request placeholder. 113 | + body 114 | 115 | + Response 200 (text/html) 116 | Description for response placeholder. 117 | + body 118 | 119 | + Response 400 (text/html) 120 | ```html 121 | Bad Request

400 Bad Request

122 | ``` 123 | -------------------------------------------------------------------------------- /docs/legacy/plex/Library/Auto Complete.md: -------------------------------------------------------------------------------- 1 | ## Autocomplete [/library/sections/{sectionId}/autocomplete{?type,field%2Equery,filters}] 2 | 3 | The field to autocomplete on is specified by the {field}.query parameter. 4 | For example `genre.query` or `title.query`. 5 | 6 | Returns a set of items from the filtered items whose {field} starts with {field}.query. 7 | - Todo: 8 | - As implemented the endpoint does not seem to be reflecting the tag type in the element at the moment 9 | - Find all supported filters for autocomplete (We may have missing joins for some filters) 10 | 11 | + Parameters 12 | + sectionId: 1 (number, required) - Section identifier 13 | + type: 1 (number, required) - Item type 14 | + field%2Equery (string, required) - "field" stands in for any field, the value is a partial string for matching 15 | + filters (string, optional) - This fake parameter stands in for the various filter parameters 16 | 17 | ### Retrieve matching tags or items [GET] 18 | 19 | + Request With title.query=a (text/xml) 20 | 21 | + Response 200 (text/xml;charset=utf-8) 22 | Example returning items 23 | 24 | + Body 25 | ```xml 26 | 27 | 28 | 42 | 54 | 55 | ``` 56 | + Request With genre.query=a (text/xml) 57 | 58 | + Response 200 (text/xml;charset=utf-8) 59 | Example returning tags 60 | 61 | + Headers 62 | 63 | Accept: text/xml 64 | 65 | + Body 66 | ```xml 67 | 68 | 69 | 70 | 71 | 72 | 73 | ``` -------------------------------------------------------------------------------- /docs/legacy/plex/Library/Common.md: -------------------------------------------------------------------------------- 1 | ## Common [/library/sections/{sectionId}/common{?type,filters}] 2 | 3 | Represents a "Common" item. It contains only the common 4 | attributes of the items selected by the provided filter 5 | 6 | + Parameters 7 | + sectionId: 1 (number, required) - Section identifier 8 | + type: 1 (number, required) - Item type 9 | + filters (string, optional) - This fake parameter stands in for the various filter parameters 10 | 11 | ### Retrieve the common item [GET] 12 | 13 | + Request No common items in filter set (text/xml) 14 | 15 | + Response 200 (text/xml;charset=utf-8) 16 | 17 | + Body 18 | ```xml 19 | 20 | 21 | 22 | 23 | 24 | ``` 25 | + Request All filtered items are common (text/xml) 26 | 27 | + Response 200 (text/xml;charset=utf-8) 28 | 29 | + Body 30 | ```xml 31 | 32 | 34 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | ``` 50 | + Response 400 (text/html) 51 | In response to missing the type parameter. 52 | 53 | + Body 54 | ```html 55 | Bad Request

400 Bad Request

56 | ``` 57 | + Response 404 (text/html) 58 | In response to a non-existant sectionId. 59 | 60 | + Body 61 | ```html 62 | Not Found

404 Not Found

63 | ``` -------------------------------------------------------------------------------- /docs/legacy/plex/Library/Hashes.md: -------------------------------------------------------------------------------- 1 | ## Hashes [/library/hashes{?url,type}] 2 | 3 | This resource returns hash values for local files. 4 | 5 | 6 | 7 | ### Get the hash values [GET] 8 | 9 | + Parameters 10 | + url (string, required) - This is the path to the local file, must be prefixed by `file://` 11 | + type: 1 (number, required) - Item type 12 | 13 | + Request url=file://C:\Image.png&type=13 (text/xml) 14 | 15 | + Response 200 (text/xml;charset=utf-8) 16 | 17 | + body 18 | ```xml 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | ``` -------------------------------------------------------------------------------- /docs/legacy/plex/Library/Hubs.md: -------------------------------------------------------------------------------- 1 | ## Group Hubs 2 | 3 | Hubs are a structured two-dimensional container for media, generally represented by multiple horizontal rows. Hubs have the following attributes: 4 | 5 | - `key`: The URL for the full list of items for the hub, used to page in more data, when available. 6 | - `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?] 7 | - `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. 8 | - `hubIdentifier`: A unique identifier for the hub, used to distinguish it from all other hubs in the group. 9 | - `size`: The number of items returned with the hub. 10 | - `title`: The localized title of the hub. 11 | - `more`: (0/1) Whether or not there are more items beyond those returned. If so, the `key` can be used to obtain them. 12 | 13 | When requesting hubs, the following parameters are generally accepted. Note that other common library parameters may be used as well, e.g. `excludeFields`: 14 | 15 | - `count`: The number of items to return with each hub. 16 | - `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) 17 | 18 | ### Get global hubs [GET /hubs] 19 | 20 | + Response 200 21 | 22 | ### Get library specific hubs [GET /hubs/sections/{section}] 23 | 24 | + Response 200 -------------------------------------------------------------------------------- /docs/legacy/plex/Library/Ingest.md: -------------------------------------------------------------------------------- 1 | ## Group Ingest 2 | 3 | ### Ingest a transient item [POST /library/file{?url,computeHashes}] 4 | 5 | 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. 6 | 7 | Note that any of the parameters passed to the metadata details endpoint (e.g. `includeExtras=1`) work here. 8 | 9 | + Parameters 10 | + url: `file:///storage%2Femulated%2F0%2FArcher-S01E01.mkv` - The file of the file to ingest. 11 | + virtualFilePath: `/Avatar.mkv` - A virtual path to use when the url is opaque. 12 | + computeHashes: `1` (boolean, optional) - Whether or not to compute Plex and OpenSubtitle hashes for the file. Defaults to 0. 13 | + ingestNonMatches: `1` (boolean, optional) - Whether or not non matching media should be stored. Defaults to 0. 14 | 15 | + Response 200 (application/xml) 16 | ```xml 17 | 18 | 20 | ``` -------------------------------------------------------------------------------- /docs/legacy/plex/Library/Introduction.md: -------------------------------------------------------------------------------- 1 | ## The Media Hierarchy 2 | 3 | Plex uses a consistent media hierarchy across all media types, from photos to movies to TV shows. 4 | 5 | **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. 6 | 7 | **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. 8 | 9 | **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. 10 | 11 | **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). 12 | 13 | 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. 14 | 15 | 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". 16 | 17 | 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. 18 | 19 | ## Metadata and Media Attributes 20 | 21 | 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: 22 | 23 | - `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). 24 | - `ratingKey`: This is an opaque string which is used to pass back to timeline, scrobble, and rating endpoints, to uniquely identify the item. 25 | - `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. 26 | - `title`: The title (e.g. "300" or "The Simpsons"). 27 | - `titleSort`: (optional) This is the string used for sorting the item. It's usually the title with any leading articles removed (e.g. "Simpsons"). 28 | - `originalTitle`: (optional) When present, used to indicate an item's original title, e.g. a movie's foreign title. 29 | - `year`: (optional) The year associated with the item's release (e.g. release year for a movie). 30 | - `index`: (optional) This represents the episode number for episodes, season number for seasons, or track number for audio tracks. 31 | - `absoluteIndex` (optional): When present, contains the disc number for a track on multi-disc albums. 32 | - `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. 33 | - `duration`: (Optional) The duration for the item, in units of milliseconds. 34 | - `summary`: (optional) Extended textual information about the item (e.g. movie plot, artist biography, album review). 35 | - `tagline`: (optional) Pithy one-liner about the item (usually only seen for movies). 36 | - `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. 37 | - `art`: (optional) The URL for the background artwork for the item. 38 | - `banner`: (optional) The URL for a banner graphic for the item. 39 | - `hero`: (optional) The URL for a hero image for the item. 40 | - `theme`: (optional) The URL for theme music for the item (usually only for TV shows). 41 | - `composite`: (optional) When present, the URL for a composite image for descendent items (e.g. photo albums). 42 | - `studio`: (optional) The studio or label which produced an item (e.g. movie studio for movies, record label for albums). 43 | - `contentRating` (optional): If known, the content rating (e.g. MPAA) for an item. 44 | - `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. 45 | - `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`. 46 | - `audienceRating` (optional): Some rating systems separate reviewer ratings from audience ratings. Expressed as a floating point number from 0 to 10. 47 | - `audienceRatingImage`: (optional) A URI representing the image to be shown with the audience rating (e.g. `rottentomatoes://image.rating.spilled`). 48 | - `userRating`: (optional) When the user has rated an item, this contains the user rating (floating point number from 0 to 10). 49 | - `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. 50 | - `viewCount`: (optional) When a users has completed watched or listened to an item, this attribute contains the number of consumptions. 51 | - `lastViewedAt`: (optional) When a user has watched or listened to an item, this contains a timestamp (epoch seconds) for that last consumption time. 52 | - `addedAt`: (optional) In units of seconds since the epoch, returns the time at which the item was added to the library. 53 | - `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). 54 | - `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). 55 | - `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. 56 | - `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. 57 | - `skipParent`: (optional) When present on an episode or track item, indicates parent should be skipped in favor of grandparent (show). 58 | - `leafCount`: For shows and seasons, contains the number of total episodes. 59 | - `viewedLeafCount`: For shows and seasons, contains the number of viewed episodes. 60 | 61 | ### Ancestor Attributes 62 | 63 | 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`. 64 | 65 | ## Common Request Parameters 66 | 67 | 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. 68 | 69 | - `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`. 70 | - `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`). 71 | 72 | -------------------------------------------------------------------------------- /docs/legacy/plex/Library/Matches.md: -------------------------------------------------------------------------------- 1 | ### Get library matches [GET /library/matches{?type,includeFullMetadata,includeAncestorMetadata,includeAlternateMetadataSources}] 2 | 3 | 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. 4 | 5 | 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. 6 | 7 | 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). 8 | 9 | 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). 10 | 11 | #### Movies 12 | 13 | The following hints are allowed: 14 | 15 | - `guid`: allowed for various URI schemes, to be defined. 16 | - `title`: required if `path` is not specified. 17 | - `year`: optional. 18 | - `path`: the full path to the movie file, used for "cloud-scanning" an item. 19 | 20 | #### Shows 21 | 22 | The following hints are allowed: 23 | 24 | - `guid`: for URI schemes to be defined. 25 | - `title`: required if `guid` is not passed. 26 | - `year`: optional. 27 | 28 | #### Episodes 29 | 30 | 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: 31 | 32 | - `grandparentTitle`: the title of the show. Required if `path` isn't passed. 33 | - `grandparentYear`: the year of the show. 34 | - `parentIndex`: the season. 35 | - `index`: the episode. 36 | - `originallyAvailableAt`: in the format `YYYY-MM-DD`. 37 | - `path`: the full path to the episode file, can be provided in lieu of all other hints. 38 | 39 | #### Artists 40 | 41 | The following hints are allowed: 42 | 43 | - `guid`: for URI schemes to be defined. 44 | - `title`: the artist name. 45 | 46 | #### Albums 47 | 48 | The following hints are allowed: 49 | 50 | - `guid`: for URI schemes to be defined. 51 | - `parentTitle`: the artist name. 52 | - `title`: the album name. 53 | - `year`: the album year. 54 | 55 | #### Tracks 56 | 57 | The following hints are required: 58 | 59 | - `guid`: for URI schemes to be defined. 60 | - `grandparentTitle`: the artist name. 61 | - `parentTitle`: the album name. 62 | - `title`: the track name. 63 | - `index`: the track index. 64 | - `parentIndex`: the disc index for multi-disc albums. 65 | - `path`: the full path to the track, can be provided in lieu of all other hints. 66 | 67 | #### Podcasts 68 | 69 | The following hints is required: 70 | 71 | - `url`: the URL for the podcast feed. 72 | 73 | #### Podcast Episodes 74 | 75 | The following hints are required: 76 | 77 | - `url`: the URL for the podcast feed. 78 | - `originallyAvailableAt`: The air date for the episode. 79 | 80 | + Parameters 81 | 82 | + type: `1` (integer) - The metadata type we're attempting to match. 83 | + 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. 84 | + Default: `0` 85 | + includeAncestorMetadata: `1` (boolean, optional) - Whether or not to include metadata for the item's ancestor (e.g. show and season data for an episode). 86 | + Default: `0` 87 | + includeAlternateMetadataSources: `1` (boolean, optional) - Whether or not to return all sources for each metadata field, which results in a different structure being passed back. 88 | + Default: `0` 89 | 90 | + Response 200 (application/xml) 91 | 92 | ```xml 93 | 94 | 96 | ``` -------------------------------------------------------------------------------- /docs/legacy/plex/Library/Media Queries.md: -------------------------------------------------------------------------------- 1 | # Media Queries 2 | 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. 3 | 4 | ### Fields 5 | Queries reference fields, which can be of a few types: 6 | 7 | * *integer*: numbers 8 | * *boolean*: true/false 9 | * *tag*: integers representing tag IDs. 10 | * *string*: strings 11 | * *date*: epoch seconds 12 | * *language*: string in ISO639-2b format. 13 | 14 | These fields are detailed in `Field` elements in the section description endpoint (e.g. `/library/sections/X?includeDetails=1`). 15 | 16 | ### Operators 17 | 18 | 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. 19 | 20 | Operators are defined per type: 21 | 22 | * *integer*: `=` (equals), `!=` (not equals), `>>=` (greater than), `<<=` (less than), `<=` (less than or equals), `>=` (greater than or equals) 23 | * *boolean*: `=0` (false) and `=1` (true) 24 | * *tag*: `=` (is) and `!=` (is not) 25 | * *string*: `=` (contains), `!=` (does not contain), `==` (equals), `!==` (does not equal), `<=` (begins with), `>=` (ends with) 26 | * *date*: `=` (equals), `!=` (not equals), `>>=` (after), `<<=` (before) 27 | * *language*: `=` (equals), `!=` (not equals) 28 | 29 | ### Relative Values and Units 30 | 31 | 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). 32 | 33 | In addition, the following unit suffixes can be used on date values: 34 | 35 | * *m*: minutes 36 | * *h*: hours 37 | * *d*: days 38 | * *w*: weeks 39 | * *mon*: months 40 | * *y*: years 41 | 42 | For example, `>>=-3y` means “within the last 3 years”. 43 | 44 | ### Field Scoping 45 | 46 | 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. 47 | 48 | * A `type` parameter must be included to specify the result type. 49 | * Any non-qualified field is defaulted to refer to the result type. 50 | * 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. 51 | * 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”. 52 | 53 | ### Sorting 54 | 55 | 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. 56 | 57 | For example, `sort=title,index` means “sort first by title ascending, then by index”. Sort features are: 58 | 59 | * *desc*: indicates a descending sort. 60 | * *nullsLast*: indicates that null values are sorted last. 61 | 62 | Sort features may be mixed and matched, e.g. `sort=title,index:desc`. 63 | 64 | ### Grouping 65 | 66 | 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 don’t want multiple tracks with the same name (e.g. same track on different albums) showing up. 67 | 68 | ### Limits 69 | 70 | The `limit` parameter is used to limit the number of results returned. Because it’s 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 can’t select tracks from a limit of 10 _albums_. 71 | 72 | ### Boolean Operators 73 | 74 | 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”. 75 | 76 | 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)`. 77 | 78 | ### Complex Expressions 79 | 80 | There’s 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: 81 | 82 | * *push=1* and *pop=1*: These are the equivalent of opening and closing parenthesis. 83 | * *or=1*: These is an explicit OR operator. 84 | 85 | 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. 86 | 87 | Happy query building! 88 | -------------------------------------------------------------------------------- /docs/legacy/plex/Library/Play Queues.md: -------------------------------------------------------------------------------- 1 | ## Play queues [/playQueues] 2 | 3 | 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. 4 | 5 | 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.  6 | 7 | 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. 8 | 9 | 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. 10 | 11 | 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. 12 | 13 | ### Create a play queue [POST /playQueues{?uri,playlistID,type,key,shuffle,repeat,continuous,limit,extrasPrefixCount,recursive,ondeck}] 14 | 15 | 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`. 16 | 17 | The media container itself has a few special attributes: 18 | 19 | - `playQueueID`: The ID of the play queue, which is used in subsequent requests. 20 | - `playQueueSelectedItemID`: The queue item ID of the currently selected item. 21 | - `playQueueSelectedItemOffset`: The offset of the selected item in the play queue, from the beginning of the queue. 22 | - `playQueueSelectedMetadataItemID`: The metadata item ID of the currently selected item (matches `ratingKey` attribute in metadata item). 23 | - `playQueueShuffled`: Whether or not the queue is shuffled. 24 | - `playQueueSourceURI`: The original URI used to create the play queue. 25 | - `playQueueTotalCount`: The total number of items in the play queue. 26 | - `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. 27 | - `playQueueLastAddedItemID`: Defines where the "Up Next" region starts 28 | 29 | + Parameters 30 | + uri: library://... (string) - the content URI for what we're playing. 31 | + playlistID: 123 (string, optional) - the ID of the playlist we're playing. 32 | + type: audio (string) - must be either `audio`, `video`, `photo`. 33 | + key: 1234 (string, optional) - the key of the first item to play, defaults to the first in the play queue. 34 | + shuffle: 0 (boolean, optional) - whether to shuffle the playlist, defaults to 0. 35 | + repeat: 0 (boolean, optional) - if the PQ is bigger than the window, fill any empty space with wraparound items, defaults to 0. 36 | + continuous: 0 (boolean, optional) - whether to create a continuous play queue (e.g. from an episode), defaults to 0. 37 | + 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. 38 | + 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. 39 | + onDeck: 0 (boolean, optional) - only applies to queues of type show or seasons, 40 | whether to return a queue that is started on the On Deck episode if one exists. 41 | Otherwise begins the play queue on the beginning of the show or season. 42 | 43 | + Response 200 (application/xml) 44 | ```xml 45 | 46 | 47 | 48 | ``` 49 | ### Retrieve a play queue [GET /playQueues/{playQueue}{?own,center,window,includeBefore,includeAfter}] 50 | 51 | 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. 52 | 53 | + Parameters 54 | + playQueue: 1023 (string) - the ID of the play queue. 55 | + own: 0 (boolean, optional) - if the server should transfer ownership to the requesting client (used in remote control scenarios). 56 | + center: 12345 (string, optional) - the play queue item ID for the center of the window - this doesn't change the current selected item. 57 | + window: 20 (optional) - how many items on each side of the center of the window 58 | + includeBefore: 1 (boolean, optional) - whether to include the items before the center (if 0, center is not included either), defaults to 1. 59 | + includeAfter: 1 (boolean, optional) - whether to include the items after the center (if 0, center is not included either), defaults to 1. 60 | 61 | + Response 200 (application/xml) 62 | ```xml 63 | 64 | 65 | ... 66 | 67 | ``` 68 | ### Add a generator or playlist to a play queue [PUT /playQueues/{playQueue}{?uri,playlistID,next}] 69 | 70 | 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. 71 | 72 | + Parameters 73 | + playQueue: 101 (string) - The ID of the play queue. 74 | + uri: library:// (string) The content URI for what we're adding to the queue. 75 | + playlistID: 100 (string, optional) - The ID of the playlist to add to the playQueue. 76 | + next: 0 (boolean, optional) - play this item next (defaults to 0 - queueing at the end of manually queued items). 77 | 78 | + Response 200 (application/xml) 79 | ```xml 80 | 81 | 82 | ... 83 | 84 | ``` 85 | ### Delete an item from a play queue [DELETE /playQueues/{playQueue}/items/{playQueueItemID}] 86 | 87 | Deletes an item in a play queue. Increments the version of the play queue. Returns the modified play queue. 88 | 89 | + Parameters 90 | + playQueue: 101 (string) - The ID of the play queue. 91 | + playQueueItemID: 123123 (string) - The play queue item ID to delete. 92 | 93 | + Response 200 (application/xml) 94 | ```xml 95 | 96 | 97 | ... 98 | 99 | ``` 100 | ### Clear a play queue [DELETE /playQueues/{playQueue}/items] 101 | 102 | Deletes all items in the play queue, and increases the version of the play queue. 103 | 104 | + Parameters 105 | + playQueue: 101 (string) - The ID of the play queue. 106 | 107 | + Response 200 (application/xml) 108 | ```xml 109 | 110 | 111 | ``` 112 | ### Move an item in a play queue [PUT /playQueues/{playQueue}/items/{playQueueItemID}/move{?after}] 113 | 114 | Moves an item in a play queue, and increases the version of the play queue. Returns the modified play queue. 115 | 116 | + Parameters 117 | + playQueue: 101 (string) - The ID of the play queue. 118 | + playQueueItemID: 123123 (string) - The play queue item ID to delete. 119 | + after: 123 (string, optional) - the play queue item ID to insert the new item after. If not present, moves to the beginning. 120 | 121 | + Response 200 (application/xml) 122 | ```xml 123 | 124 | 125 | ... 126 | 127 | ``` 128 | ### Shuffle a play queue [PUT /playQueues/{playQueue}/shuffle] 129 | 130 | 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. 131 | 132 | + Parameters 133 | + playQueue: 101 (string) - The ID of the play queue. 134 | 135 | + Response 200 (application/xml) 136 | ```xml 137 | 138 | 139 | ... 140 | 141 | ``` 142 | ### Unshuffle a play queue [PUT /playQueues/{playQueue}/unshuffle] 143 | 144 | 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. 145 | 146 | + Parameters 147 | + playQueue: 101 (string) - The ID of the play queue. 148 | 149 | + Response 200 (application/xml) 150 | ```xml 151 | 152 | 153 | ... 154 | 155 | ``` -------------------------------------------------------------------------------- /docs/legacy/plex/Library/Playlists.md: -------------------------------------------------------------------------------- 1 | ## Playlists [/playlists] 2 | 3 | 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. 4 | 5 | Retrieving a playlist, or its items, will trigger a refresh of its metadata. This may cause the duration and number of items to change. 6 | 7 | ### Retrieve Playlists [GET /playlists/all{?playlistType,smart}] 8 | 9 | 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: 10 | 11 | - `smart` (0/1) - whether or not the playlist is smart. 12 | - `duration` (milliseconds) - the total duration of the playlist. 13 | - `leafCount` - the number of items in the playlist. 14 | - `composite` - a composite image for the playlist. 15 | - `key` - leads to a list of items in the playlist. 16 | - `playlistType` - the type of the playlist (audio/video/photo). 17 | - `specialPlaylistType` - if this is a special playlist, this returns its type (e.g. favorites). 18 | - `readOnly` - if we return this as true then this playlist cannot be altered or deleted directly by the client. 19 | 20 | + Parameters 21 | + playlistType: `audio` (string, optional) - limit to a type of playlist (`audio`, `video` or `photo`) 22 | + smart: `0` (boolean, optional) - optional, type of playlists to return (default is all). 23 | 24 | + Response 200 (application/xml) 25 | ```xml 26 | 27 | 28 | 29 | 30 | ``` 31 | ### Create a Playlist [POST /playlists?{title,type,smart,uri,playQueueID}] 32 | 33 | Create a new playlist. By default the playlist is blank. To create a playlist along with a first item, pass: 34 | 35 | - `uri` - The content URI for what we're playing (e.g. `library://...`). 36 | - `playQueueID` - To create a playlist from an existing play queue. 37 | 38 | 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. 39 | 40 | + Parameters 41 | + title: `My Playlist` (string) - name of the playlist 42 | + type: `audio` (string) - type of the playlist (`video`/`audio`/`photo`) 43 | + smart: `0` (0/1) - whether the playlist is smart or not. 44 | + uri: `library://..` (string, optional) - the content URI for the playlist. 45 | + playQueueID: `123` (integer, optional) - the play queue to copy to a playlist. 46 | 47 | + Response 200 (application/xml) 48 | ```xml 49 | 50 | 51 | 52 | ``` 53 | ### Retrieve Playlist [GET /playlists/{playlistID}] 54 | 55 | Gets detailed metadata for a playlist. A playlist for many purposes (rating, editing metadata, tagging), can be treated like a regular metadata item: 56 | 57 | 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. 58 | 59 | + Parameters 60 | + playlistID: `123` (integer) - the ID of the playlist. 61 | 62 | + Response 200 (application/xml) 63 | ```xml 64 | 65 | 66 | 67 | ``` 68 | ### Retrieve Playlist Contents [GET /playlists/{playlistID}/items{?type}] 69 | 70 | 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. 71 | 72 | + Parameters 73 | + playlistID: `123` (integer) - the ID of the playlist. 74 | + type: `8` (integer) - the metadata type of the item to return. 75 | 76 | + Response 200 (application/xml) 77 | ```xml 78 | 79 | 81 | ``` 82 | ### Delete a Playlist [DELETE /playlists/{playlistID}] 83 | 84 | Deletes a playlist. 85 | 86 | + Parameters 87 | + playlistID: `123` (integer) - the ID of the playlist. 88 | 89 | + Response 200 90 | 91 | ### Editing a Playlist [PUT /library/metadata/{playlistID}] 92 | 93 | Use the standard metadata item editing endpoint (tag a playlist! edit the title!). Just listing it here to illustrate the potential. 94 | 95 | + Parameters 96 | + playlistID: `123` (integer) - the ID of the playlist. 97 | 98 | + Response 200 99 | 100 | ### Editing a Playlist (PMS >= 1.9.1) [PUT /playlists/{playlistID}] 101 | 102 | From PMS version 1.9.1 clients can also edit playlist metadata using this endpoint as they would via `PUT /library/metadata/{playlistID}` 103 | 104 | + Parameters 105 | + playlistID: `123` (integer) - the ID of the playlist. 106 | 107 | + Response 200 108 | 109 | ### Clearing a playlist [DELETE /playlists/{playlistID}/items] 110 | 111 | Clears a playlist, only works with dumb playlists. Returns the playlist. 112 | 113 | + Parameters 114 | + playlistID: `123` (integer) - the ID of the playlist. 115 | 116 | + Response 200 117 | ```xml 118 | 119 | 120 | 121 | ``` 122 | ### Adding to a Playlist [PUT /playlists/{playlistID}/items?{uri,playQueueID}] 123 | 124 | 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. 125 | 126 | + Parameters 127 | + uri: `library://..` (string, optional) - the content URI for the playlist. 128 | + playQueueID: `123` (integer, optional) - the play queue to add to a playlist. 129 | 130 | + Response 200 (application/xml) 131 | ```xml 132 | 133 | 134 | 135 | ``` 136 | ### Moving items in a playlist [PUT /playlists/{playlistID}/items/{playlistItemID}/move{?after}] 137 | 138 | Moves an item in a playlist. Only works with dumb playlists. 139 | 140 | + Parameters 141 | + playlistID: `123` (integer) - the playlist ID. 142 | + playlistItemID: `1` (integer) - the playlist item ID to move. 143 | + after: `2` (integer, optional) - the playlist item ID to insert the new item after. 144 | 145 | + Response 200 146 | 147 | ### Delete a Generator [DELETE /playlists/{playlistID}/items/{playlistItemID}] 148 | 149 | Deletes an item from a playlist. Only works with dumb playlists. 150 | 151 | + Parameters 152 | + playlistID: `123` (integer) - the playlist ID. 153 | + playlistItemID: `1` (integer) - the playlist item ID to move. 154 | 155 | + Response 200 156 | 157 | ### Upload Playlists [POST /playlists/upload{?path,force}] 158 | 159 | 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. 160 | 161 | + Parameters 162 | + 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. 163 | + 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. 164 | 165 | + Response 200 166 | -------------------------------------------------------------------------------- /docs/legacy/plex/Library/Search.md: -------------------------------------------------------------------------------- 1 | ## Group Search 2 | 3 | ### Perform a search [GET /hubs/search{?query,sectionId,limit}] 4 | 5 | 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). 6 | 7 | In the response's items, the following extra attributes are returned to further describe or disambiguate the result: 8 | 9 | - `reason`: The reason for the result, if not because of a direct search term match; can be either: 10 | - `section`: There are multiple identical results from different sections. 11 | - `originalTitle`: There was a search term match from the original title field (sometimes those can be very different or in a foreign language). 12 | - ``: 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` 13 | - `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"). 14 | - `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. 15 | 16 | This request is intended to be very fast, and called as the user types. 17 | 18 | + Parameters 19 | + query: `dog` - The query term. 20 | + sectionId: `1` (number, optional) - This gives context to the search, and can result in re-ordering of search result hubs. 21 | + limit: `5` (number, optional) - The number of items to return per hub. 22 | + Default: `3` 23 | 24 | + Response 200 (application/xml) 25 | ```xml 26 | 27 | 28 | 29 | 30 | 31 | 33 | 34 | ``` 35 | ### Perform a search tailored to voice input [GET /hubs/search/voice{?query,type,limit}] 36 | 37 | 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. 38 | 39 | Results, as well as their containing per-type hubs, contain a `distance` attribute which can be used to judge result quality. 40 | 41 | + Parameters 42 | + query: `dead+poop` - The query term. 43 | + type: `8` (number, optional) - The type of thing to limit the search to. 44 | + limit: `5` (number, optional) - The number of items to return per hub. 45 | + Default: `3` 46 | 47 | + Response 200 (application/xml) 48 | ```xml 49 | 50 | 51 | 54 | 55 | 56 | 57 | 58 | ``` -------------------------------------------------------------------------------- /docs/legacy/plex/Library/Sections.md: -------------------------------------------------------------------------------- 1 | ## Library Sections [/library/sections] 2 | 3 | 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. 4 | 5 | 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). 6 | 7 | ### Get library section details [GET /library/sections/{section}{?includeDetails}] 8 | 9 | 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: 10 | 11 | - 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: 12 | - 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. 13 | - Secondary: These are marked with `secondary="1"` and were used by old clients to provide nested menus allowing for primative (but structured) navigation. 14 | - 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. 15 | - 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: 16 | - `key`: This provides the root endpoint returning the actual media list for the type. 17 | - `type`: This is the metadata type for the type (if a standard Plex type). 18 | - `title`: The title for for the content of this type (e.g. "Movies"). 19 | - 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. 20 | - `filter`: This represents the filter name used for the filter, which can be used to construct complex media queries with. 21 | - `filterType`: This is either `string`, `integer`, or `boolean`, and describes the type of values used for the filter. 22 | - `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. 23 | - `title`: The title for the filter. 24 | - Each `Sort` object contains a description of the sort field. 25 | - `defaultDirection`: Can be either `asc` or `desc`, and specifies the default direction for the sort field (e.g. titles default to alphabetically ascending). 26 | - `descKey` and `key`: Contains the parameters passed to the `sort=...` media query for each direction of the sort. 27 | - `title`: The title of the field. 28 | 29 | + Parameters 30 | + section: `1000` (string) - The section identifier. 31 | + 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. 32 | + Default: `0` 33 | 34 | + Response 200 (application/xml) 35 | ```xml 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | ``` -------------------------------------------------------------------------------- /docs/legacy/plex/Log.md: -------------------------------------------------------------------------------- 1 | ## Group Log (/log) 2 | 3 | ### Logging a single-line message to the Plex Media Server log (GET /log) 4 | 5 | This endpoint will write a single-line log message, including a level and source to the main Plex Media Server log. 6 | 7 | + Parameters 8 | + level: An integer log level to write to the PMS log with. 9 | + Members 10 | + 0: Error 11 | + 1: Warning 12 | + 2: Info 13 | + 3: Debug 14 | + 4: Verbose 15 | + message: The text of the message to write to the log. 16 | + source: A string indicating the source of the message. 17 | 18 | + Response 200 19 | 20 | ### Logging a multi-line message to the Plex Media Server log (POST /log) 21 | 22 | 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. 23 | 24 | + Response 200 25 | 26 | ### Enabling Papertrail (GET /log/networked) 27 | 28 | This endpoint will enable all Plex Media Serverlogs to be sent to the Papertrail networked logging site for a period of time. 29 | 30 | + Parameters 31 | + minutes: The number of minutes logging should be sent to Papertrail 32 | 33 | + Response 200 (if papertrail could be enabled. 403 if the user was not signed in) 34 | -------------------------------------------------------------------------------- /docs/legacy/plex/Media Feedback.md: -------------------------------------------------------------------------------- 1 | ## Media Feedback [/:/] 2 | 3 | This group of endpoints correspond to client feedback around an item. 4 | 5 | ### Report media timeline [GET /:/timeline{?hasMDE,key,ratingKey,state,playQueueItemID,time,duration,continuing,updated,offline,timeToFirstFrame,timeStalled,bandwidth,bufferedTime,bufferedSize,location}] 6 | 7 | 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). 8 | 9 | In order to identify the client, the following headers are used: 10 | 11 | - `X-Plex-Client-Identifier`: Required, unique per client. 12 | - `X-Plex-Session-Identifier`: Optional, unique per client playback session. 13 | 14 | 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. 15 | 16 | Additional attributes include: 17 | 18 | - `terminationCode` - Optional, a code describing why the session was terminated by the server. See `decision` endpoint for more details. 19 | - `terminationText` - Optional, a user friendly and localized text describing why the session was terminated by the server. 20 | 21 | Additional child elements include: 22 | - `Bandwidths` - Optional, an element containing one or more `Bandwidth` elements. 23 | - `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. 24 | 25 | + Parameters 26 | + key: `/foo` - The details key for the item. 27 | + ratingKey: `xyz` - The rating key attribute for the item. 28 | + state: `playing` - The current state of the media. 29 | + Members 30 | + `stopped` 31 | + `buffering` 32 | + `playing` 33 | + `paused` 34 | + playQueueItemID: `123` (string, optional) - If playing media from a play queue, the play queue's ID. 35 | + time: `0` (milliseconds) - The current time offset of playback. 36 | + duration: `10000` (milliseconds) - The total duration of the item. 37 | + continuing: `1` - When state is `stopped`, a flag indicating whether or not the client is going to continue playing anothe item. 38 | + 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. 39 | + offline: `1` - Also used by sync clients, used to indicate that a timeline is being synced from being offline, as opposed to being "live". 40 | + timeToFirstFrame: `1000` - Optional, time in seconds till first frame is displayed. Sent only on the first playing timeline request. 41 | + timeStalled: `1000` (number, optional) - Time in seconds spent buffering since last request. 42 | + bandwidth: `100` (number, optional) - Bandwidth in kbps as estimated by the client. 43 | + bufferedTime: `100` (number, optional) - Amount of time in seconds buffered by client. Omit if computed by `bufferedSize` below. 44 | + bufferedSize: `1024` (number, optional) - Size in kilobytes of data buffered by client. Omit if computed by `bufferedTime` above 45 | 46 | + Response 200 (text/xml;charset=utf-8) 47 | 48 | + Body 49 | 50 | Normal response: 51 | ```xml 52 | 53 | ``` 54 | 55 | Admin terminated session: 56 | ```xml 57 | 58 | ``` 59 | Bandwidth changes included: 60 | ```xml 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | ``` 78 | 79 | ### Marking items watched [GET /:/scrobble{?key,uri,identifier}] 80 | 81 | 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). 82 | 83 | + Parameters 84 | + key: `/foo` - The rating key for the item. 85 | + uri: `library://...` - The media URI specifier. Either `key` or `uri` must be used, but not both. 86 | + identifier: `com.something` - The identifier for the item's provider. Allows multiplexing between multiple providers at a single endpoint. 87 | 88 | + Response 200 89 | 90 | 91 | ### Marking items unwatched [GET /:/unscrobble{?key,uri,identifier}] 92 | 93 | + Parameters 94 | + key: `/foo` - The rating key for the item. 95 | + uri: `library://...` - The media URI specifier. Either `key` or `uri` must be used, but not both. 96 | + identifier: `com.something` - The identifier for the item's provider. Allows multiplexing between multiple providers at a single endpoint. 97 | 98 | + Response 200 99 | 100 | 101 | ### Rating items [GET /:/rate{?key,identifier,rating}] 102 | 103 | + Parameters 104 | + key: `/foo` - The rating key for the item. 105 | + identifier: `com.something` - The identifier for the item's provider. 106 | + rating: `2.4` - The rating for the item. 107 | 108 | + Response 200 109 | 110 | -------------------------------------------------------------------------------- /docs/legacy/plex/Media Providers/Client Guide.md: -------------------------------------------------------------------------------- 1 | ### Client Guide to Media Providers 2 | 3 | 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: 4 | 5 | ##### Consume `/media/providers` instead of `/library/sections` 6 | 7 | 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). 8 | 9 | ##### Gate management functionality on the `manage` feature 10 | 11 | Server libraries allow management (e.g. media deletion). The correct way to gate this functionality is via the manage feature. 12 | 13 | ##### Make sure key construction is correct for things like genre lists 14 | 15 | 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. 16 | 17 | ##### Don't call `/library/sections/X/filters|sorts` 18 | 19 | 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. 20 | 21 | ##### Respect the Type keys in `/library/sections/x` 22 | 23 | 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. 24 | 25 | ##### Look for the skipChildren/skipParent attributes for shows 26 | 27 | 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. 28 | 29 | -------------------------------------------------------------------------------- /docs/legacy/plex/Media Providers/DVR.md: -------------------------------------------------------------------------------- 1 | ## DVRs [/livetv/dvrs] 2 | 3 | Once you have configured devices and picked a lineup, you can create a DVR. 4 | 5 | ### Create a DVR [POST /livetv/dvrs{?lineup,device,language}] 6 | 7 | + Parameters 8 | + lineup: `lineup://tv.plex.providers.epg.onconnect/USA-HI51418-DEFAULT` - The EPG lineup. 9 | + device: `device[]=device://tv.plex.grabbers.hdhomerun/1053C0CA` (array) - The device. 10 | + language: `eng` - The language. 11 | 12 | + Response 200 13 | 14 | ### Get DVRs [GET /livetv/dvrs] 15 | 16 | + Response 200 (application/xml) 17 | 18 | " 19 | 20 | 21 | 22 | 23 | 24 | 25 | " 26 | 27 | ### Get a single DVR [GET /livetv/dvrs/{dvr}] 28 | 29 | + Parameters 30 | + dvr: `1` - The ID of the DVR. 31 | 32 | + Response 200 (application/xml) 33 | 34 | " 35 | 36 | " 37 | 38 | ### Delete a DVR [DELETE /livetv/dvrs/{dvr}] 39 | 40 | + Parameters 41 | + dvr: `1` - The ID of the DVR. 42 | 43 | + Response 200 (application/xml) 44 | 45 | ### Add a device to an existing DVR [PUT /livetv/{dvr}/devices/{device}] 46 | 47 | + Parameters 48 | + dvr: `1` - The ID of the DVR. 49 | + device: `1223` - The ID of the device to add. 50 | 51 | + Response 200 (application/xml) 52 | 53 | " 54 | 55 | " 56 | 57 | ### Remove a device from an existing DVR [DELETE /livetv/dvrs/{dvr}/devices/{device}"] 58 | 59 | + Parameters 60 | + dvr: `1` - The ID of the DVR. 61 | + device: `1223` - The ID of the device to add. 62 | 63 | + Response 200 (application/xml) 64 | 65 | " 66 | 67 | " 68 | 69 | ### Set DVR preferences [PUT /livetv/dvrs/{dvr}/prefs{?name}] 70 | 71 | + Parameters 72 | + dvr: `1` - The ID of the DVR. 73 | + name: `value` - The preference names and values. 74 | 75 | + Response 200 (application/xml) 76 | 77 | " 78 | 79 | 80 | 81 | 82 | 83 | " 84 | 85 | ### Tell a DVR to reload program guide [POST /livetv/dvrs/{dvr}/reloadGuide] 86 | 87 | + Parameters 88 | + dvr: `1` - The ID of the DVR. 89 | 90 | + Response 200 91 | 92 | + Headers 93 | 94 | X-Plex-Activity: d391ddb0-b29b-4e20-a57a-46b15b4e4318 95 | 96 | ### Tell a DVR to stop reloading program guide [DELETE /livetv/dvrs/{dvr}/reloadGuide] 97 | 98 | + Parameters 99 | + dvr: `1` - The ID of the DVR. 100 | 101 | + Response 200 -------------------------------------------------------------------------------- /docs/legacy/plex/Media Providers/Devices.md: -------------------------------------------------------------------------------- 1 | ## Group Device Endpoints 2 | 3 | ### Get device details [GET /media/grabbers/devices/{device}] 4 | 5 | + Parameters 6 | + device: `42` - the ID of the device. 7 | 8 | + Response 200 (application/xml) 9 | 10 | " 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | " 19 | 20 | ### Enable or disable a device [PUT /media/grabbers/devices/{device}{?enabled}] 21 | 22 | + Parameters 23 | + device: `42` - The ID of the device. 24 | + enabled: `1` - Whether to enable the device. 25 | 26 | + Response 200 (application/xml) 27 | 28 | "" 29 | 30 | ### Set device preferences [PUT /media/grabbers/devices/{device}/prefs{?name}] 31 | 32 | + Parameters 33 | + device: `1` - The ID of the DVR. 34 | + name: `value` - The preference names and values. 35 | 36 | + Response 200 (application/xml) 37 | 38 | ### Get a device's channels [GET /media/grabbers/devices/{device}/channels] 39 | 40 | + Parameters 41 | + device: `42` - the ID of the device. 42 | 43 | + Response 200 (application/xml) 44 | 45 | " 46 | 47 | 48 | " 49 | 50 | ### Set a device's channel mapping [PUT /media/grabbers/devices/{device}/channelmap{?channelMapping,channelsEnabled}] 51 | 52 | + Parameters 53 | + device: `42` - the ID of the device. 54 | + channelMapping: `channelMapping[46.3]=002&channelMapping[48.9]=004` - the mapping of changes, passed as a map of device channel to lineup VCN. 55 | + 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. 56 | + channelsEnabled: `46.1,44.1,45.1` - the channels which are enabled. 57 | 58 | + Response 200 (application/xml) 59 | 60 | "" 61 | 62 | ### Tell a device to scan for channels [POST /media/grabbers/devices/{device}/scan{?source}] 63 | 64 | + Parameters 65 | + device: `42` - the ID of the device. 66 | + source: `Cable` - a valid source for the scan. 67 | 68 | + Response 200 (application/xml) 69 | 70 | + Headers 71 | 72 | X-Plex-Activity: 7e650c37-1639-4f60-9866-09b8eaf35a7a 73 | 74 | + Body 75 | 76 | "" 77 | 78 | ### Tell a device to stop scanning for channels [DELETE /media/grabbers/devices/{device}/scan] 79 | 80 | + Parameters 81 | + device: `42` - the ID of the device. 82 | 83 | + Response 200 (application/xml) 84 | 85 | "" 86 | -------------------------------------------------------------------------------- /docs/legacy/plex/Media Providers/EPG.md: -------------------------------------------------------------------------------- 1 | ## EPG Endpoints [/livetv/epg] 2 | 3 | These endpoint detail the EPG portion of the interface. 4 | 5 | ### Get all countries [GET /livetv/epg/countries] 6 | 7 | This endpoint returns a list of countries which EPG data is available for. There are three flavors, as specfied by the `flavor` attribute: 8 | 9 | - `0`: The country is divided into regions, and following the key will lead to a list of regions. 10 | - `1`: The county is divided by postal codes, and an example code is returned in `example`. 11 | - `2`: The country has a single postal code, returned in `example`. 12 | 13 | + Response 200 (application/xml) 14 | 15 | " 16 | 17 | 18 | 19 | " 20 | 21 | ### Get all languages [GET /livetv/epg/languages] 22 | 23 | Returns a list of all possible languages for EPG data. 24 | 25 | + Response 200 (application/xml) 26 | 27 | " 28 | 29 | 30 | 31 | " 32 | 33 | ### Get regions for a country [GET /livetv/epg/countries/{country}/{epgIdentifier}/regions] 34 | 35 | + Parameters 36 | + country: `usa` - The ISO country code. 37 | + epgIdentifier: `tv.plex.providers.epg.eyeq` ~ The EPG identifier. 38 | 39 | + Response 200 (application/xml) 40 | 41 | " 42 | 43 | 44 | " 45 | 46 | ### Get lineups for a region [GET /livetv/epg/countries/{country}/{epgIdentifier}/regions/{region}/lineups{?country,region}] 47 | 48 | Returns the list of lineups for a given country, EPG provider, and region. There are four types of lineups returned in `lineupType`: 49 | 50 | - `0`: Over the air 51 | - `1`: Cable 52 | - `2`: Satellite 53 | - `3`: IPTV 54 | - `4`: Virtual 55 | 56 | + Parameters 57 | + country: `bhr` - The ISO country code. 58 | + epgIdentifier: `tv.plex.providers.epg.eyeq` ~ The EPG identifier. 59 | + region: `134535` 60 | 61 | + Response 200 (application/xml) 62 | 63 | " 64 | 65 | " 66 | 67 | ### Get lineups for a country via postal code [GET /livetv/epg/countries/{country}/{epgIdentifier}/lineups{?postalCode}] 68 | 69 | Returns a list of lineups for a given country, EPG provider and postal code. 70 | 71 | + Parameters 72 | + postalCode: `AI-2640` - The postal code. 73 | + country: `aia` - The ISO country code. 74 | + epgIdentifier: `tv.plex.providers.epg.onconnect` ~ The EPG identifier. 75 | 76 | + Response 200 (application/xml) 77 | 78 | " 79 | 80 | 81 | 82 | " 83 | 84 | ### Get channels for a lineup [GET /livetv/epg/channels{?lineup}] 85 | 86 | + Parameters 87 | + lineup: `lineup://tv.plex.providers.epg.onconnect/CAN-OTAV4R2G5` - The URI describing the lineup. 88 | 89 | + Response 200 (application/xml) 90 | 91 | " 92 | 93 | 94 | " 95 | 96 | ### Compute the best channel map, given device and lineup [GET /livetv/epg/channelmap{?device,lineup}] 97 | 98 | + Parameters 99 | + device: `device://tv.plex.grabbers.hdhomerun/1053C0CA` - The device. 100 | + lineup: `lineup://tv.plex.providers.epg.onconnect/USA-HI51418-DEFAULT` - The lineup. 101 | 102 | + Response 200 (application/xml) 103 | 104 | " 105 | 106 | " 107 | 108 | ### Compute the best lineup, given lineup group and device [GET /livetv/epg/lineup{?device,lineupGroup}] 109 | 110 | + Parameters 111 | + device: `device://tv.plex.grabbers.hdhomerun/1053C0CA` - The device. 112 | + lineupGroup: `lineup-group://onconnect/usa/96708` - The lineup group. 113 | 114 | + Response 200 (application/xml) 115 | 116 | + Headers 117 | 118 | X-Plex-Activity: 7e650c37-1639-4f60-9866-09b8eaf35a7a 119 | 120 | + Body 121 | 122 | "" 123 | 124 | -------------------------------------------------------------------------------- /docs/legacy/plex/Media Providers/Live.md: -------------------------------------------------------------------------------- 1 | ## Live TV 2 | 3 | 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. 4 | 5 | ### Start a live TV session [POST /livetv/dvrs/{dvr}/channels/{channel}/tune] 6 | 7 | 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: 8 | 9 | - The `MediaGrabOperation`'s video contains a `Media` element which reflects the actual media characteristics of the live stream. 10 | - 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). 11 | - An `AlsoAiring` object which contains N `Video` elements, reflecting the items currently aring on different channels. 12 | 13 | The client is required to pass either `X-Plex-Session-Identifier` or `X-Plex-Client-Identifier` header to this request. 14 | 15 | 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. 16 | 17 | + Parameters 18 | + dvr: `324` - The ID of the DVR. 19 | + channel: `008` (string) - The channel identifier. 20 | 21 | + Response 200 (application/xml) 22 | 23 | " 24 | 25 | 26 | 34 | 35 | 36 | 39 | 42 | 43 | 44 | 47 | 50 | 53 | 56 | 57 | 58 | " 59 | 60 | ### Cancel an existing grab [DELETE /media/grabbers/operations/{uuid}] 61 | 62 | 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. 63 | 64 | + Parameters 65 | + uuid: `1742b85795` - The UUID if the grab. 66 | 67 | + Response 200 (application/xml) 68 | 69 | ## Live sessions [/livetv/sessions] 70 | 71 | ### Get all sessions [GET /livetv/sessions] 72 | 73 | + Response 200 (application/xml) 74 | 75 | " 76 | 77 | 85 | " 86 | 87 | ### Get particular session [GET /livetv/sessions/{session}] 88 | 89 | + Response 200 90 | -------------------------------------------------------------------------------- /docs/legacy/plex/Media Providers/Media Grabbers.md: -------------------------------------------------------------------------------- 1 | ## Media Grabber Endpoints [/media/grabbers] 2 | 3 | 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. 4 | 5 | ### Get available grabbers [GET /media/grabbers{?protocol}] 6 | 7 | + Parameters 8 | + protocol: `livetv` (optional) - Only return grabbers providing this protocol. 9 | 10 | + Response 200 (application/xml) 11 | 12 | " 13 | 14 | 15 | 16 | " 17 | 18 | ### Get all devices [GET /media/grabbers/devices] 19 | 20 | + Response 200 (application/xml) 21 | 22 | " 23 | 24 | 25 | " 26 | 27 | ### Tell grabbers to discover devices [POST /media/grabbers/devices/discover] 28 | 29 | + Response 200 (application/xml) 30 | 31 | " 32 | 33 | 34 | " 35 | 36 | ### Add a device [POST /media/grabbers/devices{?uri}] 37 | 38 | This endpoint adds a device to an existing grabber. The device is identified, and added to the correct grabber. 39 | 40 | + Parameters 41 | + uri: `http://10.0.0.5` - the URI of the device. 42 | 43 | + Response 200 (application/xml) 44 | 45 | " 46 | 47 | " 48 | 49 | ### Remove a device [DELETE /media/grabbers/devices/{device}] 50 | 51 | + Parameters 52 | + device: `42` - the ID of the device. 53 | 54 | + Response 200 (application/xml) 55 | 56 | "" 57 | 58 | + Response 404 59 | 60 | ## Device Endpoints [/media/grabbers/devices] 61 | 62 | 63 | ### Get device details [GET /media/grabbers/devices/{device}] 64 | 65 | + Parameters 66 | + device: `42` - the ID of the device. 67 | 68 | + Response 200 (application/xml) 69 | 70 | " 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | " 79 | 80 | ### Enable or disable a device [PUT /media/grabbers/devices/{device}{?enabled}] 81 | 82 | + Parameters 83 | + device: `42` - the ID of the device. 84 | 85 | + Response 200 (application/xml) 86 | 87 | "" 88 | 89 | ### Get a device's channels [GET /media/grabbers/devices/{device}/channels] 90 | 91 | + Parameters 92 | + device: `42` - the ID of the device. 93 | 94 | + Response 200 (application/xml) 95 | 96 | " 97 | 98 | 99 | " 100 | 101 | ### Get metadata item for tuned channel [GET /media/grabbers/devices/{device}/channels/{channel}] 102 | 103 | This endpoint can be used with the transcoder start and decision endpoints. 104 | 105 | + Parameters 106 | + device: `42` - the ID of the device. 107 | + channel: `2.1` - the channel ID to retrieve 108 | 109 | + Response 200 (application/xml) 110 | 111 | " 112 | 113 | 121 | " 122 | 123 | + Response 404: Channel not currently tuned 124 | 125 | ### Tune a channel on a device [POST /media/grabbers/devices/{device}/channels/{channel}/tune] 126 | 127 | + Parameters 128 | + device: `42` - the ID of the device. 129 | + channel: `2.1` - the channel ID to tune 130 | 131 | + Response 200 (application/xml) 132 | Identical to the GET above 133 | + Response 500: Tuning failed 134 | 135 | ### Set a device's channel mapping [PUT /media/grabbers/devices/{device}/channelmap{?channelMapping,channelsEnabled}] 136 | 137 | + Parameters 138 | + device: `42` - the ID of the device. 139 | + channelMapping: `channelMapping[46.3]=002&channelMapping[48.9]=004` - the mapping of changes, passed as a map. 140 | + channelsEnabled: `46.1,44.1,45.1` - the channels which are enabled. 141 | 142 | + Response 200 (application/xml) 143 | 144 | "" 145 | 146 | ### Tell a device to scan for channels [POST /media/grabbers/devices/{device}/scan{?source}] 147 | 148 | + Parameters 149 | + device: `42` - the ID of the device. 150 | + source: `Cable` - a valid source for the scan. 151 | 152 | + Response 200 (application/xml) 153 | 154 | + Headers 155 | 156 | X-Plex-Activity: 7e650c37-1639-4f60-9866-09b8eaf35a7a 157 | 158 | + Body 159 | 160 | "" 161 | 162 | ### Tell a device to stop scanning for channels [DELETE /media/grabbers/devices/{device}/scan] 163 | 164 | + Parameters 165 | + device: `42` - the ID of the device. 166 | 167 | + Response 200 (application/xml) 168 | 169 | "" 170 | -------------------------------------------------------------------------------- /docs/legacy/plex/Media Providers/Media Providers.md: -------------------------------------------------------------------------------- 1 | ## Media Providers [/media/providers] 2 | 3 | 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. 4 | 5 | The top level of a provider definition returns some basic information: 6 | 7 | - `identifier`: A unique identifier for the provider, e.g. `tv.plex.podcast`. 8 | - `title`: The title of the provider. 9 | - `types`: This attribute contains a comma-separated list of the media types exposed by the provider (e.g. `video, audio`). 10 | - `protocols`: A comma-separated list of default protocols for the provider, which can be: 11 | - `stream`: The provider allows streaming media directly from the provider (e.g. for Vimeo). 12 | - `download`: The provider allows downloading media for offline storage, sync, etc. (e.g. Podcasts). 13 | - `livetv`: The provider provides live content which is only available on a schedule basis. 14 | 15 | ```xml 16 | 17 | ``` 18 | 19 | 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. 20 | 21 | - **search**: This feature implies that it supports the server `/hubs/search` endpoint. 22 | 23 | - **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). 24 | 25 | - **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: 26 | 27 | - `hubKey`: This implies it supports a discovery endpoint with hubs. 28 | - `key`: This implies it supports a content catalog. 29 | 30 | Each content feature can contain one or both of these keys, depending on the structure. More details on the various combinations are provided below. 31 | 32 | - **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). 33 | 34 | - **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. 35 | 36 | - **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. 37 | 38 | - **rate**: This feature implies the provider supports the server `/:/rate` endpoint which allows rating content. 39 | 40 | - **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`. 41 | 42 | - **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. 43 | 44 | - **subscribe**: This provider allows media subscriptions to be created, and subsequently used to "record" into a library. 45 | 46 | - **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. 47 | 48 | - **continuewatching**: This feature allows the provider to supply an endpoint that will return a hub for merging into a global Continue Watching hub. 49 | 50 | Here's a full example provider definition: 51 | 52 | ```xml 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | ``` 67 | 68 | The `content` directories describe the navigation structure for the provider. Each directory contains either a `hubKey`, a `key`, or both attributes. 69 | 70 | - `hubKey`: Implies that following the key leads to a container of hubs. 71 | - `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.). 72 | - `icon`: Optional, specifies the icon used for a content directory. 73 | 74 | Let's see how the `content` feature specifically can be used to define a wide variety of different media providers. 75 | 76 | #### Home discovery and browsable libraries (e.g. EPG) 77 | 78 | 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. 79 | 80 | 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. 81 | 82 | #### Home discovery and libraries with browse and discovery (e.g. "classic") 83 | 84 | 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. 85 | 86 | #### Minimal provider 87 | 88 | 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. 89 | 90 | #### Deeper Hierarchies 91 | 92 | 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. 93 | 94 | #### Extensions to regular libraries 95 | 96 | This section examines extensions to plain libraries which content providers can use, and which clients need to be aware of. 97 | 98 | - **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. 99 | 100 | ```xml 101 | 102 | ``` 103 | 104 | - **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. 105 | 106 | ### Get all providers [GET /media/providers] 107 | 108 | 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. 109 | 110 | + Response 200 (application/xml) 111 | 112 | ```xml 113 | 114 | 115 | 116 | 117 | ``` 118 | 119 | ### Add a media provider [POST /media/providers{?url}] 120 | 121 | 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. 122 | 123 | + Parameters 124 | + url: `http://localhost:10000` - The URL of the media provider to add. 125 | 126 | + Response 200 127 | 128 | ### Refresh media providers [POST /media/providers/refresh] 129 | 130 | Refresh all known media providers. This is useful in case a provider has updated features, e.g. during local development. 131 | 132 | + Response 200 133 | 134 | ### Delete a media provider [DELETE /media/providers/{provider}] 135 | 136 | + Parameters 137 | + provider: `47` (number) - The ID of the media provider to delete. 138 | 139 | + Response 200 140 | -------------------------------------------------------------------------------- /docs/legacy/plex/Media Providers/Media Subscriptions.md: -------------------------------------------------------------------------------- 1 | ## Media Subscriptions [/media/subscriptions] 2 | 3 | ### Get the subscription template [GET /media/subscriptions/template{?type}] 4 | 5 | + Parameters 6 | + type: `2` - The type of the thing we're subscribing too (e.g. show, season). 7 | 8 | + Response 200 (application/xml) 9 | ```xml 10 | 11 | 19 | ``` 20 | 21 | ### Create a subscription [POST /media/subscriptions/{?targetLibrarySectionID,targetSectionLocationID,type,hints,prefs}] 22 | 23 | + Parameters 24 | + targetLibrarySectionID: `1` - The library section into which we'll grab the media. Not actually required when the subscription is to a playlist. 25 | + targetSectionLocationID: `3` (optional) - The section location into which to grab. 26 | + type: `2` - The type of the thing we're subscribing too (e.g. show, season). 27 | + 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. 28 | + prefs: `prefs[minVideoQuality]=720` (array) - Subscription preferences. 29 | + params: (array) - Subscription parameters. 30 | + `params[mediaProviderID]=1` Required for downloads to indicate which MP the subscription will download into 31 | + `params[source]=server://0123456789abcdef0123456789abcdef01234567/com.plexapp.plugins.library`: Required for downloads to indicate the source of the downloaded content. 32 | 33 | + Response 200 (application/xml) 34 | ```xml 35 | 36 | 37 | 38 | 44 | 45 | 53 | 54 | ``` 55 | ### Get all subscriptions [GET /media/subscriptions/{?includeGrabs}] 56 | 57 | + Parameters 58 | + includeGrabs: `1` (optional) - Whether or not to include all the scheduled grabs for each subcription. 59 | 60 | + Response 200 (application/xml) 61 | ```xml 62 | 63 | 64 | 66 | 67 | ``` 68 | ### Get a single subscription [GET /media/subscriptions/{subscription}{?includeGrabs}] 69 | 70 | + Parameters 71 | + subscription: `42` - The ID of the subscription. 72 | + includeGrabs: `1` (optional) - Whether or not to include all the scheduled grabs for each subcription. 73 | 74 | + Response 200 (application/xml) 75 | ```xml 76 | 77 | 78 | 80 | 81 | ``` 82 | ### Delete a subscription [DELETE /media/subscriptions/{subscription}] 83 | 84 | + Parameters 85 | + subscription: `42` - The ID of the subscription. 86 | 87 | + Response 200 88 | 89 | ### Edit a subscription [PUT /media/subscriptions/{subscription?prefs}] 90 | 91 | + Parameters 92 | + prefs: `prefs[minVideoQuality]=720` (array) - Subscription preferences. 93 | 94 | + Response 200 (application/xml) 95 | ```xml 96 | 97 | 98 | 100 | 101 | ``` 102 | ### Get all scheduled recordings [GET /media/subscriptions/scheduled] 103 | 104 | + Response 200 (application/xml) 105 | ```xml 106 | 107 | 108 | 114 | 115 | 116 | ``` 117 | ### Process all subscriptions [POST /media/subscriptions/process] 118 | 119 | + Response 200 120 | 121 | + Headers 122 | 123 | X-Plex-Activity: d391ddb0-b29b-4e20-a57a-46b15b4e4318 124 | -------------------------------------------------------------------------------- /docs/legacy/plex/Media Providers/Remote Media Grabbers.md: -------------------------------------------------------------------------------- 1 | ## Remote Media Grabbers 2 | 3 | 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. 4 | 5 | ```xml 6 | 7 | ``` 8 | 9 | ### Media Grabber Identification [GET /] 10 | 11 | Provides general information about the media grabber, including: 12 | 13 | - `identifier`: A unique string used to distinguish different media grabbers, usually specified in reverse domain format. 14 | - `title`: The friendly name of the media grabber. 15 | - `icon`: (optional) An icon representing the grabber. 16 | - `protocols`: The protocols supported by the grabber. This is used to match up media providers with media grabbers. 17 | 18 | + Response 200 (application/xml) 19 | 20 | 21 | 22 | 23 | 24 | ### Device Discovery [POST /devices/discover] 25 | 26 | 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. 27 | 28 | The response consists of a list of devices, with the following attributes: 29 | - `key`: The endpoint to request device details. This is the `devicekey` to be used in all other requests. 30 | - `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`). 31 | - `tuners` is the number of tuners the device has. 32 | - `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. 33 | - `protocol` is aways `livetv` for devices at the moment. 34 | - `title` represents a user-friendly title for the device. 35 | - `uri` (optional) represents the address of a network-accessible tuner. 36 | - `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. 37 | - `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. 38 | - `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`. 39 | 40 | - Devices can also provide device-specific preferences that can be set by the user. These are passed in `` elements as part of a Device description, with the following attributes: 41 | 42 | - `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. 43 | - `label`: A string label that will be displayed on the device settings in the Plex DVR Setup UI. 44 | - `summary`: (optional) A longer description of the setting that will be displayed below the preference on the Plex DVR Setup UI. 45 | - `type`: The data type for the preference. Possible values are `int`, `bool`, and `text`. 46 | - `value`: The current value for the preference. This will be one of the keys in the `enumValues` attribute. 47 | - `enumValues`: A pipe-separated list of options for the preference. Each option is a colon-separated entry with the form of `value:display-string`. 48 | 49 | + Response 200 (application/xml) 50 | ```xml 51 | 52 | 56 | 59 | 60 | 61 | ``` 62 | ### Device Probe [POST /devices/probe{?uri}] 63 | 64 | Probes a specific URI for a network device, and returns a device, if it exists at the given URI. 65 | 66 | + Parameters 67 | + uri: http://10.0.0.100:10000 (string) - URI for the device. Can be either HTTP or HTTPS. 68 | 69 | + Response 200 (application/xml) 70 | ```xml 71 | 72 | 73 | 74 | ``` 75 | ### Get identity and capabilities [GET /devices/{devicekey}] 76 | 77 | Returns the identity, capabilities, and current status of the devices and each of its tuners. 78 | 79 | - Tuner status can be one of the following: 80 | - `idle`: The device isn't doing anything. 81 | - `streaming`: The device is currently streaming media. 82 | - `scanning`: The device is scanning for channels. 83 | - `networksScanned`: The device has scanned for networks and is awaiting being scanned for channels, given a specific network. 84 | - `error`: The device is unhappy. 85 | 86 | - If the status is `streaming`, the following attributes should be included: 87 | - `signalStrength`: A signal strength metric normalized to a 0-100 scale. 88 | - `signalQuality`: A signal quality metric normalized to a 0-100 scale. 89 | - `symbolQuality`: (optional) A symbol quality metric normalized to a 0-100 scale. 90 | - `channelIdentifier`: The identifier for the channel currently being tuned. This should be the same format as the identifiers in the `/devices/{devicekey}/channels` endpoint. 91 | - `lock`: A 0 or 1 value denoting that the tuner has a signal lock. 92 | 93 | - If the status is `scanning`, the following attributes should be included: 94 | - `progress`: A percentage indicating how complete the scanning process is. 95 | - `channelsFound`: The number of channels found so far. 96 | 97 | + Parameters 98 | + devicekey: 12323213 (string, required) - key referring to tuner device, as originally reported in the `/devices/discover` endpoint. 99 | 100 | + Response 200 (application/xml) 101 | ```xml 102 | 103 | 107 | 108 | 109 | 110 | 111 | 112 | ``` 113 | ### Get a device's channels [GET /devices/{devicekey}/channels] 114 | 115 | Returns the current channels. This list is updated after a complete channel scan, and should not be assumed to persist beyond that. 116 | 117 | The response contains zero or more channels, with the following attributes: 118 | 119 | - `drm`: If known, whether or not a channel contains Digital Rights Management. When enabled, these channels are mostly unusable by the media server. 120 | - `channelIdentifier`: This is a unique identifier for the channel, represented by an URI. This can either be: 121 | - `id://xxx`: The channel identifier is a channel number (e.g. 12 or 46.3). 122 | - `tuple://x:y:z`: The channel identifier is a DVT tuple. 123 | - `name`: The name for the channel. This is the string that will be displayed for the channel on the client. 124 | - `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. 125 | - `number`: (optional) is a suggested channel number in a guide lineup as sent by TV provider 126 | - `type`: (optional) is either `tv` or `radio`. 127 | - `param`: (optional) denotes channel tuning parameters that have to be passed back to `/media` endpoint. 128 | - `signalStrength`: (optional) denotes the signal strength of the channel when it was scanned. 129 | - `signalQuality`: (optional) denotes the signal quality of the channel when it was scanned. 130 | 131 | + Parameters 132 | + devicekey: 12323213 (string, required) - key referring to tuner device, as originally reported in the `/devices/discover` endpoint. 133 | 134 | + Response 200 (application/xml) 135 | ```xml 136 | 137 | 139 | 140 | ``` 141 | ### Get channel scan providers [GET /devices/{devicekey}/scanners{?type}] 142 | 143 | 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. 144 | 145 | 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. 146 | 147 | + Parameters 148 | + devicekey: 12323213 (string, required) - key referring to tuner device, as originally reported in the `/devices/discover` endpoint. 149 | + 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) 150 | 151 | + Response 200 (application/xml) 152 | ```xml 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | ``` 167 | #### Scanners 168 | 169 | Defines a scanner that can be used to search for channels. They will have the following attributes: 170 | 171 | - `type`: One of the broadcast standard types: `atsc`, `cqam`, `dvb-s`, `iptv`, `virtual`, `dvb-t`, `dvb-c`, `isdbt` 172 | - `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. 173 | 174 | Each `` element will have one or more `` 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`. `` elements have the following attributes: 175 | 176 | - `id`: The ID of the setting to be displayed. This will be used internally by PMS. 177 | - `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. 178 | - `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. 179 | 180 | ### Get scanned networks [GET /devices/{devicekey}/networks] 181 | 182 | 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. 183 | 184 | + Parameters 185 | + devicekey: 12323213 (string, required) - key referring to tuner device, as originally reported in the `/devices/discover` endpoint. 186 | 187 | + Response 200 (application/xml) 188 | ```xml 189 | 190 | 191 | 192 | 193 | ``` 194 | ### Start a channel scan for network [POST /devices/{devicekey}/scan{?network,source,provider}] 195 | 196 | Starts a background channel scan. Updates are received via querying the device details endpoint (`/devices/x`). The response will have the following attributes: 197 | 198 | - `status`: The current status of the scanning operation. 199 | 200 | + Parameters 201 | + devicekey: 12323213 (string, required) - key referring to tuner device, as originally reported in the `/devices/discover` endpoint. 202 | + network: 10 (string, optional) - only valid if the device is in the `networksScanned` state, and specifies the network to scan. 203 | + source: 1 (integer, optional) - only valid when not performing a network scan. Specifies the type of scanner, as noted above. 204 | + provider: 1 (integer) - the key of the scanner to use when scanning. 205 | 206 | + Response 200 (application/xml) 207 | ```xml 208 | 209 | ``` 210 | ### Cancel channel scan [DELETE /devices/{devicekey}/scan] 211 | 212 | Cancels an ongoing background channel scan. 213 | 214 | + Parameters 215 | + devicekey: 12323213 (string, required) - key referring to tuner device, as originally reported in the `/devices/discover` endpoint. 216 | 217 | + Response 200 (application/xml) 218 | ```xml 219 | 220 | ``` 221 | ### Stream media from a tuner [GET /devices/{devicekey}/media/{channel}{?param}] 222 | 223 | + Parameters 224 | + devicekey: 12323213 (string, required) - key referring to tuner device, as originally reported in the `/devices/discover` endpoint. 225 | + channel: 5.1 (string, required) - the channel identifier passed back with each channel. 226 | + 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. 227 | 228 | + Response 200 (application/octet-stream) 229 | 230 | Media 231 | 232 | ### Provide preference values to the tuner [PUT /devices/{devicekey}/prefs] 233 | 234 | These preferences are originally provided by the device in the `/devices/discover` endpoint. 235 | 236 | + Parameters 237 | + devicekey: 12323213 (string, required) - key referring to tuner device, as originally reported in the `/devices/discover` endpoint. 238 | + Any number of key-value pairs corresponding to values set by the user for the preferences provided by the tuner. 239 | 240 | + Response 200 (no data) 241 | 242 | ### SSDP Discovery support 243 | 244 | 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. 245 | 246 | + Example SSDP output 247 | ```xml 248 | 249 | 250 | 1 251 | 0 252 | 253 | 254 | urn:plex-tv:device:Media:1 255 | Turing Hopper 3000 256 | Plex, Inc. 257 | https://plex.tv/ 258 | Turing Hopper 3000 Media Grabber 259 | Plex Media Grabber 260 | 1 261 | https://plex.tv 262 | uuid:42fde8e4-93b6-41e5-8a63-12d848655811 263 | 264 | 265 | http://10.0.0.5:8088 266 | urn:plex-tv:service:MediaGrabber:1 267 | urn:plex-tv:serviceId:MediaGrabber 268 | 269 | 270 | 271 | 272 | ``` 273 | + Parameters 274 | + UDN: (string) A UUID for the device. This should be unique across models of a device at minimum. 275 | + URLBase: (string) The base HTTP URL for the device from which all of the other endpoints are hosted. 276 | -------------------------------------------------------------------------------- /docs/legacy/plex/Security.md: -------------------------------------------------------------------------------- 1 | ## Security 2 | 3 | ### Get Transient Tokens [GET /security/token{?type,scope}] 4 | 5 | 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. 6 | 7 | + Parameters 8 | + type: `delegation` - This is the only supported `type` parameter. 9 | + scope: `all` - This is the only supported `scope` parameter. 10 | 11 | + Response 200 (application/xml) 12 | ```xml 13 | 14 | ``` 15 | ### Get Source Connection Information [GET /security/resources{?source}] 16 | 17 | 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. 18 | 19 | Note: requires Plex Media Server >= 1.15.4. 20 | 21 | + Parameters 22 | + source: `server://client-identifier` or `provider://provider-identifier` - The source identifier with an included prefix. 23 | 24 | + Response 200 (application/xml) 25 | ```xml 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | ``` -------------------------------------------------------------------------------- /docusaurus.config.js: -------------------------------------------------------------------------------- 1 | // @ts-check 2 | // Note: type annotations allow type checking and IDEs autocompletion 3 | 4 | const lightCodeTheme = require("prism-react-renderer/themes/github"); 5 | const darkCodeTheme = require("prism-react-renderer/themes/dracula"); 6 | 7 | /** @type {import('@docusaurus/types').Config} */ 8 | const config = { 9 | title: "API Documentation and SDKs for Plex", 10 | tagline: 11 | "Open and community sourced API documentation and SDKs for Plex with a kick!", 12 | favicon: "img/favicon.ico", 13 | scripts: [ 14 | { 15 | src: "https://events.plygrnd.org/js/script.js", 16 | async: true, 17 | defer: true, 18 | "data-domain": "plexapi.dev", 19 | }, 20 | ], 21 | // Set the production url of your site here 22 | url: "https://plexapi.dev", 23 | // Set the // pathname under which your site is served 24 | // For GitHub pages deployment, it is often '//' 25 | baseUrl: "/", 26 | 27 | // GitHub pages deployment config. 28 | // If you aren't using GitHub pages, you don't need these. 29 | organizationName: "lukehagar", // Usually your GitHub org/user name. 30 | projectName: "plex-docs", // Usually your repo name. 31 | 32 | onBrokenLinks: "throw", 33 | onBrokenMarkdownLinks: "warn", 34 | 35 | // Even if you don't use internalization, you can use this field to set useful 36 | // metadata like html lang. For example, if your site is Chinese, you may want 37 | // to replace "en" with "zh-Hans". 38 | i18n: { 39 | defaultLocale: "en", 40 | locales: ["en"], 41 | }, 42 | 43 | presets: [ 44 | [ 45 | "classic", 46 | /** @type {import('@docusaurus/preset-classic').Options} */ 47 | ({ 48 | docs: { 49 | editUrl: 50 | "https://github.com/LukeHagar/plex-api-spec/blob/main/plex-api-spec-dereferenced.yaml", 51 | sidebarPath: require.resolve("./sidebars.js"), 52 | docLayoutComponent: "@theme/DocPage", 53 | docItemComponent: "@theme/ApiItem", // Derived from docusaurus-theme-openapi-docs 54 | }, 55 | blog: { 56 | showReadingTime: true, 57 | // Please change this to your repo. 58 | // Remove this to remove the "edit this page" links. 59 | editUrl: "https://github.com/LukeHagar/plex-docs/tree/main", 60 | }, 61 | theme: { 62 | customCss: require.resolve("./src/css/custom.css"), 63 | }, 64 | }), 65 | ], 66 | ], 67 | 68 | themeConfig: 69 | /** @type {import('@docusaurus/preset-classic').ThemeConfig} */ 70 | ({ 71 | colorMode: { 72 | defaultMode: "dark", 73 | disableSwitch: false, 74 | respectPrefersColorScheme: false, 75 | }, 76 | // Replace with your project's social card 77 | image: "img/Open-Graph-Image.png", 78 | navbar: { 79 | title: "API Documentation and SDKs for Plex", 80 | logo: { 81 | alt: "My Site Logo", 82 | src: "img/favicon.ico", 83 | }, 84 | items: [ 85 | { to: "/docs/plex", label: "API", className: "indent" }, 86 | { to: "/docs/legacy", label: "Legacy", className: "indent" }, 87 | { to: "/sdk-docs", label: "SDKs", className: "indent" }, 88 | { to: "/blog", label: "Blog", className: "indent" }, 89 | ], 90 | }, 91 | footer: { 92 | style: "dark", 93 | links: [ 94 | { 95 | title: "Docs", 96 | items: [ 97 | { 98 | label: "API Documentation", 99 | to: "/docs/plex", 100 | }, 101 | { 102 | label: "SDK Documentation", 103 | to: "/sdk-docs", 104 | }, 105 | ], 106 | }, 107 | { 108 | title: "More", 109 | items: [ 110 | { 111 | label: "Blog", 112 | to: "/blog", 113 | }, 114 | ], 115 | }, 116 | ], 117 | }, 118 | prism: { 119 | theme: lightCodeTheme, 120 | darkTheme: darkCodeTheme, 121 | additionalLanguages: ["ruby", "csharp", "php", "java", "powershell"], 122 | }, 123 | languageTabs: [ 124 | { 125 | highlight: "bash", 126 | language: "curl", 127 | logoClass: "bash", 128 | }, 129 | { 130 | highlight: "python", 131 | language: "python", 132 | logoClass: "python", 133 | variant: "requests", 134 | }, 135 | { 136 | highlight: "go", 137 | language: "go", 138 | logoClass: "go", 139 | }, 140 | { 141 | highlight: "javascript", 142 | language: "nodejs", 143 | logoClass: "nodejs", 144 | variant: "axios", 145 | }, 146 | { 147 | highlight: "ruby", 148 | language: "ruby", 149 | logoClass: "ruby", 150 | }, 151 | { 152 | highlight: "csharp", 153 | language: "csharp", 154 | logoClass: "csharp", 155 | variant: "httpclient", 156 | }, 157 | { 158 | highlight: "php", 159 | language: "php", 160 | logoClass: "php", 161 | }, 162 | { 163 | highlight: "java", 164 | language: "java", 165 | logoClass: "java", 166 | variant: "unirest", 167 | }, 168 | { 169 | highlight: "powershell", 170 | language: "powershell", 171 | logoClass: "powershell", 172 | }, 173 | ], 174 | announcementBar: { 175 | id: "announcementBar_1", 176 | backgroundColor: "red", 177 | textColor: "white", 178 | content: 179 | "This is not an Official Plex.TV Resource and is not built or maintained by Plex. If you have any feedback on the Website or the API Specification please let me know!", 180 | }, 181 | metadata: [ 182 | { 183 | name: "keywords", 184 | content: 185 | "api documentation for plex, sdks for plex, sdk, ts, typescript, plexapi.dev", 186 | }, 187 | ], 188 | algolia: { 189 | // The application ID provided by Algolia 190 | appId: "B040KPNF7Z", 191 | 192 | // Public API key: it is safe to commit it 193 | apiKey: "6dd932b0ad77bf1b92efa0ff25023ffe", 194 | 195 | indexName: "plex-vercel", 196 | 197 | // Optional: path for search page that enabled by default (`false` to disable it) 198 | searchPagePath: "search", 199 | }, 200 | }), 201 | 202 | plugins: [ 203 | [ 204 | "docusaurus-plugin-openapi-docs", 205 | { 206 | id: "openapi", 207 | docsPluginId: "classic", 208 | config: { 209 | PlexTV: { 210 | specPath: "static/plex-tv-spec-dereferenced.yaml", // Path to designated spec file 211 | outputDir: "docs/plex-tv", // Output directory for generated .mdx docs 212 | template: "api.mustache", 213 | downloadUrl: 214 | "https://raw.githubusercontent.com/LukeHagar/plex-api-spec/main/plex-tv-spec-dereferenced.yaml", 215 | sidebarOptions: { 216 | groupPathsBy: "tag", 217 | categoryLinkSource: "tag", 218 | sidebarCollapsed: false, 219 | }, 220 | }, 221 | PMS: { 222 | specPath: "static/plex-media-server-spec-dereferenced.yaml", // Path to designated spec file 223 | outputDir: "docs/plex", // Output directory for generated .mdx docs 224 | template: "api.mustache", 225 | downloadUrl: 226 | "https://raw.githubusercontent.com/LukeHagar/plex-api-spec/main/plex-media-server-spec-dereferenced.yaml", 227 | sidebarOptions: { 228 | groupPathsBy: "tag", 229 | categoryLinkSource: "tag", 230 | sidebarCollapsed: false, 231 | }, 232 | }, 233 | }, 234 | }, 235 | ], 236 | ], 237 | 238 | themes: ["docusaurus-theme-openapi-docs"], 239 | }; 240 | 241 | module.exports = config; 242 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "plex-docs", 3 | "version": "0.0.1", 4 | "private": true, 5 | "license": "MIT", 6 | "scripts": { 7 | "docusaurus": "docusaurus", 8 | "start": "docusaurus start", 9 | "build": "docusaurus build", 10 | "swizzle": "docusaurus swizzle", 11 | "deploy": "docusaurus deploy", 12 | "clear": "docusaurus clear", 13 | "serve": "docusaurus serve", 14 | "gen-docs": "docusaurus gen-api-docs all", 15 | "clean-docs": "docusaurus clean-api-docs all", 16 | "rebuild": "yarn clean-docs && yarn gen-docs" 17 | }, 18 | "dependencies": { 19 | "@docusaurus/core": "2.4.0", 20 | "@docusaurus/preset-classic": "2.4.0", 21 | "@mdx-js/react": "^1.6.22", 22 | "clsx": "^1.2.1", 23 | "docusaurus-plugin-openapi-docs": "2.0.0-beta.2", 24 | "docusaurus-theme-openapi-docs": "2.0.0-beta.2", 25 | "prism-react-renderer": "^1.3.5", 26 | "react": "^17.0.2", 27 | "react-dom": "^17.0.2" 28 | }, 29 | "devDependencies": { 30 | "@docusaurus/module-type-aliases": "2.4.0" 31 | }, 32 | "browserslist": { 33 | "production": [ 34 | ">0.5%", 35 | "not dead", 36 | "not op_mini all" 37 | ], 38 | "development": [ 39 | "last 1 chrome version", 40 | "last 1 firefox version", 41 | "last 1 safari version" 42 | ] 43 | }, 44 | "engines": { 45 | "node": ">=16.14" 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /sidebars.js: -------------------------------------------------------------------------------- 1 | /** @type {import('@docusaurus/plugin-content-docs').SidebarsConfig} */ 2 | const sidebars = { 3 | plexSidebar: [ 4 | { 5 | type: "category", 6 | label: "Plex Media Server API", 7 | collapsible: true, 8 | collapsed: true, 9 | link: { 10 | type: "generated-index", 11 | title: "Plex Media Server API", 12 | description: 13 | "This documentation is generated from an OpenAPI Specificiation File", 14 | slug: "/plex", 15 | }, 16 | items: require("./docs/plex/sidebar.js"), 17 | }, 18 | { 19 | type: "category", 20 | label: "Plex TV API", 21 | collapsible: true, 22 | collapsed: true, 23 | link: { 24 | type: "generated-index", 25 | title: "Plex TV API", 26 | description: 27 | "This documentation is generated from an OpenAPI Specificiation File", 28 | slug: "/plex-tv", 29 | }, 30 | items: require("./docs/plex-tv/sidebar.js"), 31 | }, 32 | { 33 | type: "category", 34 | label: "Legacy Markdown", 35 | collapsible: true, 36 | collapsed: true, 37 | link: { 38 | type: "generated-index", 39 | title: "Legacy API Markdown", 40 | description: 41 | "This documentation is the source markdown data used to create the open API Document", 42 | slug: "/legacy", 43 | }, 44 | items: [ 45 | { 46 | type: "autogenerated", 47 | dirName: "legacy/plex", // generate sidebar 48 | }, 49 | ], 50 | }, 51 | ], 52 | }; 53 | 54 | module.exports = sidebars; 55 | -------------------------------------------------------------------------------- /src/components/HomepageFeatures/index.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import clsx from "clsx"; 3 | import styles from "./styles.module.css"; 4 | 5 | const FeatureList = [ 6 | { 7 | title: "Updated with the Spec", 8 | Svg: require("@site/static/img/undraw_docusaurus_mountain.svg").default, 9 | description: ( 10 | <> 11 | API Documentation and SDK for Plex dynamically generated from an{" "} 12 | 17 | OpenAPI Specification 18 | 19 | . 20 | 21 | ), 22 | }, 23 | { 24 | title: "Open Source", 25 | Svg: require("@site/static/img/undraw_docusaurus_tree.svg").default, 26 | description: ( 27 | <> 28 | The OpenAPI Specification is fully open source, and everyone is welcome 29 | to{" "} 30 | 35 | report issues 36 | {" "} 37 | or{" "} 38 | 43 | submit pull requests 44 | 45 | . 46 | 47 | ), 48 | }, 49 | { 50 | title: "SDKs", 51 | Svg: require("@site/static/img/undraw_docusaurus_react.svg").default, 52 | description: ( 53 | <> 54 | The Open API Specification is used to automatically generate SDKs in a 55 | number of different languages (JavaScript/TypeScript, GO, Python, 56 | etc...) using{" "} 57 | 58 | the world class OpenAPI Generation platform Speakeasy 59 | 60 | . 61 | 62 | ), 63 | }, 64 | ]; 65 | 66 | function Feature({ Svg, title, description }) { 67 | return ( 68 |
69 |
70 | 71 |
72 |
73 |

{title}

74 |

{description}

75 |
76 |
77 | ); 78 | } 79 | 80 | export default function HomepageFeatures() { 81 | return ( 82 |
83 |
84 |
85 | {FeatureList.map((props, idx) => ( 86 | 87 | ))} 88 |
89 |
90 |
91 | ); 92 | } 93 | -------------------------------------------------------------------------------- /src/components/HomepageFeatures/styles.module.css: -------------------------------------------------------------------------------- 1 | .features { 2 | display: flex; 3 | align-items: center; 4 | padding: 2rem 0; 5 | width: 100%; 6 | } 7 | 8 | .featureSvg { 9 | height: 200px; 10 | width: 200px; 11 | } 12 | -------------------------------------------------------------------------------- /src/css/custom.css: -------------------------------------------------------------------------------- 1 | /** 2 | * Any CSS included here will be global. The classic template 3 | * bundles Infima by default. Infima is a CSS framework designed to 4 | * work well for content-centric websites. 5 | */ 6 | 7 | /* You can override the default Infima variables here. */ 8 | :root { 9 | --ifm-color-primary: #0047ab; 10 | --ifm-color-primary-dark: #00409a; 11 | --ifm-color-primary-darker: #003c91; 12 | --ifm-color-primary-darkest: #003278; 13 | --ifm-color-primary-light: #004ebc; 14 | --ifm-color-primary-lighter: #0052c5; 15 | --ifm-color-primary-lightest: #005cde; 16 | --ifm-code-font-size: 95%; 17 | --docusaurus-highlighted-code-line-bg: rgba(0, 0, 0, 0.1); 18 | } 19 | 20 | /* For readability concerns, you should choose a lighter palette in dark mode. */ 21 | [data-theme="dark"] { 22 | --ifm-color-primary: #20b4fe; 23 | --ifm-color-primary-dark: #04aafe; 24 | --ifm-color-primary-darker: #01a2f2; 25 | --ifm-color-primary-darkest: #0185c7; 26 | --ifm-color-primary-light: #3cbefe; 27 | --ifm-color-primary-lighter: #4bc2fe; 28 | --ifm-color-primary-lightest: #75d1fe; 29 | --ifm-background-color: #000000; 30 | } -------------------------------------------------------------------------------- /src/pages/index.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import clsx from "clsx"; 3 | import Link from "@docusaurus/Link"; 4 | import useDocusaurusContext from "@docusaurus/useDocusaurusContext"; 5 | import Layout from "@theme/Layout"; 6 | import HomepageFeatures from "@site/src/components/HomepageFeatures"; 7 | 8 | import styles from "./index.module.css"; 9 | 10 | function HomepageHeader() { 11 | const { siteConfig } = useDocusaurusContext(); 12 | return ( 13 |
14 |
15 |

{siteConfig.title}

16 |

{siteConfig.tagline}

17 |
18 | 19 | Dive right in 20 | 21 |
22 |
23 |
24 | ); 25 | } 26 | 27 | export default function Home() { 28 | const { siteConfig } = useDocusaurusContext(); 29 | return ( 30 | 34 | 35 |
36 | 37 |
38 |
39 | ); 40 | } 41 | -------------------------------------------------------------------------------- /src/pages/index.module.css: -------------------------------------------------------------------------------- 1 | /** 2 | * CSS files with the .module.css suffix will be treated as CSS modules 3 | * and scoped locally. 4 | */ 5 | 6 | .heroBanner { 7 | padding: 4rem 0; 8 | text-align: center; 9 | position: relative; 10 | overflow: hidden; 11 | } 12 | 13 | @media screen and (max-width: 996px) { 14 | .heroBanner { 15 | padding: 2rem; 16 | } 17 | } 18 | 19 | .buttons { 20 | display: flex; 21 | align-items: center; 22 | justify-content: center; 23 | } 24 | -------------------------------------------------------------------------------- /src/pages/sdk-docs.js: -------------------------------------------------------------------------------- 1 | // https://docs.liblab.com/lukeslakemail/plex-api/0.0.3 2 | import React from "react"; 3 | import Layout from "@theme/Layout"; 4 | 5 | export default function SdkDocs() { 6 | return ( 7 | 12 |

Currently under maintenance, working on something very exciting.

13 |
14 | ); 15 | } 16 | -------------------------------------------------------------------------------- /src/pages/sdk-docs.module.css: -------------------------------------------------------------------------------- 1 | /** 2 | * CSS files with the .module.css suffix will be treated as CSS modules 3 | * and scoped locally. 4 | */ 5 | 6 | .sdkDocs { 7 | height: 100%; 8 | flex-grow: 1; 9 | } 10 | -------------------------------------------------------------------------------- /static/.nojekyll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LukeHagar/plex-docs/921fcad726e81c4d91e1677787fb9c63d9ba6af1/static/.nojekyll -------------------------------------------------------------------------------- /static/img/Open-Graph-Image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LukeHagar/plex-docs/921fcad726e81c4d91e1677787fb9c63d9ba6af1/static/img/Open-Graph-Image.png -------------------------------------------------------------------------------- /static/img/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LukeHagar/plex-docs/921fcad726e81c4d91e1677787fb9c63d9ba6af1/static/img/favicon.ico -------------------------------------------------------------------------------- /static/img/logo.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /static/img/undraw_docusaurus_tree.svg: -------------------------------------------------------------------------------- 1 | 2 | Focus on What Matters 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | --------------------------------------------------------------------------------