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
OfflineDemo mode — dial anything (it "answers" in a couple seconds), or stage an incoming call.
Installation
npx shadcn@latest add @handset/softphoneInstalls 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
| Prop | Type | Default | Description |
|---|---|---|---|
| softphone | Softphone | — | From createSoftphone (or createDemoSoftphone in tests/demos). |
| callerNumber | string | — | Caller ID for outbound calls — one of the tenant's Handset numbers. |
| className | string | — | Merged onto the panel. |