Exspotify
View SourceA comprehensive Elixir client for the Spotify Web API with complete coverage of endpoints, type-safe struct parsing, and automatic token management.
Features
- 🎵 Comprehensive API Coverage - 13+ modules covering Albums, Artists, Tracks, Playlists, Search, Player, Shows, Episodes, Audiobooks, and more
- 🏗️ Type-Safe Structs - All API responses parsed into well-defined Elixir structs with proper types
- 🔐 Automatic Token Management - Built-in token handling with automatic refresh support for both client credentials and user authorization flows
Installation
Add exspotify
to your list of dependencies in mix.exs
:
def deps do
[
{:exspotify, "~> 0.1.0"}
]
end
Quick Start
1. Configuration
Add your Spotify app credentials to config/config.exs
:
config :exspotify,
client_id: "your_spotify_client_id",
client_secret: "your_spotify_client_secret",
redirect_uri: "http://localhost:4000/auth/callback" # For user auth flows
2. Basic Usage
# Get an access token
{:ok, token} = Exspotify.TokenManager.get_token()
# Get album information
{:ok, album} = Exspotify.Albums.get_album("4aawyAB9vmqN3uQ7FjRGTy", token)
IO.puts(album.name) # "Global Warming"
# Search for tracks
{:ok, results} = Exspotify.Search.search("Bohemian Rhapsody", "track", token)
track = List.first(results["tracks"].items)
IO.puts("#{track.name} by #{List.first(track.artists).name}")
# Get user's playlists (requires user authorization)
{:ok, playlists} = Exspotify.Playlists.get_current_users_playlists(user_token)
Authentication
Exspotify supports both authentication flows:
Client Credentials Flow (App-only access)
# Automatic token management
{:ok, token} = Exspotify.TokenManager.get_token()
# Manual token management
{:ok, %{"access_token" => token}} = Exspotify.Auth.get_access_token()
Authorization Code Flow (User access)
# 1. Build authorization URL
scopes = ["user-read-private", "playlist-read-private"]
{:ok, auth_url} = Exspotify.Auth.build_authorization_url(scopes, "state123")
# 2. Redirect user to auth_url, they'll return with a code
# 3. Exchange code for tokens
{:ok, %{"access_token" => token, "refresh_token" => refresh}} =
Exspotify.Auth.exchange_code_for_token(code)
# 4. Refresh when needed
{:ok, %{"access_token" => new_token}} =
Exspotify.Auth.refresh_access_token(refresh)
API Coverage
Module | Endpoints | Description |
---|---|---|
Albums | 8 endpoints | Get albums, user's saved albums, new releases |
Artists | 3 endpoints | Get artists, artist albums, top tracks |
Tracks | 5 endpoints | Get tracks, user's saved tracks |
Playlists | 12 endpoints | Full playlist management |
Search | 1 endpoint | Search all content types |
Player | 11 endpoints | Playback control and state |
Users | 6 endpoints | User profiles and social features |
Shows | 5 endpoints | Podcast show management |
Episodes | 5 endpoints | Podcast episode management |
Audiobooks | 5 endpoints | Audiobook management |
Categories | 2 endpoints | Browse categories |
Chapters | 2 endpoints | Audiobook chapters |
Markets | 1 endpoint | Available markets |
Error Handling
Exspotify provides structured error handling with helpful suggestions:
case Exspotify.Albums.get_album("", token) do
{:ok, album} ->
# Handle success
{:error, %Exspotify.Error{type: :empty_id, suggestion: suggestion}} ->
IO.puts("Error: #{suggestion}")
# "album_id cannot be empty"
end
Common error types: :unauthorized
, :not_found
, :rate_limited
, :empty_id
, :invalid_token
Debug Logging
Enable debug logging to troubleshoot API issues:
# In config/dev.exs
config :exspotify, debug: true
This will log all HTTP requests and responses:
[debug] Exspotify API Request: GET https://api.spotify.com/v1/albums/123
[debug] Exspotify API Response: 200 - Success
Type-Safe Responses
All API responses are parsed into structured Elixir types:
{:ok, album} = Exspotify.Albums.get_album("4aawyAB9vmqN3uQ7FjRGTy", token)
# album is an %Exspotify.Structs.Album{} with typed fields:
album.id # String.t()
album.name # String.t()
album.artists # [%Exspotify.Structs.Artist{}]
album.images # [%Exspotify.Structs.Image{}]
album.release_date # String.t() | nil
Configuration Options
config :exspotify,
client_id: "your_client_id", # Required for all flows
client_secret: "your_client_secret", # Required for all flows
redirect_uri: "http://localhost:4000", # Required for user auth
base_url: "https://api.spotify.com/v1", # Optional, for testing
debug: false # Optional, enables request logging
Examples
Get User's Top Artists
{:ok, user_token} = get_user_token() # Your user auth implementation
{:ok, top_artists} = Exspotify.Users.get_user_top_items("artists", user_token, limit: 10)
Enum.each(top_artists.items, fn artist ->
IO.puts("#{artist.name} - #{artist.popularity}% popularity")
end)
Control Playback
# Get current playback state
{:ok, state} = Exspotify.Player.get_playback_state(user_token)
if state do
IO.puts("Currently playing: #{state.item.name}")
# Pause playback
Exspotify.Player.pause_playback(user_token)
end
Search and Create Playlist
# Search for tracks
{:ok, results} = Exspotify.Search.search("indie rock 2023", ["track"], user_token)
track_uris = Enum.map(results["tracks"].items, & &1.uri)
# Create a playlist
{:ok, playlist} = Exspotify.Playlists.create_playlist(
user_id,
"My Indie Rock Mix",
user_token,
%{description: "Generated with Exspotify"}
)
# Add tracks to playlist
Exspotify.Playlists.add_items_to_playlist(
playlist.id,
user_token,
%{uris: Enum.take(track_uris, 20)}
)
Documentation
Full documentation is available on HexDocs.
Contributing
- Fork the repository
- Create your feature branch (
git checkout -b feature/amazing-feature
) - Commit your changes (
git commit -m 'Add amazing feature'
) - Push to the branch (
git push origin feature/amazing-feature
) - Open a Pull Request
License
This project is licensed under the MIT License.
Acknowledgments
- Spotify Web API for providing a comprehensive music platform API
- The Elixir community for excellent HTTP and JSON libraries