{"files":{"SKILL.md":"---\nname: spinitron-v2-api\ndescription: \"Spinitron v2 API skill. Use when working with Spinitron v2 for personas, shows, playlists. Covers 9 endpoints.\"\nversion: 1.0.0\ngenerator: lapsh\n---\n\n# Spinitron v2 API\nAPI version: 1.0.0\n\n## Auth\nBearer bearer | ApiKey access-token in query\n\n## Base URL\nhttps://spinitron.com/api\n\n## Setup\n1. Set Authorization header with Bearer token\n2. GET /personas -- get personas\n3. POST /spins -- create first spin\n\n## Endpoints\n9 endpoints across 4 groups. See references/api-spec.lap for full details.\n\n### Personas\n| Method | Path | Description |\n|--------|------|-------------|\n| GET | /personas | Get Personas |\n| GET | /personas/{id} | Get Persona by id |\n\n### Shows\n| Method | Path | Description |\n|--------|------|-------------|\n| GET | /shows | Returns scheduled shows optionally filtered by {start} and/or {end} datetimes |\n| GET | /shows/{id} | Get a Show by id |\n\n### Playlists\n| Method | Path | Description |\n|--------|------|-------------|\n| GET | /playlists | Returns playlists optionally filtered by {start} and/or {end} datetimes |\n| GET | /playlists/{id} | Get a Playlist by id |\n\n### Spins\n| Method | Path | Description |\n|--------|------|-------------|\n| GET | /spins | Returns spins optionally filtered by {start} and/or {end} datetimes |\n| POST | /spins | Log a Spin |\n| GET | /spins/{id} | Get a Spin by id |\n\n## Common Questions\nMatch user requests to endpoints in references/api-spec.lap. Key patterns:\n- \"List all personas?\" -> GET /personas\n- \"Get persona details?\" -> GET /personas/{id}\n- \"List all shows?\" -> GET /shows\n- \"Get show details?\" -> GET /shows/{id}\n- \"List all playlists?\" -> GET /playlists\n- \"Get playlist details?\" -> GET /playlists/{id}\n- \"List all spins?\" -> GET /spins\n- \"Create a spin?\" -> POST /spins\n- \"Get spin details?\" -> GET /spins/{id}\n- \"How to authenticate?\" -> See Auth section above\n\n## Response Tips\n- Check response schemas in references/api-spec.lap for field details\n- Paginated endpoints accept limit/offset or cursor parameters\n- Create/update endpoints return the modified resource on success\n- Error responses include status codes and descriptions in the spec\n\n## References\n- Full spec: See references/api-spec.lap for complete endpoint details, parameter tables, and response schemas\n\n> Generated from the official API spec by [LAP](https://lap.sh)\n","references/api-spec.lap":"@lap v0.3\n# Machine-readable API spec. Each @endpoint block is one API call.\n@api Spinitron v2 API\n@base https://spinitron.com/api\n@version 1.0.0\n@auth Bearer bearer | ApiKey access-token in query\n@endpoints 9\n@toc personas(2), shows(2), playlists(2), spins(3)\n\n@group personas\n@endpoint GET /personas\n@desc Get Personas\n@optional {name: str # Filter by Persona name, count: int=20 # Amount of items to return, page: int # Offset, used together with count, fields: [str] # Allows to select only needed fields, expand: [str] # Allows to select extra fields}\n@returns(200) The personas\n\n@endpoint GET /personas/{id}\n@desc Get Persona by id\n@required {id: int}\n@optional {fields: [str] # Allows to select only needed fields, expand: [str] # Allows to select extra fields}\n@returns(200) {id: int, name: str, bio: str, since: int(year), email: str(email), website: str(url), image: str(url), _links: map{self: map{href: str}, shows: [map]}} # The Persona\n@errors {404: Persona not found}\n\n@endgroup\n\n@group shows\n@endpoint GET /shows\n@desc Returns scheduled shows optionally filtered by {start} and/or {end} datetimes\n@optional {start: str(date-time) # The datetime starting from items must be returned. Maximum 1 hour in past., end: str(date-time) # The ending datetime. Maximum 1 hour in past., count: int=20 # Amount of items to return, page: int # Offset, used together with count, fields: [str] # Allows to select only needed fields, expand: [str] # Allows to select extra fields}\n@returns(200) The shows\n@errors {422: Invalid datetimes in filter: either too old or {end} is less than {start}.}\n\n@endpoint GET /shows/{id}\n@desc Get a Show by id\n@required {id: int}\n@optional {fields: [str] # Allows to select only needed fields, expand: [str] # Allows to select extra fields}\n@returns(200) {id: int, start: str(date-time), end: str(date-time), duration: int, timezone: str, one_off: bool, category: str, title: str, description: str, since: int(year), url: str(url), hide_dj: bool, image: str(url), _links: map{self: map{href: str}, personas: [map], playlists: map{href: str}}} # The Show\n@errors {404: Show not found or too old}\n\n@endgroup\n\n@group playlists\n@endpoint GET /playlists\n@desc Returns playlists optionally filtered by {start} and/or {end} datetimes\n@optional {start: str(date-time) # The datetime starting from items must be returned. Maximum 1 hour in future., end: str(date-time) # The ending datetime. Maximum 1 hour in future., show_id: int # Filter by show, persona_id: int # Filter by persona, count: int=20 # Amount of items to return, page: int # Offset, used together with count, fields: [str] # Allows to select only needed fields, expand: [str] # Allows to select extra fields}\n@returns(200) The playlists\n\n@endpoint GET /playlists/{id}\n@desc Get a Playlist by id\n@required {id: int}\n@optional {fields: [str] # Allows to select only needed fields, expand: [str] # Allows to select extra fields}\n@returns(200) {id: int, persona_id: int, show_id: int, start: str(date-time), end: str(date-time), duration: int, timezone: str, category: str, title: str, description: str, since: int(year), url: str(url), hide_dj: bool, image: str(url), automation: bool, episode_name: str, episode_description: str, _links: map{self: map{href: str}, persona: map{href: str}, show: map{href: str}, spins: map{href: str}}} # The playlist\n@errors {404: Playlist not found or is in the future}\n\n@endgroup\n\n@group spins\n@endpoint GET /spins\n@desc Returns spins optionally filtered by {start} and/or {end} datetimes\n@optional {start: str(date-time) # The datetime starting from items must be returned., end: str(date-time) # The ending datetime., playlist_id: int # Filter by playlist, show_id: int # Filter by show, count: int=20 # Amount of items to return, page: int # Offset, used together with count, fields: [str] # Allows to select only needed fields, expand: [str] # Allows to select extra fields}\n@returns(200) The spins\n\n@endpoint POST /spins\n@desc Log a Spin\n@returns(201) {id: int, playlist_id: int, start: str(date-time), end: str(date-time), duration: int, timezone: str, image: str(url), classical: bool, artist: str, artist-custom: str, composer: str, release: str, release-custom: str, va: bool, label: str, label-custom: str, released: int, medium: str, genre: str, song: str, note: str, request: bool, local: bool, new: bool, work: str, conductor: str, performers: str, ensemble: str, catalog-number: str, isrc: str, upc: str, iswc: str, _links: map{self: map{href: str}, playlist: map{href: str}}} # The new created Spin.\n@errors {422: Validation failed.}\n\n@endpoint GET /spins/{id}\n@desc Get a Spin by id\n@required {id: int}\n@optional {fields: [str] # Allows to select only needed fields, expand: [str] # Allows to select extra fields}\n@returns(200) {id: int, playlist_id: int, start: str(date-time), end: str(date-time), duration: int, timezone: str, image: str(url), classical: bool, artist: str, artist-custom: str, composer: str, release: str, release-custom: str, va: bool, label: str, label-custom: str, released: int, medium: str, genre: str, song: str, note: str, request: bool, local: bool, new: bool, work: str, conductor: str, performers: str, ensemble: str, catalog-number: str, isrc: str, upc: str, iswc: str, _links: map{self: map{href: str}, playlist: map{href: str}}} # The spin\n@errors {404: Spin not found}\n\n@endgroup\n\n@end\n"}}