# Player API Reference ## Overview Player service base URL: `http://localhost:8081` This document covers the player HTTP surface only. The admin dashboard exposes its own routes for screen commands and onboarding management. Access note: most player endpoints are unauthenticated because they are meant to run inside a trusted deployment network. Anything that mutates state or writes files should be treated as internal-only unless you add your own auth layer in front of it. Pairing uses a short-lived random PIN displayed by the kiosk; the PIN is accepted only through the authenticated Web UI pairing flow. When `PULSE_SIGNAGE_SHARED_SECRET` is set, the player pages sign same-origin API fetches with `x-pulse-page-auth`, and the web app signs server-to-player requests with `x-pulse-request-timestamp` plus `x-pulse-request-signature`. Page tokens auto-renew before expiry while the page stays active, and signed server requests are only accepted when their timestamp is fresh. If the secret is unset, those checks stay disabled for compatibility. ## Endpoints ### `GET /` Returns the player onboarding landing page. Access: public within the trusted player deployment. ### `GET /onboard` Redirects to the authenticated Web UI pairing page for compatibility with older QR codes. Access: the Web UI pairing page requires a logged-in Web UI session. ### `GET /screen/{slug}` Returns the rendered player page for a screen. Access: the configured player may load only its persisted paired screen. An unpaired player is redirected to `/`; a different screen slug is rejected. The route is public within the trusted player deployment, but it no longer changes the player's binding. ### `GET /api/onboarding/status` Returns the persisted onboarding status for a device. Access: public within the trusted player deployment. Query fields: - `deviceId` required ### `GET /api/onboarding/screens` Returns the list of screens available for onboarding. Access: public within the trusted player deployment. ### `GET /api/onboarding/qr` Returns an SVG QR code that points to the onboarding form. Access: public within the trusted player deployment. Query fields: - `deviceId` required ### `POST /api/auth/page` Renews the current page-auth token before it expires. Access: internal to the player page and onboarding page. The request must include a valid `x-pulse-page-auth` header. Response fields: - `token` - `issuedAt` - `expiresAt` ### `POST /api/onboarding` Binds a device to a screen and client name. Access: internal-only. Browser submissions must go through the authenticated Web UI pairing page. The Web UI resolves the short-lived kiosk PIN to a device ID before forwarding the signed request. Protect this endpoint if the player service is reachable outside your trusted network. Accepted request fields: - `deviceId` required - `clientName` required - `screenSlug` required Response fields: - `deviceId` - `clientName` - `screenId` - `screenSlug` - `screenName` - `playerUrl` - `queued` ### `GET /api/media/config` Returns the upload directory configured for the player service. Access: internal-only. Response fields: - `mediaDir` - `uploadDir` ### `PUT /api/media/{filename}` Writes an uploaded file into the player upload directory. Access: internal-only and write-protected behind your deployment boundary. ### `DELETE /api/media/{filename}` Deletes a file from the player upload directory. Access: internal-only and write-protected behind your deployment boundary. ### `GET /api/rtmp/session` Creates or reuses an RTMP-to-HLS session for a source URL. Access: internal-only. Query fields: - `source` required - `disableAudio` optional Response fields: - `key` - `playlistUrl` - `disableAudio` - `ready` - `live` ### `GET /api/rtmp/streams/{key}/index.m3u8` Returns the RTMP session HLS manifest. Access: internal-only. ### `GET /api/rtmp/streams/{key}/{fileName}` Returns an RTMP HLS segment or related stream file. Access: internal-only. ### `GET /api/screens/{slug}/playlist` Returns the current playlist payload for a screen. Access: public within the trusted player deployment. Response fields: - `screen` - `playlist` - `slides` - `rssFeeds` - `apiSources` - `timetableGroups` - `revision` ### `GET /api/screens/{slug}/connections` ### `GET /api/screens/{slug}/clients` Returns the live player connection snapshot for a screen. Access: public within the trusted player deployment, but it exposes live connection state. Response fields: - `screen` - `screenSlug` - `count` - `connections` - `degraded` ### `POST /api/screens/{slug}/commands` Sends a command to the player connections for a screen. Access: internal-only. The admin dashboard should remain the protected control surface for commands. Accepted request fields: - `command` required - `connectionId` optional - `clientId` optional - `blackout` optional when `command=blackout` Command-specific fields: - `url` for `redirect` - `clientName` for `setclientname` - `deviceId` for `setclientname` Supported commands: - `refresh` - `reload` - `redirect` - `pause` - `blackout` - `previous` - `next` - `left` - `right` - `setclientname` If `connectionId` or `clientId` is provided, the command targets a single player connection. Otherwise it is broadcast to all connections for that screen. Response fields: - `screen` - `screenSlug` - `command` - `connectionId` - `sent` - `degraded` ## Response Shapes ### Onboarding Status Response `GET /api/onboarding/status` returns an object with: - `deviceId` - `onboarded` - `clientName` - `screenId` - `screenSlug` - `screenName` - `playerUrl` ### Onboarding Screens Response `GET /api/onboarding/screens` returns an object with: - `screens` ### QR Response `GET /api/onboarding/qr` returns SVG markup. ### Upload Config Response `GET /api/media/config` returns an object with: - `mediaDir` - `uploadDir` ### RTMP Session Response `GET /api/rtmp/session` returns an object with: - `key` - `playlistUrl` - `disableAudio` - `ready` - `live` ### Onboarding Write Response `POST /api/onboarding` returns an object with: - `deviceId` - `clientName` - `screenId` - `screenSlug` - `screenName` - `playerUrl` - `queued` ### Playlist Response `GET /api/screens/{slug}/playlist` returns an object with: - `screen` - `playlist` - `slides` - `rssFeeds` - `apiSources` - `timetableGroups` - `revision` ### Connections Response `GET /api/screens/{slug}/connections` and `GET /api/screens/{slug}/clients` return an object with: - `screen` - `screenSlug` - `count` - `connections` - `degraded` ### Command Response `POST /api/screens/{slug}/commands` returns an object with: - `screen` - `screenSlug` - `command` - `connectionId` - `sent` - `degraded` ## Data Models ### Screen - `id` - `name` - `slug` - `playlist_id` - `created_at` - `modified_at` ### Playlist - `id` - `name` - `fade_between_slides` - `skip_unavailable_rtmp` - `canvas_id` ### Slide - `id` - `title` - `body` - `duration_seconds` - `use_video_duration` - `disable_audio` - `scheduleRules` - `media_url` - `media_type` - `kind` - `template_id` - `template` - `content` ### Connection - `id` - `clientId` - `clientName` - `deviceId` - `label` - `userAgent` - `viewport` - `page` - `currentSlide` - `currentSlideId` - `currentSlideTitle` - `paused` - `blackout` - `clientIp` - `remoteAddress` - `connectedAt` - `lastSeenAt` ## Notes - The player API is the only surface documented here. - Web UI/admin routes are intentionally omitted, except where the player service itself exposes onboarding and upload endpoints.