NestJS API for Spotify Web API integration. Allows Spotify authentication and fetching user's top artists/tracks.
git clone https://github.com/williamosilva/festify-api
cd festify-apiCreate a .env file:
# Spotify (required)
SPOTIFY_CLIENT_ID=your_client_id_here
SPOTIFY_CLIENT_SECRET=your_client_secret_here
CALLBACK_URL=http://localhost:3001/auth/spotify/callback
# Database (required)
MONGO_URI=mongodb://localhost:27017/spotify-app
# URLs (required)
FRONTEND_URL=http://localhost:3000
BACKEND_URL=http://localhost:3001
# Optional
PORT=3001
NODE_ENV=development
BUILD_TARGET=developmentdocker-compose up --buildOR run with Node.js:
npm install
npm run start:devAPI will be available at: http://localhost:3001
GET /auth/spotify- Redirects to Spotify OAuth authorizationGET /auth/spotify/callback- OAuth callback, redirects to frontend with tokensPOST /auth/validate-token- Validate access tokenPOST /auth/logout- Logout and invalidate tokens
GET /spotify/top/:type- Get top artists or tracks (type:artistsortracks)GET /spotify/top/artists- Get user's top artistsGET /spotify/top/tracks- Get user's top tracksGET /spotify/top/artists/processed- Get artists distributed in 3 balanced listsDELETE /spotify/cache- Clear user's cached data
All Spotify endpoints support these optional parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
time_range |
short_term, medium_term, long_term |
medium_term |
Time period for data |
limit |
1-50 |
39 |
Number of items to return |
offset |
0+ |
0 |
Starting index for pagination |
Time Range Options:
short_term- Last 4 weeksmedium_term- Last 6 monthslong_term- Several years of data
Protected endpoints require the header:
Authorization: Bearer YOUR_TOKEN_HERE
POST /auth/validate-token
Request:
{
"accessToken": "BQC4YW9tYXRpYzEyM..."
}Valid token response:
{
"statusCode": 200,
"message": "Token is valid",
"data": {
"isValid": true,
"user": {
"id": "507f1f77bcf86cd799439011",
"spotifyId": "spotify_user_123",
"displayName": "John Doe",
"email": "john@example.com",
"profileImageUrl": "https://i.scdn.co/image/..."
}
}
}Token refresh response (when token expired but refresh successful):
{
"statusCode": 200,
"message": "Token is valid",
"data": {
"isValid": true,
"newAccessToken": "BQC4YW9tYXRpYzEyM...",
"user": {
"id": "507f1f77bcf86cd799439011",
"spotifyId": "spotify_user_123",
"displayName": "John Doe",
"email": "john@example.com",
"profileImageUrl": "https://i.scdn.co/image/..."
}
}
}Invalid token response:
{
"statusCode": 401,
"message": "User not found",
"data": {
"isValid": false,
"error": "User not found"
}
}POST /auth/logout
Request:
{
"accessToken": "BQC4YW9tYXRpYzEyM..."
}Response:
{
"statusCode": 200,
"message": "Logout successful"
}{
"href": "https://api.spotify.com/v1/me/top/artists",
"items": [
{
"id": "4q3ewBCX7sLwd24euuV69X",
"name": "Bad Bunny",
"popularity": 100,
"genres": ["reggaeton", "trap latino"],
"images": [
{
"url": "https://i.scdn.co/image/...",
"height": 640,
"width": 640
}
],
"followers": {
"total": 8000000
},
"external_urls": {
"spotify": "https://open.spotify.com/artist/..."
}
}
],
"limit": 20,
"offset": 0,
"total": 50
}{
"lists": [
{
"id": 1,
"artists": [
{
"name": "Bad Bunny",
"popularity": 100
},
{
"name": "Drake",
"popularity": 95
}
],
"averagePopularity": 97
}
],
"originalTotal": 39,
"processedAt": "2025-01-01T12:00:00Z"
}# 1. Start OAuth flow (redirects to Spotify)
curl http://localhost:3001/auth/spotify
# 2. After user authorizes, callback redirects to:
# http://localhost:3000/login-success?access=TOKEN&refresh=REFRESH_TOKEN
# 3. Validate token
curl -X POST -H "Content-Type: application/json" \
-d '{"accessToken":"YOUR_TOKEN"}' \
http://localhost:3001/auth/validate-token
# 4. Logout
curl -X POST -H "Content-Type: application/json" \
-d '{"accessToken":"YOUR_TOKEN"}' \
http://localhost:3001/auth/logout# Get top artists for last 4 weeks
curl -H "Authorization: Bearer TOKEN" \
"http://localhost:3001/spotify/top/artists?time_range=short_term&limit=20"
# Get top tracks
curl -H "Authorization: Bearer TOKEN" \
"http://localhost:3001/spotify/top/tracks?limit=10"
# Get processed artists (distributed in 3 lists)
curl -H "Authorization: Bearer TOKEN" \
"http://localhost:3001/spotify/top/artists/processed"
# Clear user cache
curl -X DELETE -H "Authorization: Bearer TOKEN" \
http://localhost:3001/spotify/cacheFor the complete interface, also clone:
git clone https://github.com/williamosilva/festify-frontend
cd festify-frontend
npm install && npm run dev- Node.js 20+ (if not using Docker)
- MongoDB running
- Spotify Developer account
William Silva
Website