spotigo

package module
v1.0.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 12, 2026 License: MIT Imports: 24 Imported by: 0

README

Spotigo

Go Version License codecov CI Release

Spotigo is a Go client library for the Spotify Web API, providing full access to Spotify's music catalog, user data, and playback controls with type safety and idiomatic Go patterns.

Features

  • Complete Spotify Web API coverage - 120+ endpoints implemented
  • Type-safe Go structs - All API responses are strongly-typed structs
  • OAuth2 authentication flows - Client Credentials, Authorization Code, PKCE, and Implicit Grant
  • Token caching - File-based and in-memory caching with secure defaults
  • Automatic retry - Exponential backoff with configurable retry policies
  • Rate limiting support - Automatic handling of rate limit responses
  • Context support - Full context.Context support for cancellation and timeouts
  • Comprehensive error handling - Typed errors matching Spotify API responses
  • Zero external dependencies - Uses only Go standard library (except for testing)

Installation

go get github.com/sv4u/spotigo

Requires Go 1.23 or later.

Prerequisites

Before using Spotigo, you'll need:

  1. Go 1.23 or later - Download from golang.org
  2. Spotify Developer Account - Sign up at developer.spotify.com
  3. Spotify App - Create an app in the Spotify Developer Dashboard to get:
    • Client ID
    • Client Secret (for server-side applications)
    • Redirect URI (for OAuth flows)

Once you have your credentials, set them as environment variables:

export SPOTIGO_CLIENT_ID="your_client_id"
export SPOTIGO_CLIENT_SECRET="your_client_secret"
export SPOTIGO_REDIRECT_URI="http://localhost:8080/callback"  # For OAuth flows

Quick Start

Client Credentials Flow (No User Authentication)

Perfect for accessing public Spotify data without user authentication:

package main

import (
	"context"
	"fmt"
	"log"
	"os"

	"github.com/sv4u/spotigo"
)

func main() {
	// Get credentials from environment variables
	clientID := os.Getenv("SPOTIGO_CLIENT_ID")
	clientSecret := os.Getenv("SPOTIGO_CLIENT_SECRET")

	if clientID == "" || clientSecret == "" {
		log.Fatal("SPOTIGO_CLIENT_ID and SPOTIGO_CLIENT_SECRET must be set")
	}

	// Create authentication manager
	auth, err := spotigo.NewClientCredentials(clientID, clientSecret)
	if err != nil {
		log.Fatalf("Failed to create auth: %v", err)
	}

	// Create client
	client, err := spotigo.NewClient(auth)
	if err != nil {
		log.Fatalf("Failed to create client: %v", err)
	}

	ctx := context.Background()

	// Search for tracks
	results, err := client.Search(ctx, "weezer", "track", &spotigo.SearchOptions{
		Limit: 20,
	})
	if err != nil {
		log.Fatalf("Search failed: %v", err)
	}

	// Display results
	fmt.Println("Search Results:")
	for i, track := range results.Tracks.Items {
		if track != nil {
			artistName := "Unknown"
			if len(track.Artists) > 0 && track.Artists[0] != nil {
				artistName = track.Artists[0].Name
			}
			fmt.Printf("%d. %s by %s\n", i+1, track.Name, artistName)
		}
	}
}
OAuth Flow (User Authentication)

For accessing user-specific data like playlists, saved tracks, and playback control:

package main

import (
	"context"
	"fmt"
	"log"
	"os"

	"github.com/sv4u/spotigo"
)

func main() {
	clientID := os.Getenv("SPOTIGO_CLIENT_ID")
	clientSecret := os.Getenv("SPOTIGO_CLIENT_SECRET")
	redirectURI := os.Getenv("SPOTIGO_REDIRECT_URI")

	if clientID == "" || clientSecret == "" {
		log.Fatal("SPOTIGO_CLIENT_ID and SPOTIGO_CLIENT_SECRET must be set")
	}

	// Create OAuth manager with required scopes
	auth, err := spotigo.NewSpotifyOAuth(
		clientID,
		clientSecret,
		redirectURI,
		"user-read-private user-read-email user-library-read",
	)
	if err != nil {
		log.Fatalf("Failed to create OAuth: %v", err)
	}

	ctx := context.Background()

	// Get authorization code (opens browser automatically)
	code, err := auth.GetAuthorizationCode(ctx, true)
	if err != nil {
		log.Fatalf("Failed to get authorization code: %v", err)
	}

	// Exchange code for tokens
	if err := auth.ExchangeCode(ctx, code); err != nil {
		log.Fatalf("Failed to exchange code: %v", err)
	}

	// Create client
	client, err := spotigo.NewClient(auth)
	if err != nil {
		log.Fatalf("Failed to create client: %v", err)
	}

	// Get current user profile
	user, err := client.CurrentUser(ctx)
	if err != nil {
		log.Fatalf("Failed to get user: %v", err)
	}

	fmt.Printf("Logged in as: %s (%s)\n", user.DisplayName, user.ID)

	// Get saved tracks
	tracks, err := client.CurrentUserSavedTracks(ctx, nil)
	if err != nil {
		log.Fatalf("Failed to get saved tracks: %v", err)
	}

	fmt.Println("\nYour Saved Tracks:")
	for _, item := range tracks.Items {
		if item != nil && item.Track != nil {
			artistName := "Unknown"
			if len(item.Track.Artists) > 0 && item.Track.Artists[0] != nil {
				artistName = item.Track.Artists[0].Name
			}
			fmt.Printf("  %s – %s\n", artistName, item.Track.Name)
		}
	}
}

Authentication

Spotigo supports all OAuth2 flows required by the Spotify Web API:

Client Credentials Flow

Use for accessing public data without user authentication:

auth, err := spotigo.NewClientCredentials(clientID, clientSecret)
client, err := spotigo.NewClient(auth)
Authorization Code Flow

Use for accessing user-specific data:

auth, err := spotigo.NewSpotifyOAuth(
	clientID,
	clientSecret,
	redirectURI,
	"user-read-private user-read-email",
)
code, err := auth.GetAuthorizationCode(ctx, true)
err = auth.ExchangeCode(ctx, code)
client, err := spotigo.NewClient(auth)
PKCE Flow

Use for public clients (mobile apps, SPAs) without client secret:

auth, err := spotigo.NewSpotifyPKCE(
	clientID,
	redirectURI,
	"user-read-private",
)
code, err := auth.GetAuthorizationCode(ctx, true)
err = auth.ExchangeCode(ctx, code)
client, err := spotigo.NewClient(auth)
Environment Variables

Spotigo supports environment variables for configuration:

  • SPOTIGO_CLIENT_ID - Your Spotify app client ID
  • SPOTIGO_CLIENT_SECRET - Your Spotify app client secret
  • SPOTIGO_REDIRECT_URI - OAuth redirect URI
  • SPOTIGO_CLIENT_USERNAME - Username for token caching

Client Configuration

Basic Client
client, err := spotigo.NewClient(auth)
Client with Options
import (
	"net/http"
	"time"

	"github.com/sv4u/spotigo"
)

// Custom HTTP client
httpClient := &http.Client{
	Timeout: 30 * time.Second,
}

// Custom cache handler (set on auth manager, not client)
cache := spotigo.NewFileCacheHandler("/path/to/cache", "username")
auth.CacheHandler = cache

// Custom retry configuration
retryConfig := &spotigo.RetryConfig{
	MaxRetries:     3,
	StatusRetries: 3,
	StatusForcelist: []int{429, 500, 502, 503, 504},
	BackoffFactor:  0.3,
}

// Create client with options
client, err := spotigo.NewClient(
	auth,
	spotigo.WithHTTPClient(httpClient),
	spotigo.WithRetryConfig(retryConfig),
	spotigo.WithLanguage("en"),
	spotigo.WithRequestTimeout(10*time.Second),
)

API Usage Examples

import (
	"context"
	"fmt"
	"log"

	"github.com/sv4u/spotigo"
)

ctx := context.Background()

// Search for tracks
results, err := client.Search(ctx, "Blinding Lights", "track", &spotigo.SearchOptions{
	Limit:  10,
	Market: "US",
})
if err != nil {
	log.Fatal(err)
}

for _, track := range results.Tracks.Items {
	if track != nil {
		fmt.Println(track.Name)
	}
}
Get Track by ID, URI, or URL

Spotigo accepts multiple input formats and automatically parses them:

import (
	"context"
	"github.com/sv4u/spotigo"
)

// All of these work:
track1, _ := client.Track(ctx, "4iV5W9uYEdYUVa79Axb7Rh")                    // Raw ID
track2, _ := client.Track(ctx, "spotify:track:4iV5W9uYEdYUVa79Axb7Rh")    // URI
track3, _ := client.Track(ctx, "https://open.spotify.com/track/4iV5W9uYEdYUVa79Axb7Rh") // URL
Pagination
import (
	"context"
	"fmt"
	"log"

	"github.com/sv4u/spotigo"
)

// Get first page
tracks, err := client.AlbumTracks(ctx, albumID, nil)
if err != nil {
	log.Fatal(err)
}

// Iterate through all pages
for tracks != nil {
	for _, item := range tracks.Items {
		if item != nil && item.Track != nil {
			fmt.Println(item.Track.Name)
		}
	}

	// Get next page
	if tracks.Next != "" {
		tracks, err = tracks.Next()
		if err != nil {
			log.Fatal(err)
		}
	} else {
		break
	}
}
Error Handling
import (
	"context"
	"fmt"

	"github.com/sv4u/spotigo"
)

track, err := client.Track(ctx, trackID)
if err != nil {
	// Check error type
	if spotifyErr, ok := err.(*spotigo.SpotifyError); ok {
		switch spotifyErr.HTTPStatus {
		case 404:
			fmt.Println("Track not found")
		case 401:
			fmt.Println("Authentication required")
		case 429:
			fmt.Println("Rate limit exceeded")
			if delay, ok := spotifyErr.RetryAfter(); ok {
				fmt.Printf("Retry after: %v\n", delay)
			}
		default:
			fmt.Printf("API error: %v\n", spotifyErr)
		}
	} else {
		fmt.Printf("Unexpected error: %v\n", err)
	}
	return
}

// Use track
fmt.Println(track.Name)
Context for Timeouts and Cancellation
import (
	"context"
	"fmt"
	"time"

	"github.com/sv4u/spotigo"
)

// Create context with timeout
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()

// Use context in API call
track, err := client.Track(ctx, trackID)
if err != nil {
	if err == context.DeadlineExceeded {
		fmt.Println("Request timed out")
	} else if err == context.Canceled {
		fmt.Println("Request canceled")
	} else {
		fmt.Printf("Error: %v\n", err)
	}
}

Type Safety

All API responses are strongly-typed Go structs:

import (
	"context"
	"fmt"
	"log"

	"github.com/sv4u/spotigo"
)

// Track is a typed struct, not a map
track, err := client.Track(ctx, trackID)
if err != nil {
	log.Fatal(err)
}

// Direct field access with type safety
fmt.Println(track.Name)           // string
fmt.Println(track.DurationMs)     // int
fmt.Println(track.Popularity)     // int
fmt.Println(track.Explicit)      // bool

// Nested structs are also typed
if len(track.Artists) > 0 {
	artist := track.Artists[0]
	fmt.Println(artist.Name)      // string
	fmt.Println(artist.ID)        // string
}

// Optional fields use pointers
if track.Album != nil {
	fmt.Println(track.Album.Name)
}

Token Caching

Token caching helps avoid unnecessary re-authentication. You can configure caching when setting up your authentication manager.

File Cache (Default)

Tokens are automatically cached to a file when you set a cache handler:

// Cache to default location (.cache-username)
cache := spotigo.NewFileCacheHandler("", "username")
auth.CacheHandler = cache

Note: The cache handler must be set on the auth manager (before creating the client), not on the client itself.

Memory Cache

For short-lived applications or testing (tokens are lost when the program exits):

cache := spotigo.NewMemoryCacheHandler()
auth.CacheHandler = cache
Custom Cache Path
cache := spotigo.NewFileCacheHandler("/path/to/cache.json", "")
auth.CacheHandler = cache

Retry Logic

Spotigo automatically retries failed requests with exponential backoff:

import (
	"github.com/sv4u/spotigo"
)

retryConfig := &spotigo.RetryConfig{
	MaxRetries:     3,              // Maximum retry attempts
	StatusRetries: 3,               // Retries for status codes
	StatusForcelist: []int{429, 500, 502, 503, 504}, // Retryable status codes
	BackoffFactor:  0.3,            // Backoff multiplier
	RetryAfterHeader: true,         // Respect Retry-After header
}

client, err := spotigo.NewClient(auth, spotigo.WithRetryConfig(retryConfig))

Examples

See the examples directory for complete, runnable examples:

  • basic_search.go - Search without authentication
  • oauth_flow.go - Complete OAuth authorization flow
  • user_profile.go - Get user info and saved content

Each example is a standalone program. Run them individually:

go run examples/basic_search.go
go run examples/oauth_flow.go
go run examples/user_profile.go

Note: Examples are separate programs and cannot be built together. They are excluded from go test ./... runs. See examples/README.md for more details.

Documentation

Troubleshooting

401 Unauthorized
  • Check that your client ID and secret are correct
  • Verify required scopes are included in your OAuth flow
  • Ensure tokens haven't expired (caching should handle this automatically)
Rate Limiting

Spotigo automatically handles rate limits with retries. If you're hitting limits frequently:

  • Reduce request frequency
  • Use pagination to fetch data in batches
  • Consider caching responses
Token Cache Issues

If you're seeing "incorrect user" errors:

  • Clear the token cache file
  • Use show_dialog=true in OAuth flow to force re-authentication
  • Check that SPOTIGO_CLIENT_USERNAME matches your Spotify username
Search Not Finding Tracks
  • Use the Market parameter to specify a country code
  • Some tracks may not be available in all markets
  • Check track availability using the AvailableMarkets field

Contributing

Contributions are welcome! Please see CONTRIBUTING.md for guidelines.

License

MIT License - see LICENSE for details.

Attribution

This project is a Go rewrite of Spotipy, a lightweight Python library for the Spotify Web API. Original Spotipy library by Paul Lamere.

Documentation

Overview

Package spotigo provides a Go client library for the Spotify Web API.

This library provides full access to Spotify's music catalog, user data, and playback controls with type safety and idiomatic Go patterns.

Quick Start:

auth := spotigo.NewClientCredentials("client_id", "client_secret")
client, err := spotigo.NewClient(auth)
if err != nil {
	panic(err)
}

track, err := client.Track(context.Background(), "track_id")

For more information, see:

Index

Constants

View Source
const (
	// EnvCachePath is the environment variable for custom cache path
	EnvCachePath = "SPOTIGO_CACHE_PATH"
	// DefaultCacheFilename is the default cache filename
	DefaultCacheFilename = ".cache"
)
View Source
const (
	// DefaultAPIPrefix is the default Spotify Web API base URL
	DefaultAPIPrefix = "https://api.spotify.com/v1/"
	// DefaultTimeout is the default request timeout
	DefaultTimeout = 5 * time.Second
	// DefaultMaxRetries is the default maximum number of retries
	DefaultMaxRetries = 3
)
View Source
const (
	// AuthURL is the Spotify OAuth2 authorization endpoint
	AuthURL = "https://accounts.spotify.com/authorize"
	// TokenURL is the Spotify OAuth2 token endpoint
	TokenURL = "https://accounts.spotify.com/api/token"
)
View Source
const (
	EnvClientID     = "SPOTIGO_CLIENT_ID"
	EnvClientSecret = "SPOTIGO_CLIENT_SECRET"
	EnvRedirectURI  = "SPOTIGO_REDIRECT_URI"
	EnvUsername     = "SPOTIGO_CLIENT_USERNAME"
)

Environment variable names for OAuth credentials

Variables

View Source
var SupportedCountryCodes = map[string]bool{}/* 177 elements not displayed */

SupportedCountryCodes is the list of supported country codes (96 countries as of latest API) TODO: Consider fetching from Spotify's /markets endpoint for accuracy

Functions

func GenerateRandomState

func GenerateRandomState() (string, error)

GenerateRandomState generates a random state string for CSRF protection

func GetHostPort

func GetHostPort(netloc string) (string, *int)

GetHostPort parses host and port from a network location string (host:port format) Returns (host, port) where port is nil if not specified

func GetID

func GetID(uri string, entityType ...string) (string, error)

GetID extracts a Spotify ID from URI, URL, or raw ID entityType is optional and used for validation

func GetURI

func GetURI(id, entityType string) (string, error)

GetURI converts an ID to Spotify URI format

func HandleOAuthError

func HandleOAuthError(httpError error, body []byte) error

HandleOAuthError parses OAuth errors from HTTP responses (JSON or text)

func IsURI

func IsURI(uri string) bool

IsURI checks if a string is a valid Spotify URI

func NormalizeScope

func NormalizeScope(scope interface{}) string

NormalizeScope converts scope input to normalized space-separated string Accepts string (comma-separated), slice of strings, or empty/nil

func ParseAuthResponseURL

func ParseAuthResponseURL(responseURL string) (string, string, error)

ParseAuthResponseURL parses the authorization response URL to extract code and state Returns (code, state, error)

func ValidateCountryCode

func ValidateCountryCode(code string) bool

ValidateCountryCode validates an ISO 3166-1 alpha-2 country code Returns true if the code is in Spotify's supported countries list

func WrapHTTPError

func WrapHTTPError(err error, statusCode int, method string, url string, body []byte, headers map[string][]string) error

WrapHTTPError wraps an HTTP error with Spotify error information. Always creates a SpotifyError for HTTP error status codes (>= 400), even if err is nil. If err is provided, it will be wrapped; otherwise, the SpotifyError is returned directly.

func WrapJSONError

func WrapJSONError(err error) error

WrapJSONError wraps JSON decode errors with context

func WrapRetryError

func WrapRetryError(err error, url string, reason string) error

WrapRetryError wraps errors that occur during retry attempts

Types

type Actions

type Actions struct {
	InterruptingPlayback  bool `json:"interrupting_playback"`
	Pausing               bool `json:"pausing"`
	Resuming              bool `json:"resuming"`
	Seeking               bool `json:"seeking"`
	SkippingNext          bool `json:"skipping_next"`
	SkippingPrev          bool `json:"skipping_prev"`
	TogglingRepeatContext bool `json:"toggling_repeat_context"`
	TogglingShuffle       bool `json:"toggling_shuffle"`
	TogglingRepeatTrack   bool `json:"toggling_repeat_track"`
	TransferringPlayback  bool `json:"transferring_playback"`
}

Actions represents available actions

type Album

type Album struct {
	AlbumType            string                   `json:"album_type"`
	Artists              []Artist                 `json:"artists"`
	AvailableMarkets     []string                 `json:"available_markets"`
	Copyrights           []Copyright              `json:"copyrights"`
	ExternalIDs          *ExternalIDs             `json:"external_ids"`
	ExternalURLs         *ExternalURLs            `json:"external_urls"`
	Genres               []string                 `json:"genres"`
	Href                 string                   `json:"href"`
	ID                   string                   `json:"id"`
	Images               []Image                  `json:"images"`
	Label                string                   `json:"label"`
	Name                 string                   `json:"name"`
	Popularity           int                      `json:"popularity"`
	ReleaseDate          string                   `json:"release_date"`
	ReleaseDatePrecision string                   `json:"release_date_precision"`
	Restrictions         *Restrictions            `json:"restrictions,omitempty"`
	Tracks               *Paging[SimplifiedTrack] `json:"tracks"`
	TotalTracks          int                      `json:"total_tracks"`
	Type                 string                   `json:"type"`
	URI                  string                   `json:"uri"`
}

Album represents a full album object

type AlbumTracksOptions

type AlbumTracksOptions struct {
	Market string // ISO 3166-1 alpha-2 country code
	Limit  int    // Default: 20, Max: 50
	Offset int    // Default: 0
}

AlbumTracksOptions holds options for AlbumTracks

type AlbumsResponse

type AlbumsResponse struct {
	Albums []Album `json:"albums"`
}

AlbumsResponse represents a response with multiple albums

type AnalysisBar

type AnalysisBar struct {
	Start      float64 `json:"start"`
	Duration   float64 `json:"duration"`
	Confidence float64 `json:"confidence"`
}

AnalysisBar represents a bar in audio analysis

type AnalysisBeat

type AnalysisBeat struct {
	Start      float64 `json:"start"`
	Duration   float64 `json:"duration"`
	Confidence float64 `json:"confidence"`
}

AnalysisBeat represents a beat in audio analysis

type AnalysisMeta

type AnalysisMeta struct {
	AnalyzerVersion string  `json:"analyzer_version"`
	Platform        string  `json:"platform"`
	DetailedStatus  string  `json:"detailed_status"`
	StatusCode      int     `json:"status_code"`
	Timestamp       int64   `json:"timestamp"`
	AnalysisTime    float64 `json:"analysis_time"`
	InputProcess    string  `json:"input_process"`
}

AnalysisMeta represents analysis metadata

type AnalysisSection

type AnalysisSection struct {
	Start                   float64 `json:"start"`
	Duration                float64 `json:"duration"`
	Confidence              float64 `json:"confidence"`
	Loudness                float64 `json:"loudness"`
	Tempo                   float64 `json:"tempo"`
	TempoConfidence         float64 `json:"tempo_confidence"`
	Key                     int     `json:"key"`
	KeyConfidence           float64 `json:"key_confidence"`
	Mode                    int     `json:"mode"`
	ModeConfidence          float64 `json:"mode_confidence"`
	TimeSignature           int     `json:"time_signature"`
	TimeSignatureConfidence float64 `json:"time_signature_confidence"`
}

AnalysisSection represents a section in audio analysis

type AnalysisSegment

type AnalysisSegment struct {
	Start           float64   `json:"start"`
	Duration        float64   `json:"duration"`
	Confidence      float64   `json:"confidence"`
	LoudnessStart   float64   `json:"loudness_start"`
	LoudnessMax     float64   `json:"loudness_max"`
	LoudnessMaxTime float64   `json:"loudness_max_time"`
	LoudnessEnd     float64   `json:"loudness_end"`
	Pitches         []float64 `json:"pitches"`
	Timbre          []float64 `json:"timbre"`
}

AnalysisSegment represents a segment in audio analysis

type AnalysisTatum

type AnalysisTatum struct {
	Start      float64 `json:"start"`
	Duration   float64 `json:"duration"`
	Confidence float64 `json:"confidence"`
}

AnalysisTatum represents a tatum in audio analysis

type AnalysisTrack

type AnalysisTrack struct {
	NumSamples              int     `json:"num_samples"`
	Duration                float64 `json:"duration"`
	SampleMD5               string  `json:"sample_md5"`
	OffsetSeconds           int     `json:"offset_seconds"`
	WindowSeconds           int     `json:"window_seconds"`
	AnalysisSampleRate      int     `json:"analysis_sample_rate"`
	AnalysisChannels        int     `json:"analysis_channels"`
	EndOfFadeIn             float64 `json:"end_of_fade_in"`
	StartOfFadeOut          float64 `json:"start_of_fade_out"`
	Loudness                float64 `json:"loudness"`
	Tempo                   float64 `json:"tempo"`
	TempoConfidence         float64 `json:"tempo_confidence"`
	TimeSignature           int     `json:"time_signature"`
	TimeSignatureConfidence float64 `json:"time_signature_confidence"`
	Key                     int     `json:"key"`
	KeyConfidence           float64 `json:"key_confidence"`
	Mode                    int     `json:"mode"`
	ModeConfidence          float64 `json:"mode_confidence"`
	Codestring              string  `json:"codestring"`
	CodeVersion             float64 `json:"code_version"`
	Echoprintstring         string  `json:"echoprintstring"`
	EchoprintVersion        float64 `json:"echoprint_version"`
	Synchstring             string  `json:"synchstring"`
	SynchVersion            float64 `json:"synch_version"`
	Rhythmstring            string  `json:"rhythmstring"`
	RhythmVersion           float64 `json:"rhythm_version"`
}

AnalysisTrack represents track analysis

type Artist

type Artist struct {
	ExternalURLs *ExternalURLs `json:"external_urls"`
	Followers    *Followers    `json:"followers"`
	Genres       []string      `json:"genres"`
	Href         string        `json:"href"`
	ID           string        `json:"id"`
	Images       []Image       `json:"images"`
	Name         string        `json:"name"`
	Popularity   int           `json:"popularity"`
	Type         string        `json:"type"`
	URI          string        `json:"uri"`
}

Artist represents a full artist object

type ArtistAlbumsOptions

type ArtistAlbumsOptions struct {
	IncludeGroups []string // album, single, appears_on, compilation
	Country       string   // ISO 3166-1 alpha-2 country code
	Limit         int      // Default: 20, Max: 50
	Offset        int      // Default: 0
}

ArtistAlbumsOptions holds options for ArtistAlbums

type ArtistsResponse

type ArtistsResponse struct {
	Artists []Artist `json:"artists"`
}

ArtistsResponse represents a response with multiple artists

type AudioAnalysis

type AudioAnalysis struct {
	Meta     *AnalysisMeta     `json:"meta"`
	Track    *AnalysisTrack    `json:"track"`
	Bars     []AnalysisBar     `json:"bars"`
	Beats    []AnalysisBeat    `json:"beats"`
	Sections []AnalysisSection `json:"sections"`
	Segments []AnalysisSegment `json:"segments"`
	Tatums   []AnalysisTatum   `json:"tatums"`
}

AudioAnalysis represents detailed audio analysis

type AudioFeatures

type AudioFeatures struct {
	Danceability     float64 `json:"danceability"`
	Energy           float64 `json:"energy"`
	Key              int     `json:"key"`
	Loudness         float64 `json:"loudness"`
	Mode             int     `json:"mode"`
	Speechiness      float64 `json:"speechiness"`
	Acousticness     float64 `json:"acousticness"`
	Instrumentalness float64 `json:"instrumentalness"`
	Liveness         float64 `json:"liveness"`
	Valence          float64 `json:"valence"`
	Tempo            float64 `json:"tempo"`
	Type             string  `json:"type"`
	ID               string  `json:"id"`
	URI              string  `json:"uri"`
	TrackHref        string  `json:"track_href"`
	AnalysisURL      string  `json:"analysis_url"`
	DurationMs       int     `json:"duration_ms"`
	TimeSignature    int     `json:"time_signature"`
}

AudioFeatures represents audio features for a track

type Audiobook

type Audiobook struct {
	SimplifiedAudiobook
	Chapters *Paging[Chapter] `json:"chapters"`
}

Audiobook represents a full audiobook object

type AudiobookChaptersOptions

type AudiobookChaptersOptions struct {
	Market string // ISO 3166-1 alpha-2 country code
	Limit  int    // Default: 20, Max: 50
	Offset int    // Default: 0
}

AudiobookChaptersOptions holds options for GetAudiobookChapters

type AudiobooksResponse

type AudiobooksResponse struct {
	Audiobooks []Audiobook `json:"audiobooks"`
}

AudiobooksResponse represents a response with multiple audiobooks

type AuthManager

type AuthManager interface {
	// GetAccessToken retrieves the current access token (returns token string, not TokenInfo)
	GetAccessToken(ctx context.Context) (string, error)
	// GetCachedToken retrieves the cached token info (separate method for getting full token info)
	GetCachedToken(ctx context.Context) (*TokenInfo, error)
	// RefreshToken refreshes the access token if expired
	RefreshToken(ctx context.Context) error
}

AuthManager defines the interface for authentication managers.

Implementations handle OAuth2 flows and token management for the Spotify API. The library provides several implementations:

  • ClientCredentials for client-only authentication
  • SpotifyOAuth for authorization code flow
  • SpotifyPKCE for PKCE flow
  • SpotifyImplicitGrant for implicit grant flow (deprecated)

type Author

type Author struct {
	Name string `json:"name"`
}

Author represents an author

type BrowseCategoriesOptions

type BrowseCategoriesOptions struct {
	Country string // ISO 3166-1 alpha-2 country code
	Locale  string // ISO 639-1 language code and ISO 3166-1 alpha-2 country code
	Limit   int    // Default: 20, Max: 50
	Offset  int    // Default: 0
}

BrowseCategoriesOptions holds options for browse categories

type CacheHandler

type CacheHandler interface {
	// GetCachedToken retrieves a cached token from storage
	// Returns (nil, nil) if token not found (not an error condition)
	// Returns (nil, error) if cache read fails
	GetCachedToken(ctx context.Context) (*TokenInfo, error)

	// SaveTokenToCache saves a token to cache storage
	// Returns error if cache write fails
	SaveTokenToCache(ctx context.Context, token *TokenInfo) error
}

CacheHandler defines the interface for token cache implementations.

Implementations store and retrieve OAuth2 tokens to avoid re-authentication. The library provides two implementations:

  • FileCacheHandler for persistent file-based caching
  • MemoryCacheHandler for in-memory caching

type Category

type Category struct {
	Href  string  `json:"href"`
	Icons []Image `json:"icons"`
	ID    string  `json:"id"`
	Name  string  `json:"name"`
}

Category represents a browse category

type CategoryPlaylistsOptions

type CategoryPlaylistsOptions struct {
	Country string // ISO 3166-1 alpha-2 country code
	Limit   int    // Default: 20, Max: 50
	Offset  int    // Default: 0
}

CategoryPlaylistsOptions holds options for category playlists

type CategoryPlaylistsResponse

type CategoryPlaylistsResponse struct {
	Playlists Paging[SimplifiedPlaylist] `json:"playlists"`
}

CategoryPlaylistsResponse represents category playlists response

type ChangePlaylistDetailsOptions

type ChangePlaylistDetailsOptions struct {
	Name          *string `json:"name,omitempty"`
	Public        *bool   `json:"public,omitempty"`
	Collaborative *bool   `json:"collaborative,omitempty"`
	Description   *string `json:"description,omitempty"`
}

ChangePlaylistDetailsOptions holds options for changing playlist details

type Chapter

type Chapter struct {
	Audiobook            *SimplifiedAudiobook `json:"audiobook,omitempty"`
	AudioPreviewURL      *string              `json:"audio_preview_url"`
	AvailableMarkets     []string             `json:"available_markets"`
	ChapterNumber        int                  `json:"chapter_number"`
	Description          string               `json:"description"`
	HTMLDescription      string               `json:"html_description"`
	DurationMs           int                  `json:"duration_ms"`
	Explicit             bool                 `json:"explicit"`
	ExternalURLs         *ExternalURLs        `json:"external_urls"`
	Href                 string               `json:"href"`
	ID                   string               `json:"id"`
	Images               []Image              `json:"images"`
	IsPlayable           bool                 `json:"is_playable"`
	Languages            []string             `json:"languages"`
	Name                 string               `json:"name"`
	ReleaseDate          string               `json:"release_date"`
	ReleaseDatePrecision string               `json:"release_date_precision"`
	ResumePoint          *ResumePoint         `json:"resume_point,omitempty"`
	Type                 string               `json:"type"`
	URI                  string               `json:"uri"`
	Restrictions         *Restrictions        `json:"restrictions,omitempty"`
}

Chapter represents a chapter object

type Client

type Client struct {
	HTTPClient     *http.Client      // Custom HTTP client (optional)
	AuthManager    AuthManager       // Authentication manager (required)
	CacheHandler   CacheHandler      // Token cache handler (optional)
	APIPrefix      string            // API base URL (default: https://api.spotify.com/v1/)
	Language       string            // Language for localized responses
	RetryConfig    *RetryConfig      // Retry configuration
	RequestTimeout time.Duration     // Request timeout
	Logger         Logger            // Logger for debugging
	Proxies        map[string]string // HTTP proxies
	MaxRetries     int               // Maximum retry attempts
	CountryCodes   []string          // Supported country codes (ISO 3166-1 alpha-2)
}

Client is the main Spotify API client.

It provides methods for accessing all Spotify Web API endpoints. All methods accept context.Context for cancellation and timeouts.

Example:

auth := spotigo.NewClientCredentials("client_id", "client_secret")
client, err := spotigo.NewClient(auth)
if err != nil {
	panic(err)
}

track, err := client.Track(ctx, "4iV5W9uYEdYUVa79Axb7Rh")

func NewClient

func NewClient(authManager AuthManager, opts ...ClientOption) (*Client, error)

NewClient creates a new Spotify API client.

The authManager parameter is required and provides authentication for API requests. Use ClientOption functions to customize the client behavior.

Example:

auth := spotigo.NewClientCredentials("client_id", "client_secret")
client, err := spotigo.NewClient(auth,
	spotigo.WithCacheHandler(cache),
	spotigo.WithLanguage("en"),
)

func (*Client) Album

func (c *Client) Album(ctx context.Context, albumID string, market ...string) (*Album, error)

Album retrieves a single album by ID, URI, or URL

func (*Client) AlbumTracks

func (c *Client) AlbumTracks(ctx context.Context, albumID string, opts *AlbumTracksOptions) (*Paging[SimplifiedTrack], error)

AlbumTracks retrieves tracks from an album

func (*Client) Albums

func (c *Client) Albums(ctx context.Context, albumIDs []string, market ...string) (*AlbumsResponse, error)

Albums retrieves multiple albums by IDs, URIs, or URLs Maximum 20 albums per request

func (*Client) Artist

func (c *Client) Artist(ctx context.Context, artistID string) (*Artist, error)

Artist retrieves a single artist by ID, URI, or URL

func (*Client) ArtistAlbums

func (c *Client) ArtistAlbums(ctx context.Context, artistID string, opts *ArtistAlbumsOptions) (*Paging[SimplifiedAlbum], error)

ArtistAlbums retrieves albums by an artist

func (*Client) ArtistRelatedArtists

func (c *Client) ArtistRelatedArtists(ctx context.Context, artistID string) (*ArtistsResponse, error)

ArtistRelatedArtists retrieves artists related to an artist Note: This endpoint may be deprecated by Spotify

func (*Client) ArtistTopTracks

func (c *Client) ArtistTopTracks(ctx context.Context, artistID, market string) (*TracksResponse, error)

ArtistTopTracks retrieves top tracks for an artist by country

func (*Client) Artists

func (c *Client) Artists(ctx context.Context, artistIDs []string) (*ArtistsResponse, error)

Artists retrieves multiple artists by IDs, URIs, or URLs

func (*Client) AudioAnalysis

func (c *Client) AudioAnalysis(ctx context.Context, trackID string) (*AudioAnalysis, error)

AudioAnalysis retrieves detailed audio analysis for a track

func (*Client) AudioFeatures

func (c *Client) AudioFeatures(ctx context.Context, trackID string) (*AudioFeatures, error)

AudioFeatures retrieves audio features for a track

func (*Client) AudioFeaturesMultiple

func (c *Client) AudioFeaturesMultiple(ctx context.Context, trackIDs []string) ([]AudioFeatures, error)

AudioFeaturesMultiple retrieves audio features for multiple tracks

func (*Client) AvailableMarkets

func (c *Client) AvailableMarkets(ctx context.Context) ([]string, error)

AvailableMarkets retrieves list of available markets

func (*Client) BrowseCategories

func (c *Client) BrowseCategories(ctx context.Context, opts *BrowseCategoriesOptions) (*Paging[Category], error)

BrowseCategories retrieves browse categories

func (*Client) BrowseCategory

func (c *Client) BrowseCategory(ctx context.Context, categoryID string, opts *BrowseCategoriesOptions) (*Category, error)

BrowseCategory retrieves a single category

func (*Client) BrowseCategoryPlaylists

func (c *Client) BrowseCategoryPlaylists(ctx context.Context, categoryID string, opts *CategoryPlaylistsOptions) (*CategoryPlaylistsResponse, error)

BrowseCategoryPlaylists retrieves playlists for a category

func (*Client) BrowseFeaturedPlaylists

func (c *Client) BrowseFeaturedPlaylists(ctx context.Context, opts *FeaturedPlaylistsOptions) (*FeaturedPlaylistsResponse, error)

BrowseFeaturedPlaylists retrieves featured playlists

func (*Client) BrowseNewReleases

func (c *Client) BrowseNewReleases(ctx context.Context, opts *NewReleasesOptions) (*NewReleasesResponse, error)

BrowseNewReleases retrieves new releases

func (*Client) CurrentUser

func (c *Client) CurrentUser(ctx context.Context) (*User, error)

CurrentUser retrieves the current user's profile

func (*Client) CurrentUserAddToQueue

func (c *Client) CurrentUserAddToQueue(ctx context.Context, uri string, deviceID ...string) error

CurrentUserAddToQueue adds an item (track or episode) to the user's playback queue uri: track or episode URI, URL, or ID deviceID: optional device ID to target

func (*Client) CurrentUserDevices

func (c *Client) CurrentUserDevices(ctx context.Context) ([]Device, error)

CurrentUserDevices retrieves user's available devices

func (*Client) CurrentUserFollowPlaylist

func (c *Client) CurrentUserFollowPlaylist(ctx context.Context, playlistID string, public ...bool) error

CurrentUserFollowPlaylist follows a playlist

func (*Client) CurrentUserFollowedArtists

func (c *Client) CurrentUserFollowedArtists(ctx context.Context, opts *FollowedArtistsOptions) (*CursorPaging[Artist], error)

CurrentUserFollowedArtists retrieves user's followed artists

func (*Client) CurrentUserFollowingArtists

func (c *Client) CurrentUserFollowingArtists(ctx context.Context, artistIDs []string) ([]bool, error)

CurrentUserFollowingArtists checks if user follows artists

func (*Client) CurrentUserFollowingUsers

func (c *Client) CurrentUserFollowingUsers(ctx context.Context, userIDs []string) ([]bool, error)

CurrentUserFollowingUsers checks if user follows users

func (*Client) CurrentUserPausePlayback

func (c *Client) CurrentUserPausePlayback(ctx context.Context, opts *PausePlaybackOptions) error

CurrentUserPausePlayback pauses playback

func (*Client) CurrentUserPlaybackState

func (c *Client) CurrentUserPlaybackState(ctx context.Context, opts *CurrentlyPlayingOptions) (*PlaybackState, error)

CurrentUserPlaybackState retrieves current playback state

func (*Client) CurrentUserPlayingTrack

func (c *Client) CurrentUserPlayingTrack(ctx context.Context, opts *CurrentlyPlayingOptions) (*CurrentlyPlaying, error)

CurrentUserPlayingTrack retrieves currently playing track/episode

func (*Client) CurrentUserPlaylists

func (c *Client) CurrentUserPlaylists(ctx context.Context, opts *CurrentUserPlaylistsOptions) (*Paging[SimplifiedPlaylist], error)

CurrentUserPlaylists retrieves playlists for the current user

func (*Client) CurrentUserQueue

func (c *Client) CurrentUserQueue(ctx context.Context) (*QueueResponse, error)

CurrentUserQueue retrieves the user's current playback queue

func (*Client) CurrentUserRecentlyPlayed

func (c *Client) CurrentUserRecentlyPlayed(ctx context.Context, opts *RecentlyPlayedOptions) (*CursorPaging[PlayHistoryItem], error)

CurrentUserRecentlyPlayed retrieves user's recently played tracks

func (*Client) CurrentUserSavedAlbums

func (c *Client) CurrentUserSavedAlbums(ctx context.Context, opts *SavedAlbumsOptions) (*Paging[SavedAlbum], error)

CurrentUserSavedAlbums retrieves user's saved albums

func (*Client) CurrentUserSavedAlbumsAdd

func (c *Client) CurrentUserSavedAlbumsAdd(ctx context.Context, albumIDs []string) error

CurrentUserSavedAlbumsAdd adds albums to user's library

func (*Client) CurrentUserSavedAlbumsContains

func (c *Client) CurrentUserSavedAlbumsContains(ctx context.Context, albumIDs []string) ([]bool, error)

CurrentUserSavedAlbumsContains checks if albums are saved

func (*Client) CurrentUserSavedAlbumsDelete

func (c *Client) CurrentUserSavedAlbumsDelete(ctx context.Context, albumIDs []string) error

CurrentUserSavedAlbumsDelete removes albums from user's library

func (*Client) CurrentUserSavedEpisodes

func (c *Client) CurrentUserSavedEpisodes(ctx context.Context, opts *SavedEpisodesOptions) (*Paging[SavedEpisode], error)

CurrentUserSavedEpisodes retrieves user's saved episodes

func (*Client) CurrentUserSavedEpisodesAdd

func (c *Client) CurrentUserSavedEpisodesAdd(ctx context.Context, episodeIDs []string) error

CurrentUserSavedEpisodesAdd adds episodes to user's library

func (*Client) CurrentUserSavedEpisodesContains

func (c *Client) CurrentUserSavedEpisodesContains(ctx context.Context, episodeIDs []string) ([]bool, error)

CurrentUserSavedEpisodesContains checks if episodes are saved

func (*Client) CurrentUserSavedEpisodesDelete

func (c *Client) CurrentUserSavedEpisodesDelete(ctx context.Context, episodeIDs []string) error

CurrentUserSavedEpisodesDelete removes episodes from user's library

func (*Client) CurrentUserSavedShows

func (c *Client) CurrentUserSavedShows(ctx context.Context, opts *SavedShowsOptions) (*Paging[SavedShow], error)

CurrentUserSavedShows retrieves user's saved shows

func (*Client) CurrentUserSavedShowsAdd

func (c *Client) CurrentUserSavedShowsAdd(ctx context.Context, showIDs []string) error

CurrentUserSavedShowsAdd adds shows to user's library

func (*Client) CurrentUserSavedShowsContains

func (c *Client) CurrentUserSavedShowsContains(ctx context.Context, showIDs []string) ([]bool, error)

CurrentUserSavedShowsContains checks if shows are saved

func (*Client) CurrentUserSavedShowsDelete

func (c *Client) CurrentUserSavedShowsDelete(ctx context.Context, showIDs []string) error

CurrentUserSavedShowsDelete removes shows from user's library

func (*Client) CurrentUserSavedTracks

func (c *Client) CurrentUserSavedTracks(ctx context.Context, opts *SavedTracksOptions) (*Paging[SavedTrack], error)

CurrentUserSavedTracks retrieves user's saved tracks

func (*Client) CurrentUserSavedTracksAdd

func (c *Client) CurrentUserSavedTracksAdd(ctx context.Context, trackIDs []string) error

CurrentUserSavedTracksAdd adds tracks to user's library CurrentUserSavedTracksAdd saves tracks for the current user trackIDs: list of track IDs, URIs, or URLs (empty array is accepted by API but will have no effect)

func (*Client) CurrentUserSavedTracksContains

func (c *Client) CurrentUserSavedTracksContains(ctx context.Context, trackIDs []string) ([]bool, error)

CurrentUserSavedTracksContains checks if tracks are saved

func (*Client) CurrentUserSavedTracksDelete

func (c *Client) CurrentUserSavedTracksDelete(ctx context.Context, trackIDs []string) error

CurrentUserSavedTracksDelete removes tracks from user's library CurrentUserSavedTracksDelete removes saved tracks for the current user trackIDs: list of track IDs, URIs, or URLs (empty array is accepted by API but will have no effect)

func (*Client) CurrentUserSeekToPosition

func (c *Client) CurrentUserSeekToPosition(ctx context.Context, opts *SeekToPositionOptions) error

CurrentUserSeekToPosition seeks to position in currently playing track

func (*Client) CurrentUserSetRepeatMode

func (c *Client) CurrentUserSetRepeatMode(ctx context.Context, opts *SetRepeatModeOptions) error

CurrentUserSetRepeatMode sets repeat mode

func (*Client) CurrentUserSetVolume

func (c *Client) CurrentUserSetVolume(ctx context.Context, opts *SetVolumeOptions) error

CurrentUserSetVolume sets playback volume

func (*Client) CurrentUserSkipToNext

func (c *Client) CurrentUserSkipToNext(ctx context.Context, deviceID ...string) error

CurrentUserSkipToNext skips to next track

func (*Client) CurrentUserSkipToPrevious

func (c *Client) CurrentUserSkipToPrevious(ctx context.Context, deviceID ...string) error

CurrentUserSkipToPrevious skips to previous track

func (*Client) CurrentUserStartPlayback

func (c *Client) CurrentUserStartPlayback(ctx context.Context, opts *StartPlaybackOptions) error

CurrentUserStartPlayback starts or resumes playback

func (*Client) CurrentUserToggleShuffle

func (c *Client) CurrentUserToggleShuffle(ctx context.Context, opts *ToggleShuffleOptions) error

CurrentUserToggleShuffle toggles shuffle mode

func (*Client) CurrentUserTopArtists

func (c *Client) CurrentUserTopArtists(ctx context.Context, opts *TopItemsOptions) (*Paging[Artist], error)

CurrentUserTopArtists retrieves user's top artists

func (*Client) CurrentUserTopTracks

func (c *Client) CurrentUserTopTracks(ctx context.Context, opts *TopItemsOptions) (*Paging[Track], error)

CurrentUserTopTracks retrieves user's top tracks

func (*Client) CurrentUserTransferPlayback

func (c *Client) CurrentUserTransferPlayback(ctx context.Context, deviceIDs []string, opts *TransferPlaybackOptions) error

CurrentUserTransferPlayback transfers playback to a device

func (*Client) CurrentUserUnfollowPlaylist

func (c *Client) CurrentUserUnfollowPlaylist(ctx context.Context, playlistID string) error

CurrentUserUnfollowPlaylist unfollows a playlist

func (*Client) Episode

func (c *Client) Episode(ctx context.Context, episodeID string, market ...string) (*Episode, error)

Episode retrieves a single episode by ID, URI, or URL

func (*Client) Episodes

func (c *Client) Episodes(ctx context.Context, episodeIDs []string, market ...string) (*EpisodesResponse, error)

Episodes retrieves multiple episodes by IDs, URIs, or URLs

func (*Client) GetAudiobook

func (c *Client) GetAudiobook(ctx context.Context, audiobookID string, market ...string) (*Audiobook, error)

GetAudiobook retrieves a single audiobook by ID, URI, or URL

func (*Client) GetAudiobookChapters

func (c *Client) GetAudiobookChapters(ctx context.Context, audiobookID string, opts *AudiobookChaptersOptions) (*Paging[Chapter], error)

GetAudiobookChapters retrieves chapters from an audiobook

func (*Client) GetAudiobooks

func (c *Client) GetAudiobooks(ctx context.Context, audiobookIDs []string, market ...string) (*AudiobooksResponse, error)

GetAudiobooks retrieves multiple audiobooks by IDs, URIs, or URLs

func (*Client) Next

func (c *Client) Next(ctx context.Context, paging interface{}) (interface{}, error)

Next retrieves the next page from a paginated result Returns (nil, nil) if no next page available (not an error, matching Spotipy behavior)

func (*Client) Playlist

func (c *Client) Playlist(ctx context.Context, playlistID string, opts *PlaylistOptions) (*Playlist, error)

Playlist retrieves a playlist by ID

func (*Client) PlaylistAddItems

func (c *Client) PlaylistAddItems(ctx context.Context, playlistID string, items []string, position ...int) (*PlaylistSnapshotID, error)

PlaylistAddItems adds items (tracks or episodes) to a playlist items: list of track/episode URIs, URLs, or IDs (empty array is accepted by API but will have no effect) position: optional position to insert items (0-based)

func (*Client) PlaylistChangeDetails

func (c *Client) PlaylistChangeDetails(ctx context.Context, playlistID string, opts *ChangePlaylistDetailsOptions) error

PlaylistChangeDetails changes playlist details

func (*Client) PlaylistCoverImage

func (c *Client) PlaylistCoverImage(ctx context.Context, playlistID string) ([]Image, error)

PlaylistCoverImage retrieves the playlist cover image

func (*Client) PlaylistIsFollowing

func (c *Client) PlaylistIsFollowing(ctx context.Context, playlistID string, userIDs []string) ([]bool, error)

PlaylistIsFollowing checks if users follow a playlist

func (*Client) PlaylistRemoveItems

func (c *Client) PlaylistRemoveItems(ctx context.Context, playlistID string, items []PlaylistItemToRemove, snapshotID ...string) (*PlaylistSnapshotID, error)

PlaylistRemoveItems removes items from a playlist Note: Spotify DELETE with body requires special handling

func (*Client) PlaylistReorderItems

func (c *Client) PlaylistReorderItems(ctx context.Context, playlistID string, opts *ReorderItemsOptions) (*PlaylistSnapshotID, error)

PlaylistReorderItems reorders items in a playlist

func (*Client) PlaylistReplaceItems

func (c *Client) PlaylistReplaceItems(ctx context.Context, playlistID string, items []string) (*PlaylistSnapshotID, error)

PlaylistReplaceItems replaces all items in a playlist items: list of track/episode URIs, URLs, or IDs

func (*Client) PlaylistTracks

func (c *Client) PlaylistTracks(ctx context.Context, playlistID string, opts *PlaylistTracksOptions) (*Paging[PlaylistTrack], error)

PlaylistTracks retrieves tracks from a playlist

func (*Client) PlaylistUploadCoverImage

func (c *Client) PlaylistUploadCoverImage(ctx context.Context, playlistID string, imageData []byte) error

PlaylistUploadCoverImage uploads a custom cover image for a playlist imageData: JPEG image data (base64 encoded, max 256KB)

func (*Client) Previous

func (c *Client) Previous(ctx context.Context, paging interface{}) (interface{}, error)

Previous retrieves the previous page from a paginated result Returns (nil, nil) if no previous page available (not an error, matching Spotipy behavior)

func (*Client) RecommendationGenreSeeds

func (c *Client) RecommendationGenreSeeds(ctx context.Context) ([]string, error)

RecommendationGenreSeeds retrieves available genre seeds for recommendations Note: This endpoint may be deprecated by Spotify

func (*Client) Recommendations

func (c *Client) Recommendations(ctx context.Context, opts *RecommendationsOptions) (*RecommendationsResponse, error)

Recommendations retrieves track recommendations

func (*Client) Search

func (c *Client) Search(ctx context.Context, query, searchType string, opts *SearchOptions) (*SearchResponse, error)

Search performs a search query searchType: comma-separated types: 'artist', 'album', 'track', 'playlist', 'show', 'episode', 'audiobook'

func (*Client) Show

func (c *Client) Show(ctx context.Context, showID string, market ...string) (*Show, error)

Show retrieves a single show by ID, URI, or URL

func (*Client) ShowEpisodes

func (c *Client) ShowEpisodes(ctx context.Context, showID string, opts *ShowEpisodesOptions) (*Paging[SimplifiedEpisode], error)

ShowEpisodes retrieves episodes from a show

func (*Client) Shows

func (c *Client) Shows(ctx context.Context, showIDs []string, market ...string) (*ShowsResponse, error)

Shows retrieves multiple shows by IDs, URIs, or URLs

func (*Client) Track

func (c *Client) Track(ctx context.Context, trackID string, market ...string) (*Track, error)

Track retrieves a single track by ID, URI, or URL.

The trackID parameter can be:

The optional market parameter restricts results to a specific country. If not provided, results may vary by user's country.

Example:

track, err := client.Track(ctx, "4iV5W9uYEdYUVa79Axb7Rh", "US")
if err != nil {
	// Handle error
}
fmt.Println(track.Name)

See also: Tracks for retrieving multiple tracks.

func (*Client) Tracks

func (c *Client) Tracks(ctx context.Context, trackIDs []string, market ...string) (*TracksResponse, error)

Tracks retrieves multiple tracks by IDs, URIs, or URLs Maximum 50 tracks per request

func (*Client) User

func (c *Client) User(ctx context.Context, userID string) (*PublicUser, error)

User retrieves a user's profile by ID

func (*Client) UserFollowArtists

func (c *Client) UserFollowArtists(ctx context.Context, artistIDs []string) error

UserFollowArtists follows artists UserFollowArtists follows one or more artists artistIDs: list of artist IDs, URIs, or URLs (empty array is accepted by API but will have no effect)

func (*Client) UserFollowUsers

func (c *Client) UserFollowUsers(ctx context.Context, userIDs []string) error

UserFollowUsers follows one or more users userIDs: list of user IDs, URIs, or URLs (empty array is accepted by API but will have no effect)

func (*Client) UserPlaylistCreate

func (c *Client) UserPlaylistCreate(ctx context.Context, userID string, opts *CreatePlaylistOptions) (*Playlist, error)

UserPlaylistCreate creates a new playlist for a user

func (*Client) UserUnfollowArtists

func (c *Client) UserUnfollowArtists(ctx context.Context, artistIDs []string) error

UserUnfollowArtists unfollows artists UserUnfollowArtists unfollows one or more artists artistIDs: list of artist IDs, URIs, or URLs (empty array is accepted by API but will have no effect)

func (*Client) UserUnfollowUsers

func (c *Client) UserUnfollowUsers(ctx context.Context, userIDs []string) error

UserUnfollowUsers unfollows users UserUnfollowUsers unfollows one or more users userIDs: list of user IDs, URIs, or URLs (empty array is accepted by API but will have no effect)

type ClientCredentials

type ClientCredentials struct {
	*SpotifyAuthBase
}

ClientCredentials implements the Client Credentials OAuth2 flow

func NewClientCredentials

func NewClientCredentials(clientID, clientSecret string) (*ClientCredentials, error)

NewClientCredentials creates a new Client Credentials auth manager Client Credentials flow doesn't require redirect URI

func (*ClientCredentials) GetAccessToken

func (c *ClientCredentials) GetAccessToken(ctx context.Context) (string, error)

GetAccessToken retrieves or refreshes the access token

func (*ClientCredentials) GetCachedToken

func (c *ClientCredentials) GetCachedToken(ctx context.Context) (*TokenInfo, error)

GetCachedToken returns the cached token info

func (*ClientCredentials) RefreshToken

func (c *ClientCredentials) RefreshToken(ctx context.Context) error

RefreshToken refreshes the access token

type ClientOption

type ClientOption func(*Client)

ClientOption is a functional option for client configuration. Use With* functions to configure the client.

func WithAPIPrefix

func WithAPIPrefix(prefix string) ClientOption

WithAPIPrefix sets a custom API prefix

func WithCacheHandler

func WithCacheHandler(handler CacheHandler) ClientOption

WithCacheHandler sets a cache handler

func WithHTTPClient

func WithHTTPClient(httpClient *http.Client) ClientOption

WithHTTPClient sets a custom HTTP client

func WithLanguage

func WithLanguage(lang string) ClientOption

WithLanguage sets the Accept-Language header

func WithLogger

func WithLogger(logger Logger) ClientOption

WithLogger sets a custom logger

func WithRequestTimeout

func WithRequestTimeout(timeout time.Duration) ClientOption

WithRequestTimeout sets the request timeout

func WithRetryConfig

func WithRetryConfig(config *RetryConfig) ClientOption

WithRetryConfig sets the retry configuration

type Context

type Context struct {
	ExternalURLs *ExternalURLs `json:"external_urls"`
	Href         string        `json:"href"`
	Type         string        `json:"type"`
	URI          string        `json:"uri"`
}

Context represents playback context

type Copyright struct {
	Text string `json:"text"`
	Type string `json:"type"`
}

Copyright represents copyright information

type CreatePlaylistOptions

type CreatePlaylistOptions struct {
	Name          string `json:"name"`
	Public        *bool  `json:"public,omitempty"`
	Collaborative *bool  `json:"collaborative,omitempty"`
	Description   string `json:"description,omitempty"`
}

CreatePlaylistOptions holds options for creating a playlist

type CurrentUserPlaylistsOptions

type CurrentUserPlaylistsOptions struct {
	Limit  int // Default: 20, Max: 50
	Offset int // Default: 0
}

CurrentUserPlaylistsOptions holds options for current user playlists

type CurrentlyPlaying

type CurrentlyPlaying struct {
	Timestamp            int64       `json:"timestamp"`
	Context              *Context    `json:"context"`
	ProgressMs           int         `json:"progress_ms"`
	IsPlaying            bool        `json:"is_playing"`
	Item                 interface{} `json:"item"` // Can be Track or Episode
	CurrentlyPlayingType string      `json:"currently_playing_type"`
	Actions              *Actions    `json:"actions"`
}

CurrentlyPlaying represents currently playing track/episode

type CurrentlyPlayingOptions

type CurrentlyPlayingOptions struct {
	Market          string // ISO 3166-1 alpha-2 country code
	AdditionalTypes string // Comma-separated: track, episode
}

CurrentlyPlayingOptions holds options for currently playing

type CursorPaging

type CursorPaging[T any] struct {
	Href     string   `json:"href"`
	Items    []T      `json:"items"`
	Limit    int      `json:"limit"`
	Next     *string  `json:"next"`
	Previous *string  `json:"previous,omitempty"` // Some cursor pagination has previous
	Cursors  *Cursors `json:"cursors"`
	Total    int      `json:"total"`
}

CursorPaging represents a cursor-based paginated response

func NextCursor

func NextCursor[T any](c *Client, ctx context.Context, paging interface{ GetNext() *string }) (*CursorPaging[T], error)

NextCursor retrieves the next page from a cursor-based paginated result with type safety Returns (nil, nil) if no next page available (not an error)

func PreviousCursor

func PreviousCursor[T any](c *Client, ctx context.Context, paging interface{ GetPrevious() *string }) (*CursorPaging[T], error)

PreviousCursor retrieves the previous page from a cursor-based paginated result with type safety Returns (nil, nil) if no previous page available (not an error)

func (*CursorPaging[T]) GetNext

func (p *CursorPaging[T]) GetNext() *string

GetNext returns the next page URL

func (*CursorPaging[T]) GetPrevious

func (p *CursorPaging[T]) GetPrevious() *string

GetPrevious returns the previous page URL

type Cursors

type Cursors struct {
	After  *string `json:"after"`
	Before *string `json:"before"`
}

Cursors represents pagination cursors

type DefaultLogger

type DefaultLogger struct{}

DefaultLogger wraps Go's standard log package. Provides basic logging functionality with INFO, WARN, and ERROR levels. Debug logging is disabled by default.

func (*DefaultLogger) Debug

func (l *DefaultLogger) Debug(format string, v ...interface{})

func (*DefaultLogger) Error

func (l *DefaultLogger) Error(format string, v ...interface{})

func (*DefaultLogger) Info

func (l *DefaultLogger) Info(format string, v ...interface{})

func (*DefaultLogger) Warn

func (l *DefaultLogger) Warn(format string, v ...interface{})

type Device

type Device struct {
	ID               *string `json:"id"`
	IsActive         bool    `json:"is_active"`
	IsPrivateSession bool    `json:"is_private_session"`
	IsRestricted     bool    `json:"is_restricted"`
	Name             string  `json:"name"`
	Type             string  `json:"type"`
	VolumePercent    *int    `json:"volume_percent"`
}

Device represents a playback device

type Episode

type Episode struct {
	SimplifiedEpisode
	Show *SimplifiedShow `json:"show"`
}

Episode represents a full episode object

type EpisodesResponse

type EpisodesResponse struct {
	Episodes []Episode `json:"episodes"`
}

EpisodesResponse represents a response with multiple episodes

type ErrorResponse

type ErrorResponse struct {
	Error struct {
		Status  int    `json:"status"`
		Message string `json:"message"`
		Reason  string `json:"reason"`
	} `json:"error"`
}

ErrorResponse represents the JSON structure of Spotify error responses

type ExplicitContentSettings

type ExplicitContentSettings struct {
	FilterEnabled bool `json:"filter_enabled"`
	FilterLocked  bool `json:"filter_locked"`
}

ExplicitContentSettings represents explicit content settings

type ExternalIDs

type ExternalIDs struct {
	ISRC *string `json:"isrc,omitempty"`
	EAN  *string `json:"ean,omitempty"`
	UPC  *string `json:"upc,omitempty"`
}

ExternalIDs represents external identifiers

type ExternalURLs

type ExternalURLs struct {
	Spotify string `json:"spotify"`
}

ExternalURLs represents external URLs

type FeaturedPlaylistsOptions

type FeaturedPlaylistsOptions struct {
	Country   string // ISO 3166-1 alpha-2 country code
	Locale    string // ISO 639-1 language code
	Limit     int    // Default: 20, Max: 50
	Offset    int    // Default: 0
	Timestamp string // ISO 8601 timestamp
}

FeaturedPlaylistsOptions holds options for featured playlists

type FeaturedPlaylistsResponse

type FeaturedPlaylistsResponse struct {
	Message   string                     `json:"message"`
	Playlists Paging[SimplifiedPlaylist] `json:"playlists"`
}

FeaturedPlaylistsResponse represents featured playlists response

type FileCacheHandler

type FileCacheHandler struct {
	CachePath string
	Username  string
}

FileCacheHandler implements file-based token caching

func NewFileCacheHandler

func NewFileCacheHandler(cachePath, username string) (*FileCacheHandler, error)

NewFileCacheHandler creates a new file cache handler

func (*FileCacheHandler) GetCachedToken

func (f *FileCacheHandler) GetCachedToken(ctx context.Context) (*TokenInfo, error)

GetCachedToken retrieves token from cache file Returns (nil, nil) if file doesn't exist (not an error) Returns (nil, error) for actual errors

func (*FileCacheHandler) SaveTokenToCache

func (f *FileCacheHandler) SaveTokenToCache(ctx context.Context, token *TokenInfo) error

SaveTokenToCache saves token to cache file using atomic write pattern

type FollowedArtistsOptions

type FollowedArtistsOptions struct {
	Type  string // "artist" (required)
	After string // Cursor for pagination
	Limit int    // Default: 20, Max: 50
}

FollowedArtistsOptions holds options for followed artists

type Followers

type Followers struct {
	Href  *string `json:"href,omitempty"`
	Total int     `json:"total"`
}

Followers represents follower information

type Image

type Image struct {
	URL    string `json:"url"`
	Height *int   `json:"height,omitempty"`
	Width  *int   `json:"width,omitempty"`
}

Image represents an image

type Logger

type Logger interface {
	Debug(format string, v ...interface{})
	Info(format string, v ...interface{})
	Warn(format string, v ...interface{})
	Error(format string, v ...interface{})
}

Logger defines a simple logging interface for the client. Implement this interface to provide custom logging behavior.

type MemoryCacheHandler

type MemoryCacheHandler struct {
	Token *TokenInfo
	// contains filtered or unexported fields
}

MemoryCacheHandler implements in-memory token caching

func NewMemoryCacheHandler

func NewMemoryCacheHandler() *MemoryCacheHandler

NewMemoryCacheHandler creates a new in-memory cache handler

func (*MemoryCacheHandler) GetCachedToken

func (m *MemoryCacheHandler) GetCachedToken(ctx context.Context) (*TokenInfo, error)

GetCachedToken retrieves token from memory

func (*MemoryCacheHandler) SaveTokenToCache

func (m *MemoryCacheHandler) SaveTokenToCache(ctx context.Context, token *TokenInfo) error

SaveTokenToCache saves token to memory

type Narrator

type Narrator struct {
	Name string `json:"name"`
}

Narrator represents a narrator

type NewReleasesOptions

type NewReleasesOptions struct {
	Country string // ISO 3166-1 alpha-2 country code
	Limit   int    // Default: 20, Max: 50
	Offset  int    // Default: 0
}

NewReleasesOptions holds options for new releases

type NewReleasesResponse

type NewReleasesResponse struct {
	Albums Paging[SimplifiedAlbum] `json:"albums"`
}

NewReleasesResponse represents new releases response

type PaginationHelper

type PaginationHelper interface {
	GetNext() *string
	GetPrevious() *string
}

PaginationHelper is an interface for paginated results

type Paging

type Paging[T any] struct {
	Href     string  `json:"href"`
	Items    []T     `json:"items"`
	Limit    int     `json:"limit"`
	Next     *string `json:"next"`
	Offset   int     `json:"offset"`
	Previous *string `json:"previous"`
	Total    int     `json:"total"`
}

Paging represents a paginated response (offset-based)

func NextGeneric

func NextGeneric[T any](c *Client, ctx context.Context, paging interface{ GetNext() *string }) (*Paging[T], error)

NextGeneric retrieves the next page from a paginated result with type safety using generics Returns (nil, nil) if no next page available (not an error) This is a type-safe version of Next. The old Next method is kept for backward compatibility but will be removed after comprehensive testing.

func PreviousGeneric

func PreviousGeneric[T any](c *Client, ctx context.Context, paging interface{ GetPrevious() *string }) (*Paging[T], error)

PreviousGeneric retrieves the previous page from a paginated result with type safety using generics Returns (nil, nil) if no previous page available (not an error) This is a type-safe version of Previous. The old Previous method is kept for backward compatibility but will be removed after comprehensive testing.

func (*Paging[T]) GetNext

func (p *Paging[T]) GetNext() *string

GetNext returns the next page URL

func (*Paging[T]) GetPrevious

func (p *Paging[T]) GetPrevious() *string

GetPrevious returns the previous page URL

type PausePlaybackOptions

type PausePlaybackOptions struct {
	DeviceID string // Device ID
}

PausePlaybackOptions holds options for pausing playback

type PlayHistoryItem

type PlayHistoryItem struct {
	Track    Track    `json:"track"`
	PlayedAt string   `json:"played_at"` // ISO 8601 timestamp
	Context  *Context `json:"context,omitempty"`
}

PlayHistoryItem represents a play history item

type PlaybackState

type PlaybackState struct {
	Device               *Device     `json:"device"`
	RepeatState          string      `json:"repeat_state"`
	ShuffleState         bool        `json:"shuffle_state"`
	Context              *Context    `json:"context"`
	Timestamp            int64       `json:"timestamp"`
	ProgressMs           int         `json:"progress_ms"`
	IsPlaying            bool        `json:"is_playing"`
	Item                 interface{} `json:"item"` // Can be Track or Episode
	CurrentlyPlayingType string      `json:"currently_playing_type"`
	Actions              *Actions    `json:"actions"`
}

PlaybackState represents playback state

type Playlist

type Playlist struct {
	SimplifiedPlaylist
	Followers   *Followers `json:"followers"`
	Description *string    `json:"description"`
}

Playlist represents a full playlist object

type PlaylistAddItemsRequest

type PlaylistAddItemsRequest struct {
	URIs     []string `json:"uris"`
	Position *int     `json:"position,omitempty"`
}

PlaylistAddItemsRequest represents the request body for adding items to a playlist Format matches Spotify Web API specification: {"uris": [...], "position": int} uris: Array of Spotify URIs (spotify:track:... or spotify:episode:...) position: Optional position to insert items (0-based index)

type PlaylistItem

type PlaylistItem struct {
	AddedAt string      `json:"added_at"`
	AddedBy *PublicUser `json:"added_by"`
	IsLocal bool        `json:"is_local"`
	Track   *Track      `json:"track,omitempty"`
	Episode *Episode    `json:"episode,omitempty"`
}

PlaylistItem represents an item in a playlist (track or episode)

type PlaylistItemToRemove

type PlaylistItemToRemove struct {
	URI       string `json:"uri"`
	Positions []int  `json:"positions,omitempty"`
}

PlaylistItemToRemove represents an item to remove from a playlist PlaylistItemToRemove represents an item to remove from a playlist Format matches Spotify Web API specification: {"uri": "...", "positions": [...]} uri: Spotify URI of the track/episode to remove positions: Optional array of positions where the item appears (0-based indices)

type PlaylistOptions

type PlaylistOptions struct {
	Fields          string // Comma-separated field list
	AdditionalTypes string // Comma-separated types: track, episode
	Market          string // ISO 3166-1 alpha-2 country code
}

PlaylistOptions holds options for playlist retrieval

type PlaylistRemoveItemsRequest

type PlaylistRemoveItemsRequest struct {
	Tracks     []PlaylistItemToRemove `json:"tracks"`
	SnapshotID *string                `json:"snapshot_id,omitempty"`
}

PlaylistRemoveItemsRequest represents the request body for removing items from a playlist Format matches Spotify Web API specification: {"tracks": [...], "snapshot_id": "..."} tracks: Array of PlaylistItemToRemove objects snapshot_id: Optional playlist snapshot ID for optimistic concurrency

type PlaylistSnapshotID

type PlaylistSnapshotID struct {
	SnapshotID string `json:"snapshot_id"`
}

PlaylistSnapshotID represents a playlist snapshot ID response

type PlaylistTrack

type PlaylistTrack struct {
	AddedAt string      `json:"added_at"`
	AddedBy *PublicUser `json:"added_by"`
	IsLocal bool        `json:"is_local"`
	Track   interface{} `json:"track"` // Can be Track or Episode
}

PlaylistTrack represents a track in a playlist

type PlaylistTracksOptions

type PlaylistTracksOptions struct {
	Fields          string // Comma-separated field list
	Limit           int    // Default: 100, Max: 100
	Offset          int    // Default: 0
	Market          string // ISO 3166-1 alpha-2 country code
	AdditionalTypes string // Comma-separated types: track, episode
}

PlaylistTracksOptions holds options for playlist tracks

type PlaylistTracksRef

type PlaylistTracksRef struct {
	Href  string `json:"href"`
	Total int    `json:"total"`
}

PlaylistTracksRef represents a reference to playlist tracks

type PublicUser

type PublicUser struct {
	DisplayName  *string       `json:"display_name"`
	ExternalURLs *ExternalURLs `json:"external_urls"`
	Followers    *Followers    `json:"followers"`
	Href         string        `json:"href"`
	ID           string        `json:"id"`
	Images       []Image       `json:"images"`
	Type         string        `json:"type"`
	URI          string        `json:"uri"`
}

PublicUser represents a public user profile

type QueueItem

type QueueItem interface{}

QueueItem represents an item in the queue (can be Track or Episode) Use interface{} with type assertion to handle both types Callers should use type assertion: item.(*Track) or item.(*Episode)

type QueueResponse

type QueueResponse struct {
	CurrentlyPlaying *CurrentlyPlaying `json:"currently_playing"`
	Queue            []QueueItem       `json:"queue"`
}

QueueResponse represents the user's playback queue

type RecentlyPlayedOptions

type RecentlyPlayedOptions struct {
	Limit  int    // Default: 20, Max: 50
	After  *int64 // Unix timestamp in milliseconds
	Before *int64 // Unix timestamp in milliseconds
}

RecentlyPlayedOptions holds options for recently played

type RecommendationSeed

type RecommendationSeed struct {
	AfterFilteringSize int    `json:"afterFilteringSize"`
	AfterRelinkingSize int    `json:"afterRelinkingSize"`
	Href               string `json:"href"`
	ID                 string `json:"id"`
	InitialPoolSize    int    `json:"initialPoolSize"`
	Type               string `json:"type"`
}

RecommendationSeed represents a recommendation seed

type RecommendationsOptions

type RecommendationsOptions struct {
	SeedArtists            []string // Up to 5 artist IDs
	SeedGenres             []string // Up to 5 genre names
	SeedTracks             []string // Up to 5 track IDs
	Limit                  int      // Default: 20, Max: 100
	Market                 string   // ISO 3166-1 alpha-2 country code
	MinAcousticness        *float64
	MaxAcousticness        *float64
	TargetAcousticness     *float64
	MinDanceability        *float64
	MaxDanceability        *float64
	TargetDanceability     *float64
	MinDurationMs          *int
	MaxDurationMs          *int
	TargetDurationMs       *int
	MinEnergy              *float64
	MaxEnergy              *float64
	TargetEnergy           *float64
	MinInstrumentalness    *float64
	MaxInstrumentalness    *float64
	TargetInstrumentalness *float64
	MinKey                 *int
	MaxKey                 *int
	TargetKey              *int
	MinLiveness            *float64
	MaxLiveness            *float64
	TargetLiveness         *float64
	MinLoudness            *float64
	MaxLoudness            *float64
	TargetLoudness         *float64
	MinMode                *int
	MaxMode                *int
	TargetMode             *int
	MinPopularity          *int
	MaxPopularity          *int
	TargetPopularity       *int
	MinSpeechiness         *float64
	MaxSpeechiness         *float64
	TargetSpeechiness      *float64
	MinTempo               *float64
	MaxTempo               *float64
	TargetTempo            *float64
	MinTimeSignature       *int
	MaxTimeSignature       *int
	TargetTimeSignature    *int
	MinValence             *float64
	MaxValence             *float64
	TargetValence          *float64
}

RecommendationsOptions holds options for recommendations

type RecommendationsResponse

type RecommendationsResponse struct {
	Seeds  []RecommendationSeed `json:"seeds"`
	Tracks []Track              `json:"tracks"`
}

RecommendationsResponse represents a recommendations response

type ReorderItemsOptions

type ReorderItemsOptions struct {
	RangeStart   int     `json:"range_start"`
	InsertBefore int     `json:"insert_before"`
	RangeLength  *int    `json:"range_length,omitempty"`
	SnapshotID   *string `json:"snapshot_id,omitempty"`
}

ReorderItemsOptions holds options for reordering playlist items

type Restrictions

type Restrictions struct {
	Reason string `json:"reason,omitempty"`
}

Restrictions represents content restrictions

type ResumePoint

type ResumePoint struct {
	FullyPlayed      bool `json:"fully_played"`
	ResumePositionMs int  `json:"resume_position_ms"`
}

ResumePoint represents a resume point

type RetryConfig

type RetryConfig struct {
	MaxRetries       int
	StatusRetries    int
	StatusForcelist  []int
	BackoffFactor    float64
	RetryAfterHeader bool
}

RetryConfig holds retry configuration

func DefaultRetryConfig

func DefaultRetryConfig() *RetryConfig

DefaultRetryConfig returns default retry configuration

type SavedAlbum

type SavedAlbum struct {
	AddedAt string `json:"added_at"`
	Album   Album  `json:"album"`
}

SavedAlbum represents a saved album

type SavedAlbumsOptions

type SavedAlbumsOptions struct {
	Limit  int // Default: 20, Max: 50
	Offset int // Default: 0
}

SavedAlbumsOptions holds options for saved albums

type SavedEpisode

type SavedEpisode struct {
	AddedAt string  `json:"added_at"`
	Episode Episode `json:"episode"`
}

SavedEpisode represents a saved episode

type SavedEpisodesOptions

type SavedEpisodesOptions struct {
	Market string // ISO 3166-1 alpha-2 country code
	Limit  int    // Default: 20, Max: 50
	Offset int    // Default: 0
}

SavedEpisodesOptions holds options for saved episodes

type SavedShow

type SavedShow struct {
	AddedAt string `json:"added_at"`
	Show    Show   `json:"show"`
}

SavedShow represents a saved show

type SavedShowsOptions

type SavedShowsOptions struct {
	Limit  int // Default: 20, Max: 50
	Offset int // Default: 0
}

SavedShowsOptions holds options for saved shows

type SavedTrack

type SavedTrack struct {
	AddedAt string `json:"added_at"`
	Track   Track  `json:"track"`
}

SavedTrack represents a saved track

type SavedTracksOptions

type SavedTracksOptions struct {
	Market string // ISO 3166-1 alpha-2 country code
	Limit  int    // Default: 20, Max: 50
	Offset int    // Default: 0
}

SavedTracksOptions holds options for saved tracks

type SearchOptions

type SearchOptions struct {
	Market          string // ISO 3166-1 alpha-2 country code or "from_token"
	Limit           int    // Default: 10, Min: 1, Max: 50
	Offset          int    // Default: 0
	IncludeExternal string // "audio" to include external audio content
}

SearchOptions holds options for search

type SearchResponse

type SearchResponse struct {
	Tracks     *Paging[Track]               `json:"tracks,omitempty"`
	Artists    *Paging[Artist]              `json:"artists,omitempty"`
	Albums     *Paging[SimplifiedAlbum]     `json:"albums,omitempty"`
	Playlists  *Paging[SimplifiedPlaylist]  `json:"playlists,omitempty"`
	Shows      *Paging[SimplifiedShow]      `json:"shows,omitempty"`
	Episodes   *Paging[SimplifiedEpisode]   `json:"episodes,omitempty"`
	Audiobooks *Paging[SimplifiedAudiobook] `json:"audiobooks,omitempty"`
}

SearchResponse represents a search response

type SeekToPositionOptions

type SeekToPositionOptions struct {
	PositionMs int    // Position in milliseconds
	DeviceID   string // Device ID
}

SeekToPositionOptions holds options for seeking

type SetRepeatModeOptions

type SetRepeatModeOptions struct {
	State    string // "track", "context", "off"
	DeviceID string // Device ID
}

SetRepeatModeOptions holds options for setting repeat mode

type SetVolumeOptions

type SetVolumeOptions struct {
	VolumePercent int    // 0-100
	DeviceID      string // Device ID
}

SetVolumeOptions holds options for setting volume

type Show

type Show struct {
	SimplifiedShow
	Episodes *Paging[SimplifiedEpisode] `json:"episodes"`
}

Show represents a full show object

type ShowEpisodesOptions

type ShowEpisodesOptions struct {
	Market string // ISO 3166-1 alpha-2 country code
	Limit  int    // Default: 20, Max: 50
	Offset int    // Default: 0
}

ShowEpisodesOptions holds options for ShowEpisodes

type ShowsResponse

type ShowsResponse struct {
	Shows []Show `json:"shows"`
}

ShowsResponse represents a response with multiple shows

type SimplifiedAlbum

type SimplifiedAlbum struct {
	AlbumType            string        `json:"album_type"`
	Artists              []Artist      `json:"artists"`
	AvailableMarkets     []string      `json:"available_markets"`
	ExternalURLs         *ExternalURLs `json:"external_urls"`
	Href                 string        `json:"href"`
	ID                   string        `json:"id"`
	Images               []Image       `json:"images"`
	Name                 string        `json:"name"`
	ReleaseDate          string        `json:"release_date"`
	ReleaseDatePrecision string        `json:"release_date_precision"`
	Restrictions         *Restrictions `json:"restrictions,omitempty"`
	TotalTracks          int           `json:"total_tracks"`
	Type                 string        `json:"type"`
	URI                  string        `json:"uri"`
}

SimplifiedAlbum represents a simplified album object

type SimplifiedArtist

type SimplifiedArtist struct {
	ExternalURLs *ExternalURLs `json:"external_urls"`
	Href         string        `json:"href"`
	ID           string        `json:"id"`
	Name         string        `json:"name"`
	Type         string        `json:"type"`
	URI          string        `json:"uri"`
}

SimplifiedArtist represents a simplified artist object

type SimplifiedAudiobook

type SimplifiedAudiobook struct {
	Authors          []Author      `json:"authors"`
	AvailableMarkets []string      `json:"available_markets"`
	Copyrights       []Copyright   `json:"copyrights"`
	Description      string        `json:"description"`
	Edition          *string       `json:"edition"`
	Explicit         bool          `json:"explicit"`
	ExternalURLs     *ExternalURLs `json:"external_urls"`
	Href             string        `json:"href"`
	ID               string        `json:"id"`
	Images           []Image       `json:"images"`
	Languages        []string      `json:"languages"`
	MediaType        string        `json:"media_type"`
	Name             string        `json:"name"`
	Narrators        []Narrator    `json:"narrators"`
	Publisher        string        `json:"publisher"`
	Type             string        `json:"type"`
	URI              string        `json:"uri"`
	TotalChapters    int           `json:"total_chapters"`
}

SimplifiedAudiobook represents a simplified audiobook object

type SimplifiedEpisode

type SimplifiedEpisode struct {
	AudioPreviewURL      *string       `json:"audio_preview_url"`
	Description          string        `json:"description"`
	DurationMs           int           `json:"duration_ms"`
	Explicit             bool          `json:"explicit"`
	ExternalURLs         *ExternalURLs `json:"external_urls"`
	Href                 string        `json:"href"`
	ID                   string        `json:"id"`
	Images               []Image       `json:"images"`
	IsExternallyHosted   bool          `json:"is_externally_hosted"`
	IsPlayable           bool          `json:"is_playable"`
	Language             *string       `json:"language"`
	Languages            []string      `json:"languages"`
	Name                 string        `json:"name"`
	ReleaseDate          string        `json:"release_date"`
	ReleaseDatePrecision string        `json:"release_date_precision"`
	Restrictions         *Restrictions `json:"restrictions,omitempty"`
	Type                 string        `json:"type"`
	URI                  string        `json:"uri"`
}

SimplifiedEpisode represents a simplified episode object

type SimplifiedPlaylist

type SimplifiedPlaylist struct {
	Collaborative bool               `json:"collaborative"`
	Description   *string            `json:"description"`
	ExternalURLs  *ExternalURLs      `json:"external_urls"`
	Href          string             `json:"href"`
	ID            string             `json:"id"`
	Images        []Image            `json:"images"`
	Name          string             `json:"name"`
	Owner         *PublicUser        `json:"owner"`
	Public        *bool              `json:"public"`
	SnapshotID    string             `json:"snapshot_id"`
	Tracks        *PlaylistTracksRef `json:"tracks"`
	Type          string             `json:"type"`
	URI           string             `json:"uri"`
}

SimplifiedPlaylist represents a simplified playlist object

type SimplifiedShow

type SimplifiedShow struct {
	AvailableMarkets   []string      `json:"available_markets"`
	Copyrights         []Copyright   `json:"copyrights"`
	Description        string        `json:"description"`
	Explicit           bool          `json:"explicit"`
	ExternalURLs       *ExternalURLs `json:"external_urls"`
	Href               string        `json:"href"`
	ID                 string        `json:"id"`
	Images             []Image       `json:"images"`
	IsExternallyHosted bool          `json:"is_externally_hosted"`
	Languages          []string      `json:"languages"`
	MediaType          string        `json:"media_type"`
	Name               string        `json:"name"`
	Publisher          string        `json:"publisher"`
	Type               string        `json:"type"`
	URI                string        `json:"uri"`
	TotalEpisodes      int           `json:"total_episodes"`
}

SimplifiedShow represents a simplified show object

type SimplifiedTrack

type SimplifiedTrack struct {
	Artists          []SimplifiedArtist `json:"artists"`
	AvailableMarkets []string           `json:"available_markets"`
	DiscNumber       int                `json:"disc_number"`
	DurationMs       int                `json:"duration_ms"`
	Explicit         bool               `json:"explicit"`
	ExternalURLs     *ExternalURLs      `json:"external_urls"`
	Href             string             `json:"href"`
	ID               string             `json:"id"`
	IsPlayable       *bool              `json:"is_playable,omitempty"`
	LinkedFrom       *TrackLink         `json:"linked_from,omitempty"`
	Restrictions     *Restrictions      `json:"restrictions,omitempty"`
	Name             string             `json:"name"`
	PreviewURL       *string            `json:"preview_url,omitempty"`
	TrackNumber      int                `json:"track_number"`
	Type             string             `json:"type"`
	URI              string             `json:"uri"`
	IsLocal          bool               `json:"is_local"`
}

SimplifiedTrack represents a simplified track object

type SpotifyAuthBase

type SpotifyAuthBase struct {
	ClientID        string
	ClientSecret    string
	RedirectURI     string
	Scope           string
	HTTPClient      *http.Client
	TokenInfo       *TokenInfo
	CacheHandler    CacheHandler // Will be defined in cache.go
	Proxies         map[string]string
	RequestsTimeout time.Duration
}

SpotifyAuthBase provides base functionality for all auth managers

func NewSpotifyAuthBase

func NewSpotifyAuthBase(clientID, clientSecret, redirectURI, scope string) (*SpotifyAuthBase, error)

NewSpotifyAuthBase creates a new base auth manager with environment variable fallback

func (*SpotifyAuthBase) AddCustomValuesToTokenInfo

func (b *SpotifyAuthBase) AddCustomValuesToTokenInfo(tokenInfo *TokenInfo) *TokenInfo

AddCustomValuesToTokenInfo adds expires_at field calculated from expires_in

func (*SpotifyAuthBase) Close

func (b *SpotifyAuthBase) Close()

Close closes HTTP client connections (cleanup method)

func (*SpotifyAuthBase) GetAuthHeader

func (b *SpotifyAuthBase) GetAuthHeader() string

GetAuthHeader generates Basic authentication header Format: "Basic {base64(client_id:client_secret)}"

func (*SpotifyAuthBase) IsScopeSubset

func (b *SpotifyAuthBase) IsScopeSubset(requested, granted string) bool

IsScopeSubset checks if requested scopes are subset of granted scopes Both scopes should be space-separated strings Returns true if all requested scopes are in granted scopes

func (*SpotifyAuthBase) IsTokenExpired

func (b *SpotifyAuthBase) IsTokenExpired(tokenInfo *TokenInfo) bool

IsTokenExpired checks if token expires within 60 seconds

func (*SpotifyAuthBase) ParseTokenResponse

func (b *SpotifyAuthBase) ParseTokenResponse(body []byte) (*TokenInfo, error)

ParseTokenResponse parses token response from Spotify and adds expires_at field

type SpotifyBaseException

type SpotifyBaseException interface {
	error
	// contains filtered or unexported methods
}

SpotifyBaseException is a marker interface for all Spotify-specific errors.

All Spotify error types implement this interface to allow type checking.

type SpotifyError

type SpotifyError struct {
	HTTPStatus int
	Code       int
	URL        string // Request URL (separate from message)
	Method     string // HTTP method (optional)
	Message    string // Error message (without URL prefix)
	Reason     string
	Headers    map[string][]string
}

SpotifyError represents an error returned by the Spotify API.

It includes the HTTP status code, error code, message, and optional reason. Use IsRetryable() to check if the error indicates a retryable condition.

Example:

track, err := client.Track(ctx, trackID)
if err != nil {
	if spotifyErr, ok := err.(*SpotifyError); ok {
		if spotifyErr.IsRetryable() {
			// Retry the request
		}
	}
}

func (*SpotifyError) Error

func (e *SpotifyError) Error() string

Error implements the error interface with structured format

func (*SpotifyError) IsRetryable

func (e *SpotifyError) IsRetryable() bool

IsRetryable returns true if the error indicates a retryable condition

func (*SpotifyError) RetryAfter

func (e *SpotifyError) RetryAfter() (time.Duration, bool)

RetryAfter extracts the Retry-After header value if present

type SpotifyImplicitGrant

type SpotifyImplicitGrant struct {
	*SpotifyAuthBase
	State       string
	OpenBrowser bool
	ShowDialog  bool
}

SpotifyImplicitGrant implements the Implicit Grant OAuth2 flow (deprecated)

func NewSpotifyImplicitGrant

func NewSpotifyImplicitGrant(clientID, redirectURI, scope string) (*SpotifyImplicitGrant, error)

NewSpotifyImplicitGrant creates a new Implicit Grant auth manager Implicit Grant doesn't require client secret

func (*SpotifyImplicitGrant) GetAccessToken

func (i *SpotifyImplicitGrant) GetAccessToken(ctx context.Context) (string, error)

GetAccessToken retrieves the access token

func (*SpotifyImplicitGrant) GetAuthURL

func (i *SpotifyImplicitGrant) GetAuthURL(state string, showDialog bool) (string, error)

GetAuthURL generates authorization URL with response_type=token

func (*SpotifyImplicitGrant) GetAuthorizationCode

func (i *SpotifyImplicitGrant) GetAuthorizationCode(ctx context.Context, openBrowser bool) (string, error)

GetAuthorizationCode performs the interactive authorization flow for Implicit Grant

func (*SpotifyImplicitGrant) GetCachedToken

func (i *SpotifyImplicitGrant) GetCachedToken(ctx context.Context) (*TokenInfo, error)

GetCachedToken returns the cached token info

func (*SpotifyImplicitGrant) ParseTokenFromURL

func (i *SpotifyImplicitGrant) ParseTokenFromURL(urlStr string) error

ParseTokenFromURL extracts token from URL fragment Format: #access_token=...&expires_in=...&scope=...&state=...

func (*SpotifyImplicitGrant) RefreshToken

func (i *SpotifyImplicitGrant) RefreshToken(ctx context.Context) error

RefreshToken is not supported in Implicit Grant flow

type SpotifyOAuth

type SpotifyOAuth struct {
	*SpotifyAuthBase
	State       string
	OpenBrowser bool
	ShowDialog  bool
}

SpotifyOAuth implements the Authorization Code OAuth2 flow

func NewSpotifyOAuth

func NewSpotifyOAuth(clientID, clientSecret, redirectURI, scope string) (*SpotifyOAuth, error)

NewSpotifyOAuth creates a new Authorization Code auth manager

func (*SpotifyOAuth) ExchangeCode

func (o *SpotifyOAuth) ExchangeCode(ctx context.Context, code string) error

ExchangeCode exchanges authorization code for tokens

func (*SpotifyOAuth) GetAccessToken

func (o *SpotifyOAuth) GetAccessToken(ctx context.Context) (string, error)

GetAccessToken retrieves or refreshes the access token

func (*SpotifyOAuth) GetAuthURL

func (o *SpotifyOAuth) GetAuthURL(state string, showDialog bool) (string, error)

GetAuthURL generates the authorization URL

func (*SpotifyOAuth) GetAuthorizationCode

func (o *SpotifyOAuth) GetAuthorizationCode(ctx context.Context, openBrowser bool) (string, error)

GetAuthorizationCode performs the interactive authorization flow

func (*SpotifyOAuth) GetCachedToken

func (o *SpotifyOAuth) GetCachedToken(ctx context.Context) (*TokenInfo, error)

GetCachedToken returns the cached token info

func (*SpotifyOAuth) RefreshToken

func (o *SpotifyOAuth) RefreshToken(ctx context.Context) error

RefreshToken refreshes the access token using refresh token

type SpotifyOAuthError

type SpotifyOAuthError struct {
	ErrorType        string
	ErrorDescription string
	AdditionalFields map[string]interface{}
}

SpotifyOAuthError represents an OAuth2 authentication error

func (*SpotifyOAuthError) Error

func (e *SpotifyOAuthError) Error() string

Error implements the error interface

type SpotifyPKCE

type SpotifyPKCE struct {
	*SpotifyAuthBase
	CodeVerifier  string
	CodeChallenge string
	State         string
	OpenBrowser   bool
	ShowDialog    bool
}

SpotifyPKCE implements the PKCE OAuth2 flow

func NewSpotifyPKCE

func NewSpotifyPKCE(clientID, redirectURI, scope string) (*SpotifyPKCE, error)

NewSpotifyPKCE creates a new PKCE auth manager PKCE doesn't require client secret

func (*SpotifyPKCE) ExchangeCode

func (p *SpotifyPKCE) ExchangeCode(ctx context.Context, code string) error

ExchangeCode exchanges authorization code for tokens using code verifier (no client secret)

func (*SpotifyPKCE) GenerateCodeChallenge

func (p *SpotifyPKCE) GenerateCodeChallenge(verifier string) string

GenerateCodeChallenge generates code challenge from verifier using S256 method

func (*SpotifyPKCE) GenerateCodeVerifier

func (p *SpotifyPKCE) GenerateCodeVerifier() (string, error)

GenerateCodeVerifier generates a new code verifier Length is between 43-128 characters (URL-safe base64)

func (*SpotifyPKCE) GetAccessToken

func (p *SpotifyPKCE) GetAccessToken(ctx context.Context) (string, error)

GetAccessToken retrieves or refreshes the access token

func (*SpotifyPKCE) GetAuthURL

func (p *SpotifyPKCE) GetAuthURL(state string, showDialog bool) (string, error)

GetAuthURL generates authorization URL with PKCE parameters

func (*SpotifyPKCE) GetAuthorizationCode

func (p *SpotifyPKCE) GetAuthorizationCode(ctx context.Context, openBrowser bool) (string, error)

GetAuthorizationCode performs the interactive authorization flow (same as SpotifyOAuth)

func (*SpotifyPKCE) GetCachedToken

func (p *SpotifyPKCE) GetCachedToken(ctx context.Context) (*TokenInfo, error)

GetCachedToken returns the cached token info

func (*SpotifyPKCE) RefreshToken

func (p *SpotifyPKCE) RefreshToken(ctx context.Context) error

RefreshToken refreshes the access token using refresh token For PKCE, include client_id in payload (no Basic auth header)

type SpotifyStateError

type SpotifyStateError struct {
	*SpotifyOAuthError
	LocalState  string
	RemoteState string
}

SpotifyStateError represents a state mismatch error in OAuth flow

func (*SpotifyStateError) Error

func (e *SpotifyStateError) Error() string

Error implements the error interface

type StartPlaybackOptions

type StartPlaybackOptions struct {
	DeviceID   string                 // Device ID
	ContextURI string                 // Spotify URI of context (album, artist, playlist)
	URIs       []string               // Array of Spotify URIs
	Offset     map[string]interface{} // Offset object
	PositionMs *int                   // Position in milliseconds
}

StartPlaybackOptions holds options for starting playback

type ToggleShuffleOptions

type ToggleShuffleOptions struct {
	State    bool   // Shuffle state
	DeviceID string // Device ID
}

ToggleShuffleOptions holds options for toggling shuffle

type TokenInfo

type TokenInfo struct {
	AccessToken      string                 `json:"access_token"`
	TokenType        string                 `json:"token_type"`
	ExpiresIn        int                    `json:"expires_in"`
	ExpiresAt        int                    `json:"expires_at"` // Custom field, calculated
	RefreshToken     string                 `json:"refresh_token,omitempty"`
	Scope            string                 `json:"scope"`
	AdditionalFields map[string]interface{} `json:"-"`
}

TokenInfo represents OAuth2 token information returned by Spotify.

It includes the access token, refresh token (if available), expiration time, and granted scopes. The ExpiresAt field is calculated from ExpiresIn.

type TopItemsOptions

type TopItemsOptions struct {
	TimeRange string // "short_term", "medium_term", "long_term" (default: "medium_term")
	Limit     int    // Default: 20, Max: 50
	Offset    int    // Default: 0
}

TopItemsOptions holds options for top items

type Track

type Track struct {
	Album            *SimplifiedAlbum `json:"album"`
	Artists          []Artist         `json:"artists"`
	AvailableMarkets []string         `json:"available_markets"`
	DiscNumber       int              `json:"disc_number"`
	DurationMs       int              `json:"duration_ms"`
	Explicit         bool             `json:"explicit"`
	ExternalIDs      *ExternalIDs     `json:"external_ids"`
	ExternalURLs     *ExternalURLs    `json:"external_urls"`
	Href             string           `json:"href"`
	ID               string           `json:"id"`
	IsPlayable       *bool            `json:"is_playable,omitempty"`
	LinkedFrom       *TrackLink       `json:"linked_from,omitempty"`
	Restrictions     *Restrictions    `json:"restrictions,omitempty"`
	Name             string           `json:"name"`
	Popularity       int              `json:"popularity"`
	PreviewURL       *string          `json:"preview_url,omitempty"`
	TrackNumber      int              `json:"track_number"`
	Type             string           `json:"type"`
	URI              string           `json:"uri"`
	IsLocal          bool             `json:"is_local"`
}

Track represents a full track object

type TrackLink struct {
	ExternalURLs *ExternalURLs `json:"external_urls"`
	Href         string        `json:"href"`
	ID           string        `json:"id"`
	Type         string        `json:"type"`
	URI          string        `json:"uri"`
}

TrackLink represents a link to another track

type TracksResponse

type TracksResponse struct {
	Tracks []Track `json:"tracks"`
}

TracksResponse represents a response with multiple tracks

type TransferPlaybackOptions

type TransferPlaybackOptions struct {
	Play bool // Whether to start playback
}

TransferPlaybackOptions holds options for transferring playback

type User

type User struct {
	Country         *string                  `json:"country"`
	DisplayName     *string                  `json:"display_name"`
	Email           *string                  `json:"email"`
	ExplicitContent *ExplicitContentSettings `json:"explicit_content"`
	ExternalURLs    *ExternalURLs            `json:"external_urls"`
	Followers       *Followers               `json:"followers"`
	Href            string                   `json:"href"`
	ID              string                   `json:"id"`
	Images          []Image                  `json:"images"`
	Product         *string                  `json:"product"`
	Type            string                   `json:"type"`
	URI             string                   `json:"uri"`
}

User represents a full user profile

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL