Skip to content

Embeddable API for controlling and manipulating the UI

Embeddable provides an API that allows developers to control the UI and flow of the application via the embedded CTI. It is based on the postMessage API.

Active call control

[ | 1.x]

Following APIs need to work with Web phone call event to get callId.

Answer a ringing call

document.querySelector("#rc-widget-adapter-frame").contentWindow.postMessage({
  type: 'rc-adapter-control-call',
  callAction: 'answer',
  callId: `call id`
}, '*');
// callId comes from web phone call event

// answer the current ringing call, call id default is current ringing call id.
document.querySelector("#rc-widget-adapter-frame").contentWindow.postMessage({
  type: 'rc-adapter-control-call',
  callAction: 'answer',
}, '*');

Reject a ringing call

document.querySelector("#rc-widget-adapter-frame").contentWindow.postMessage({
  type: 'rc-adapter-control-call',
  callAction: 'reject',
  callId: `call id`
}, '*');

To voicemail a ringing call

document.querySelector("#rc-widget-adapter-frame").contentWindow.postMessage({
  type: 'rc-adapter-control-call',
  callAction: 'toVoicemail',
  callId: `call id`
}, '*');

Forward a ringing call

document.querySelector("#rc-widget-adapter-frame").contentWindow.postMessage({
  type: 'rc-adapter-control-call',
  callAction: 'forward',
  callId: `call id`,
  options: {
    forwardNumber: 'forward_number'
  }
}, '*');

Hangup a call

document.querySelector("#rc-widget-adapter-frame").contentWindow.postMessage({
  type: 'rc-adapter-control-call',
  callAction: 'hangup',
  callId: `call id`
}, '*');

// hangup current active call
document.querySelector("#rc-widget-adapter-frame").contentWindow.postMessage({
  type: 'rc-adapter-control-call',
  callAction: 'hangup',
}, '*');

Hold a call

document.querySelector("#rc-widget-adapter-frame").contentWindow.postMessage({
  type: 'rc-adapter-control-call',
  callAction: 'hold',
  callId: `call id`
}, '*');

Unhold a call

document.querySelector("#rc-widget-adapter-frame").contentWindow.postMessage({
  type: 'rc-adapter-control-call',
  callAction: 'unhold',
  callId: `call id`
}, '*');

Transfer a call

document.querySelector("#rc-widget-adapter-frame").contentWindow.postMessage({
  type: 'rc-adapter-control-call',
  callAction: 'transfer',
  callId: `call id`,
  options: {
    transferNumber: 'transfer_number'
  }
}, '*');

Record a call

document.querySelector("#rc-widget-adapter-frame").contentWindow.postMessage({
  type: 'rc-adapter-control-call',
  callAction: 'startRecord',
  callId: `call id`
}, '*');

This will only work after the call has already started (Inbound call accepted/Oubound call connected)

Stop record a call

document.querySelector("#rc-widget-adapter-frame").contentWindow.postMessage({
  type: 'rc-adapter-control-call',
  callAction: 'stopRecord',
  callId: `call id`
}, '*');

Mute a call

document.querySelector("#rc-widget-adapter-frame").contentWindow.postMessage({
  type: 'rc-adapter-control-call',
  callAction: 'mute',
  callId: `call id`
}, '*');

Unmute a call

document.querySelector("#rc-widget-adapter-frame").contentWindow.postMessage({
  type: 'rc-adapter-control-call',
  callAction: 'unmute',
  callId: `call id`
}, '*');

Embeddable widget

Show custom alert message

1.8.6

const requestId = Date.now().toString();
document.querySelector("#rc-widget-adapter-frame").contentWindow.postMessage({
  type: 'rc-adapter-message-request',
  requestId: requestId,
  path: '/custom-alert-message',
  alertMessage: 'Test info message',
  alertLevel: 'info',
  ttl: 5000 //5000ms => 5s
}, '*');

Note: alertLevel can be info, warning or danger.

2.0.0

const alertId = await RCAdapter.alertMessage({
  message: 'Test info message',
  level: 'info',
  ttl: 5000 //5000ms => 5s, 0 for infinite
});
// Dismiss the alert message
RCAdapter.dismissMessage(alertId); // dismiss the alert message
// Dismiss all alert messages
RCAdapter.dismissMessage();

2.1.0

Alert with details

const alertId = await RCAdapter.alertMessage({
  message: 'Can not log phone call',
  ttl: 0,
  level: 'danger',
  details: [{
    title: 'Description',
    items: [{
      id: '1',
      type: 'text',
      text: 'This is a longer more descriptive explanation of the problem that can expand over multiple lines.'
    }],
  }, {
    title: 'Error from CRM',
    items: [{
      id: '1',
      type: 'text',
      text: 'OAU-1973 Contact not found'
    }],
  }, {
    title: 'Actions',
    items: [{
      id: '1',
      type: 'link',
      text: 'Need help? Ask out community.',
      href: 'https://community.ringcentral.com'
    }, {
      id: '2',
      type: 'link', // when not href set, it will send a event with [button event](./sms-toolbar-button.md)
      text: 'Resolve logging conflict',
    }]
  }]
})

Minimize/Hide/Remove the widget

Only for Adapter JS way:

Minimize:

RCAdapter.setMinimized(true);
// RCAdapter.setMinimized(false); // maximize

You can also disable Minimize feature by following here.

Hide:

RCAdapter.setClosed(true);
// RCAdapter.setClosed(false); // Show

Remove:

RCAdapter.dispose();

Only for Adapter JS way and popup window feature enabled:

RCAdapter.popupWindow();  // popup the widget in a standalone window

Login and authorization

Log out user

document.querySelector("#rc-widget-adapter-frame").contentWindow.postMessage({
  type: 'rc-adapter-logout'
}, '*');

Trigger Login button click

App will open login popup window after getting this command. Follow here to disable popup window, and receive oauth uri.

document.querySelector("#rc-widget-adapter-frame").contentWindow.postMessage({
  type: 'rc-adapter-login'
}, '*');

This command only works when user is not logged in

Open the dialer and start a call

Find the widget iframe and use postMessage to send command and data:

document.querySelector("#rc-widget-adapter-frame").contentWindow.postMessage({
  type: 'rc-adapter-new-call',
  phoneNumber: `phone number`,
  toCall: true,
}, '*');

This feature can be used for Click to Dial. If you set toCall to ture, it will start the call immediately.

If you are using Adapter JS way, just you can just call RCAdapter.clickToCall('phonenumber').

Here is tutorial to use RingCentral C2D library to quick implement Click to Dial feature.

Navigate to path:

document.querySelector("#rc-widget-adapter-frame").contentWindow.postMessage({
  type: 'rc-adapter-navigate-to',
  path: '/messages', // '/meeting', '/dialer', '//history', '/settings'
}, '*');

Navigate back to previous path:

2.0.0

document.querySelector("#rc-widget-adapter-frame").contentWindow.postMessage({
  type: 'rc-adapter-navigate-to',
  path: 'goBack',
}, '*');

Go to the SMS tab

document.querySelector("#rc-widget-adapter-frame").contentWindow.postMessage({
  type: 'rc-adapter-new-sms',
  phoneNumber: `phone number`,
}, '*');

Go to SMS conversation for specific phone number

document.querySelector("#rc-widget-adapter-frame").contentWindow.postMessage({
  type: 'rc-adapter-new-sms',
  phoneNumber: `phone number`,
  conversation: true, // will go to conversation page if conversation existed
}, '*');

Go to SMS page with prefilled text

document.querySelector("#rc-widget-adapter-frame").contentWindow.postMessage({
  type: 'rc-adapter-new-sms',
  phoneNumber: `phone number`,
  text: `your text`
  }]
}, '*');

If you are using Adapter JS way, just you can just call RCAdapter.clickToSMS('phonenumber', 'text').

Auto-populate SMS conversation text

document.querySelector("#rc-widget-adapter-frame").contentWindow.postMessage({
  type: 'rc-adapter-auto-populate-conversation',
  text: `your text`
}, '*');

This only works when user is already on the SMS conversation detail page. It will add the specified text into user's conversation input.

Go to SMS page with prefilled image/attachment

document.querySelector("#rc-widget-adapter-frame").contentWindow.postMessage({
  type: 'rc-adapter-new-sms',
  phoneNumber: `phone number`,
  attachments: [{
    name: 'test.txt',
    content: 'data:text/plain;base64,SGVsbG8sIFdvcmxkIQ%3D%3D', // base64 encoded data URI
    }], // optional for sending MMS message with attachments
  }]
}, '*');

This only works when user is already on the SMS conversation detail page. It will add the specified text into user's conversation input.

Schedule a meeting

Your applicaton needs to have the "Meeting" application scope for this to work.

// meeting info
const meetingBody = {
  topic: "Embbnux Ji's Meeting",
  meetingType: "Scheduled",
  password: "",
  schedule: {
    startTime: 1583312400368,
    durationInMinutes: 60,
    timeZone: {
      id: "1"
    }
  },
  allowJoinBeforeHost: false,
  startHostVideo: false,
  startParticipantsVideo: false,
  audioOptions: [
    "Phone",
    "ComputerAudio"
  ]
};

// send a request to schedule meeting
const requestId = Date.now().toString();
document.querySelector("#rc-widget-adapter-frame").contentWindow.postMessage({
  type: 'rc-adapter-message-request',
  requestId: requestId,
  path: '/schedule-meeting',
  body: meetingBody,
}, '*');

// listen response
window.addEventListener('message', function (e) {
  var data = e.data;
  if (data && data.type === 'rc-adapter-message-response') {
    if (data.responseId === requestId) {
      console.log(data.response);
    }
  }
});

Set presence

1.8.2

document.querySelector("#rc-widget-adapter-frame").contentWindow.postMessage({
  type: 'rc-adapter-set-presence',
  userStatus: 'Available', // Offline, Busy, Available
  dndStatus: 'TakeAllCalls', // TakeAllCalls, DoNotAcceptAnyCalls, DoNotAcceptDepartmentCalls, TakeDepartmentCallsOnly
}, '*');

To get current presence status please refer this event.

Update ringtone settings

2.0.0

Set ringtone audio

document.querySelector("#rc-widget-adapter-frame").contentWindow.postMessage({
  type: 'rc-adapter-update-ringtone',
  name: 'CoolRingTone', // Ringtone name
  uri: 'https://xxx.wav', // Ringtone URI, support http/https and base64 data URI
}, '*');

Set ringtone volume

document.querySelector("#rc-widget-adapter-frame").contentWindow.postMessage({
  type: 'rc-adapter-update-ringtone',
  volume: 0.5, // 0 - 1.0
}, '*');

If you are using Adapter JS way, just you can just call RCAdapter.updateRingtone({ name, uri, volume }).