Skip to main content
By the end of this guide, you will have a working web application that uses the Cognigy Click To Call SDK to establish a SIP-based voice call from the browser. You will install the SDK, verify browser compatibility, configure a client, and make your first call. The code examples in this guide use TypeScript. If you use plain JavaScript, remove the type annotations.

Prerequisites

  • A modern web browser with WebRTC support. For more information, refer to Supported Browsers.
  • Node.js version 18 or later.
  • A web application where you can install npm packages.
    • The web application must be served over HTTPS or from localhost. WebSocket and UDP traffic must be allowed for SIP signaling and media transport.
  • A Cognigy.AI Flow with a configured Voice Gateway Endpoint.

Install the SDK

  1. Install the SDK in your web application project using npm:
    npm install @cognigy/click-to-call-sdk
    
  2. Verify the installation:
    npm list @cognigy/click-to-call-sdk
    

Configure the Client

Import the SDK, verify browser support, and create a client instance:
import { createWebRTCClient, checkWebRTCSupport } from '@cognigy/click-to-call-sdk';

const support = checkWebRTCSupport();
if (!support.supported) {
  console.error('WebRTC not supported. Missing features:', support.missing);
  throw new Error('Browser does not support WebRTC');
}

const client = await createWebRTCClient({
  endpointUrl: 'https://your-cognigy-environment.com/endpoint-token',
  userId: 'user-123',
});
The endpointUrl parameter must point to a valid Cognigy Voice Gateway Endpoint:
  1. In the Configuration section of the Voice Gateway Endpoint, copy the URL from the Endpoint URL field.
  2. Replace wss:// with https:// and remove /voiceGateway from the path. For example, if your Endpoint URL is:
    wss://endpoint-trial.cognigy.ai/d17711ad79bc73f9da03865066201d744386d78cf11651a3377ae35085902268/voiceGateway
    
    Then your endpointUrl will be:
    https://endpoint-trial.cognigy.ai/d17711ad79bc73f9da03865066201d744386d78cf11651a3377ae35085902268
    
The SDK fetches SIP credentials and server details from this URL automatically.

(Optional) Configure Custom STUN/TURN Servers

For advanced use cases, such as specifying custom STUN or TURN servers, provide a pcConfig object when creating the client. Use pcConfig only if your application requires custom NAT traversal or TURN servers. Otherwise, the SDK uses default servers automatically.
const client = await createWebRTCClient({
  endpointUrl: 'https://your-cognigy-environment.com/endpoint-token',
  userId: 'user-123',
  pcConfig: {
    iceServers: [
      { urls: 'stun:stun.l.google.com:19302' },
      { urls: 'turn:your-turn-server.com:3478', username: 'user', credential: 'password' }
    ]
  }
});

Register Event Listeners

Set up event listeners before making any calls:
// Connection events
client.on('connecting', () => console.log('Connecting to SIP server...'));
client.on('registered', () => console.log('SIP client registered'));
client.on('disconnected', () => console.log('Disconnected from SIP server'));

// Call events
client.on('answered', (session) => console.log('Call answered. Session ID:', session.id));
client.on('ended', (session, endInfo) => console.log('Call ended. Cause:', endInfo.cause));
client.on('failed', (session, endInfo) => console.error('Call failed. Cause:', endInfo.cause));

// Error handling
client.on('error', (error) => console.error('WebRTC SDK error:', error.message));
Audio playback is automatic. You don’t need to add an <audio> element to your HTML. For advanced use cases, such as custom audio processing or visualization, refer to Custom Audio.

Start and End a Call

With the client configured and events registered, start a voice call:
// Connect and start the call in one step
await client.connectAndCall();
To end the call and clean up:
await client.endCall();
await client.disconnect();
Instead of calling endCall() and disconnect() separately, you can call client.destroy() to end the call, disconnect, and release all resources in one step.

Run and Verify

  1. Combine the code from the previous sections into a single function and bind it to a button click in your web application. A call must be initiated by a user gesture, for example, a button click, because browsers block audio autoplay without user interaction. Refer to the Complete Example.
  2. Start your application and open it in a supported browser.
  3. Open the browser developer console.
  4. Click the button that triggers the call. You should see the following messages in the console:
    • Connecting to SIP server... — the SDK is establishing a connection.
    • SIP client registered — registration succeeded.
    • Call answered. Session ID: ... — the call is active and audio should be playing.
If you don’t hear audio or the call fails to connect, refer to Troubleshooting.

Complete Example

import { createWebRTCClient, checkWebRTCSupport } from '@cognigy/click-to-call-sdk';

async function main() {
  const support = checkWebRTCSupport();
  if (!support.supported) {
    console.error('WebRTC not supported:', support.missing);
    return;
  }

  const client = await createWebRTCClient({
    endpointUrl: 'https://your-cognigy-environment.com/endpoint-token',
    userId: 'user-123',
  });

  // Connection events
  client.on('connecting', () => console.log('Connecting to SIP server...'));
  client.on('registered', () => console.log('SIP client registered'));
  client.on('disconnected', () => console.log('Disconnected from SIP server'));

  // Call events
  client.on('answered', (session) => console.log('Call answered:', session.id));
  client.on('ended', (session, endInfo) => console.log('Call ended:', endInfo.cause));
  client.on('failed', (session, endInfo) => console.error('Call failed:', endInfo.cause));
  client.on('error', (error) => console.error('Error:', error.message));

  await client.connectAndCall();

  // Clean up when the page unloads.
  // destroy() disconnects the SIP client, ends any active call, and releases all resources.
  window.addEventListener('beforeunload', () => {
    void client.destroy().catch(() => {
    });
  });
}

main();

Next Steps