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.
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
Every below-300ms hop in a real-time session lives on exactly one of the two planes, and a call that crosses between browser and carrier spans both. Pick the endpoint for the experience you want — the plane follows: video rooms always ride the SFU, PSTN legs always ride Jambonz, and the softphone is the one surface where your SDK picks between the SFU and a SIP-over-WSS gateway. The scenario-by-scenario picking table lives in Media planes; this page covers the deeper architecture of both planes.Media paths per scenario
The diagram differs per entry point. Orbit never re-splits a leg once it lands on a plane — the only hybrid is the softphone-to-PSTN bridge. Browser softphone → PSTN (spans both planes):Orbit Media (the SFU)
Orbit Media is Orbit’s Selective Forwarding Unit. 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/roomsand/api/v1/video/rooms-scheduledcreate 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/tokenmints an Orbit Media token for a deterministic per-user room (softphone:<tenant>:<user>), so reconnects are idempotent. See Softphone token.
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/callsinitiates 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.
POST /api/v1/voice/calls/:id/recording/start), not SFU egress.
Leg bridging & the token model
“Bridging” here is concrete, not architectural hand-waving: Jambonz is the SIP endpoint that joins two otherwise disjoint media domains.- The SFU side — the browser client holds a short-lived join token and publishes/subscribes audio in its Orbit Media room via DTLS/SRTP.
- The bridge — Jambonz attaches to that room as a participant, converts the room’s WebRTC audio into a SIP leg, and maintains both the SFU-room membership and the carrier-side SIP dialog while the call is up.
- The carrier side — RTPengine relays the resulting RTP/SRTP between Jambonz and the Devotel wholesale softswitch.
- SFU path —
POST /api/v1/voice/softphone/tokenreturns a short-lived room-scoped join token for the deterministic roomsoftphone:<tenant>:<user>. Because the room name is derived from the tenant + user and the token endpoint pre-creates the room (idempotently, tolerating “room already exists”), a token refresh or a client reconnect rejoins the same room the Jambonz bridge is already anchored to. There is nothing to revoke: a token is a bearer credential that expires on its own. - SIP-over-WSS path —
POST /api/v1/voice/softphone/registerissues a short-lived SIP credential (HMAC-derived password, never stored server-side) whose issuance metadata is persisted, so a tenant can revoke it ahead of expiry viaDELETE /api/v1/voice/softphone/credentials/:username. The gateway rejects the credential on its next validation even while inside its nominal lifetime. This is the one transport where revocation matters — the credential is a SIPREGISTERticket, not a one-shot join token.
Recording planes
Recording follows the plane the media rides — the two mechanisms are independent and never mix on the same leg:
Voice recording has mid-call controls beyond start/stop — pause/resume
keeps a single SIPREC session open and stamps the excluded window into
call metadata, which is the CCaaS PCI/HIPAA pattern (exclude a card
window without splitting the recording into files). A softphone call
that crosses onto the carrier plane records on the carrier plane: SIPREC
captures the bridged carrier leg, not the SFU room.
Failure & edge behavior
The transport architecture assumes clients disconnect, tokens expire mid-session, and uploads fail — the surfaces above are designed to degrade instead of corrupt:- Reconnects are idempotent by name. The softphone room is
softphone:<tenant>:<user>— a reconnect rejoins the same room, and re-POSTing/softphone/tokenre-creates it if it was GC’d. The carrier-side bridge re-anchors to the same room name on reconnect, so a leg doesn’t fork into a duplicate. - Tokens expire; SIP credentials are revocable. SFU join tokens are short-lived and not revocable (they simply age out); SIP-over-WSS credentials can be revoked before expiry. Pick the transport whose failure mode you prefer — immediate expiry vs. explicitly revocable.
- Recording upload failure doesn’t lose the recording. The recorder retries with backoff, marks a failed upload for operator triage rather than dropping it, and the API’s SIPREC callback is idempotent on retry — a duplicate completion for the same call updates the same recording record instead of creating a second one.
- Mid-call media controls are leg-scoped.
recording/start,dtmf,hold/unhold, warm-transfer etc. all operate on the active call leg via Jambonz mid-call updates — they affect the carrier-side dialog, not the SFU room membership.
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
transportfield on thePOST /api/v1/voice/callsbody and noINVALID_TRANSPORTerror 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.
- There is no API-controlled codec list, DTX toggle, or per-call RTP profile — codec negotiation is internal to each plane’s signaling and isn’t a request parameter.
- There is no cross-region failover tunable per call — a room lives in one media region end to end (see Multi-region media routing), and the carrier plane doesn’t expose a route-choice request field.
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/tokenand joins an Orbit Media room. - SIP over WSS — the
@devotel-orbit/webSoftphonecallsPOST /api/v1/voice/softphone/registerto obtain a short-lived SIP credential andREGISTERs 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. CallDELETE /api/v1/voice/softphone/credentials/:usernameto revoke one — the gateway rejects the HMAC on its next validation even while it’s still within its lifetime.
Cross-references
- Media planes — which plane picks you, per scenario, with an end-to-end browser-to-PSTN trace.
- Multi-region media routing — how a media region is picked at room creation and why a room never moves regions.
- Voice API → Softphone token — how a softphone token is minted for browser clients.
- Video API — every endpoint mints Orbit Media (SFU) tokens.
- Voice quickstart — end-to-end walk-through of a voice call.
- Attribution — Orbit Media’s open-source license notices.