Match Spotify listener data to CRM contacts using GET /v1/me (user-read-email scope) to retrieve the authorized user's email, then GET /v1/me/top/artists for genre/taste segments. Critical limitation: Spotify has NO server-to-server 'find user by email' lookup. CRM matching requires each listener to individually OAuth-authorize your app. Development Mode caps you at 5 authorized users — production scale requires Extended Quota Mode, which since May 2025 requires a legally registered organization with 250,000+ monthly active users.
API Quick Reference
OAuth 2.0
Rolling 30-second window per app (exact threshold undisclosed)
JSON
Available
Understanding the Spotify Web API
The Spotify Web API is a REST API at https://api.spotify.com/v1 that provides access to user profile data, listening history, playlists, and the music catalog. For audience segmentation, the relevant endpoints are GET /v1/me (user profile including email), GET /v1/me/top/artists (genre preferences), and GET /v1/me/top/tracks (listening taste).
The most critical limitation for CRM use cases: Spotify has NO server-to-server 'find user by email' API. You cannot query Spotify's user database with an email address and get listening data back. The only way to match a Spotify listener to a CRM contact is to have that listener individually complete an OAuth authorization flow on your website or app, granting your app access to their profile. After they authorize, you call GET /v1/me?fields=email to get their Spotify email, then match it against your CRM.
This limitation has a major scale constraint: Development Mode allows only 5 authorized users per Client ID as of February 11, 2026. The app owner must have Spotify Premium. For production audience segmentation at real scale, Extended Quota Mode is required — and since May 15, 2025, Spotify only grants this to legally registered businesses/organizations with an active launched product and 250,000+ monthly active users. Individual developers and small teams are no longer eligible. Official docs: https://developer.spotify.com/documentation/web-api
https://api.spotify.com/v1Setting Up Spotify API Authentication
Audience segmentation requires each individual Spotify user to authorize your app — there is no batch authorization or server-to-server approach. You need user-read-email to retrieve their email for CRM matching, user-read-private for country/product tier, and user-top-read for listening taste data. Each authorized user gets their own access token and refresh token that you must store securely per user. Access tokens expire in 3,600 seconds.
- 1Log in to https://developer.spotify.com/dashboard with your Spotify Premium account (required for Development Mode)
- 2Click 'Create app', add name and description, set redirect URIs to your actual website URL (e.g., https://yourapp.com/auth/spotify/callback)
- 3Copy Client ID and Client Secret from app settings
- 4Build the authorization URL with required scopes: GET https://accounts.spotify.com/authorize?client_id=YOUR_CLIENT_ID&response_type=code&redirect_uri=YOUR_REDIRECT_URI&scope=user-read-email%20user-read-private%20user-top-read
- 5Embed an 'Connect Spotify' button on your site that redirects users to this authorization URL
- 6In your callback handler, exchange the code for tokens: POST https://accounts.spotify.com/api/token with grant_type=authorization_code
- 7Store each user's access_token, refresh_token, and spotify_user_id in your database, linked to their CRM contact record
- 8Refresh individual user tokens before each sync run using their stored refresh_token
- 9In Development Mode, manually add test users at developer.spotify.com/dashboard — only added users can authorize (max 5 total)
1import os2import base643import requests4from datetime import datetime, timedelta56CLIENT_ID = os.environ['SPOTIFY_CLIENT_ID']7CLIENT_SECRET = os.environ['SPOTIFY_CLIENT_SECRET']89def get_auth_url(redirect_uri, state=None):10 """Generate the OAuth authorization URL for a user."""11 scopes = 'user-read-email user-read-private user-top-read'12 params = {13 'client_id': CLIENT_ID,14 'response_type': 'code',15 'redirect_uri': redirect_uri,16 'scope': scopes17 }18 if state:19 params['state'] = state # CSRF protection20 from urllib.parse import urlencode21 return f'https://accounts.spotify.com/authorize?{urlencode(params)}'2223def exchange_code_for_tokens(code, redirect_uri):24 """Exchange authorization code for access and refresh tokens."""25 creds = base64.b64encode(f"{CLIENT_ID}:{CLIENT_SECRET}".encode()).decode()26 response = requests.post(27 'https://accounts.spotify.com/api/token',28 headers={'Authorization': f'Basic {creds}'},29 data={'grant_type': 'authorization_code', 'code': code, 'redirect_uri': redirect_uri}30 )31 response.raise_for_status()32 data = response.json()33 return {34 'access_token': data['access_token'],35 'refresh_token': data['refresh_token'],36 'expires_at': (datetime.now() + timedelta(seconds=3600)).isoformat()37 }3839def refresh_user_token(refresh_token):40 """Refresh a user's access token."""41 creds = base64.b64encode(f"{CLIENT_ID}:{CLIENT_SECRET}".encode()).decode()42 response = requests.post(43 'https://accounts.spotify.com/api/token',44 headers={'Authorization': f'Basic {creds}'},45 data={'grant_type': 'refresh_token', 'refresh_token': refresh_token}46 )47 response.raise_for_status()48 return response.json()['access_token']Security notes
- •Store each user's refresh token encrypted in your database — a leaked refresh token gives full account access
- •Use CSRF state parameter in the OAuth flow to prevent cross-site request forgery attacks
- •Never log access tokens or refresh tokens — only log token refresh events and user IDs
- •Store Client Secret in server-side environment variables only — never expose to browsers or mobile apps
- •Implement token revocation when a user disconnects their Spotify account from your app
- •In Development Mode, do not add users you don't control — you are responsible for their data
- •Match Spotify email to CRM only server-side — never send email matching logic to the browser
- •Comply with Spotify's Developer Terms and your jurisdiction's data protection laws (GDPR, CCPA) when storing user listening data
Key endpoints
/v1/meReturns the current authorized user's Spotify profile including email (if user-read-email scope granted), country, and product tier (free/premium). This is the only way to get a user's Spotify email — there is no lookup by email.
Response
1{"id":"wizzler","display_name":"John W","email":"john@example.com","country":"US","product":"premium","followers":{"total":25},"external_urls":{"spotify":"https://open.spotify.com/user/wizzler"}}/v1/me/top/artistsReturns the user's most listened-to artists with genre tags. Use time_range=short_term for current preference signals. Genres are the primary segmentation data point.
| Parameter | Type | Required | Description |
|---|---|---|---|
time_range | string | optional | short_term (~4 weeks), medium_term (~6 months), long_term (years) |
limit | number | optional | Number of artists, 1-50 |
Response
1{"items":[{"id":"7jy3rLJdDQY21OgRLCZ9sD","name":"Foo Fighters","genres":["alternative metal","alternative rock","post-grunge","rock"],"popularity":79,"external_urls":{"spotify":"https://open.spotify.com/artist/7jy3rLJdDQY21OgRLCZ9sD"}}],"total":20}/v1/me/top/tracksReturns the user's most played tracks. Use to supplement genre data with specific artist affinity signals for more granular CRM segmentation.
| Parameter | Type | Required | Description |
|---|---|---|---|
time_range | string | optional | short_term, medium_term, or long_term |
limit | number | optional | Number of tracks, 1-50 |
Response
1{"items":[{"id":"4iV5W9uYEdYUVa79Axb7Rh","name":"Everlong","artists":[{"name":"Foo Fighters"}],"popularity":74,"uri":"spotify:track:4iV5W9uYEdYUVa79Axb7Rh"}],"total":50}/v1/me/playlistsReturns the user's playlists. Playlist names and descriptions can hint at taste signals (e.g., 'Workout Hits', 'Jazz for Coffee') for additional segmentation metadata.
| Parameter | Type | Required | Description |
|---|---|---|---|
limit | number | optional | Number of playlists, 1-50 |
offset | number | optional | Pagination offset |
Response
1{"items":[{"id":"3cEYpjA9oz9GiPac4AsH4n","name":"Workout Hits","tracks":{"total":45},"public":true}],"total":12}Step-by-step automation
Build the OAuth Callback Handler
Why: Every CRM match requires an individual user authorization — the callback handler is the entry point for every new contact.
When a user clicks 'Connect Spotify' on your site, they are sent to Spotify's authorization page. After they authorize, Spotify redirects them to your callback URL with a code parameter. Your callback handler exchanges this code for access and refresh tokens, calls GET /v1/me to retrieve their Spotify email, matches it against your CRM, and stores their tokens linked to the CRM contact. Implement CSRF protection using the state parameter.
1# Step 1: Exchange authorization code for tokens2curl -X POST 'https://accounts.spotify.com/api/token' \3 -H 'Authorization: Basic BASE64_CLIENT_ID_COLON_SECRET' \4 -H 'Content-Type: application/x-www-form-urlencoded' \5 -d 'grant_type=authorization_code&code=AUTH_CODE&redirect_uri=https%3A%2F%2Fyourapp.com%2Fauth%2Fspotify%2Fcallback'67# Step 2: Fetch user profile with email8curl 'https://api.spotify.com/v1/me' \9 -H 'Authorization: Bearer ACCESS_TOKEN'Pro tip: Always use the state parameter in the authorization URL to carry the CRM contact ID through the OAuth flow. This prevents you from needing to match by email alone, which can fail if the user's Spotify email differs from their CRM email.
Expected result: User's Spotify email, user ID, country, product tier (free/premium), and stored tokens linked to their CRM contact record.
Fetch Genre and Taste Data for Segmentation
Why: Genre preferences are the core segmentation signal — they tell you what kind of listener this person is for targeted campaign matching.
After storing the user's tokens, call GET /v1/me/top/artists with short_term time range to get current taste. Extract and aggregate genre tags across the top 20 artists. Also call GET /v1/me/top/tracks to identify specific artist affinities. These signals become CRM tags like 'listener:rock', 'listener:hip-hop', 'listener:classical'.
1curl -G 'https://api.spotify.com/v1/me/top/artists' \2 -H 'Authorization: Bearer USER_ACCESS_TOKEN' \3 -d 'time_range=short_term' \4 -d 'limit=20'Pro tip: Map Spotify genre tags to your CRM's existing segment structure. For example, if your CRM has segments for 'Rock Fans', 'Pop Fans', 'Electronic Fans', build a mapping table that translates Spotify's granular genre tags (e.g., 'indie rock', 'classic rock', 'hard rock') into your coarser CRM categories.
Expected result: Structured segment data per user: top genres, top artists, average track popularity, and CRM-ready tags like 'music_genre:alternative-rock', 'music_popularity:mid'.
Sync Segments to CRM
Why: The Spotify data is only valuable when it's written back to your CRM as contact properties or tags for campaign targeting.
Take the segment tags and taste profile data from the previous step and write them to your CRM via its API. The specific implementation depends on your CRM — this step shows patterns for common CRMs (HubSpot, Salesforce, generic REST). Match the contact by the email retrieved in Step 1. Store both the raw genre data and the derived segment tags.
1# Example: Update HubSpot contact with Spotify segments2# Replace YOUR_HUBSPOT_ACCESS_TOKEN and CONTACT_ID3curl -X PATCH 'https://api.hubapi.com/crm/v3/objects/contacts/CONTACT_ID' \4 -H 'Authorization: Bearer YOUR_HUBSPOT_ACCESS_TOKEN' \5 -H 'Content-Type: application/json' \6 -d '{"properties":{"spotify_top_genre":"alternative rock","spotify_taste_profile":"popular-niche","spotify_avg_popularity":"67","spotify_connected":"true"}}'Pro tip: Add a spotify_last_synced timestamp to each CRM contact. Run a re-sync monthly to refresh the taste profile — listening habits change over 6 months and outdated segments will degrade campaign performance.
Expected result: CRM contact updated with Spotify genre data, taste profile, and a spotify_connected:true flag. The contact is now tagged for targeted music-preference campaigns.
Schedule Re-Sync for Authorized Users
Why: Listening habits evolve — monthly re-syncs keep CRM segments accurate without requiring users to re-authorize.
Build a batch re-sync job that iterates over all stored refresh tokens, refreshes each user's access token, fetches updated top artists and tracks, recalculates segment tags, and writes updated data to the CRM. This runs server-side on a monthly schedule using a task queue or cron. At scale (Extended Quota Mode), add per-user queuing to avoid compounding the rolling rate limit across hundreds of concurrent syncs.
1# Refresh a user's token (run per user in the batch job)2curl -X POST 'https://accounts.spotify.com/api/token' \3 -H 'Authorization: Basic BASE64_CLIENT_ID_COLON_SECRET' \4 -H 'Content-Type: application/x-www-form-urlencoded' \5 -d 'grant_type=refresh_token&refresh_token=USER_REFRESH_TOKEN'Pro tip: Catch and handle token refresh failures separately from segment fetch failures. A failed refresh might mean the user revoked access — mark those contacts as spotify_connected:false and stop attempting to sync them.
Expected result: All connected CRM contacts re-synced with updated Spotify listening preferences. Log output shows success/failure counts per batch.
Complete working code
This is a two-part system. The first part handles the OAuth callback when a user connects their Spotify account. The second part runs a monthly batch re-sync of all connected users. Both parts are shown in the complete automation script. Replace the database stubs with your actual database implementation.
1import os2import base643import time4import requests5from collections import Counter6from datetime import datetime78CLIENT_ID = os.environ['SPOTIFY_CLIENT_ID']9CLIENT_SECRET = os.environ['SPOTIFY_CLIENT_SECRET']10REDIRECT_URI = os.environ['SPOTIFY_REDIRECT_URI']1112def get_creds_header():13 return base64.b64encode(f"{CLIENT_ID}:{CLIENT_SECRET}".encode()).decode()1415def exchange_code(code):16 r = requests.post('https://accounts.spotify.com/api/token',17 headers={'Authorization': f'Basic {get_creds_header()}'},18 data={'grant_type': 'authorization_code', 'code': code, 'redirect_uri': REDIRECT_URI})19 r.raise_for_status()20 return r.json()2122def refresh_user_token(refresh_token):23 r = requests.post('https://accounts.spotify.com/api/token',24 headers={'Authorization': f'Basic {get_creds_header()}'},25 data={'grant_type': 'refresh_token', 'refresh_token': refresh_token})26 r.raise_for_status()27 return r.json()['access_token']2829def api_get(token, path, params=None):30 r = requests.get(f'https://api.spotify.com/v1{path}',31 headers={'Authorization': f'Bearer {token}'}, params=params)32 if r.status_code == 429:33 time.sleep(int(r.headers.get('Retry-After', 5)))34 return api_get(token, path, params)35 r.raise_for_status()36 return r.json()3738def build_segments(access_token):39 artists = api_get(access_token, '/me/top/artists', {'time_range': 'short_term', 'limit': 20})['items']40 tracks = api_get(access_token, '/me/top/tracks', {'time_range': 'short_term', 'limit': 20})['items']41 genre_scores = Counter()42 for i, a in enumerate(artists):43 for g in a['genres']:44 genre_scores[g] += (20 - i)45 top_genres = [g for g, _ in genre_scores.most_common(5)]46 avg_pop = sum(t['popularity'] for t in tracks) / len(tracks) if tracks else 047 return {48 'top_genres': top_genres,49 'top_artists': [a['name'] for a in artists[:5]],50 'avg_popularity': round(avg_pop),51 'crm_tags': [f'music_genre:{g.replace(" ","-")}' for g in top_genres[:3]],52 'synced_at': datetime.now().isoformat()53 }5455# === PART 1: OAuth callback (call from your web route) ===56def on_spotify_connect(auth_code, crm_contact_id):57 tokens = exchange_code(auth_code)58 profile = api_get(tokens['access_token'], '/me')59 segments = build_segments(tokens['access_token'])60 # Store in database (implement your own)61 user_record = {62 'crm_contact_id': crm_contact_id,63 'spotify_user_id': profile['id'],64 'spotify_email': profile.get('email'),65 'refresh_token': tokens['refresh_token'],66 'segments': segments67 }68 print(f'Connected: {profile.get("email")} -> {segments["top_genres"][:2]}')69 return user_record7071# === PART 2: Monthly batch re-sync ===72def batch_resync(connected_users):73 # connected_users: list of {crm_contact_id, refresh_token} from DB74 success, failed = 0, 075 for user in connected_users:76 try:77 token = refresh_user_token(user['refresh_token'])78 segments = build_segments(token)79 print(f'Re-synced {user["crm_contact_id"]}: {segments["top_genres"][:2]}')80 success += 181 time.sleep(0.5) # Per-user rate limit courtesy82 except Exception as e:83 print(f'Error syncing {user["crm_contact_id"]}: {e}')84 failed += 185 print(f'Batch complete: {success} ok, {failed} failed')Error handling
{"error":{"status":403,"message":"Insufficient client scope"}}The access token was issued without user-read-email scope, or the user declined to grant the email permission during OAuth. Also returned for deprecated endpoints (audio-features, recommendations, related-artists).
Re-authorize the user with the full scope string including user-read-email. If the user explicitly denied email access, you will need to request re-authorization — some users intentionally block email sharing.
Not retryable — fix the scope or handle missing email gracefully.
{"error":{"status":401,"message":"No token provided"}}Access token expired (3,600 seconds) or the user revoked the app's access from their Spotify account settings.
Refresh using the refresh_token. If the refresh also fails with 400/401, the user has revoked access — mark their CRM contact as spotify_connected:false and stop attempting syncs.
Refresh once and retry. If refresh fails, mark user as disconnected.
{"error":{"status":429,"message":"API rate limit exceeded"}}Too many requests in the rolling 30-second window. At scale, multiple concurrent user syncs compound the rate limit.
Implement per-user queuing with 500ms delays. Honor the Retry-After header. Process batch re-syncs sequentially with delays rather than concurrently.
Honor Retry-After header. Resume processing after the wait period.
{"error":"invalid_grant"}Refresh token is invalid, expired, or was already used. This happens when a user revokes app access via their Spotify account settings.
Remove the stored refresh token for this user, mark their CRM record as spotify_connected:false, and optionally send them a re-connection email.
Not retryable — the user must re-authorize the app.
Rate Limits for Spotify API
| Scope | Limit | Window |
|---|---|---|
| Per app (rolling window) | Undisclosed exact threshold | Rolling 30 seconds |
| Single-user sync (3-4 API calls) | Well within limits for individual syncs | Completes in under 3 seconds |
| Batch re-sync at scale | Add 500ms delay between users | Process sequentially, not concurrently |
1import time23def api_get_with_retry(token, url, params=None, max_retries=3):4 headers = {'Authorization': f'Bearer {token}'}5 for attempt in range(max_retries):6 r = requests.get(url, headers=headers, params=params)7 if r.status_code == 429:8 wait = int(r.headers.get('Retry-After', 2 ** attempt))9 print(f'Rate limited. Waiting {wait}s (attempt {attempt+1})')10 time.sleep(wait)11 elif r.status_code == 401:12 raise ValueError('Token expired — refresh and retry outside this function')13 elif r.ok:14 return r.json()15 else:16 r.raise_for_status()17 raise RuntimeError('Max retries exceeded')- Process batch re-syncs sequentially with 500ms delays between users — concurrent processing at scale will hit the rolling rate limit
- Run re-syncs during off-peak hours (e.g., 2-4 AM) when your app's other API usage is lower
- Cache the user profile data (email, country) from Step 1 — it rarely changes and does not need re-fetching on every sync
- Honor the Retry-After header on every 429 — do not implement fixed backoff durations
- Log all rate limit events with timestamps to identify patterns in when you're hitting limits
Security checklist
- Encrypt all stored refresh tokens at rest — a leaked refresh token gives full Spotify account read access
- Use CSRF state parameter in every OAuth authorization URL to prevent cross-site request forgery
- Implement token revocation handling — when a user disconnects, call Spotify's revoke endpoint and delete their stored tokens
- Never expose user email matching logic to the browser — all CRM matching must happen server-side
- Store Client Secret in server-side environment variables only — never in client-side JavaScript or mobile apps
- Comply with GDPR and CCPA when storing Spotify listening data — disclose what data you collect and provide opt-out
- Log all sync events with user IDs for audit trail, but never log token values
- Rotate Client Secrets periodically from developer.spotify.com/dashboard and update environment variables
- In Development Mode, only add users you have explicit consent from — Spotify holds you responsible for authorized users' data
Automation use cases
Music Fan Segmentation for Event Promoters
advancedEvent promoters tag CRM contacts with top genre preferences to send targeted promotions for concerts and festivals matching their taste.
Artist-to-Fan CRM Enrichment
advancedAn artist's official website offers 'Connect Spotify' to fans, syncing genre affinity and artist affinity data to enrich the fan CRM for targeted merch and tour announcements.
Music Preference Survey Replacement
intermediateInstead of asking new subscribers to fill out a genre preference survey, offer 'Connect Spotify' to auto-populate taste segments with verified listening data.
Streaming Platform Acquisition Attribution
advancedMatch Spotify premium vs free tier data (from the product field in GET /v1/me) to CRM contacts to target Premium users with different upgrade messaging than Free users.
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/monthZapier's Spotify integration can trigger CRM updates from Spotify listening events, though the per-user OAuth flow still requires a custom callback handler.
- + No code for CRM sync logic
- + Connects Spotify to 7,000+ CRM and email tools
- + Runs automatically
- - Still requires a custom OAuth callback for initial user authorization
- - Free tier limited to 100 tasks/month
- - Cannot match by email server-side within a Zap
Make
Free tier available; paid plans from $9/monthMake can handle the Spotify OAuth flow and CRM update in a single scenario with HTTP modules, reducing the amount of custom code needed.
- + Visual multi-step scenario builder
- + Handles OAuth callback flows
- + More flexible than Zapier for custom data mapping
- - OAuth setup is complex compared to code
- - CRM sync logic requires knowledge of Make's data mapping
- - Scale limitations on free tier
n8n
Self-hosted free; cloud from €20/monthn8n's Webhook node can receive OAuth callbacks, and the Spotify node handles API calls, making it a capable self-hosted alternative for the full segmentation pipeline.
- + Self-hosted = free unlimited executions
- + Full code access in Code nodes for matching logic
- + Open source
- - Requires server setup for self-hosting
- - OAuth callback requires public HTTPS endpoint
- - More complex than pure-code approach
Best practices
- Be upfront with users about what Spotify data you're accessing — display the scope permissions on your Connect Spotify page before they authorize
- Store a spotify_connected_at timestamp and spotify_last_synced timestamp on each CRM contact to track data freshness
- Handle the case where a user's Spotify email differs from their CRM email by matching on spotify_user_id instead of email after initial connection
- Gracefully handle missing email (some Spotify accounts do not have an email address) by falling back to matching on the CRM contact ID passed through the state parameter
- Limit the CRM tags you create to a manageable number — genre tags like 'music_genre:post-grunge' are actionable; storing all 50 raw genres as tags creates noise
- Test your full OAuth flow with a real user account in Development Mode before requesting Extended Quota — many bugs surface during the redirect and callback phase
- Implement a user-facing 'Disconnect Spotify' option that revokes access tokens and clears stored segments — it's legally required under GDPR and builds trust
Ask AI to help
Copy one of these prompts to get a personalized, working implementation.
I'm building a Spotify audience segmentation system for a music marketing CRM. My approach: users connect Spotify via OAuth on my website, I get their email via GET /v1/me, match to a CRM contact, then fetch GET /v1/me/top/artists to extract genre preferences as CRM tags. The problem: some users have a different email on Spotify than in my CRM. How should I handle the case where the Spotify email doesn't match any existing CRM contact? Should I create a new contact, flag for manual review, or use the state parameter to carry the CRM contact ID through the OAuth flow to avoid email matching entirely? What are the tradeoffs?
Build a 'Connect Spotify' feature for a music marketing platform. The UI needs: 1) A 'Connect Your Spotify' page with an explanation of what data will be accessed (listening history for genre segmentation) and a Spotify-branded 'Connect' button that initiates OAuth with user-read-email and user-top-read scopes, 2) An OAuth callback page that shows a loading spinner while processing, then redirects to a success page, 3) A success page showing the user's Spotify display name, their top 3 genres detected from GET /v1/me/top/artists, and a 'Disconnect Spotify' button, 4) A 'Disconnect' confirmation modal that clears the stored tokens. Handle OAuth errors (user denied access) with a friendly error message. Use Tailwind CSS.
Frequently asked questions
Can I look up a user's Spotify data by their email address without them authorizing my app?
No — this is the single most important limitation for CRM use cases. Spotify has no server-to-server 'find user by email' API. The only way to access a user's listening data is for that user to individually complete the OAuth authorization flow on your website or app. After they authorize, you can call GET /v1/me with user-read-email scope to retrieve their Spotify email and match it to your CRM.
How many users can I segment in Development Mode?
Only 5 authorized Spotify users per Client ID in Development Mode (as of February 11, 2026). The app owner must have Spotify Premium. You must manually add each test user at developer.spotify.com/dashboard before they can authorize. For production audience segmentation at real scale, Extended Quota Mode is required — which since May 15, 2025 requires a legally registered organization with 250,000+ monthly active users.
Is the Spotify API free for audience segmentation?
Yes — the API itself is free. But Development Mode is limited to 5 users, making it unsuitable for production segmentation campaigns. Extended Quota Mode requires a legally registered organization with 250,000+ MAU — this is a hard requirement, not a paid tier. There is no paid plan to purchase more Development Mode slots.
What happens when I hit the rate limit?
You receive HTTP 429 with a Retry-After header. At scale (Extended Quota), concurrent user syncs compound the rolling 30-second rate limit. Process batch re-syncs sequentially with 500ms delays between users rather than running them concurrently. Always honor the Retry-After header value exactly.
Can I use audio features (tempo, energy, danceability) for more precise segmentation?
No — GET /v1/audio-features is permanently deprecated for apps created after November 27, 2024 and returns HTTP 403. Use genre tags from GET /v1/me/top/artists as the primary segmentation signal. Genre tags like 'post-grunge', 'dance pop', or 'lo-fi beats' provide meaningful taste segmentation without audio features data.
What data protection obligations apply when storing Spotify listening history in a CRM?
Listening history is personal data under GDPR and similar regulations. You must: disclose what Spotify data you collect in your privacy policy, obtain explicit consent via the OAuth flow, provide a way for users to disconnect and have their data deleted, and store tokens and listening data securely (encrypted at rest). Do not sell or share Spotify listening data with third parties without explicit consent. Spotify's Developer Terms also have their own data use restrictions.
Can RapidDev help build a production Spotify CRM segmentation system?
Yes — RapidDev has built 600+ integrations including OAuth flows, CRM connectors, and audience segmentation systems. We can build a complete 'Connect Spotify' feature with secure token storage, monthly re-sync, CRM tag management, and compliance tooling. Reach out at rapidevelopers.com for a free consultation.
Need this automated?
Our team has built 600+ apps with API automations. We can build this for you.
Book a free consultation