Browser Calls (WebRTC)

Voicebip supports browser-based voice calls via WebRTC using pion/webrtc. This enables two use cases:

  1. Dashboard test calls - Test your agent from the dashboard without a phone
  2. Shareable links - Let anyone call your agent from a browser (see Shareable Links)

WebRTC Signaling (Public Endpoint)

The public endpoint handles WebRTC signaling for shareable agent links. No authentication required.

$curl -X POST "https://api.voicebip.com/v1/public/try/{agent_id}/offer" \
> -H "Content-Type: application/json" \
> -d '{
> "sdp": "v=0\r\no=- 1234567890 2 IN IP4 127.0.0.1\r\n...",
> "agent_id": "agt_PAEZ_njcfm2kycpjs"
> }'

Response:

1{
2 "sdp": "v=0\r\no=- 9876543210 2 IN IP4 ...\r\n...",
3 "type": "answer",
4 "call_id": "call_webrtc_abc123"
5}

Browser Implementation

Here is a minimal JavaScript example for establishing a WebRTC call:

1async function callAgent(agentId) {
2 // 1. Get microphone access
3 const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
4
5 // 2. Create peer connection
6 const pc = new RTCPeerConnection({
7 iceServers: [{ urls: "stun:stun.l.google.com:19302" }],
8 });
9
10 // 3. Add audio track
11 stream.getTracks().forEach((track) => pc.addTrack(track, stream));
12
13 // 4. Handle remote audio
14 const remoteAudio = new Audio();
15 remoteAudio.autoplay = true;
16 pc.ontrack = (event) => {
17 remoteAudio.srcObject = event.streams[0];
18 };
19
20 // 5. Create and send offer
21 const offer = await pc.createOffer();
22 await pc.setLocalDescription(offer);
23
24 const response = await fetch(
25 `https://api.voicebip.com/v1/public/try/${agentId}/offer`,
26 {
27 method: "POST",
28 headers: { "Content-Type": "application/json" },
29 body: JSON.stringify({ sdp: offer.sdp, agent_id: agentId }),
30 }
31 );
32 const { sdp, call_id } = await response.json();
33
34 // 6. Set remote description
35 await pc.setRemoteDescription({ type: "answer", sdp });
36
37 // Call is now active. The agent will greet the caller via TTS.
38 console.log("Call started:", call_id);
39
40 // 7. Hang up
41 return {
42 hangup: () => {
43 pc.close();
44 stream.getTracks().forEach((track) => track.stop());
45 },
46 callId: call_id,
47 };
48}

Audio Visualization

The dashboard includes real-time audio level visualization during calls. To implement this in your own UI:

1const audioContext = new AudioContext();
2const analyser = audioContext.createAnalyser();
3const source = audioContext.createMediaStreamSource(stream);
4source.connect(analyser);
5
6analyser.fftSize = 256;
7const dataArray = new Uint8Array(analyser.frequencyBinCount);
8
9function draw() {
10 analyser.getByteFrequencyData(dataArray);
11 const average = dataArray.reduce((a, b) => a + b) / dataArray.length;
12 // Use `average` to drive a visual indicator (0-255)
13 requestAnimationFrame(draw);
14}
15draw();

Live Transcript

During a WebRTC call, you can stream the live transcript via Server-Sent Events (SSE). Pass your API key as a ?token= query parameter since browsers cannot set Authorization headers on EventSource connections.

1const es = new EventSource(
2 `https://api.voicebip.com/v1/calls/${callId}/transcript/stream?token=${apiKey}`
3);
4
5es.onmessage = (event) => {
6 const data = JSON.parse(event.data);
7 if (data.event_type === "call.transcription") {
8 console.log("Transcript:", data.payload.text);
9 }
10};
11
12// Close when done
13es.close();

Requirements

  • Modern browser with WebRTC support (Chrome, Firefox, Safari, Edge)
  • Microphone access permission
  • Agent must have shareable: true for public endpoint access

Current Limitations

Barge-in is not yet supported on WebRTC calls. When the agent is speaking and the user interrupts, the WebRTC path lets the current TTS audio finish before processing the next turn. Barge-in (interrupting mid-response) works on regular phone calls placed and received via the API (ESL and SIP transports), but is not yet wired into the WebRTC peer connection path.

Error Handling

HTTP StatusMeaning
200SDP answer returned, call established
404Agent not found or shareable is false
503Agent busy — concurrent limit (10 simultaneous calls) or daily limit (50 calls/day) exceeded
400Invalid SDP offer