openapi: 3.0.0
servers:
  - url: https://spinitron.com/api
info:
  contact:
    x-twitter: Spinitron
  description: |
    ## Notes

    **Tutorial demo** using this API is at [https://spinitron.com/v2-api-demo/](https://spinitron.com/v2-api-demo/). For web integration using iframes and/or JavaScript instead of an API, see [https://spinitron.github.io/v2-web-integration/](https://spinitron.github.io/v2-web-integration/).

    **Your API key** is found in the Spinitron web app. Log in to Spinitron and go to *Automation & API* in the *Admin* menu.

    **Authenticate** by presenting your API key using either HTTP Bearer Authorization
    (preferred)

        curl -H 'Authorization: Bearer YOURAPIKEY' 'https://spinitron.com/api/spins'

    or in the query parameter `access-token` (less secure owing to webserver
    log files)

        curl 'https://spinitron.com/api/spins?access-token=YOURAPIKEY'

    **Limit** per page of results is 20 by default and miximally 200.

    **Try it out** below works to
    generate example cURL requests but not to get responses from Spinitron. We
    do not accept queries sent from web browsers. Copy-paste the cURL commands
    and run them from your computer.

    **Cache** the data you get from the API if you are using it in web or mobile integration. It's not ok to query the API on *every* page request you serve. The [demo](https://spinitron.com/v2-api-demo/) shows how easy it can be to implement a file cache.

    An extension to this API with access to all stations for partner applications is available. Contact us.
  title: Spinitron v2 API
  version: 1.0.0
  x-apisguru-categories:
    - media
  x-logo:
    url: https://twitter.com/Spinitron/profile_image?size=original
  x-origin:
    - format: swagger
      url: https://raw.githubusercontent.com/spinitron/v2api/master/spinitron.yaml
      version: "2.0"
  x-providerName: spinitron.com
security:
  - httpBearer: []
  - accessToken: []
tags:
  - name: Persona
  - name: Show
  - name: Playlist
  - name: Spin
paths:
  /personas:
    get:
      parameters:
        - description: Filter by Persona name
          in: query
          name: name
          schema:
            type: string
        - $ref: "#/components/parameters/limit"
        - $ref: "#/components/parameters/page"
        - $ref: "#/components/parameters/fields"
        - $ref: "#/components/parameters/expand"
      responses:
        "200":
          content:
            application/json:
              schema:
                allOf:
                  - $ref: "#/components/schemas/BaseIndexResponse"
                  - properties:
                      items:
                        items:
                          $ref: "#/components/schemas/Persona"
                        type: array
                    type: object
            application/xml:
              schema:
                allOf:
                  - $ref: "#/components/schemas/BaseIndexResponse"
                  - properties:
                      items:
                        items:
                          $ref: "#/components/schemas/Persona"
                        type: array
                    type: object
          description: The personas
      summary: Get Personas
      tags:
        - Persona
  "/personas/{id}":
    get:
      parameters:
        - in: path
          name: id
          required: true
          schema:
            type: integer
        - $ref: "#/components/parameters/fields"
        - $ref: "#/components/parameters/expand"
      responses:
        "200":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Persona"
            application/xml:
              schema:
                $ref: "#/components/schemas/Persona"
          description: The Persona
        "404":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
            application/xml:
              schema:
                $ref: "#/components/schemas/Error"
          description: Persona not found
      summary: Get Persona by id
      tags:
        - Persona
  /playlists:
    get:
      description: |
        Get Playlists optionally filtered by a datetime range.
        Only past Playlists will be returned (with allowed tolerance equals 1 hour in future).

        Ordered chronologically from newest to oldest.
      parameters:
        - description: |
            The datetime starting from items must be returned. Maximum 1 hour in future.
          in: query
          name: start
          schema:
            format: date-time
            type: string
        - description: |
            The ending datetime. Maximum 1 hour in future.
          in: query
          name: end
          schema:
            format: date-time
            type: string
        - description: Filter by show
          in: query
          name: show_id
          schema:
            type: integer
        - description: Filter by persona
          in: query
          name: persona_id
          schema:
            type: integer
        - $ref: "#/components/parameters/limit"
        - $ref: "#/components/parameters/page"
        - $ref: "#/components/parameters/fields"
        - $ref: "#/components/parameters/expand"
      responses:
        "200":
          content:
            application/json:
              schema:
                allOf:
                  - $ref: "#/components/schemas/BaseIndexResponse"
                  - properties:
                      items:
                        items:
                          $ref: "#/components/schemas/Playlist"
                        type: array
                    type: object
            application/xml:
              schema:
                allOf:
                  - $ref: "#/components/schemas/BaseIndexResponse"
                  - properties:
                      items:
                        items:
                          $ref: "#/components/schemas/Playlist"
                        type: array
                    type: object
          description: The playlists
      summary: Returns playlists optionally filtered by {start} and/or {end} datetimes
      tags:
        - Playlist
  "/playlists/{id}":
    get:
      description: |
        The response object represents the playlist specified by {id}.

        Status 404 is returned if a playlist with {id} does not exist or if it does but starts in the future (with allowed tolerance equals 1 hour in future).
      parameters:
        - in: path
          name: id
          required: true
          schema:
            type: integer
        - $ref: "#/components/parameters/fields"
        - $ref: "#/components/parameters/expand"
      responses:
        "200":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Playlist"
            application/xml:
              schema:
                $ref: "#/components/schemas/Playlist"
          description: The playlist
        "404":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
            application/xml:
              schema:
                $ref: "#/components/schemas/Error"
          description: Playlist not found or is in the future
      summary: Get a Playlist by id
      tags:
        - Playlist
  /shows:
    get:
      description: |
        **Terminology**: Spinitron defines a *show* as a radio program. A show can have one or more *schedules*,
        each of which may specify either an *occurence* or a *repetition*, which represents a set of occurences.
        Thus scheduled shows have occurences that, for example, may be displayed in a calendar.

        In the response, `items` is an array of objects representing occurences of scheduled shows.

        You may optionally filter `items` to a datetime *range* by including in the request {start} and/or {end}
        parameters, both of which must be no more than one hour in the past. An occurence starting at {end} is
        included in the reponse.

        `itmes` can include occurences that begin *or* end within the filter range. A show that goes on air before
        {start} appears in `items` if it ends *after* but not *at* {start}. An occurence starting at or before {end}
        is included.

        If the request omits the {start} parameter, the server sets its value to the current time so that the filter
        range's start is always defined. If the request specifies {end} then the requested range is *bounded*,
        otherwise it is *unbounded*.

        For a bounded request, `items` includes *every* occurence of all shows occuring in the range. The only
        difference between objects in `items` representing a given show will be the `start` field value.

        For an unbounded request, `items` includes *only one* occurence per show, specifically, the
        next occurrence after {start} of all shows occuring after {start}.

        Use an unbounded request to get a straight list all shows. Use a bounded request to get a calendar/agenda
        of shows expanded into occurrences by thir shedules and repetitions.

        Objects in `items` are ordered first by `datetime` and then by `id`.
      parameters:
        - description: |
            The datetime starting from items must be returned. Maximum 1 hour in past.
          in: query
          name: start
          schema:
            format: date-time
            type: string
        - description: |
            The ending datetime. Maximum 1 hour in past.
          in: query
          name: end
          schema:
            format: date-time
            type: string
        - $ref: "#/components/parameters/limit"
        - $ref: "#/components/parameters/page"
        - $ref: "#/components/parameters/fields"
        - $ref: "#/components/parameters/expand"
      responses:
        "200":
          content:
            application/json:
              schema:
                allOf:
                  - $ref: "#/components/schemas/BaseIndexResponse"
                  - properties:
                      items:
                        items:
                          $ref: "#/components/schemas/Show"
                        type: array
                    type: object
            application/xml:
              schema:
                allOf:
                  - $ref: "#/components/schemas/BaseIndexResponse"
                  - properties:
                      items:
                        items:
                          $ref: "#/components/schemas/Show"
                        type: array
                    type: object
          description: The shows
        "422":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
            application/xml:
              schema:
                $ref: "#/components/schemas/Error"
          description: |
            Invalid datetimes in filter: either too old or {end} is less than {start}.
      summary: Returns scheduled shows optionally filtered by {start} and/or {end} datetimes
      tags:
        - Show
  "/shows/{id}":
    get:
      description: |
        The response object represents the next occurence of the show specified by {id}.

        Status 404 is returned if a show with {id} does not exist or if it does but all its scheduled occurences elapsed in the past.
      parameters:
        - in: path
          name: id
          required: true
          schema:
            type: integer
        - $ref: "#/components/parameters/fields"
        - $ref: "#/components/parameters/expand"
      responses:
        "200":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Show"
            application/xml:
              schema:
                $ref: "#/components/schemas/Show"
          description: The Show
        "404":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
            application/xml:
              schema:
                $ref: "#/components/schemas/Error"
          description: Show not found or too old
      summary: Get a Show by id
      tags:
        - Show
  /spins:
    get:
      description: |
        Get Spins optionally filtered by a datetime range. Only past Spins will be returned.
      parameters:
        - description: |
            The datetime starting from items must be returned.
          in: query
          name: start
          schema:
            format: date-time
            type: string
        - description: |
            The ending datetime.
          in: query
          name: end
          schema:
            format: date-time
            type: string
        - description: Filter by playlist
          in: query
          name: playlist_id
          schema:
            type: integer
        - description: Filter by show
          in: query
          name: show_id
          schema:
            type: integer
        - $ref: "#/components/parameters/limit"
        - $ref: "#/components/parameters/page"
        - $ref: "#/components/parameters/fields"
        - $ref: "#/components/parameters/expand"
      responses:
        "200":
          content:
            application/json:
              schema:
                allOf:
                  - $ref: "#/components/schemas/BaseIndexResponse"
                  - properties:
                      items:
                        items:
                          $ref: "#/components/schemas/Spin"
                        type: array
                    type: object
            application/xml:
              schema:
                allOf:
                  - $ref: "#/components/schemas/BaseIndexResponse"
                  - properties:
                      items:
                        items:
                          $ref: "#/components/schemas/Spin"
                        type: array
                    type: object
          description: The spins
      summary: Returns spins optionally filtered by {start} and/or {end} datetimes
      tags:
        - Spin
    post:
      description: An endpoint for automation systems to log spins into the spin table.
      requestBody:
        content:
          application/x-www-form-urlencoded:
            schema:
              properties:
                artist:
                  type: string
                composer:
                  type: string
                duration:
                  type: integer
                genre:
                  type: string
                isrc:
                  type: string
                label:
                  type: string
                live:
                  description: |
                    Only when automation params are configured with the "Pass through" mode.
                    Enables "live assist" mode. Default mode is "full automation".
                  type: boolean
                release:
                  type: string
                song:
                  type: string
                start:
                  format: date-time
                  type: string
              required:
                - artist
                - song
              type: object
      responses:
        "201":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Spin"
            application/xml:
              schema:
                $ref: "#/components/schemas/Spin"
          description: The new created Spin.
        "422":
          content:
            application/json:
              schema:
                items:
                  $ref: "#/components/schemas/ValidationError"
                type: array
            application/xml:
              schema:
                items:
                  $ref: "#/components/schemas/ValidationError"
                type: array
          description: Validation failed.
        default:
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
            application/xml:
              schema:
                $ref: "#/components/schemas/Error"
          description: Failed to create the object for unknown reason.
      summary: Log a Spin
      tags:
        - Spin
  "/spins/{id}":
    get:
      parameters:
        - in: path
          name: id
          required: true
          schema:
            type: integer
        - $ref: "#/components/parameters/fields"
        - $ref: "#/components/parameters/expand"
      responses:
        "200":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Spin"
            application/xml:
              schema:
                $ref: "#/components/schemas/Spin"
          description: The spin
        "404":
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/Error"
            application/xml:
              schema:
                $ref: "#/components/schemas/Error"
          description: Spin not found
      summary: Get a Spin by id
      tags:
        - Spin
components:
  parameters:
    expand:
      description: Allows to select extra fields
      in: query
      name: expand
      schema:
        items:
          type: string
        type: array
    fields:
      description: Allows to select only needed fields
      in: query
      name: fields
      schema:
        items:
          type: string
        type: array
    limit:
      description: Amount of items to return
      in: query
      name: count
      schema:
        default: 20
        minimum: 1
        type: integer
    page:
      description: Offset, used together with count
      in: query
      name: page
      schema:
        minimum: 1
        type: integer
  schemas:
    BaseIndexResponse:
      properties:
        _links:
          properties:
            self:
              $ref: "#/components/schemas/Link"
          type: object
        _meta:
          $ref: "#/components/schemas/Pagination"
      type: object
    Error:
      properties:
        code:
          type: integer
        message:
          type: string
        name:
          type: string
        status:
          type: integer
        type:
          type: string
      type: object
    Link:
      properties:
        href:
          type: string
      type: object
    Pagination:
      properties:
        currentPage:
          type: integer
        pageCount:
          type: integer
        perPage:
          type: integer
        totalCount:
          type: integer
      type: object
    Persona:
      description: The `Persona` object describes a radio DJ/host. One person can have multiple personas
      properties:
        _links:
          properties:
            self:
              $ref: "#/components/schemas/Link"
            shows:
              items:
                $ref: "#/components/schemas/Link"
              type: array
          type: object
        bio:
          description: HTML-formatted biography
          example: <p>Besides DJ'ing industrial and experimental music since 1991, Deftly has performed in industrial ...
          type: string
        email:
          description: DJ/host's email address
          example: example@spinitron.com
          format: email
          type: string
        id:
          example: 2832
          type: integer
        image:
          example: https://spinitron.com/images/Persona/28/2832-img_profile-original.jpg
          format: url
          type: string
        name:
          description: On-air DJ/host name
          example: Deftly-D
          type: string
        since:
          description: Since what year has the DJ/host been at the station?
          example: 1991
          format: year
          type: integer
        website:
          description: URL to web site for the DJ/host
          example: https://spinitron.com/example/doesnt/exist
          format: url
          type: string
      type: object
    Playlist:
      properties:
        _links:
          properties:
            persona:
              $ref: "#/components/schemas/Link"
            self:
              $ref: "#/components/schemas/Link"
            show:
              $ref: "#/components/schemas/Link"
            spins:
              $ref: "#/components/schemas/Link"
          type: object
        automation:
          description: Was the playlist created playlists created by a radio station automation system?
          example: false
          type: boolean
        category:
          description: Program/show category
          example: Music
          type: string
        description:
          description: HTML-formatted description of the playlist or program/show
          example: It is a <em>cross-­cultural musical journey united in voices and rhythms</em>.
          type: string
        duration:
          description: Duration in seconds
          example: 3600
          type: integer
        end:
          description: UTC datetime ISO-8601
          example: 2018-03-30T14:00:00+0000
          format: date-time
          type: string
        episode_description:
          description: HTML-formatted description of the episode
          example: <p>Episode description</p>
          type: string
        episode_name:
          description: Title of this episode of the program/show
          type: string
        hide_dj:
          description: Should the client application hide information about the playlist's DJ/host?
          example: false
          type: boolean
        id:
          example: 219992
          type: integer
        image:
          example: https://spinitron.com/images/Show/44/4498/img_show-original.jpg
          format: url
          type: string
        persona_id:
          example: 2832
          type: integer
        show_id:
          example: 4498
          type: integer
        since:
          description: Since what year has the program/show existed?
          example: 1999
          format: year
          type: integer
        start:
          description: UTC datetime ISO-8601
          example: 2018-03-30T13:00:00+0000
          format: date-time
          type: string
        timezone:
          description: Station's time zone
          example: America/Chicago
          type: string
        title:
          description: Program/show title
          example: Transworld Airwaves
          type: string
        url:
          description: URL to web site for the playlist or program/show
          format: url
          type: string
      type: object
    Show:
      description: A `Show` object describes one occurrence of a radio program. A result set may contain multiple occurrences of the same show with difference `start` and `end` values.
      properties:
        _links:
          properties:
            personas:
              items:
                $ref: "#/components/schemas/Link"
              type: array
            playlists:
              $ref: "#/components/schemas/Link"
            self:
              $ref: "#/components/schemas/Link"
          type: object
        category:
          description: Program/show category
          example: Music
          type: string
        description:
          description: HTML-formatted description of the playlist or program/show
          example: <p>Since 2001, <strong>The High Voltage Circumcision</strong> show has delivered a full spectrum barrage of dark hard and experimental music from industrial to noise to idm to ebm to bizarre to audio collage often with a side of live guests, social consciousness, interviews, twisted humor, studio experiments and left turns.</p>
          type: string
        duration:
          description: Duration in seconds
          example: 10800
          type: integer
        end:
          description: UTC datetime ISO-8601
          example: 2018-04-03T02:00:00+0000
          format: date-time
          type: string
        hide_dj:
          description: Should the client application hide information about the show's DJs/hosts?
          example: false
          type: boolean
        id:
          example: 4498
          type: integer
        image:
          example: https://spinitron.com/images/Show/44/4498/img_show-original.jpg
          format: url
          type: string
        one_off:
          description: Is the show a one-off in the schedule instead of repeating?
          example: false
          type: boolean
        since:
          description: Since what year has the program/show existed?
          example: 2001
          format: year
          type: integer
        start:
          description: UTC datetime ISO-8601
          example: 2018-04-02T23:00:00+0000
          format: date-time
          type: string
        timezone:
          description: Station's time zone
          example: America/Chicago
          type: string
        title:
          description: Program/show title
          example: Voidstar Productions’ High Voltage Circumcision Show
          type: string
        url:
          description: URL to web site for the program/show
          example: https://spinitron.com/example/doesnt/exist
          format: url
          type: string
      type: object
    Spin:
      properties:
        _links:
          properties:
            playlist:
              $ref: "#/components/schemas/Link"
            self:
              $ref: "#/components/schemas/Link"
          type: object
        artist:
          example: The Beatles
          type: string
        artist-custom:
          description: Station-specific custom field relating to the song's artist
          type: string
        catalog-number:
          description: Reference number in the record label's catalog
          example: 5C 006-04982
          type: string
        classical:
          description: Is the track's metadata schema "classical" rather than "popular"?
          example: false
          type: boolean
        composer:
          example: Lennon - McCartney
          type: string
        conductor:
          description: For classical music, conducor of the ensemble
          example: Herbert von Karajan
          type: string
        duration:
          description: Duration in seconds
          example: 199
          type: integer
        end:
          description: UTC datetime ISO-8601
          example: 2018-03-30T13:10:25+0000
          format: date-time
          type: string
        ensemble:
          description: For classical music, orchestra, performing ensemble, choir, etc.
          example: Vienna Philharmonic Orchestra
          type: string
        genre:
          example: Pop
          type: string
        id:
          example: 8017277
          type: integer
        image:
          description: Cover art
          example: https://is5-ssl.mzstatic.com/image/thumb/Music3/v4/ef/e8/67/efe8674e-467a-adfe-9f67-8d50860b4f1e/dj.sokyjuyt.jpg/170x170bb.jpg
          format: url
          type: string
        isrc:
          example: GBAYE9901218
          type: string
        iswc:
          example: T-010.434.166-3
          type: string
        label:
          description: Record label, i.e. publisher of the sound recording
          example: Apple Records
          type: string
        label-custom:
          description: Station-specific custom field relating to the record label
          type: string
        local:
          description: Is the artist local to the station?
          example: false
          type: boolean
        medium:
          description: Media format in which the sound recording was reased
          example: 7"
          type: string
        new:
          description: Is this a recent release?
          example: false
          type: boolean
        note:
          description: HTML-formatted DJ annotation of the spin, can include images etc.
          example: B-side of the <strong>original</strong> 7" vinyl in the station's collection.
          type: string
        performers:
          description: For classical music, featured performing artists, e.g. soloists
          example: Rohan DeSaram (cello), Marianne Schroeder (piano)
          type: string
        playlist_id:
          example: 336722
          type: integer
        release:
          example: All Together Now / Hey Bulldog
          type: string
        release-custom:
          description: Station-specific custom field relating to the release
          type: string
        released:
          description: Year of initial release
          example: 1972
          type: integer
        request:
          description: Was the spin requested by a listener?
          example: false
          type: boolean
        song:
          description: Title of the song or track
          example: Hey Bulldog
          type: string
        start:
          description: UTC datetime ISO-8601
          example: 2018-03-30T13:07:08+0000
          format: date-time
          type: string
        timezone:
          description: Station's time zone
          example: America/Chicago
          type: string
        upc:
          description: Universal Product Code of the release
          example: "4006408126775"
          type: string
        va:
          description: Is it a "Various Artists" release?
          example: false
          type: boolean
        work:
          description: For classical music, the main compositional work the track (see `song` field) belongs to
          example: The Marriage of Figaro
          type: string
      type: object
    ValidationError:
      properties:
        field:
          type: string
        message:
          type: string
      type: object
  securitySchemes:
    accessToken:
      in: query
      name: access-token
      type: apiKey
    httpBearer:
      bearerFormat: JWT
      scheme: bearer
      type: http
