Skip to main content

Set up the browser (WebRTC) softphone

The browser softphone lets an agent place and answer PSTN calls without leaving the browser — no desk phone, no desktop SIP app. There are three ways to put it in front of an agent, and they share the same credential and infrastructure underneath:
  1. The built-in dashboard softphone — Orbit ships a ready-made softphone inside the dashboard. This is the zero-code path and the right starting point for most teams.
  2. An embedded LiveKit-based softphone (Softphone in @devotel/orbit-web-sdk) — you mount the softphone inside your own agent workspace (CRM, contact-centre wall, internal tool) with your own UI.
  3. An embedded SIP-over-WSS softphone (the SIP-register path) — a classic SIP client (e.g. JsSIP) that registers straight against Orbit’s WebRTC-to-SIP gateway, for teams that want standard SIP semantics and their own call-control logic.
This guide walks through setup in the order you’ll actually do it: register devices, mint credentials, choose how inbound calls find the softphone, wire a client, then verify.
The browser softphone only needs a browser with a microphone. Inbound push notifications (section 1) are a mobile companion for when agents move to the Orbit mobile app — they are not required for the browser itself.

1. Device registration & VoIP push tokens (mobile)

Skip this section if your agents work only in the browser. Register a VoIP device only when the agent also needs inbound calls to ring their phone as a native call — i.e. the Orbit mobile app, backgrounded or locked, still rings like a phone call instead of showing a passive banner. Registering a VoIP device is a single API call:
  • platform is ios or android. On iOS voip_token is the PushKit (CallKit) token; on Android it’s the FCM registration token used for the high-priority call channel.
  • bundle_id (iOS only) is the app bundle id — the VoIP push topic is <bundle_id>.voip.
  • The response returns the registered device (id, platform, last_seen_at).
Manage the fleet with GET /push/voip-devices (list) and DELETE /push/voip-devices/:id (unregister a device). You normally don’t call these by hand — the mobile SDK registers, refreshes, and removes its own row. A permanently-dead token (the OS revoked it, or the app was uninstalled) is marked revoked automatically and skipped on the next inbound ring, so a stale device never blocks the queue’s ring cycle.
A VoIP token is not the same as a regular push token. iOS revokes the VoIP entitlement from apps that reuse it for marketing or alert pushes, so the two token types are kept strictly separate. Never send a non-call push to a voip_token.

2. Mint softphone credentials

An agent browser needs a short-lived credential before it can connect. Which endpoint you mint against depends on the client you’ve chosen — dashboard, embedded LiveKit, or embedded SIP.

Built-in dashboard / embedded LiveKit softphone

The softphone’s first move is a token request. POST /voice/softphone/token returns a short-lived LiveKit access token plus the media URL to connect to:
Response (abridged):
The token is scoped to a per-user room so two agents never share a session. Placing a call after connecting is POST /voice/softphone/dial with { "to": "+15550123", "from": "+15559876" } — see the full snippet in section 4.

Embedded SIP/WSS softphone

A SIP client registers directly over a WebSocket. POST /voice/softphone/register swaps your authenticated API request for a short-lived SIP credential:
Response (abridged):
Key properties to design around:
  • Credentials live for 60 minutes — re-register before expiresAt or the session drops.
  • callerIdNumber must be a number your organization owns (it’s 403’d otherwise) — this is how outbound CLI spoofing is blocked.
  • The username binds to your organization, so a stolen username can’t be replayed against a different tenant.
  • Token issuance is owner/admin/developer-scoped — it’s not a public, anonymous endpoint.
Revoke a credential immediately with DELETE /voice/softphone/credentials/:username if an agent leaves or a token leaks. Revocation is owner-only so a leaked credential stays a small-blast-radius event.

3. Choose how inbound calls reach the softphone

Inbound calls must be routed so they land on an agent’s browser. You have three tenant-owned options — use the one that matches how your phone numbers are set up.
  • DNIS → queue → softphone. The most common path: your phone number’s inbound routing sends the call to an ACD queue, and the queue offers it to an available agent’s browser softphone (and, if they’re on the mobile app, a VoIP push — section 1). You set this up per number in the dashboard’s number routing, or through the flows builder.
  • DNIS → SIP routing. Route inbound calls to the SIP domain your softphone registrations live on. Use this when your inbound traffic already lands on SIP (for example a DID forwarded to your SIP URI) and you want the registered softphone to answer directly.
  • The caller’s softphone dials out. For outbound-driven teams the inbound question never arises — the agent initiates calls and any inbound answer is on a number that routes to a queue (back to option one).
Whatever you choose, the softphone’s own credential never changes — sections 1, 2, and 4 are identical under any inbound topology. Inbound routing is a property of the number, not the softphone.

4. Full JS snippet — mic, VoIP push + browser fallback

Here is a complete, copy-pasteable browser softphone. It works with both embedded options (LiveKit and SIP-over-WSS) and handles the browser-fallback reality: some agents will be on browsers or networks where the primary media path is unavailable, so you always wire a fallback.
WebRTC needs a getUserMedia grant and an HTTPS page. A softphone that “does nothing” is almost always one of: an HTTP (non-secure) page, a denied mic prompt, or a corporate network blocking UDP 3478.

5. Verification & troubleshooting

Verify the setup end to end:
  1. Mint a credential (section 2), connect the client (section 4), and look for a room connect / SIP registered event.
  2. Place an outbound call to your own mobile — you should hear ring, then two-way audio on answer.
  3. Have an inbound call routed to your number (section 3) and confirm the softphone rings and answers.
  4. If you registered a mobile VoIP device (section 1), background the mobile app and confirm a native incoming-call UI appears.
Troubleshooting rules, in the order you’ll hit them: Also confirm you aren’t reusing the wrong endpoint: register (SIP/WSS) ↔ SIP clients, token ↔ LiveKit clients, voip-devices ↔ mobile push only.

Where to go next

  • SIP trunk setup — if you want to bring your own carrier/trunk alongside the browser softphone.
  • Voice queues — the ACD queue inbound calls route through before a softphone answers.
  • Web SDK — full event map for Softphone and the other SDK surfaces.