Skip to main content
RapidDev - Software Development Agency
API AutomationsSpotifyOAuth 2.0

How to Automate Spotify Listening Reports using the API

Generate Spotify listening reports using GET /v1/me/top/tracks and GET /v1/me/top/artists with time_range=short_term|medium_term|long_term, plus GET /v1/me/player/recently-played for up to 50 recent plays. Important: recently-played returns only ~50 items with no way to paginate further back. The deprecated Audio Features endpoint (GET /v1/audio-features) returns 403 for apps created after November 27, 2024 — tempo, energy, danceability, and valence cannot be included in reports for new apps.

Need help automating? Talk to an expert
4.9Clutch rating
600+Happy partners
17+Countries served
190+Team members
Beginner7 min read15-30 minutesSpotifyMay 2026RapidDev Engineering Team
TL;DR

Generate Spotify listening reports using GET /v1/me/top/tracks and GET /v1/me/top/artists with time_range=short_term|medium_term|long_term, plus GET /v1/me/player/recently-played for up to 50 recent plays. Important: recently-played returns only ~50 items with no way to paginate further back. The deprecated Audio Features endpoint (GET /v1/audio-features) returns 403 for apps created after November 27, 2024 — tempo, energy, danceability, and valence cannot be included in reports for new apps.

API Quick Reference

Auth

OAuth 2.0

Rate limit

Rolling 30-second window (exact threshold undisclosed)

Format

JSON

SDK

Available

Understanding the Spotify Web API

The Spotify Web API is a REST API at https://api.spotify.com/v1 that gives access to user listening history, top items, and music catalog data. For listening reports, the three most useful endpoints are GET /v1/me/top/tracks, GET /v1/me/top/artists, and GET /v1/me/player/recently-played. All three require OAuth 2.0 Authorization Code flow with user-specific scopes — Client Credentials flow cannot access personal listening data.

A critical limitation for new apps: GET /v1/audio-features was permanently deprecated on November 27, 2024 and returns HTTP 403 for apps created after that date. This means you cannot include acoustic properties like tempo, energy, danceability, valence, or instrumentalness in reports. Older tutorials that show these fields are written for grandfathered Extended Quota apps. Build reports using track names, artist names, popularity scores, genres, and album data instead.

The recently-played endpoint has a hard ceiling of ~50 items with no historical pagination — it is not a full listening history. There is no Spotify API endpoint that gives you complete historical listening data. Official docs: https://developer.spotify.com/documentation/web-api

Base URLhttps://api.spotify.com/v1

Setting Up Spotify API Authentication

Listening history is user-specific data that requires OAuth 2.0 Authorization Code flow. You need two scopes: user-top-read for top tracks and artists, and user-read-recently-played for recent plays. Access tokens expire in 3,600 seconds — the refresh token workflow must be implemented for automated report generation.

  1. 1Log in to https://developer.spotify.com/dashboard with your Spotify Premium account
  2. 2Click 'Create app', set a name, description, and redirect URI (e.g., http://localhost:8888/callback)
  3. 3Copy your Client ID and Client Secret from the app settings page
  4. 4Build the authorization URL: GET https://accounts.spotify.com/authorize?client_id=YOUR_CLIENT_ID&response_type=code&redirect_uri=YOUR_REDIRECT_URI&scope=user-top-read%20user-read-recently-played
  5. 5After user grants access, extract the code parameter from the redirect
  6. 6Exchange the code for tokens: POST https://accounts.spotify.com/api/token with grant_type=authorization_code, code, redirect_uri, and Authorization: Basic base64(client_id:client_secret)
  7. 7Store the access_token (3600s lifetime) and refresh_token securely in environment variables
  8. 8Before each report run, refresh: POST https://accounts.spotify.com/api/token with grant_type=refresh_token and your refresh_token
auth.py
1import os
2import base64
3import requests
4
5CLIENT_ID = os.environ['SPOTIFY_CLIENT_ID']
6CLIENT_SECRET = os.environ['SPOTIFY_CLIENT_SECRET']
7REFRESH_TOKEN = os.environ['SPOTIFY_REFRESH_TOKEN']
8
9def get_access_token():
10 """Exchange refresh token for a new Spotify access token."""
11 creds = base64.b64encode(f"{CLIENT_ID}:{CLIENT_SECRET}".encode()).decode()
12 response = requests.post(
13 'https://accounts.spotify.com/api/token',
14 headers={'Authorization': f'Basic {creds}'},
15 data={'grant_type': 'refresh_token', 'refresh_token': REFRESH_TOKEN}
16 )
17 response.raise_for_status()
18 return response.json()['access_token']
19
20token = get_access_token()
21headers = {'Authorization': f'Bearer {token}'}

Security notes

  • Store Client ID, Client Secret, and refresh token in environment variables — never in code or git history
  • Refresh tokens are long-lived — encrypt them at rest if persisting in a database
  • Only request user-top-read and user-read-recently-played — do not request write scopes for a read-only report
  • Access tokens expire after exactly 3,600 seconds — refresh proactively before each report run
  • In Development Mode, only the app owner and up to 4 other explicitly authorized Spotify users can generate reports
  • Never log the access token or refresh token values

Key endpoints

GET/v1/me/top/tracks

Returns the current user's top tracks over a specified time range. Use time_range to get short-term (~4 weeks), medium-term (~6 months), or long-term (years) listening summaries.

ParameterTypeRequiredDescription
time_rangestringoptionalshort_term (~4 weeks), medium_term (~6 months), or long_term (years). Default: medium_term
limitnumberoptionalNumber of items to return, 1-50, default 20
offsetnumberoptionalPagination offset, max 49 (total items capped at 50)

Response

json
1{"items":[{"id":"4iV5W9uYEdYUVa79Axb7Rh","name":"Bohemian Rhapsody","artists":[{"id":"1dfeR4HaWDbWqFHLkxsg1d","name":"Queen"}],"album":{"name":"A Night at the Opera","release_date":"1975-11-21","images":[{"url":"https://i.scdn.co/image/...","height":640,"width":640}]},"popularity":82,"duration_ms":357000,"uri":"spotify:track:4iV5W9uYEdYUVa79Axb7Rh","external_urls":{"spotify":"https://open.spotify.com/track/4iV5W9uYEdYUVa79Axb7Rh"}}],"total":50,"limit":50,"offset":0,"next":null}
GET/v1/me/top/artists

Returns the user's top artists over the specified time range. Each artist object includes genres, making this useful for identifying listening taste profiles.

ParameterTypeRequiredDescription
time_rangestringoptionalshort_term, medium_term, or long_term
limitnumberoptionalNumber of items, 1-50, default 20
offsetnumberoptionalPagination offset

Response

json
1{"items":[{"id":"1dfeR4HaWDbWqFHLkxsg1d","name":"Queen","genres":["classic rock","glam rock","rock"],"popularity":88,"followers":{"total":38000000},"images":[{"url":"https://i.scdn.co/image/..."}],"external_urls":{"spotify":"https://open.spotify.com/artist/1dfeR4HaWDbWqFHLkxsg1d"}}],"total":50}
GET/v1/me/player/recently-played

Returns up to 50 of the user's most recently played tracks with timestamps. This is the closest available endpoint to a listening history — but it cannot paginate further than ~50 plays.

ParameterTypeRequiredDescription
limitnumberoptionalNumber of items, 1-50, default 20
afternumberoptionalUnix timestamp in milliseconds — return items after this timestamp
beforenumberoptionalUnix timestamp in milliseconds — return items before this timestamp

Response

json
1{"items":[{"track":{"id":"7lEptt4wbM0yJTyqhLXsIV","name":"Everlong","artists":[{"name":"Foo Fighters"}],"duration_ms":250627,"popularity":73,"uri":"spotify:track:7lEptt4wbM0yJTyqhLXsIV"},"played_at":"2026-05-07T08:31:20.157Z","context":{"type":"playlist"}}],"next":null,"cursors":{"after":"MTcxNTY3MjI4MDk0Mw==","before":"MTcxNTY3MjI3OTk4Mw=="}}

Step-by-step automation

1

Fetch Top Tracks for All Three Time Ranges

Why: Comparing short, medium, and long-term listening patterns is the core of a Wrapped-style report.

Call GET /v1/me/top/tracks three times with time_range=short_term, medium_term, and long_term. Set limit=50 to get the maximum number of tracks per range. A full set is only 3 API calls — well within rate limits. Store results keyed by time range for the report generation step.

request.sh
1# Short term (~4 weeks)
2curl -G 'https://api.spotify.com/v1/me/top/tracks' \
3 -H 'Authorization: Bearer YOUR_ACCESS_TOKEN' \
4 -d 'time_range=short_term' \
5 -d 'limit=50'
6
7# Medium term (~6 months)
8curl -G 'https://api.spotify.com/v1/me/top/tracks' \
9 -H 'Authorization: Bearer YOUR_ACCESS_TOKEN' \
10 -d 'time_range=medium_term' \
11 -d 'limit=50'
12
13# Long term (all time)
14curl -G 'https://api.spotify.com/v1/me/top/tracks' \
15 -H 'Authorization: Bearer YOUR_ACCESS_TOKEN' \
16 -d 'time_range=long_term' \
17 -d 'limit=50'

Pro tip: Popularity is 0-100 and reflects recent streaming volume across all Spotify users — not just your own listens. Use it as a proxy for how mainstream your taste is, not how often you played the track.

Expected result: Three arrays of up to 50 track objects each, ranked by listening frequency for each time period. Each track includes name, artists, album, popularity (0-100), and uri.

2

Fetch Top Artists and Extract Genre Insights

Why: Artist data includes genres, which is the primary way to characterize listening taste since audio features are deprecated for new apps.

Call GET /v1/me/top/artists for all three time ranges. The genres array on each artist is the most valuable data point for taste profiling. Aggregate genre counts across your top artists to find your dominant listening categories. Note: artist follower counts and popularity scores may be restricted for Development Mode apps as of February 2026.

request.sh
1curl -G 'https://api.spotify.com/v1/me/top/artists' \
2 -H 'Authorization: Bearer YOUR_ACCESS_TOKEN' \
3 -d 'time_range=short_term' \
4 -d 'limit=50'

Pro tip: Weight genres by artist position in the top list: an artist at rank 1 should contribute more to genre scoring than one at rank 50. Multiply genre occurrences by (51 - rank) for weighted genre analysis.

Expected result: Three arrays of up to 50 artist objects per time range, each with name, genres array, and Spotify URL. Genre aggregation gives you the user's dominant listening categories.

3

Fetch Recently Played Tracks

Why: Recently played provides a time-stamped snapshot of the last ~50 plays, giving context that top-items endpoints don't have.

Call GET /v1/me/player/recently-played?limit=50 to retrieve the last 50 plays with timestamps. Each item has a played_at ISO 8601 timestamp and a context object (what playlist/album/artist page the track was played from). Important: there is no way to paginate further than this ~50-item window — it is not a complete listening history. The before/after cursor parameters exist but only move within the ~50-item window.

request.sh
1curl -G 'https://api.spotify.com/v1/me/player/recently-played' \
2 -H 'Authorization: Bearer YOUR_ACCESS_TOKEN' \
3 -d 'limit=50'

Pro tip: The recently-played endpoint returns plays in reverse chronological order. Use played_at timestamps to calculate listening time-of-day patterns — useful for 'morning person vs night owl' type insights in your report.

Expected result: Array of up to 50 items, each with a track object and played_at ISO timestamp. Context object indicates whether it was played from a playlist, album, or artist page.

4

Compile and Format the Report

Why: Raw API data needs to be aggregated and formatted into a readable summary before delivery.

Combine data from all three endpoint groups into a structured report. Include: top 10 tracks for each time range, top 10 artists, genre breakdown, and a recent activity snapshot. Export as JSON, text, HTML, or write back to a Notion database or Google Sheet. Skip any audio features fields (tempo, energy, danceability, valence) — they are unavailable for new apps.

request.sh
1# No single cURL command for report compilation see Python/Node.js scripts

Pro tip: Save each report with a dated filename (e.g., listening_report_2026_05.json) to build a historical archive, since the API doesn't provide historical data.

Expected result: A structured JSON report with top tracks per time range, top artists, genre breakdown, and recent activity stats. Ready to save to a file, send via email, or push to Notion/Sheets.

Complete working code

This script generates a complete Spotify listening report: refreshes the OAuth token, fetches top tracks and artists for all three time ranges, pulls recently played tracks, and compiles everything into a structured JSON report saved to disk. Run it monthly for a DIY Spotify Wrapped.

automate_listening_reports.py
1import os
2import base64
3import json
4import requests
5from datetime import datetime
6from collections import Counter
7
8CLIENT_ID = os.environ['SPOTIFY_CLIENT_ID']
9CLIENT_SECRET = os.environ['SPOTIFY_CLIENT_SECRET']
10REFRESH_TOKEN = os.environ['SPOTIFY_REFRESH_TOKEN']
11OUTPUT_DIR = os.environ.get('REPORT_OUTPUT_DIR', '.')
12
13def get_token():
14 creds = base64.b64encode(f"{CLIENT_ID}:{CLIENT_SECRET}".encode()).decode()
15 r = requests.post('https://accounts.spotify.com/api/token',
16 headers={'Authorization': f'Basic {creds}'},
17 data={'grant_type': 'refresh_token', 'refresh_token': REFRESH_TOKEN})
18 r.raise_for_status()
19 return r.json()['access_token']
20
21def api_get(token, path, params=None):
22 r = requests.get(f'https://api.spotify.com/v1{path}',
23 headers={'Authorization': f'Bearer {token}'}, params=params)
24 if r.status_code == 429:
25 import time
26 time.sleep(int(r.headers.get('Retry-After', 5)))
27 return api_get(token, path, params)
28 r.raise_for_status()
29 return r.json()
30
31def main():
32 token = get_token()
33 time_ranges = ['short_term', 'medium_term', 'long_term']
34 labels = {'short_term': '~4 weeks', 'medium_term': '~6 months', 'long_term': 'all time'}
35
36 # Fetch top tracks and artists for all time ranges
37 top_tracks = {}
38 top_artists = {}
39 for tr in time_ranges:
40 top_tracks[tr] = api_get(token, '/me/top/tracks', {'time_range': tr, 'limit': 50})['items']
41 top_artists[tr] = api_get(token, '/me/top/artists', {'time_range': tr, 'limit': 50})['items']
42 print(f'{labels[tr]}: {len(top_tracks[tr])} tracks, {len(top_artists[tr])} artists')
43
44 # Fetch recently played
45 recent = api_get(token, '/me/player/recently-played', {'limit': 50})['items']
46 print(f'Recently played: {len(recent)} tracks')
47
48 # Aggregate genres from short-term artists
49 genre_counts = Counter()
50 for artist in top_artists['short_term']:
51 genre_counts.update(artist['genres'])
52
53 # Build report
54 report = {
55 'generated_at': datetime.now().isoformat(),
56 'period': datetime.now().strftime('%Y-%m'),
57 'top_tracks': {
58 tr: [{'rank': i+1, 'name': t['name'],
59 'artist': ', '.join(a['name'] for a in t['artists']),
60 'album': t['album']['name'],
61 'popularity': t['popularity'],
62 'url': t['external_urls']['spotify']}
63 for i, t in enumerate(tracks[:20])]
64 for tr, tracks in top_tracks.items()
65 },
66 'top_artists_this_month': [
67 {'rank': i+1, 'name': a['name'],
68 'genres': a['genres'][:3],
69 'url': a['external_urls']['spotify']}
70 for i, a in enumerate(top_artists['short_term'][:20])
71 ],
72 'top_genres_this_month': dict(genre_counts.most_common(15)),
73 'recent_plays': [
74 {'track': item['track']['name'],
75 'artist': ', '.join(a['name'] for a in item['track']['artists']),
76 'played_at': item['played_at']}
77 for item in recent[:20]
78 ],
79 'stats': {
80 'total_recent_plays': len(recent),
81 'unique_recent_tracks': len({i['track']['id'] for i in recent})
82 },
83 'note': 'Audio features (tempo/energy/danceability/valence) unavailable for apps created after Nov 27, 2024'
84 }
85
86 # Save to file
87 filename = f'{OUTPUT_DIR}/listening_report_{report["period"]}.json'
88 with open(filename, 'w') as f:
89 json.dump(report, f, indent=2)
90 print(f'\nReport saved to {filename}')
91
92if __name__ == '__main__':
93 main()

Error handling

403{"error":{"status":403,"message":"Forbidden"}}
Cause

Returned for deprecated endpoints (GET /v1/audio-features, GET /v1/audio-analysis) for apps created after November 27, 2024. Also returned when scopes are missing.

Fix

Remove any audio-features or audio-analysis calls from your code — these endpoints are permanently unavailable for new apps. For scope issues, re-authorize with user-top-read and user-read-recently-played.

Retry strategy

Not retryable for deprecated endpoints. Fix scope issues by re-authorizing.

401{"error":{"status":401,"message":"No token provided"}}
Cause

Access token expired (tokens last exactly 3,600 seconds) or is invalid.

Fix

Refresh the access token using the refresh_token before each report run.

Retry strategy

Refresh immediately and retry once.

429{"error":{"status":429,"message":"API rate limit exceeded"}}
Cause

Too many requests in the rolling 30-second window. A full report uses ~7 calls — this is unlikely to trigger rate limits unless you are generating reports for many users simultaneously.

Fix

Read the Retry-After header and wait that many seconds. For multi-user report generation, add delays between each user's report run.

Retry strategy

Honor Retry-After header value exactly.

204(empty response body)
Cause

GET /v1/me/player/recently-played returns 204 with no body when the user hasn't played any tracks recently or the user's account has no play history.

Fix

Check for 204 status before parsing the response body. Handle gracefully by showing an empty recent plays section in the report.

Retry strategy

Not an error — handle as empty data.

Rate Limits for Spotify API

ScopeLimitWindow
Per appUndisclosed exact thresholdRolling 30 seconds
Single-user report (7 API calls)Well within limitsCompletes in under 5 seconds
Multi-user report generationAdd delays between usersRecommended: 1 user per second maximum
retry-handler.ts
1import time
2import requests
3
4def api_get_with_retry(token, url, params=None, max_retries=3):
5 headers = {'Authorization': f'Bearer {token}'}
6 for attempt in range(max_retries):
7 r = requests.get(url, headers=headers, params=params)
8 if r.status_code == 429:
9 wait = int(r.headers.get('Retry-After', 2 ** attempt))
10 print(f'Rate limited. Waiting {wait}s...')
11 time.sleep(wait)
12 elif r.status_code == 204:
13 return None # No content
14 elif r.ok:
15 return r.json()
16 else:
17 r.raise_for_status()
18 raise RuntimeError('Max retries exceeded')
  • A single-user report uses only ~7 API calls — no need for delays unless generating reports for multiple users
  • For multi-user report generation, add 1-second delays between each user's batch of calls
  • Cache the user ID from GET /v1/me — it never changes and saves one API call per run
  • Generate reports on a schedule (monthly) rather than on-demand to keep total API usage low
  • Honor the Retry-After header on 429 responses — Spotify's threshold is undisclosed so proactive delay management is the safest approach

Security checklist

  • Store Client ID, Client Secret, and refresh token in environment variables — never in source code
  • Report output files may contain personal listening data — do not commit them to version control or store in public locations
  • Only request user-top-read and user-read-recently-played scopes — do not add write scopes
  • Refresh tokens are long-lived — encrypt at rest if stored in a database
  • In Development Mode, only authorized users can generate reports — do not add unauthorized accounts to test
  • Access tokens expire in 3,600 seconds — never cache them for longer than 55 minutes
  • Validate the access token response before using it — a failed refresh returns a non-2xx status

Automation use cases

Monthly Listening Digest

beginner

Run on the first of each month to generate a personal Wrapped-style report saved to JSON for archiving.

Weekly Taste Profile

beginner

Use short_term top artists and genres to build a weekly taste snapshot that can feed into playlist curation decisions.

Friend Listening Comparison

intermediate

Compare top tracks and genres across multiple authorized users in Development Mode (up to 5) to find shared and divergent listening tastes.

Listening Habit Dashboard

advanced

Store monthly reports to a database and build a web dashboard showing listening trends over time, top genre shifts, and artist loyalty metrics.

No-code alternatives

Don't want to write code? These platforms can automate the same workflows visually.

Zapier

Free tier available; paid plans from $19.99/month

Zapier's Spotify integration can trigger workflows on recently played tracks, though building a full listening report requires chaining multiple steps.

Pros
  • + No code required
  • + Easy integration with Google Sheets or Notion for report storage
  • + Runs automatically on schedule
Cons
  • - Cannot easily aggregate data across multiple API calls in a single Zap
  • - Free tier limited to 100 tasks/month
  • - No native report-building capability

Make

Free tier available; paid plans from $9/month

Make can chain multiple Spotify API calls in a single scenario using HTTP modules to replicate the report generation logic.

Pros
  • + Visual multi-step scenario builder
  • + Flexible data aggregation with built-in functions
  • + Free tier includes 1,000 operations/month
Cons
  • - Complex multi-step scenarios require more setup time than code
  • - Data aggregation functions are more limited than Python/JS
  • - Requires paid plan for advanced scheduling

n8n

Self-hosted free; cloud from €20/month

n8n's Spotify node covers top tracks and recently played, and Code nodes can aggregate genre data — making it a capable no-code alternative.

Pros
  • + Self-hosted = free unlimited executions
  • + Code node allows custom aggregation logic in JS
  • + Spotify node plus HTTP Request node for full API coverage
Cons
  • - Requires server setup for self-hosting
  • - More complex than a simple Python script for this use case

Best practices

  • Always request all three time ranges in a single run — it only costs 6 extra API calls and provides much richer report content
  • Make the absence of audio features data explicit in your reports — note that tempo, energy, and danceability are unavailable for apps created after November 27, 2024, so users don't think the report is broken
  • Handle the 204 (no content) response from recently-played gracefully — new Spotify accounts or users who haven't played anything recently will trigger it
  • Save reports with dated filenames to build a historical archive — the API provides no way to retrieve historical top-item data retroactively
  • Use genre aggregation from top artists as the primary taste-characterization signal, since audio features are no longer available
  • Test with your own account first (in Development Mode) before building a multi-user report service that would require Extended Quota approval

Ask AI to help

Copy one of these prompts to get a personalized, working implementation.

ChatGPT / Claude Prompt

I'm building a Spotify listening report generator using the Web API. I use GET /v1/me/top/tracks and GET /v1/me/top/artists with time_range=short_term|medium_term|long_term, and GET /v1/me/player/recently-played. I want to compare listening patterns across time ranges — specifically, I want to identify tracks that appear in short_term but not in long_term (recently discovered music) and tracks in long_term but not short_term (old favorites I've stopped playing). Can you write a Python function that takes the three top_tracks dictionaries and returns two lists: 'new discoveries' and 'nostalgic favorites' with their track name, artist, and position in each time range?

Lovable / V0 Prompt

Build a Spotify Listening Report dashboard with these features: 1) OAuth login button with Spotify branding that requests user-top-read and user-read-recently-played scopes, 2) After login, show three tabs: 'This Month' (short_term), '6 Months' (medium_term), 'All Time' (long_term) — each showing top 20 tracks and top 20 artists as cards with album art, 3) A 'Genre Breakdown' section showing the top 10 genres from this month's top artists as a horizontal bar chart, 4) A 'Recently Played' section showing the last 20 tracks with relative timestamps (e.g., '2 hours ago'), 5) A 'Generate Report' button that exports all data as a JSON file. Handle token refresh automatically and show loading spinners during API calls. Use Tailwind CSS.

Frequently asked questions

Is the Spotify API free for generating listening reports?

Yes — the Spotify Web API is free to use. In Development Mode you are limited to 5 authorized users per Client ID (as of February 11, 2026) and the app owner must have Spotify Premium. This is sufficient for personal use or small team applications.

Why can't I include tempo, energy, or danceability in my listening reports?

GET /v1/audio-features was permanently deprecated for apps created after November 27, 2024 and returns HTTP 403. This includes tempo, energy, danceability, valence, instrumentalness, and all other audio analysis properties. These endpoints are still accessible to grandfathered Extended Quota apps that existed before that date. For new apps, use genre data from top artists as the alternative for taste characterization.

Can I retrieve more than 50 recently played tracks for my report?

No — GET /v1/me/player/recently-played has a hard limit of ~50 items and cannot be paginated further back. The before and after cursor parameters only move within this ~50-item window. There is no Spotify API endpoint that provides complete historical listening data. The top tracks endpoints (short_term, medium_term, long_term) are the best proxy for longer-term listening patterns.

What exactly does 'short_term' mean for the time_range parameter?

Spotify describes short_term as 'approximately last 4 weeks', medium_term as 'approximately last 6 months', and long_term as 'calculated from several years of data and including all new data as it becomes available'. These are Spotify's descriptions — the exact algorithm for determining top items is proprietary and not publicly documented.

What happens when I hit the rate limit?

You receive HTTP 429 with a Retry-After header. A single-user report generation uses only ~7 API calls and is extremely unlikely to trigger rate limits. Multi-user report generation is where rate limiting becomes relevant — add 1-second delays between each user's batch of requests.

Can RapidDev help build a custom Spotify listening report tool?

Yes — RapidDev has built 600+ integrations and can create a production Spotify analytics dashboard with OAuth flow, scheduled report generation, historical data storage, and trend visualization. Reach out at rapidevelopers.com for a free consultation.

Does Spotify have a webhook I can use to trigger report generation when a user plays a new track?

No — Spotify has no webhook system for the Web API. There is no way to receive a push notification when a user plays a track. Report generation must be scheduled (e.g., monthly cron) or triggered manually. The Web Playback SDK offers in-browser player events, but only while your web page is actively open and the user is using your embedded player.

RapidDev

Need this automated?

Our team has built 600+ apps with API automations. We can build this for you.

Book a free consultation

Skip the coding — we'll build it for you

Our experts have built 600+ API automations. From prototype to production in days, not weeks.

Book a free consultation

We put the rapid in RapidDev

Need a dedicated strategic tech and growth partner? Discover what RapidDev can do for your business! Book a call with our team to schedule a free, no-obligation consultation. We'll discuss your project and provide a custom quote at no cost.