{
  "openapi": "3.1.0",
  "info": {
    "title": "xOTT Player API",
    "version": "1.0.0",
    "description": "Player credentials are scoped to an access line. Staff and reseller control-plane APIs use separate authentication. Native events use explicit native-event collection rules without requiring stable slots; slot-only grants remain separate. VOD is progressive file delivery with seeking."
  },
  "servers": [
    {
      "url": "/api/player/v1"
    }
  ],
  "paths": {
    "/auth/web/token": {
      "post": {
        "summary": "Same-origin browser sign-in; remembered refresh credentials use an HTTPS HttpOnly cookie",
        "security": [],
        "parameters": [],
        "responses": {
          "200": {
            "description": "Authorized result"
          },
          "204": {
            "description": "Operation completed without a response body"
          },
          "401": {
            "description": "Authenticate or refresh credentials"
          },
          "403": {
            "description": "Policy or permission denied"
          },
          "404": {
            "description": "Unavailable or unauthorized resource"
          },
          "429": {
            "description": "Request limit reached"
          },
          "503": {
            "description": "Service temporarily unavailable"
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "username",
                  "password"
                ],
                "properties": {
                  "username": {
                    "type": "string",
                    "maxLength": 100
                  },
                  "password": {
                    "type": "string",
                    "writeOnly": true
                  },
                  "deviceId": {
                    "type": "string",
                    "maxLength": 128
                  },
                  "deviceName": {
                    "type": "string",
                    "maxLength": 100
                  },
                  "remember": {
                    "type": "boolean"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/auth/web/refresh": {
      "post": {
        "summary": "Rotate the same-origin browser refresh cookie; coordinate refreshes across tabs",
        "security": [],
        "parameters": [],
        "responses": {
          "200": {
            "description": "Authorized result"
          },
          "204": {
            "description": "Operation completed without a response body"
          },
          "401": {
            "description": "Authenticate or refresh credentials"
          },
          "403": {
            "description": "Policy or permission denied"
          },
          "404": {
            "description": "Unavailable or unauthorized resource"
          },
          "429": {
            "description": "Request limit reached"
          },
          "503": {
            "description": "Service temporarily unavailable"
          }
        }
      }
    },
    "/auth/web/logout": {
      "post": {
        "summary": "Clear and revoke the browser remembered login",
        "security": [],
        "parameters": [],
        "responses": {
          "200": {
            "description": "Authorized result"
          },
          "204": {
            "description": "Operation completed without a response body"
          },
          "401": {
            "description": "Authenticate or refresh credentials"
          },
          "403": {
            "description": "Policy or permission denied"
          },
          "404": {
            "description": "Unavailable or unauthorized resource"
          },
          "429": {
            "description": "Request limit reached"
          },
          "503": {
            "description": "Service temporarily unavailable"
          }
        }
      }
    },
    "/guide": {
      "post": {
        "summary": "Read a bounded, entitlement-filtered guide window in one request",
        "security": [
          {
            "playerBearer": []
          }
        ],
        "parameters": [],
        "responses": {
          "200": {
            "description": "Authorized result"
          },
          "204": {
            "description": "Operation completed without a response body"
          },
          "401": {
            "description": "Authenticate or refresh credentials"
          },
          "403": {
            "description": "Policy or permission denied"
          },
          "404": {
            "description": "Unavailable or unauthorized resource"
          },
          "429": {
            "description": "Request limit reached"
          },
          "503": {
            "description": "Service temporarily unavailable"
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "channelIds"
                ],
                "properties": {
                  "channelIds": {
                    "type": "array",
                    "maxItems": 40,
                    "minItems": 1,
                    "items": {
                      "type": "string",
                      "format": "uuid"
                    }
                  },
                  "start": {
                    "type": "string",
                    "format": "date-time"
                  },
                  "end": {
                    "type": "string",
                    "format": "date-time"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/categories/{kind}": {
      "get": {
        "summary": "List authorized VOD category facets",
        "security": [
          {
            "playerBearer": []
          }
        ],
        "parameters": [
          {
            "name": "kind",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Authorized result"
          },
          "204": {
            "description": "Operation completed without a response body"
          },
          "401": {
            "description": "Authenticate or refresh credentials"
          },
          "403": {
            "description": "Policy or permission denied"
          },
          "404": {
            "description": "Unavailable or unauthorized resource"
          },
          "429": {
            "description": "Request limit reached"
          },
          "503": {
            "description": "Service temporarily unavailable"
          }
        }
      }
    },
    "/sessions/{id}/qoe": {
      "post": {
        "summary": "Report bounded player-observed quality, never authoritative traffic usage",
        "security": [
          {
            "playerBearer": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Authorized result"
          },
          "204": {
            "description": "Operation completed without a response body"
          },
          "401": {
            "description": "Authenticate or refresh credentials"
          },
          "403": {
            "description": "Policy or permission denied"
          },
          "404": {
            "description": "Unavailable or unauthorized resource"
          },
          "429": {
            "description": "Request limit reached"
          },
          "503": {
            "description": "Service temporarily unavailable"
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "instance",
                  "sequence",
                  "stalls",
                  "recoveries"
                ],
                "properties": {
                  "instance": {
                    "type": "string",
                    "maxLength": 128
                  },
                  "sequence": {
                    "type": "integer",
                    "minimum": 1
                  },
                  "stalls": {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 100000
                  },
                  "recoveries": {
                    "type": "integer",
                    "minimum": 0,
                    "maximum": 100000
                  },
                  "startupMs": {
                    "type": [
                      "integer",
                      "null"
                    ],
                    "minimum": 0,
                    "maximum": 120000
                  }
                }
              }
            }
          }
        }
      }
    },
    "/sdk.js": {
      "get": {
        "summary": "Download the public browser/CommonJS player SDK",
        "security": [],
        "responses": {
          "200": {
            "description": "JavaScript client",
            "content": {
              "application/javascript": {
                "schema": {
                  "type": "string"
                }
              }
            }
          }
        }
      }
    },
    "/auth/token": {
      "post": {
        "summary": "Sign in with access-line credentials",
        "security": [],
        "parameters": [],
        "responses": {
          "200": {
            "description": "Authorized result"
          },
          "204": {
            "description": "Operation completed without a response body"
          },
          "401": {
            "description": "Authenticate or refresh credentials"
          },
          "403": {
            "description": "Policy or permission denied"
          },
          "404": {
            "description": "Unavailable or unauthorized resource"
          },
          "429": {
            "description": "Request limit reached"
          },
          "503": {
            "description": "Service temporarily unavailable"
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "username",
                  "password"
                ],
                "properties": {
                  "username": {
                    "type": "string",
                    "maxLength": 100
                  },
                  "password": {
                    "type": "string",
                    "maxLength": 512,
                    "writeOnly": true
                  },
                  "deviceId": {
                    "type": "string",
                    "maxLength": 128
                  }
                }
              }
            }
          }
        }
      }
    },
    "/auth/refresh": {
      "post": {
        "summary": "Rotate a refresh token; serialize requests and persist its replacement",
        "security": [],
        "parameters": [],
        "responses": {
          "200": {
            "description": "Authorized result"
          },
          "204": {
            "description": "Operation completed without a response body"
          },
          "401": {
            "description": "Authenticate or refresh credentials"
          },
          "403": {
            "description": "Policy or permission denied"
          },
          "404": {
            "description": "Unavailable or unauthorized resource"
          },
          "429": {
            "description": "Request limit reached"
          },
          "503": {
            "description": "Service temporarily unavailable"
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "refreshToken"
                ],
                "properties": {
                  "refreshToken": {
                    "type": "string",
                    "writeOnly": true
                  }
                }
              }
            }
          }
        }
      }
    },
    "/auth/logout": {
      "post": {
        "summary": "Revoke this player login and stop its active playback session",
        "security": [
          {
            "playerBearer": []
          }
        ],
        "parameters": [],
        "responses": {
          "200": {
            "description": "Authorized result"
          },
          "204": {
            "description": "Operation completed without a response body"
          },
          "401": {
            "description": "Authenticate or refresh credentials"
          },
          "403": {
            "description": "Policy or permission denied"
          },
          "404": {
            "description": "Unavailable or unauthorized resource"
          },
          "429": {
            "description": "Request limit reached"
          },
          "503": {
            "description": "Service temporarily unavailable"
          }
        }
      }
    },
    "/capabilities": {
      "get": {
        "summary": "Discover supported features and subscription output rights",
        "security": [
          {
            "playerBearer": []
          }
        ],
        "parameters": [],
        "responses": {
          "200": {
            "description": "Authorized result"
          },
          "204": {
            "description": "Operation completed without a response body"
          },
          "401": {
            "description": "Authenticate or refresh credentials"
          },
          "403": {
            "description": "Policy or permission denied"
          },
          "404": {
            "description": "Unavailable or unauthorized resource"
          },
          "429": {
            "description": "Request limit reached"
          },
          "503": {
            "description": "Service temporarily unavailable"
          }
        }
      }
    },
    "/me": {
      "get": {
        "summary": "Read line expiry, connection allowance and traffic usage",
        "security": [
          {
            "playerBearer": []
          }
        ],
        "parameters": [],
        "responses": {
          "200": {
            "description": "Authorized result"
          },
          "204": {
            "description": "Operation completed without a response body"
          },
          "401": {
            "description": "Authenticate or refresh credentials"
          },
          "403": {
            "description": "Policy or permission denied"
          },
          "404": {
            "description": "Unavailable or unauthorized resource"
          },
          "429": {
            "description": "Request limit reached"
          },
          "503": {
            "description": "Service temporarily unavailable"
          }
        }
      }
    },
    "/changes": {
      "get": {
        "summary": "Check VOD catalogue and entitlement versions; discard cached rows when resetRequired",
        "security": [
          {
            "playerBearer": []
          }
        ],
        "parameters": [
          {
            "name": "vodVersion",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "entitlementGeneration",
            "in": "query",
            "schema": {
              "type": "integer"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Authorized result"
          },
          "204": {
            "description": "Operation completed without a response body"
          },
          "401": {
            "description": "Authenticate or refresh credentials"
          },
          "403": {
            "description": "Policy or permission denied"
          },
          "404": {
            "description": "Unavailable or unauthorized resource"
          },
          "429": {
            "description": "Request limit reached"
          },
          "503": {
            "description": "Service temporarily unavailable"
          }
        }
      }
    },
    "/channels": {
      "get": {
        "summary": "List authorized linear channels",
        "security": [
          {
            "playerBearer": []
          }
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 50
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "search",
            "in": "query",
            "schema": {
              "type": "string",
              "maxLength": 200
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Authorized result"
          },
          "204": {
            "description": "Operation completed without a response body"
          },
          "401": {
            "description": "Authenticate or refresh credentials"
          },
          "403": {
            "description": "Policy or permission denied"
          },
          "404": {
            "description": "Unavailable or unauthorized resource"
          },
          "429": {
            "description": "Request limit reached"
          },
          "503": {
            "description": "Service temporarily unavailable"
          }
        }
      }
    },
    "/channels/{id}/epg": {
      "get": {
        "summary": "Read the matched guide for one channel",
        "security": [
          {
            "playerBearer": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 50
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Authorized result"
          },
          "204": {
            "description": "Operation completed without a response body"
          },
          "401": {
            "description": "Authenticate or refresh credentials"
          },
          "403": {
            "description": "Policy or permission denied"
          },
          "404": {
            "description": "Unavailable or unauthorized resource"
          },
          "429": {
            "description": "Request limit reached"
          },
          "503": {
            "description": "Service temporarily unavailable"
          }
        }
      }
    },
    "/events": {
      "get": {
        "summary": "List authorized provider event snapshots without fetching providers",
        "security": [
          {
            "playerBearer": []
          }
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 50
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "search",
            "in": "query",
            "schema": {
              "type": "string",
              "maxLength": 200
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Authorized result"
          },
          "204": {
            "description": "Operation completed without a response body"
          },
          "401": {
            "description": "Authenticate or refresh credentials"
          },
          "403": {
            "description": "Policy or permission denied"
          },
          "404": {
            "description": "Unavailable or unauthorized resource"
          },
          "429": {
            "description": "Request limit reached"
          },
          "503": {
            "description": "Service temporarily unavailable"
          }
        }
      }
    },
    "/events/{id}": {
      "get": {
        "summary": "Read an event snapshot",
        "security": [
          {
            "playerBearer": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Authorized result"
          },
          "204": {
            "description": "Operation completed without a response body"
          },
          "401": {
            "description": "Authenticate or refresh credentials"
          },
          "403": {
            "description": "Policy or permission denied"
          },
          "404": {
            "description": "Unavailable or unauthorized resource"
          },
          "429": {
            "description": "Request limit reached"
          },
          "503": {
            "description": "Service temporarily unavailable"
          }
        }
      }
    },
    "/event-slots": {
      "get": {
        "summary": "List permanent authorized event slots and their current assignments",
        "security": [
          {
            "playerBearer": []
          }
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 50
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "search",
            "in": "query",
            "schema": {
              "type": "string",
              "maxLength": 200
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Authorized result"
          },
          "204": {
            "description": "Operation completed without a response body"
          },
          "401": {
            "description": "Authenticate or refresh credentials"
          },
          "403": {
            "description": "Policy or permission denied"
          },
          "404": {
            "description": "Unavailable or unauthorized resource"
          },
          "429": {
            "description": "Request limit reached"
          },
          "503": {
            "description": "Service temporarily unavailable"
          }
        }
      }
    },
    "/series/{id}/episodes": {
      "get": {
        "summary": "List authorized published episodes",
        "security": [
          {
            "playerBearer": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 50
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "search",
            "in": "query",
            "schema": {
              "type": "string",
              "maxLength": 200
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Authorized result"
          },
          "204": {
            "description": "Operation completed without a response body"
          },
          "401": {
            "description": "Authenticate or refresh credentials"
          },
          "403": {
            "description": "Policy or permission denied"
          },
          "404": {
            "description": "Unavailable or unauthorized resource"
          },
          "429": {
            "description": "Request limit reached"
          },
          "503": {
            "description": "Service temporarily unavailable"
          }
        }
      }
    },
    "/episodes/{id}": {
      "get": {
        "summary": "Read one published episode and its playable renditions",
        "security": [
          {
            "playerBearer": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Authorized result"
          },
          "204": {
            "description": "Operation completed without a response body"
          },
          "401": {
            "description": "Authenticate or refresh credentials"
          },
          "403": {
            "description": "Policy or permission denied"
          },
          "404": {
            "description": "Unavailable or unauthorized resource"
          },
          "429": {
            "description": "Request limit reached"
          },
          "503": {
            "description": "Service temporarily unavailable"
          }
        }
      }
    },
    "/playback": {
      "post": {
        "summary": "Admit playback under the shared global connection limit",
        "security": [
          {
            "playerBearer": []
          }
        ],
        "parameters": [],
        "responses": {
          "200": {
            "description": "Authorized result"
          },
          "204": {
            "description": "Operation completed without a response body"
          },
          "401": {
            "description": "Authenticate or refresh credentials"
          },
          "403": {
            "description": "Policy or permission denied"
          },
          "404": {
            "description": "Unavailable or unauthorized resource"
          },
          "429": {
            "description": "Request limit reached"
          },
          "503": {
            "description": "Service temporarily unavailable"
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "type",
                  "id"
                ],
                "properties": {
                  "type": {
                    "type": "string",
                    "enum": [
                      "channel",
                      "event",
                      "event_slot",
                      "vod"
                    ]
                  },
                  "id": {
                    "type": "string"
                  },
                  "format": {
                    "type": "string",
                    "enum": [
                      "hls",
                      "mpegts",
                      "file"
                    ]
                  },
                  "assetId": {
                    "type": "string",
                    "format": "uuid",
                    "description": "Optional verified VOD rendition; must belong to the authorized title."
                  }
                }
              }
            }
          }
        }
      }
    },
    "/sessions": {
      "get": {
        "summary": "List this line’s active playback sessions",
        "security": [
          {
            "playerBearer": []
          }
        ],
        "parameters": [],
        "responses": {
          "200": {
            "description": "Authorized result"
          },
          "204": {
            "description": "Operation completed without a response body"
          },
          "401": {
            "description": "Authenticate or refresh credentials"
          },
          "403": {
            "description": "Policy or permission denied"
          },
          "404": {
            "description": "Unavailable or unauthorized resource"
          },
          "429": {
            "description": "Request limit reached"
          },
          "503": {
            "description": "Service temporarily unavailable"
          }
        }
      }
    },
    "/sessions/{id}": {
      "delete": {
        "summary": "Terminate an owned playback session",
        "security": [
          {
            "playerBearer": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Authorized result"
          },
          "204": {
            "description": "Operation completed without a response body"
          },
          "401": {
            "description": "Authenticate or refresh credentials"
          },
          "403": {
            "description": "Policy or permission denied"
          },
          "404": {
            "description": "Unavailable or unauthorized resource"
          },
          "429": {
            "description": "Request limit reached"
          },
          "503": {
            "description": "Service temporarily unavailable"
          }
        }
      }
    },
    "/sessions/{id}/release": {
      "post": {
        "summary": "Release this browser’s current native lease without blocking a new playback",
        "security": [
          {
            "playerBearer": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Authorized result"
          },
          "204": {
            "description": "Operation completed without a response body"
          },
          "401": {
            "description": "Authenticate or refresh credentials"
          },
          "403": {
            "description": "Policy or permission denied"
          },
          "404": {
            "description": "Unavailable or unauthorized resource"
          },
          "429": {
            "description": "Request limit reached"
          },
          "503": {
            "description": "Service temporarily unavailable"
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "sessionNonce",
                  "generation"
                ],
                "properties": {
                  "sessionNonce": {
                    "type": "string",
                    "format": "uuid"
                  },
                  "generation": {
                    "type": "integer",
                    "minimum": 1
                  }
                }
              }
            }
          }
        }
      }
    },
    "/sessions/{id}/heartbeat": {
      "post": {
        "summary": "Keep this device’s playback lease active while its player is watching",
        "security": [
          {
            "playerBearer": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Authorized result"
          },
          "204": {
            "description": "Operation completed without a response body"
          },
          "401": {
            "description": "Authenticate or refresh credentials"
          },
          "403": {
            "description": "Policy or permission denied"
          },
          "404": {
            "description": "Unavailable or unauthorized resource"
          },
          "429": {
            "description": "Request limit reached"
          },
          "503": {
            "description": "Service temporarily unavailable"
          }
        }
      }
    },
    "/devices": {
      "get": {
        "summary": "List this line’s registered playback devices",
        "security": [
          {
            "playerBearer": []
          }
        ],
        "parameters": [],
        "responses": {
          "200": {
            "description": "Authorized result"
          },
          "204": {
            "description": "Operation completed without a response body"
          },
          "401": {
            "description": "Authenticate or refresh credentials"
          },
          "403": {
            "description": "Policy or permission denied"
          },
          "404": {
            "description": "Unavailable or unauthorized resource"
          },
          "429": {
            "description": "Request limit reached"
          },
          "503": {
            "description": "Service temporarily unavailable"
          }
        }
      }
    },
    "/devices/{id}": {
      "delete": {
        "summary": "Revoke an owned playback device",
        "security": [
          {
            "playerBearer": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Authorized result"
          },
          "204": {
            "description": "Operation completed without a response body"
          },
          "401": {
            "description": "Authenticate or refresh credentials"
          },
          "403": {
            "description": "Policy or permission denied"
          },
          "404": {
            "description": "Unavailable or unauthorized resource"
          },
          "429": {
            "description": "Request limit reached"
          },
          "503": {
            "description": "Service temporarily unavailable"
          }
        }
      }
    },
    "/progress": {
      "get": {
        "summary": "Read authorized continue-watching history",
        "security": [
          {
            "playerBearer": []
          }
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 50
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Authorized result"
          },
          "204": {
            "description": "Operation completed without a response body"
          },
          "401": {
            "description": "Authenticate or refresh credentials"
          },
          "403": {
            "description": "Policy or permission denied"
          },
          "404": {
            "description": "Unavailable or unauthorized resource"
          },
          "429": {
            "description": "Request limit reached"
          },
          "503": {
            "description": "Service temporarily unavailable"
          }
        }
      }
    },
    "/progress/{id}": {
      "put": {
        "summary": "Save progress; supply the last revision to reject stale updates",
        "security": [
          {
            "playerBearer": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Authorized result"
          },
          "204": {
            "description": "Operation completed without a response body"
          },
          "401": {
            "description": "Authenticate or refresh credentials"
          },
          "403": {
            "description": "Policy or permission denied"
          },
          "404": {
            "description": "Unavailable or unauthorized resource"
          },
          "429": {
            "description": "Request limit reached"
          },
          "503": {
            "description": "Service temporarily unavailable"
          }
        },
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "required": [
                  "positionSeconds"
                ],
                "properties": {
                  "positionSeconds": {
                    "type": "number",
                    "minimum": 0
                  },
                  "revision": {
                    "type": "integer",
                    "minimum": 1
                  }
                }
              }
            }
          }
        }
      }
    },
    "/favourites": {
      "get": {
        "summary": "Read favourites that remain authorized",
        "security": [
          {
            "playerBearer": []
          }
        ],
        "parameters": [],
        "responses": {
          "200": {
            "description": "Authorized result"
          },
          "204": {
            "description": "Operation completed without a response body"
          },
          "401": {
            "description": "Authenticate or refresh credentials"
          },
          "403": {
            "description": "Policy or permission denied"
          },
          "404": {
            "description": "Unavailable or unauthorized resource"
          },
          "429": {
            "description": "Request limit reached"
          },
          "503": {
            "description": "Service temporarily unavailable"
          }
        }
      }
    },
    "/favourites/{type}/{id}": {
      "put": {
        "summary": "Add an authorized favourite",
        "security": [
          {
            "playerBearer": []
          }
        ],
        "parameters": [
          {
            "name": "type",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Authorized result"
          },
          "204": {
            "description": "Operation completed without a response body"
          },
          "401": {
            "description": "Authenticate or refresh credentials"
          },
          "403": {
            "description": "Policy or permission denied"
          },
          "404": {
            "description": "Unavailable or unauthorized resource"
          },
          "429": {
            "description": "Request limit reached"
          },
          "503": {
            "description": "Service temporarily unavailable"
          }
        }
      },
      "delete": {
        "summary": "Remove a favourite",
        "security": [
          {
            "playerBearer": []
          }
        ],
        "parameters": [
          {
            "name": "type",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Authorized result"
          },
          "204": {
            "description": "Operation completed without a response body"
          },
          "401": {
            "description": "Authenticate or refresh credentials"
          },
          "403": {
            "description": "Policy or permission denied"
          },
          "404": {
            "description": "Unavailable or unauthorized resource"
          },
          "429": {
            "description": "Request limit reached"
          },
          "503": {
            "description": "Service temporarily unavailable"
          }
        }
      }
    },
    "/movies": {
      "get": {
        "summary": "List authorized published movies",
        "security": [
          {
            "playerBearer": []
          }
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 50
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "search",
            "in": "query",
            "schema": {
              "type": "string",
              "maxLength": 200
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Authorized result"
          },
          "204": {
            "description": "Operation completed without a response body"
          },
          "401": {
            "description": "Authenticate or refresh credentials"
          },
          "403": {
            "description": "Policy or permission denied"
          },
          "404": {
            "description": "Unavailable or unauthorized resource"
          },
          "429": {
            "description": "Request limit reached"
          },
          "503": {
            "description": "Service temporarily unavailable"
          }
        }
      }
    },
    "/movies/{id}": {
      "get": {
        "summary": "Read published movies metadata",
        "security": [
          {
            "playerBearer": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Authorized result"
          },
          "204": {
            "description": "Operation completed without a response body"
          },
          "401": {
            "description": "Authenticate or refresh credentials"
          },
          "403": {
            "description": "Policy or permission denied"
          },
          "404": {
            "description": "Unavailable or unauthorized resource"
          },
          "429": {
            "description": "Request limit reached"
          },
          "503": {
            "description": "Service temporarily unavailable"
          }
        }
      }
    },
    "/series": {
      "get": {
        "summary": "List authorized published series",
        "security": [
          {
            "playerBearer": []
          }
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 50
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "search",
            "in": "query",
            "schema": {
              "type": "string",
              "maxLength": 200
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Authorized result"
          },
          "204": {
            "description": "Operation completed without a response body"
          },
          "401": {
            "description": "Authenticate or refresh credentials"
          },
          "403": {
            "description": "Policy or permission denied"
          },
          "404": {
            "description": "Unavailable or unauthorized resource"
          },
          "429": {
            "description": "Request limit reached"
          },
          "503": {
            "description": "Service temporarily unavailable"
          }
        }
      }
    },
    "/series/{id}": {
      "get": {
        "summary": "Read published series metadata",
        "security": [
          {
            "playerBearer": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Authorized result"
          },
          "204": {
            "description": "Operation completed without a response body"
          },
          "401": {
            "description": "Authenticate or refresh credentials"
          },
          "403": {
            "description": "Policy or permission denied"
          },
          "404": {
            "description": "Unavailable or unauthorized resource"
          },
          "429": {
            "description": "Request limit reached"
          },
          "503": {
            "description": "Service temporarily unavailable"
          }
        }
      }
    },
    "/recordings": {
      "get": {
        "summary": "List authorized published recordings",
        "security": [
          {
            "playerBearer": []
          }
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 50
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "search",
            "in": "query",
            "schema": {
              "type": "string",
              "maxLength": 200
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Authorized result"
          },
          "204": {
            "description": "Operation completed without a response body"
          },
          "401": {
            "description": "Authenticate or refresh credentials"
          },
          "403": {
            "description": "Policy or permission denied"
          },
          "404": {
            "description": "Unavailable or unauthorized resource"
          },
          "429": {
            "description": "Request limit reached"
          },
          "503": {
            "description": "Service temporarily unavailable"
          }
        }
      }
    },
    "/recordings/{id}": {
      "get": {
        "summary": "Read published recordings metadata",
        "security": [
          {
            "playerBearer": []
          }
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Authorized result"
          },
          "204": {
            "description": "Operation completed without a response body"
          },
          "401": {
            "description": "Authenticate or refresh credentials"
          },
          "403": {
            "description": "Policy or permission denied"
          },
          "404": {
            "description": "Unavailable or unauthorized resource"
          },
          "429": {
            "description": "Request limit reached"
          },
          "503": {
            "description": "Service temporarily unavailable"
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "playerBearer": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "JWT"
      }
    }
  }
}
