net2phone Dialer SDK

A TypeScript library to embed a net2phone dialer on custom websites with an ability to control it using an API.

The library is currently in pre-release mode. We encourage our customers to try using it and provide feedback. The UI of the dialer may change and there could be some breaking changes in the API until the 1.0.0 is released.

Getting Started

The net2phone dialer SDK is distributed as an NPM package, but it's also possible to use CDNs like unpkg.com or jsDelivr to reference the library if you are not using a JavaScript build system.

Install from NPM

$ npm install @net2phone/dialer-sdk

Once the package is installed, import and initialize the library using:

import Net2PhoneDialer from "@net2phone/dialer-sdk";

const net2PhoneDialer = new Net2PhoneDialer({
  rootHtmlElement: document.getElementById('net2phone-dialer')
});

Load from CDN

Using Universal Module Definition:

<div id="net2phone-dialer"></div>
<script
  src="https://unpkg.com/@net2phone/dialer-sdk/dist/net2phone-dialer-sdk.umd.js">
</script>
<script>
  const dialer = new Net2PhoneDialer({
    rootHtmlElement: document.getElementById('net2phone-dialer')
  })
</script>

Using ES Modules:

<div id="net2phone-dialer"></div>
<script type="module">
  import Net2PhoneDialer
    from 'https://unpkg.com/@net2phone/dialer-sdk/dist/net2phone-dialer-sdk.es.js';

  const dialer = new Net2PhoneDialer({
    rootHtmlElement: document.getElementById('net2phone-dialer')
  });
</script>

Demo

Your custom website

Usage

The net2phone dialer API is exposed as a single JavaScript class. Learn how to create the instance of the class in the getting started section.

There are several ways to interact with the dialer instance:

  1. You can invoke methods to trigger an action, for example to make a new outbound call.
  2. You can subscribe to events, for example to update something on your page when the call is ringing.
// Create a dialer instance during the page load.
const net2PhoneDialer = new Net2PhoneDialer({
  // Pass the options as the object to the constructor function
  rootHtmlElement: document.getElementById('net2phone-dialer')
});


// Invoke methods on the dialer instance.
// Methods are typically asynchronous and return JavaScript promises.
net2PhoneDialer
  .placeCall({ to: 'PHONE_NUMBER_HERE' })
  .catch(console.error);

// Subscribe to events
function onNet2PhoneDialerEvent(event) {
  console.log(event);
}
const subscription = net2PhoneDialer.subscribe(onNet2PhoneDialerEvent);
// Unsubscribe when your app is not interested in the events anymore.
subscription.dispose();

// Dispose the dialer to remove.
// This will remove it from the DOM and inbound calls won't be received anymore.
net2PhoneDialer.dispose();

We'll use TypeScript with comments in further sections to describe the APIs available on the dialer object, however you don't need to use TypeScript to use the SDK, it's just a convenient way to document API contracts.

Methods

The dialer instance methods typically accept at most a single parameter with method options and return back a JavaScript promise.

All known errors inherit from the Net2PhoneDialer.errors.Net2PhoneDialerError class, which also extends from the standard JavaScript Error and therefore has a message field with explanation of the error. You can check for the specific error type with the instanceof operator like this:

const {
  Net2PhoneDialerError,
  InvalidPhoneNumberError
} = Net2phoneDialer.errors;
try {
  await net2phoneDialer.placeCall({ to: 'invalid_input' });
} catch (e) {
  if (e instanceof InvalidPhoneNumberError) {
    console.log(
      'The phone call was not dispatched. The phone number was invalid.',
      e.message);
  }
  if (e instanceof Net2PhoneDialerError) {
    console.log('Some other known error from the dialer.', e.message)
  }
  console.error('Unknown error.', e);
}

Create Dialer

net2phone Dialer SDK requires a root HTML element to render itself, so pass it as an option to the constructor function.

interface Net2PhoneDialerConstructorOptions {
  rootHtmlElement: HTMLElement;
}

interface Net2PhoneDialer {
  // The constructor requires an options object to be passed
  (options: Net2PhoneDialerConstructorOptions): Net2PhoneDialer;
}

Place Call

This method is used to initiate a call. Multiple outbound calls are not supported, so this method should only be called when there are no active calls currently. If taking user input, we also recommend to use libphonenumber-js to validate and parse phone numbers before passing them to this method.

interface PlaceCallCommand {
  // The phone number to call to.
  to: string;
}

interface Net2PhoneDialer {
  placeCall(placeCallCommand: PlaceCallCommand): Promise<void>
}

// This error will be returned in case of invalid phone number.
class InvalidPhoneNumberError extends Net2PhoneDialerError {}
// This error will be returned in case of already ringing outgoing call.
class OutgoingCallAlreadyRingingError extends Net2PhoneDialerError {}
// This error will be returned in case of denied microphone permission.
class MicrophonePermissionError extends Net2PhoneDialerError {}
// This error will be returned in case of not authenticated user.
class AuthenticationError extends Net2PhoneDialerError {}

Dispose Dialer

Disposing the dialer removes it from the page and stops all existing event subscriptions. The dialer instance must be recreated to start calling again.

interface Net2PhoneDialer {
  dispose(): void
}

Events

Use subscribe method on the dialer instance to start receiving events. Use dispose method on a subscription object to unsubscribe.

interface EventSubscription {
  // Unsubscribe (callback related to this subscription will not be invoked anymore).
  dispose(): void
}

interface Net2PhoneDialer {
  // This can be called multiple times to have more than one subscription.
  subscribe(callback: (event: CallStateChanged) => void): EventSubscription;
}

The callStateChanged event can be used to track the state transitions of the call. The payload of this event contains the latest accumulated state.

interface CallStateChanged {
  type: 'callStateChanged'
  call: Call
}

interface Call {
  // Unique identifier of the call.
  id: string;

  // The current state of the call.
  state: CallState;

  direction: CallDirection;

  // The final call status.
  // Set to `null` when `state` is not "completed".
  result: CallResult | null;

  // E.164 phone number or an extension.
  // Set to 'null' if the phone number is hidden.
  from: string | null;

  // E.164 phone number or an extension.
  // Set to `null` if the phone number is hidden.
  to: string | null;

  caller: {
    // The optional display name as set in the call information.
    caller_display_name: string | null;
  };

  start_time: Date;

  // The time when the call transitioned to an "answered" state.
  // Set to `null` until then.
  answer_time: Date | null;

  // The time when the call transitioned to a "disconnected" state.
  // Set to `null` until then.
  end_time: Date | null;
}


enum CallResult {
  // The call was answered and some conversation happened.
  // This may also include calls with automated responses,
  // For example, there was no actual talk, but voicemail was recorded.
  Answered = 'answered',
  // The call wasn't answered:
  // - The call rang for too long and was missed.
  // - The callee was busy.
  // - The call was rejected by a callee.
  // - The call was rejected, blocked or dropped by net2phone.
  // - The call was cancelled early by a caller.
  NotAnswered = 'not_answered'
}

enum CallDirection {
  Inbound = 'inbound',
  Outbound = 'outbound'
}

enum CallState {
  // The initial (first) state of the call.
  Connecting = 'connecting',
  // The call was accepted on the other side.
  Answered = 'answered',
  // The final (last) state of the call.
  // This event is always emitted, no matter if a call was successful,
  // or it was rejected, canceled, blocked, etc.
  // See the "result" field for the details.
  Disconnected = 'disconnected'
}