TVH Voice docs

#Browser softphone (@voice/softphone)

A small wrapper around SIP.js for WebRTC calling in your CRM. Use it from your frontend; it never sees your API key — it gets short-lived credentials from your backend.

import { Softphone } from '@voice/softphone';

const phone = new Softphone({
  // Your backend calls POST /v1/agents/{agent_ref}/softphone-config and returns the JSON.
  getConfig: () => fetch('/crm/softphone-config').then((r) => r.json()),
  autoAnswer: false,
});

phone.on('registered', () => setStatus('online'));
phone.on('incoming', (call) => {
  // Click-to-call: the agent leg carries the platform call id (X-Call-Id).
  if (call.platformCallId === pendingClickToCallId) void phone.answer(call.id);
  else showIncomingUi(call); // from: call.remote
});
phone.on('call', (call) => render(call)); // state: ringing | connecting | active | held | ended
phone.on('error', (e) => console.error(e));

await phone.start(); // connects over WSS and registers; renews credentials before they expire
Method Does
start() / stop() Register / unregister and disconnect
call(target, { headers }) Call an agent (agent_ref) or a number (+31…). Choose the caller ID with header X-Caller-Id: +31… (must be one of your numbers; otherwise the workspace default is used)
answer(id?), hangup(id?) Answer / end
hold(id?), unhold(id?) SIP hold
mute(id?), unmute(id?) Microphone
sendDtmf('123#', id?) RFC 4733 DTMF
transfer(target, id?) Blind transfer (SIP REFER)
attendedTransfer(id, consultId) Connect two calls
calls Current calls

Requirements: HTTPS page (microphone permission), the browser must reach the SIP WSS URL (TCP 7443) and the TURN server (UDP/TCP 3478). A plain <script> build is published as dist/softphone.global.js (global VoiceSoftphone); /demo/softphone on the API is a working example.