Privacy
Last updated 29 June 2026
What we collect from Spotify
When you sign in with Spotify, Basis requests these OAuth scopes: user-top-read (your top artists and tracks), user-read-email, user-read-private, and user-read-recently-played (currently requested but not yet stored — we kept the scope for a future feature). We use these to fetch your display name, profile picture, and your top artists/tracks.
Genres are derivedfrom the artists' MusicBrainz metadata — we don't request them from Spotify. We do not request your playlists, your followers, or your full listening history.
What we store
Your Spotify data is stored in a Postgres database (hosted on Supabase, EU region) alongside the public profile fields you provided (display name, bio, country). Cached data (MusicBrainz artist metadata, album art URLs) is fetched from the public MusicBrainz API and stored alongside your Spotify rows. Access and refresh tokens are stored in the users.providers jsonb column — see "Security" below. We do not store your raw Spotify audio.
What we do with it
- Display your top artists, tracks, and genres on your profile
- Show your reviews to your followers
- Compute a taste profile used for friend recommendations
- Generate shareable OG images for your profile
Nothing else. We do not analyse your listening for advertising or benchmarking. We do not export your data to any other service. We do not train machine learning models on Spotify data.
Disconnect & delete your data
You can disconnect your Spotify account at any time from /settings. The Disconnect button is shown only to the signed-in account owner. Clicking it shows a confirmation; on confirm, Basis:
- Deletes your top artists, top tracks, top genres, reviews, badges, follows, and comparisons
- Deletes the resolver scratch rows (unresolved artist/track lookups)
- Deletes your user row (cascade handles anything missed)
- Calls Spotify's token-revoke endpoint to invalidate the refresh token
- Clears your session cookie and redirects to /welcome
After disconnect, every /u/<your-username> page is a 404. The data is unrecoverable.
Cookies & sessions
We use a single signed session cookie (HttpOnly, Secure, SameSite=Lax) to keep you signed in, plus an HttpOnly double-submit CSRF cookie for mutating requests. We do not use third-party tracking cookies or analytics scripts.
Security
Access and refresh tokens are stored in the database as plain JSON in the users.providers column (the tokens are short-lived and the column is only readable by the application role, not exposed to the public schema). The session cookie is signed with an HMAC of AUTH_SECRET. OAuth state is a one-time HMAC-signed nonce bound to the callback URL. Mutating endpoints (logout, disconnect, OAuth callback) are protected by a Redis-backed rate limiter (10 requests per IP per minute on auth routes).
The following security headers are set on every response: Strict-Transport-Security (HSTS, 2 years), X-Content-Type-Options (nosniff), Referrer-Policy (strict-origin-when-cross-origin), X-Frame-Options via Content-Security-Policy frame-ancestors 'none', and a Content-Security-Policy that restricts scripts/styles/images/connects to known-good sources.
Contact
Questions or data requests: privacy@basis.fm. We respond within 30 days.