Authentication
Every request acts for one member, and carries one bearer token in the Authorization header:
GET /v1/me HTTP/1.1Host: getrefract.appAuthorization: Bearer rfk_…| Who runs the code | Use | Token lifetime |
|---|---|---|
| You, for yourself | A personal key | Until you revoke it, or the expiry you chose |
| Your app, for other members | Sign in with Refract (OAuth 2.1, PKCE) | Access token one hour, refresh token 90 days |
| A device without a keyboard | The device code | Same as OAuth |
The API is open to a first group of members while it is new. A member outside it cannot create keys or approve apps, and the API refuses tokens issued for them.
Scopes
Section titled “Scopes”A credential carries the scopes the member granted. Each endpoint needs one, named in the
reference; a credential without it gets 403 with
INSUFFICIENT_SCOPE.
| Scope | Lets your app |
|---|---|
profile:read |
See the member’s profile: username, display name, avatar. |
library:read |
See the library and the watchlist. |
history:read |
See what the member watched and when. |
ratings:read |
See the member’s ratings. |
lists:read |
See the member’s lists. |
The matching :write scopes exist and imply read; the API serves no write yet.
Personal keys
Section titled “Personal keys”For code that only you run. In the Refract app, open Access and connected apps from the Integrations screen
and create a key: name it, pick its scopes, and optionally give it an expiry between 1 and 365 days. The key starts
with rfk_, carries a checksum, and is shown once. A member can hold up to 10 keys and revoke any of them from
the same screen; a revoked key stops working at once.
Never ship a personal key in an app other people install: it opens your own account.
Sign in with Refract
Section titled “Sign in with Refract”For apps that other members use. Refract is an OAuth 2.1 authorization server with PKCE (S256 only), refresh token rotation and OpenID Connect.
Register your app in the same Access screen, under your apps. Give it a name and its redirect URIs:
https:// addresses, loopback http://127.0.0.1 or http://[::1] for desktop tools, or a reverse-domain scheme
for a native app (com.example.app:/callback). Choose a public client (no secret; PKCE protects the exchange) for
apps that run on the user’s device, or a confidential client (with a secret you can rotate) for a server.
The flow. Send the member to the authorization endpoint with a fresh PKCE verifier:
https://getrefract.app/api/auth/oauth2/authorize ?response_type=code &client_id=YOUR_CLIENT_ID &redirect_uri=https://example.com/callback &scope=profile:read library:read offline_access &state=RANDOM_STATE &code_challenge=BASE64URL_SHA256_OF_VERIFIER &code_challenge_method=S256 &resource=https://getrefract.app/v1The member signs in to Refract, sees your app’s name and the scopes in plain words, and approves or refuses. Refract
redirects back with code and your state. Check the state, then exchange the code:
curl https://getrefract.app/api/auth/oauth2/token \ -d grant_type=authorization_code \ -d code=THE_CODE \ -d redirect_uri=https://example.com/callback \ -d client_id=YOUR_CLIENT_ID \ -d code_verifier=THE_VERIFIER \ -d resource=https://getrefract.app/v1The answer holds an access_token for the API (one hour) and, if you asked for offline_access, a
refresh_token. Each refresh returns a new refresh token and retires the old one; store the new one before using it.
Refresh tokens last 90 days. A member can disconnect your app at any time from their Access screen; your next refresh
then fails and your access token stops working when it expires.
Send resource=https://getrefract.app/v1 (RFC 8707) when you ask for tokens: it names the API the token is for.
TVs, consoles and terminals
Section titled “TVs, consoles and terminals”The device authorization grant (RFC 8628), for devices where typing a password is painful:
- Your device asks for a code:
Terminal window curl https://getrefract.app/api/auth/device/code \-d client_id=YOUR_CLIENT_ID \-d "scope=profile:read library:read offline_access" \-d resource=https://getrefract.app/v1 - Show the
user_codeand ask the member to open getrefract.app/device on their phone. They sign in, check the app name and the scopes, and approve. - Meanwhile, poll the token endpoint every
intervalseconds:Terminal window curl https://getrefract.app/api/auth/oauth2/token \-d grant_type=urn:ietf:params:oauth:grant-type:device_code \-d device_code=THE_DEVICE_CODE \-d client_id=YOUR_CLIENT_IDauthorization_pendingmeans keep waiting;slow_downmeans wait longer between polls.
Discovery
Section titled “Discovery”| Document | Address |
|---|---|
| Authorization server metadata | https://getrefract.app/.well-known/oauth-authorization-server |
| OpenID Connect configuration | https://getrefract.app/.well-known/openid-configuration |
| The API’s protected-resource metadata (RFC 9728) | https://getrefract.app/.well-known/oauth-protected-resource/v1 |
A 401 from the API carries a WWW-Authenticate header that points to the protected-resource metadata and names
the scope the endpoint needs.