openapi: 3.0.0 servers: - url: 'https://spinitron.com/api' info: title: Spinitron v2 API version: 1.0.0 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. tags: - name: Persona - name: Show - name: Playlist - name: Spin security: - httpBearer: [] - accessToken: [] paths: /personas: get: summary: Get Personas tags: - Persona parameters: - name: name in: query description: Filter by Persona name schema: type: string - $ref: '#/components/parameters/limit' - $ref: '#/components/parameters/page' - $ref: '#/components/parameters/fields' - $ref: '#/components/parameters/expand' responses: '200': description: The personas content: application/json: schema: allOf: - $ref: '#/components/schemas/BaseIndexResponse' - type: object properties: items: type: array items: $ref: '#/components/schemas/Persona' application/xml: schema: allOf: - $ref: '#/components/schemas/BaseIndexResponse' - type: object properties: items: type: array items: $ref: '#/components/schemas/Persona' '/personas/{id}': get: summary: Get Persona by id tags: - Persona parameters: - name: id in: path required: true schema: type: integer - $ref: '#/components/parameters/fields' - $ref: '#/components/parameters/expand' responses: '200': description: The Persona content: application/json: schema: $ref: '#/components/schemas/Persona' application/xml: schema: $ref: '#/components/schemas/Persona' '404': description: Persona not found content: application/json: schema: $ref: '#/components/schemas/Error' application/xml: schema: $ref: '#/components/schemas/Error' /shows: get: summary: >- Returns scheduled shows optionally filtered by {start} and/or {end} datetimes 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`. tags: - Show parameters: - name: start description: > The datetime starting from items must be returned. Maximum 1 hour in past. in: query schema: type: string format: date-time - name: end description: | The ending datetime. Maximum 1 hour in past. in: query schema: type: string format: date-time - $ref: '#/components/parameters/limit' - $ref: '#/components/parameters/page' - $ref: '#/components/parameters/fields' - $ref: '#/components/parameters/expand' responses: '200': description: The shows content: application/json: schema: allOf: - $ref: '#/components/schemas/BaseIndexResponse' - type: object properties: items: type: array items: $ref: '#/components/schemas/Show' application/xml: schema: allOf: - $ref: '#/components/schemas/BaseIndexResponse' - type: object properties: items: type: array items: $ref: '#/components/schemas/Show' '422': description: > Invalid datetimes in filter: either too old or {end} is less than {start}. content: application/json: schema: $ref: '#/components/schemas/Error' application/xml: schema: $ref: '#/components/schemas/Error' '/shows/{id}': get: summary: Get a Show by id 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. tags: - Show parameters: - name: id in: path required: true schema: type: integer - $ref: '#/components/parameters/fields' - $ref: '#/components/parameters/expand' responses: '200': description: The Show content: application/json: schema: $ref: '#/components/schemas/Show' application/xml: schema: $ref: '#/components/schemas/Show' '404': description: Show not found or too old content: application/json: schema: $ref: '#/components/schemas/Error' application/xml: schema: $ref: '#/components/schemas/Error' /playlists: get: summary: 'Returns playlists optionally filtered by {start} and/or {end} datetimes' 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. tags: - Playlist parameters: - name: start description: > The datetime starting from items must be returned. Maximum 1 hour in future. in: query schema: type: string format: date-time - name: end description: | The ending datetime. Maximum 1 hour in future. in: query schema: type: string format: date-time - name: show_id description: Filter by show in: query schema: type: integer - name: persona_id description: Filter by persona in: query schema: type: integer - $ref: '#/components/parameters/limit' - $ref: '#/components/parameters/page' - $ref: '#/components/parameters/fields' - $ref: '#/components/parameters/expand' responses: '200': description: The playlists content: application/json: schema: allOf: - $ref: '#/components/schemas/BaseIndexResponse' - type: object properties: items: type: array items: $ref: '#/components/schemas/Playlist' application/xml: schema: allOf: - $ref: '#/components/schemas/BaseIndexResponse' - type: object properties: items: type: array items: $ref: '#/components/schemas/Playlist' '/playlists/{id}': get: summary: Get a Playlist by id 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). tags: - Playlist parameters: - name: id in: path required: true schema: type: integer - $ref: '#/components/parameters/fields' - $ref: '#/components/parameters/expand' responses: '200': description: The playlist content: application/json: schema: $ref: '#/components/schemas/Playlist' application/xml: schema: $ref: '#/components/schemas/Playlist' '404': description: Playlist not found or is in the future content: application/json: schema: $ref: '#/components/schemas/Error' application/xml: schema: $ref: '#/components/schemas/Error' /spins: get: summary: 'Returns spins optionally filtered by {start} and/or {end} datetimes' description: > Get Spins optionally filtered by a datetime range. Only past Spins will be returned. tags: - Spin parameters: - name: start description: | The datetime starting from items must be returned. in: query schema: type: string format: date-time - name: end description: | The ending datetime. in: query schema: type: string format: date-time - name: playlist_id description: Filter by playlist in: query schema: type: integer - name: show_id description: Filter by show in: query schema: type: integer - $ref: '#/components/parameters/limit' - $ref: '#/components/parameters/page' - $ref: '#/components/parameters/fields' - $ref: '#/components/parameters/expand' responses: '200': description: The spins content: application/json: schema: allOf: - $ref: '#/components/schemas/BaseIndexResponse' - type: object properties: items: type: array items: $ref: '#/components/schemas/Spin' application/xml: schema: allOf: - $ref: '#/components/schemas/BaseIndexResponse' - type: object properties: items: type: array items: $ref: '#/components/schemas/Spin' post: summary: Log a Spin tags: - Spin description: An endpoint for automation systems to log spins into the spin table. responses: '201': description: The new created Spin. content: application/json: schema: $ref: '#/components/schemas/Spin' application/xml: schema: $ref: '#/components/schemas/Spin' '422': description: Validation failed. content: application/json: schema: type: array items: $ref: '#/components/schemas/ValidationError' application/xml: schema: type: array items: $ref: '#/components/schemas/ValidationError' default: description: Failed to create the object for unknown reason. content: application/json: schema: $ref: '#/components/schemas/Error' application/xml: schema: $ref: '#/components/schemas/Error' requestBody: content: application/x-www-form-urlencoded: schema: type: object properties: live: description: > Only when automation params are configured with the "Pass through" mode. Enables "live assist" mode. Default mode is "full automation". type: boolean start: type: string format: date-time duration: type: integer artist: type: string release: type: string label: type: string genre: type: string song: type: string composer: type: string isrc: type: string required: - artist - song '/spins/{id}': get: summary: Get a Spin by id tags: - Spin parameters: - name: id in: path required: true schema: type: integer - $ref: '#/components/parameters/fields' - $ref: '#/components/parameters/expand' responses: '200': description: The spin content: application/json: schema: $ref: '#/components/schemas/Spin' application/xml: schema: $ref: '#/components/schemas/Spin' '404': description: Spin not found content: application/json: schema: $ref: '#/components/schemas/Error' application/xml: schema: $ref: '#/components/schemas/Error' components: parameters: limit: name: count description: Amount of items to return in: query schema: type: integer minimum: 1 default: 20 page: name: page description: 'Offset, used together with count' in: query schema: type: integer minimum: 1 fields: name: fields description: Allows to select only needed fields in: query schema: type: array items: type: string expand: name: expand description: Allows to select extra fields in: query schema: type: array items: type: string securitySchemes: httpBearer: type: http scheme: bearer bearerFormat: JWT accessToken: type: apiKey in: query name: access-token schemas: Persona: description: The `Persona` object describes a radio DJ/host. One person can have multiple personas type: object properties: id: type: integer example: 2832 name: type: string description: On-air DJ/host name example: Deftly-D bio: type: string description: HTML-formatted biography example:

Besides DJ'ing industrial and experimental music since 1991, Deftly has performed in industrial ... since: type: integer format: year description: Since what year has the DJ/host been at the station? example: 1991 email: type: string format: email description: DJ/host's email address example: "example@spinitron.com" website: type: string format: url description: URL to web site for the DJ/host example: "https://spinitron.com/example/doesnt/exist" image: type: string format: url example: https://spinitron.com/images/Persona/28/2832-img_profile-original.jpg _links: type: object properties: self: $ref: '#/components/schemas/Link' shows: type: array items: $ref: '#/components/schemas/Link' Show: type: object 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: id: type: integer example: 4498 start: type: string format: date-time description: UTC datetime ISO-8601 example: "2018-04-02T23:00:00+0000" end: type: string format: date-time description: UTC datetime ISO-8601 example: "2018-04-03T02:00:00+0000" duration: type: integer description: Duration in seconds example: 10800 timezone: type: string description: Station's time zone example: America/Chicago one_off: type: boolean description: Is the show a one-off in the schedule instead of repeating? example: false category: type: string description: Program/show category example: Music title: type: string description: Program/show title example: Voidstar Productions’ High Voltage Circumcision Show description: type: string description: HTML-formatted description of the playlist or program/show example:

Since 2001, The High Voltage Circumcision 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.

since: type: integer format: year description: Since what year has the program/show existed? example: 2001 url: type: string format: url description: URL to web site for the program/show example: "https://spinitron.com/example/doesnt/exist" hide_dj: type: boolean description: Should the client application hide information about the show's DJs/hosts? example: false image: type: string format: url example: https://spinitron.com/images/Show/44/4498/img_show-original.jpg _links: type: object properties: self: $ref: '#/components/schemas/Link' personas: type: array items: $ref: '#/components/schemas/Link' playlists: $ref: '#/components/schemas/Link' Playlist: type: object properties: id: type: integer example: 219992 persona_id: type: integer example: 2832 show_id: type: integer example: 4498 start: type: string format: date-time description: UTC datetime ISO-8601 example: 2018-03-30T13:00:00+0000 end: type: string format: date-time description: UTC datetime ISO-8601 example: 2018-03-30T14:00:00+0000 duration: type: integer description: Duration in seconds example: 3600 timezone: type: string description: Station's time zone example: America/Chicago category: type: string description: Program/show category example: Music title: type: string description: Program/show title example: Transworld Airwaves description: type: string description: HTML-formatted description of the playlist or program/show example: It is a cross-­cultural musical journey united in voices and rhythms. since: type: integer format: year description: Since what year has the program/show existed? example: 1999 url: type: string format: url description: URL to web site for the playlist or program/show hide_dj: type: boolean description: Should the client application hide information about the playlist's DJ/host? example: false image: type: string format: url example: https://spinitron.com/images/Show/44/4498/img_show-original.jpg automation: type: boolean description: Was the playlist created playlists created by a radio station automation system? example: false episode_name: type: string description: Title of this episode of the program/show episode_description: type: string description: HTML-formatted description of the episode example:

Episode description

_links: type: object properties: self: $ref: '#/components/schemas/Link' persona: $ref: '#/components/schemas/Link' show: $ref: '#/components/schemas/Link' spins: $ref: '#/components/schemas/Link' Spin: type: object properties: id: type: integer example: 8017277 playlist_id: type: integer example: 336722 start: type: string format: date-time description: UTC datetime ISO-8601 example: 2018-03-30T13:07:08+0000 end: type: string format: date-time description: UTC datetime ISO-8601 example: 2018-03-30T13:10:25+0000 duration: type: integer description: Duration in seconds example: 199 timezone: type: string description: Station's time zone example: America/Chicago image: type: string description: Cover art format: url example: https://is5-ssl.mzstatic.com/image/thumb/Music3/v4/ef/e8/67/efe8674e-467a-adfe-9f67-8d50860b4f1e/dj.sokyjuyt.jpg/170x170bb.jpg classical: type: boolean description: Is the track's metadata schema "classical" rather than "popular"? example: false artist: type: string example: The Beatles artist-custom: type: string description: Station-specific custom field relating to the song's artist composer: type: string example: Lennon - McCartney release: type: string example: All Together Now / Hey Bulldog release-custom: type: string description: Station-specific custom field relating to the release va: type: boolean description: Is it a "Various Artists" release? example: false label: type: string description: Record label, i.e. publisher of the sound recording example: Apple Records label-custom: type: string description: Station-specific custom field relating to the record label released: type: integer description: Year of initial release example: 1972 medium: type: string description: Media format in which the sound recording was reased example: 7" genre: type: string example: Pop song: type: string description: Title of the song or track example: Hey Bulldog note: type: string description: HTML-formatted DJ annotation of the spin, can include images etc. example: B-side of the original 7" vinyl in the station's collection. request: type: boolean description: Was the spin requested by a listener? example: false local: type: boolean description: Is the artist local to the station? example: false new: type: boolean description: Is this a recent release? example: false work: type: string description: For classical music, the main compositional work the track (see `song` field) belongs to example: The Marriage of Figaro conductor: type: string description: For classical music, conducor of the ensemble example: Herbert von Karajan performers: type: string description: For classical music, featured performing artists, e.g. soloists example: Rohan DeSaram (cello), Marianne Schroeder (piano) ensemble: type: string description: For classical music, orchestra, performing ensemble, choir, etc. example: Vienna Philharmonic Orchestra catalog-number: type: string description: Reference number in the record label's catalog example: 5C 006-04982 isrc: type: string example: GBAYE9901218 upc: type: string description: Universal Product Code of the release example: "4006408126775" iswc: type: string example: T-010.434.166-3 _links: type: object properties: self: $ref: '#/components/schemas/Link' playlist: $ref: '#/components/schemas/Link' ValidationError: type: object properties: field: type: string message: type: string Error: type: object properties: name: type: string message: type: string code: type: integer status: type: integer type: type: string Pagination: type: object properties: totalCount: type: integer pageCount: type: integer currentPage: type: integer perPage: type: integer Link: type: object properties: href: type: string BaseIndexResponse: type: object properties: _links: type: object properties: self: $ref: '#/components/schemas/Link' _meta: $ref: '#/components/schemas/Pagination'