Raven Docs

RTC Quickstart

Install, authenticate, join a room, and publish media — the shortest real path to a working call, on every supported SDK.

What you'll build: two participants in a room, each publishing camera and microphone and seeing/hearing the other. Every step below is the real API — copy it, swap in your own token endpoint, and it runs.

Prerequisites: a Raven project and a project API key (see API Keys) — RTC tokens are minted with it, server-side, and never in a browser or app.

1. Install

Not published to npm yet. The commands below are what installation will look like once these packages are released. Until then, install from a local checkout — see Installing from source.

npm install @corvidhq/rtc

2. Authenticate

Mint a token on your backend — never construct one client-side:

import { Raven } from '@corvidhq/server';
const raven = new Raven({ apiKey: process.env.RAVEN_API_KEY });
 
app.post('/join-room', async (req, res) => {
  const room = await raven.rooms.create({ name: 'demo-room' });
  const token = await raven.tokens.create({
    room: room.id,
    identity: req.user.id,
    permissions: { join: true, publish: true, subscribe: true },
  });
  res.json(token); // { token, endpoint, iceServers, ... }
});

See Authentication for what each permission controls.

3. Create a client and join

import { createRTCClient } from '@corvidhq/rtc';
 
const resp = await fetch('/join-room', { method: 'POST' }).then((r) => r.json());
 
const client = createRTCClient({
  token: resp.token,
  endpoint: resp.endpoint,
  iceServers: resp.iceServers,
});
 
const room = await client.join('demo-room');

4. Enable microphone and camera

await room.enableCamera();      // captures and publishes in one call
await room.enableMicrophone();

Publishing happens automatically once a device is enabled — there's no separate publish() call to remember, on any platform.

5. Receive a participant

Anyone already in the room arrives synchronously; anyone who joins after you fires an event.

for (const participant of room.remoteParticipants) {
  for (const track of participant.tracks) {
    videoElement.appendChild(track.attach());
  }
}
 
room.on('trackSubscribed', (track, participant) => {
  videoElement.appendChild(track.attach());
});

6. Leave

await room.leave();

What Raven handles vs. what you handle

Raven handles: signaling, media routing through the SFU, ICE/TURN negotiation, reconnection with backoff, and firing participant/track events as the room's state actually changes.

You handle: minting tokens from your own authenticated backend session, the UI around connection/error states, and requesting device permission (automatic on React Native/Flutter, browser-native on web).

Common errors

ErrorWhyFix
ROOM_NOT_FOUNDroomId passed to join() doesn't match what the token was minted for.Pass the same room id/name your backend used in tokens.create({ room }).
TOKEN_EXPIREDTokens are short-lived by default.Mint a fresh one — there's no way to extend an existing token's lifetime.
CAMERA_PERMISSION_DENIED / MICROPHONE_PERMISSION_DENIEDOS or browser denied device access.See Permissions.

See Troubleshooting for connection failures that aren't a thrown error (e.g. "works on Wi-Fi, fails on cellular").

Production notes

  • Never call raven.tokens.create() (or any @corvidhq/server/raven-sdk method) from a browser or app — it needs your project API key, which must never leave your backend.
  • Derive identity from your own authenticated session, never from a value the client sent — anyone could ask to join as anyone else.
  • Forward iceServers from the token response as-is. Hand-constructing your own is the most common cause of calls that work on Wi-Fi but fail on cellular or a corporate network.
  • RTC → Overview — the room/participant/track model behind this.
  • Rooms & Participants — device selection, data messages.
  • Audio & Video — the create-then-publish pattern, muting.
  • Need messaging alongside the call? See Chat — the two planes are independent.

API reference

createRTCClient / Raven / RavenRoom, Room, Participant, Track — full method and event tables in RTC → Overview.