Skip to content

Jabra JavaScript SDK

With the Jabra JavaScript SDK, you can easily integrate Jabra device functionality into your JavaScript applications. The SDK supports the following use cases:

  • Call control integration for softphones
  • Getting device information
  • Reading and changing settings and other properties (properties module)
  • Subscribing to telemetry events such as audio telemetry (properties module)
  • Customizing buttons and LEDs on supported headsets (button customization module)

Supported runtimes

  • Desktop versions of Google Chrome, Microsoft Edge and other Chromium based browsers.
  • Node.js on Windows, macOS and common Linux distributions.

Installing JavaScript SDK

Please install the @gnaudio/jabra-js package via NPM (get NPM by installing Node.js). You can do this by running the following command in your project directory:

sh
npm install @gnaudio/jabra-js

Once installed, you can import and use the SDK in your JavaScript code.

js
import { 
  init,
  createApi,
  webHidPairing,
  RequestedBrowserTransport,
  TransportContext,
  LogLevel,
  EasyCallControlFactory, 
} from './node_modules/@gnaudio/jabra-js/browser-esm/index.js';
js
import { 
  init,
  createApi,
  LogLevel,
  EasyCallControlFactory, 
} from '@gnaudio/jabra-js/node-esm/index.js';

Set type to "module"

html
<script src="index.js" type="module"></script>
json
{
  (...),
  "type": "module"
}

Import methods

While we recommend using the ECMAScript import-syntax for loading the jabra-js library for browser and Node.js apps, the library also supports:

  • CommonJS for Node.js apps.
  • UMD for browser apps.

Installing optional modules

The @gnaudio/jabra-js contains the core SDK including everything needed for call control integrations. In addition to this core module, the SDK includes 2 optional modules:

sh
npm install @gnaudio/jabra-js-properties
npm install @gnaudio/jabra-js-button-customization

Import from these modules is similar to import from the core jabra-js SDK.

js
import { ButtonInteraction, createDeviceController, ButtonId, Color, LedMode } from '@gnaudio/jabra-js-button-customization';
import { IProperty, IPropertyFactory, IPropertyMap, IPropertyModule, PropertyModule } from '@gnaudio/jabra-js-properties';

Getting Started

The easiest way to get started is to try out one of our code samples.

Initializing the SDK

Before using the SDK you need to initialize it. For browser based apps, you should always use the "Chrome extension with WebHID fallback transport". For Node.js you can ignore the transport option.

js
// For browser apps, you should always use CHROME_EXTENSION_WITH_WEB_HID_FALLBACK for transport. 
  /** @type {import('@gnaudio/jabra-js').IConfig} */
  const config = {
    partnerKey: 'your-partner-key', // We recommend initializing with a proper Partner Key.
    transport: RequestedBrowserTransport.CHROME_EXTENSION_WITH_WEB_HID_FALLBACK,
    appId: 'my-app-id', // may contain a combination of letters (A-Z, a-z), numbers (123), underscores (_), and hyphens (-)
    appName: 'My app name', // end-user friendly name for your application
    logger: {
      write(logEvent) {
        console.log("Jabra SDK log event: " + logEvent.message, logEvent.layer);
      }
    }
  };

  // Initialize Jabra library using the init method and config object (recommended until version 4.9.0 of the SDK)
  // const jabraSdk = await init(config);
  // Using createApi() from SDK version 4.9.0 and later - instead of init() to avoid timing issue with SDK initialization and subscribing to device added events.
  const jabraSdk = await createApi(sdkConfig);
  // (...) setup device added/removed events (see below)
  // Finalize initialization using start() to start subscribing to device added events. 
  await jabraSdk.start();
js
// For Node.js apps, you don't need to specify transport. 
  /** @type {import('@gnaudio/jabra-js').IConfig} */
  const config = {
    partnerKey: 'your-partner-key', // We recommend initializing with a proper Partner Key.
    appId: 'my-app-id', // may contain a combination of letters (A-Z, a-z), numbers (123), underscores (_), and hyphens (-)
    appName: 'My app name', // end-user friendly name for your application
    logger: {
      write(logEvent) {
        console.log("Jabra SDK log event: " + logEvent.message, logEvent.layer);
      }
    }
  };

  // Initialize Jabra library using the init method and config object (recommended until version 4.9.0 of the SDK)
  // const jabraSdk = await createApi(config);
  // Using createApi() from SDK version 4.9.0 and later - instead of init() to avoid timing issue with SDK initialization and subscribing to device added events.
  const jabraSdk = await createApi(config);
  // (...) setup device added/removed events (see below)
  // Finalize initialization using start() to start subscribing to device added events. 
  await jabraSdk.start();

Get your Partner Key by contacting us through the support form.

Device added/removed

You can choose to subscribe to deviceAdded/deviceRemoved events or to subscribe to changes to the entire Jabra deviceList.

js
// Subscribe to Jabra devices being attached/detected by the SDK
jabraSdk.deviceAdded.subscribe(async (/**@type {import('@gnaudio/jabra-js').IDevice} */ device) => {
  console.log(`Device attached/detected: ${device.name} (Product ID: ${device.productId}, Serial #: ${device.serialNumber})`);
  // (...) Your code working with the device here. 
  // Example: Set up Easy Call Control for the device, if you're building a softphone integration. 
});

// Subscribe to Jabra devices being detached
jabraSdk.deviceRemoved.subscribe(async (/**@type {import('@gnaudio/jabra-js').IDevice} */ device) => {
  console.log(`Device detached/removed: ${device.name} (Product ID: ${device.productId}, Serial #: ${device.serialNumber})`);
  // (...) Your code handling that the device was removed. 
  // Example: If you were using the device for call control, you might want to setup another device for call control. 
});

// Subscribe to changes in the entire list of Jabra devices
jabraSdk.deviceList.subscribe((/**@type {import('@gnaudio/jabra-js').IDevice[]} */ devices) => { 
  console.log('Device list changed. New device list:');
  devices.forEach(async (/**@type {import('@gnaudio/jabra-js').IDevice} */ device) => {
    console.log(`--Device: ${device.name} (Product ID: ${device.productId}, Serial #: ${device.serialNumber})`);
    // (...) Your code depending on whether this was the device you were looking for. 
    // Example: If device matches the audio device selected in a softphone, set up Easy Call Control for device. 
  });
});

Important note on WebHID transport

If your application is running in the browser, the transport mode most of your customers will use is "WebHID". In this case you will need to ensure you trigger the WebHID consent dialog. Example:
To trigger the WebHID consent dialog add for example a button to your HTML:

html
<button id="webHidButton">Add Jabra headset</button>

Then add an event listener from where you trigger the WebHID consent dialog:

js
const webHidButton = document.getElementById('webHidButton');
webHidButton.addEventListener('click', async () => {
  console.log('Adding Jabra device using WebHID');
  await webHidPairing();
  // If user added a device, the deviceAdded and deviceList subscriptions 
  // will trigger and you should handle the device interaction there.

Device connections

When an end-user connects a headset to their computer, some cases can lead to multiple connections.
Note: This only applies to Node.js apps and to web apps where the transport mode is to use Chrome Extension - please see Transport mode for web apps.

Example: For a BT headset you can simultaneously connect the headset using a wireless dongle connection for calls, in addition to a wired USB cable connection. A new wired connection does not report the headset as an additional device, but merely as an additional connection for the same device.

For a device, you can subscribe to ConnectionAdded/ConnectionRemoved events or subscribe to changes to the entire ConnectionList. You can also get a list of CurrentConnections.

js
// Connection added event
device.connectionAdded.subscribe(async (/**@type {import('@gnaudio/jabra-js').IConnection} */ connection) => {
  console.log(`Device connection added: ${connection.id}`);
});

// Connection removed event
device.connectionRemoved.subscribe(async (/**@type {import('@gnaudio/jabra-js').IConnection} */ connection) => {  
  console.log(`Device connection removed: ${connection.id}`);
});

// Connection list changed event
device.connectionList.subscribe(async (/**@type {import('@gnaudio/jabra-js').IConnection[]} */ connections) => {
  console.log(`Device connection list for ${device.name}:`);
  connections.forEach(/**@type {import('@gnaudio/jabra-js').IConnection} */ connection => {
    console.log(`Connection: ${connection.id}`);
  });
});

Easy Call Control

The recommended way for integrating call control with Jabra headsets into a softphone is to use our Easy Call Control (multi-call option) which is part of the JavaScript SDK.

Legacy CallControl and Easy Call Control (single-call option)

If you have an existing softphone integration using the legacy CallControl or Easy Call Control (single-call option), you can keep using that and it is fully supported. However, for all new integrations, we strongly recommend basing only on Easy Call Control (multi-call option).

Easy Call Control offers a high-level abstraction for call control integrations and is intended to be quick and easy to integrate with no need to understand the complexities of signals to and from headsets.

Once Easy Call Control is setup for a device, you can change the call state using high-level methods. Likewise, you can subscribe to events from Easy Call Control letting you know what state the device has requested.

Call control sample code

See code samples for a complete demo implementation of Easy Call Control.

Setup Easy Call Control

To set up Easy Call Control for a device, you should first check that the device supports call control and then create an instance of Easy Call Control.

js
// Create an Easy Call Control Factory from your 
// instance of the IApi you got when initializing SDK. 
var easyCallControlFactory = new EasyCallControlFactory(jabraSdk);
// If the device supports Easy Call Control, enable it.
if (easyCallControlFactory.supportsEasyCallControl(device)) {
  /**@type {import('@gnaudio/jabra-js').IMultiCallControl} */  
  var easyCallControl = await easyCallControlFactory.createMultiCallControl(device);
};

Subscribe to events

By listening to these events your application can keep track of the call state of the device and update your application's state accordingly.

js
// OngoingCalls is the number of ongoing calls on the device. This includes active and held calls. 

easyCallControl.ongoingCalls.subscribe((ongoingCalls) =>
{
    // (...)
});

// MuteState is the microphone mute state of the device. 
easyCallControl.muteState.subscribe((muteState) =>
{
    // (...)
});

// HoldState indicates if call is on hold or not. 
easyCallControl.holdState.subscribe((holdState) =>
{
    // (...)
});

// SwapRequest is called when the user wants to swap between two calls. 
easyCallControl.swapRequest.subscribe(() =>
{
    // (...) 
});

Change call state

By using these methods you can update Easy Call Control with state changes from your application.

js
// New incoming call
// The async call to signalIncomingCall() will not resolve 
// until the call is either accepted or rejected.
console.log("signalIncomingCall()");
var callAcceptedResult = await easyCallControl.signalIncomingCall();
if (callAcceptedResult) {
  console.log("signalIncomingCall() - Call accepted");
} else {
  console.log("signalIncomingCall() - Call rejected");
};
js
// Accept incoming call. 
// Note there is an optional parameter in case of multiple calls to specify whether to 
// accept and hang up current call, or accept and put current call on hold.
await easyCallControl.acceptIncomingCall();
js
// Reject incoming call. 
await easyCallControl.rejectIncomingCall();
js
// New outgoing call
await easyCallControl.startCall();
js
// End active call
await easyCallControl.endCall();
js
// Put active call on hold
await easyCallControl.hold();
js
// Resume call from held state
await easyCallControl.resume();
js
// Mute headset microphone
await easyCallControl.mute();
js
/// Unmute headset microphone
await easyCallControl.unmute();

Properties

The Properties module is used to get and set settings on Jabra devices and to listen for telemetry events from devices. For a sample implementation demonstrating how to work with device properties, please see the Properties & Button Customization demo in the samples section below. The demo implementation includes details on common properties for Jabra Engage 40, Jabra Engage 50 and Jabra Engage 50 II headset devices.

Separate NPM package

Before you can use the Properties module in your application, do remember to install the Properties module.

Setup Properties

To start interacting with Properties, first create an instance of the PropertyModule and then create an instance of the PropertyFactory.

js
//Initialize the SDK's properties module
let propertyModule = new PropertyModule();
let propertyFactory = await propertyModule.createPropertyFactory(propertiesDefinition);
ts
//Initialize the SDK's properties module
let propertyModule: IPropertyModule = new PropertyModule();
let propertyFactory: IPropertyFactory = await propertyModule.createPropertyFactory(propertiesDefinition);

PropertyMap

Before reading or writing properties to/from a device you need to define a PropertyMap of the properties you intend to use. In this example we're using select properties from the Jabra Engage 40, 50 and 50 II headsets.

js
// List the Jabra device properties and prepare them for use on the device
const propertyNames = [
  "firmwareVersion",
  "backgroundNoiseLevel",
  "audioExposure",
  "customerSpeaking",
  "agentSpeaking",
  "microphoneMuteState",
  "sidetoneEnabled"
];
const propertyMap = await propertyFactory.createProperties(device, propertyNames);

Read/write property

To read the current state of a setting (property) or change a setting, you simply get the property or start a transaction for setting properties.

js
//Read properties from device
const firmwareVersion = await propertyMap.get("firmwareVersion").get();
console.log("Firmware version: " + firmwareVersion, { deviceName: device.name });
js
//Write properties to device.
const value = true;
await propertyMap.startTransaction().set("sidetoneEnabled", value).commit();

Some settings trigger reboot

Note that some of the settings you can change using properties will trigger Jabra devices to reboot.

Telemetry data

Some properties can be observed for ongoing telemetry data. Examples include the "backgroundNoiseLevel" property available in Jabra Engage 40/50/50II headsets.

js
// Observing a property 
const backgroundNoiseLevelProperty = propertyMap.get("backgroundNoiseLevel");
backgroundNoiseLevelProperty.watch().subscribe({
    next(value) {
      // When a new value is received
      console.log(`${property.name}: ${value}`);
    },
    error(e) {
      // When an error occurs when setting up or running the watch
      if (e instanceof JabraError) {
        console.error(`Could not subscribe to ${property.name}. It may not be supported by device`, { level: "error" });
      } else {
        console.error(`Failed monitoring ${property.name}: ${e}`, { level: "error" });
      }
    },
    complete() {
      // When the watch is ended. E.g. when the device is disconnected
      console.log(`Completed observing ${property.name}`);
    }
  });

Other properties

In the Properties & Button Customization demo we're detailing common properties of interest for developers for select headset devices. If you're interested in other settings or telemetry data points for Jabra devices, please contact us, detailing what you're looking for.

Button customization

The Button customization module allows you to customize buttons and LEDs on supported Jabra headsets. You can take control of buttons, listen for button interactions, and control LED colors and modes. For a comprehensive sample implementation demonstrating button and LED customization on the Jabra Engage 40, 50 and 50 II, please see the Properties & Button Customization demo in the samples section below.

Separate NPM package

Before you can use the Button customization module in your application, do remember to install the Button customization module.

Setup Button customization

To start working with button customization, create a device controller and get access to the button you want to customize:

js
import { ButtonInteraction, createDeviceController, ButtonId, Color, LedMode } from '@gnaudio/jabra-js-button-customization';

async function setupButtonCustomization(device) {
  const controller = await createDeviceController(device);
  if (!controller) {
    console.error("Failed to create device controller. The device may not support button customization.");
    return;
  }
  
  // Get the three-dot button
  const threeDotButton = await controller.getButton(ButtonId.threeDot);
  
  // Take control of the button (disables default functionality)
  threeDotButton.open();
  
  return { controller, threeDotButton };
}

Setting LED color and mode

Once you have control of a button, you can set its LED color and mode:

js
// Set LED to green with slow pulsing
threeDotButton.setColor(Color.green, LedMode.slowPulse);

// Set LED to solid red
threeDotButton.setColor(Color.red, LedMode.on);

// Turn LED off
threeDotButton.setColor(Color.red, LedMode.off);

Available predefined colors:

  • Color.red
  • Color.green
  • Color.blue
  • Color.yellow
  • Color.cyan
  • Color.magenta
  • Color.white

Available LED modes:

  • LedMode.off - LED is turned off
  • LedMode.on - LED is on with steady light
  • LedMode.slowPulse - LED is pulsing slowly
  • LedMode.fastPulse - LED is pulsing quickly

Custom RGB colors

You can also create custom colors using RGB values (0-255):

js
// Create custom orange color
const orange = new Color(255, 165, 0);
threeDotButton.setColor(orange, LedMode.on);

Listening for button interactions

To respond to button presses, use the listenFor method:

js
// Listen for button taps
const taps = await threeDotButton.listenFor(ButtonInteraction.tap);
taps.subscribe({
  next: () => {
    // Called when a button tap event is received
  },
  error: (error) => {
    // Called if an error occurs when listening for button events
  },
  complete: () => {
    // Called when listening for button events is stopped
  }
});

Available button interactions:

  • ButtonInteraction.press - Button held down longer than a tap
  • ButtonInteraction.tap - Quick button press
  • ButtonInteraction.doubleTap - Two quick taps in succession
  • ButtonInteraction.down - Button is pressed down
  • ButtonInteraction.up - Button is released

Releasing button control

If you're done with button customization, call close() to restore the button's default functionality:

js
// Release control and restore default functionality
threeDotButton.close();

Important

When a button is opened for control, any other functionality assigned to the button is disabled until control is released through close(). When closed, any custom LED configurations are reset and standard functionality is restored.

Supported devices

Button customization is currently supported on:

  • Jabra Engage 40
  • Jabra Engage 50
  • Jabra Engage 50 II

Transport mode for web apps

Note: This section is not relevant for Node.js applications.

For web applications, running directly in Chrome, Edge or another Chromium based web browser, you need to consider the transport mode used to communicate with Jabra devices.

Important: As mentioned previously on initialization, we strongly recommend that you choose "Chrome extension with WebHID fallback transport" when initializing the SDK. This way, the SDK automatically selects the optimal transport based on whether End-user components are installed on the end user's PC or not.

The SDK can use either "WebHID" or "Chrome Extension" transport mode for web apps. To check which transport mode is currently used:

js
switch (jabraSdk.transportContext){
  case TransportContext.WEB_HID: console.log('Using WebHID transport'); break;
  case TransportContext.CHROME_EXTENSION: console.log('Using Chrome Extension transport'); break;
  default: break;

WebHID transport mode

This means that the Jabra SDK uses the browser's native WebHID API to communicate to/from the Jabra device. WebHID requires no installed software and therefore works across any desktop version of Chrome/Edge or other Chromium based browsers, including on ChromeOS. WebHID requires end user consent to access a headset device controls, similar to how access to microphone or camera requires consent. The WebHID consent dialog can only be triggered by an end user interaction, such as clicking a button. Consent is persisted in the browser, so end users only need to consent once per Jabra device in your web app. See Device added/removed for example on how to trigger WebHID consent dialog.

WebHID policies

If one of your customers prefer to avoid the WebHID consent dialog for their end users, they can use Chrome/Edge administrator policies to allow access to Jabra headsets from your URL. Please see:
Chrome WebHID policy
Edge WebHID policy
Example policy for Chrome on Windows, allowing all Jabra devices (vendor ID 2830) - replace www.example.org with your URL and save as a .reg file - then open .reg file to test policy:

Windows Registry Editor Version 5.00

[HKEY_CURRENT_USER\Software\Policies\Google\Chrome]
"WebHidAllowDevicesForUrls"="[ {  \"devices\": [   {    \"vendor_id\": 2830   }  ],  \"urls\": [   \"https://sdk.jabra.com\",  ] }]"

WebHID limitations

While the SDK generally ensures that multiple softphones can have Jabra call control integrations co-exist without conflicts, part of this protection against softphone conflicts cannot work only with WebHID.
Additionally, the features around device connections do not work with WebHID currently. *If a customer of your softphone run into conflicts with other softphones accessing the headset, please instruct your customer to install the End-user components.

Chrome Extension transport mode

If a customer has installed both End-user components, then your web app will automatically use the Chrome Extension transport mode. In this transport mode the SDK sends messages to/from the browser extension. The extension then uses native messaging to communicate with the Jabra Device Connector application. The Jabra Device Connector application has full access to all Jabra device features, ensuring against conflicts between multiple softphones using the Jabra headset at the same time.

Samples and documentation

Code samples

Easy Call Control demo app
Please see the comprehensive demo project for Easy Call Control. The recommended transport to use for the demo is "Chrome Extension with WebHID fallback".

Please ignore other demos in the demo project

The downloadable for the Easy Call Control demo also contains other demo code. We recommend only basing off the Easy Call Control (multi-call option) sample code as that is the recommended way to integrate call controls for Jabra headsets.

Properties & Button Customization demo
Please see the demo project for working with device properties and button customization which demonstrates in JavaScript/TypeScript:

  • How to read/write settings from devices
  • How to subscribe to data telemetry events like background noise (on supported devices)
  • How to take over buttons and LEDs (on supported devices)

API references

Please see the relevant API reference for detailed information on the SDK not covered in the above:

End-user components

In certain scenarios the SDK requires installation of two Jabra software components on the end-users laptop. These components are available here:

Scenarios requiring end-user components:

  • End-users run multiple softphones simultaneously and experiences conflicts where calls to/from one softphone affects the state of the other.
FileDescriptionDownload
Browser Extension for Device ConnectorWorks across operating systems. Supports Microsoft Edge and Google Chrome.Chrome Web Store
Device Connector ApplicationInstalled application required by the Browser ExtensionWindows
macOS
Linux