openapi: 3.0.0
info:
  title: AzuraCast
  description: 'AzuraCast is a standalone, turnkey web radio management tool. Radio stations hosted by AzuraCast expose a public API for viewing now playing data, making requests and more.'
  license:
    name: 'Apache 2.0'
    url: 'https://www.apache.org/licenses/LICENSE-2.0.html'
  version: 0.17.7
servers:
  -
    url: 'https://demo.azuracast.com/api'
    description: 'AzuraCast Public Demo Server'
paths:
  /admin/custom_fields:
    get:
      tags:
        - 'Administration: Custom Fields'
      description: 'List all current custom fields in the system.'
      operationId: getCustomFields
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/CustomField'
        '403':
          $ref: '#/components/responses/AccessDenied'
        '500':
          $ref: '#/components/responses/GenericError'
      security:
        -
          ApiKey: []
    post:
      tags:
        - 'Administration: Custom Fields'
      description: 'Create a new custom field.'
      operationId: addCustomField
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CustomField'
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CustomField'
        '403':
          $ref: '#/components/responses/AccessDenied'
        '500':
          $ref: '#/components/responses/GenericError'
      security:
        -
          ApiKey: []
  '/admin/custom_field/{id}':
    get:
      tags:
        - 'Administration: Custom Fields'
      description: 'Retrieve details for a single custom field.'
      operationId: getCustomField
      parameters:
        -
          name: id
          in: path
          description: ID
          required: true
          schema:
            type: integer
            format: int64
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/CustomField'
        '403':
          $ref: '#/components/responses/AccessDenied'
        '404':
          $ref: '#/components/responses/RecordNotFound'
        '500':
          $ref: '#/components/responses/GenericError'
      security:
        -
          ApiKey: []
    put:
      tags:
        - 'Administration: Custom Fields'
      description: 'Update details of a single custom field.'
      operationId: editCustomField
      parameters:
        -
          name: id
          in: path
          description: ID
          required: true
          schema:
            type: integer
            format: int64
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CustomField'
      responses:
        '200':
          $ref: '#/components/responses/Success'
        '403':
          $ref: '#/components/responses/AccessDenied'
        '404':
          $ref: '#/components/responses/RecordNotFound'
        '500':
          $ref: '#/components/responses/GenericError'
      security:
        -
          ApiKey: []
    delete:
      tags:
        - 'Administration: Custom Fields'
      description: 'Delete a single custom field.'
      operationId: deleteCustomField
      parameters:
        -
          name: id
          in: path
          description: ID
          required: true
          schema:
            type: integer
            format: int64
      responses:
        '200':
          $ref: '#/components/responses/Success'
        '403':
          $ref: '#/components/responses/AccessDenied'
        '404':
          $ref: '#/components/responses/RecordNotFound'
        '500':
          $ref: '#/components/responses/GenericError'
      security:
        -
          ApiKey: []
  /admin/permissions:
    get:
      tags:
        - 'Administration: Roles'
      description: 'Return a list of all available permissions.'
      operationId: getPermissions
      responses:
        '200':
          description: Success
        '403':
          $ref: '#/components/responses/AccessDenied'
        '404':
          $ref: '#/components/responses/RecordNotFound'
        '500':
          $ref: '#/components/responses/GenericError'
      security:
        -
          ApiKey: []
  /internal/relays:
    get:
      tags:
        - 'Administration: Relays'
      description: "Returns all necessary information to relay all 'relayable' stations."
      operationId: internalGetRelayDetails
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/Api_Admin_Relay'
  /admin/roles:
    get:
      tags:
        - 'Administration: Roles'
      description: 'List all current roles in the system.'
      operationId: getRoles
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/Role'
        '404':
          $ref: '#/components/responses/RecordNotFound'
        '500':
          $ref: '#/components/responses/GenericError'
      security:
        -
          ApiKey: []
    post:
      tags:
        - 'Administration: Roles'
      description: 'Create a new role.'
      operationId: addRole
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Role'
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Role'
        '404':
          $ref: '#/components/responses/RecordNotFound'
        '500':
          $ref: '#/components/responses/GenericError'
      security:
        -
          ApiKey: []
  '/admin/role/{id}':
    get:
      tags:
        - 'Administration: Roles'
      description: 'Retrieve details for a single current role.'
      operationId: getRole
      parameters:
        -
          name: id
          in: path
          description: 'Role ID'
          required: true
          schema:
            type: integer
            format: int64
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Role'
        '403':
          $ref: '#/components/responses/AccessDenied'
        '404':
          $ref: '#/components/responses/RecordNotFound'
        '500':
          $ref: '#/components/responses/GenericError'
      security:
        -
          ApiKey: []
    put:
      tags:
        - 'Administration: Roles'
      description: 'Update details of a single role.'
      operationId: editRole
      parameters:
        -
          name: id
          in: path
          description: 'Role ID'
          required: true
          schema:
            type: integer
            format: int64
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Role'
      responses:
        '200':
          $ref: '#/components/responses/Success'
        '403':
          $ref: '#/components/responses/AccessDenied'
        '404':
          $ref: '#/components/responses/RecordNotFound'
        '500':
          $ref: '#/components/responses/GenericError'
      security:
        -
          ApiKey: []
    delete:
      tags:
        - 'Administration: Roles'
      description: 'Delete a single role.'
      operationId: deleteRole
      parameters:
        -
          name: id
          in: path
          description: 'Role ID'
          required: true
          schema:
            type: integer
            format: int64
      responses:
        '200':
          $ref: '#/components/responses/Success'
        '403':
          $ref: '#/components/responses/AccessDenied'
        '404':
          $ref: '#/components/responses/RecordNotFound'
        '500':
          $ref: '#/components/responses/GenericError'
      security:
        -
          ApiKey: []
  /admin/cpu/stats:
    get:
      tags:
        - 'Administration: CPU stats'
      description: 'Return a list of all CPU usage stats.'
      operationId: getCpuStats
      responses:
        '200':
          description: Success
        '403':
          $ref: '#/components/responses/AccessDenied'
        '404':
          $ref: '#/components/responses/RecordNotFound'
        '500':
          $ref: '#/components/responses/GenericError'
      security:
        -
          ApiKey: []
  /admin/settings:
    get:
      tags:
        - 'Administration: Settings'
      description: 'List the current values of all editable system settings.'
      operationId: getSettings
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Settings'
        '403':
          $ref: '#/components/responses/AccessDenied'
        '500':
          $ref: '#/components/responses/GenericError'
      security:
        -
          ApiKey: []
    put:
      tags:
        - 'Administration: Settings'
      description: 'Update settings to modify any settings provided.'
      operationId: editSettings
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Settings'
      responses:
        '200':
          $ref: '#/components/responses/Success'
        '403':
          $ref: '#/components/responses/AccessDenied'
        '500':
          $ref: '#/components/responses/GenericError'
      security:
        -
          ApiKey: []
  /admin/stations:
    get:
      tags:
        - 'Administration: Stations'
      description: 'List all current stations in the system.'
      operationId: adminGetStations
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/Station'
        '403':
          $ref: '#/components/responses/AccessDenied'
        '500':
          $ref: '#/components/responses/GenericError'
      security:
        -
          ApiKey: []
    post:
      tags:
        - 'Administration: Stations'
      description: 'Create a new station.'
      operationId: adminAddStation
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Station'
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Station'
        '403':
          $ref: '#/components/responses/AccessDenied'
        '500':
          $ref: '#/components/responses/GenericError'
      security:
        -
          ApiKey: []
  '/admin/station/{id}':
    get:
      tags:
        - 'Administration: Stations'
      description: 'Retrieve details for a single station.'
      operationId: adminGetStation
      parameters:
        -
          name: id
          in: path
          description: ID
          required: true
          schema:
            type: integer
            format: int64
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Station'
        '403':
          $ref: '#/components/responses/AccessDenied'
        '404':
          $ref: '#/components/responses/RecordNotFound'
        '500':
          $ref: '#/components/responses/GenericError'
      security:
        -
          ApiKey: []
    put:
      tags:
        - 'Administration: Stations'
      description: 'Update details of a single station.'
      operationId: adminEditStation
      parameters:
        -
          name: id
          in: path
          description: ID
          required: true
          schema:
            type: integer
            format: int64
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Station'
      responses:
        '200':
          $ref: '#/components/responses/Success'
        '403':
          $ref: '#/components/responses/AccessDenied'
        '404':
          $ref: '#/components/responses/RecordNotFound'
        '500':
          $ref: '#/components/responses/GenericError'
      security:
        -
          ApiKey: []
    delete:
      tags:
        - 'Administration: Stations'
      description: 'Delete a single station.'
      operationId: adminDeleteStation
      parameters:
        -
          name: id
          in: path
          description: ID
          required: true
          schema:
            type: integer
            format: int64
      responses:
        '200':
          $ref: '#/components/responses/Success'
        '403':
          $ref: '#/components/responses/AccessDenied'
        '404':
          $ref: '#/components/responses/RecordNotFound'
        '500':
          $ref: '#/components/responses/GenericError'
      security:
        -
          ApiKey: []
  /admin/storage_locations:
    get:
      tags:
        - 'Administration: Storage Locations'
      description: 'List all current storage locations in the system.'
      operationId: getStorageLocations
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/Api_Admin_StorageLocation'
        '403':
          $ref: '#/components/responses/AccessDenied'
        '500':
          $ref: '#/components/responses/GenericError'
      security:
        -
          ApiKey: []
    post:
      tags:
        - 'Administration: Storage Locations'
      description: 'Create a new storage location.'
      operationId: addStorageLocation
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Api_Admin_StorageLocation'
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Api_Admin_StorageLocation'
        '403':
          $ref: '#/components/responses/AccessDenied'
        '500':
          $ref: '#/components/responses/GenericError'
      security:
        -
          ApiKey: []
  '/admin/storage_location/{id}':
    get:
      tags:
        - 'Administration: Storage Locations'
      description: 'Retrieve details for a single storage location.'
      operationId: getStorageLocation
      parameters:
        -
          name: id
          in: path
          description: 'User ID'
          required: true
          schema:
            type: integer
            format: int64
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Api_Admin_StorageLocation'
        '403':
          $ref: '#/components/responses/AccessDenied'
        '404':
          $ref: '#/components/responses/RecordNotFound'
        '500':
          $ref: '#/components/responses/GenericError'
      security:
        -
          ApiKey: []
    put:
      tags:
        - 'Administration: Storage Locations'
      description: 'Update details of a single storage location.'
      operationId: editStorageLocation
      parameters:
        -
          name: id
          in: path
          description: 'Storage Location ID'
          required: true
          schema:
            type: integer
            format: int64
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Api_Admin_StorageLocation'
      responses:
        '200':
          $ref: '#/components/responses/Success'
        '403':
          $ref: '#/components/responses/AccessDenied'
        '404':
          $ref: '#/components/responses/RecordNotFound'
        '500':
          $ref: '#/components/responses/GenericError'
      security:
        -
          ApiKey: []
    delete:
      tags:
        - 'Administration: Storage Locations'
      description: 'Delete a single storage location.'
      operationId: deleteStorageLocation
      parameters:
        -
          name: id
          in: path
          description: 'Storage Location ID'
          required: true
          schema:
            type: integer
            format: int64
      responses:
        '200':
          $ref: '#/components/responses/Success'
        '403':
          $ref: '#/components/responses/AccessDenied'
        '404':
          $ref: '#/components/responses/RecordNotFound'
        '500':
          $ref: '#/components/responses/GenericError'
      security:
        -
          ApiKey: []
  /admin/users:
    get:
      tags:
        - 'Administration: Users'
      description: 'List all current users in the system.'
      operationId: getUsers
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/User'
        '403':
          $ref: '#/components/responses/AccessDenied'
        '500':
          $ref: '#/components/responses/GenericError'
      security:
        -
          ApiKey: []
    post:
      tags:
        - 'Administration: Users'
      description: 'Create a new user.'
      operationId: addUser
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/User'
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/User'
        '403':
          $ref: '#/components/responses/AccessDenied'
        '500':
          $ref: '#/components/responses/GenericError'
      security:
        -
          ApiKey: []
  '/admin/user/{id}':
    get:
      tags:
        - 'Administration: Users'
      description: 'Retrieve details for a single current user.'
      operationId: getUser
      parameters:
        -
          name: id
          in: path
          description: 'User ID'
          required: true
          schema:
            type: integer
            format: int64
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/User'
        '403':
          $ref: '#/components/responses/AccessDenied'
        '404':
          $ref: '#/components/responses/RecordNotFound'
        '500':
          $ref: '#/components/responses/GenericError'
      security:
        -
          ApiKey: []
    put:
      tags:
        - 'Administration: Users'
      description: 'Update details of a single user.'
      operationId: editUser
      parameters:
        -
          name: id
          in: path
          description: 'User ID'
          required: true
          schema:
            type: integer
            format: int64
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/User'
      responses:
        '200':
          $ref: '#/components/responses/Success'
        '403':
          $ref: '#/components/responses/AccessDenied'
        '404':
          $ref: '#/components/responses/RecordNotFound'
        '500':
          $ref: '#/components/responses/GenericError'
      security:
        -
          ApiKey: []
    delete:
      tags:
        - 'Administration: Users'
      description: 'Delete a single user.'
      operationId: deleteUser
      parameters:
        -
          name: id
          in: path
          description: 'User ID'
          required: true
          schema:
            type: integer
            format: int64
      responses:
        '200':
          $ref: '#/components/responses/Success'
        '403':
          $ref: '#/components/responses/AccessDenied'
        '404':
          $ref: '#/components/responses/RecordNotFound'
        '500':
          $ref: '#/components/responses/GenericError'
      security:
        -
          ApiKey: []
  /status:
    get:
      tags:
        - Miscellaneous
      description: 'Returns an affirmative response if the API is active.'
      operationId: bc32a129ca3e8ad2060b71bdd90da78d
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Api_SystemStatus'
  /time:
    get:
      tags:
        - Miscellaneous
      description: "Returns the time (with formatting) in GMT and the user's local time zone, if logged in."
      operationId: 3092a8238a915a0b6b324f2a90942a94
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Api_Time'
  /nowplaying:
    get:
      tags:
        - 'Now Playing'
      description: "Returns a full summary of all stations' current state."
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/Api_NowPlaying'
  '/nowplaying/{station_id}':
    get:
      tags:
        - 'Now Playing'
      description: "Returns a full summary of the specified station's current state."
      parameters:
        -
          $ref: '#/components/parameters/StationIdRequired'
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Api_NowPlaying'
        '404':
          $ref: '#/components/responses/RecordNotFound'
  '/station/{station_id}/art/{media_id}':
    get:
      tags:
        - 'Stations: Media'
      description: 'Returns the album art for a song, or a generic image.'
      parameters:
        -
          $ref: '#/components/parameters/StationIdRequired'
        -
          name: media_id
          in: path
          description: 'The station media unique ID'
          required: true
          schema:
            type: string
      responses:
        '200':
          description: 'The requested album artwork'
        '404':
          description: 'Image not found; generic filler image.'
    post:
      tags:
        - 'Stations: Media'
      description: 'Sets the album art for a track.'
      parameters:
        -
          $ref: '#/components/parameters/StationIdRequired'
        -
          name: id
          in: path
          description: 'Media ID'
          required: true
          schema:
            anyOf:
              -
                type: integer
                format: int64
              -
                type: string
      responses:
        '200':
          $ref: '#/components/responses/Success'
        '403':
          $ref: '#/components/responses/AccessDenied'
        '404':
          $ref: '#/components/responses/RecordNotFound'
        '500':
          $ref: '#/components/responses/GenericError'
      security:
        -
          ApiKey: []
    delete:
      tags:
        - 'Stations: Media'
      description: 'Removes the album art for a track.'
      parameters:
        -
          $ref: '#/components/parameters/StationIdRequired'
        -
          name: id
          in: path
          description: 'Media ID'
          required: true
          schema:
            anyOf:
              -
                type: integer
                format: int64
              -
                type: string
      responses:
        '200':
          $ref: '#/components/responses/Success'
        '403':
          $ref: '#/components/responses/AccessDenied'
        '404':
          $ref: '#/components/responses/RecordNotFound'
        '500':
          $ref: '#/components/responses/GenericError'
      security:
        -
          ApiKey: []
  '/station/{station_id}/fallback':
    get:
      tags:
        - 'Stations: General'
      description: 'Get the custom fallback track for a station.'
      parameters:
        -
          $ref: '#/components/parameters/StationIdRequired'
      responses:
        '200':
          description: Success
        '403':
          $ref: '#/components/responses/AccessDenied'
        '404':
          $ref: '#/components/responses/RecordNotFound'
        '500':
          $ref: '#/components/responses/GenericError'
      security:
        -
          ApiKey: []
    post:
      tags:
        - 'Stations: General'
      description: 'Update the custom fallback track for the station.'
      parameters:
        -
          $ref: '#/components/parameters/StationIdRequired'
      responses:
        '200':
          $ref: '#/components/responses/Success'
        '403':
          $ref: '#/components/responses/AccessDenied'
        '404':
          $ref: '#/components/responses/RecordNotFound'
        '500':
          $ref: '#/components/responses/GenericError'
      security:
        -
          ApiKey: []
    delete:
      tags:
        - 'Stations: General'
      description: 'Removes the custom fallback track for a station.'
      parameters:
        -
          $ref: '#/components/parameters/StationIdRequired'
      responses:
        '200':
          $ref: '#/components/responses/Success'
        '403':
          $ref: '#/components/responses/AccessDenied'
        '404':
          $ref: '#/components/responses/RecordNotFound'
        '500':
          $ref: '#/components/responses/GenericError'
      security:
        -
          ApiKey: []
  '/station/{station_id}/files':
    get:
      tags:
        - 'Stations: Media'
      description: 'List all current uploaded files.'
      operationId: getFiles
      parameters:
        -
          $ref: '#/components/parameters/StationIdRequired'
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/StationMedia'
        '403':
          $ref: '#/components/responses/AccessDenied'
        '500':
          $ref: '#/components/responses/GenericError'
      security:
        -
          ApiKey: []
    post:
      tags:
        - 'Stations: Media'
      description: 'Upload a new file.'
      operationId: addFile
      parameters:
        -
          $ref: '#/components/parameters/StationIdRequired'
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Api_UploadFile'
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/StationMedia'
        '403':
          $ref: '#/components/responses/AccessDenied'
        '500':
          $ref: '#/components/responses/GenericError'
      security:
        -
          ApiKey: []
  '/station/{station_id}/file/{id}':
    get:
      tags:
        - 'Stations: Media'
      description: 'Retrieve details for a single file.'
      operationId: getFile
      parameters:
        -
          $ref: '#/components/parameters/StationIdRequired'
        -
          name: id
          in: path
          description: 'Media ID'
          required: true
          schema:
            type: integer
            format: int64
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/StationMedia'
        '403':
          $ref: '#/components/responses/AccessDenied'
        '404':
          $ref: '#/components/responses/RecordNotFound'
        '500':
          $ref: '#/components/responses/GenericError'
      security:
        -
          ApiKey: []
    put:
      tags:
        - 'Stations: Media'
      description: 'Update details of a single file.'
      operationId: editFile
      parameters:
        -
          $ref: '#/components/parameters/StationIdRequired'
        -
          name: id
          in: path
          description: 'Media ID'
          required: true
          schema:
            type: integer
            format: int64
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/StationMedia'
      responses:
        '200':
          $ref: '#/components/responses/Success'
        '403':
          $ref: '#/components/responses/AccessDenied'
        '404':
          $ref: '#/components/responses/RecordNotFound'
        '500':
          $ref: '#/components/responses/GenericError'
      security:
        -
          ApiKey: []
    delete:
      tags:
        - 'Stations: Media'
      description: 'Delete a single file.'
      operationId: deleteFile
      parameters:
        -
          $ref: '#/components/parameters/StationIdRequired'
        -
          name: id
          in: path
          description: 'Media ID'
          required: true
          schema:
            type: integer
            format: int64
      responses:
        '200':
          $ref: '#/components/responses/Success'
        '403':
          $ref: '#/components/responses/AccessDenied'
        '404':
          $ref: '#/components/responses/RecordNotFound'
        '500':
          $ref: '#/components/responses/GenericError'
      security:
        -
          ApiKey: []
  '/station/{station_id}/history':
    get:
      tags:
        - 'Stations: History'
      description: 'Return song playback history items for a given station.'
      operationId: getStationHistory
      parameters:
        -
          $ref: '#/components/parameters/StationIdRequired'
        -
          name: start
          in: query
          description: 'The start date for records, in YYYY-MM-DD format.'
          required: false
          schema:
            type: string
        -
          name: end
          in: query
          description: 'The end date for records, in YYYY-MM-DD format.'
          required: false
          schema:
            type: string
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/Api_DetailedSongHistory'
        '403':
          $ref: '#/components/responses/AccessDenied'
        '404':
          $ref: '#/components/responses/RecordNotFound'
        '500':
          $ref: '#/components/responses/GenericError'
      security:
        -
          ApiKey: []
  '/station/{station_id}/hls_streams':
    get:
      tags:
        - 'Stations: HLS Streams'
      description: 'List all current HLS streams.'
      operationId: getHlsStreams
      parameters:
        -
          $ref: '#/components/parameters/StationIdRequired'
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/StationMount'
        '403':
          $ref: '#/components/responses/AccessDenied'
        '500':
          $ref: '#/components/responses/GenericError'
      security:
        -
          ApiKey: []
    post:
      tags:
        - 'Stations: HLS Streams'
      description: 'Create a new HLS stream.'
      operationId: addHlsStream
      parameters:
        -
          $ref: '#/components/parameters/StationIdRequired'
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/StationMount'
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/StationMount'
        '403':
          $ref: '#/components/responses/AccessDenied'
        '500':
          $ref: '#/components/responses/GenericError'
      security:
        -
          ApiKey: []
  '/station/{station_id}/hls_stream/{id}':
    get:
      tags:
        - 'Stations: HLS Streams'
      description: 'Retrieve details for a single HLS stream.'
      operationId: getHlsStream
      parameters:
        -
          $ref: '#/components/parameters/StationIdRequired'
        -
          name: id
          in: path
          description: 'HLS Stream ID'
          required: true
          schema:
            type: integer
            format: int64
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/StationMount'
        '403':
          $ref: '#/components/responses/AccessDenied'
        '404':
          $ref: '#/components/responses/RecordNotFound'
        '500':
          $ref: '#/components/responses/GenericError'
      security:
        -
          ApiKey: []
    put:
      tags:
        - 'Stations: HLS Streams'
      description: 'Update details of a single HLS stream.'
      operationId: editHlsStream
      parameters:
        -
          $ref: '#/components/parameters/StationIdRequired'
        -
          name: id
          in: path
          description: 'HLS Stream ID'
          required: true
          schema:
            type: integer
            format: int64
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/StationMount'
      responses:
        '200':
          $ref: '#/components/responses/Success'
        '403':
          $ref: '#/components/responses/AccessDenied'
        '404':
          $ref: '#/components/responses/RecordNotFound'
        '500':
          $ref: '#/components/responses/GenericError'
      security:
        -
          ApiKey: []
    delete:
      tags:
        - 'Stations: HLS Streams'
      description: 'Delete a single HLS stream.'
      operationId: deleteHlsStream
      parameters:
        -
          $ref: '#/components/parameters/StationIdRequired'
        -
          name: id
          in: path
          description: 'HLS Stream ID'
          required: true
          schema:
            type: integer
            format: int64
      responses:
        '200':
          $ref: '#/components/responses/Success'
        '403':
          $ref: '#/components/responses/AccessDenied'
        '404':
          $ref: '#/components/responses/RecordNotFound'
        '500':
          $ref: '#/components/responses/GenericError'
      security:
        -
          ApiKey: []
  /stations:
    get:
      tags:
        - 'Stations: General'
      description: 'Returns a list of stations.'
      operationId: getStations
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/Api_NowPlaying_Station'
  '/station/{station_id}':
    get:
      tags:
        - 'Stations: General'
      description: 'Return information about a single station.'
      operationId: getStation
      parameters:
        -
          $ref: '#/components/parameters/StationIdRequired'
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Api_NowPlaying_Station'
        '404':
          $ref: '#/components/responses/RecordNotFound'
  '/station/{station_id}/listeners':
    get:
      tags:
        - 'Stations: Listeners'
      description: 'Return detailed information about current listeners.'
      operationId: getStationListeners
      parameters:
        -
          $ref: '#/components/parameters/StationIdRequired'
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/Api_Listener'
        '403':
          $ref: '#/components/responses/AccessDenied'
        '404':
          $ref: '#/components/responses/RecordNotFound'
        '500':
          $ref: '#/components/responses/GenericError'
      security:
        -
          ApiKey: []
  '/station/{station_id}/mount/{id}/intro':
    get:
      tags:
        - 'Stations: Mount Points'
      description: 'Get the intro track for a mount point.'
      parameters:
        -
          $ref: '#/components/parameters/StationIdRequired'
        -
          name: id
          in: path
          description: 'Mount Point ID'
          required: true
          schema:
            type: integer
            format: int64
      responses:
        '200':
          description: Success
        '403':
          $ref: '#/components/responses/AccessDenied'
        '404':
          $ref: '#/components/responses/RecordNotFound'
        '500':
          $ref: '#/components/responses/GenericError'
      security:
        -
          ApiKey: []
    post:
      tags:
        - 'Stations: Mount Points'
      description: 'Update the intro track for a mount point.'
      parameters:
        -
          $ref: '#/components/parameters/StationIdRequired'
        -
          name: id
          in: path
          description: 'Mount Point ID'
          required: true
          schema:
            type: integer
            format: int64
      responses:
        '200':
          $ref: '#/components/responses/Success'
        '403':
          $ref: '#/components/responses/AccessDenied'
        '404':
          $ref: '#/components/responses/RecordNotFound'
        '500':
          $ref: '#/components/responses/GenericError'
      security:
        -
          ApiKey: []
    delete:
      tags:
        - 'Stations: Mount Points'
      description: 'Removes the intro track for a mount point.'
      parameters:
        -
          $ref: '#/components/parameters/StationIdRequired'
        -
          name: id
          in: path
          description: 'Mount Point ID'
          required: true
          schema:
            type: integer
            format: int64
      responses:
        '200':
          $ref: '#/components/responses/Success'
        '403':
          $ref: '#/components/responses/AccessDenied'
        '404':
          $ref: '#/components/responses/RecordNotFound'
        '500':
          $ref: '#/components/responses/GenericError'
      security:
        -
          ApiKey: []
  '/station/{station_id}/mounts':
    get:
      tags:
        - 'Stations: Mount Points'
      description: 'List all current mount points.'
      operationId: getStationMounts
      parameters:
        -
          $ref: '#/components/parameters/StationIdRequired'
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/StationMount'
        '403':
          $ref: '#/components/responses/AccessDenied'
        '500':
          $ref: '#/components/responses/GenericError'
      security:
        -
          ApiKey: []
    post:
      tags:
        - 'Stations: Mount Points'
      description: 'Create a new mount point.'
      operationId: addMount
      parameters:
        -
          $ref: '#/components/parameters/StationIdRequired'
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/StationMount'
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/StationMount'
        '403':
          $ref: '#/components/responses/AccessDenied'
        '500':
          $ref: '#/components/responses/GenericError'
      security:
        -
          ApiKey: []
  '/station/{station_id}/mount/{id}':
    get:
      tags:
        - 'Stations: Mount Points'
      description: 'Retrieve details for a single mount point.'
      operationId: getMount
      parameters:
        -
          $ref: '#/components/parameters/StationIdRequired'
        -
          name: id
          in: path
          description: 'Streamer ID'
          required: true
          schema:
            type: integer
            format: int64
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/StationMount'
        '403':
          $ref: '#/components/responses/AccessDenied'
        '404':
          $ref: '#/components/responses/RecordNotFound'
        '500':
          $ref: '#/components/responses/GenericError'
      security:
        -
          ApiKey: []
    put:
      tags:
        - 'Stations: Mount Points'
      description: 'Update details of a single mount point.'
      operationId: editMount
      parameters:
        -
          $ref: '#/components/parameters/StationIdRequired'
        -
          name: id
          in: path
          description: 'Streamer ID'
          required: true
          schema:
            type: integer
            format: int64
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/StationMount'
      responses:
        '200':
          $ref: '#/components/responses/Success'
        '403':
          $ref: '#/components/responses/AccessDenied'
        '404':
          $ref: '#/components/responses/RecordNotFound'
        '500':
          $ref: '#/components/responses/GenericError'
      security:
        -
          ApiKey: []
    delete:
      tags:
        - 'Stations: Mount Points'
      description: 'Delete a single mount point.'
      operationId: deleteMount
      parameters:
        -
          $ref: '#/components/parameters/StationIdRequired'
        -
          name: id
          in: path
          description: 'StationMount ID'
          required: true
          schema:
            type: integer
            format: int64
      responses:
        '200':
          $ref: '#/components/responses/Success'
        '403':
          $ref: '#/components/responses/AccessDenied'
        '404':
          $ref: '#/components/responses/RecordNotFound'
        '500':
          $ref: '#/components/responses/GenericError'
      security:
        -
          ApiKey: []
  '/station/{station_id}/playlists':
    get:
      tags:
        - 'Stations: Playlists'
      description: 'List all current playlists.'
      operationId: getPlaylists
      parameters:
        -
          $ref: '#/components/parameters/StationIdRequired'
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/StationPlaylist'
        '403':
          $ref: '#/components/responses/AccessDenied'
        '500':
          $ref: '#/components/responses/GenericError'
      security:
        -
          ApiKey: []
    post:
      tags:
        - 'Stations: Playlists'
      description: 'Create a new playlist.'
      operationId: addPlaylist
      parameters:
        -
          $ref: '#/components/parameters/StationIdRequired'
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/StationPlaylist'
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/StationPlaylist'
        '403':
          $ref: '#/components/responses/AccessDenied'
        '500':
          $ref: '#/components/responses/GenericError'
      security:
        -
          ApiKey: []
  '/station/{station_id}/playlist/{id}':
    get:
      tags:
        - 'Stations: Playlists'
      description: 'Retrieve details for a single playlist.'
      operationId: getPlaylist
      parameters:
        -
          $ref: '#/components/parameters/StationIdRequired'
        -
          name: id
          in: path
          description: 'Playlist ID'
          required: true
          schema:
            type: integer
            format: int64
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/StationPlaylist'
        '403':
          $ref: '#/components/responses/AccessDenied'
        '404':
          $ref: '#/components/responses/RecordNotFound'
        '500':
          $ref: '#/components/responses/GenericError'
      security:
        -
          ApiKey: []
    put:
      tags:
        - 'Stations: Playlists'
      description: 'Update details of a single playlist.'
      operationId: editPlaylist
      parameters:
        -
          $ref: '#/components/parameters/StationIdRequired'
        -
          name: id
          in: path
          description: 'Playlist ID'
          required: true
          schema:
            type: integer
            format: int64
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/StationPlaylist'
      responses:
        '200':
          $ref: '#/components/responses/Success'
        '403':
          $ref: '#/components/responses/AccessDenied'
        '404':
          $ref: '#/components/responses/RecordNotFound'
        '500':
          $ref: '#/components/responses/GenericError'
      security:
        -
          ApiKey: []
    delete:
      tags:
        - 'Stations: Playlists'
      description: 'Delete a single playlist relay.'
      operationId: deletePlaylist
      parameters:
        -
          $ref: '#/components/parameters/StationIdRequired'
        -
          name: id
          in: path
          description: 'Playlist ID'
          required: true
          schema:
            type: integer
            format: int64
      responses:
        '200':
          $ref: '#/components/responses/Success'
        '403':
          $ref: '#/components/responses/AccessDenied'
        '404':
          $ref: '#/components/responses/RecordNotFound'
        '500':
          $ref: '#/components/responses/GenericError'
      security:
        -
          ApiKey: []
  '/station/{station_id}/podcast/{podcast_id}/episodes':
    get:
      tags:
        - 'Stations: Podcasts'
      description: 'List all current episodes for a given podcast ID.'
      operationId: getEpisodes
      parameters:
        -
          $ref: '#/components/parameters/StationIdRequired'
        -
          name: podcast_id
          in: path
          description: 'Podcast ID'
          required: true
          schema:
            type: string
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/Api_PodcastEpisode'
        '403':
          $ref: '#/components/responses/AccessDenied'
        '404':
          $ref: '#/components/responses/RecordNotFound'
        '500':
          $ref: '#/components/responses/GenericError'
      security:
        -
          ApiKey: []
    post:
      tags:
        - 'Stations: Podcasts'
      description: 'Create a new podcast episode.'
      operationId: addEpisode
      parameters:
        -
          $ref: '#/components/parameters/StationIdRequired'
        -
          name: podcast_id
          in: path
          description: 'Podcast ID'
          required: true
          schema:
            type: string
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Api_PodcastEpisode'
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Api_PodcastEpisode'
        '403':
          $ref: '#/components/responses/AccessDenied'
        '404':
          $ref: '#/components/responses/RecordNotFound'
        '500':
          $ref: '#/components/responses/GenericError'
      security:
        -
          ApiKey: []
  '/station/{station_id}/podcast/{podcast_id}/episode/{id}':
    get:
      tags:
        - 'Stations: Podcasts'
      description: 'Retrieve details for a single podcast episode.'
      operationId: getEpisode
      parameters:
        -
          $ref: '#/components/parameters/StationIdRequired'
        -
          name: podcast_id
          in: path
          description: 'Podcast ID'
          required: true
          schema:
            type: string
        -
          name: id
          in: path
          description: 'Podcast Episode ID'
          required: true
          schema:
            type: string
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Api_PodcastEpisode'
        '403':
          $ref: '#/components/responses/AccessDenied'
        '404':
          $ref: '#/components/responses/RecordNotFound'
        '500':
          $ref: '#/components/responses/GenericError'
      security:
        -
          ApiKey: []
    put:
      tags:
        - 'Stations: Podcasts'
      description: 'Update details of a single podcast episode.'
      operationId: editEpisode
      parameters:
        -
          $ref: '#/components/parameters/StationIdRequired'
        -
          name: podcast_id
          in: path
          description: 'Podcast ID'
          required: true
          schema:
            type: string
        -
          name: id
          in: path
          description: 'Podcast Episode ID'
          required: true
          schema:
            type: string
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Api_PodcastEpisode'
      responses:
        '200':
          $ref: '#/components/responses/Success'
        '403':
          $ref: '#/components/responses/AccessDenied'
        '404':
          $ref: '#/components/responses/RecordNotFound'
        '500':
          $ref: '#/components/responses/GenericError'
      security:
        -
          ApiKey: []
    delete:
      tags:
        - 'Stations: Podcasts'
      description: 'Delete a single podcast episode.'
      operationId: deleteEpisode
      parameters:
        -
          $ref: '#/components/parameters/StationIdRequired'
        -
          name: podcast_id
          in: path
          description: 'Podcast ID'
          required: true
          schema:
            type: string
        -
          name: id
          in: path
          description: 'Podcast Episode ID'
          required: true
          schema:
            type: string
      responses:
        '200':
          $ref: '#/components/responses/Success'
        '403':
          $ref: '#/components/responses/AccessDenied'
        '404':
          $ref: '#/components/responses/RecordNotFound'
        '500':
          $ref: '#/components/responses/GenericError'
      security:
        -
          ApiKey: []
  '/station/{station_id}/podcast/{podcast_id}/art':
    get:
      tags:
        - 'Stations: Podcasts'
      description: 'Gets the album art for a podcast.'
      parameters:
        -
          $ref: '#/components/parameters/StationIdRequired'
        -
          name: podcast_id
          in: path
          description: 'Podcast ID'
          required: true
          schema:
            type: string
      responses:
        '200':
          description: Success
        '403':
          $ref: '#/components/responses/AccessDenied'
        '404':
          $ref: '#/components/responses/RecordNotFound'
        '500':
          $ref: '#/components/responses/GenericError'
      security:
        -
          ApiKey: []
    post:
      tags:
        - 'Stations: Podcasts'
      description: 'Sets the album art for a podcast.'
      parameters:
        -
          $ref: '#/components/parameters/StationIdRequired'
        -
          name: podcast_id
          in: path
          description: 'Podcast ID'
          required: true
          schema:
            type: string
      responses:
        '200':
          $ref: '#/components/responses/Success'
        '403':
          $ref: '#/components/responses/AccessDenied'
        '404':
          $ref: '#/components/responses/RecordNotFound'
        '500':
          $ref: '#/components/responses/GenericError'
      security:
        -
          ApiKey: []
    delete:
      tags:
        - 'Stations: Podcasts'
      description: 'Removes the album art for a podcast.'
      parameters:
        -
          $ref: '#/components/parameters/StationIdRequired'
        -
          name: podcast_id
          in: path
          description: 'Podcast ID'
          required: true
          schema:
            type: string
      responses:
        '200':
          $ref: '#/components/responses/Success'
        '403':
          $ref: '#/components/responses/AccessDenied'
        '404':
          $ref: '#/components/responses/RecordNotFound'
        '500':
          $ref: '#/components/responses/GenericError'
      security:
        -
          ApiKey: []
  '/station/{station_id}/podcast/{podcast_id}/episode/{episode_id}/art':
    get:
      tags:
        - 'Stations: Podcasts'
      description: 'Gets the album art for a podcast episode.'
      parameters:
        -
          $ref: '#/components/parameters/StationIdRequired'
        -
          name: podcast_id
          in: path
          description: 'Podcast ID'
          required: true
          schema:
            type: string
        -
          name: episode_id
          in: path
          description: 'Podcast Episode ID'
          required: true
          schema:
            type: string
      responses:
        '200':
          description: Success
        '403':
          $ref: '#/components/responses/AccessDenied'
        '404':
          $ref: '#/components/responses/RecordNotFound'
        '500':
          $ref: '#/components/responses/GenericError'
      security:
        -
          ApiKey: []
    post:
      tags:
        - 'Stations: Podcasts'
      description: 'Sets the album art for a podcast episode.'
      parameters:
        -
          $ref: '#/components/parameters/StationIdRequired'
        -
          name: podcast_id
          in: path
          description: 'Podcast ID'
          required: true
          schema:
            type: string
        -
          name: episode_id
          in: path
          description: 'Podcast Episode ID'
          required: true
          schema:
            type: string
      responses:
        '200':
          $ref: '#/components/responses/Success'
        '403':
          $ref: '#/components/responses/AccessDenied'
        '404':
          $ref: '#/components/responses/RecordNotFound'
        '500':
          $ref: '#/components/responses/GenericError'
      security:
        -
          ApiKey: []
    delete:
      tags:
        - 'Stations: Podcasts'
      description: 'Removes the album art for a podcast episode.'
      parameters:
        -
          $ref: '#/components/parameters/StationIdRequired'
        -
          name: podcast_id
          in: path
          description: 'Podcast ID'
          required: true
          schema:
            type: string
        -
          name: episode_id
          in: path
          description: 'Podcast Episode ID'
          required: true
          schema:
            type: string
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Api_Status'
        '404':
          description: 'Record not found'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Api_Error'
        '403':
          description: 'Access denied'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Api_Error'
      security:
        -
          ApiKey: []
  '/station/{station_id}/podcast/{podcast_id}/episode/{episode_id}/media':
    get:
      tags:
        - 'Stations: Podcasts'
      description: 'Gets the media for a podcast episode.'
      parameters:
        -
          $ref: '#/components/parameters/StationIdRequired'
        -
          name: podcast_id
          in: path
          description: 'Podcast ID'
          required: true
          schema:
            type: string
        -
          name: episode_id
          in: path
          description: 'Podcast Episode ID'
          required: true
          schema:
            type: string
      responses:
        '200':
          description: Success
        '403':
          $ref: '#/components/responses/AccessDenied'
        '404':
          $ref: '#/components/responses/RecordNotFound'
        '500':
          $ref: '#/components/responses/GenericError'
      security:
        -
          ApiKey: []
    post:
      tags:
        - 'Stations: Podcasts'
      description: 'Sets the media for a podcast episode.'
      parameters:
        -
          $ref: '#/components/parameters/StationIdRequired'
        -
          name: podcast_id
          in: path
          description: 'Podcast ID'
          required: true
          schema:
            type: string
        -
          name: episode_id
          in: path
          description: 'Podcast Episode ID'
          required: true
          schema:
            type: string
      responses:
        '200':
          $ref: '#/components/responses/Success'
        '403':
          $ref: '#/components/responses/AccessDenied'
        '404':
          $ref: '#/components/responses/RecordNotFound'
        '500':
          $ref: '#/components/responses/GenericError'
      security:
        -
          ApiKey: []
    delete:
      tags:
        - 'Stations: Podcasts'
      description: 'Removes the media for a podcast episode.'
      parameters:
        -
          $ref: '#/components/parameters/StationIdRequired'
        -
          name: podcast_id
          in: path
          description: 'Podcast ID'
          required: true
          schema:
            type: string
        -
          name: episode_id
          in: path
          description: 'Podcast Episode ID'
          required: true
          schema:
            type: string
      responses:
        '200':
          $ref: '#/components/responses/Success'
        '403':
          $ref: '#/components/responses/AccessDenied'
        '404':
          $ref: '#/components/responses/RecordNotFound'
        '500':
          $ref: '#/components/responses/GenericError'
      security:
        -
          ApiKey: []
  '/station/{station_id}/podcasts':
    get:
      tags:
        - 'Stations: Podcasts'
      description: 'List all current podcasts.'
      operationId: getPodcasts
      parameters:
        -
          $ref: '#/components/parameters/StationIdRequired'
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/Api_Podcast'
        '403':
          $ref: '#/components/responses/AccessDenied'
        '404':
          $ref: '#/components/responses/RecordNotFound'
        '500':
          $ref: '#/components/responses/GenericError'
      security:
        -
          ApiKey: []
    post:
      tags:
        - 'Stations: Podcasts'
      description: 'Create a new podcast.'
      operationId: addPodcast
      parameters:
        -
          $ref: '#/components/parameters/StationIdRequired'
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Api_Podcast'
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Api_Podcast'
        '403':
          $ref: '#/components/responses/AccessDenied'
        '404':
          $ref: '#/components/responses/RecordNotFound'
        '500':
          $ref: '#/components/responses/GenericError'
      security:
        -
          ApiKey: []
  '/station/{station_id}/podcast/{id}':
    get:
      tags:
        - 'Stations: Podcasts'
      description: 'Retrieve details for a single podcast.'
      operationId: getPodcast
      parameters:
        -
          $ref: '#/components/parameters/StationIdRequired'
        -
          name: id
          in: path
          description: 'Podcast ID'
          required: true
          schema:
            type: string
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Api_Podcast'
        '403':
          $ref: '#/components/responses/AccessDenied'
        '404':
          $ref: '#/components/responses/RecordNotFound'
        '500':
          $ref: '#/components/responses/GenericError'
      security:
        -
          ApiKey: []
    put:
      tags:
        - 'Stations: Podcasts'
      description: 'Update details of a single podcast.'
      operationId: editPodcast
      parameters:
        -
          $ref: '#/components/parameters/StationIdRequired'
        -
          name: id
          in: path
          description: 'Podcast ID'
          required: true
          schema:
            type: string
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Api_Podcast'
      responses:
        '200':
          $ref: '#/components/responses/Success'
        '403':
          $ref: '#/components/responses/AccessDenied'
        '404':
          $ref: '#/components/responses/RecordNotFound'
        '500':
          $ref: '#/components/responses/GenericError'
      security:
        -
          ApiKey: []
    delete:
      tags:
        - 'Stations: Podcasts'
      description: 'Delete a single podcast.'
      operationId: deletePodcast
      parameters:
        -
          $ref: '#/components/parameters/StationIdRequired'
        -
          name: id
          in: path
          description: 'Podcast ID'
          required: true
          schema:
            type: string
      responses:
        '200':
          $ref: '#/components/responses/Success'
        '403':
          $ref: '#/components/responses/AccessDenied'
        '404':
          $ref: '#/components/responses/RecordNotFound'
        '500':
          $ref: '#/components/responses/GenericError'
      security:
        -
          ApiKey: []
  '/station/{station_id}/queue':
    get:
      tags:
        - 'Stations: Queue'
      description: 'Return information about the upcoming song playback queue.'
      operationId: getQueue
      parameters:
        -
          $ref: '#/components/parameters/StationIdRequired'
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/Api_StationQueueDetailed'
        '403':
          $ref: '#/components/responses/AccessDenied'
        '404':
          $ref: '#/components/responses/RecordNotFound'
        '500':
          $ref: '#/components/responses/GenericError'
      security:
        -
          ApiKey: []
  '/station/{station_id}/queue/{id}':
    get:
      tags:
        - 'Stations: Queue'
      description: 'Retrieve details of a single queued item.'
      operationId: getQueueItem
      parameters:
        -
          $ref: '#/components/parameters/StationIdRequired'
        -
          name: id
          in: path
          description: 'Queue Item ID'
          required: true
          schema:
            type: integer
            format: int64
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Api_StationQueueDetailed'
        '403':
          $ref: '#/components/responses/AccessDenied'
        '404':
          $ref: '#/components/responses/RecordNotFound'
        '500':
          $ref: '#/components/responses/GenericError'
      security:
        -
          ApiKey: []
    delete:
      tags:
        - 'Stations: Queue'
      description: 'Delete a single queued item.'
      operationId: deleteQueueItem
      parameters:
        -
          $ref: '#/components/parameters/StationIdRequired'
        -
          name: id
          in: path
          description: 'Queue Item ID'
          required: true
          schema:
            type: integer
            format: int64
      responses:
        '200':
          $ref: '#/components/responses/Success'
        '403':
          $ref: '#/components/responses/AccessDenied'
        '404':
          $ref: '#/components/responses/RecordNotFound'
        '500':
          $ref: '#/components/responses/GenericError'
      security:
        -
          ApiKey: []
  '/station/{station_id}/remotes':
    get:
      tags:
        - 'Stations: Remote Relays'
      description: 'List all current remote relays.'
      operationId: getRelays
      parameters:
        -
          $ref: '#/components/parameters/StationIdRequired'
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/Api_StationRemote'
        '403':
          $ref: '#/components/responses/AccessDenied'
        '404':
          $ref: '#/components/responses/RecordNotFound'
        '500':
          $ref: '#/components/responses/GenericError'
      security:
        -
          ApiKey: []
    post:
      tags:
        - 'Stations: Remote Relays'
      description: 'Create a new remote relay.'
      operationId: addRelay
      parameters:
        -
          $ref: '#/components/parameters/StationIdRequired'
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Api_StationRemote'
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Api_StationRemote'
        '403':
          $ref: '#/components/responses/AccessDenied'
        '404':
          $ref: '#/components/responses/RecordNotFound'
        '500':
          $ref: '#/components/responses/GenericError'
      security:
        -
          ApiKey: []
  '/station/{station_id}/remote/{id}':
    get:
      tags:
        - 'Stations: Remote Relays'
      description: 'Retrieve details for a single remote relay.'
      operationId: getRelay
      parameters:
        -
          $ref: '#/components/parameters/StationIdRequired'
        -
          name: id
          in: path
          description: 'Remote Relay ID'
          required: true
          schema:
            type: integer
            format: int64
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Api_StationRemote'
        '403':
          $ref: '#/components/responses/AccessDenied'
        '404':
          $ref: '#/components/responses/RecordNotFound'
        '500':
          $ref: '#/components/responses/GenericError'
      security:
        -
          ApiKey: []
    put:
      tags:
        - 'Stations: Remote Relays'
      description: 'Update details of a single remote relay.'
      operationId: editRelay
      parameters:
        -
          $ref: '#/components/parameters/StationIdRequired'
        -
          name: id
          in: path
          description: 'Remote Relay ID'
          required: true
          schema:
            type: integer
            format: int64
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Api_StationRemote'
      responses:
        '200':
          $ref: '#/components/responses/Success'
        '403':
          $ref: '#/components/responses/AccessDenied'
        '404':
          $ref: '#/components/responses/RecordNotFound'
        '500':
          $ref: '#/components/responses/GenericError'
      security:
        -
          ApiKey: []
    delete:
      tags:
        - 'Stations: Remote Relays'
      description: 'Delete a single remote relay.'
      operationId: deleteRelay
      parameters:
        -
          $ref: '#/components/parameters/StationIdRequired'
        -
          name: id
          in: path
          description: 'Remote Relay ID'
          required: true
          schema:
            type: integer
            format: int64
      responses:
        '200':
          $ref: '#/components/responses/Success'
        '403':
          $ref: '#/components/responses/AccessDenied'
        '404':
          $ref: '#/components/responses/RecordNotFound'
        '500':
          $ref: '#/components/responses/GenericError'
      security:
        -
          ApiKey: []
  '/station/{station_id}/requests':
    get:
      tags:
        - 'Stations: Song Requests'
      description: 'Return a list of requestable songs.'
      operationId: getRequestableSongs
      parameters:
        -
          $ref: '#/components/parameters/StationIdRequired'
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/Api_StationRequest'
        '403':
          $ref: '#/components/responses/AccessDenied'
        '404':
          $ref: '#/components/responses/RecordNotFound'
        '500':
          $ref: '#/components/responses/GenericError'
  '/station/{station_id}/request/{request_id}':
    post:
      tags:
        - 'Stations: Song Requests'
      description: 'Submit a song request.'
      operationId: submitSongRequest
      parameters:
        -
          $ref: '#/components/parameters/StationIdRequired'
        -
          name: request_id
          in: path
          description: 'The requestable song ID'
          required: true
          schema:
            type: string
      responses:
        '200':
          $ref: '#/components/responses/Success'
        '403':
          $ref: '#/components/responses/AccessDenied'
        '404':
          $ref: '#/components/responses/RecordNotFound'
        '500':
          $ref: '#/components/responses/GenericError'
  '/station/{station_id}/schedule':
    get:
      tags:
        - 'Stations: Schedules'
      description: 'Return upcoming and currently ongoing schedule entries.'
      operationId: getSchedule
      parameters:
        -
          $ref: '#/components/parameters/StationIdRequired'
        -
          name: now
          in: query
          description: 'The date/time to compare schedule items to. Defaults to the current date and time.'
          required: false
          schema:
            type: string
        -
          name: rows
          in: query
          description: 'The number of upcoming/ongoing schedule entries to return. Defaults to 5.'
          required: false
          schema:
            type: integer
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/Api_StationSchedule'
        '404':
          $ref: '#/components/responses/RecordNotFound'
        '500':
          $ref: '#/components/responses/GenericError'
  '/station/{station_id}/status':
    get:
      tags:
        - 'Stations: Service Control'
      description: 'Retrieve the current status of all serivces associated with the radio broadcast.'
      operationId: getServiceStatus
      parameters:
        -
          $ref: '#/components/parameters/StationIdRequired'
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Api_StationServiceStatus'
        '403':
          $ref: '#/components/responses/AccessDenied'
        '404':
          $ref: '#/components/responses/RecordNotFound'
        '500':
          $ref: '#/components/responses/GenericError'
      security:
        -
          ApiKey: []
  '/station/{station_id}/restart':
    post:
      tags:
        - 'Stations: Service Control'
      description: 'Restart all services associated with the radio broadcast.'
      operationId: restartServices
      parameters:
        -
          $ref: '#/components/parameters/StationIdRequired'
      responses:
        '200':
          $ref: '#/components/responses/Success'
        '403':
          $ref: '#/components/responses/AccessDenied'
        '404':
          $ref: '#/components/responses/RecordNotFound'
        '500':
          $ref: '#/components/responses/GenericError'
      security:
        -
          ApiKey: []
  '/station/{station_id}/frontend/{action}':
    post:
      tags:
        - 'Stations: Service Control'
      description: 'Perform service control actions on the radio frontend (Icecast, Shoutcast, etc.)'
      operationId: doFrontendServiceAction
      parameters:
        -
          $ref: '#/components/parameters/StationIdRequired'
        -
          name: action
          in: path
          description: 'The action to perform (start, stop, restart)'
          required: false
          schema:
            type: string
            default: restart
      responses:
        '200':
          $ref: '#/components/responses/Success'
        '403':
          $ref: '#/components/responses/AccessDenied'
        '404':
          $ref: '#/components/responses/RecordNotFound'
        '500':
          $ref: '#/components/responses/GenericError'
      security:
        -
          ApiKey: []
  '/station/{station_id}/backend/{action}':
    post:
      tags:
        - 'Stations: Service Control'
      description: 'Perform service control actions on the radio backend (Liquidsoap)'
      operationId: doBackendServiceAction
      parameters:
        -
          $ref: '#/components/parameters/StationIdRequired'
        -
          name: action
          in: path
          description: 'The action to perform (for all: start, stop, restart, skip, disconnect)'
          required: false
          schema:
            type: string
            default: restart
      responses:
        '200':
          $ref: '#/components/responses/Success'
        '403':
          $ref: '#/components/responses/AccessDenied'
        '404':
          $ref: '#/components/responses/RecordNotFound'
        '500':
          $ref: '#/components/responses/GenericError'
      security:
        -
          ApiKey: []
  '/station/{station_id}/sftp-users':
    get:
      tags:
        - 'Stations: SFTP Users'
      description: 'List all current SFTP users.'
      operationId: getSftpUsers
      parameters:
        -
          $ref: '#/components/parameters/StationIdRequired'
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/SftpUser'
        '403':
          $ref: '#/components/responses/AccessDenied'
        '404':
          $ref: '#/components/responses/RecordNotFound'
        '500':
          $ref: '#/components/responses/GenericError'
      security:
        -
          ApiKey: []
    post:
      tags:
        - 'Stations: SFTP Users'
      description: 'Create a new SFTP user.'
      operationId: addSftpUser
      parameters:
        -
          $ref: '#/components/parameters/StationIdRequired'
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SftpUser'
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SftpUser'
        '403':
          $ref: '#/components/responses/AccessDenied'
        '404':
          $ref: '#/components/responses/RecordNotFound'
        '500':
          $ref: '#/components/responses/GenericError'
      security:
        -
          ApiKey: []
  '/station/{station_id}/sftp-user/{id}':
    get:
      tags:
        - 'Stations: SFTP Users'
      description: 'Retrieve details for a single SFTP user.'
      operationId: getSftpUser
      parameters:
        -
          $ref: '#/components/parameters/StationIdRequired'
        -
          name: id
          in: path
          description: 'SFTP User ID'
          required: true
          schema:
            type: integer
            format: int64
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SftpUser'
        '403':
          $ref: '#/components/responses/AccessDenied'
        '404':
          $ref: '#/components/responses/RecordNotFound'
        '500':
          $ref: '#/components/responses/GenericError'
      security:
        -
          ApiKey: []
    put:
      tags:
        - 'Stations: SFTP Users'
      description: 'Update details of a single SFTP user.'
      operationId: editSftpUser
      parameters:
        -
          $ref: '#/components/parameters/StationIdRequired'
        -
          name: id
          in: path
          description: 'Remote Relay ID'
          required: true
          schema:
            type: integer
            format: int64
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/SftpUser'
      responses:
        '200':
          $ref: '#/components/responses/Success'
        '403':
          $ref: '#/components/responses/AccessDenied'
        '404':
          $ref: '#/components/responses/RecordNotFound'
        '500':
          $ref: '#/components/responses/GenericError'
      security:
        -
          ApiKey: []
    delete:
      tags:
        - 'Stations: SFTP Users'
      description: 'Delete a single remote relay.'
      operationId: deleteSftpUser
      parameters:
        -
          $ref: '#/components/parameters/StationIdRequired'
        -
          name: id
          in: path
          description: 'Remote Relay ID'
          required: true
          schema:
            type: integer
            format: int64
      responses:
        '200':
          $ref: '#/components/responses/Success'
        '403':
          $ref: '#/components/responses/AccessDenied'
        '404':
          $ref: '#/components/responses/RecordNotFound'
        '500':
          $ref: '#/components/responses/GenericError'
      security:
        -
          ApiKey: []
  '/station/{station_id}/stereo-tool-configuration':
    get:
      tags:
        - 'Stations: Broadcasting'
      description: 'Get the Stereo Tool configuration file for a station.'
      parameters:
        -
          $ref: '#/components/parameters/StationIdRequired'
      responses:
        '200':
          description: Success
        '403':
          $ref: '#/components/responses/AccessDenied'
        '404':
          $ref: '#/components/responses/RecordNotFound'
        '500':
          $ref: '#/components/responses/GenericError'
      security:
        -
          ApiKey: []
    post:
      tags:
        - 'Stations: Broadcasting'
      description: 'Update the Stereo Tool configuration file for a station.'
      parameters:
        -
          $ref: '#/components/parameters/StationIdRequired'
      responses:
        '200':
          $ref: '#/components/responses/Success'
        '403':
          $ref: '#/components/responses/AccessDenied'
        '404':
          $ref: '#/components/responses/RecordNotFound'
        '500':
          $ref: '#/components/responses/GenericError'
      security:
        -
          ApiKey: []
    delete:
      tags:
        - 'Stations: Broadcasting'
      description: 'Removes the Stereo Tool configuration file for a station.'
      parameters:
        -
          $ref: '#/components/parameters/StationIdRequired'
      responses:
        '200':
          $ref: '#/components/responses/Success'
        '403':
          $ref: '#/components/responses/AccessDenied'
        '404':
          $ref: '#/components/responses/RecordNotFound'
        '500':
          $ref: '#/components/responses/GenericError'
      security:
        -
          ApiKey: []
  '/station/{station_id}/streamers':
    get:
      tags:
        - 'Stations: Streamers/DJs'
      description: 'List all current Streamer/DJ accounts for the specified station.'
      operationId: getStreamers
      parameters:
        -
          $ref: '#/components/parameters/StationIdRequired'
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/StationStreamer'
        '403':
          $ref: '#/components/responses/AccessDenied'
        '404':
          $ref: '#/components/responses/RecordNotFound'
        '500':
          $ref: '#/components/responses/GenericError'
      security:
        -
          ApiKey: []
    post:
      tags:
        - 'Stations: Streamers/DJs'
      description: 'Create a new Streamer/DJ account.'
      operationId: addStreamer
      parameters:
        -
          $ref: '#/components/parameters/StationIdRequired'
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/StationStreamer'
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/StationStreamer'
        '403':
          $ref: '#/components/responses/AccessDenied'
        '404':
          $ref: '#/components/responses/RecordNotFound'
        '500':
          $ref: '#/components/responses/GenericError'
      security:
        -
          ApiKey: []
  '/station/{station_id}/streamer/{id}':
    get:
      tags:
        - 'Stations: Streamers/DJs'
      description: 'Retrieve details for a single Streamer/DJ account.'
      operationId: getStreamer
      parameters:
        -
          $ref: '#/components/parameters/StationIdRequired'
        -
          name: id
          in: path
          description: 'Streamer ID'
          required: true
          schema:
            type: integer
            format: int64
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/StationStreamer'
        '403':
          $ref: '#/components/responses/AccessDenied'
        '404':
          $ref: '#/components/responses/RecordNotFound'
        '500':
          $ref: '#/components/responses/GenericError'
      security:
        -
          ApiKey: []
    put:
      tags:
        - 'Stations: Streamers/DJs'
      description: 'Update details of a single Streamer/DJ account.'
      operationId: editStreamer
      parameters:
        -
          $ref: '#/components/parameters/StationIdRequired'
        -
          name: id
          in: path
          description: 'Streamer ID'
          required: true
          schema:
            type: integer
            format: int64
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/StationStreamer'
      responses:
        '200':
          $ref: '#/components/responses/Success'
        '403':
          $ref: '#/components/responses/AccessDenied'
        '404':
          $ref: '#/components/responses/RecordNotFound'
        '500':
          $ref: '#/components/responses/GenericError'
      security:
        -
          ApiKey: []
    delete:
      tags:
        - 'Stations: Streamers/DJs'
      description: 'Delete a single Streamer/DJ account.'
      operationId: deleteStreamer
      parameters:
        -
          $ref: '#/components/parameters/StationIdRequired'
        -
          name: id
          in: path
          description: 'StationStreamer ID'
          required: true
          schema:
            type: integer
            format: int64
      responses:
        '200':
          $ref: '#/components/responses/Success'
        '403':
          $ref: '#/components/responses/AccessDenied'
        '404':
          $ref: '#/components/responses/RecordNotFound'
        '500':
          $ref: '#/components/responses/GenericError'
      security:
        -
          ApiKey: []
  '/station/{station_id}/webhooks':
    get:
      tags:
        - 'Stations: Web Hooks'
      description: 'List all current web hooks.'
      operationId: getWebhooks
      parameters:
        -
          $ref: '#/components/parameters/StationIdRequired'
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/StationWebhook'
        '403':
          $ref: '#/components/responses/AccessDenied'
        '404':
          $ref: '#/components/responses/RecordNotFound'
        '500':
          $ref: '#/components/responses/GenericError'
      security:
        -
          ApiKey: []
    post:
      tags:
        - 'Stations: Web Hooks'
      description: 'Create a new web hook.'
      operationId: addWebhook
      parameters:
        -
          $ref: '#/components/parameters/StationIdRequired'
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/StationWebhook'
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/StationWebhook'
        '403':
          $ref: '#/components/responses/AccessDenied'
        '404':
          $ref: '#/components/responses/RecordNotFound'
        '500':
          $ref: '#/components/responses/GenericError'
      security:
        -
          ApiKey: []
  '/station/{station_id}/webhook/{id}':
    get:
      tags:
        - 'Stations: Web Hooks'
      description: 'Retrieve details for a single web hook.'
      operationId: getWebhook
      parameters:
        -
          $ref: '#/components/parameters/StationIdRequired'
        -
          name: id
          in: path
          description: 'Web Hook ID'
          required: true
          schema:
            type: integer
            format: int64
      responses:
        '200':
          description: Success
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/StationWebhook'
        '403':
          $ref: '#/components/responses/AccessDenied'
        '404':
          $ref: '#/components/responses/RecordNotFound'
        '500':
          $ref: '#/components/responses/GenericError'
      security:
        -
          ApiKey: []
    put:
      tags:
        - 'Stations: Web Hooks'
      description: 'Update details of a single web hook.'
      operationId: editWebhook
      parameters:
        -
          $ref: '#/components/parameters/StationIdRequired'
        -
          name: id
          in: path
          description: 'Web Hook ID'
          required: true
          schema:
            type: integer
            format: int64
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/StationWebhook'
      responses:
        '200':
          $ref: '#/components/responses/Success'
        '403':
          $ref: '#/components/responses/AccessDenied'
        '404':
          $ref: '#/components/responses/RecordNotFound'
        '500':
          $ref: '#/components/responses/GenericError'
      security:
        -
          ApiKey: []
    delete:
      tags:
        - 'Stations: Web Hooks'
      description: 'Delete a single web hook relay.'
      operationId: deleteWebhook
      parameters:
        -
          $ref: '#/components/parameters/StationIdRequired'
        -
          name: id
          in: path
          description: 'Web Hook ID'
          required: true
          schema:
            type: integer
            format: int64
      responses:
        '200':
          $ref: '#/components/responses/Success'
        '403':
          $ref: '#/components/responses/AccessDenied'
        '404':
          $ref: '#/components/responses/RecordNotFound'
        '500':
          $ref: '#/components/responses/GenericError'
      security:
        -
          ApiKey: []
components:
  schemas:
    Api_Admin_Relay:
      properties:
        id:
          description: 'Station ID'
          type: integer
          example: 1
        name:
          description: 'Station name'
          type: string
          example: 'AzuraTest Radio'
          nullable: true
        shortcode:
          description: 'Station "short code", used for URL and folder paths'
          type: string
          example: azuratest_radio
          nullable: true
        description:
          description: 'Station description'
          type: string
          example: 'An AzuraCast station!'
          nullable: true
        url:
          description: 'Station homepage URL'
          type: string
          example: 'https://www.azuracast.com/'
          nullable: true
        genre:
          description: 'The genre of the station'
          type: string
          example: Variety
          nullable: true
        type:
          description: 'Which broadcasting software (frontend) the station uses'
          type: string
          example: shoutcast2
          nullable: true
        port:
          description: 'The port used by this station to serve its broadcasts.'
          type: integer
          example: 8000
          nullable: true
        relay_pw:
          description: 'The relay password for the frontend (if applicable).'
          type: string
          example: p4ssw0rd
        admin_pw:
          description: 'The administrator password for the frontend (if applicable).'
          type: string
          example: p4ssw0rd
        mounts:
          description: '*/'
          type: array
          items:
            $ref: '#/components/schemas/Api_NowPlaying_StationMount'
      type: object
    Api_Admin_StorageLocation:
      properties:
        id:
          type: integer
          example: 1
        type:
          description: 'The type of storage location.'
          type: string
          example: station_media
        adapter:
          description: 'The storage adapter to use for this location.'
          type: string
          example: local
        path:
          description: 'The local path, if the local adapter is used, or path prefix for S3/remote adapters.'
          type: string
          example: /var/azuracast/stations/azuratest_radio/media
          nullable: true
        s3CredentialKey:
          description: 'The credential key for S3 adapters.'
          type: string
          example: your-key-here
          nullable: true
        s3CredentialSecret:
          description: 'The credential secret for S3 adapters.'
          type: string
          example: your-secret-here
          nullable: true
        s3Region:
          description: 'The region for S3 adapters.'
          type: string
          example: your-region
          nullable: true
        s3Version:
          description: 'The API version for S3 adapters.'
          type: string
          example: latest
          nullable: true
        s3Bucket:
          description: 'The S3 bucket name for S3 adapters.'
          type: string
          example: your-bucket-name
          nullable: true
        s3Endpoint:
          description: 'The optional custom S3 endpoint S3 adapters.'
          type: string
          example: 'https://your-region.digitaloceanspaces.com'
          nullable: true
        dropboxAuthToken:
          description: 'The optional Dropbox Auth Token.'
          type: string
          example: ''
          nullable: true
        sftpHost:
          description: 'The host for SFTP adapters'
          type: string
          example: 127.0.0.1
          nullable: true
        sftpUsername:
          description: 'The username for SFTP adapters'
          type: string
          example: root
          nullable: true
        sftpPassword:
          description: 'The password for SFTP adapters'
          type: string
          example: abc123
          nullable: true
        sftpPort:
          description: 'The port for SFTP adapters'
          type: integer
          example: 20
          nullable: true
        sftpPrivateKey:
          description: 'The private key for SFTP adapters'
          type: string
          nullable: true
        sftpPrivateKeyPassPhrase:
          description: 'The private key pass phrase for SFTP adapters'
          type: string
          nullable: true
        storageQuota:
          type: string
          example: '50 GB'
          nullable: true
        storageQuotaBytes:
          type: string
          example: '120000'
          nullable: true
        storageUsed:
          type: string
          example: '1 GB'
          nullable: true
        storageUsedBytes:
          type: string
          example: '60000'
          nullable: true
        storageAvailable:
          type: string
          example: '1 GB'
          nullable: true
        storageAvailableBytes:
          type: string
          example: '120000'
          nullable: true
        storageUsedPercent:
          type: integer
          example: '75'
          nullable: true
        isFull:
          type: boolean
          example: 'true'
        uri:
          description: 'The URI associated with the storage location.'
          type: string
          example: /var/azuracast/www
        stations:
          description: 'The stations using this storage location, if any.'
          type: array
          items:
            type: string
            example: 'AzuraTest Radio'
          nullable: true
      type: object
    Api_DetailedSongHistory:
      type: object
      allOf:
        -
          $ref: '#/components/schemas/Api_NowPlaying_SongHistory'
        -
          properties:
            listeners_start:
              description: 'Number of listeners when the song playback started.'
              type: integer
              example: 94
            listeners_end:
              description: 'Number of listeners when song playback ended.'
              type: integer
              example: 105
            delta_total:
              description: "The sum total change of listeners between the song's start and ending."
              type: integer
              example: 11
            is_visible:
              description: 'Whether the entry is visible on public playlists.'
              type: boolean
              example: true
    Api_Error:
      properties:
        code:
          description: 'The numeric code of the error.'
          type: integer
          example: 500
        type:
          description: 'The programmatic class of error.'
          type: string
          example: NotLoggedInException
        message:
          description: 'The text description of the error.'
          type: string
          example: 'Error description.'
        formatted_message:
          description: 'The HTML-formatted text description of the error.'
          type: string
          example: '<b>Error description.</b><br>Detailed error text.'
          nullable: true
        extra_data:
          description: 'Stack traces and other supplemental data.'
          type: array
          items: {  }
        success:
          description: 'Used for API calls that expect an \Entity\Api\Status type response.'
          type: boolean
          example: false
      type: object
    Api_Listener:
      properties:
        ip:
          description: "The listener's IP address"
          type: string
          example: 127.0.0.1
        user_agent:
          description: "The listener's HTTP User-Agent"
          type: string
          example: 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.86 Safari/537.36'
        hash:
          description: 'A unique identifier for this listener/user agent (used for unique calculations).'
          type: string
          example: ''
        mount_is_local:
          description: 'Whether the user is connected to a local mount point or a remote one.'
          type: boolean
          example: false
        mount_name:
          description: 'The display name of the mount point.'
          type: string
          example: /radio.mp3
        connected_on:
          description: 'UNIX timestamp that the user first connected.'
          type: integer
          example: 1609480800
        connected_until:
          description: 'UNIX timestamp that the user disconnected (or the latest timestamp if they are still connected).'
          type: integer
          example: 1609480800
        connected_time:
          description: 'Number of seconds that the user has been connected.'
          type: integer
          example: 30
        device:
          description: 'Device metadata, if available'
          type: array
          items: {  }
        location:
          description: 'Location metadata, if available'
          type: array
          items: {  }
      type: object
    Api_NewRecord:
      type: object
      allOf:
        -
          $ref: '#/components/schemas/Api_Status'
        -
          properties:
            links:
              type: array
              items:
                type: string
                example: 'http://localhost/api/record/1'
    Api_NowPlaying_CurrentSong:
      type: object
      allOf:
        -
          $ref: '#/components/schemas/Api_NowPlaying_SongHistory'
        -
          properties:
            elapsed:
              description: "Elapsed time of the song's playback since it started."
              type: integer
              example: 25
            remaining:
              description: 'Remaining time in the song, in seconds.'
              type: integer
              example: 155
    Api_NowPlaying_Listeners:
      properties:
        total:
          description: 'Total non-unique current listeners'
          type: integer
          example: 20
        unique:
          description: 'Total unique current listeners'
          type: integer
          example: 15
        current:
          description: 'Total non-unique current listeners (Legacy field, may be retired in the future.)'
          type: integer
          example: 20
      type: object
    Api_NowPlaying_Live:
      properties:
        is_live:
          description: 'Whether the stream is known to currently have a live DJ.'
          type: boolean
          example: false
        streamer_name:
          description: 'The current active streamer/DJ, if one is available.'
          type: string
          example: 'DJ Jazzy Jeff'
        broadcast_start:
          description: 'The start timestamp of the current broadcast, if one is available.'
          type: integer
          example: '1591548318'
          nullable: true
        art:
          description: 'URL to the streamer artwork (if available).'
          example: 'https://picsum.photos/1200/1200'
          nullable: true
      type: object
    Api_NowPlaying:
      properties:
        station:
          $ref: '#/components/schemas/Api_NowPlaying_Station'
        listeners:
          $ref: '#/components/schemas/Api_NowPlaying_Listeners'
        live:
          $ref: '#/components/schemas/Api_NowPlaying_Live'
        now_playing:
          nullable: true
          oneOf:
            -
              $ref: '#/components/schemas/Api_NowPlaying_CurrentSong'
        playing_next:
          nullable: true
          oneOf:
            -
              $ref: '#/components/schemas/Api_NowPlaying_StationQueue'
        song_history:
          description: '*/'
          type: array
          items:
            $ref: '#/components/schemas/Api_NowPlaying_SongHistory'
        is_online:
          description: 'Whether the stream is currently online.'
          type: boolean
          example: true
        cache:
          description: 'Debugging information about where the now playing data comes from.'
          type: string
          enum:
            - hit
            - database
            - station
          nullable: true
      type: object
    Api_NowPlaying_SongHistory:
      properties:
        sh_id:
          description: 'Song history unique identifier'
          type: integer
        played_at:
          description: 'UNIX timestamp when playback started.'
          type: integer
          example: 1609480800
        duration:
          description: 'Duration of the song in seconds'
          type: integer
          example: 180
        playlist:
          description: 'Indicates the playlist that the song was played from, if available, or empty string if not.'
          type: string
          example: 'Top 100'
          nullable: true
        streamer:
          description: 'Indicates the current streamer that was connected, if available, or empty string if not.'
          type: string
          example: 'Test DJ'
          nullable: true
        is_request:
          description: 'Indicates whether the song is a listener request.'
          type: boolean
        song:
          $ref: '#/components/schemas/Api_Song'
      type: object
    Api_NowPlaying_Station:
      properties:
        id:
          description: 'Station ID'
          type: integer
          example: 1
        name:
          description: 'Station name'
          type: string
          example: 'AzuraTest Radio'
        shortcode:
          description: 'Station "short code", used for URL and folder paths'
          type: string
          example: azuratest_radio
        description:
          description: 'Station description'
          type: string
          example: 'An AzuraCast station!'
        frontend:
          description: 'Which broadcasting software (frontend) the station uses'
          type: string
          example: shoutcast2
        backend:
          description: 'Which AutoDJ software (backend) the station uses'
          type: string
          example: liquidsoap
        listen_url:
          description: 'The full URL to listen to the default mount of the station'
          example: 'http://localhost:8000/radio.mp3'
        url:
          description: 'The public URL of the station.'
          type: string
          example: 'https://example.com/'
          nullable: true
        public_player_url:
          description: 'The public player URL for the station.'
          example: 'https://example.com/public/example_station'
        playlist_pls_url:
          description: 'The playlist download URL in PLS format.'
          example: 'https://example.com/public/example_station/playlist.pls'
        playlist_m3u_url:
          description: 'The playlist download URL in M3U format.'
          example: 'https://example.com/public/example_station/playlist.m3u'
        is_public:
          description: 'If the station is public (i.e. should be shown in listings of all stations)'
          type: boolean
          example: true
        mounts:
          description: '*/'
          type: array
          items:
            $ref: '#/components/schemas/Api_NowPlaying_StationMount'
        remotes:
          description: '*/'
          type: array
          items:
            $ref: '#/components/schemas/Api_NowPlaying_StationRemote'
        hls_enabled:
          description: 'If the station has HLS streaming enabled.'
          type: boolean
          example: true
        hls_url:
          description: 'The full URL to listen to the HLS stream for the station.'
          example: 'https://example.com/hls/azuratest_radio/live.m3u8'
          nullable: true
        hls_listeners:
          description: 'HLS Listeners'
          type: integer
          example: 1
      type: object
    Api_NowPlaying_StationMount:
      type: object
      allOf:
        -
          $ref: '#/components/schemas/Api_NowPlaying_StationRemote'
        -
          properties:
            path:
              description: 'The relative path that corresponds to this mount point'
              type: string
              example: /radio.mp3
            is_default:
              description: 'If the mount is the default mount for the parent station'
              type: boolean
              example: true
    Api_NowPlaying_StationQueue:
      properties:
        cued_at:
          description: 'UNIX timestamp when the AutoDJ is expected to queue the song for playback.'
          type: integer
          example: 1609480800
        played_at:
          description: 'UNIX timestamp when playback is expected to start.'
          type: integer
          example: 1609480800
        duration:
          description: 'Duration of the song in seconds'
          type: integer
          example: 180
        playlist:
          description: 'Indicates the playlist that the song was played from, if available, or empty string if not.'
          type: string
          example: 'Top 100'
          nullable: true
        is_request:
          description: 'Indicates whether the song is a listener request.'
          type: boolean
        song:
          $ref: '#/components/schemas/Api_Song'
      type: object
    Api_NowPlaying_StationRemote:
      properties:
        id:
          description: 'Mount/Remote ID number.'
          type: integer
          example: 1
        name:
          description: 'Mount point name/URL'
          type: string
          example: /radio.mp3
        url:
          description: 'Full listening URL specific to this mount'
          example: 'http://localhost:8000/radio.mp3'
        bitrate:
          description: 'Bitrate (kbps) of the broadcasted audio (if known)'
          type: integer
          example: 128
          nullable: true
        format:
          description: 'Audio encoding format of broadcasted audio (if known)'
          type: string
          example: mp3
          nullable: true
        listeners:
          $ref: '#/components/schemas/Api_NowPlaying_Listeners'
      type: object
    Api_Podcast:
      type: object
      allOf:
        -
          $ref: '#/components/schemas/HasLinks'
        -
          properties:
            id:
              type: string
              nullable: true
            storage_location_id:
              type: integer
              nullable: true
            title:
              type: string
              nullable: true
            link:
              type: string
              nullable: true
            description:
              type: string
              nullable: true
            language:
              type: string
              nullable: true
            author:
              type: string
              nullable: true
            email:
              type: string
              nullable: true
            has_custom_art:
              type: boolean
            art:
              type: string
              nullable: true
            art_updated_at:
              type: integer
            categories:
              type: array
              items:
                type: string
            episodes:
              type: array
              items:
                type: string
    Api_PodcastEpisode:
      type: object
      allOf:
        -
          $ref: '#/components/schemas/HasLinks'
        -
          properties:
            id:
              type: string
              nullable: true
            title:
              type: string
              nullable: true
            description:
              type: string
              nullable: true
            explicit:
              type: boolean
            publish_at:
              type: integer
              nullable: true
            has_media:
              type: boolean
            media:
              $ref: '#/components/schemas/Api_PodcastMedia'
            has_custom_art:
              type: boolean
            art:
              type: string
              nullable: true
            art_updated_at:
              type: integer
    Api_PodcastMedia:
      properties:
        id:
          type: string
          nullable: true
        original_name:
          type: string
          nullable: true
        length:
          type: number
          format: float
        length_text:
          type: string
          nullable: true
        path:
          type: string
          nullable: true
      type: object
    Api_Song:
      properties:
        id:
          description: "The song's 32-character unique identifier hash"
          type: string
          example: 9f33bbc912c19603e51be8e0987d076b
        text:
          description: 'The song title, usually "Artist - Title"'
          type: string
          example: 'Chet Porter - Aluko River'
        artist:
          description: 'The song artist.'
          type: string
          example: 'Chet Porter'
        title:
          description: 'The song title.'
          type: string
          example: 'Aluko River'
        album:
          description: 'The song album.'
          type: string
          example: 'Moving Castle'
        genre:
          description: 'The song genre.'
          type: string
          example: Rock
        isrc:
          description: 'The International Standard Recording Code (ISRC) of the file.'
          type: string
          example: US28E1600021
        lyrics:
          description: 'Lyrics to the song.'
          type: string
          example: ''
        art:
          description: 'URL to the album artwork (if available).'
          example: 'https://picsum.photos/1200/1200'
        custom_fields:
          type: array
          items:
            type: string
            example: custom_field_value
      type: object
    Api_StationOnDemand:
      properties:
        track_id:
          description: 'Track ID unique identifier'
          type: string
          example: 1
        download_url:
          description: 'URL to download/play track.'
          type: string
          example: /api/station/1/ondemand/download/1
        media:
          $ref: '#/components/schemas/Api_Song'
        playlist:
          type: string
      type: object
    Api_StationPlaylistQueue:
      properties:
        spm_id:
          description: 'ID of the StationPlaylistMedia record associating this track with the playlist'
          type: integer
          example: 1
          nullable: true
        media_id:
          description: 'ID of the StationPlaylistMedia record associating this track with the playlist'
          type: integer
          example: 1
        song_id:
          description: "The song's 32-character unique identifier hash"
          type: string
          example: 9f33bbc912c19603e51be8e0987d076b
        artist:
          description: 'The song artist.'
          type: string
          example: 'Chet Porter'
        title:
          description: 'The song title.'
          type: string
          example: 'Aluko River'
      type: object
    Api_StationQueueDetailed:
      type: object
      allOf:
        -
          $ref: '#/components/schemas/Api_NowPlaying_StationQueue'
        -
          $ref: '#/components/schemas/HasLinks'
        -
          properties:
            sent_to_autodj:
              description: 'Indicates whether the song has been sent to the AutoDJ.'
              type: boolean
            is_played:
              description: 'Indicates whether the song has already been marked as played.'
              type: boolean
            autodj_custom_uri:
              description: 'Custom AutoDJ playback URI, if it exists.'
              type: string
              example: ''
              nullable: true
            log:
              description: 'Log entries on how the specific queue item was picked by the AutoDJ.'
              type: array
              items: {  }
              nullable: true
    Api_StationRemote:
      type: object
      allOf:
        -
          $ref: '#/components/schemas/HasLinks'
        -
          properties:
            id:
              type: integer
              nullable: true
            display_name:
              type: string
              example: '128kbps MP3'
              nullable: true
            is_visible_on_public_pages:
              type: boolean
              example: true
            type:
              type: string
              example: icecast
            is_editable:
              type: boolean
              example: 'true'
            enable_autodj:
              type: boolean
              example: false
            autodj_format:
              type: string
              example: mp3
              nullable: true
            autodj_bitrate:
              type: integer
              example: 128
              nullable: true
            custom_listen_url:
              type: string
              example: 'https://custom-listen-url.example.com/stream.mp3'
              nullable: true
            url:
              type: string
              example: 'https://custom-url.example.com'
            mount:
              type: string
              example: /stream.mp3
              nullable: true
            admin_password:
              type: string
              example: password
              nullable: true
            source_port:
              type: integer
              example: 8000
              nullable: true
            source_mount:
              type: string
              example: /
              nullable: true
            source_username:
              type: string
              example: source
              nullable: true
            source_password:
              type: string
              example: password
              nullable: true
            is_public:
              type: boolean
              example: false
            listeners_unique:
              description: 'The most recent number of unique listeners.'
              type: integer
              example: 10
            listeners_total:
              description: 'The most recent number of total (non-unique) listeners.'
              type: integer
              example: 12
    Api_StationRequest:
      properties:
        request_id:
          description: 'Requestable ID unique identifier'
          type: string
          example: 1
        request_url:
          description: 'URL to directly submit request'
          type: string
          example: /api/station/1/request/1
        song:
          $ref: '#/components/schemas/Api_Song'
      type: object
    Api_StationSchedule:
      properties:
        id:
          description: 'Unique identifier for this schedule entry.'
          type: integer
          example: 1
        type:
          description: 'The type of this schedule entry.'
          type: string
          enum:
            - playlist
            - streamer
          example: playlist
        name:
          description: "Either the playlist or streamer's display name."
          type: string
          example: 'Example Schedule Entry'
        title:
          description: 'The name of the event.'
          type: string
          example: 'Example Schedule Entry'
        description:
          description: 'The full name of the type and name combined.'
          type: string
          example: 'Playlist: Example Schedule Entry'
        start_timestamp:
          description: 'The start time of the schedule entry, in UNIX format.'
          type: integer
          example: 1609480800
        start:
          description: 'The start time of the schedule entry, in ISO 8601 format.'
          type: string
          example: '020-02-19T03:00:00-06:00'
        end_timestamp:
          description: 'The end time of the schedule entry, in UNIX format.'
          type: integer
          example: 1609480800
        end:
          description: 'The start time of the schedule entry, in ISO 8601 format.'
          type: string
          example: '020-02-19T05:00:00-06:00'
        is_now:
          description: 'Whether the event is currently ongoing.'
          type: boolean
          example: true
      type: object
    Api_StationServiceStatus:
      properties:
        backend_running:
          type: boolean
          example: true
        frontend_running:
          type: boolean
          example: true
        station_has_started:
          type: boolean
          example: true
        station_needs_restart:
          type: boolean
          example: true
      type: object
    Api_Status:
      properties:
        success:
          type: boolean
          example: true
        message:
          type: string
          example: 'Changes saved successfully.'
        formatted_message:
          type: string
          example: '<b>Changes saved successfully.</b>'
      type: object
    Api_SystemStatus:
      properties:
        online:
          description: 'Whether the service is online or not (should always be true)'
          type: boolean
          example: true
        timestamp:
          description: 'The current UNIX timestamp'
          type: integer
          example: 1609480800
      type: object
    Api_Time:
      properties:
        timestamp:
          description: 'The current UNIX timestamp'
          type: integer
          example: 1497652397
        utc_datetime:
          type: string
          example: '2017-06-16 10:33:17'
        utc_date:
          type: string
          example: 'June 16, 2017'
        utc_time:
          type: string
          example: '10:33pm'
        utc_json:
          type: string
          example: '2012-12-25T16:30:00.000000Z'
      type: object
    HasLinks:
      properties:
        links:
          type: array
          items:
            type: string
            example: 'http://localhost/api/stations/1/queue/1'
      type: object
    Api_UploadFile:
      properties:
        path:
          description: 'The destination path of the uploaded file.'
          type: string
          example: relative/path/to/file.mp3
        file:
          description: 'The base64-encoded contents of the file to upload.'
          type: string
          example: ''
      type: object
    CustomField:
      type: object
      allOf:
        -
          $ref: '#/components/schemas/HasAutoIncrementId'
        -
          properties:
            name:
              type: string
            short_name:
              description: 'The programmatic name for the field. Can be auto-generated from the full name.'
              type: string
            auto_assign:
              description: 'An ID3v2 field to automatically assign to this value, if it exists in the media file.'
              type: string
              nullable: true
    Relay:
      type: object
      allOf:
        -
          $ref: '#/components/schemas/HasAutoIncrementId'
        -
          properties:
            base_url:
              type: string
              example: 'https://custom-url.example.com'
            name:
              type: string
              example: Relay
              nullable: true
            is_visible_on_public_pages:
              type: boolean
              example: true
            created_at:
              type: integer
              example: 1609480800
            updated_at:
              type: integer
              example: 1609480800
    Role:
      type: object
      allOf:
        -
          $ref: '#/components/schemas/HasAutoIncrementId'
        -
          properties:
            name:
              type: string
              example: 'Super Administrator'
            permissions:
              description: 'RolePermission> */'
              type: array
              items: {  }
    Settings:
      properties:
        app_unique_identifier:
          type: string
        base_url:
          description: 'Site Base URL'
          type: string
          example: 'https://your.azuracast.site'
          nullable: true
        instance_name:
          description: 'AzuraCast Instance Name'
          type: string
          example: 'My AzuraCast Instance'
          nullable: true
        prefer_browser_url:
          description: 'Prefer Browser URL (If Available)'
          type: boolean
          example: 'false'
        use_radio_proxy:
          description: 'Use Web Proxy for Radio'
          type: boolean
          example: 'false'
        history_keep_days:
          description: 'Days of Playback History to Keep'
          type: integer
        always_use_ssl:
          description: 'Always Use HTTPS'
          type: boolean
          example: 'false'
        api_access_control:
          description: "API 'Access-Control-Allow-Origin' header"
          type: string
          example: '*'
          nullable: true
        enable_static_nowplaying:
          description: 'Whether to use high-performance static JSON for Now Playing data updates.'
          type: boolean
          example: 'false'
        analytics:
          description: 'Listener Analytics Collection'
          type: string
          nullable: true
        check_for_updates:
          description: 'Check for Updates and Announcements'
          type: boolean
          example: 'true'
        update_results:
          description: 'Results of the latest update check.'
          type: array
          items: {  }
          example: ''
          nullable: true
        update_last_run:
          description: 'The UNIX timestamp when updates were last checked.'
          type: integer
          example: 1609480800
        public_theme:
          description: 'Base Theme for Public Pages'
          type: string
          example: light
          nullable: true
        hide_album_art:
          description: 'Hide Album Art on Public Pages'
          type: boolean
          example: 'false'
        homepage_redirect_url:
          description: 'Homepage Redirect URL'
          type: string
          example: 'https://example.com/'
          nullable: true
        default_album_art_url:
          description: 'Default Album Art URL'
          type: string
          example: 'https://example.com/image.jpg'
          nullable: true
        use_external_album_art_when_processing_media:
          description: 'Attempt to fetch album art from external sources when processing media.'
          type: boolean
          example: 'false'
        use_external_album_art_in_apis:
          description: 'Attempt to fetch album art from external sources in API requests.'
          type: boolean
          example: 'false'
        last_fm_api_key:
          description: 'An API key to connect to Last.fm services, if provided.'
          type: string
          example: SAMPLE-API-KEY
          nullable: true
        hide_product_name:
          description: 'Hide AzuraCast Branding on Public Pages'
          type: boolean
          example: 'false'
        public_custom_css:
          description: 'Custom CSS for Public Pages'
          type: string
          example: ''
          nullable: true
        public_custom_js:
          description: 'Custom JS for Public Pages'
          type: string
          example: ''
          nullable: true
        internal_custom_css:
          description: 'Custom CSS for Internal Pages'
          type: string
          example: ''
          nullable: true
        backup_enabled:
          description: 'Whether backup is enabled.'
          type: boolean
          example: 'false'
        backup_time_code:
          description: 'The timecode (i.e. 400 for 4:00AM) when automated backups should run.'
          type: string
          example: 400
          nullable: true
        backup_exclude_media:
          description: 'Whether to exclude media in automated backups.'
          type: boolean
          example: 'false'
        backup_keep_copies:
          description: 'Number of backups to keep, or infinite if zero/null.'
          type: integer
          example: 2
        backup_storage_location:
          description: 'The storage location ID for automated backups.'
          type: integer
          example: 1
          nullable: true
        backup_format:
          description: 'The output format for the automated backup.'
          type: string
          example: zip
          nullable: true
        backup_last_run:
          description: 'The UNIX timestamp when automated backup was last run.'
          type: integer
          example: 1609480800
        backup_last_output:
          description: 'The output of the latest automated backup task.'
          type: string
          example: ''
          nullable: true
        setup_complete_time:
          description: 'The UNIX timestamp when setup was last completed.'
          type: integer
          example: 1609480800
        sync_disabled:
          description: 'Temporarily disable all sync tasks.'
          type: boolean
          example: 'false'
        sync_last_run:
          description: 'The last run timestamp for the unified sync task.'
          type: integer
          example: 1609480800
        external_ip:
          description: "This installation's external IP."
          type: string
          example: 192.168.1.1
          nullable: true
        geolite_license_key:
          description: 'The license key for the Maxmind Geolite download.'
          type: string
          example: ''
          nullable: true
        geolite_last_run:
          description: 'The UNIX timestamp when the Maxmind Geolite was last downloaded.'
          type: integer
          example: 1609480800
        enable_advanced_features:
          description: "Whether to enable 'advanced' functionality in the system that is intended for power users."
          type: boolean
          example: false
        mail_enabled:
          description: 'Enable e-mail delivery across the application.'
          type: boolean
          example: 'true'
        mail_sender_name:
          description: 'The name of the sender of system e-mails.'
          type: string
          example: AzuraCast
          nullable: true
        mail_sender_email:
          description: 'The e-mail address of the sender of system e-mails.'
          type: string
          example: example@example.com
          nullable: true
        mail_smtp_host:
          description: 'The host to send outbound SMTP mail.'
          type: string
          example: smtp.example.com
          nullable: true
        mail_smtp_port:
          description: 'The port for sending outbound SMTP mail.'
          type: integer
          example: 465
        mail_smtp_username:
          description: 'The username when connecting to SMTP mail.'
          type: string
          example: username
          nullable: true
        mail_smtp_password:
          description: 'The password when connecting to SMTP mail.'
          type: string
          example: password
          nullable: true
        mail_smtp_secure:
          description: 'Whether to use a secure (TLS) connection when sending SMTP mail.'
          type: boolean
          example: 'true'
        avatar_service:
          description: 'The external avatar service to use when fetching avatars.'
          type: string
          example: libravatar
          nullable: true
        avatar_default_url:
          description: 'The default avatar URL.'
          type: string
          example: ''
          nullable: true
        acme_email:
          description: 'ACME (LetsEncrypt) e-mail address.'
          type: string
          example: ''
          nullable: true
        acme_domains:
          description: 'ACME (LetsEncrypt) domain name(s).'
          type: string
          example: ''
          nullable: true
      type: object
    SftpUser:
      type: object
      allOf:
        -
          $ref: '#/components/schemas/HasAutoIncrementId'
        -
          properties:
            username:
              type: string
            password:
              type: string
            publicKeys:
              type: string
              nullable: true
    Station:
      type: object
      allOf:
        -
          $ref: '#/components/schemas/HasAutoIncrementId'
        -
          properties:
            name:
              description: 'The full display name of the station.'
              type: string
              example: 'AzuraTest Radio'
            short_name:
              description: 'The URL-friendly name for the station, typically auto-generated from the full station name.'
              type: string
              example: azuratest_radio
            is_enabled:
              description: "If set to 'false', prevents the station from broadcasting but leaves it in the database."
              type: boolean
              example: true
            frontend_type:
              description: 'The frontend adapter (icecast,shoutcast,remote,etc)'
              type: string
              example: icecast
              nullable: true
            frontend_config:
              description: 'An array containing station-specific frontend configuration'
              type: array
              items: {  }
            backend_type:
              description: 'The backend adapter (liquidsoap,etc)'
              type: string
              example: liquidsoap
              nullable: true
            backend_config:
              description: 'An array containing station-specific backend configuration'
              type: array
              items: {  }
            description:
              type: string
              example: 'A sample radio station.'
              nullable: true
            url:
              type: string
              example: 'https://demo.azuracast.com/'
              nullable: true
            genre:
              type: string
              example: Various
              nullable: true
            radio_base_dir:
              type: string
              example: /var/azuracast/stations/azuratest_radio
              nullable: true
            enable_requests:
              description: 'Whether listeners can request songs to play on this station.'
              type: boolean
              example: true
            request_delay:
              type: integer
              example: 5
              nullable: true
            request_threshold:
              type: integer
              example: 15
              nullable: true
            disconnect_deactivate_streamer:
              type: integer
              example: 0
              nullable: true
            enable_streamers:
              description: 'Whether streamers are allowed to broadcast to this station at all.'
              type: boolean
              example: false
            is_streamer_live:
              description: 'Whether a streamer is currently active on the station.'
              type: boolean
              example: false
            enable_public_page:
              description: 'Whether this station is visible as a public page and in a now-playing API response.'
              type: boolean
              example: true
            enable_on_demand:
              description: "Whether this station has a public 'on-demand' streaming and download page."
              type: boolean
              example: true
            enable_on_demand_download:
              description: "Whether the 'on-demand' page offers download capability."
              type: boolean
              example: true
            enable_hls:
              description: 'Whether HLS streaming is enabled.'
              type: boolean
              example: true
            api_history_items:
              description: "The number of 'last played' history items to show for a station in API responses."
              type: integer
              example: 5
            timezone:
              description: 'The time zone that station operations should take place in.'
              type: string
              example: UTC
              nullable: true
            branding_config:
              description: 'An array containing station-specific branding configuration'
              type: array
              items: {  }
    StationHlsStream:
      type: object
      allOf:
        -
          $ref: '#/components/schemas/HasAutoIncrementId'
        -
          properties:
            name:
              type: string
              example: aac_lofi
            format:
              type: string
              example: aac
              nullable: true
            bitrate:
              type: integer
              example: 128
              nullable: true
    StationMedia:
      type: object
      allOf:
        -
          $ref: '#/components/schemas/HasAutoIncrementId'
        -
          $ref: '#/components/schemas/HasSongFields'
        -
          properties:
            unique_id:
              description: 'A unique identifier associated with this record.'
              type: string
              example: 69b536afc7ebbf16457b8645
              nullable: true
            album:
              description: "The name of the media file's album."
              type: string
              example: 'Test Album'
              nullable: true
            genre:
              description: 'The genre of the media file.'
              type: string
              example: Rock
              nullable: true
            lyrics:
              description: 'Full lyrics of the track, if available.'
              type: string
              example: '...Never gonna give you up...'
              nullable: true
            isrc:
              description: 'The track ISRC (International Standard Recording Code), used for licensing purposes.'
              type: string
              example: GBARL0600786
              nullable: true
            length:
              description: 'The song duration in seconds.'
              type: number
              format: float
              example: 240
              nullable: true
            length_text:
              description: 'The formatted song duration (in mm:ss format)'
              type: string
              example: '4:00'
              nullable: true
            path:
              description: 'The relative path of the media file.'
              type: string
              example: test.mp3
            mtime:
              description: 'The UNIX timestamp when the database was last modified.'
              type: integer
              example: 1609480800
              nullable: true
            amplify:
              description: 'The amount of amplification (in dB) to be applied to the radio source (liq_amplify)'
              type: number
              format: float
              example: -14
              nullable: true
            fade_overlap:
              description: 'The length of time (in seconds) before the next song starts in the fade (liq_start_next)'
              type: number
              format: float
              example: 2
              nullable: true
            fade_in:
              description: 'The length of time (in seconds) to fade in the next track (liq_fade_in)'
              type: number
              format: float
              example: 3
              nullable: true
            fade_out:
              description: 'The length of time (in seconds) to fade out the previous track (liq_fade_out)'
              type: number
              format: float
              example: 3
              nullable: true
            cue_in:
              description: 'The length of time (in seconds) from the start of the track to start playing (liq_cue_in)'
              type: number
              format: float
              example: 30
              nullable: true
            cue_out:
              description: 'The length of time (in seconds) from the CUE-IN of the track to stop playing (liq_cue_out)'
              type: number
              format: float
              example: 30
              nullable: true
            art_updated_at:
              description: 'The latest time (UNIX timestamp) when album art was updated.'
              type: integer
              example: 1609480800
            playlists:
              description: 'StationPlaylistMedia> */'
              type: array
              items: {  }
    StationMount:
      type: object
      allOf:
        -
          $ref: '#/components/schemas/HasAutoIncrementId'
        -
          properties:
            name:
              type: string
              example: /radio.mp3
            display_name:
              type: string
              example: '128kbps MP3'
              nullable: true
            is_visible_on_public_pages:
              type: boolean
              example: true
            is_default:
              type: boolean
              example: false
            is_public:
              type: boolean
              example: false
            fallback_mount:
              type: string
              example: /error.mp3
              nullable: true
            relay_url:
              type: string
              example: 'https://radio.example.com:8000/radio.mp3'
              nullable: true
            authhash:
              type: string
              example: ''
              nullable: true
            max_listener_duration:
              type: integer
              example: 43200
            enable_autodj:
              type: boolean
              example: true
            autodj_format:
              type: string
              example: mp3
              nullable: true
            autodj_bitrate:
              type: integer
              example: 128
              nullable: true
            custom_listen_url:
              type: string
              example: 'https://custom-listen-url.example.com/stream.mp3'
              nullable: true
            frontend_config:
              type: array
              items: {  }
            listeners_unique:
              description: 'The most recent number of unique listeners.'
              type: integer
              example: 10
            listeners_total:
              description: 'The most recent number of total (non-unique) listeners.'
              type: integer
              example: 12
    StationPlaylist:
      type: object
      allOf:
        -
          $ref: '#/components/schemas/HasAutoIncrementId'
        -
          properties:
            name:
              type: string
              example: 'Test Playlist'
            type:
              type: string
              example: default
            source:
              type: string
              example: songs
            order:
              type: string
              example: shuffle
            remote_url:
              type: string
              example: 'https://remote-url.example.com/stream.mp3'
              nullable: true
            remote_type:
              type: string
              example: stream
              nullable: true
            remote_buffer:
              description: 'The total time (in seconds) that Liquidsoap should buffer remote URL streams.'
              type: integer
              example: 0
            is_enabled:
              type: boolean
              example: true
            is_jingle:
              description: 'If yes, do not send jingle metadata to AutoDJ or trigger web hooks.'
              type: boolean
              example: false
            play_per_songs:
              type: integer
              example: 5
            play_per_minutes:
              type: integer
              example: 120
            play_per_hour_minute:
              type: integer
              example: 15
            weight:
              type: integer
              example: 3
            include_in_requests:
              type: boolean
              example: true
            include_in_on_demand:
              description: "Whether this playlist's media is included in 'on demand' download/streaming if enabled."
              type: boolean
              example: true
            backend_options:
              type: string
              example: 'interrupt,loop_once,single_track,merge'
              nullable: true
            avoid_duplicates:
              type: boolean
              example: true
            schedule_items:
              description: 'StationSchedule> */'
              type: array
              items: {  }
    StationSchedule:
      type: object
      allOf:
        -
          $ref: '#/components/schemas/HasAutoIncrementId'
        -
          properties:
            start_time:
              type: integer
              example: 900
            end_time:
              type: integer
              example: 2200
            days:
              description: 'Array of ISO-8601 days (1 for Monday, 7 for Sunday)'
              type: string
              example: '0,1,2,3'
              nullable: true
            loop_once:
              type: boolean
              example: false
    StationStreamer:
      description: 'Station streamers (DJ accounts) allowed to broadcast to a station.'
      type: object
      allOf:
        -
          $ref: '#/components/schemas/HasAutoIncrementId'
        -
          properties:
            streamer_username:
              type: string
              example: dj_test
            streamer_password:
              type: string
              example: ''
            display_name:
              type: string
              example: 'Test DJ'
              nullable: true
            comments:
              type: string
              example: 'This is a test DJ account.'
              nullable: true
            is_active:
              type: boolean
              example: true
            enforce_schedule:
              type: boolean
              example: false
            reactivate_at:
              type: integer
              example: 1609480800
              nullable: true
            schedule_items:
              description: 'StationSchedule> */'
              type: array
              items: {  }
    StationStreamerBroadcast:
      description: 'Each individual broadcast associated with a streamer.'
      type: object
      allOf:
        -
          $ref: '#/components/schemas/HasAutoIncrementId'
    StationWebhook:
      type: object
      allOf:
        -
          $ref: '#/components/schemas/HasAutoIncrementId'
        -
          properties:
            name:
              description: 'The nickname of the webhook connector.'
              type: string
              example: 'Twitter Post'
              nullable: true
            type:
              description: 'The type of webhook connector to use.'
              type: string
              example: twitter
            is_enabled:
              type: boolean
              example: true
            triggers:
              description: 'List of events that should trigger the webhook notification.'
              type: array
              items: {  }
            config:
              description: 'Detailed webhook configuration (if applicable)'
              type: array
              items: {  }
            metadata:
              description: 'Internal details used by the webhook to preserve state.'
              type: array
              items: {  }
    HasAutoIncrementId:
      properties:
        id:
          type: integer
          nullable: true
      type: object
    HasSongFields:
      properties:
        song_id:
          type: string
        text:
          type: string
          nullable: true
        artist:
          type: string
          nullable: true
        title:
          type: string
          nullable: true
      type: object
    HasUniqueId:
      properties:
        id:
          type: string
          nullable: true
      type: object
    User:
      type: object
      allOf:
        -
          $ref: '#/components/schemas/HasAutoIncrementId'
        -
          properties:
            email:
              type: string
              example: demo@azuracast.com
            new_password:
              type: string
              example: ''
              nullable: true
            name:
              type: string
              example: 'Demo Account'
              nullable: true
            locale:
              type: string
              example: en_US
              nullable: true
            theme:
              type: string
              example: dark
              nullable: true
            show_24_hour_time:
              type: boolean
              example: true
              nullable: true
            two_factor_secret:
              type: string
              example: A1B2C3D4
              nullable: true
            created_at:
              type: integer
              example: 1609480800
            updated_at:
              type: integer
              example: 1609480800
            roles:
              description: 'Role> */'
              type: array
              items: {  }
  responses:
    Success:
      description: Success
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Api_Status'
    AccessDenied:
      description: 'Access denied.'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Api_Error'
    RecordNotFound:
      description: 'Record not found.'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Api_Error'
    GenericError:
      description: 'A generic exception has occurred.'
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Api_Error'
  parameters:
    StationIdRequired:
      name: StationIdRequired
      in: path
      required: true
      schema:
        anyOf:
          -
            type: integer
            format: int64
          -
            type: string
            format: string
  securitySchemes:
    ApiKey:
      type: apiKey
      name: X-API-Key
      in: header
tags:
  -
    name: 'Now Playing'
    description: 'Endpoints that provide full summaries of the current state of stations.'
  -
    name: 'Stations: General'
  -
    name: 'Stations: Broadcasting'
  -
    name: 'Stations: Song Requests'
  -
    name: 'Stations: Service Control'
  -
    name: 'Stations: Automation'
  -
    name: 'Stations: History'
  -
    name: 'Stations: HLS Streams'
  -
    name: 'Stations: Listeners'
  -
    name: 'Stations: Schedules'
  -
    name: 'Stations: Media'
  -
    name: 'Stations: Mount Points'
  -
    name: 'Stations: Playlists'
  -
    name: 'Stations: Podcasts'
  -
    name: 'Stations: Queue'
  -
    name: 'Stations: Remote Relays'
  -
    name: 'Stations: SFTP Users'
  -
    name: 'Stations: Streamers/DJs'
  -
    name: 'Stations: Web Hooks'
  -
    name: 'Administration: Custom Fields'
  -
    name: 'Administration: Users'
  -
    name: 'Administration: Relays'
  -
    name: 'Administration: Roles'
  -
    name: 'Administration: Settings'
  -
    name: 'Administration: Stations'
  -
    name: 'Administration: Storage Locations'
  -
    name: Miscellaneous
externalDocs:
  description: 'AzuraCast on GitHub'
  url: 'https://github.com/AzuraCast/AzuraCast'
