> ## Documentation Index
> Fetch the complete documentation index at: https://docs.orbit.devotel.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Transport architecture

> How Orbit moves real-time audio and video: the Orbit Media SFU for WebRTC and the Jambonz SBC + RTPengine for PSTN/SIP carrier legs

# Transport architecture

Orbit's real-time media rides two planes, split by **where the media
originates**, not by a per-call flag you set:

* **Orbit Media (SFU)** carries WebRTC media — video rooms and the
  browser softphone.
* **Jambonz SBC + RTPengine** carries PSTN/SIP carrier media — inbound
  DIDs and outbound calls.

A single call can span both planes (a browser softphone dialling a PSTN
number rides Orbit Media for the browser leg and is bridged through
Jambonz to the carrier). There is **no** `transport` request field and
**no** per-call SFU-vs-bridge decision the API makes on your behalf —
the plane follows directly from the endpoint and the leg type.

## TL;DR

| What you're doing                                          | Plane                                        | Why                                                                       |
| ---------------------------------------------------------- | -------------------------------------------- | ------------------------------------------------------------------------- |
| Any video room (`/api/v1/video/rooms`, `/rooms-scheduled`) | **Orbit Media (SFU)**                        | Simulcast, per-subscriber bitrate, server-side recording (egress)         |
| Browser softphone session                                  | **Orbit Media (SFU)** or **SIP/WSS gateway** | Depends on the client — see [Browser softphone](#browser-softphone) below |
| Inbound PSTN/SIP call (Telnyx / DIDWW DID)                 | **Jambonz SBC + RTPengine**                  | Carrier SIP terminates on the SBC; RTPengine bridges media                |
| Outbound (MT) voice call (`POST /api/v1/voice/calls`)      | **Jambonz SBC → Devotel softswitch**         | Outbound termination exits **only** via the Devotel wholesale softswitch  |

## Orbit Media (the SFU)

Orbit Media is Orbit's Selective Forwarding Unit. It is forked from
[LiveKit OSS](https://github.com/livekit/livekit) under Apache-2 — see
[Attribution](/legal/attribution). It handles everything that needs
server-side fan-out or mixing of WebRTC media: simulcast, per-subscriber
bitrate adaptation, codec negotiation, DTLS/SRTP, and server-side
recording via egress.

Clients never talk to the SFU with a long-lived key. The API mints a
short-lived join token scoped to a single room:

* **Video** — `POST /api/v1/video/rooms` and
  `/api/v1/video/rooms-scheduled` create a room and mint a participant
  token against Orbit Media. There is no non-SFU mode for video.
* **Voice (browser softphone)** — `POST /api/v1/voice/softphone/token`
  mints an Orbit Media token for a deterministic per-user room
  (`softphone:<tenant>:<user>`), so reconnects are idempotent. See
  [Softphone token](/api-reference/voice#softphone-token).

Recording for SFU sessions is produced by Orbit Media's egress pipeline.

## Jambonz SBC + RTPengine (carrier legs)

PSTN and SIP carrier media never touches the SFU. It terminates on the
Jambonz session border controller, with RTPengine bridging RTP/SRTP
between the carrier and Orbit:

* **Inbound** — Telnyx and DIDWW DIDs route through Jambonz, which
  applies the tenant's number-handler routing.
* **Outbound (MT)** — `POST /api/v1/voice/calls` initiates a call
  through Jambonz, which terminates it on the **Devotel wholesale
  softswitch**. Outbound voice exits only via Devotel — Orbit never
  wires a carrier's call-control API for outbound termination.

In-call voice recording on this plane is **SIPREC** (`POST
/api/v1/voice/calls/:id/recording/start`), not SFU egress.

## Browser softphone

The browser softphone has two client transports, chosen by the SDK in
use — not by a request flag:

* **Orbit Media (WebRTC)** — the dashboard softphone calls
  `POST /api/v1/voice/softphone/token` and joins an Orbit Media room.
* **SIP over WSS** — the `@devotel/orbit-web-sdk` `Softphone` calls
  `POST /api/v1/voice/softphone/register` to obtain a short-lived SIP
  credential and `REGISTER`s against Orbit's WebRTC-to-SIP gateway over
  a secure WebSocket. The SIP password itself is HMAC-derived and never
  stored, but issuance and revocation metadata (issue/expiry times, the
  owning org, and a revoked flag) *is* persisted server-side so a tenant
  can revoke a credential before it expires. Call `DELETE
  /api/v1/voice/softphone/credentials/:username` to revoke one — the
  gateway rejects the HMAC on its next validation even while it's still
  within its lifetime.

Either way the carrier leg, when one exists, is bridged through Jambonz
as described above.

## What the API does *not* expose

To keep this page honest against the code, a few things that earlier
drafts implied but the API does **not** do:

* There is no `transport` field on the `POST /api/v1/voice/calls` body
  and no `INVALID_TRANSPORT` error code. The plane is implied by the
  endpoint and leg type.
* There is no client-facing "decision tree" service that ranks SFU vs.
  WebSocket bridge per call, and no per-call latency-budget selection.

## Cross-references

* [Voice API → Softphone token](/api-reference/voice#softphone-token) —
  how a softphone token is minted for browser clients.
* [Video API](/api-reference/video) — every endpoint mints Orbit Media
  (SFU) tokens.
* [Voice quickstart](/voice/quickstart) — end-to-end walk-through of a
  voice call.
* [Attribution](/legal/attribution) — Orbit Media is forked from LiveKit
  OSS under Apache-2.
