Voice
Calls in the browser
Let people talk to an assistant from your web app with their microphone, no phone line involved.
A browser call is a voice call over WebRTC. Your server asks for one with its secret key and gets back a short-lived token; the browser uses that token to join the call's voice room, where the assistant is already waiting. The voice rooms run on LiveKit, so the browser side is LiveKit's client library.
Start the call from your server
The request needs your secret key, so it belongs on your server, behind your own login.
// POST /voice-session on your server: returns what the browser needs to join
app.post('/voice-session', async (req, res) => {
const r = await fetch('https://api.myleadsfactory.tech/api/calls/web', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.MLF_API_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
assistant_id: 'asst_7d2e9b14c6a04f3e8b5d1a9c0e7f6b23',
variables: { first_name: req.user.firstName },
metadata: { user_id: req.user.id },
}),
})
if (!r.ok) return res.status(502).json({ error: 'could_not_start_call' })
const { call_id, url, token } = await r.json()
res.json({ call_id, url, token })
}){
"call_id": "call_3b7d9f1a2c4e4b6d8f0a1c3e5b7d9f2a",
"room": "web_call_3b7d9f1a2c4e4b6d8f0a1c3e5b7d9f2a",
"token": "eyJhbGciOiJIUzI1NiJ9...",
"url": "wss://voice.example.livekit.cloud"
}The token lets one person join that one room to speak and listen. It must be used within 15 minutes.
Join from the browser
Install LiveKit's client, connect with the url and token, turn the microphone on and play the assistant's audio.
npm install livekit-clientimport { Room, RoomEvent } from 'livekit-client'
export async function startVoiceCall() {
const { url, token } = await fetch('/voice-session', { method: 'POST' }).then((r) => r.json())
const room = new Room()
// play the assistant when its audio arrives
room.on(RoomEvent.TrackSubscribed, (track) => {
if (track.kind === 'audio') document.body.append(track.attach())
})
await room.connect(url, token)
await room.localParticipant.setMicrophoneEnabled(true) // asks for microphone permission
return room // call room.disconnect() to hang up
}Start the call from a click: browsers only allow audio to play and the microphone to open after the person has interacted with the page.
Hang up and read it back
room.disconnect() ends the call from the browser; POST/api/calls/{id}/hangup ends it from your server. A browser call is a call like any other: it appears in GET/api/calls with call_type web, has a transcript and analysis, and sends the call.* webhooks.
Things to know
- Keep the secret key on the server. Only
urlandtokentravel to the browser; neither can start another call. - Variables and metadata work as they do for outbound calls: fill
{{ placeholders }}per call and tag the call with your own IDs. - If voice is not set up on your account, the request answers
503 livekit_not_configured.