curl you can paste into a terminal, with the equivalent dashboard click-path alongside.
By the end you will have hosted a two-person recorded meeting and know which deep guide to read for each capability you saw.
Here is the loop:
- Create a recorded room with one
curl— or the equivalent dashboard clicks - Issue a guest invite, delivered by email or shared as a link
- Mint a join token from your backend and join as the host
- End the meeting and find the recording
- Follow the deep guide for each capability you just saw
Before you start
- An Orbit account with video enabled on your plan, and an API key (
dv_live_sk_…for production,dv_test_sk_…for test mode). Create keys under Settings → API keys. - A basic grasp of how you authenticate: every call below sends your key in the
X-API-Keyheader. - If you want to experiment without touching live data, run these same calls in test mode first — see Sandbox test mode.
1. Create the room
A room is a scheduled meeting: a name, an optional start time, and a recording policy. This call turns recording on so step 4 has an artifact to find:id — the invite and join calls take it as :id in the path.
recording_format picks the artifact shape: composite renders one MP4 with every track mixed (the right default for a first meeting), tracks writes per-participant tracks for analysis or QA review, and both produces both families. When omitted, your organization’s default applies.
In the dashboard: open Voice → Video, click Schedule (or Create room for an ad-hoc meeting), set the name and flip recording on. The room appears in the list with its id and join link — the same row this API call returns.
Omit scheduled_at and the room is available immediately; pass an ISO timestamp (e.g. "2026-10-14T15:00:00Z") to hold it for a future slot.
Two people is the floor, not the default size: max_participants caps the room from 2 up to 300 seats (bounded by your plan), and omitting it inherits your plan’s ceiling. For a series rather than a one-off, pass recurrence_rule as an RFC 5545 RRULE body (e.g. FREQ=WEEKLY;BYDAY=MO;COUNT=10) and the invite emails carry calendar attachments for the whole series. Capacity, recurrence, and reminder settings are covered in Video meetings.
If a field fails validation the API answers 422 with a VALIDATION_ERROR code and the offending field in the details block — match the field name against the body above and re-send. A 401 means the X-API-Key header is missing or the key was revoked; a 403 means the key’s role does not cover video writes.
Read the room back any time to confirm its current status, recording policy, and seat cap:
GET /api/v1/video/rooms-scheduled?status=scheduled&keyword=sync searches the catalog by name — handy once the id has scrolled out of your shell history.
2. Invite a guest
Guests join through an invite: a bounded token with an expiry and a use-count, plus a ready-to-share link. Issue one and have the API email it, or hand the link over yourself:join_urlis the link your guest opens. No account, no API key — the invite is their credential.email_statustells you whether Orbit dispatched the invite email (sent,failed, ornot_requestedwhen you omitguest_email). Onfailedthe invite itself still works; hand overjoin_urlmanually.max_uses: 1makes the link single-entry; raise it for a link a guest reuses across the day, or omit it for the default.
guest_name and participant_name are accepted aliases for the same field — the name the guest’s tile shows in the room. Use one or the other; if both are present, participant_name wins.
The guest experience: opening join_url lands on a lobby page that asks for a name (pre-filled when you passed guest_name), requests camera and microphone permission, and joins as a participant. Guests see the same room controls — mute, camera, screen share, chat — without ever touching the dashboard.
Prefer to share the link yourself? Omit guest_email and copy join_url into any channel. Revoking is a one-click action on the room’s invite list in the dashboard, or the revoke endpoint — the full invite lifecycle, including listing and expiring invites, is in Video room access tokens.
Use invites for people you do not authenticate — guests, customers, candidates — and /join for users your system already knows, where your backend should own identity and role. The two coexist in one room: a panel on minted tokens plus an audience on invite links is the standard webinar layout.
For embedded apps that want the guest flow server-side, POST /api/v1/video/invites/:invite_token/redeem exchanges an invite for a join token programmatically — the same token the join_url lobby mints when the guest clicks through.
3. Get a join token and join
Your own backend joins authenticated users by minting a join token. The token carries the participant’s identity and role; the room URL is where the browser goes, the token is what authorizes the connection:tokenis a short-lived, identity-bound access token. Your server mints it; your client consumes it. Never embed an API key in browser code to work around this step. Passttl_seconds(60 to 86400) to override the token’s validity window; expiry is enforced at the SFU, so a stale token refuses the connection rather than joining silently.token_typeandlivekit_urltell a client SDK how to connect: feedtokento the LiveKit client and point it atlivekit_url. Browser joins via the room link (your dashboard room row, or thejoin_urlfrom step 2) need no token handling at all.- Requesting
role: "host"grants moderator controls (mute-all, lock, recording start/stop). Everyone else joins as"participant".
role field is the simple split — host moderates, participant doesn’t. When you need finer grain, participant_tier on the same call selects one of four permission tiers:
Minting
host or hidden_supervisor requires an owner/admin credential; a 403 on the join call means the role or tier exceeded what the caller may grant.
With both legs connected — your host session and the guest’s invite link — the meeting is live.
Roles, permission tiers, per-participant publish limits, and token TTLs are covered in depth in Video room access tokens.
4. End the meeting and find your recording
End the meeting from the room controls (host) or let the room close when everyone leaves. Because you setrecording_enabled: true at create time, Orbit’s media pipeline rendered the session while it ran; a few minutes after the room ends, the artifact is attached to the room.
In the dashboard: open Voice → Video → History, pick the room, and the recording row shows playback, download, and share actions. The share player gives you a link you can send to anyone in your organization without exporting the file.
Recordings land in Orbit-managed storage by default; the share player and download links in History point there. If your compliance posture requires recordings never to touch shared infrastructure, connect your own bucket first per Recordings to your own storage — the same API flow then delivers artifacts to your bucket instead.
While the meeting runs, the host console covers moderation in one place: mute-all, lock the room, spotlight a presenter, promote a participant to panelist, and turn on live captions. Every console action has a matching POST /api/v1/video/rooms-scheduled/$ROOM_ID/… call (/mute-all, /lock, /spotlight) for backend-driven moderation.
Two guides cover what happens next, depending on where recordings should live:
- Share recordings with the hosted player — hosted playback links, expiry, and access control.
- Recordings to your own storage — deliver the composite MP4 or per-track files into your own bucket the moment egress finishes.
recording_format: "tracks" option from step 1 — re-create the room with it and the same loop produces separable tracks.
If your backend should act the moment a recording lands (notify participants, attach the file to a CRM record), subscribe to the video.room.ended and video.recording.completed webhook events under Settings → Webhooks instead of polling — the payload shapes are in the Webhook events reference.
5. Run the whole loop as one script
Once you have walked the steps once, this script runs create → invite → join in a single paste against test mode. Two interactive steps stay human: the guest opensjoin_url in a browser, and the meeting ends when participants leave.
ended under Voice → Video → History, the recording appears on it a few minutes later, and GET /api/v1/video/rooms-scheduled/$ROOM_ID/activity returns the join/leave timeline for the session. Rooms move through scheduled → live → ended, and the same three statuses filter GET /api/v1/video/rooms-scheduled?status=… when your backend lists rooms programmatically.
6. Where to go next
You have run the full loop: room, invite, join, recording. The deep guides per capability:- Video meetings — the complete scheduled-meeting reference: recurrence, reminders, co-hosting, and the meetings console.
- Persistent rooms — always-on rooms with a stable URL for office hours and standing meetings.
- Webinars — panelist/audience splits at higher seat counts, with a registration gate for sign-up flows.
- Embed a consultation button — put a one-click video call button on your website.
- Room access tokens — the full token and invite contract, including revocation and TTL policy.
- Dial-in and SIP room systems — a PSTN number and PIN for participants who join by phone.
- HLS/DASH egress — live-stream the room out for large read-only audiences; RTMP egress sends it to external platforms.