# SDK Guide `videochat-sdk` — browser SDK (TypeScript) for joining rooms on the VideoChat platform. > Status: **beta** (`0.1.0-beta.x`). The API surface (`connect`/`join`/`publish`/events) is stable; simulcast controls may change before 1.0. ## Install ```bash npm install videochat-sdk ``` The package ships compiled ESM plus TypeScript declarations (`dist/index.js`, `dist/index.d.ts`). ## Quick start Joining a call is a three-step flow: get a token from the control plane, connect the SDK to the SFU, publish your media. ```ts import { VideoChatClient } from 'videochat-sdk'; // 1. Ask YOUR backend for a join token (never embed API keys in the browser): // POST /api/v1/tokens { room_id, display_name } -> { token, ws_url } const { token, ws_url } = await fetch('/my-backend/join?room=standup').then(r => r.json()); // 2. Connect to the SFU signaling channel. const client = new VideoChatClient({ wsUrl: ws_url, token }); const participantId = await client.connect(); // resolves on `connected` client.join(roomId); // sends the `join` message // 3. Publish camera + microphone. const stream = await navigator.mediaDevices.getUserMedia({ audio: true, video: true }); await client.publish(stream); // Remote media arrives as `track` events. client.addEventListener('track', (e) => { const { streams, track, participantId } = (e as CustomEvent).detail; videoElement.srcObject = streams[0]; }); // Peer lifecycle. client.onPeer(({ joined, left }) => { if (joined) console.log(`${joined.name} joined`); if (left) console.log(`${left} left`); }); ``` A complete working page lives in [`web/demo/index.html`](../web/demo/index.html) (it takes `wsUrl`, `token`, `roomId`, `name` as query parameters). ## API surface ```ts new VideoChatClient(options: ClientOptions) client.connect(): Promise // participant id assigned by the SFU client.join(roomId: string): void // must match the room baked into the token client.publish(stream: MediaStream): Promise client.subscribe(): void // create the PeerConnection before publishing (optional; publish() does it too) client.onTrack(cb: (e: TrackEventDetail) => void): void client.onPeer(cb: (e: { joined?: ParticipantInfo; left?: string }) => void): void ``` Events (`EventTarget`): | Event | Detail | When | |-------|--------|------| | `track` | `{ streams, track, participantId? }` | A remote peer's track arrives — attach `streams[0]` to a `