JAVASCRIPT • WEBRTC • STEP-BY-STEP

How to add voice calling to your website

Build a one-to-one audio call with JavaScript and RTCExpress. This starter gives each browser its own identity, incoming call controls, mute, and hang up.

Check voice access before you startFree includes chat. This starter requires a voice-enabled Starter or Pro project. Contact us to request voice access, or try the separate public demo.

Download voice starter Try the live demo

1. Prepare your project

You need Node.js 22, a modern browser, headphones, and an RTCExpress project with voice calling enabled. Voice is available on Starter and Pro; the Free chat plan does not include voice. Contact us for voice access.

Already testing the public demo? That uses a separate demo project. Your integration needs its own App ID and user tokens.

2. Download and run locally

Extract the ZIP into a new, empty folder (for example, D:\rtcexpress-voice-test). Do not mix it with an existing project or extract the archives inside vendor. Open a terminal in the folder containing package.json, and run:

npm install
npm run dev

Open the localhost address printed in the terminal in two browser tabs. The archive includes the web SDK and protocol packages as local dependencies. You do not need to install an unpublished package from npm.

The files are small enough to explore: index.html contains the interface, main.js connects the SDK and handles calls, and vendor contains the bundled SDK packages.

3. Give each tab a different user

Log in to your customer console → Token tools. Create two short-lived tokens using the same project and room:

  • First token: user ID alice, room ID voice-test.
  • Second token: user ID bob, room ID voice-test.

In the first tab, enter your App ID, alice, voice-test, and Alice's token. Set the peer user ID to bob. In the second tab, enter the same App ID and room, bob and Bob's token, and set the peer to alice.

Use user tokens, never your App SecretThe manual token fields are for local testing. The starter clears the token input after connecting and does not save tokens in browser storage.

4. Connect, call, and accept

  1. Press Connect and join in both tabs. Wait for each to say Joined.
  2. In Alice's tab, press Call.
  3. In Bob's tab, press Accept. Allow microphone access when prompted.
  4. Check that both tabs report Call connected. Test Mute, Unmute, and End call.

Two tabs are useful for checking controls. For actual audio quality, use two devices and headphones with an HTTPS deployment, or open the live demo on your phone and laptop. Do not expose the local development server publicly.

What the SDK does

The SDK connects signaling, joins the authorized room, exchanges the call invitation, and negotiates a WebRTC peer connection. It plays the remote audio automatically. Enable calling only after the roomJoined event; joinRoom sends a request and is not a promise that confirms membership.

import { RTCExpress } from '@rtc/sdk';
const rtc = new RTCExpress();
rtc.on('roomJoined', () => { /* enable Call */ });
rtc.on('callInvite', () => { /* show Accept / Reject */ });
rtc.on('callState', ({ state }) => console.log(state));
await rtc.init({ serverUrl, appId, userId, token, mediaMode: 'p2p' });
rtc.joinRoom('voice-test');
// After both users join, on the caller's button click:
// rtc.callUser('bob', { callType: 'voice' });
// On the recipient's Accept button: await rtc.acceptCall();

Troubleshooting your first call

  • Voice not included in Free: connection and room membership can succeed while calls are blocked. Request voice access for your project; generating another token does not change your plan.
  • Cannot connect: check the App ID, matching user ID, token expiry, and project access.
  • Call stays disabled: wait for room membership confirmation. Both tokens must permit the same room.
  • No incoming call: use the other tab's exact user ID, and keep it connected.
  • Microphone blocked: allow microphone access in browser site settings, then retry.
  • Connected but no audio: check microphone hardware, mute, output volume, and browser permissions. Test on separate networks to check the deployment's TURN connectivity.

5. Add your own backend before shipping

Replace manual token entry with your application's authenticated token endpoint. Your server must check the signed-in user's identity and room access, then request a short-lived token from RTCExpress. Store the App Secret only on your server.

Serve your application over HTTPS. Add reconnect handling, permission errors, accessible call controls, and monitoring. Test physical devices, rejected calls, expired tokens, different networks, and background behavior before inviting customers.

This starter demonstrates one-to-one browser voice calls. It is not a complete production authentication system or a background mobile calling implementation.