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.
POST /auth/device/codewith your registeredclient_id. Returnsuser_code,device_code,verification_uri,expires_in(900 seconds), andinterval(minimum seconds between polls).- Show
user_codeand point the person athttps://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. POST /auth/device/tokenwith thedevice_code, no faster thaninterval. The endpoint returns200for every state. The body'serrorfield tells you where things stand:authorization_pending(keep polling),access_denied(the person declined, stop polling), orexpired_token(the 15-minute window lapsed, request a fresh code). After approval the body carriesaccess_tokenplus 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 unrecognizeddevice_codegets a non-200.- Store the token. It is a 30-day session bound to your
client_id, and the response'sexpires_attells 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"const me = await fetch('https://flicklist.tv/api/v3/me', {
headers: { Authorization: `Bearer ${token}` }
}).then((r) => r.json());me = requests.get(
"https://flicklist.tv/api/v3/me",
headers={"Authorization": f"Bearer {token}"},
).json()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.