Recipes← all recipesView on GitHub

Call from a browser

VoiceWebRTC browser calling

Place a call from a web page into the same flow a phone reaches.

call-fabrictokens

The claim

WebRTC calling needs two things a static page cannot hold: a credential and a destination. A small server mints a Subscriber Access Token for the signed-in user (POST /api/fabric/subscribers/tokens). The Browser SDK v4 connects with that token and dials a phone number, or a Fabric address such as /public/support. A Fabric address can land on a SWML script, an AI agent or another subscriber. The project API token never leaves the server.

How it works

Server (python/app.py):

client.fabric.tokens.create_subscriber_token(reference=user_id, display_name="Dana")   # -> {"token": ..., "refresh_token": ...}

Browser (typescript/index.ts):

const { token, destination } = await (await fetch("/token", { method: "POST", ... })).json();
const client = new SignalWire(new StaticCredentialProvider({ token }));
await client.connect();
const call = await client.dial(destination, { audio: true, video: false });
call.remoteStream$.subscribe((s) => { if (s) audio.srcObject = s; });
call.state$.subscribe((state) => status.textContent = state);

A Subscriber Access Token identifies one user and can also receive calls after client.register(). See receive-calls-in-the-browser. For an anonymous visitor who should reach exactly one destination, mint a Guest token instead (get-a-webrtc-token-with-restricted-dial-targets). For a button with no backend at all, use the embeddable widget (embed-a-call-widget-with-no-backend). Tokens expire; the companion refresh_token is how a long session rolls over.

What to change first

Set DIAL_DESTINATION to the address of an AI agent (route-a-call-to-an-ai-agent) and the button talks to the agent instead of a person.