VideoRayan exposes a small, predictable REST control plane and speaks standard WebRTC through any LiveKit-compatible SDK. Create rooms, mint short-lived guest tokens, and connect — no vendor SDK lock-in, no opaque cloud between you and your users.
The free tier needs no account and no API key — a room name is the credential. Everything below runs against the production API.
POST /v1/public/rooms with a name. Get back a roomId you can share or embed.
POST /v1/guest/rooms/{ref}/tokens with a display identity. Receive a short-lived LiveKit JWT.
Hand the token to livekit-client, React Components, Flutter, or open the hosted UI at /r/{roomId}.
# 1 — create a room (no key needed; same name returns the same room) curl -s -X POST https://api.videorayan.ir/v1/public/rooms \ -H "Content-Type: application/json" \ -d '{"name":"standup-2026"}' # → { "roomId": "3f9c…", "name": "standup-2026" } # 2 — mint a guest token curl -s -X POST https://api.videorayan.ir/v1/guest/rooms/standup-2026/tokens \ -H "Content-Type: application/json" \ -d '{"identity":"sara"}' # → { "token": "eyJ…", "identity": "sara", "roomName": "standup-2026", "expiresAt": "…" }
// 1 — create a room (no key needed) const room = await fetch('https://api.videorayan.ir/v1/public/rooms', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ name: 'standup-2026' }) }).then(r => r.json()); // → { roomId, name } // 2 — mint a guest token (ref = roomId or the room name) const { token } = await fetch(`https://api.videorayan.ir/v1/guest/rooms/${room.roomId}/tokens`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ identity: 'sara' }) }).then(r => r.json()); // 3 — connect with livekit-client import { Room } from 'livekit-client'; const live = new Room(); await live.connect('wss://rtc.videorayan.ir', token);
import requests BASE = "https://api.videorayan.ir/v1" # 1 — create a room (no key needed) room = requests.post(f"{BASE}/public/rooms", json={"name": "standup-2026"}).json() # → {"roomId": "...", "name": "standup-2026"} # 2 — mint a guest token (ref = roomId or the room name) tok = requests.post(f"{BASE}/guest/rooms/{room['roomId']}/tokens", json={"identity": "sara"}).json() # → {"token": "eyJ…", "identity": "sara", "roomName": "...", "expiresAt": "…"} # 3 — connect from any LiveKit SDK with tok["token"] on wss://rtc.videorayan.ir
Both surfaces run on the same self-hosted media plane — you can start free and upgrade rooms to tenant-owned without changing your client code.
The fastest path: create rooms from the browser or any HTTP client, join with a link, password-protect when needed. Perfect for MVPs, internal tools, and hosted meeting links.
POST /v1/public/rooms — create (name is the handle)GET /v1/public/rooms/{ref} — resolve + password probePOST /v1/guest/rooms/{ref}/tokens — join tokenen.videorayan.ir/r/{roomId}For products that own their rooms: tenant-scoped rooms with externalId correlation, host/guest roles, server-side participant caps, participant inspection, and lifecycle control.
POST /v1/rooms — create with idempotency keyPOST /v1/rooms/{id}/tokens — host or guest, TTL up to 1hGET /v1/rooms/{id}/participants — live rosterDELETE /v1/rooms/{id} — end room, cut everyoneBecause the media plane is a standard LiveKit SFU, every first-party LiveKit SDK works with your token — no custom SDK to wait for.
| Platform | SDK | Install | Connect |
|---|---|---|---|
| Web / SPA | livekit-client | npm i livekit-client | room.connect('wss://rtc.videorayan.ir', token) |
| React | @livekit/components-react | npm i @livekit/components-react livekit-client | <LiveKitRoom token={token} serverUrl={wsUrl} /> |
| iOS | LiveKitSDK (Swift) | .package(url: "livekit/swift-sdk") | try await room.connect(url: wsUrl, token: token) |
| Android | livekit-android | implementation "io.livekit:livekit-android" | room.connect(wsUrl, token) |
| Flutter | livekit_client | flutter pub add livekit_client | room.connect(wsUrl, token) |
| Server agents | livekit-server-sdk / REST | pip install livekit-api | mint tokens server-side, connect headlessly |
Everything below is running in production today on the self-hosted stack.
Opus audio with echo cancellation and noise suppression, VP8/VP9 video via an SFU with dynacast — no mesh scaling problems.
Display-tab or window share from the browser, active-speaker switching, and click-to-pin stages in the hosted UI.
Ephemeral, room-scoped messaging with chunked file hand-off up to 10 MB over WebRTC data channels — nothing stored server-side.
Expiry sweeps every 60 s, empty-room timeouts, idempotent creation, and a live contract at /v1/openapi.yaml.
Every join is a signed, single-room JWT with minimal grants. Private rooms add a server-enforced password. Cross-tenant probes return 404.
Security-relevant actions land in an audit log; secrets are never returned by the API. Hardened SSH, automated backups, restore drills.
Concepts, step-by-step guides for the browser flow and the tenant backend flow, security notes, and troubleshooting for every error code.
Every endpoint with parameters, responses, status codes, and copy-paste cURL / JavaScript / Python examples. OpenAPI spec included.
Agent-friendly resources: llms.txt, a full machine-readable API contract, and pure-REST workflows your agent can run today.
Live spec served by the control API itself (OpenAPI 3.0). Import into Postman, Insomnia, or generate a client.
Create a free room, open the invite link, and inspect the traffic — then wire the same flow into your product.
A free community room for open discussion (voice, video and text chat, no account) and a feedback channel the operator actually reads.