Contact usRequest a demo

Agent Embedded JS API

The Agent Embedded JS API lets you embed Unblu’s agent functionality in other web applications, such as customer relationship management (CRM) systems. It gives you programmatic access to an agent’s conversations, inbox, conversation history, and notifications, together with two web components that render Unblu’s agent interface in your page. The API works without displaying any Unblu interface, so you can also use it to add Unblu features to an interface of your own design.

Concepts

The Agent Embedded JS API has two parts:

  • The JavaScript API. The API provides the logic: connecting to the Collaboration Server, reading the agent’s inbox and conversation history, starting and joining conversations, and receiving notifications. It contains no visual elements of its own.

  • Two web components that render Unblu’s agent interface. <unblu-embedded-app> shows the agent’s inbox, and <unblu-conversation> shows a single conversation. You place them in your page like any other HTML element.

How much of Unblu’s interface you use is up to you. The JavaScript API on its own is enough to show the agent’s unread message count in your own navigation, react to conversations arriving in the inbox, and build an inbox of your own with your own filtering and columns. To open a conversation, however, you must use one of the web components.

Agent permissions

Every API call runs with the permissions of the agent who is currently logged in. Agents can do no more and no less through the API than they can in the Agent Desk. For example, an agent who isn’t allowed to end conversations can’t end one through the API. The call fails with an UnbluApiError of type ACTION_NOT_GRANTED.

The same applies to reading a conversation’s metadata, adding and removing person labels, starting calls, inviting participants, and assigning an agent. Permissions also determine which conversations and people an agent can reach: an agent can’t start a conversation with a person they have no access to.

This is an important point to consider when you test an integration. A call that succeeds for you as an administrator or a supervisor may fail for a regular agent.

Prerequisites

All the properties are in the CONVERSATION_TEMPLATE and CONVERSATION scopes and are empty by default. The two message properties are only visible if com.unblu.conversation.feature.textChatEnabled is true, and the file upload property if com.unblu.conversation.feature.fileSharingEnabled is true. Until you set them, the corresponding API calls fail with an ACTION_NOT_GRANTED error.

Installation

You can either load the Agent Embedded JS API from your Unblu server or install it from the npm registry.

To load it from the server, add a script tag to the head of your page:

Listing 1. Loading the library from your Unblu server
<script src="<unblu-server>/app/js-api/v8/agent-embedded/agent-embedded-js-api.min.js"></script>

Replace <unblu-server> with the address of your Unblu server. Once the script has loaded, the API is available at window.unblu.agentEmbedded.api.

To use the library with a bundler such as webpack, install it from the npm registry instead:

Listing 2. Installing the library from the npm registry
npm install --save @unblu/agent-embedded-js-api

You can then import the API:

Listing 3. Importing the API
import { api } from "@unblu/agent-embedded-js-api";

The library’s version is synchronized with the version of the Collaboration Server. Use the highest library version that doesn’t exceed the version of the Collaboration Server you’re running.

Typedefs are available from your server at https://<unblu-server>/app/js-api/v8/agent-embedded/agent-embedded-js-api.d.ts. For instructions on adding them to WebStorm or Visual Studio Code, refer to the Agent Embedded JS API reference.

Initializing the API

Call configure(), then initialize(). Initialization resolves to the UnbluAgentEmbeddedApi instance, which you use for everything else.

Listing 4. Configuring and initializing the Agent Embedded JS API
/* When you load the library with a script tag, the API is available in the global scope.
   If you installed it from the npm registry, import `api` instead. */
const { api } = window.unblu.agentEmbedded;

try {
  /* `configure()` returns the API, so you can chain `initialize()`. Configuration has to
     happen before initialization; calling `configure()` afterwards throws an error. */
  const unbluApi = await api
    .configure({
      // Every field is optional.
      // If omitted, no API key is sent when loading Unblu.
      apiKey: 'YOUR_API_KEY',
      // If omitted, the domain of the current page is used.
      serverUrl: 'https://unblu.yourcompany.com',
      // If omitted, '/app' is used.
      entryPath: '/app',
      // If omitted, the browser's locale is used.
      locale: 'en-US',
      // Initialization timeout in milliseconds. If omitted, 30000 is used.
      initTimeout: 30000,
    })
    .initialize();

  // `unbluApi` is your entry point to the inbox, conversations, and notifications.
  // ...
} catch (error) {
  /* `initialize()` rejects with an `UnbluApiError`. Check `error.type` to distinguish
     a missing configuration from an unsupported browser or a timed-out initialization. */
  console.error(`Unblu initialization failed: ${error.type}`);
}

There’s only ever one instance of the API. Each call to initialize() returns the same instance.

Instead of awaiting the promise, you can listen for the READY event on the static API, or for ERROR if initialization fails. For the full list of lifecycle events, refer to UnbluStaticAgentEmbeddedApi.

When you no longer need the Agent Embedded JS API, call deinitialize() on the instance. This destroys the UI, and the API instance becomes permanently unusable. Later calls on it fail with an ILLEGAL_STATE error. Initialize the API again to obtain a new instance.

The API

The UnbluAgentEmbeddedApi instance groups most of its functionality into four containers:

  • inbox lists the conversations in the agent’s inbox and reports when that list changes. getConversations() returns every conversation in the agent’s inbox, not just those on a particular tab. Any filtering your own inbox needs is therefore yours to implement. getMetadata() returns a conversation’s metadata if com.unblu.conversation.allowMetadataAccess permits it.

  • conversationConnections connects the agent to a conversation without displaying it anywhere. connect() joins the conversation as a full participant. connectAsGhost() observes it without appearing as a participant.

    Each connection keeps a conversation session alive on the Collaboration Server, so call disconnectConversation() on conversations you no longer need. Closing a conversation in one of the web components disconnects it for you.

  • conversationHistory queries the conversation history. get() fetches a single conversation. search() runs a paginated query. Neither emits events, so what you get back is a snapshot rather than a live view.

  • notification reports incoming messages, calls, missed calls, admission requests, and layer inactivity. getNotificationCount() returns the number of unread messages. Subscribe to the container’s events to render these notifications in your own interface. For more information, refer to Notifications.

The instance also has methods of its own. For example, startConversation() starts a conversation, though it doesn’t connect the agent to it; use connect() for that. getPersonInfo() returns information about the current agent. addPersonLabel() and removePersonLabel() change the labels assigned to the agent. For the full list, refer to UnbluAgentEmbeddedApi.

Web components

The two web components <unblu-embedded-app> and <unblu-conversation> are custom elements that you place in the body of your page. They display Unblu’s interface once you initialize the API.

Each component uses a shadow root for its content, so your page’s styles don’t affect what’s inside it. Size and position are up to your page. The Unblu interface fills whatever space you give the element. To change the appearance of the interface itself, use Unblu’s configuration properties.

You can place as many of either component in a page as you like. However, a single conversation can only be displayed in one component at a time. Attempting to open a conversation that’s already displayed elsewhere shows the message in com.unblu.agent_embedded.sinlgeConversationUiDialogMessage instead.

Embedded app component

<unblu-embedded-app> shows the agent’s inbox. Set its conversation-id attribute, or the equivalent conversationId property in JavaScript, to display a conversation instead. If the ID doesn’t identify a conversation the agent can access, the component displays an error dialog and resets the conversation ID to null.

The component reports which conversation is open with its openConversationChanged event. The event’s detail is the conversation ID, or null when no conversation is open.

Clicking a conversation in the inbox opens it in the same component. To take control of that, register an open conversation interceptor with registerOpenConversationInterceptor(). Unblu calls the interceptor each time the agent opens a conversation in the inbox, passes it the conversation’s ID, and waits for it to return one of two actions:

  • DISCARD stops the inbox opening the conversation, leaving your integration to display it wherever you want.

  • OPEN lets the inbox open it as usual, which is also what happens if you register no interceptor at all.

Since the interceptor runs for every conversation the agent opens, you can decide case by case which of the two to return. unregisterOpenConversationInterceptor() removes the interceptor again.

Conversation component

<unblu-conversation> displays a single conversation, with its chat, calls, and collaboration layers. Its conversation-id attribute sets the conversation to display. Its access-type attribute determines how the agent joins it:

  • NORMAL makes the agent a full participant.

  • GHOST lets the agent observe the conversation as a ghost, without being visible as a participant.

Until you initialize the API, the component renders any content your page places inside the element. From then until a conversation is open, it renders the content of the no-conversation slot, or Unblu’s standard loader if you’ve provided no slot content.

openConversation() opens a conversation from JavaScript, closing and disconnecting any conversation that was already open. You can also set the conversationId and accessType properties directly. Unblu applies both changes in a single update so the conversation doesn’t reconnect needlessly, but use openConversation() when you want explicit control.

The conversationChanged and accessTypeChanged events report those changes. The read-only conversation property gives you the Conversation API for the conversation currently open in the component, or null if there is none.

Configuring the components

The following configuration properties affect the components:

Notifications

Unblu raises a notification when something happens that the agent should know about: a new message, an incoming or missed call, an admission request, or an inactive collaboration layer. Subscribe to the newNotification event to render notifications in your own interface. Subscribe to notificationCountChange to keep a counter or badge up to date.

Every notification carries a title and a body to display, and a type identifying what happened. Other fields include:

  • groupId identifies the group a notification belongs to. Notifications of the same type that share a groupId concern the same thing, so you can collapse them into one in your interface. For message notifications, the groupId is the ID of the conversation the message was sent in. If you render notifications with the browser’s Notification API, pass the groupId as the notification’s tag.

  • sticky tells you whether the agent may dismiss the notification. If it’s true, they can’t.

  • closeRequested is a promise that resolves when the notification should no longer be displayed. Await it to know when to remove the notification from your interface, for example when the caller hangs up.

  • imageUrl is the URL to an image to display with the notification.

Notifications come with actions the agent can take, such as answering a call or opening a conversation. Each action has a label to display and a role. The role tells you how prominently to present the action, so you can style it to match the rest of your interface. DEFAULT marks the action to run when the agent clicks the notification itself. PRIMARY and SECONDARY mark actions to present as buttons, with primary given the greater emphasis.

Calling execute() runs the action. It takes a target, which specifies the web component that should handle the result. Your page may contain several components. Without the target, Unblu can’t tell which component should open the conversation that the notification relates to.

Custom actions

Custom actions let you add your own functionality to Unblu’s interfaces. The Agent Embedded JS API can both react to custom actions and trigger them.

Two of a custom action’s settings control how it reaches your integration:

  • In the Available in section, check Agent embedded integration so the agent can invoke the action from your integration.

  • In the Triggered on section, check Agent embedded JS API so that invoking it raises an event your integration receives.

Enabling one without the other is valid: an action can be available in your integration but fire a webhook instead of a JS API event, or raise a JS API event when invoked from the Agent Desk. Through the web API, the fields are invocableFromFrontends and triggerAgentEmbeddedApiEvent.

Listen for the customActionInvocation event on a conversation to react to an action the agent invokes. Unblu raises the event on the API rather than on a component, so you receive it whichever component the agent used, and regardless of whether a component is displayed.

You can also read the actions available in a conversation with getCustomConversationActions() and getCustomPersonActions(), and invoke them yourself with triggerCustomConversationAction() and triggerCustomPersonAction(). The API has no getter or trigger for custom message actions, but you do receive their invocations as CustomMessageActionInvocation, which identifies the target message and its sender. The customConversationActionsChanged and customPersonActionsChanged events tell you when the available actions change.

Limitations

The Agent Embedded JS API doesn’t cover everything an agent can do in the Agent Desk. Bear the following in mind when you plan an integration:

  • Your code can’t retrieve all the messages in a conversation. The conversation component displays messages to the agent, and the inbox and message notifications expose the most recent message.

  • The API offers no queue functionality, so your code can’t present the queue or accept a request waiting in it. Agents accept requests in the Agent Desk, or your backend dispatches them. You can, however, set a different assigned agent on an existing conversation with setAssignedAgent().

  • The API can’t search for people, and it doesn’t expose agent availability.

See also