Getting started .md

Authentication

Two credential types, one rule: every request carries one of them. Catalog and sync endpoints both require a credential; the only exceptions are the public list and discovery endpoints and the global calendar.

Credential Best for How it authenticates
Session token Apps acting as a signed-in person (Kodi addons, TV apps, mobile) Authorization: Bearer <token>, obtained through the device-code flow
API key Scripts and server-side tools tied to your own account Authorization: Bearer fs_live_… or ?api_key=fs_live_… (TMDB style)

The device-code flow#

Four steps, following the standard device-authorization pattern (RFC 8628, the same flow TV apps use everywhere). The quickstart walks it end to end with the full poll loop in three languages.

  1. POST /auth/device/code with your registered client_id. Returns user_code, device_code, verification_uri, expires_in (900 seconds), and interval (minimum seconds between polls).
  2. Show user_code and point the person at https://flicklist.tv/link, where they approve the device from any signed-in browser. They can label the session ("Living Room TV") and revoke it later from their Connected Apps settings.
  3. POST /auth/device/token with the device_code, no faster than interval. The endpoint returns 200 for every state. The body's error field tells you where things stand: authorization_pending (keep polling), access_denied (the person declined, stop polling), or expired_token (the 15-minute window lapsed, request a fresh code). After approval the body carries access_token plus the account's profile. That profile object currently includes the account email and internal role fields: treat it as sensitive, and don't display, store, or transmit more of it than your app needs. Only an unrecognized device_code gets a non-200.
  4. Store the token. It is a 30-day session bound to your client_id, and the response's expires_at tells you exactly when it lapses.

Token rotation#

POST /auth/refresh with a valid session token returns a new token with a fresh 30-day expiration and invalidates the old one (rotation, not extension). Refresh whenever you like; a common pattern is on app start when the token is older than a week.

API keys are not refreshed through this endpoint (sending one returns 400). They carry their own independent expiration.

API keys and scopes#

Create keys from your FlickList dashboard (Settings, then Apps). Treat a key like a password: it belongs in server-side code and scripts, never in browser code you ship. Keys are prefixed fs_live_ and carry scopes:

Scope Grants
read Every GET under /v3/sync/*, plus your personal calendar
write Mutations under /v3/sync/* and all of /v3/scrobble/*

Requests that lack the needed scope fail with 403 and the standard error envelope. Catalog reads work with any valid credential, no scope needed.

Checking who you are#

GET /v3/me returns the account behind the calling credential: id, username, display name, avatar. It deliberately omits email and internal flags. Use it on startup to confirm a stored token still works and which account it belongs to.

curl -H "Authorization: Bearer $TOKEN" "https://flicklist.tv/api/v3/me"

Respect the revoke#

Any FlickList user can disconnect your app at any moment from their own settings, without telling you first. A revoked session starts returning 401: treat that as "re-run the device flow", never as an error worth retry-hammering.