Embedded Apps Guide
The Webex Embedded Apps Framework allows Webex users to seamlessly interact with your third party application from within Webex.
anchorEmbedded App Framework Development Workflow
anchorThe general approach to developing embedded apps is similar to developing any other web app. The main difference is that your app runs within the context of a Webex Meeting or Space, rather than in an external web browser. Embedded apps integrate with the Embedded App Framework to enable the following features:
- Ability to start an "Open Together" session with Meeting participants, or "Add to Tab" functionality in a Space.
- Get information about the meeting or messaging space host and user information (if permitted by the user or organization), Webex or Meeting Center theme color (light or dark, for example), and other details.
- Respond to events emitted by the framework about changes to the app's environment (theme change, for example), changes to the meeting host or space , or display context (sidebar or pop-out window).
The basic workflow for developing embedded apps is as follows:
- Create an embedded app in the Webex Developer Portal, providing the URL of your app's starting page. At this point your app is in development mode is only visible to your Webex account.
- Enable Developer Tools in Meeting Center or Spaces so you can debug your app within the embedded context.
- Open the app in a Meeting or Space to test it. Publish changes or fixes to your web host, and use the Reload menu item available the right-click/control-click context menu to reload your app's resources. In this way you can quickly iterate on changes directly in the Meeting or Space.
anchorEnabling Developer Tools in Meeting Client and Webex
anchorTo test and debug your embedded app while it runs in the Webex or Meeting Center client, you can use the standard developer tools available in Chrome and other modern web browsers. You first need to set a system flag or preference on your development system to enable access to developer tools.
To enable developer tools in the Meeting Center client:
On Windows, set
EnableEmbeddedAppDebugto1in theComputer\HKEY_CURRENT_USER\SOFTWARE\WebEx\DeveloperToolsregistry key.
On MacOS, run the following command:
defaults write NSGlobalDomain WebexWebAppDeveloperExtras -bool true
To enable developer tools in the Webex client:
On MacOS, create an empty file named
cisco_spark_enable_webinspector.txtand save it to your Mac's Desktop folder, for example:touch ~/Desktop/cisco_spark_enable_webinspector.txt
To open the developer tools, right-click (or Ctrl-click) anywhere inside the app's viewport and select Inspect Element. A Reload button also appears in the context menu, which you use to reload changes to your embedded app's assets.

anchorDeveloper Quick Start
anchorIn this quick start you'll create and test a basic embedded app in a Webex meeting and a Webex space. You'll learn the following:
- The basics of using the embedded app framework in a web application.
- How to create and configure your embedded app in the Developer Portal.
- How to test your app in Webex meetings and spaces.
- How to respond to events generated by the framework.
- How to retrieve user information with the Embedded App Framework API.
Prerequisites
The URL for your embedded app (the initiator app, as described previously) needs to be available at a publicly accessible URL. Similarly, any URLs that the initiator app shares with users via the setShareUrl() method must also be publicly accessible. Your app can require users to login to access private or protected resources, or to use the app generally, if desired.
Before getting started, select the two URLs that you'll use for the initiator app and the shared app. For example, these URLs might be "www.example.com/start.html" and "www.example.com/shared.html". You'll need the first URL when you create your app on the Developer Portal, and the second when you're writing code to call setShareUrl().
About the App You'll Create
As explained in overview of embedded apps, a complete embedded app solution involves two parts:
- The initiator app that a user opens from the Apps tray in a Webex meeting or space. The purpose of this app is to open the URL of another embedded app with Webex meeting participants, or add as a tab to a Webex space.
- The shared app is the app at the URL shared by the initiator app.
In this tutorial you’ll create two static HTML pages to represent these two apps. In a real-world solution these would be applications that provide richer user interactions and experience but the same concepts will apply.
Create the Embedded App's Start Page
You'll start by creating the HTML start page for your embedded app. The URL for this page is loaded when a user opens the Apps tray in a meeting or space and clicks your app.
Create an HTML file named index.html and add the following code to it:
<html> <head> <title>Embedded Apps Quick Start</title> <script src="https://binaries.webex.com/static-content-pipeline/webex-embedded-app/v1/webex-embedded-app-sdk.js" defer></script> <script src="./index.js" defer></script> </head> <body> <h1>Embedded App Quick Start</h1> <p>This is the initator app. Its job is to specify a URL to share. Click <b>Set Share URL</b>, then click either <b>Open Together</b> (when running in a meeting) or <b>Add to tab</b> (when running in a space).</p> <button onclick="handleSetShare()">Set Share URL</button> <h2>Event Log</h2> <ul id="console" /> </body> </html>Note the following about this HTML:
- The first
<script>tag loads the Embedded Apps JavaScript library. Note thedeferattribute on the script tag. - A second
<script>tag that loads your app'sindex.jsfile, which you'll create next. Note thedeferattribute on this script tag, as well. Scripts with this attribute execute in the order in which they appear in the document. This way you can be sure the framework has loaded before your app attempts to use it. - A
<button>element that will be used to callsetShareUrl(), passing it the URL to be opened with meeting participants, or added as a tab to a space. You'll define thehandleSetShare()function specified by the"onclick"attribute next. - A
<ul>element used to display log statements. The nativeconsole.log()function is also available to your app (once you've enabled developer tools in Meeting Center and Webex) but this provides an easier way to view app output.
- The first
Save your changes to index.html. Next you'll create the app's
index.jsJavaScript file.Create a JavaScript file named
index.jsand add to it the following code:// Create a new Webex app instance var app = new window.Webex.Application(); // Wait for onReady() promise to fulfill before using framework app.onReady().then(() => { log("App ready. Instance", app); }).catch((errorcode) => { log("Error with code: ", Webex.Application.ErrorCodes[errorcode]) }); // Button click handler to set share URL function handleSetShare() { // Replace this with the URL of your shared page var url = "https://www.example.com/shared.html" // "Shared App" is the title of the window or tab that will be created app.setShareUrl(url, "", "Shared App").then(() => { log("Set share URL", url); }).catch((errorcode) => { log("Error: ", Webex.Application.ErrorCodes[errorcode]) }); } // Utility function to log app messages function log(type, data) { var ul = document.getElementById("console"); var li = document.createElement("li"); var payload = document.createTextNode(`${type}: ${JSON.stringify(data)}`); li.appendChild(payload) ul.prepend(li); }Note the following about this code:
- It first creates a new instance. This is the main app object you'll use to set sharing URLs, register event listeners, get information about the app's context and environment, and more.
- The
app.onReady()promise handler displays an "App ready" message (using a customlog()function) in the console if the promise is fulfilled, or an error code if the promise fails. Apps should always wait for theonReady()promise to be fulfilled successfully before using the framework. The framework behavior's is undefined if used before theonReady()is fulfilled, or if the promise fails.
Save index.js in the same folder as index.html and publish them to your web host. Note the URL as you'll use it next to create your app on the Developer Portal. Next, you'll create the HTML page whose URL the initiator app shares.
Create the Shared Embedded App Page
Next you'll create the embedded app page whose URL is shared by the initiator app. For this example the shared page displays the ID of the current user using the method.
Create an HTML file named shared.html and add the following code to it:
<html> <head> <title>Embedded App Test</title> <script src="https://binaries.webex.com/static-content-pipeline/webex-embedded-app/v1/webex-embedded-app-sdk.js" defer></script> <script src="./shared.js" defer></script> </head> <body> <h2>Shared page</h2> <p>This page was shared by the initator app.</p> <ul id="console" /> </body> </html>Like the start page HTML (except without the buttons) the shared app loads the framework JavaScript library and a custom script file (shared.js), which you'll create next.
Create a JavaScript file named shared.js in the same folder as shared.html that contains the following code.
var app = new window.Webex.Application(); // Wait for onReady promise, handle error scenario app.onReady().then(() => { log("Application ready. App", app); // Display the ID of the current user app.context.getUser().then((user)=> { log("User ID", user.id) }).catch((errorcode) => { log("Error", errorcode) }) }).catch((errorcode) => { log("Error with code: ", Webex.Application.ErrorCodes[errorcode]) }); function log(type, data) { var ul = document.getElementById("console"); var li = document.createElement("li"); var payload = document.createTextNode(`${type}: ${JSON.stringify(data)}`); li.appendChild(payload) ul.prepend(li); }This code largely similar to that used in the iniator app but also displays the value of the
user.idfield returned by the in the app's log console.Save your changes to shared.html and shared.js and publish them to your web host.
Create your Embedded App on the Developer Portal
Next you'll create your embedded application on the Developer Portal. You'll need to provide the following information about your embedded app:
- If the app will run in a Webex Meeting, Space, or both. In this case the app will be available in both contexts.
- The URL of the initiator app (index.html) that you previously created. You can specify unique URLs for in-meeting and in-space versions of the initiator app, but for this example you'll use the same start page URL for both contexts.
- A list of valid domains for your start page URL, and for any URLs that will be shared by the initiator app. In this case initiator page and shared page are being served from the same domain so there will only be one domain one need to add.
- App name, description, and icon, and other common app metadata.
For details on using the Developer Portal to create and configure embedded apps, see Creating an Embedded App in the Developer Portal.
To create your app on the Developer Portal:
Login to the Developer Portal and click Start Building Apps or select My Webex Apps from the profile menu in the upper-right.
Click Create a New App, then click Create Embedded App.
In the New Embedded App page enter the requested information for your application:
Where does your app work? — Select both Meeting and Messaging.
Embedded app name — App name that appears in Apps picker in a meeting or space.
Description — App's description.
Tag line — App's tagline.
Icon — App's icon. Select one of the default icons or upload a 512x512px custom icon in PNG or JPEG formats.
Start page URL — URL of the initiator app that you created previously (for example,
www.example.com/index.html).Valid domains — The domain(s) where you host your embedded application's start page URL, and any other URLs shared by the initiator app using .
Leave the other fields blank. The following shows the configuration for an sample in-meeting application.
Click Add Embedded App.
Now you're ready to test your app in a Webex meeting or space. At this point your embedded app is in development mode and is only visible in the Apps tray to you (the user who created the app). An app must be approved by your Web organization administrator before others can see it in your organization.
Open the Shared App in a Meeting
Next you'll start a meeting and open the initiator app. You'll click the Set Share URL button, and then click Open together to open the app for other meeting participants. To fully test the end-user experience you will need to invite another user in your organization to your meeting.
To test your embedded application in a meeting:
Start a new meeting and invite another user in your organization to join as a participant.
You must start the meeting using the Meeting Client desktop app, not the web app.
Click the Apps tray and then click your application in the tray to open it. Because the app hasn't been approved for use in your organization a privacy dialog appears first appears, as shown below. The app user can decide if they want to share their private information with the app or not. See About Access to Private Data in Embedded Apps for more information.

Select Open and share my personal information, then click Open. The initiator app opens and the "ready" message is logged to the app console, as shown below.

Click Set Share URL, which makes the Open together button visible.

Click Open together.
The meeting participant you invited sees a window open with the same privacy dialog.
The participant clicks Open and the URL shared by initiator app (shared.html) opens in the app window.

Note that the user ID is displayed in the app console.
In the initiator app, click Stop session, which has replaced the Open together button. The app window closes for the meeting participant.

Add the Shared App to a Space
Next you'll use the initiator app to add the shared URL as a tab to a Webex meeting space. Any user that's a member of the space can open and view the app.
To add your embedded application to a space:
In Webex and open an existing space, or create a new space.
Click the + Apps tab in the space to open the Apps dialog, and scroll to the bottom of the list to view in-development apps.

Click your app in the list. The same privacy dialog appears as in the meeting context.
Select a privacy option and click Open to open the initiator app.

Click Set Share URL to enable the Add to tab button.

Click Add to tab. The app appears as a tab in the space. All users in the space can see the tab.

anchorResponding to Events
anchorThe framework emits events in response to changes to the meeting, space, or application (Webex or Meeting Center client) in which an embedded app is running. Embedded apps can create event listeners to respond to these events, as needed. The following events are currently generated by the framework. The event object passed to your app's event listener contains details about the event.
application:shareStateChanged— Fired when an embedded app starts or stops a sharing session.application:displayContextChanged— Fired when the app's rendering context changes, such as when a user pops out the app from the sidebar into its own window.application:themeChanged— Fired when the user changes the color theme in the Meeting Center or Webex client.meeting:infoChanged— Fired when information has changed for the meeting in which the embedded app is running.meeting:roleChanged— Fired when the role for the current participant changes, such as fromspace:infoChanged— Fired when changes are made to information about the current space, such as the space's title.
Creating Event Listeners
The basic pattern for creating event listeners is shown below, where app is a Webex.Application instance previously created:
app.listen().then(function() {
// listen().then() ok
app.on(<eventName1>, <callback>);
app.on(<eventName2>, <callback>);
})
.catch(function (reason) {
// listen().then() failed
});Or, with JavaScript arrow functions:
app.listen().then(() => {
app.on(<eventName1>, <callback>);
app.on(<eventName2>, <callback>);
})
.catch(function (reason) {
// Listen() promise failed
});When the listen() promise resolves successfully it indicates that the framework is ready to register your application's callback functions. For example, the following creates listeners for both meeting.infoChanged and application.themeChanged.
app
.listen()
.then(() => {
app.on("meeting.infoChanged", (event) => {
let meetingId = event.id;
let conferenceId = event.conferenceId
// etc..
})
app.on("application:themeChanged", (event) => {
// Call custom function to update theme:
// updateAppTheme(event);
})
})
.catch(function (reason) {
console.error("listen: fail reason=" + reason);
});Responding to Color Theme Changes
In the screenshot of the Open Together session shown previously you'll notice that the host and participant had different themes applied to their Meeting Center client. The white background of the shared URL looks good for the host (whose meeting window is set to use the light theme) but not as good for the participant who has selected the dark theme. Ideally, the application theme matches client application's theme.
In this section you'll add code that updates basic CSS styles in the shared application to match the currently selected theme. There are two parts to this:
- Setting color styles to match the theme setting on initial launch. You can get the current theme setting from the property.
- Responding to theme changes the user makes in Webex or Meeting client, which generates an event.
To make the app's colors match the selected theme:
Open shared.js from the embedded app you created in the quick start.
Append the following code to the
onReady().then()handler:// Register event handler for themeChanged event: app.on('application:themeChanged', (theme) => { updateColorTheme(theme); log("Updating theme to", theme) }) })When the
application:themeChangedevent is emitted the listener function calls a custom function namedupdateColorTheme(), passing it the event object containing the newly selected theme.Add the
updateColorTheme()function to shared.js:function updateColorTheme(theme) { switch (theme) { case "LIGHT": document.body.style["background"] = "#FFFFFF"; document.body.style["color"] = "#000000"; break; case "DARK": document.body.style["background"] = "#121212"; document.body.style["color"] = "#F7F7F7"; break; default: break; } }Lastly, for the app's colors to match the theme when the application starts, add following code to the app's
onReady()handler.updateColorTheme(app.theme)Your app's
onReady()handler should look like the following:app.onReady().then(() => { log("Application ready. App", app); app.context.getUser().then((user)=> { log("User ID", user.id) }).catch((errorcode) => { log("Error", errorcode) }) // Register event handler for themeChanged event: app.on('application:themeChanged', (theme) => { updateColorTheme(theme); log("Updating theme to", theme) }) // Set app theme to match selected theme on load: updateColorTheme(app.theme) })Publish your changes to shared.js to your web host.
To test these changes:
Open the shared app in a meeting add as a tab to a space. If the shared app is already open in a meeting or space, right-click (or control-click) on any empty area of the shared app's viewport and select Reload.
The app's color theme should match the currently selected theme on initial load.
In Meeting Center select View > Themes and select a different theme, or in a Webex Space open Preferences, click Appearance and select a new theme.
The app's theme changes to match the currently selected theme.

anchorCreating an Embedded App in the Developer Portal
anchorYou use the Developer Portal to create your embedded app. Creating your application involves providing the following information about your app:
- Embedded app's context: Webex Meeting, Webex Space, or both.
- App name, description, icon, and other common meta-data
- Starting URL for your embedded app. You can use the same URL for both meeting and spaces, or specify unique URLs for each context. This is the URL of the initiator app that's used to share a URL with meeting participants in real-time, or add as a tab to a space (see About Embedded Apps in Spaces and Meetings for more information).
- List of valid domains you will use as the start URL(s) for your embedded app, or that will be shared with others by a method call.
By default, the initiator app is only visible to your own Webex account inside a meeting or space.
To create your embedded app:
Login to the Developer Portal and click Start Building Apps.

Click Create a new App, or Create Embedded App if you haven't yet created an app.


In the New Embedded App page that opens configure your application as follows:
Where does your app work? — Select whether your application will be used in a Webex meeting, Webex messaging space, or both.
Application name — Enter the name of your embedded app as it will appear in Webex.
Description — Provide details about what your embedded app does, its benefits, and how a user can get started using it (1024 character maximum). If your app is listed on the Webex App Hub this will be used as the listing’s description. You can use basic Markdown text formatting, bullets, and links in your description.

Tag line — A catchy one-liner for your app (256 character maximum). The tag line will appear in search results and the app detail page.
Icon — Select or upload an image that is displayed with your application. Image must be in JPEG or PNG format and its dimensions must be 512x512px.
Valid domains — Add the domain(s) where you will host your application's start page URLs (see below). You must add at least one domain and it must match the domain(s) used by all start page URLs. For example, if your application's start page URL is www.example.com/embedded-app then you would need to add example.com as a domain.
Start page URL — The URL that the initiator (meeting host, for example) will load in the client before sharing in the Webex meeting or space. The URL must be HTTPS and be served from a valid domain.
In-meeting start page URL — (Optional) Distinct start page URL for using this app in a Webex meeting. If not specified then Start Page URL is used. The URL must be HTTPS and be served from a valid domain.
Space start page URL — (Optional) Distinct start page URL for using this app in a Webex messaging space. If not specified then Start Page URL is used. The URL must be HTTPS and be served from a valid domain.

For example, the following screenshot shows the configuration for an in-meeting application.
Click Add Embedded App.

At this point your application is in development mode and is available for your personal use in Webex meetings and messaging spaces. You can request approval of the application so others in your organization can also use it.
Requesting Approval of Embedded Apps
When you create a new embedded app in the Developer Portal it's only visible to you in Web or Meeting Center. You can optionally request your organization's admin to approve that app so that it will be available to all users in your organization.
Open your My Apps page in the Developer Portal.
Click the app you want to have approved.
On the app details page click Request admin approval.

The current submission status is displayed.
Submitting your App to Webex App Hub
You can optionally submit your application to Webex for inclusion on App Hub.
To submit your app to App Hub:
Open your My Apps page in the Developer Portal.
Click the app you want to submit.
Click Submit to Webex App Hub to open the Webex App Hub Submission page.
Provide values for all required fields and click Submit.

anchorDesign Guidelines for Embedded Apps
anchorThis section contains design guidelines and considerations for embedded app developers and designers.
Size Constraints for Embedded Apps in Meetings and Spaces
Embedded apps can run in several window sizes, from the size of a handheld device, to a tablet, or a full-screen desktop window. The same responsive design techniques used on the open web to provide the best experience should also be used for embedded apps.
Webex provides a Figma design file created by designers at Webex that contains detailed layouts and size constraints for embedded apps running in-meeting and in-space. Designers can use this information to specify appropriate CSS breakpoints for the various form factors.

Placement of In-App Navigation
If your application contains buttons or other navigation components its recommended that they are placed toward the bottom of the window. This is especially true when the app is running in the sidebar (not in a separate window).

In general, avoid placing multiple navigation components in the same area as this can lead to user confusion.
anchorPersonally Identifiable Information (PII) and Embedded Apps
anchorThe Embedded App framework provides APIs that apps can use to obtain personally identifiable information (PII) about its users, but only if permitted by the Webex organization’s administrator. By default, access to PII by embedded apps is disabled for all organizations.
The following data is considered personally identifiable by Webex policy:
The following user data returned by app.context.getUser():
- ID (
user.id) - Email (
user.email) - Display name (
user.displayName) - Organization ID (
user.orgId)
- ID (
The following meeting data returned by app.context.getMeeting():
- Conference ID (
meeting.conferenceId) - ID (
meeting.id) - Title (
meeting.title)
- Conference ID (
The following space data returned by app.context.getSpace():
- ID (
space.id) - Title (
meeting.title)
- ID (
In addition, the JSON Web Token (JWT) included in the response to getUser() contains additional PII data fields that are not exposed as top-level properties. See About the JSON Web Token (JWT) for more information.
An embedded app can determine if it has access to PII by checking the value of app.isPrivateDataAvailable. If true, PII fields will actual data for users, meetings, and spaces; if false, the values provided to your app will either be empty strings or derived values. See About Derived PII Values for more information.
About Derived PII Values
If access to private data has been disabled for an organization, then PII data fields will either contain empty strings or be derived values. Derived values are opaque but are guaranteed to be consistent across different contexts. For example, if the same user from the same organization opens an embedded application on different days, then the derived value for user.id will be the same in both sessions. This allows apps to track users across sessions even without actual user data.
Derived values are generated for the following properties:
meeting.idmeeting.conferenceIduser.iduser.orgIdspace.id
For example, the following shows an example User object returned by app.context.getUser() when access to PII has been disabled:
{
"id":"eceb7c00-...",
"orgId":"86434df5-...",
"email":"",
"displayName":"",
"token":"xxx.yyy.zzz"
}Note that the email and displayName fields are empty, while id and orgId contain derived values. The same derived values for id and orgId would be returned for the same user if they closed and then opened the app again at a later time.
If a meeting or space has a mix of participants – some with PII enabled and some without – there will be two different IDs. Users with PII enabled will have the real meeting (or space) ID in the meeting.id or space.id field, while users without PII enabled will have derived IDs for those fields. To provide apps with a common ID across all users the JWT includes the derived meeting or space ID as an extra field in the token for all users, regardless of whether PII is enabled.
About the JSON Web Token (JWT)
The User object returned by app.context.getUser() contains a field named token whose value is a signed JSON Web Token, or JWT. The purpose of the JWT in the context of embedded apps is two-fold:
- Provide a way for embedded apps to verify the integrity of the data they are provided by the framework.
- Expose additional data fields to apps beyond what are available as top-level API properties.
The JWT is not an access token for calling Webex APIs on behalf of the user of your application. Your applications will need to obtain an access token following the standard integration workflows.
To validate that JWT was actually signed by Cisco you can use the value of the new_verification_key field of the JSON object at the verification endpoint at https://idbroker.webex.com/idb/oauth2/v2/keys/verification, shown below.

JWT field reference
The section lists the fields of the JWT returned in response to a call to app.context.getUser(). Some of these fields are also available on the User object returned by getUser(), such as user.id or user.email. Others are only available as JWT fields, such as given_name.
The following are registered claim names included in the JWT:
exp– Number. Life span of token in seconds.iat– Number. The time the token was issued.iss– String. URI of the principal that issued the claims contained by the token (https://idbroker.webex.com/idb, for example)aud– String. ID of embedded application.name– String. User’s display name. Blank if PII has been disabled.given_name– String. User’s first name. Blank if PII has been disabled.family_name– String. User’s last name. Blank if PII has been disabled.email– String. User's email. Blank if PII has been disabled.email_verified– Boolean. If "true" indicates that the email was verified by Cisco and the user's PII is shared in the token. If "false", indicates that the user's email was not verified by Cisco and derived values are used for PII.
The following are Cisco claim names included in the JWT:
com.cisco.user.orgid– String. User's organization ID. Contains a derived value if PII is disabled.com.cisco.user.uuid– String. User ID. Contains a derived value if PII is disabled.com.cisco.user.level– Array. Contains one or more of the following values:- "admin"
- "guest"
- "basic"
- "enhanced"
com.cisco.context.uuid.conferenceid– String. Conference ID. Contains a derived value if PII is disabled.com.cisco.context.uuid.conferenceid.derived – String. Derived conference ID. If PII is disabled this will match the value of com.cisco.context.uuid.conferenceid.com.cisco.context.uuid.meetingid– String. Meeting ID. Contains a derived value if PII is disabled.com.cisco.context.uuid.meetingid.derived– String. Derived meeting ID. If PII is disabled this will match the value of com.cisco.context.uuid.meetingid.com.cisco.context.uuid.spaceid– String. Space ID. Contains a derived value if PII is disabled.com.cisco.context.uuid.spaceid.derived– String. Derived space ID. If PII is disabled this will match the value of com.cisco.context.uuid.spaceid.com.cisco.user.info– JSON blob containing additional information about the user, meeting, or space.
Below is an example JWT returned by a call to app.context.getUser(), using abbreviated UUIDs for clarity. In this case, email_verified is false indicating that derived values are returned for PII.
{
"email_verified": false,
"iss": "https://idbroker-b-us.webex.com/idb",
"com.cisco.context.uuid.meetingid.derived": "a9b68195-...",
"com.cisco.user.uuid": "bbd582d2-...",
"com.cisco.context.uuid.meetingid": "a9b68195-...",
"com.cisco.context.uuid.conferenceid": "55c205d8-...",
"given_name": "",
"aud": "Y2lzY29z...",
"com.cisco.user.orgid": "86434df5-...",
"com.cisco.context.uuid.conferenceid.derived": "55c205d8-...",
"name": "",
"com.cisco.user.level": [
"enhanced",
"admin"
],
"exp": 1634679561,
"iat": 1634593161,
"family_name": "",
"email": "",
"com.cisco.user.info": "{\"some_property_name\":\"Some data.\"}"
}Access to PII for In-Development Apps
Before an embedded application has been approved for use within an organization, it is considered "in-development". Only the user who created the embedded app in the Developer Portal can add an instance of the app to a meeting or space. Other participants in the meeting or space can view the app shared by the app owner but are first presented with a dialog asking them if they want to open the app and share their PII, or open the app without sharing any PII.

Note that the JWT token contains derived values, even if the user chooses to share their personal information when opening the app.
anchorDevelopment Tips and Tricks
anchorThis section provides an assortment of solutions to common questions or problems for developing Embedded Apps.
Checking for an Existing Sharing Session
It's good practice to check the value of before calling setShareUrl(). This avoids the scenario of the "Open together" button mistakenly appearing for meeting participants.
For example, in the following code sample the embedded app's handleSetShare() is responsible for calling setShareUrl() in response to some other event. The function first checks the value of app.isShared and exits the function if it's true.
function handleSetShare(url)
if (app.isShared) {
log('ERROR: setShareUrl() should not be called while session is active');
return;
}
// Call setShareUrl() as usual...
}Check if App is Running In-Space or In-Meeting
In some cases an embedded app may need to determine if it's running in a meeting or a space. One way to do this is to check the value of the app.displayContext, which contains one of the following values: "MEETING_SIDEBAR", "MEETING_STANDALONE_WINDOW", "MEETING_MAINVIEW", or "SPACETAB". For example, the following code uses the includes() function to check if app.displayContext contains the string "MEETING". If includes() returns true the app is running in a meeting, otherwise it's running in a space.
var app = new window.Webex.Application();
var isMeeting = false;
app.onReady().then(() => {
// Check if running in a meeting
isMeeting = app.displayContext.includes("MEETING");
if(isMeeting) {
console.log("I'm running in a meeting");
} else {
console.log("I'm running in a space");
}
}).catch((errorcode) => {
log("Error: ", Webex.Application.ErrorCodes[errorcode]);
});Using Cookies and Web Storage
Embedded apps can use cookies and Web Storage the same way they are used in web browsers. Persistent cookies and local storage data are persisted after a user quits the Webex app or Meeting Center client; session cookies and session storage data are deleted when the user closes Webex or Meeting Center.
The Webex Kitchen Sink app on GitHub demonstrates the various storage options.

Webex Integrations in Embedded Apps
For an embedded app to make Webex API calls on behalf of its users, the app must first obtain an access token using the standard OAuth grant flow used by Webex Integrations. The signed JSON Web Token (JWT) returned in the response to app.context.getUser() cannot be used to make Webex API calls. Its purpose is to provide apps a way to confirm that the data came from Cisco by verifying the JWT's signature. See About the JSON Web Token for more information.
Clearing the Webex Cache
When iteratively testing changes to your embedded app you'll typically post your changes to your web host, and then click "Reload" in developer tools menu to refresh the app. Like stand-alone web browsers the Webex app caches your embedded app's assets for faster loading times, so you may need to clear its cache to view your app's most recent changes.
To manually clear the cache, see the instructions in the following Webex support articles:
Alternatively, you can click Clear Cookies under the Accounts tab in the Webex app's preferences. (Note that this will also log you out of any current Webex sessions.)

- Embedded App Framework Development Workflow
- Enabling Developer Tools in Meeting Client and Webex
- Developer Quick Start
- Responding to Events
- Creating an Embedded App in the Developer Portal
- Design Guidelines for Embedded Apps
- Personally Identifiable Information (PII) and Embedded Apps
- Development Tips and Tricks

