Build a client (iOS, Android, desktop)
TRaX is built to be driven by your own code — including full third-party "thick clients" that produce a show without ever opening our web studio. A rich client doesn't speak one protocol; it speaks several, one per job. This guide is the map: which transport for which task, and how to authenticate each.
The two authentication models — pick by who you are
Before anything else, decide who your code acts as:
| You're building… | Authenticate as | Credential |
|---|---|---|
| A first-party app a user logs into (mobile / desktop that produces or controls a show) | the user | OAuth 2.0 (PKCE) → user access token (JWT), sent as Authorization: Bearer <jwt> |
| Server-to-server automation / a third-party integration (dashboards, bots, headless jobs) | yourself (the developer) | an API key: Authorization: Bearer sk_live_… on the /v1 REST API |
These aren't mutually exclusive — a mobile app might log the user in with OAuth
for live control and call /v1 with the user's token for reads — but the
question "am I logging a user in, or running my own automation?" decides
your primary path.
Transport map — which API for which job
| I want to… | Transport | How | Auth |
|---|---|---|---|
| Control a studio + receive live state (scenes, sources, go-live, presence, chat control) | WebSocket | connect to the studio control plane (below) | user bearer |
| Publish camera / mic / screen from the app | WebRTC WHIP | POST an SDP offer to the studio's WHIP endpoint — see WHIP / WHEP | media session token (Bearer) |
| Publish a hardware / OBS / camera feed | SRT or RTMP(S) | SRT streamid · RTMP | session token in streamid / userinfo |
| Watch the program or a source preview — now | WebRTC WHEP | POST an SDP offer to the WHEP endpoint — see WHIP / WHEP | media read token (Bearer) |
| Watch at lowest latency — later | MoQ (roadmap) | not shipped yet; use WHEP today | — |
| List / read studios, sources, destinations, stream status; go live / offline | REST /v1 |
the Developer API | sk_live_ API key (or user bearer) |
Rule of thumb for a thick client: one WebSocket to control a studio and
stream its live state; WebRTC (WHIP up / WHEP down) for media; REST
(/v1) for headless reads and automation. Stream paths (the studios/{id}/…
names you publish and play) follow one grammar — see Stream paths.
Native-app authentication — OAuth 2.0 with PKCE
A first-party app logs the user in against the TRaX identity provider using the
Authorization Code flow with PKCE (the standard, secret-less flow for native
and single-page apps). You get back a user access token (JWT) and a refresh
token; the access token is what every TRaX surface accepts as
Authorization: Bearer <jwt>.
Identity provider (dev): https://auth-dev.traxstreaming.live
| Purpose | Endpoint |
|---|---|
| Authorize | https://auth-dev.traxstreaming.live/oauth/v2/authorize |
| Token | https://auth-dev.traxstreaming.live/oauth/v2/token |
| End session (logout) | https://auth-dev.traxstreaming.live/oidc/v1/end_session |
Scopes: openid profile email. You'll register your app (to get a client id
and your allowed redirect URIs) with the TRaX team — contact us for a
native app registration.
The flow:
Generate a PKCE pair. Create a random
code_verifier, thencode_challenge = BASE64URL(SHA256(code_verifier)).Open the authorize URL in a system browser /
ASWebAuthenticationSession(iOS) / Custom Tab (Android) — not an embedded webview:https://auth-dev.traxstreaming.live/oauth/v2/authorize ?response_type=code &client_id=<your-client-id> &redirect_uri=<your-redirect-uri> &scope=openid%20profile%20email &code_challenge=<challenge> &code_challenge_method=S256Use a custom URI scheme (
com.yourapp://callback) or a loopback redirect for the native round-trip.Handle the redirect — you receive
?code=<authorization_code>.Exchange the code for tokens (no client secret — PKCE stands in for it):
curl -sS https://auth-dev.traxstreaming.live/oauth/v2/token \ -H "Content-Type: application/x-www-form-urlencoded" \ -d grant_type=authorization_code \ -d client_id=<your-client-id> \ -d code=<authorization_code> \ -d redirect_uri=<your-redirect-uri> \ -d code_verifier=<code_verifier>The response includes
access_token(a JWT),refresh_token, andexpires_in. Store them in the platform keystore (iOS Keychain / Android Keystore), and usegrant_type=refresh_tokenwith the sameclient_idto get a fresh access token before it expires.
Send the resulting access token as Authorization: Bearer <jwt> on the
WebSocket upgrade, on WebRTC WHIP/WHEP signaling, and on /v1 REST calls.
This is the same OAuth-PKCE pattern this docs site itself uses to log in — a native app differs only in the redirect (custom scheme / loopback instead of a web
/callbackpage) and in storing tokens in the OS keystore.
Native vs. browser: the header advantage
A native app can set request headers everywhere, which keeps auth uniform:
- WebSocket — set
Authorization: Bearer <jwt>on the upgrade request. (Browsers can't set headers on a WebSocket handshake, so the web client has to fall back to passing the token another way — a native app has no such limit and should use the header.) - WebRTC WHIP / WHEP — set
Authorization: Bearer <token>on the signalingPOST. - REST
/v1—Authorization: Bearer …as usual.
Preferring the header on native keeps the token out of URLs and logs.
Controlling a studio (WebSocket)
Real-time studio control — scenes, sources, going live, presence, chat control, and the live state stream back to your UI — runs over a WebSocket to the studio control plane:
wss://studio-api-dev.traxstreaming.live/api/v1/studios/{studioId}/ws
Open it with the user's bearer token; the server resolves the user's access to that studio once at upgrade, then gates each operation by role. Frames are JSON — request/reply RPCs plus server-pushed realtime events.
The full RPC + event catalog for this surface is first-party/internal
today. If you're a logged-in first-party developer, see the internal reference
for the exhaustive method and event lists (WS RPCs, WS events, and the private
transport map). Third-party apps reach the platform through the public /v1
REST gateway and this WebSocket — never internal service endpoints directly.
Where to go next
- Developer API (
/v1) — REST reference, endpoint table, API keys, and OpenAPI client generation. - Authentication & session tokens — token claims and how to verify a TRaX-issued token against our JWKS.
- WHIP / WHEP — publish and play media over WebRTC.
- SRT streamid · RTMP / RTMPS — push a hardware or OBS feed.
- Stream paths — the
studios/{id}/…path grammar shared by every media transport.
Tell us what you're building — the roadmap follows what the community wants to ship.