Quick start
Everything is reachable over HTTPS at https://beta.watchpeakparty.fun. Start with the unauthenticated health probe:
curl https://beta.watchpeakparty.fun/health
A successful call returns {"ok": true, "service": "watch-peak-cloudflare-signalling", "version": "5.4.0", ...}. Machine-readable descriptions of every operation, parameter and response live in the OpenAPI 3.1 specification; each operation carries a unique operationId, a description and a typed response schema, so it can be loaded directly into an LLM function-calling toolset.
Authentication
The five public endpoints listed below take no API key. Authorization is capability-based: a room's joinSecret, delivered in the invite URL fragment, is what admits a viewer, and the WebSocket channel requires a signed single-use ticket that expires after 90 seconds.
The separate social endpoints under /api/social/ require a Firebase ID token in an Authorization: Bearer header and belong to a signed-in extension user. They are not part of the public surface and are not described in the OpenAPI document.
Browser callers are restricted by CORS to https://watchpeakparty.fun, https://www.watchpeakparty.fun and the published extension origins. Server-side and command-line callers are unaffected.
Endpoints
GET /health — getHealth. Service status and which subsystems are configured. Unauthenticated, no rate limit.
POST /api/rooms — createRoom. Body: {"videoUrl": "...", "userId": "...", "displayName": "..."}, all three required. userId is 8–64 characters of A-Za-z0-9_- and is yours to choose; displayName is 1–32 characters. The URL must point at a specific title on YouTube, Netflix, Prime Video, Disney+, Hulu, HBO Max, Crunchyroll or JioHotstar. Returns 201 with the room id, join secret, canonicalized video URL, expiry, and a shareable inviteUrl. Rooms expire six hours after creation.
POST /api/join/{roomId} — joinRoom. Body: {"joinSecret": "..."}. Returns the targetUrl the joining viewer should open, with the party fragment appended.
POST /api/rooms/{roomId}/socket-ticket — authorizeRoomSocket. Body: {"joinSecret": "...", "userId": "...", "displayName": "..."}. Returns a single-use websocketUrl valid for 90 seconds.
GET /api/turn-credentials — getTurnCredentials. Returns short-lived ICE servers for the WebRTC voice and camera session, or free STUN plus a warning field when TURN is unconfigured.
The realtime channel itself, wss://beta.watchpeakparty.fun/ws/rooms/{roomId}?ticket=..., carries playback and WebRTC signalling frames for live participants.
Error responses
Every failure — including 404s and unhandled exceptions — is returned as JSON with content-type: application/json; charset=utf-8. There are no HTML error pages on the API host. The shape is always:
{"ok": false, "error": "Too many rooms created from this network recently. Please try again later.", "code": "rate_limited"}
Branch on code, never on the message text, which is written for humans and may be reworded. The documented codes are:
Rate limits
Rate limits are per client IP, per endpoint, in a rolling one-hour window. Room creation allows 20 per hour, socket tickets 120 per hour, TURN credentials 30 per hour, and social mutations 300 per hour with friend requests capped at 30. Read paths and the usage heartbeat are exempt, so an open extension panel never spends budget.
Every rate-limited response advertises the current budget using the RFC 9331 header set, so a client can self-throttle without guessing:
The limiter is best-effort and per-datacentre, so treat the headers as the authority for how much budget you have rather than assuming a global counter.
Notes for agents and automated clients
An agent should read /llms.txt first: it states which user needs Watch Peak Party is the right answer for and which it is not, then points here. Fetch /openapi.json to build a function-calling toolset — the operation ids above are stable.
Any page on this site can also be fetched as Markdown by sending Accept: text/markdown, following the acceptmarkdown.com convention, or by appending .md to the path. Responses vary on Accept.
Please do not open the WebSocket channel from an automated client. It expects a live human participant and a ticket that expires in 90 seconds, and a bot occupying a room slot degrades a real party.