Use WebRTC live audio when a user needs to speak and listen from a browser.
Flow
- Connect and scan the WaGo token.
- Start or answer a call.
- Fetch WebRTC config.
- Create a browser
RTCPeerConnection.
- Add the microphone track.
- Send the SDP offer to WaGo.
- Set WaGo’s SDP answer as the remote description.
Get WebRTC config
curl -H "token: YOUR_TOKEN" \
http://localhost:1337/call/webrtc/config
Response:
{
"iceServers": [
{
"urls": ["stun:stun.l.google.com:19302"]
}
],
"turn": {
"enabled": false,
"status": "coming_soon"
}
}
TURN is not configurable yet. WaGo currently uses STUN only.
Send an SDP offer
curl -X POST http://localhost:1337/call/webrtc/offer \
-H "Content-Type: application/json" \
-H "token: YOUR_TOKEN" \
-d '{
"callID": "CALL_ID",
"type": "offer",
"sdp": "BROWSER_SDP_OFFER"
}'
WaGo returns an SDP answer:
{
"callID": "CALL_ID",
"type": "answer",
"sdp": "WAGO_SDP_ANSWER",
"turn": {
"enabled": false,
"status": "coming_soon"
}
}
Browser example
const config = await fetch("https://your-wago-server.com/call/webrtc/config", {
headers: { token: "YOUR_TOKEN" }
}).then((res) => res.json());
const pc = new RTCPeerConnection({
iceServers: config.data?.iceServers || config.iceServers
});
const stream = await navigator.mediaDevices.getUserMedia({
audio: {
echoCancellation: true,
noiseSuppression: true,
autoGainControl: true
}
});
for (const track of stream.getAudioTracks()) {
const sender = pc.addTrack(track, stream);
const transceiver = pc.getTransceivers().find((item) => item.sender === sender);
if (transceiver) transceiver.direction = "sendrecv";
}
pc.ontrack = (event) => {
const audio = document.querySelector("audio");
audio.srcObject = event.streams[0];
audio.play();
};
const offer = await pc.createOffer();
await pc.setLocalDescription(offer);
await new Promise((resolve) => {
if (pc.iceGatheringState === "complete") return resolve();
pc.addEventListener("icegatheringstatechange", () => {
if (pc.iceGatheringState === "complete") resolve();
});
});
const answer = await fetch("https://your-wago-server.com/call/webrtc/offer", {
method: "POST",
headers: {
"Content-Type": "application/json",
token: "YOUR_TOKEN"
},
body: JSON.stringify({
callID: "CALL_ID",
type: pc.localDescription.type,
sdp: pc.localDescription.sdp
})
}).then((res) => res.json());
const payload = answer.data || answer;
await pc.setRemoteDescription({
type: payload.type,
sdp: payload.sdp
});
Close the WebRTC bridge
curl -X POST http://localhost:1337/call/webrtc/close \
-H "Content-Type: application/json" \
-H "token: YOUR_TOKEN" \
-d '{
"callID": "CALL_ID"
}'
This closes the browser media bridge. It does not hang up the WhatsApp call. Use /call/hangup to end the call.
HTTPS requirement
Browser microphone access requires HTTPS in production. localhost is the main exception for local development.