- Authorization code + PKCE for browser, website, and native apps that can receive a callback
- Device code for TV, desktop, CLI, and clients without a convenient browser callback
/api/platform/v1.
Register your app first
Create a developer app at Get API key. Each app receives a stableclient_id.
- Confidential clients also receive a
client_secret - Public clients use
client_idonly - Every app defines its maximum
allowed_scopes - The approval screen shows the app name and requested scopes before the user approves access
Client types
Current scopes
Apps can currently request these scopes:
If a request omits
scope, PunchPlay grants the app’s configured allowed_scopes.
If a request asks for a scope outside the app’s allowed_scopes, the request fails with invalid_scope.
email:read is reserved and is not available to developer apps. Use the
stable user ID returned by GET /api/platform/v1/me when linking accounts.
PunchPlay’s /me/push-devices routes are also reserved for developer apps
explicitly marked as first-party. The notification scopes remain available to
third-party apps for inbox, unread-state, and preference features.
Third-party apps should only redirect users to the GET /api/platform/v1/oauth/authorize endpoint. The consent screen’s POST decision
handler is used by PunchPlay’s own signed-in, same-origin UI; it is not an app
approval API, even though it appears in the generated reference with
security: [].
Flow selection
Use this rule:- Use authorization code + PKCE for browser, website, and native apps that can redirect a user and receive a callback
- Use device code for TV, desktop, CLI, and clients that cannot handle a normal browser callback cleanly
Authorization code + PKCE
1. Redirect the user to PunchPlay
response_type=codeclient_id=YOUR_CLIENT_IDredirect_uri=YOUR_REGISTERED_REDIRECT_URIcode_challenge=BASE64URL_SHA256_OF_CODE_VERIFIERcode_challenge_method=S256
scope=profile:read playback:read playback:write events:readstate=YOUR_OPAQUE_STATE
302 back to your redirect_uri with:
codestateif you sent onescope
error. Redirect-based failures may also include request_id so the developer has something concrete to report.
Users can review and revoke approved apps later from https://punchplay.tv/settings/connected-apps.
Store the state value with the pending authorization transaction and compare
it exactly on callback. Keep the original PKCE verifier private until the code
exchange completes; a verifier is not a substitute for state validation.
2. Exchange the code for tokens
client_id only. Confidential apps send both client_id and client_secret.
Successful response:
3. Refresh the access token
Device code
1. Request a device code
client_secret.
Response fields:
2. Poll the token endpoint
400 with the standard OAuth device-flow error:
3. Refresh the access token
Authenticated requests
Use the access token in theAuthorization header:
/api/platform/v1.
Token lifetimes
Access tokens live for one hour (expires_in: 3600). Refresh tokens live for
a year, and rotate on every use — each refresh returns a new one, and the
previous one stops working immediately.
Your client must refresh. Either refresh shortly before expires_in elapses, or
retry once on a 401 after refreshing. Both work; do not do neither.
Access tokens are deliberately short lived because they are bearer credentials:
anyone holding one is the user until it expires. Revocation covers leaks you
notice; a short lifetime covers the ones you do not.
Debugging auth failures
Platform auth errors include:request_idin the JSON bodyX-PunchPlay-Request-Idin the response headers
request_id.
When reporting a failure, capture:
request_id- UTC timestamp
- endpoint path
client_id- status code
- raw error body
Security guidance
- Treat
client_secret, refresh tokens, and access tokens as sensitive credentials. - Do not embed
client_secretin native apps, browser apps, or sample code intended for public distribution. - Use public clients when your app cannot safely hold a secret.
- Keep
allowed_scopesas narrow as possible for each app. - Rotate secrets immediately if you suspect they were exposed.
- Deactivate an app if you need to revoke its issued tokens quickly.
- If your app runs entirely in the browser, keep in mind that standard
EventSourceclients cannot attach custom authorization headers.
Recommended polling behavior
Poll every few seconds until the user approves the request or the device code expires. Back off if your app has multiple concurrent authorization attempts. Authentication JSON and form bodies are limited to 64 KiB and must arrive within 10 seconds. Oversized bodies return413; timed-out bodies return 408.