Softphone

A phone that lives inside your product: connection status, dialer, in-call controls, and inbound ringing in one panel. Calls to your Handset numbers ring here.

Phone

Offline

Demo mode — dial anything (it "answers" in a couple seconds), or stage an incoming call.

Installation

npx shadcn@latest add @handset/softphone

Installs dialer, call-hud, and incoming-call-toast, plus the @handset/webrtc package.

Usage

import { createSoftphone } from "@handset/webrtc";
import { SoftphonePanel } from "@/components/handset/softphone";

// Once, at module scope (or useMemo). getToken calls YOUR backend,
// which mints it via POST /v1/web_clients/{id}/tokens.
const softphone = createSoftphone({
  getToken: async () => {
    const res = await fetch(`/api/handset/web_clients/${seatId}/tokens`, { method: "POST" });
    const { token } = await res.json();
    return token;
  },
});

<SoftphonePanel softphone={softphone} callerNumber={tenant.number} />

The setup story lives in Softphone setup: one web client per agent seat, tokens minted server-side, and inbound routing that includes client:wc_… as a ring target so calls to the tenant's number ring the browser.

Props

Props
PropTypeDefaultDescription
softphoneSoftphoneFrom createSoftphone (or createDemoSoftphone in tests/demos).
callerNumberstringCaller ID for outbound calls — one of the tenant's Handset numbers.
classNamestringMerged onto the panel.