Video
Orbit’s video channel gives you live, in-browser video rooms that run over WebRTC on Orbit Media (Devotel’s hosted SFU). Rooms need nothing installed — a guest joins from a link in any modern browser — and they live on the same account as your SMS, voice, WhatsApp, and email, so a video session lands in the shared inbox alongside the rest of the conversation. This page is the concept-and-reference surface: room kinds, join tokens, the embed, recording, moderation, and broadcast. For the full endpoint parameter and response contract see the Video API reference; for the ordered walkthroughs see Video meetings and conferences, Video room access tokens, and the embedded video consultation button.When video is the right channel
Reach for video when the conversation needs eye contact or a screen, not as a default channel. Three patterns it fits well:- 1:1 agent escalation — a chat or SMS thread hands off to a face-to-face session from the shared inbox, so the agent shares a screen or reads the customer’s demeanor without the customer installing an app.
- Telehealth and professional consultations — scheduled rooms with a waiting-room lobby, recording consent at join, and per-participant grants (host / panelist / viewer).
- In-app support — the embedded
orbit-video-roomelement or the JS widget inside your own product, so a customer starts a call without leaving your page.
Webhooks and event ordering
Every room emits granular lifecycle events, so the ordering below is a guarantee you can build on. For a room created withrecording_enabled: true, webhooks arrive in this sequence:
video.room.startedvideo.participant.joined(one per join)video.participant.left(one per leave)video.room.endedvideo.recording.completed(orvideo.recording.failed)
end_reason: failed_no_connect on video.room.ended. The end_reason field distinguishes last_participant_left, operator_end, timeout, room_finished, and error. Full payload shapes live in the webhook event reference; register receivers per the webhooks overview.
Web SDK: join, publish, and leave
The web SDK’sOrbitVideoRoom joins a room with a container element and the server-minted token — remote tracks attach to the right participant tile as they are subscribed, and the control bar covers mute, camera, screen-share, the device picker, and leave:
start-with-camera / start-with-microphone are set, or when the participant toggles them in the control bar — subject to the grant your join token carries (can_publish). Receiving is automatic: remote tracks attach to their participant tile as they arrive. For the lower-level media client (direct track control beyond the prebuilt widget) see the Web SDK reference; the access tokens guide covers the grant tiers.
Two kinds of rooms
Scheduled rooms are the first-class surface: they carry a host, an optional schedule and recurrence rule, a capacity, recording, guest invite links, and an inbox entry. Ad-hoc rooms are the lighter primitive for one-off “start a call now” flows.
Create and schedule from the API
A scheduled room with a calendar slot, recurrence, recording, and a named host — the same create call in four languages:scheduled_at unset to start now, pass an RFC 5545 recurrence_rule for a repeating series, and omit max_participants to inherit your tenant’s participant ceiling.
The 201 create returns the room handle (room_id) under the data envelope alongside the minted host token — the egress ids and storage descriptor are non-null only when recording started at create. The room itself carries a status ("scheduled" → "live" → "ended") and an expires_at you can read back from the room record; the token above is the response’s terminal shape — a room id plus the handle usable immediately.
An ad-hoc room uses the same body on the shorter endpoint — for a click-to-start call inside your product where a persisted schedule record would be noise:
201
Limits
Video plans are tenant-level, and every control below is set by the tenant on its own account:GET /api/v1/video/rooms-scheduled/limits returns your resolved participant cap, the platform defaults, and whether an override is in effect — read it before rendering your own create-room form.
Join tokens: the browser never sees your API key
Joining a room is a two-step wire. Your back end mints a bounded, per-participant join token:{ data, meta } envelope so a consumer never has to decode the JWT:
Tokens are per-participant: identity, display name, and grant bind at mint time. Re-issuing is a fresh
POST every time — mint a new token when expires_at approaches (the default lifetime is 1 hour, override with ttl_seconds in the body) and replace the token in your client before the SFU rejects it. Identity binding is restrictive by design: a token under another user’s identity requires the owner or admin role plus a non-empty impersonation_reason, so guests and teammates cannot mint-as-others from an ordinary API key.
Embed a room with the web SDK
The Orbit web SDK (@devotel-orbit/web) registers a prebuilt orbit-video-room element. All of these attributes are optional except token and server-url:
The camera, microphone, screen-share, and device-selection toggles ship with the widget, so an embedded room is a snippet rather than a UI build:
orbit-state, orbit-participant-joined, orbit-participant-left, and orbit-error. For the full embed walkthrough see the embedded video consultation button guide.
Recording and playback
Drive recording from the API —/api/v1/video/rooms-scheduled/:id/recording/start, /stop, and /pause — or set recording_enabled: true on create so recording starts automatically when the first participant joins. Completed recordings arrive as composite MP4s and land back on the room, and the returned recording_url is a short-lived signed URL (fetch the room again when it expires) with recording_url_expires_at alongside so you can warn a viewer before the link lapses. Completion (or failure) is delivered as video.recording.completed / video.recording.failed; handle both. To store recordings in your own bucket instead of Orbit storage, see video recording BYO storage.
Per-participant recording consent is respected at join time (allow_recording in the join body) and can be changed mid-room by a host via /api/v1/video/rooms-scheduled/:id/participants/:identity/recording-consent; a decliner’s media is excluded from the composite and track egress.
Waiting room: the lobby
Arm the lobby withPOST /api/v1/video/rooms-scheduled/:id/waiting-room ({ enabled: true }, optionally auto_promote: true). While the lobby is armed, new non-host joins receive receive-only tokens — the join response reports lobby_downgraded: true and permissions.can_subscribe: false, so your client can show a “waiting for the host to admit you” state instead of broken controls. A host (owner, admin, or developer role) admits a pending participant with POST /api/v1/video/rooms-scheduled/:id/waiting-room/admit/:identity; admission promotes them to the full panelist grant without a new token. With auto_promote: true the hold still applies to the join but the first host to enter lifts everyone automatically — use it for open-office-hours style rooms.
Moderation and broadcast
Hosts moderate from the dashboard or the API: spotlight a speaker, mute or remove a participant, lock the room so no new joins land (/lock), run the waiting-room lobby above, and clear the deck with mute-all.
For a larger audience, push the room to a streaming destination with RTMP egress. POST /api/v1/video/rooms-scheduled/:id/egress/rtmp takes:
{ egress_id, rtmp_url, additional_rtmp_urls }) so your UI can display destinations without holding secrets. Keep the egress_id as the handle for DELETE /:id/egress/rtmp/:egressId, which stops the whole fan-out. Additional destinations fan out from a single composite render, so simulcast to YouTube plus Twitch costs one render. Stream keys are never persisted — only the URL and handle land in room settings.
To run a room audio-only, set audio_only: true at create: every publisher’s grant is clamped to microphone at token mint, and camera plus screen-share come back for a given participant only once the transcript-verified video-only gate has proof of genuine speech — it widens the two video sources onto an already-publishing grant and can never convert a subscriber into a publisher. The full grant semantics live in Transcript-verified video-only gate.
You can also bridge the room to the phone network with dial-in for guests and dial-out to bring a PSTN participant in.
Common failure modes
Run through the full checklist, including token handling and lobby downgrade, in Video room lifecycle troubleshooting; for chat, polls, and RTMP-specific failures see Video features: chat, polls, Q&A, invites, RTMP.
Errors
The feature-level codes — chat, polls, Q&A, invites, moderation, hands,
spotlight, whiteboard, RTMP egress, and the SSO-policy gate — have their
own runbook: Video room features: chat, polls, Q&A, invites, RTMP.
Room-config templates
Save a room’s configuration as a reusable template under/rooms-scheduled/templates and create later rooms from it with the same behavior as a direct create — the fixed onboarding-call or weekly-sync setup stops being a copy-paste of settings.