<![CDATA[Cisco Webex for Developers]]> https://developer.webex.com/blog https://developer.webex.com/images/home-hero.svg Cisco Webex for Developers https://developer.webex.com/blog RSS for Node Tue, 28 Jan 2020 16:22:45 GMT <![CDATA[Come See Us at Cisco Live EMEA 2020]]>

Cisco Live, Cisco’s annual customer and partner conference, kicks off in Barcelona next week! We’ll be presenting several sessions about the Webex API, SDKs, and Widgets. If you’re in town for Cisco Live, the Webex for Developers team would love to meet you, so stop by and say hi! Here’s some more information about the sessions:


Webex APIs for Administrators — Steve Sfartz will explore the administrative capabilities of the Webex APIs with real-world use cases covering Teams, Meetings, and Devices.

Integrate and automate apps and workflows with the Webex Meetings APIs — (also on Tuesday) David Staudt will lead a hands-on session to explore the latest Webex Meetings API capabilities.


Building browser applications in JavaScript with the Webex Teams SDK — (also on Thursday) Adam Weeks will lead a hands-on workshop where you’ll build your own voice, video, and messaging-enabled web page, and explore some of the latest JavaScript SDK features like websockets and extended meeting support.

Cutting edge collaboration apps with Webex Teams APIs — JP Shipherd will explore the latest and cutting edge features of the Webex APIs and SDKs.

Create compelling collaboration workflows with the latest Webex Teams SDK features — Olivier Proffit and JP Shipherd will guide you through the breadth of Cisco’s programmable cloud collaboration experiences—including SDKs, APIs, components, and interfaces—for managing, automating, and embedding collaborative meetings.

Extending the Collaboration Eco-System using Webex Teams APIs for Non-Developers — Johannes Krohn will guide anyone without software development experience from zero to building a simple integration based on the Webex APIs.

Integrate and automate apps and workflows with the Webex Meetings APIs — (also on Monday) David Staudt will lead a hands-on session to explore the latest Webex Meetings API capabilities.


Webex for Telehealth — Kevin Chatow will give a talk about Webex use cases in Telehealth. Come see it in the Collaboration Booth in the World of Solutions at 13:30 CET.

Experiment with Adaptive Cards for Webex Teams — (also on Thursday) David Staudt will guide you through how you can add Buttons and Cards functionality to your Webex Teams bots.


Building browser applications in JavaScript with the Webex Teams SDK — (also on Tuesday) Adam Weeks will lead a hands-on workshop where you’ll build your own voice, video, and messaging-enabled web page, and explore some of the latest JavaScript SDK features like websockets and extended meeting support.

Experiment with Adaptive Cards for Webex Teams — (also on Wednesday) David Staudt will guide you through how you can add Buttons and Cards functionality to your Webex Teams bots.

Webex Room Device APIs: The power of automated, integrated, immersive collaboration — Richard Bayes will show you how you can leverage the Webex Devices platform to solve business use cases.

We’ve got a lot going on during the week and that’s just a small taste of what you can learn at Cisco Live. See you next week in Barcelona! Stay in touch with us throughout the week via @CiscoWebexDev on Twitter!

https://developer.webex.com/blog/come-see-us-at-cisco-live-emea-2020 https://developer.webex.com/blog/come-see-us-at-cisco-live-emea-2020 Tue, 21 Jan 2020 00:00:00 GMT
<![CDATA[Join our Webex Meetings REST API Beta Program]]>

The Webex Engineering team has been hard at work creating brand new REST APIs for Webex Meetings. If you’re currently a Webex Meetings developer, or if you’re interested in adding Webex Meetings features to your current Webex apps, we’d like to invite you to join the beta program. This is your opportunity to test drive the new APIs and provide us with your direct feedback.

The initial release of the Webex Meetings REST API will include the following functionality and features:

  • meeting scheduling
  • meeting invitee management
  • user preferences management
  • recordings management

Future REST API releases will include in-meeting controls (such as muting participants) and even more popular features.

Joining the Beta

If you’re interested in joining the beta program, please reach out to our Webex Developer Support team at devsupport@webex.com.

We’re looking forward to your feedback!

https://developer.webex.com/blog/join-our-webex-meetings-rest-api-beta-program https://developer.webex.com/blog/join-our-webex-meetings-rest-api-beta-program Wed, 15 Jan 2020 00:00:00 GMT
<![CDATA[From Zero to Webex Teams Chatbot in 15 Minutes]]>

Webex Teams currently powers thousands of bots with a variety of functionality – ranging from simple chat bots that provide specific information like the current weather, to more sophisticated bots that understand natural language and automate complex business tasks. Perhaps you've been wanting to deploy a handy chatbot of some kind and just haven't gotten a chance to start on it yet. Well, this is your big chance!

What we're making

Back when Webex Teams (then called Spark) bot functionality was first made available, there were several simple starters. We always liked the sparkbotstarter which was created by Victor Algaze, using a framework called Flint, which was created by Nick Marus. This sample is based on the new, rebranded webex-node-bot-framework, and adds a few fun new tricks, like posting a message using Webex Buttons and Cards.

Getting Started

Even if you don't have any prior knowledge of the Webex APIs, this guide will have you deploy a functioning chatbot application pretty quickly. Then from there, the bot-starter application can serve as a template for creating your own customized bots and can be extended to your heart's content. You might need to be at least a little familiar with node.js and also have the following prerequisites:

  1. Node & npm (minimum tested version is node 8.0.0 or higher) and git installed on your machine

  2. A Webex Teams account: https://teams.webex.com/

Sign into Webex Teams

The first thing we'll need to do is create a new bot. You can simply use your regular Webex Teams credentials to log in to Webex for Developers. When you create the bot account, be sure to jot down the bot’s username & access token before leaving the creation page - we'll need those in a minute.

Set up the Local Web Server

The bot application has to be hosted on a server where it can communicate over HTTP. For now, we'll use nGrok, which is a tool that turns your machine into a web server by opening a local port to the Internet. We're doing this so we can start using our chatbot as quickly as possible without having to think about deployment or hosting. Once you’ve customized your chatbot, you’d likely want to deploy it on a proper cloud hosting service, such as Microsoft Azure or other similar platforms, instead of your machine. Since we are aiming to get started quickly though, nGrok uses the least number of steps to get there:

  1. Download and setup nGrok here: https://ngrok.com/

  2. After downloading and unzipping nGrok, from the same directory as the nGrok executable execute this command:

    $ ./ngrok http 7001

  3. Once it's running, write down the web address that's tunneling to your localhost:7001 (e.g. http://XXXXXXX.ngrok.io)

Configure and Run the App

Now we just need to download the project, swap in a few values, and start the bot up!

  1. Download the node.js Webex Bot Starter template project with this command in your terminal:

    git clone https://github.com/WebexSamples/webex-bot-starter && cd webex-bot-starter

  2. Inside the project's root config-template.json file, use a code or text editor to swap out the following values:

     "webhookUrl": "http://XXXXXXX.ngrok.io",
     "port": 7001

    Note that if/when you turn off nGrok, when you turn it back on the URL will change and you will need to update the config with the new address.

  3. Save the changes, then rename the config-template.json file to config.json.

  4. Finally, to install and start the application, run this command:

    $ npm start

  5. If you're using a Mac, you might receive a prompt asking about “node” accepting incoming network connections. If so, click Allow to load the server:

incoming connection

Interact with the Bot in Webex Teams

Now that the nGrok server is loaded and the app is running, create a new group space (name the title whatever you want) in the Webex Teams client. Next, add your bot to the space (by the username you created earlier), just as you would add any other Webex user.

If everything was done correctly, your bot should have greeted you with some instructions when it was added to the space. You now have a running chatbot! To go further, open the index.js file in an editor and extend functionality as much as you need.

Helpful Resources

https://developer.webex.com/blog/from-zero-to-webex-teams-chatbot-in-15-minutes https://developer.webex.com/blog/from-zero-to-webex-teams-chatbot-in-15-minutes Tue, 10 Dec 2019 00:00:00 GMT
<![CDATA[New Jira Cloud and Trello Bots now support Buttons & Cards!]]>

Let’s face it, while bots and integrations help Webex Teams users take quick actions and stay up to date on various projects, command line syntax is not the easiest form of interaction. Not to worry! As we’d mentioned recently, Webex Teams clients now support the Adaptive Cards framework developed by Microsoft allowing developers to greatly improve the usability of bots and integrations for their users.

And this week we’re announcing a new release for both Jira Cloud and Trello bots supporting Buttons and Cards! Creating a Jira issue or Trello Card from a Webex Teams Space has never been easier. Choose from drop down lists or update text fields to quickly take action without having to look up the proper command. Add it to a Webex Teams space and try it out today!

How to get started

  1. Create a new space or use an existing space to add either of the bots below
  2. Once the bot is added, type “@” and select the bot, followed by the command help.
  3. Link your account and that’s it!

Learn more about what you can do with the new Jira Cloud and Trello bots on the Cisco Webex App Hub:

If you’re a developer, check out the getting started guide for Buttons and Cards and see how easy it is to improve usability and increase engagement for your bots and integrations.

https://developer.webex.com/blog/new-jira-cloud-and-trello-bots-now-support-buttons-cards https://developer.webex.com/blog/new-jira-cloud-and-trello-bots-now-support-buttons-cards Wed, 06 Nov 2019 00:00:00 GMT
<![CDATA[Using Websockets with the Webex JavaScript SDK]]>

Most developers who have created applications for Webex are familiar with the concept of Webhooks. Webhooks are registered on resources like ‘messages’ or ‘memberships’ to notify applications of events on these resources. When the registered event has occurred - for example a message was created or a membership was deleted - an HTTP POST event with a JSON payload is sent and your application can react to it accordingly.

When your application runs as a web server using a publicly-accessible URL, you don’t need to do much else beyond creating a webhook and having an app running at the webhook's targetUrl to process the webhook payload. This approach can be a problem though if your app needs to run behind a corporate firewall or in restrictive environments. To get around this problem, we recently introduced functionality in the Webex JavaScript SDK that allows applications to "listen" for Webex Teams messaging events using websockets, a technology that does not require a web server running on a public IP address.

Websockets are persistent connections established over HTTP that allow direct communication between servers (the Webex API in this case) and clients (the Webex JavaScript SDK). In this post, we will walk you through creating and using websockets to listen for events sent from Webex.

Websocket example

Websockets are not created by sending a POST request to the API like you would to create a webhook. Websockets are created programmatically with the help of the JavaScript SDK, as they're a unique concept that requires additional behind the scenes setup.

Websocket listeners can be created for memberships, rooms, or messages. Each of these resources has a listen() method in the JavaScript SDK, which you need to call in order to start your websocket. Once the listener is started, you can specify the type of event you would like to be notified about, by calling the on() method. As mentioned earlier, there is no need for a targetURL, like you need for a webhook, because the events from the server are not sent via HTTP. Instead, they're routed through the websocket, and any on() handlers you have registered for the event are called directly by the SDK.

Applications which use the Webex JavaScript SDK can make use of websockets today! Additionally, support websockets has been added to the Node Flint framework.

If your application isn't written in JavaScript, don't worry, you can still take advantage of websockets. In the following sections, we will go through each step of creating a node.js based websocket listener app, built specifically to forward Webex events to another locally running application. In this sample, we will listen for "message:created" events and forward them to a specified localhost/PORT. On the other side of it, we will have a sample Java app listening on localhost/PORT, interpreting the request and sending a reply to the room the message was sent from.


The node.js app

Before getting started with websockets, make sure you have everything that's needed to get up and running with Node.js and NPM - more information can be found in the Node.js SDK documentation and the JavaScript SDK's GitHub repo. Once you have that covered, go the hookbuster example repo and follow the instructions for installation.

The Java app

Our app uses Maven to build the project, so you will need that set up before you can run the example. You will also need Java 1.6 or higher installed. Once both are functional, open the GitHub repo and follow the instructions to install and run it.

Everything else

You will also need a bot access token (it's much easier and simpler to test with a bot token vs an integration token accessing your personal data). Even though you won't need the token in the application code itself, it will be necessary later to run the demo. To create one, see our Bots Guide and hang onto the access token for now.

Creating a Websocket listener -- the node.js app

Step 1: Authentication

Once the node.js app is up and running, per the instructions mentioned in the Github repo earlier, you'll need to provide it with an access token. This will be entered in the console and we need to use it to make the demo functional. The token is then used to initialize a Webex object, which is used to communicate with the Webex API. Here is the code where we retrieve the access token provided in the Console:

function _initializeWebex(accessToken) {
    webex = Webex.init({
        credentials: {
            access_token: accessToken

To make sure the access token is valid, we do a call to the Webex API's /people/me endpoint:

return new Promise((resolve, reject) => {

    webex.people.get('me').then(person => {

    }).catch(() => {
            reject('not authenticated');

We use this call to do the validation because everyone has access to view the "person" associated with the token they're using; it will rarely fail for any other reason besides the access token being invalid.

Step 2: Start listening

The app will then ask for a port that it will use for forwarding the incoming POST requests; in our example, we will use port 5000 but you can set that to whichever port you prefer.

After that, we will be prompted to select our resource and event. We will select messages and created, respectively. This will start the websocket listener and it will then listen for incoming messages. Please note - only messages where our bot is mentioned will be triggered; this is because bots are restricted and can only access messages where the bot is explicitly mentioned. Here a screenshot showing both steps 1 and 2:

Hookbuster example

This is the node.js code triggered by the above console commands for the resource and event selection:

webex.messages.listen().then(() => {

    //logging a formatted info message in the console
        'listener is running for ') +
        fonts.highlight(` ${resource.toUpperCase()}:${event.toUpperCase()} `)

    webex.messages.on(event, request => {

        let request_string = JSON.stringify(request);


}).catch(reason => {

Step 3: Forward the request

Make sure the Java application for the bot is also running, and then send a simple message to the bot via Webex Teams. Since 'hello' is all our Java bot is built to understand, we will only send that command. We're sending the test via a group space, but a direct message would work as well:

Webex Teams message

As soon as the message is posted, the server triggers a POST request, the same way it would for a webhook. The difference is, instead of a public targetURL, the message is sent to our websocket because we registered a listener for all messages created for our bot (we told the system to listen for our bots messages specifically, when we entered our bot access token in the node.js app earlier). Once the message reaches our running code, it is directly forwarded to localhost:5000, as shown below:

function _forwardRequest(request) {

    //logging info to the console
    console.log(fonts.info('request received'));

    //gathering some details
    const options = {
        hostname: 'localhost',
        port: specifications.port,
        method: 'POST',
        headers: {
            'Content-Type': 'application/json',
            'Content-Length': request.length

    //creating the forward request
    const req = http.request(options, res => {
        console.log(`statusCode: ${res.statusCode}`);

    req.on('error', error => {

    //sending the request

    console.log(fonts.info(`request forwarded to localhost:${specifications.port}`));

Hookbuster sample output

Step 4: Stop listening

This might seem like we're getting a little ahead of ourselves, but it is important to note - if we do not clean up the listener after it is no longer needed, we might run into trouble later. This is why our node.js app stops all listeners once you exit the app. The following code handles the clean up process:


Listen to incoming request -- the Java bot application

Step 1: Authentication

Just like our node.js websocket listener app, our Javabot application needs an access token to function. After you start up the app, it will ask for the token. Here we use the same bot token as before, because we want to post our simple replies with the same identity. After entering the token, it is verified with the below code:

private static boolean verifyAccount(String accessToken) {

    boolean isValid = false;
    Bot bot = new Bot(accessToken);

    try {
        Console.printInfo("Verifying account");
        Person me = bot.getMyDetails();
        isValid = true;
        Console.printInfo("Account verified as " + me.getDisplayName().toUpperCase());

    } catch (Exception e) {
        Console.printError("Access token invalid");

    return isValid;

The verification is done by our Bot object, which is actually a wrapper for the Java SDK's Spark object:

public Person getMyDetails() {
    return spark.people().path("/me").get();

Step 2: Start listening

The only other parameter needed for our Java app is a port to listen on. We will use the same 5000 port, that we used with the node.js app.

This is all we need to start listening for incoming requests on localhost:5000. With the parameters gathered and verified, we can now instantiate the socket and begin accepting incoming messages using the following code:

public void run() {

    Console.printInfo("Service listening on localhost:" + port);

    try {
        ServerSocket serverSocket = new ServerSocket(port);

        while (true) {

            try {
                //waits for incoming request
                Socket socket = serverSocket.accept();

                JSONObject requestBody = getRequestBodyFromInput(socket);

            } catch (Exception e) {
    } catch (IOException e) {
        //socket already in use
        Console.printError("Service not running");

Here is a screenshot showing the Console workflow for the above code:

Javabot example output

Step 3: Evaluating the request

Once we receive our "hello" message from the node.js app, the request is interpreted using the below code:

private void evaluateRequest(JSONObject requestBody) {

    //print info to the console
    Console.printInfo("Request received");

    String resource = (String) requestBody.get("resource");
    JSONObject data = getDataObjectFromJson(requestBody);
    String roomId = (String) data.get("roomId");

    if (resource.equals("messages")) {
        String messageId = (String) data.get("id");
        Message message = bot.getMessageById(messageId);

        if (!message.getPersonEmail().contains("@webex.bot")) {
            //split the message along spaces
            String[] trimmedMessage = message.getText().split("\\s");
            //convert the message array into a searchable list
            ArrayList<String> messageList = new ArrayList<>(Arrays.asList(trimmedMessage));

            if (messageList.contains("hello")) {

Step 4: Sending a reply

The Java SDK includes prebuilt methods we then call to send the actual reply back to the space/room where the original "hello" originated:

void sayHello(String roomId) {

    Message message = new Message();
    message.setMarkdown("hello there \uD83D\uDC4B" );

This is how it looks like, back in Webex Teams:

Webex Teams sample message - hello

If you have any questions, please don't hesitate to contact our Webex Developer Support team.

https://developer.webex.com/blog/using-websockets-with-the-webex-javascript-sdk https://developer.webex.com/blog/using-websockets-with-the-webex-javascript-sdk Thu, 26 Sep 2019 00:00:00 GMT
<![CDATA[Meet the New Webex Browser SDK]]>

Harnessing the power of Webex Meetings, this new SDK plugin allows you to create and join Webex Meetings from your browser with no external plugin required!

The SDK team has been hard at work taking what we've learned from the original "phone" SDK plugin and expanding the features into the new "meetings" plugin.

New and Improved Capabilities

  • Create and join audio and/or video meetings by email address, SIP address, or PSTN number
  • Meeting and event controls
  • Audio and video meeting control
  • Maximum bandwidth configuration
  • View shared content
  • Share screen/application from Chrome and Firefox
  • Device controls (get device list, send PIN, pair)
  • Device search
  • Personal Meeting Room (PMR) support
  • Move media
  • Moderator controls

And more features on the way!

Quick Start

Interested in getting started with Webex Meetings? We've got a quick start guide on our developer portal: https://developer.webex.com/docs/sdks/browser/getting-started

Goodbye SDK's "Phone" Plugin

Are you a current user of the Webex Browser SDK making calls with the "phone" plugin? This plugin has been deprecated and will no longer be supported.

Don't worry, we've got you covered with the upgrade guide.

Getting Support, Providing Feedback

This plugin is in active development, so if you're stuck or spot something not working correctly, contact the Webex Developer Support team!

https://developer.webex.com/blog/meet-the-new-webex-browser-sdk https://developer.webex.com/blog/meet-the-new-webex-browser-sdk Fri, 16 Aug 2019 00:00:00 GMT
<![CDATA[It's here: Buttons and Cards for your Webex Teams Apps]]>

We're making it easier for Webex Teams users to interact with your bots and integrations. Complex interactions with bots can be difficult to build and difficult for your users to use. To collect information from users, developers often rely on complicated command line syntax, multi-step wizards, or natural language input, but sometimes nothing beats point and click. Today we’re releasing Cards for bots, allowing your applications to send the user buttons, form fields, images, and rich formatting.

We’ve been asked a lot for buttons in messages, but we wanted to go a step further. The forms you can build with Cards include buttons for sure, but also drop-down lists, radio buttons, and text fields. You can format messages with columns and images. You can use a button on one Card to open up another Card.

Sending a message with a Card is just like sending any other message. You specify the roomId or the Person to send to, include your content, and POST it to /v1/messages like any other message. Cards are created using a JSON grammar called Adaptive Cards. Responses to your cards are delivered as a webhook, just like you get new messages delivered today.

Adaptive Cards was created by Microsoft and they opened the framework for other messaging tools to use. We’re leaning on existing standards for Cards by adopting the Adaptive Cards framework version 1.1. This way, you can take advantage of the existing rich toolset for designing and debugging your cards. Check out the Adaptive Cards documentation and interactive card builder for in-depth understanding of all the elements and how to construct your JSON structure.

This feature is available today for new and existing applications. Both the desktop and web Webex Teams clients can display Cards, with mobile applications, widgets, and SDKs support coming soon. Look for more in-depth training sessions and tutorials on this in the future.

Give it a shot. Refer to our getting started guide for Cards. You can now build apps that let your users do expense approvals, polls, create or update tickets and a whole lot of use cases right within Webex Teams in just few clicks.

https://developer.webex.com/blog/new-buttons-cards-webex-teams https://developer.webex.com/blog/new-buttons-cards-webex-teams Tue, 06 Aug 2019 00:00:00 GMT
<![CDATA[How Approved Contact uses the new Meeting Details API]]> Last week we introduced the capability to programmatically get the Webex meeting join information for a space via the Space Meeting Details API. Before now, you were only able to get the SIP video address of the space. Not anymore. Now you can get much more: the Webex meeting URL, dial-in phone numbers, and the video address. Meeting attendees can use the Webex meeting URL to quickly join the meeting from any client. There are still many people that join meetings by dialing in over the phone. And why not? PSTN connectivity still works great. And for those users that want to join via VoIP, or a video application or system, the video address to join the meeting is also available.

The API works by adding /meetingInfo to any rooms resource. Imagine you have an existing API call that looks like this:

GET https://api.ciscospark.com/v1/rooms/S0xMWU5LTliOWUtNzd

...and has a response of...

      "id": "S0xMWU5LTliOWUtNzd",
      "title": "Meeting Info blog post",
      "type": "group",
      "isLocked": false,
      "lastActivity": "2019-06-18T15:38:04.846Z",
      "creatorId": "DAzYi0zZTY5ZDc2ZTZjNzg",
      "created": "2019-06-13T16:41:56.827Z"

If you'd like to get the space's meeting information, you can add /meetingInfo to the end of that API call:

GET https://api.ciscospark.com/v1/rooms/S0xMWU5LTliOWUtNzd/meetingInfo

...and you'll get a response that looks like this:

  "roomId": "S0xMWU5LTliOWUtNzd",
  "meetingLink": "https://cisco.webex.com/m/a32160d6-d0fd",
  "sipAddress": "5559999@cisco.webex.com",
  "meetingNumber": "5559999",
  "callInTollFreeNumber": "+1-866-432-9903",
  "callInTollNumber": "+1-408-525-6800"

The meeting information you get from the API is exactly the same as a user sees if they open up the Schedule activity menu in the Webex Teams space.

Exciting? Let’s see what our friends at Approved Contact did with this new meeting information. We all know how challenging, painful, and frustrating it is to schedule a meeting with users in different companies. Users can’t see each others’ calendars and there is always a constant back and forth of sharing available times to decide on a time that works. Approved Contact is doing some very interesting things to solve that problem.

We are very happy to be a part of their solution. First, you add the Approved Contact bot to a space. The bot takes you through the flow of finding a suitable time slot in all the users’ calendars. It includes the detailed meeting information of the space in the calendar invite. Guess where it gets the meeting information from? The new meeting information API. “With Teams now making the meeting info available via a REST API, we have allowed users of our Calendar bot to schedule a meeting in Cisco Webex Teams at the perfect open time for everybody in the space.” Nathan Yorke, CIO – Approved Contact. “Scheduling meetings with a group of people could take days, but you can now do it in a few minutes.”

https://developer.webex.com/blog/how-approved-contact-uses-the-new-meeting-details-api https://developer.webex.com/blog/how-approved-contact-uses-the-new-meeting-details-api Tue, 18 Jun 2019 00:00:00 GMT
<![CDATA[Did you see the new API features we announced at Cisco Live?]]>

This week was Cisco Live in San Diego. 25,000 of our closest friends were hanging out in San Diego. You should come next year, it’s pretty awesome.

Webex was on display in a big way. Hotel room keys (shown above) featured Webex. The new Webex experience was a huge portion of the exhibit hall and it was always crowded.

Developers, we’ve got you covered as well. We unveiled what’s the most extensive set of APIs since we started as Spark for Developers three years ago.

Look for in-depth blog posts in the coming weeks that show you detailed samples and help for everything we announced this week.

Today, here are some details on some of the biggest things we’re shipping.

One of the more popular requests we’ve gotten is for meetings APIs for teams. Every space has a persistent meeting attached to it, but there’s been no way to get the meeting URL or the dial-in info for that meeting through code.

The Meetings Info API, available to everyone starting today, puts the meeting information for every space into a REST API. Add /meetingInfo to the end of any room API URL and you’ll get the same meeting information that you see in the Teams client.

Space Meeting information

GET /v1/rooms/...zYWY1NDEw.../meetingInfo

  "roomId": "...zYWY1NDEw...",
  "meetingLink": "https://go.webex.com/m/8a744c15-1c35...",
  "sipAddress": "157504757@go.webex.com",
  "meetingNumber": "157504757",
  "callInTollFreeNumber": "1-877-668-4488",
  "callInTollNumber": "+1-415-655-0000"

When building a bot, a conversational user interface through chat is great, but sometimes nothing beats presenting a form, some buttons, and maybe a graphic for someone to interact with. Our new support for the open Adaptive Cards format gives you just that.

Adaptive Card example

Being tested now by selected developers in our Early Feature Trial program, Adaptive Cards lets your users interact with your bot's messages in a graphical user interface. We've joined Microsoft's efforts to create a standard for these sorts of cards, ensuring that you can take advantage of the wide application and tooling support as Adaptive Cards grows in popularity.

We also showed off Cloud XAPI. Developers today can send commands to our Room Devices, access their sensors, and manage configurations using the popular XAPI, but the application needs local network access to connect to the device. The Cloud XAPI allows developers in our Early Features Trial program to use a secure HTTP channel to use the XAPI remotely over the internet for any cloud-registered device. Developers can search their devices, get device details, generate activation keys, and even migrate an on-premises device to the cloud while preserving key device settings. We'll be making Cloud XAPI generally available to all organizations and developers shortly.

When you hear Webex, you think meetings; and no wonder. According to Synergy Research, more people use Webex meetings than all other vendors combined. So a huge set of API announcements wouldn't be complete without something new in Meetings APIs.

This week we previewed the upcoming REST Meetings APIs. Webex has a robust set of XML-based APIs already, but they function differently than the modern SaaS developer expects an API to work. So we're moving into the REST world with this new set of APIs. Gone are the days of separate Meetings and Teams APIs. One API with unified user management, OAuth for everything, and core concepts that apply whether you're uploading a file to a Webex Teams space or scheduling a meeting for your quarterly board meeting.

The first release of the Meetings API gives you the ability to schedule, update, and delete Webex Meeting Center meetings, to manage invitees of meetings, and to manage recordings of your meetings.

POST /v1/meetings
Authorization: Bearer 5d042160a3382f45

  "title": "Project Fancy Pants",
  "start": "2020-05-31T20:30:00-07:00",
  "end": "2020-05-31T21:30:00-07:00",
  "timezone": "America/Los_Angeles",
  "attendees": [
       "email": “alice@example.com", 
       "displayName":"Alice Hyatt"
     {"email": “carl@example.com"},
     {"email": “susan@example.com"}
  "enabledAutoRecordMeeting": true

The Meetings API is available for Early Feature Trial now. If you'd like us to consider you for Meetings API access, email a description of your use case to devsupport@webex.com and we'll get back to you in short order.

We talked about a lot of APIs this week. Stay tuned here for some upcoming blog posts with details on APIs for Partner Admin, Policies, a websocket interface to Webex events, Teams read receipts, and a websocket interface for XAPI.

https://developer.webex.com/blog/did-you-see-the-new-api-features-we-announced-at-cisco-live- https://developer.webex.com/blog/did-you-see-the-new-api-features-we-announced-at-cisco-live- Fri, 14 Jun 2019 00:00:00 GMT
<![CDATA[(Re)Introducing MindMeld: Webex's Open Source Conversational AI Platform]]>

MindMeld is the conversational AI platform that powers Webex Assistant and Cisco's web site search. This week, we released it as an open source framework for anyone building state-of-the-art conversational applications. The platform is easy-to-use for beginners learning to build conversational assistants, and flexible and powerful enough for advanced use by machine learning experts—making it an impressive alternative to existing solutions.

What is MindMeld?

MindMeld is a full stack conversational AI platform that allows developers to build domain-specific conversational applications. It’s a python-based framework that leverages advanced machine learning (ML) algorithms from libraries like Scikit-learn and TensorFlow to understand human language and a sophisticated information retrieval-based engine to provide domain expertise to the client.

There are several key differences between MindMeld and other cloud AI platforms like DialogFlow and Lex:

  • MindMeld provides APIs that build state-of-the-art ML models for language understanding. These models are highly configurable based on the customer's application.
  • Customers don't need to upload data to a cloud environment. The platform runs on the device, so the customer owns their own data.
  • It natively integrates with a knowledge base built into its platform on-device, enabling the development of compelling domain-specific conversational applications.
  • It provides a sophisticated dialogue state management system that intuitively handles context switches in multi-turn conversations.
  • It provides the ability to recover from automatic speech recognition transcription errors by isolating and resolving entities from multiple transcript hypothesis in a phonetically accurate manner.
  • It supports intelligent entity grouping similar to semantic parsers.

MindMeld also has key differences to other open-source AI platforms like RASA, especially since the platform natively supports textual/voice-based entity resolution and knowledge-base management, which are components not packaged in other open source platforms.

The MindMeld platform architecture contains four main components:

  • The natural language processor contains all the classifiers and resolvers to understand human language
  • A knowledge base containing all the domain-specific objects for a particular application
  • A dialogue manager that handles dialogue flows
  • The application manager, which interfaces input/output with various external services.

Architecture of the MindMeld platform Architecture of the MindMeld platform

Who uses MindMeld?

MindMeld is the technology behind Webex Assistant, a voice assistant that enables collaboration across Webex Board and Room Kit devices. In addition to Webex Assistant, MindMeld also supports language understanding components of Cisco.com search (with more than a million search queries a month) and its affiliated intranet search sites. Cisco partners and external developers are using MindMeld to build successful deep-domain conversational AI agents.

We built MindMeld for data scientists, ML practitioners and software developers who need to build and own the entire conversational AI stack, from the ML models that understand human language to the information retrieval engine needed to resolve entities to their canonical form.

We often see developers transition to the MindMeld platform after trying DialogFlow's narrow vocabulary intents and more basic chat capabilities. MindMeld provides greater configurability, allowing for classifiers that are tailor-made for the specific application. The knowledge base gives developers greater control of the quality of relevant business objects returned to the user.

Where can I learn more?

Visit MindMeld.com to learn more and start building your own conversational application. To help you get started, example applications are available with all the necessary machine learning training data, dialogue state handlers, and knowledge based retrieval logic. You can also learn how to integrate a MindMeld bot with Webex Teams.

An interaction with the food-ordering bot on Webex Teams An interaction with the food-ordering bot on Webex Teams

https://developer.webex.com/blog/mindmeld-webex-open-source-ai https://developer.webex.com/blog/mindmeld-webex-open-source-ai Fri, 10 May 2019 00:00:00 GMT
<![CDATA[Updating your listing on the Webex App Hub]]> When our application directory Webex App Hub first debuted as the Cisco Spark Depot, the only way to add an application was to send us the details and we'd add it for you. Likewise, updating the details meant a request to our support folks, who would make the changes for you.

Since that time, we've opened up access to let you manage the content for your own bots and integrations. Publishing an application is as simple as filling out some fields on a web form. We can review and approve new applications much more quickly, reducing the friction you experience when promoting your applications.

App Hub Update Tool

This same self-serve content management lets you update applications you've already published. Say your App Hub description is looking a little dated because it still says it works with Cisco Spark or your screenshots don't match your application anymore. You can update it yourself by visiting the My Apps page and clicking on the app you want to change. Every App Hub content field shows up right on that page for you to change.

For the most common changes, you can make them without any downtime or further review. Editing these fields will immediately update your App Hub listing. The other fields will require a review by Cisco before your listing is updated. During this review period, your App Hub listing will be removed.

Fields that can be immediately updated are your Description, Tagline, the Redirect URL for Integrations, and your contact name and email. If you change one of the other fields, we will unpublish your application while Cisco reviews it. Your application will still work, but the listing won't appear on the App Hub until we approve the changes.

If you want to minimze the time your application changes are under review, you can email your proposed changes to us ahead of time. Let us know what edits you're going to make and we'll let you know if you'll need to fix anything. That way, when you make your App Hub edits, we'll be ready for them and can quickly verify your updates and re-publish your application. To take advantage of this option, email devsupport@webex.com with the list of fields you're changing and what changes you're planning on making.

https://developer.webex.com/blog/updating-your-listing-on-the-webex-app-hub https://developer.webex.com/blog/updating-your-listing-on-the-webex-app-hub Fri, 05 Apr 2019 00:00:00 GMT
<![CDATA[Bulk Actions using the Webex Teams API]]> Let’s say we need to make multiple similar requests to the Webex Teams API. Maybe you want to send the same message to multiple Spaces or edit the same attribute of various users in your org. Currently, you’ll need to make those requests one at a time. This post will walk through both editing and deleting multiple users in an organization, and removing a list of rooms as well, to show you how to loop through a list of items to achieve a bulk action. You can then use this method to handle the majority of bulk actions with some relatively minor changes.

Since we’re first discussing editing and deleting multiple users from an organization, you’ll need to have admin privileges in order to run this particular portion of the example. If you modify the code for less restricted actions, like deleting rooms in the second portion, admin privileges won’t be needed. Also note that once a user is deleted, there is no way to restore that user, so a new user will need to be created if you delete any users by mistake (probably best to run this on a test org before implementing it on your real org).

This demo uses the requests library for python, so you may need to install that if you have not done so already.

One of the examples below is written for Python 2, and the other for Python 3, so keep that in mind as you go along. Really, the only difference is how the quote function is imported. In Python 2, use from urllib import quote or in Python 3, it's from urllib.parse import quote.

Updating a List of Webex Teams Users

The CSV file viewed in Excel

We’ll start by editing a list of people. Let’s say the email domain of your company is changing, so you want to update all of your user accounts to reflect this. This example assumes that you have all of the email addresses that need to be changed, in a single column CSV file, like this example CSV.

Note that the first row, where headers typically go, is intentionally left empty.

This tutorial refers to the EditDeletePeople sample application found on GitHub. You might want to open that repository and follow along. We'll note the correct line numbers as we go.

There are several scripts in the sample application. This portion of the tutorial focuses on edit_people_emails_from_csv.py.


The code requires four small changes to configure your application. (lines 20 through 23 if viewing from the GitHub repo). The changes required are:

bearer = "ADMIN_TOKEN" # A Oauth token for a Webex Teams Admin user
filepath = "/full/path/to/people_emails.csv"
from_domain = "@domone.com"
to_domain = "@domtwo.com"
  • bearer must be an OAuth token for a Webex Teams admin user.

    If you are an admin, for testing purposes you can sign in to the developer portal and copy your token from the section, “Your Personal Access Token,” found here

    Note the developer portal token currently only lasts 12 hours, so if you want this to be a more permanent solution you can run without manually updating the token each time you run it, you want to build an integration

  • filepath must be either a full/absolute filepath or a relative filepath to the CSV from the location of the python script on your machine.

  • from_domain is the current domain of the user email addresses. For example, if the new email looks like john@oldcorp.com you would enter @oldcorp.com.

  • to_domain is the desired domain of the user email addresses. For example, if the new email looks like john@newcorp.com you would enter @newcorp.com.

How it works

Starting at line 25, we read the emails in the file here:

lines = []
with open(filepath, 'r') as f:
    lines = f.readlines()

then in line 32 we loop over each email in the .csv file:

for line in lines[1:]:

For each email address, we look up the person details from Webex Teams with the sendGET function. This also gives us the personId, which we need to make any changes to a person. Then in line 50, we edit the email address to use the new domain and update the person detail dictionary:


Then we tell Webex Teams to update the person with the sendPUT function. The bulk of this effort takes place between lines 39 and 54.

    new_email = person_email.replace(from_domain, to_domain)
    data = person_details[0]
    result = sendPUT(edit_url.format(person_id), data)

The example code also handles API throttling responses in the bottom third of the code. More details about that can be found in our Retry-After handler code sample.

Deleting a List of Webex Teams Users

Now let’s say we have people we want to delete from Webex Teams. Assuming we have a CSV file setup in the same way as above, our code will look very similar, and even a little shorter. We’ll trade out our sendPUT function for sendDELETE.

Take a look at the script delete_people_from_csv.py. Note the differing import of the quote function, so that this code will work for Python 2 instead.

This time, you’ll only need to edit bearer and filepath on lines 20 and 21.

In summary, this code is almost the same as the code to edit people. We still have to look up the personId using the email address and our sendGET function. Then we use that ID to delete the person with our sendDELETE function.

Deleting a List of RoomIds from Webex Teams

What if you already have a list of IDs? We can simplify this even further and show how you could use the same process to delete a list of rooms. Assuming your roomIds are in a CSV in the same format as the emails from the previous example, we can run the following (also found in delete_rooms_from_csv.py:

import requests

def sendDELETE(url):
    response = requests.delete(url,
                           headers={"Accept" : "application/json",
                                    "Authorization": "Bearer "+bearer})
    return response

bearer = "BEARER_TOKEN" #your bearer token
filepath = "rooms.csv" #each roomId on a new line.

lines = []
with open(filepath, 'r') as f:
    lines = f.readlines()

delete_url = 'https://api.ciscospark.com/v1/rooms/{0}'
failure = False
for line in lines[1:]:#basically, this is 'for every ID in the list'
    room_id = line.strip('\r\n')
    print("RoomId to delete is: {0}".format(room_id)) #we'll just print this roomId.
    print("Deleting room...")
    result = sendDELETE(delete_url.format(room_id))
    print("Delete result (204 is success): {0}".format(result.status_code))

Once again the bearer and filepath will need to be changed, but otherwise, this code is even shorter than the others. It doesn’t require a sendGET at all, because we’re starting with the IDs. That means we can go right into the delete action.

Since we’re using a list of IDs, this could be easily translated to pretty much any Webex Teams API endpoint, whether it be deleting rooms, memberships, or people. All that would really need to be changed is the delete_url.

The code

The full code and sample CSVs for everything discussed in this post can be found in our Webex Samples GitHub repository.

https://developer.webex.com/blog/bulk-actions-using-the-webex-teams-api https://developer.webex.com/blog/bulk-actions-using-the-webex-teams-api Wed, 27 Mar 2019 00:00:00 GMT
<![CDATA[Webex Platform Disabling TLS 1.1]]>

Beginning April 27, 2019, the Webex platform will require that API clients use the Transport Layer Security (TLS) 1.2 protocol. To align with industry best practices for transport security, the TLS 1.1 encryption protocol will be disabled on all endpoints. TLS 1.0 was disabled on March 17, 2018.

Our internal telemetry of API connections indicates that very few API clients are using TLS 1.1. To prevent any service disruption between your applications and the Webex platform after April 27, ensure that your applications' server operating system, libraries, and frameworks support TLS 1.2. Consult the documentation for your applications' libraries and frameworks to ensure that they support TLS 1.2.

If your applications do not automatically use TLS 1.2, you will need to explicitly configure it. Please see below for information about common languages and libraries:


Java 1.7: TLS 1.2 is supported, but it needs to be explicitly enabled when creating SSLSocket and SSLEngine instances.

Java 1.8: TLS 1.2 is the default.

See https://blogs.oracle.com/java-platform-group/jdk-8-will-use-tls-12-as-default for more details.


Ruby uses the system's OpenSSL package. TLS 1.2 support was added and made the default in OpenSSL 1.0.1.

You can check the version of OpenSSL that your Ruby links against by running: ruby -ropenssl -e 'puts OpenSSL::OPENSSL_LIBRARY_VERSION'


Python also uses the system's OpenSSL package. TLS 1.2 support was added and made the default in OpenSSL 1.0.1.

You can check the version of OpenSSL that your Python links against by running: python -c 'import ssl; print(ssl.OPENSSL_VERSION)'

.NET Framework

See https://docs.microsoft.com/en-us/dotnet/framework/network-programming/tls for details about TLS in .NET applications.


Support for TLS 1.2 was added in cURL 7.34.0.

If you have any questions, our Webex Developer Support Team is available to help. Please contact them with your question or concern.

https://developer.webex.com/blog/webex-platform-disabling-tls-1-1 https://developer.webex.com/blog/webex-platform-disabling-tls-1-1 Fri, 15 Mar 2019 00:00:00 GMT
<![CDATA[Creating a FAQ Bot in zero lines of code with Dialogflow and Webex Teams]]>

Traditionally creating a chatbot requires an advanced level of programming and technical ability. At Cisco, we have drastically lowered the barrier to entry for creating Webex Teams chatbots by integrating Webex Teams with a service from Google called Dialogflow. You can now use Dialogflow to create a question and answer bot without needing to do any programming at all.

Want to see what the finished product looks like? Add our pre-made FAQ bot by adding "faqdevbot@webex.bot" to a Webex Teams space and have a play!

How it works

Dialogflow uses a feature called ‘Knowledge’ to automatically create a chatbot for Webex Teams that can instantly respond to questions. All you have to do is provide Dialogflow with a text file containing the questions and answers you want the bot to respond to.

Create a Webex Teams bot

Before we can get started with Dialogflow we first need to create a bot entity on Webex Teams. To do this create a new bot and fill in the bot details.

Take note of the bot Access Token, we will need this later. Copy it to a text file, the web site won’t show it to you again.

Integrating Webex with Dialogflow

These steps walk you through getting started with Dialogflow and integrating Dialogflow with your new Webex Teams bot.

Create Dialogflow account

Firstly, you will need a Dialogflow account. Follow these instructions to signup.

Create Dialogflow agent

Next, you’ll need to create a Dialogflow agent (This is how Dialogflow refers to an individual chatbot).

  1. Within the Dialogflow console, click Create agent in the left menu and fill in the details for your new agent.

  2. Click Create.

Add Webex Teams integration to Dialogflow agent

To make Webex Teams and Dialogflow talk to each other we need to add the integration from within the Dialogflow Console.

  1. Click on Integrations in the left menu.

  2. Turn on the Webex Teams/Cisco Spark integration (Cisco Spark is the old name of Webex Teams).

  3. Add the Access Token for the Webex Teams bot you created.

  4. Click Start

Your Dialogflow agent is now linked with your Webex Teams bot.

Create a chatbot question list

The chatbot needs a list of questions and answers that must be uploaded to Dialogflow for the agent to digest and answer questions from.

Dialogflow can accept the question list as either a simple text file or an FAQ webpage linked directly from your company website.

Your Question list is on a web page

If you have your questions and answers already on a publicly accessible web page, all you need is the web address for the FAQ page. The chatbot will import your questions and answers from it.

Create a Question list as a text file (.csv)

The question list should be a spreadsheet of questions and answers with questions in the first column and answers in the second column. This is where you can get creative!

After you’ve compiled the questions the question list must be exported as a CSV file (comma separated variable file). To do this from Microsoft Excel: File Save As File Format: CSV.

Note: There should be no headings in the spreadsheet.

CSV file containing questions and answers

Create Dialogflow knowledge base from the question list

We will now add the question list to Dialogflow’s Knowledge feature which turns the question list into a format our bot can search and use.

Turn beta features on

As of writing this (February 2019) the knowledge feature is still in beta phase, so we need to enable beta features from within Dialogflow.

  1. Click on the settings cog in the left menu of the Dialogflow console.

  2. Turn on Beta Features and APIs.

Create the knowledge base

This is where the question list will be uploaded to and stored.

  1. Click on Knowledge in the left menu of the Dialogflow console.

  2. Click Create Knowledge Base.

  3. Enter Knowledge base name and click save.

Add knowledge document

We now want to add our question list to the Knowledge Base we have created.

  1. Click create the first one to create a knowledge document.

  2. Complete the new document form (Choose FAQ as the Knowledge Type).

    a. If using a question list file: Set the Mime Type to text/csv, select Upload file from your computer and upload the question list .csv file.

    b. If using an existing FAQ webpage: Set Mime Type to text/html, select URL and enter the web address of the FAQ webpage.

  3. Click Create.

  4. Under Responses, click Add Response (leave these details as the default prepopulated values).

  5. Click Save.

You have now uploaded the questions to Dialogflow. Click on View Detail to see a list of each question and answer you have created.

Example question details in Dialogflow

Deploy the chatbot

The chatbot is now up and running. To talk to it you can use the bot's email address to add it to a space in Webex Teams and start asking questions!

https://developer.webex.com/blog/creating-a-faq-bot-in-zero-lines-of-code-with-dialogflow-and-webex-teams https://developer.webex.com/blog/creating-a-faq-bot-in-zero-lines-of-code-with-dialogflow-and-webex-teams Thu, 14 Feb 2019 00:00:00 GMT
<![CDATA[The Best of Cisco Live Europe]]>

We had a busy week in Barcelona last week at Cisco Live Europe.

The training sessions and workshops in the DevNet Zone were standing-room-only affairs, with people crowding around to see how to use our latest features, get started with the basics, or just dive deep into something they've already used.

Over in the exhibit hall, we got to see a bunch of new things. Some highlights:

AppSpace on the Webex Board

  • AppSpace using the upcoming Signage Mode on the Webex Board. Super cool to see how a Webex developer is using this to deliver some amazing applications.
  • Hands on with the RoomKit Mini, set up in a small room so we could see how it worked in real-life. One cool feature that's unique in the RoomKit lineup is USB input. Plug your computer in and the Mini becomes a 4k Webcam, complete with speakers and microphone. The Mini even has all the same APIs as its bigger siblings.
  • Jabber Team Messaging mode turns our enormous Jabber customer base into Webex Teams messaging users. The developer angle here is that in a future release the same bots and integrations you've built for Webex Teams will work in Jabber for customers that enable this feature.

We had a great time at Webex After Dark, meeting and hearing from some of the Webex Ambassador Masters over cava and tapas. They talked about how the Collaboration business has changed since they got started in it (it's gotten easier, cheaper, and more ubiquitous), and where they think it's going.

Next up is Cisco Live Australia-New Zealand in Melbourne, March 5-8. Will we see you there?

https://developer.webex.com/blog/the-best-of-cisco-live-europe-2019 https://developer.webex.com/blog/the-best-of-cisco-live-europe-2019 Wed, 06 Feb 2019 00:00:00 GMT
<![CDATA[Visit Webex for Developers this week at Cisco Live Barcelona]]> Cisco Live, our annual customer conference, kicks off the European edition today in Barcelona, Spain and runs through Friday with 830+ sessions, keynotes, parties, and more. If you're in town for Cisco Live, the Webex for Developers team would love to meet you. Here's where you can find us:

All Week

All week long, you can drop into the Walk-In Self-Paced Labs and try your hand at Building Webex Teams bots using business logic templates. You'll find the Walk-In Self-Paced Labs hosted in The Hub in Hall 6.

Stop by the Webex for Developers demo in Cisco's Collaboration Village inside the World of Solutions Tuesday through Wednesday to see demos of how real customers are integrating Webex into their workflows.


You can learn to Embed Webex Messaging and Calling in Your iOS App in our workshop sessions. Jonathan Field will be teaching this popular small-group class four times in Workshop 6 in the DevNet Zone! Come by Monday, Tuesday, Wednesday, or Thursday at 2 PM. You'll find the DevNet Zone in Hall 6.


Product Manager Olivier Proffit will give an overview and coding demo of the Webex Teams Video SDK Tuesday at 11 AM in DevNet Classroom 2.

You can get Hands on with the Webex Teams Guest Access API with Dorin Ciobanu, the software engineer that designed and built the Guest Access API. You'll find this small-group workshop held on both Tuesday and Wednesday at 11 AM in DevNet Workshop 4.

The second running of Jonathan Field's Embed Webex Messaging and Calling in Your iOS App is Tuesday at 2 PM at Workshop 6 in the DevNet Zone.

New to coding? Learn the basics of REST APIs from Adam Kalsey by running some hands-on examples using the Teams API and Postman. You'll find this in DevNet Classroom 3 on Tuesday at 2 PM, Wednesday at 1 PM, Thursday at 9 AM and 4 PM, and Friday at 9 AM.

Tuesday night, join Webex Ambassadors for at party at Webex After Dark, where you can Meet The Masters and hear from some of our most knowledgable Webex users and partners. (Registration required).


Jonathan Field will be presenting Streamlining Real World Use Cases with Webex for Developers on Wednesday at 9 AM in the DevNet Theater in the heart of the DevNet Zone.

One of the engineers behind the Webex Browser SDK, Adam Weeks, will show you how to combine server and client-side Javascript code to build applications with the Webex Teams SDK. This hands-on workshop will be held Wednesday at 10 AM and then again Thursday at 1 PM, both at Workshop 3 in the DevNet Zone.

The second delivery of Adam Kalsey's Intro to APIs and REST is in DevNet Classroom 3 Wednesday at 1 PM.

The third running of Jonathan Field's Embed Webex Messaging and Calling in Your iOS App is Wednesday at 2 PM at Workshop 6 in the DevNet Zone.

If you're not a developer you can still take advantage of the Webex APIs. Johannes Krohn will show you how Wednesday at 2:30 PM in Extending the Collaboration Eco-System using Webex Teams APIs for Non-Developers. You'll find this talk in Hall 8.0, Session Room D138.


David Staudt will show you how to create meetings with a number of Cisco APIs, including Teams in DevNet Zone's Classroom 2, Thursday at 9 AM. DEVNET-1489

The third and fourth deliveries of Adam Kalsey's Intro to APIs and REST are in DevNet Classroom 3 Thursday at 9 AM and 4 PM.

Steve Sfartz will be showing Webex Teams APIs for Admin and Serviceability 1 PM Thursday in DevNet Classroom 1.

Adam Weeks will have an encore of Building Server and Client-side Applications in Javascript with the Webex Teams SDK Thursday at 1 PM at Workshop 3 in the DevNet Zone.

The final running of Jonathan Field's Embed Webex Messaging and Calling in Your iOS App is Thursday at 2PM at Workshop 6 in the DevNet Zone.


The final session of Intro to APIs and REST is in DevNet Classroom 3 Friday at 9 AM.


Phew, that's a LOT. But we're not too busy to chat with you. Have some questions or ideas? Grab one of the team and say hello. Make sure and follow @CiscoWebexDev on Twitter for pictures, updates, and some giveaways at the conference.

https://developer.webex.com/blog/visit-webex-for-developers-this-week-at-cisco-live-barcelona https://developer.webex.com/blog/visit-webex-for-developers-this-week-at-cisco-live-barcelona Mon, 28 Jan 2019 00:00:00 GMT
<![CDATA[ISV Developer Dynamic Signal is now on Cisco’s Global Price List]]>

The Webex Global ISV Ecosystem team is thrilled to add another fantastic developer to Cisco’s Solutions Plus.

Dynamic Signal, a leader in employee communication and engagement, has integrated with Cisco Collaboration with the Cisco Webex API’s making Webex Teams a channel for corporate communications. And, now, Dynamic Signal has been added to the Cisco Global Price List with an annuity offer on the Solutions Plus program - orderable through CCW by any Cisco reseller.

Dynamic Signal has a customer base that includes Oracle, CDW, Samsung, Volvo, Penske, and FedEx. More than 20% of the Fortune 100 trust Dynamic Signal to communicate with their employees through the most effective digital channels. And, Dynamic Signal allows companies to track employee engagement with content - critical in today’s world of frenetic indiscriminate messaging.

For a demo of Dynamic Signal, reach out at https://dynamicsignal.com/, talk to your Cisco reseller, or talk to your Cisco Collaboration sales team.

To get started with your own integration with the Cisco Collaboration Cloud, check out https://developer.webex.com/.

https://developer.webex.com/blog/isv-developer-dynamic-signal-is-now-on-cisco-s-global-price-list https://developer.webex.com/blog/isv-developer-dynamic-signal-is-now-on-cisco-s-global-price-list Wed, 19 Dec 2018 00:00:00 GMT
<![CDATA[How We Build With Webex: Approved Contact]]>

Sure, it’s easy to use Webex Teams and Webex Meetings to connect your remote teammates and geographically dispersed partners. But actually finding that open window to meet? Unless you’ve got a personal assistant with tons of time on their hands, you’re looking at a pretty tedious task.

Good thing Approved Contact has set out to change that.

About Approved Contact

The Approved Contact mission, according to Vice President Marketing Rich Fetter, is simple: to provide “one consolidated view into free/busy time that makes it easier to schedule all your resources for a conference call.”

Here’s how it works: First, users automatically connect their digital calendars (whatever the platform) to Approved Contact. Then, they grant permission for Approved Contact to review their schedules—a step possible even for those have not yet joined the site. Finally, by referencing free/busy times for everyone involved, they determine the best time to meet, quickly and simply.

That second step of granting calendar permission is a subtle but fundamental design point. Like you, the Approved Contact team believes that free time is precious time. That it should be up to you—and not, say, contacts from another organization—to determine how to best spend that time.

And their customers agree, from manufacturers who have to sync with downstream vendors, to insurers and bankers looking to collaborate with individual contributors, to civil servants and education experts who need to share their insights with contacts outside their immediate networks.

Why Webex?

Off of their web platform, Approved Contact uses our APIs for their Webex Teams Calendar bot, which brings calendar comparison and meeting suggestions right into your chosen spaces. For them, the decision to work with Webex was an easy one to make, though this was their very first bot project. Why?

Did you guess that it was because Webex is where the people are? If you did, you’d be right. Our impressive base of users made Webex the perfect place for Approved Contact to start building their bot. Plus, now that it’s been added to the Cisco Global Price List, the team is growing just as we grow.

Numbers aside, Approved Contact was also looking to bridge the gap between Webex Teams and Webex Meetings. And with the bot, they have. Users can now schedule meetings natively form Webex Teams, then jump on a call with their colleagues on Webex Meetings.

The Developer Journey

The foundation of interconnecting calendars already built, the one-person Approved Contact developer team first turned to our REST API to build the bot. Not only their first bot project for Approved Contact, it was also their first time diving into the Webex Teams documentation. Yet it couldn’t have gone any more smoothly.

From start to finish, it took the developer two months to complete the Approved Contact Calendar bot, though not all of that time was set aside strictly for bot work. Looking back on the process, they praised the convenience of being able to call the REST API directly to see raw payloads and full functionality—as opposed to relying on the SDK.

What’s Ahead

Beyond the bot, Approved Contact aims to continue to expand into the future. They’re looking to focus more on voice, text, and chat by further extending the interface, using Webex Teams as the backbone. Artificial intelligence is also on their radar as they explore how scheduling automation can improve relationship management.

To learn more about their work, check out the Approved Contact bot for Webex Teams. Want to get started on your creation? Head over to our developer documentation.

https://developer.webex.com/blog/how-we-build-with-webex-approved-contact https://developer.webex.com/blog/how-we-build-with-webex-approved-contact Wed, 19 Dec 2018 00:00:00 GMT
<![CDATA[The Guests Have Arrived]]>

You asked, and we delivered. Persistent Guests for Webex Teams developers is here! We know you’ve been waiting for it for a long time, so thanks for your patience.

Why did we create Persistent Guests?

With Webex Teams embedded in your mobile app or website, end users get a fantastic integrated calling and business messaging experience with great features. But there was one obstacle: For you to be able to grant users access to that experience, they needed a Webex account. However, some users don’t want to subscribe to Webex. For example, patients using a telehealth app only few minutes a year for a preventive checkup may not want to go through the Webex subscription process. Same with a citizen seeking just a quick interaction with a governmental agency or a consumer reaching out to a retail agent.

With the recent launch of Persistent Guests, people now no longer require a Webex account to get that fantastic integrated experience with another Webex user. (Note that the guest can collaborate only with paid Webex users. You can start with a trial here.)

Let me guide you through this new, powerful solution.

The Persistent Guests solution is a new authentication model that any developer can employ to allow end users to leverage the Webex platform. It gives users access to all the main Webex features, including secured 1:1 or group messaging (including chatbots), documents, and audio-video calls.

The developer generates and manages the user credentials, so the login flow becomes transparent.

With this new solution, you can:

  • Provide a seamless user login experience and avoid the burden of Webex onboarding
  • Make Guests’ histories either persistent (the default) or ephemeral (using our API)
  • Own, manage, and secure Guests’ identities. (Cisco doesn’t have access to the identities.)

This solution can help make a big impact. Learn how New York State can now help people who got hurt on the job with virtual hearings, thanks to the Webex platform and Persistent Guests.

So how do you get started? Simply generate Guest tokens and inject them in your app to grant the end user access to the Webex platform. There are just three steps:

Step 1. Register your Guests issuer on our developer portal. (Your issuer is your backend function that will generate the Guest tokens.) You’ll get a Guest Issuer ID and a shared secret.

Guest Issuer Creation Overview

Step 2. Build your issuer with the Guest Issuer ID and shared secret., (Here are several examples. Please also make sure you read the More Resources section on this page.)

Step 3. Validate your Guest token in the new widget demo. Then embed it in your mobile app or website associated to your users’ sessions.No additional login for them, they will love it !

Have any feedback? We’d would love to hear it.

https://developer.webex.com/blog/the-guests-have-arrived https://developer.webex.com/blog/the-guests-have-arrived Tue, 18 Dec 2018 00:00:00 GMT
<![CDATA[ISV Developer Mio is now on Cisco’s Global Price List]]>

The Webex Global ISV Ecosystem team is thrilled to add another fantastic developer to Cisco’s Solutions Plus.

Mio provides collaboration interoperability – critical for all companies in this complex world of vendors, partners, and customers all using a mix of collaboration platforms. Cisco understands that companies are dealing with this complexity and Mio simplifies this facilitating collaboration in this ever changing environment. Cisco is committed to making collaboration as easy to use for as many people as possible, and Mio plays an important role in this ecosystem.

And, now, Mio has been added to the Cisco Global Price List with an annuity offer on the Solutions Plus program - orderable through CCW by any Cisco reseller.

For a demo of Mio, reach out at https://m.io/, talk to your Cisco reseller, or talk to your Cisco Collaboration sales team.

To get started with your own integration with the Cisco Collaboration Cloud, check out https://developer.webex.com/.

https://developer.webex.com/blog/isv-developer-mio-is-now-on-cisco-s-global-price-list https://developer.webex.com/blog/isv-developer-mio-is-now-on-cisco-s-global-price-list Mon, 17 Dec 2018 00:00:00 GMT
<![CDATA[Emergency Communications with Cisco Webex Teams and Singlewire]]>

You don’t think you need it until something happens. And then, it’s too late. That's why every Cisco customer should look at InformaCast from Singlewire Software.

Singlewire is a leader in the Emergency Management Communications space. Singlewire is on the Cisco GPL orderable through CCW. They are a long time Cisco development partner, a Collaboration Integrator Partner, an early adopter of the Collaboration Cloud API’s, and installed on shipped UC platforms making it super easy to turn on for a customer.

Singlewire has integrated with Cisco Webex Teams by creating a situation space in Webex Teams called the Incident Response Space. In this space the important parties are added to a centralized space for the situation management team to facilitate and coordinate operations for that emergency. From right within the space, Singlewire InformaCast messages can be broadcast. For more information on the Webex Teams integration, check out Singlewire’s video.

Emergency Management Communications has been getting a lot of attention lately with school emergencies being on the news every few weeks. What’s obvious from these stories is that clear communication can make a difference in the outcome. Watch this Singlewire video.

The violence in schools and workplaces is unnerving in large part due to the helplessness one feels when hearing about these situations, and how these stories could fit at random into your lives.

Dealing with violence is where the conversations about Emergency Management Communication always starts and ends, but it’s more than that. Talking with the Singlewire team, they recently shared a story with me about one of their customers, a large manufacturing company. One of the employees on the factory floor was having a heart attack. InformaCast played a key role in getting help to that person, directing emergency responders quickly to the right location, and the employee’s life was saved. Customers end up using the Singlewire platform for communicating about medical emergencies, weather emergencies, and facility emergencies (such as spilled chemicals) on a regular basis.

It’s not often that we work with a partner that has such a moral or ethical value in their mission. It’s a good feeling to support them. We love telling people about Singlewire and giving our customers a great option on how to help improve the outcomes from emergencies that so often seem to be out of our control. At least there are some things we can do to plan for the unexpected.

If you’re a school or a business without an Emergency Mass Notification System and plan, we recommend you check out InformaCast from Singlewire.

Additional resources: https://www.singlewire.com/notification-informacast-and-cisco-webex-teams https://www.singlewire.com/blog/emergency-notification/meraki-camera https://apphub.webex.com/integrations/informacast-incident-response-singlewire

https://developer.webex.com/blog/emergency-communications-with-cisco-webex-teams-and-singlewire https://developer.webex.com/blog/emergency-communications-with-cisco-webex-teams-and-singlewire Tue, 04 Dec 2018 00:00:00 GMT
<![CDATA[What to Know About the New Cisco Webex for Developers Portal]]>

We’re constantly working to improve the Cisco Webex developer experience, from signing up to promoting your apps in the Webex App Hub. With our latest update, we are releasing a refreshed Cisco Webex for Developers portal experience.

This updated portal better equips our team to build powerful new features. It also enables us to share news and resources with developers like you even faster. While many of the portal improvements are on the back-end, there are several that you’ll notice as a user.

Improved Documentation Pages

Among many improvements to the Documentation pages is an updated API Changelog page and a right navigation bar to make it easier to find what you’re looking for within any page. We’ve made a slew of changes to the API Reference pages, adding response properties for every resource and improving the testing experience. We’ve also made it easier for you to copy code blocks.

Redesigned Blog

We think you’ll appreciate the elegant new look and feel of the Cisco Webex for Developers Blog. With four categories to filter content (“Product Announcements,” “How To’s,” “Events,” and “Developer Stories”) you’ll more quickly find the posts you’re looking for. You can even send them to your friends and followers with the new social sharing feature.

Cleaner Organization

To make it easier for you to find the information you’re after, we’ve reorganized the portal content. This update also includes a revised home page and a detailed footer with handy links.

Revamped Tokens

To ensure you don’t accidentally use your personal access token in a production app, we’ve updated the portal to provide you with a new personal access token. This token is valid for 12 hours after your login, and can be copied from the Getting Started page or the API Reference pages for any quick testing needed outside the portal. For production apps, navigate to My Webex Teams Apps to create production tokens.

Updates on the Way

But that’s not all. We have more portal updates coming soon like full-site search, blog and API changelog subscription buttons, embedded feedback widget on every documentation page, easier ways to do OAuth and more guides, use cases and step-by-step tutorials!

Have portal suggestions or other feedback for us? Please send us a message!

https://developer.webex.com/blog/what-know-about-new-cisco-webex-for-devs-portal https://developer.webex.com/blog/what-know-about-new-cisco-webex-for-devs-portal Thu, 08 Nov 2018 00:00:00 GMT
<![CDATA[How We Build With Webex: Vbrick]]>

It’s not hard to understand why video makes for such a powerful way to meet. In today’s world of dispersed teams and on-the-go work styles, video lets you collaborate face to face in real time — for real connections. No wonder it’s become so widespread so quickly.

Yet video can sometimes come with surprising challenges. Sure, it’s simple to turn on video on Webex (Just click the button!), but what if you need to stream your broadcast to other channels? And what happens after the meeting ends? How can you reliably and easily manage and distribute your video?

These are the questions on the minds of IT teams in large enterprises everywhere. That’s because video capture tools tend to by clunky and complicated, while many video management solutions try to do it all — instead of providing the simple editing and speech-to-text abilities most customers are actually looking for.

So, you’ve got your capture and management issues. On top of those, you’ve also got the problem of scale. How do you best distribute high-quality video to thousands of simultaneous viewers?

Bring in Vbrick.

About Vbrick

A longtime Cisco Integrator Partner, Vbrick uses our APIs to enable Webex users to capture, manage, and distribute their videos. As Dan Bagley, Vice President of Technical Sales and Operations, puts it, Vbrick is moving “synchronous video communications to the asynchronous.”

Sounds pretty abstract, right? But it’s not. Just think about all the practical applications.

Imagine you work at the headquarters for a large insurance company that employs many independent agents. It’s up to you to make sure the agents are trained to your company’s standards, but you can’t be there to train each person individually.

So, you broadcast a series of video tutorials. Some agents are able to tune in as they happen, but those who can’t get the content delivered to their Webex video library to review later. They can even ask the Vbrick bot, Rev, to search for the specific videos they’re after.

Why Webex?

For the Vbrick team, the network- and video-centric aspects of Webex set it apart from other, seemingly similar enterprise communication platforms. As Bagley recounts, “It was a natural fit.” It’s why they went with Webex.

And what a productive partnership it’s been. On the one side, the Webex platform gets a big boost from the video capture, management, and distribution capabilities made possible by Vbrick’s bot and integration. (At Cisco, we even use it ourselves!) As for Vbrick? They’ve seen their business grow by leaps and bounds as they’ve landed deals with customers looking for collaboration tech packaged up with powerful video management features.

It’s not just a win-win for Vbrick and Webex. When you consider the customers, it’s a win-win-win.

The Developer Journey

Another win for Vbrick? The super smooth developer journey to build on Webex. “It’s a very developer-friendly platform,” describes Bagley.

Bagley focused on the authentication and documentation aspects of the build. He highlighted how he was able to leverage OAuth when adding users to Webex, enabling them sign in and grab a token.

“It’s a user-centric approach,” Bagley explains “Easy from an architectural perspective.”

What’s Ahead

We’re so excited for what’s next for our partnership with Vbrick. Curious to learn more about Vbrick itself? Take a look back at our previous Vbrick blog post and check out their website, then visit the Webex App Hub to explore the Vbrick Rev bot and integration.

Finally, if you’re feeling inspired to get started on a build of your very own, head over to our Webex developer documentation.

https://developer.webex.com/blog/how-we-build-with-webex-vbrick https://developer.webex.com/blog/how-we-build-with-webex-vbrick Wed, 07 Nov 2018 00:00:00 GMT
<![CDATA[How We Build With Webex: Involvio]]>

Only 59 out of 100. That’s the percentage of college students who will go on to graduate from the same institution where they started. And technically, 59% is a failing grade.

That’s not just a problem for the schools who have invested in their students. As you can imagine, it’s an even bigger problem for the students themselves, many of whom lack the skills and abilities to make their mark in the professional world — and pay off any institutional loans.

But why? Why is this student retention rate so low, how can developers like you help improve it, and what can you learn about this problem that helps inform your future creations?

If you guessed it’s all about student engagement — about students getting involved in their college careers — you’d be right. (You teacher’s pet, you.) And as Involvio has shown, the answer lies in the marriage of big data analytics with real-time, personal connection.

About Involvio

As Involvio Founder and CEO Ari Winkleman points out, for institutions to make an intervention in their students’ lives before they drop out, they first need to know which students are even at risk.

Enter Involvio and big data analytics. Here’s how their approach works: Students download an app that connects them with the right advisors and instructors, collects all their activities together, and gives them the sense of community they need to turn involvement into engagement.

On the other side of the app, advisors and instructors keep track of their students using data-driven risk profiles and timely notifications, nudging them along if they’re flagged as being off-track. When issues arise, they can directly address them with their students by seamlessly hopping on video calls.

Why Webex?

Where does Webex enter the picture? Involvio has integrated the Webex Teams SDK into their app, letting students chat or have a video call with their advisors without ever downloading Webex. Pretty smart, right?

But that’s not all. Involvio has also created a bot to send critical notifications to busy advistors and instructors, alerting them when their students miss classes, fail to fill out forms, or demonstrate other lack of engagement indicators.

For Winkleman, the pre-existing infrastructure and power of Webex Teams made it a no-brainer for the Involvio builds. As he put it, “We didn’t consider any other platforms because we didn’t really see any [that] have broad deployment across schools. None of the other platforms are ‘enterprise-grade.’”

And because Involvio is a partner in Cisco SolutionsPlus program, the benefits to working on the Webex platform don’t end there. Soon enough, schools will have the option to purchase Webex and Involvio together as one integrated package, helping accelerate Involvio’s growth while making life simpler for our customers.

The Developer Journey

It wasn’t just the decision to go with Webex Teams that was fast and easy. It was also fast and easy to build and launch on the platform.

In fact, though Winkleman and his team had no familiarity with Webex documentation before creating their app and bot, it only took a few days to build the bot from scratch. While the video SDK work was understandably a bit more complicated, Winkleman says there’s nothing the docs couldn’t answer.

What’s Ahead

It’s always upwards and onwards for Involvio. Moving forward, Winkleman and the team are planning on perfecting the notification strategy for the bot, as well as adding in more calling features to the app. Improving the student retention rate will take time and effort, but if any team can do it, it’s Involvio’s. And we’re so excited to help.

Want to learn more about how Involvio works? Check out our previous Involvio blog post and head over to their website. Then, get started on your own build by referencing our Webex developer documentation.

https://developer.webex.com/blog/how-we-build-with-webex-involvio https://developer.webex.com/blog/how-we-build-with-webex-involvio Wed, 07 Nov 2018 00:00:00 GMT
<![CDATA[How We Build With Webex: Dynamic Signal]]>

“Catch the Webex Teams message about the survey we need to complete?”

“Have you seen the intranet post that’s been blowing up the past few hours? You should check it out.”

“Sorry. But can you check your secondary email...again?”

Any of these situations sound familiar? We’re guessing yes. With so many communication channels and so little time, it’s becoming hard to keep up with the message overload. Cue this classic “Portlandia” sketch.

If you’re wondering how companies can best cut through the noise and connect with their employees, you’re not alone. It was this exact question that led the Dynamic Signal team to rethink the ways we communicate internally.

Wondering how they approached the problem — and where Webex enters the equation? Come along with us to find out.

About Dynamic Signal

Not only was the Dynamic Signal team interested in fostering communication within working communities, they also wanted to make it easier for marketers measure and improve the reach and overall impact of their messages. After all, more informed employees are more engaged and effective employees.

To those ends, the team built a consolidated platform where marketers can create personalized, relevant posts and share them with the right audiences at the right time. They also created a sharing tool directly in the platform, allowing recipients to broadcast their messages on Webex Teams.

From the marketer’s perspective, that’s huge: From many posts, many channels, and many missing metrics — to one post, one platform, and one complete set of metrics.

But Dynamic Signal can go even further than that. It can also help you you keep close to your community.

Just one example? Senior Product Manager Idoh Gersten highlighted Nurses Spotting Nurses, a program at one hospital in which nurses are encouraged to share examples of excellence they see among their nursing colleagues. With Nurses Spotting Nurses on Dynamic Signal, participants can make wholly new connections with their teammates as they celebrate mini-wins together.

Why Webex?

For Dynamic Signal, choosing Webex was a no-brainer. As a staple in enterprise collaboration, Webex is not just nice to have, its necessary for Dynamic Signal to connect with the Webex ecosystem. But beyond being included in the suite of platforms to which a message can be sent, one of the key benefits of Dynamic Signal’s Webex bot is that users can send messages directly from Webex Teams that will go out to all the communication channels specified for that bot.

The Developer Journey

For the Dynamic Signal team, the journey to develop an app for Webex Teams was not really a journey at all — it was more like a walk in the park. That’s because it took just two days for the build: one to become acquainted with the Webex Teams documentation, and one to actually create the app.

Any surprises for the Dynamic Signal team throughout the process? Just the happy kind: Senior Product Manager Gersten found the ability to make API calls directly from the documentation to be incredibly useful. It’s a feature he hasn’t seen on other similar documentation pages. (We’ll take that as a compliment!)

What’s Ahead

There’s nary a dull moment on the DySi team. We can’t wait to see what they’ll come up with next. Whatever it is, we’re confident it will help streamline enterprise communications while bringing work communities closer together.

Want to dig into Dynamic Signal? Learn more by visiting their website. Then, begin on your very own Webex Teams build by exploring our Webex developer documentation.

https://developer.webex.com/blog/how-we-build-with-webex-dynamic-signal https://developer.webex.com/blog/how-we-build-with-webex-dynamic-signal Tue, 06 Nov 2018 00:00:00 GMT
<![CDATA[How We Build With Webex: Rollbar]]>

Pick one: speedy release cycles or flawless code? On the one hand, speedy release cycles mean your customers are able to keep current with the latest technology. On the other hand, flawless code keeps quality consistently high-level — even if it takes a long time to write.

So, which one will you pick? Why not both? That’s exactly what the team at Rollbar was asking themselves. As tech industry experts, they knew that though speed had always been of the essence in deployments, the pace of work was picking up more and more and showed no signs of slowing down. They also knew that as less time is spent on an increasing number of iterations, the more code errors appear.

While the speed versus quality question may have been easy for them to answer, actually solving the issue was another matter entirely. Here’s how the Rollbar team did it.

About Rollbar

The team knew that error reporting was a good start, but understood that it would only call out flaws in the code. To bring developers the agility they were after, Rollbar also added in automated, instant post-deployment updates — updates that explain what the errors are, where the errors are, and who they affect.

“You don’t even need to reproduce the issue.” Director of Engineering, Francesco Crippa explains. “It’s about creating an immediate context.”

Let’s take a look at what that might look like in action.

Say you work at a big software company in the human resources space. As customer service tickets start to pile up in support, you suspect something in the code has gone awry. You start to scramble to search through scores of log files in order to figure out what’s happening in production. Maybe you have a homegrown solution that cobbles together relevant updates, but even when you do find what you’re looking for, you’re likely lacking the critical contextual information you actually need. Cancel your lunch plans. You’ve got work to do.

But with Rollbar? You’ve got an early warning system for errors you can count on. When issues arise, you go from alerting to impact analysis and resolution in just minutes. Maybe you hear from the support team that a single customer has spotted an error, but by that time, you’ve already fixed the issue. And right on time. Lunch, anyone?

Why Webex?

As Rollbar evolves into its next stage of growth, it’s starting to serve more and more large enterprises (100,000+ employees). For them, the popularity of Webex as an enterprise collaboration tool — it is the world’s leading meeting platform, after all — played a big part in their choice to bring their solution to Cisco.

But it goes deeper than that. Rollbar sees its relationship with Webex as more than a partnership. For them, there’s a correlation between our missions. And we see it too. After all, we’re both transforming how people connect and collaborate in real time — just in our own ways.

The Developer Journey

While one Rollbar developer had previous experience with the Webex Teams documentation, the actual process of submitting their creations to Cisco was new to all.

How did it all go? Consider Crippa’s one word summary: “Frictionless.”

From start to finish, it took Rollbar about a month to create both their bot and their integration. The prototype itself, however, took just a week. Francesco was especially impressed with the functionalities of Webex Teams bots, specifically noting how they cannot read user messages. That’s especially important for their customers who sometimes handle sensitive information, like those in the hypothetical human resources software company example above.

What’s Ahead

We can’t wait to see what the Rollbar team will roll out next. Currently, they’re focusing on building more solutions that leverage the real-time collaboration capabilities of the Webex Teams platform. Stay tuned!

To learn more about Rollbar, visit their website and check out their Webex App Hub solution. Then, begin on your own build by referencing our Webex developer documentation.

https://developer.webex.com/blog/how-we-build-with-webex-rollbar https://developer.webex.com/blog/how-we-build-with-webex-rollbar Mon, 05 Nov 2018 00:00:00 GMT
<![CDATA[Real world walkthrough of building an OAuth Webex integration]]>

This walkthrough goes into a deep dive explanation of OAuth, what it is used for, and how to work with it. This will help when creating Webex Teams Integrations, which exclusively use OAuth for authorization.

What is OAuth?

OAuth is a framework that allows a user to authorize a product/app to programmatically gain access to data stored within a different product/app. A common example of this would be using your Google or Facebook credentials to log into a third-party site. Instead of creating a new set of credentials for the third-party site, the OAuth process issues a token that represents the user and allows access to the data after the user logs in. The user can then revoke access as needed by revoking the token, vs. removing an entire set of user credentials.

Why OAuth is Important: Security Issues and User Limitations

Before OAuth, if users (also known as resource owners) wanted to allow another integration or application to access their data or resources from another account, they would have to share their credentials with the other third-party application. However, this process created security issues, particularly related to password storage. Sites would either store user passwords in clear text or as an encrypted hash - even when encrypted, there are several free sites that can be used to decrypt hashed strings, and there is little way to know what security measures the third-party site might be using to protect the credentials as a whole.

The other issue was with individual user limitations. Before OAuth, revoking access to one individual end user wasn't possible without revoking access to all users working with the same credentials to access the resources. This meant resource owners couldn't properly restrict access on a case by case basis—if you had the credentials, you had access.

OAuth solved these issues. With OAuth, third-party applications are given an access token which is used to obtain information about the specific service or resource; this token represents the user without exposing their actual credentials. The process of retrieving this access token is called the grant flow.

Integrations and OAuth in Webex Teams

Integrations request permission to invoke Webex Teams APIs on behalf of a user. An example of an integration would be a connection between Webex Teams and a Box folder with the Box integration. Any changes (such as uploading new files or making comments on files) would invoke the Webex Teams API to post a message in a space on behalf of the user that authorized the integration. This differs from a Webex Teams bot, which does not have access to individual user data and exists as its own entity.

Helpful Definitions

Before moving on, knowing the definitions listed below will be helpful, as they may be referenced throughout the rest of this post. For more information, you can also visit our Authentication documentation.

The Four OAuth Roles (as described in RFC6749):

Resource Owner — An entity capable of granting access to a protected resource. When the resource owner is a person, it is typically referred to as an end user.

Resource Server — The server hosting the protected resources, capable of accepting and responding to protected resource requests using Access Tokens.

Client — An application making protected resource requests on behalf of the resource owner and with its authorization. The term "client" does not imply any particular implementation characteristics (e.g., whether the application executes on a server, a desktop, or other devices).

Authorization Server — The server issuing Access Tokens to the client after successfully authenticating the Resource Owner and obtaining authorization.

Client ID — The Authorization Server (in this case, the Webex Teams API) provides the Client Identifier for the integration. The Client ID however, is distinct from the Client Secret (mentioned next) because it is exposed to the Resource Owner (i.e. the user of the integration) and shouldn't be used by itself for client authentication. The Client ID is unique to the Authorization Server.
Example: a3ae1859d31806348e9fa80e20e5c71d3f1496ca61879bde4ef39739897e4788d

Client Secret — The Authorization Server (again, the Webex Teams API in this case) also provides the Client Secret for the integration, which authorizes the Client that is requesting an Access Token. In this way, OAuth 2 uses the Client Secret to verify that a Client should have access to the Resource Server that's waiting for an Access Token, so it can make requests on the user's behalf.
Example: f883984e7a2ba716179f9a5e9cf33abb1b1b83f067a8b0c9c4fa90dae256998c7

Access Token — An object that contains security information such as identity and privileges/scopes for the user account being authorized. Access Tokens for the Webex Teams API are valid for 14 days before expiring automatically.

Refresh Token — A Refresh Token is used to acquire a new Access Token after the original token generated by the Grant Flow expires or is about to expire. The Refresh Token should be stored securely by the application, and is valid for 90 days unless used, at which point the timer will reset (making this type of token effectively perpetual). This enables you to renew the Access Token for a user before it expires (at the previously mentioned 14 days), allowing a user to essentially remain authenticated forever.

Scopes — Scopes determine what resources the Access Token has access to. A full list of scopes available in Webex Teams can be found in our Authentication documentation.

State — This is a unique identifier that can optionally be defined when creating the integration and can be used to verify the authorization request when it's sent to the Redirect URI. Basically, this helps check whether the request containing the Authorization Code is coming from the correct Client or not.

Redirect URI — This represents the endpoint where your users are sent to after they authorize the application. This is typically a valid HTTP endpoint which supports TLS (recommended), so the Authorization Code or Access Tokens can be transmitted securely to avoid attacks.
Example: https://lockbot.cisco.sparkbot.io/oauth

Bear in mind, for native and mobile apps, the Redirect URI scheme may be different. For example: mydemoapp://oauth

The following link includes more information regarding the Redirect URI: https://www.oauth.com/oauth2-servers/redirect-uris/

OAuth Grant Types

As noted above, in order to access the Resource Owner's protected resources, the Client needs to get a credential representing the Resource Owner's authorization and then obtain an Access Token. There are four grant types in OAuth 2.0:

  • Authorization Code
  • Implicit
  • Resource Owner Password Credentials
  • Client Credentials

Webex Teams currently only supports Authorization Code, which is a grant flow used mostly with web applications to get access to an API.

Setting up the Redirect URI

We'll now get into the actual steps to create the integration. First step: your Redirect URI. As also previously mentioned above, the Redirect URI scheme could be different depending on the nature of the application, whether it's a web based app, a native app, or a mobile app. The Redirect URI acts as the callback entry point for the app and could either be an HTTP redirect URI or custom URI scheme. For example: https://mydemoapp.com:10023/register or mydemoapp://register

We'll focus on how to set up an HTTP Redirect URI for this walkthrough. The Redirect URI is required to use TLS 1.1 or higher for any HTTP URI, in order to protect the endpoint. This prevents any interception during the authorization process. For development purposes, on a Mac you can locally launch a simple light weight server from Terminal with the following command (on Windows, you'd need to install Python first):

python -m SimpleHTTPServer

You should see the following response if everything works correctly:

This is a simple built-in web server from Python that listens on default port 8000, so or http://localhost:8000 will be your redirect URI.

If you use this method, you will need to use a tunneling proxy such as ngrok to expose the endpoint to the public internet. Many users find this convenient for initial development, but once you're ready to run this in production, you'll want to get an actual hosted site. Common options many developers use include AWS or Heroku, but you're not limited to any specific hosting option as long as your URL is accessible to the open Internet (i.e. not locked down behind a firewall).

Creating an Integration through the Webex for Developers Portal

The next step is to create your integration through the Webex for Developers Portal, which is very easy. Simply log into your Webex account at https://developer.webex.com, click on your avatar at the top right, then click "My Webex Teams Apps". This will take you to the "My Apps" page. Click the blue plus at the top right and then choose "Create an Integration". You should now be on the "New Integration" page. Choose a unique name, a contact email (for Cisco internal support use only, it won't be referenced anywhere publicly), an icon, and the general description or purpose of the integration.

Once these are completed, provide a Redirect URI. You can enter more than one by separating them with a comma, which allows you to redirect your application to different endpoints using a single integration. This could be useful if you have multiple data centers that all perform the same tasks, such as when you have failover setup.

Next, choose which scopes your integration needs access to, and then lastly submit the app by clicking on the "Create Integration" button in blue at the bottom.

Once it has been submitted, be sure to save and store the Client Secret provided (located below the Scopes section of the page) before directing away from this page. If this is lost, you will need to regenerate a new one.

The OAuth Authorization URL shown at the bottom of the integration details page provide the following, in this order:

  • client_id
  • response-type
  • redirect_uri
  • scopes
  • state

We will reference what to do with that Authorization URL in the next section.

Authorization Code Grant Flow

Retrieving the Authorization Code

After your Redirect URI is set up and your Webex Teams integration is created, the next step is to get your Authorization Code. The Client (your app) will ask the Authorization Server (Webex Teams) for an Authorization Code, which will later be exchanged for an Access Token. To do so, you will need to send your prospective users to https://api.ciscospark.com/v1/authorize with the following parameters included, all in one form-encoded URL:

  • response_type — Must be set to 'code' (string)
  • client_id — The Client Identifier (ID), issued when registering the app
  • redirect_uri — Must match one of the URIs provided when the application was created
  • scope — A space-separated list of scopes being requested by the application. This should match exactly with the scopes that were selected when the application was created (see our Authentication guide for full list)
  • state — A unique string used to verify authenticity of the incoming request to the defined redirect URI (optional)

Using a Cisco-built and publicly available integration called LockBot as an example, when someone goes to its page on the Webex App Hub and clicks "Visit Site To Connect", they're directed to https://lockbot.cisco.sparkbot.io/request/.

The Grant button on that page goes to a URL that looks like this (note all the parameters mentioned above are included):


With your integration, this URL should match the OAuth Authorization URL shown on the integration detail page in "My Apps" when you created your Webex Teams integration.

When a user clicks on that link, it will send them to the standard Webex login page. Once they sign in, they would see the following authorization prompt for LockBot:

Once they click Accept, they've granted LockBot access to their Webex Teams data, but LockBot doesn't yet have a functional token to use. Instead, Webex Teams sends an Authorization Code to the previously defined Redirect URI (in LockBot's case, https://lockbot.cisco.sparkbot.io/oauth) with the code and state, like the following:


Looking at that URL, the code in the query string and state "lockbot" previously passed in the request are both present. This code will need to be exchanged for an actual token, which we go through in a later step.

Next as a quick sidebar, we'll show how to create a real simple Grant Flow Landing Page that mimics what a user would see with LockBot; feel free to use it as a baseline for your own landing page.

Creating a Grant Flow Landing Page

Below is a very simple HTML example showing how to build an interface with a Grant button, allowing the user to grant the integration access to their Webex Teams data. The main piece to note is the URL associated with the Grant button itself, which sends the user into the Grant Flow process:

This is the HTML used to create the above LockBot Grant page.

<!DOCTYPE html>
    <title>LockBot Permissions Request</title>
    <meta charset='utf-8'>
    <link rel='stylesheet' type='text/css' href="/static/css/index.css">
    <script src='http://code.jquery.com/jquery-1.4.2.js'></script>
    <section class='container'>
      <div class='center content'>
        <div class='spacer'></div>
        <img src= "/static/css/lock-bot.png"/>
        <div class='spacer'></div>
        <div class='center'>
          <h1>Grant Lockbot Access To Webex Teams</h1>
        <div class='spacer-small'></div>
        <div class='center'>
          <a href="https://api.ciscospark.com/v1/authorize?client_id=a3ae1859d31806348e9fa80e20e5c71d3f1496ca61879bde4ef39739897e4788d&response_type=code&redirect_uri=https%3A%2F%2Flockbot.cisco.sparkbot.io%2Foauth&scope=spark%3Amessages_write%20spark%3Arooms_read%20spark%3Amemberships_read%20spark%3Arooms_write%20spark%3Apeople_read%20spark%3Akms%20spark%3Amemberships_write&state=lockbot">
            <div class='button' style='width:512px;'>GRANT</div>

Getting the Access Token

Once your user has moved through the Grant Flow process and you have the Authorization Code, next you'll need to exchange that code for the actual Access Token your app can use to invoke the Webex Teams APIs on behalf of your user. To do this, the app will need to perform an HTTP POST to the following URL with a standard set of OAuth parameters (this endpoint will only accept an x-www-form-urlencoded body): https://api.ciscospark.com/v1/access_token

The required parameters are:

  • grant_type — This should be set to "authorization_code"
  • client_id — Issued when creating your integration
  • client_secret — Remember this guy? You kept it safe somewhere when creating your integration.
  • code — The Authorization Code from the previous step
  • redirect_uri — Must match the one used in the previous step

An example might look like this:


Webex Teams will then respond with JSON containing an Access Token that's valid for 14 days, and a Refresh Token that expires in 90 days, as shown in the example below:

    "expires_in":1209600, //seconds
    "refresh_token_expires_in":7776000 //seconds

The Refresh Token is used to get a new Access Token before it expires, so you can keep your application live without prompting the user to go through the grant process again. Every time the Refresh Token is used to get a new Access Token, the expiration timer will reset.

However, if you allow the Access Token to expire, using it to make a request from the API will result in an "Invalid Token Error" like the following example:

If the Access Token expires, you need to use the Refresh Token to generate a new Access Token. To refresh an Access token, it's recommended to catch token errors in your application, and when they occur, refresh the token and try again. If the refresh fails, this might mean your Refresh Token is older than 90 days and has expired, or that the user or an admin has otherwise revoked their tokens. When this happens, direct the user to the Webex Teams login process again and get a new set of tokens for them. This is considered a better practice than using a timer to refresh tokens before they expire.

Getting a new Access Token using the Refresh Token is done much like getting the initial Access Token but with different parameters:

  • grant_type — This should be set to "refresh_token"
  • client_id — Same client_id you received when you created your integration
  • client_secret — Same secret you used to get the Access Token originally
  • refresh_token: — This is the Refresh Token returned when you got the initial Access Token

An example might look like:


Once this is done, a new Access Token will be returned in the response and can be used for the next 14 days.

Example response:

    "access_token": "82d19946849bac67373eb401824b3afcb919544dcda8314220a867a6e561b9e43",
    "expires_in": 1209599, //seconds
    "refresh_token": "a434252a53e6f97483df14d4097ba956a24cdf56a6673014a1647ef6eadf4cc50",
    "refresh_token_expires_in": 7775975 //seconds

Example: Retrieving the Authorization Code via Python

Provided below is a snippet in Python, which shows how to retrieve the authorization code through the back-end once the request is redirected back to the server endpoint or Redirect URI. For this example, we're using the Flask web framework. Full working code is available at: https://github.com/webex/Spark-API-Demos/tree/master/OAuthDemo

def oauth():
    """Retrieves oauth code to generate tokens for users"""

    if "code" in request.args and state == "YOUR_STATE_STRING":
        state = request.args.get("state") #Captures value of the state.
        code = request.args.get("code") #Captures value of the code.
        print "OAuth code:", code
        print "OAuth state:", state
        access_token, refresh_token = get_tokens(code) #As you can see, get_tokens() uses the code and returns access and refresh tokens.

        #Now, let's do something with the generated token: Get the user's info: PersonId, Email Address and DisplayName.
        personID, emailID, displayName = get_oauthuser_info(access_token)
        print "personID:", personID
        print "email ID:", emailID
        print "display Name", displayName
        return render_template("granted.html")
        return render_template("index.html")

Example: Retrieving an Access Token Via Python

The following example snippet is part of the same app as the last example, but shows how to retrieve an Access Token instead of the Authorization Code:

import requests
import json

redirectURI = "APP_REDIRECTURI" #This could different if you publicly expose this endpoint.

def get_tokens(code):
    #Gets access token and refresh token
    print "code:", code
    url = "https://api.ciscospark.com/v1/access_token"
    headers = {'accept':'application/json','content-type':'application/x-www-form-urlencoded'}
    payload = ("grant_type=authorization_code&client_id={0}&client_secret={1}&"
                    "code={2}&redirect_uri={3}").format(clientID, secretID, code,  redirectURI)
    req = requests.post(url=url, data=payload, headers=headers)
    results = json.loads(req.text)
    print results
    access_token = results["access_token"]
    refresh_token = results["refresh_token"]
return access_token, refresh_token


You can get the complete demo code at: https://github.com/webex/Spark-API-Demos/tree/master/OAuthDemo

Example: Retrieving an Access Token via Postman

While this isn't likely to be anything you'll use in production, sometimes having a GUI REST Client example makes things easier to understand.

  1. Retrieve your Authorization Code from the original Grant Flow and save it - note the authorization code is only valid for one request and will become invalid once the request to /access_token is made.

    Example: code=Njc5NmI0YTU4OTc1ZDRhNDczMDcxZDE4ZDI4ZmQzMjMzNjJiZDczMWQzMTgwMGI0O&state=<insert chosen state>

  2. In Postman, make a POST request using the following information:

    Endpoint: https://api.ciscospark.com/v1/access\_token


    Accept: application/json

    Content-type application/json



    Once you have performed the POST request, the response body should include both the Access Token and the Refresh Token.

  3. In order to generate a new access_token using the refresh_token, you can do a POST to the same endpoint and with the same header mentioned above, but with a slightly different body


Using OAuth is a secure, though slightly complex way to allow access to Webex Teams API resources. Hopefully this detailed walkthrough helps make sense of the steps necessary to get from the creation of your Webex Teams application on the developer portal to the retrieval of a valid Access Token for your application to use. If you have any additional questions, you can reach out to the Webex Developer Support team via email or live chat 24/7/365.

Colby Alladaye, Arielle Johnson, and Jeff Marshall also contributed to this post.

https://developer.webex.com/blog/real-world-walkthrough-of-building-an-oauth-webex-integration https://developer.webex.com/blog/real-world-walkthrough-of-building-an-oauth-webex-integration Thu, 06 Sep 2018 00:00:00 GMT
<![CDATA[Actiance is now on the Cisco GPL]]>

Actiance, a Cisco Webex Teams integrator, is on Cisco’s Global Price List and available for transactions by any Cisco seller/reseller.

actiance logo

Actiance, the leader in communications compliance, archiving, and analytics, is now on the Cisco Global Price List available for Cisco Collaboration Sellers to transact through CCW. Companies understand the need for risk mitigation of their employee communications. Actiance is the answer.

Actiance, welcome to the price list!

To find out more follow up with your Cisco Collaboration Seller or go to https://www.actiance.com/.

https://developer.webex.com/blog/actiance-is-now-on-the-cisco-gpl https://developer.webex.com/blog/actiance-is-now-on-the-cisco-gpl Tue, 28 Aug 2018 00:00:00 GMT
<![CDATA[Approved Contact Now on the Cisco GPL]]>

Aproved Contact logo Approved Contact, a Cisco Webex Teams integrator, is on Cisco’s Global Price List and available for transactions by any Cisco sellers/resellers.

Cisco has focused on “one button to push” for starting meetings but what about setting up a meeting? Approved Contact has focused on “one touch” to schedule meetings. In business, we all suffer from the scheduling merry go round wasting valuable time just checking on people’s availability. The return on investment for this service is huge especially for employee roles where meetings are critical to the function of that role. Approved Contact integrates with all the major calendaring services, supports views across multiple organizations, and has the critical access and security policies. And, this capability is available from within Cisco Collaboration.

Approved Contact, welcome to the price list!

To get engaged with Approved Contact, reach out at https://approvedcontact.com/.

https://developer.webex.com/blog/approved-contact-now-on-the-cisco-gpl https://developer.webex.com/blog/approved-contact-now-on-the-cisco-gpl Tue, 14 Aug 2018 00:00:00 GMT
<![CDATA[Involvio Now on the Cisco GPL]]>

Involvio is now on the Cisco GPL with an annuity offering and available for transactions by any Cisco sellers/resellers.


Involvio is a Cisco Webex Teams Integrator focused on the higher education market with an innovative offering that addresses student engagement and retention. This is the big question for higher education: Are students engaged? If not, what actions can be taken to keep them on track? Cisco Collaboration provides that critical communication channel between students and administration.

Welcome to the Cisco price list. To get engaged with Involvio reach out at www.involvio.com or hello@involvio.com.

https://developer.webex.com/blog/involvio-now-on-the-cisco-gpl https://developer.webex.com/blog/involvio-now-on-the-cisco-gpl Tue, 17 Jul 2018 00:00:00 GMT
<![CDATA[Local Measure Now on the Cisco GPL]]>

Local Measure is on Cisco's Global Price List and available for transactions by any Cisco sellers/resellers.


Local Measure provides a retail and hospitality service that connects the front line staff to customers and customer feedback. Local Measure combines social analytics, local based activity, and customer history to generate valuable business actions. Cisco Collaboration provides the critical communication channel for real time actions by company team members. Integration with Cisco Meraki is also a plus. Current customers include Sea World, Orange, Virgin Hotels, and Quantas.

Welcome to the price list! To get engaged with Local Measure, reach out at: www.localmeasure.com. And be sure to check out their integration with Webex Teams on the Webex App Hub.

https://developer.webex.com/blog/local-measure-now-on-the-cisco-gpl https://developer.webex.com/blog/local-measure-now-on-the-cisco-gpl Mon, 09 Jul 2018 00:00:00 GMT
<![CDATA[Oblong Takes Cisco Hollywood]]>

It's not often that Cisco can claim Hollywood credit, but we can claim something better - we are bringing Hollywood to life.

Oblong Logo

Oblong Industries, a Cisco solution partner, was founded by the man that Hollywood turns to for envisioning the future of human computer interface as seen in blockbuster movies - like Minority Report, The Hulk, and Iron Man - John Underkoffler. At some point, he decided to make the futuristic concepts a reality. The best part? That reality works seamlessly with Cisco technology.

So what does Oblong do?

Oblong puts a multi-stream content layer on top of Cisco Webex. Do you want to share content in a more flexible way? Do you want to make your content more interactive with multiple people sharing at once? Do your collaborators want to see content from different sources side-by-side? Do you want your system, room, and environment to be so immersive that people can't help but be captivated?

Oblong meeting

A really cool aspect of using Oblong is the experience in a meeting room. When you walk into a room with Oblong's Mezzanine product, you'll often see a number of large screens arrayed to form the shared, pixel-rich workspace. (You might even see screens on multiple wall surfaces.) There is a remote control called a wand that provides for gesture control of the information - while another group at some other location are also doing the same. You're all working together, seeing and controlling the same content at the same time.

For an example of the utility Mezzanine brings to projects, check out this short video illustrating how a workflow in Cisco Webex Teams can jump from desktop to multi-stream Mezzanine meeting space for collaborators in multiple locations.

Or take a deeper dive, and go behind the scenes at Oblong with Spencer Kelly of BBC Click

Behavior is driven by the tools and environment that people are in. If you have a traditional meeting, right after lunch when people's blood sugar is dropping, and someone is droning on, presenting from a slide deck, people just aren't fully engaged.

Put those same people in a room with an immersive Oblong <> Cisco Webex experience - huge screens, all sharing content at the same time, engaged in discussions - it's exciting!

It's like you're actually in the movie instead of watching one. If you're interested in how Oblong can do this for your customers or at your company let us know. Then, at your next meeting, your team might confuse you for Tony Stark.

And, if you're interested in hearing from the man himself, check out John Underkoffler's TED Talk on the future of Human Machine Interfaces.

https://developer.webex.com/blog/oblong-takes-cisco-hollywood https://developer.webex.com/blog/oblong-takes-cisco-hollywood Mon, 25 Jun 2018 00:00:00 GMT
<![CDATA[Changes to Admin and Compliance Scopes]]>

As a Webex developer, we want to give you advance notice of a key functionality change with spark-admin and spark-compliance scopes.

The following authorization scopes are now deprecated and will no longer work after August 15, 2018:

  • spark-admin:events_read
  • spark-admin:memberships_read
  • spark-admin:memberships_write
  • spark-admin:messages_read
  • spark-admin:messages_write
  • spark-admin:rooms_read
  • spark-admin:teams_read
  • spark-admin:team_memberships_read
  • spark-admin:team_memberships_write

Webex Teams apps which currently use spark-admin scopes to perform compliance activities as an organization administrator will need to transition to spark-compliance scopes over the next two months. After this change, organization administrators will no longer be able to perform compliance activities. Instead, these activities will be limited to only the compliance officers for an organization.

The deprecated scopes have been removed from the Webex for Developers site and are no longer available for new applications, testing via Test Mode in the Webex Teams API Reference, or with an administrator’s portal token.

If any of your apps make use of the spark-admin scopes listed above, please update them now.

We'll keep you posted on any other changes on this, and, of course, will continue to update you on other refinements we make to further improve and enhance the Webex Teams API.

https://developer.webex.com/blog/changes-to-admin-and-compliance-scopes https://developer.webex.com/blog/changes-to-admin-and-compliance-scopes Tue, 19 Jun 2018 00:00:00 GMT
<![CDATA[Using PubNub for Enterprise Bots Behind the Firewall]]>

Building Cisco Webex Teams bots and integrations that need access to behind-the-firewall resources is a challenge that regularly faces developers building Webex applications for internal use. Webex API events are delivered with an HTTP push model that requires your bot to be hosted on a web server that’s available on the public internet, but not all IT infrastructure allows for public web servers. To make this easier, we've worked with PubNub to create a reference architecture that allows enterprise applications to use PubNub's infrastructure to deploy bots and integrations behind the firewall.

PubNub is a publish and subscribe service that makes it easy to deliver events to applications in real-time, across a wide variety of network configurations. If the application can reach the internet, it can receive PubNub events. Today we're publishing a reference architecture, helper applications, and sample code that allow you to use PubNub as a transport to get your Webex Teams events delivered behind the firewall, to mobile clients, or wherever you need them to go.

This reference architecture uses PubNub as your webhook URL, and PubNub will publish all webhooks to a PubNub channel. Your application subscribes to this channel, receiving all webhooks over this channel in real time. Minimal changes are required to your application, often only requiring a few lines of code to be added.

PubNub flow

We've published a GitHub repository containing sample code, instructions for implementation, and helper applications. The repository also contains a plugin for Howdy Botkit that makes any Botkit application use PubNub.

Sign up for PubNub's free developer trial and download the sample code to get started.

If you're at Cisco Live in Orlando this week, stop by the PubNub booth in the Investment Village inside the World of Solutions to talk about this reference architecture and many other ways you can build real-time applications with PubNub. And stop at the theater near the Investment Village at 2:50pm on Monday June 11 to hear Webex Evangelist Phil Bellanti and PubNub CEO Todd Greene talk about this architecture.

https://developer.webex.com/blog/using-pubnub-for-enterprise-bots-behind-the-firewall https://developer.webex.com/blog/using-pubnub-for-enterprise-bots-behind-the-firewall Mon, 11 Jun 2018 00:00:00 GMT
<![CDATA[Cisco Webex Cloud API Development Partners at Cisco Live! Orlando]]>

We are excited to have such an amazing group of development partners showcasing their solutions and platforms at Cisco Live! Orlando from June 11th through June 14th. We are including a snapshot of our Webex Teams API partners who will be attending.

If you're going, please stop by, say hello, get a demo, and find out how they can add value to your business. And, if you'd like to connect with them before the show please reach out directly or through us.

Make sure to print this out before you go!

CLUS card

M.io - in the Cisco Live! Collaboration Village

Unified team chat for Webex Teams and Slack

Dynamic Signal - in the Cisco Live! Collaboration Village

Connect with your most valuable assets. Your Employees.

Vbrick - booth # 1667

Enterprise Video. Like you've never seen it!

Oblong - in the Cisco Live! Collaboration Village

Multi-stream content on top of Webex

Vyopta - in the Cisco Live! Collaboration Village

Unified Communications and Collaboration Performance Management

Actiance - in the Cisco Live! Collaboration Village

Redefining Archiving for Compliance

Singlewire - booth # 1646

Emergency Notification with Informacast

Pega - in the Cisco Live! Collaboration Village

Customer engagement. Digital Process Automation.

See you there!

https://developer.webex.com/blog/cisco-webex-cloud-api-development-partners-at-cisco-live-orlando https://developer.webex.com/blog/cisco-webex-cloud-api-development-partners-at-cisco-live-orlando Fri, 01 Jun 2018 00:00:00 GMT
<![CDATA[M.io Lets You Talk Across Apps, Including Cisco Webex Teams]]>

-- This post is co-authored by Chris Traganos, VP Product of M.io & Frank Geck, Business Development Manager of Cisco --

having a meeting

Sounds simple right? In the last few years collaboration, specifically messaging and video solutions have proliferated across both consumer and enterprise customers. They are becoming easier to deploy and often out of the control of IT and InfoSec departments.

Some teams are sending WhatsApp messages with critical business information and others are using Cisco Webex Teams or even Slack. We often run into sales situations where a Fortune 500 customer is interested in a corporate rollout of Cisco Webex Teams but during the sales process the customer discovers several groups using Slack, and they aren't interested in switching.

That's where M.io comes in.


M.io is a Silicon Valley startup that just moved to my home city of Austin, Texas (the Live Music Capital of the World) and they understand collaboration platforms and the collaboration API's better than just about anyone. And they've created an amazing product that federates between these platforms that is seamless to users.

Does your product marketing team want to use Cisco Webex Boards so they can digitally whiteboard from remote locations and then communicate that information to the Engineering team where everyone's not on Webex Teams but some are on Slack? No problem.

[Webex Teams & Slack Interoperability](https://vimeo.com/271170116) from [Message.io](https://vimeo.com/messageio) on [Vimeo](https://vimeo.com/).

Solving this problem is harder than one might think at first. Sure, just do some API mapping and create bridge functions between the two. Not so simple. M.io has had to consider the security and scale that comes along with the Cisco Webex Teams platform.

We're thrilled about this solution for many reasons. First, we've been spending a ton of time focusing on our core products and love the fact that a third-party development partner has solved this extremely hard problem with us. Second, it's really a sign that our Webex for Developers program is going in the right direction. This interoperability is hard so our open API's have been able to help deliver on a complex problem like this.


And, for the market, this is a sign of where we are going as a company. We recognize that companies are going to have mixed environments and we're working to support seamless experiences - not just with our own products - but across an enterprise's complex mix of technology platforms.

M.io is making it easy for us to all talk to one another. Imagine all the good things that are going to come from that. We care about bringing interoperability to you!

Next Steps -- For more information reach out to M.io directly online or follow up with Frank Geck on Webex Teams using fgeck@cisco.com.

https://developer.webex.com/blog/m-io-lets-you-talk-across-apps-including-cisco-webex-teams https://developer.webex.com/blog/m-io-lets-you-talk-across-apps-including-cisco-webex-teams Wed, 23 May 2018 00:00:00 GMT
<![CDATA[Upcoming Bot Username Changes]]>

Following the rebranding of Cisco Spark to Cisco Webex Teams, all newly created bots will now be given a domain of webex.bot. Existing bots, which use the sparkbot.io domain, will remain unchanged until August 31, 2018. However if you, as a bot developer, would like to update the domain to webex.bot before then, you now have that option when you select a bot on the My Webex Teams Apps page.

There are a few things that you will want to consider when deciding when to update your bot's domain. Remember, the bot's address (username and domain) is the identifier that you give to your customers so that they can open a 1-to-1 space with your bot or add it to a group space. When you change the domain, you will need to update all of the places where you externally advertise the bot's address.

When the address changes, all existing space memberships remain unchanged; the bot is still a member of any spaces previous to the domain change. In this respect, it is like changing the bot's avatar. Similar to avatar changes, the Webex Teams clients may not reflect the address change for several days. This will not prevent your users from communicating with the bot. New users will only ever see the new address and will not be aware that there ever was an address with @sparkbot.io.

Before changing the domain, you will want to ensure that your bot will behave correctly with the new name. One useful precaution is to search your codebase for the string 'sparkbot.io'. If it appears anywhere in your code then that code is going to misbehave when the address of your bot changes from mybot@sparkbot.io to mybot@webex.bot. Your code might be checking the personEmail field of the message sender to see if it is from your own bot. This is useful if you want to avoid replying to your own messages. One way to fix this is to change the code to use the new address: mybot@webex.bot. However, a better fix is to stop using the bot's address completely. Instead, check the personId of the sender against your bot's personId. While a bot's address can change, the personId cannot, so your code will survive any future domain or username changes.

We will support bots with @sparkbot.io addresses until August 31, 2018. After that time, all bots will be migrated to the webex.bot domain. All new bots created on the Webex for Developers portal will use the new @webex.bot domain. If you try to create a new bot with a matching username, it will be refused. For example, if you own mybot@sparkbot.io then it will not be possible for anyone to create a bot with the address mybot@webex.bot.

If you have any questions about this change, our Webex Developer Support Team is available 24/7 to help. Please contact them with your concern.

https://developer.webex.com/blog/upcoming-bot-username-changes https://developer.webex.com/blog/upcoming-bot-username-changes Fri, 18 May 2018 00:00:00 GMT
<![CDATA[Enhanced Communications with Cisco Webex Teams and Vyopta]]>

How many times have you been on a conference call and people complain they can't hear you?

"You're breaking up!,"

"Is it your cellular connection?,"

"Is it your headset?,"

"Is it your wireless network?"

Experiencing communication breakdowns like these are all too familiar for many of us. The quality of your communications is absolutely critical for being successful in your career by being able to effectively get your messages across -- literally.

I was once at a startup where the IT department deployed a low cost communication platform on an overburdened and thus ineffective network (overburdened perhaps because the four guys in engineering liked to play networked video games in the middle of the day when they were taking their break!). As a result, how was our sales strategy going? Very poorly. Every sales call was jittery - interrupted by the "I can't hear you" and the classic, "Can you hear me now?!" refrains. How do you close an end of quarter deal with poor communications like that? IT had no idea how to fix the problem and this scenario went on for months. To say that the sales team was furious was an understatement.

Enter Cisco Independent Software Vendor (ISV) Vyopta. Vyopta is the leading communication analytics platform on the market. For Unified Communications, video, and conference calling, Vyopta not only monitors quality of service, Vyopta pinpoints the crucial performance areas that need improvement.

Cisco And Vyopta

Is there a router that can't handle the capacity and needs an upgrade? Is the sales team experiencing customer calls with less than optimal quality? What's the average packet loss across your calls? These are the types of questions that Vyopta answers, helps to troubleshoot, and ultimately resolve.

Vyopta is a long time development partner with Cisco and they've been an early adopter of our cloud APIs. Vyopta has deployed a bot to our Webex App Hub that allows IT departments to pull information from Vyopta when they are troubleshooting communication problems. Vyopta has also partnered with Cisco for Early Field Tests (EFT's) on our API's to help drive our strategic direction for mutual benefit. We love feedback like this from our development and ISV partners to make sure that we deliver the best APIs.

Abbvie Testimonial - vyopta

Additionally, reflecting the spirit of our Webex Teams APIs and open standards, we also love the fact that Vyopta can do their analysis in mixed environments. It's important to recognize that most large companies have mixed environments. For example, Cisco mixed with Avaya mixed with Polycom -- not a problem for Vyopta. They've integrated with virtually all of the communication platforms.

Vyopta UI

This is a big reason why Vyopta has been added to the Cisco Global Price List (GPL) with an annuity SKU. What that means is if you're part of the Cisco sales ecosystem, you get compensated when including Vyopta in a deal. If you're selling to a new Webex customer, you want to show Vyopta as well.

Vyopta can show direct improvements in quality of service and utilization as a result of modifications that are implemented, which have been driven from their analysis. Add to that a dramatic drop in IT help desk requests, thereby increasing company productivity by removing time spent submitting and addressing IT issues -- something no one wishes to spend their time at work on.

If you want your communication platform to work as it should, then you want to check out Vyopta. Optimize your collaboration environment!

https://developer.webex.com/blog/enhanced-communications-with-cisco-webex-teams-and-vyopta https://developer.webex.com/blog/enhanced-communications-with-cisco-webex-teams-and-vyopta Mon, 14 May 2018 00:00:00 GMT
<![CDATA[Cisco Webex Teams and Appspace Help Optimize Digital Real Estate]]>

I recently visited a tech company in Austin. Entered the lobby, checked in, was told that my contact was running late, and was asked, could I "please take a seat and wait?" "Okay, sure." After sitting down on a modern-esque chair-you know, the kind you'd expect to see in a tech company-I'm surprised the flat panel on the wall isn't playing 'Squawk on the Street.'

Instead, the screen is displaying rotating pictures of various company events - a hike in a green space, some holiday dinners/gatherings, etc. The images segue to some screen captures of news about the company, including a new partnership they just signed, and then some customer logos. Then the system plays a video about the company's product line for the healthcare market.

digital real estate

At the end of my wait, I couldn't help but think that waiting in a lobby is usually pretty boring but in this case it was actually really cool. In just five minutes, I got this overview of the company, its employees, including a sense of what it felt like working there, and some great news highlights about the company. When it was time for my meeting, I was able to ask a few questions based on that content to help 'break the ice,' get the meeting started, and make everyone feel comfortable right off the bat. Loved it.

That corporate messaging is all managed by a Cisco Webex Teams Integration Partner called Appspace. And they do it extremely well. Companies can create their own digital channels - with all kinds of content, including pictures, videos, etc. - and play them back on hundreds of displays in offices around the world.


Appspace has a philosophy that there should never be a blank screen. In this case, the screens they are referring to are Cisco endpoints - Room Kits, DX80's, and Cisco Webex Boards. Of course, many large enterprises have these devices installed. Appspace turns these devices into a rich internal and external (i.e., for visitors) communications channel.


I love partners who enhance Cisco products like Cisco Webex Teams (formerly Cisco Spark) by adding useful features and thereby adding tremendous value. It's mainly because I love the creativity-seeing innovative integrations like Appspace.

Appspace has certainly embraced Webex Teams. With Appspace, the various digital channels you create are not limited to playback on large format displays. They can also be viewed outside of meeting rooms (on small LCD displays used for room bookings) in the Webex Teams app on your laptop or phone. From a Cisco Webex Teams space, it's easy to subscribe to one of the Appspace digital channels.

Think of all the possibilities: When an employee walks into an office for a meeting with coworkers, they can be greeted with a video of the CEO speaking at the latest town hall; pictures from the last 'all-hands' offsite; - or product updates. And this same information is available for people who work remotely directly from their Webex Teams app- keeping the entire team informed and engaged. We're all inundated with information, with shortened attention spans, so isn't it great to have the ability to better communicate with your employees by making the information more easily available?

room availability

Many companies certainly like what Appspace has to offer. Appspace has existing clients in Oil and Gas, HealthCare, Media, Finance, Transportation, and Social Media. At Cisco, we also use Appspace for our corporate communication digital signage network and Appspace room scheduling displays across 380 offices in 165 countries.

If you have Cisco endpoints or use the Webex Teams app, with Appspace, you can definitely get more value from them.

My team at Cisco is starting to use Appspace to broadcast partnership information to all of our partners. Right now, if I have a general partner update, I go to each partner Webex Teams Space and paste in my update. With Appspace, I can create a channel, subscribe my partner spaces to that channel, then post my updates once in Appspace and all my partners will get the updates. It's a really efficient way to communicate information.

With Cisco and Appspace, it's a great way for companies to take advantage of and optimize this digital real estate, enhancing your ability to communicate and market to your employees and visitors. It's a winning combination, and one that'll make that lobby chair way more comfortable, too!

https://developer.webex.com/blog/cisco-webex-teams-and-appspace-help-optimize-digital-real-estate https://developer.webex.com/blog/cisco-webex-teams-and-appspace-help-optimize-digital-real-estate Mon, 07 May 2018 00:00:00 GMT
<![CDATA[Optimizing Webex Bot Development with the Webex API Emulator]]>

Do you develop bots for Cisco Webex Teams (formerly Cisco Spark)? Do you ever wish that there was a way to create a set of regression tests to ensure that your bot behaves consistently given the same input? Or maybe you wish that there was a way to speed up your iterative development/debug process when you are working on a bot response to a complex set of input? Or perhaps, you just wished you could do some bot development work when you were in a place that didn’t have good internet connectivity?

If so, I’m happy to let you know that the Webex API Emulator, originally created by Stève Sfartz, API Evangelist at Cisco DevNet, can help make your wishes come true. The emulator is a simple node.js project which you can download from GitHub and run locally. It loads a tokens.json configuration file that tells it about the users that can interact with it. This file, which is editable by you, allows you to create “authorization tokens” and “personIds” for your bot, your tester and any other “people” that might be added to spaces as part of your tests. Think of it as your own, local, common identity server.

Let’s start making those wishes come true by dealing with the last wish first, the idea of doing bot development when you are offline. Once the emulator is up and running you can use a tool like Postman to send requests to the Webex API Emulator to do things like create spaces, add a user (or bot) to a space, or post a message to the space. The emulator also supports the webhooks API so if you configure your bot to talk to your locally running instance of the emulator, your bot will get notified when it is added to a space or when a message is sent to it. Once you can can send a message to your bot via the emulator, you can open up your favorite editor or debugger, and you can start stepping through your bot’s responses to these commands, building and debugging responses to these inputs, all without an internet connection.

We’ve glossed over a few things here, but we’ll get back to it. Assume you are now able to send commands to your bot via Postman and see the Webex API requests that your bot makes in response, all offline. Handy for working offline, right? But once you get used to this, you may start to realize that running in this mode simplifies your development motion even when you DO have an internet connection. Imagine your bot needs to have a particular response in certain specific, potentially complex, circumstances. For example if you send your bot a message like “who from my company is in this room”, you might want it to list people from your company but also be sure that it skips people from other companies. You’d want to make sure that the bot behaves properly in circumstances where there are no people from your company, some people from your company, no people from other companies and some people from other companies. To test this you’d ideally create a several spaces and add several combinations of people to each of those space, and then type in your requests in all those spaces. Doing this manually in the Webex Teams app can be time consuming and it might not make your test subjects very happy to keep getting added to different spaces as you test different variations!

With Postman and the emulator, you can make the API calls to create the spaces, others to add each of the users, and another set to send in the commands. These can then be saved in a postman collection and run with a couple of keystrokes. Your bot didn’t respond as you expected? Simply stop the emulator and your bot and restart them (in that order!). This brings you back to a pristine environment where no spaces have been created yet. Alternately, have another set of commands to delete the spaces and run your test again as often as you like, until it works perfectly for all the variations that you care to test for!

Hmm, as we start building up these sets of API calls to emulate user input that we want our bot to respond to, we are starting to get close to what some might call a regression test. There is still one problem though, a true regression test should also validate the responses from your bot. Luckily the Webex API Emulator also supports “bot test mode”. In this mode we can instruct the emulator to look for bot responses to certain input and provide that back in its responses to us.

In order to better understand how bot test mode works we’ve created a bot-test-framework-example to demonstrate a set of tests in action. It includes a link to the Webex API Emulator project, a sample bot, a full collection of Postman tests and a detailed set of instructions to help you get this going. Since the Webex API emulator is written in javascript we chose a node.js sparkbotstarter project originally written by Victor Algaze, based on the node-flint framework created by Nick Marus. We hope to add some bots built with python in the future. The emulator doesn’t care about your framework, but you DO need to be able to configure the Webex API endpoint that your bot sends requests to.

Now, let’s get a flavor for how bot test mode works.

Before we could run any tests we needed to start our Webex API Emulator in “bot test mode” and start our bot using an API token specified in the emulator’s tokens.json file. When we’ve got the the emulator and our bot running properly we’ll have some terminal windows that look something like this:

Webex Emulator

Once those services are running we can start sending in our test input. The first couple of test cases don’t generate any bot reaction, they simply set our state.

  1. We create a new space via a POST to the /rooms API and store the roomId in a postman environment variable called “_room”.
  2. We then add our bot to the space via a POST the /memberships API.

Now we are ready to send a message to the bot and check if it responds as we expect. Here’s what that request looks like in postman:

Webex Emulator 2

This is a fairly standard POST to the /messages endpoint with a body which specifies the roomId of the previously created space (stored in a postman environment variable), and includes some markdown which mentions our bot and sends the command “/leave”. (Note that all of the environment variables used in these test cases are explained in more detail in the bot-test-framework-example readme). Now let’s look at what makes this request a true “regression test”.

Here are the headers for this request:

Webex Emulator 3

The Authorization and Content-Type headers should look familiar to anyone who has used postman to send requests to the Webex API, but there is a new header “X-Bot-Responses” as well. When the emulator sees a request with this header, it understands that we expect the bot under test to make two subsequent requests in response to this command. It will “intercept” the original response to this request and “hold” it until it gets the two bot requests and then build out a consolidated response that looks something like this:

Webex Emulator 4

This response contains two objects:

  1. A testFrameworkResponse which is the emulator’s original response to our POST to the /messages endpoint
  2. An array of botResponses, which show us the requests that the bot made in response to our test input. In this case, our bot made a POST to the /messages endpoint with the text “OK. I know when I’m not wanted…”. It then made a DELETE call to the memberships API and deleted its membership in the space, effectively leaving the room.

Finally, notice the “Test Results” circled in the image above. For each step in our test suite, we created Postman test cases to validate that the API response was as expected, and when appropriate, that the bot responded as expected as well. We won’t delve too deeply into how these tests work, but a full set of example postman tests, including the test cases are provided in the bot-test-framework-example.

While there are a lot of moving parts here to make this work, we think it can ultimately speed up your bot development process. I’ve been using this for a few months now and the regression tests have helped me discover bugs in my bots that I would have depended on users finding for me without it. I also love being able to work on a bot while on an airplane with sketchy internet connectivity!

If you decide to give the Webex API Emulator and bot-test-framework-example a try, we’d love to hear how it goes. git Join the Ask Webex API Emulator space on Webex Teams and give us feedback. Right now this is just another Webex API developer community supported project, and we hope this post makes it clear that tools like this only happen with an active and engaged developer community who make contributions like Stève, Victor and Nick have done. Who knows though, if usage of the emulator really takes off, we may someday be able to turn it into a full fledged service provided by Cisco.

Let us know what you think!

https://developer.webex.com/blog/optimizing-webex-bot-development-with-the-webex-api-emulator https://developer.webex.com/blog/optimizing-webex-bot-development-with-the-webex-api-emulator Mon, 30 Apr 2018 00:00:00 GMT
<![CDATA[The new Cisco Webex for Developers is Here - What Developers Need to Know From Our Rebrand]]>

New look and feel, same great service? Think again. There's more to our recent rebrand of Cisco Spark than initially meets the eye - in fact, there's quite a lot to like about our makeover, including some key things specifically for you as a former Spark/now Webex Teams developer and an upcoming refresh of a familiar Webex Meetings portfolio for existing Webex Meetings developers.

Take a tour of the top three developer takeaways for our new rebrand, excited for our next evolution together. It's a whole new era for our dev community!

  1. What's in a Name?
    • As Shakespeare concluded, a rose by any other name would smell as sweet. So why are we also changing the name of Cisco Spark for Developers to Cisco Webex for Developers?
    • Because we've combined the best of both worlds. In this new environment of cloud-based collaboration technology, our mission is to connect teams with a single, open, secure, interoperable, intuitive cloud platform. We changed the name to reflect how we've combined our separate meeting, calling, and team collaboration solutions into a single, integrated suite. So welcome to Webex for Developers!
    • And for those submitting integrations and bots to the Cisco Spark Depot - welcome to Cisco Webex App Hub, a central hub to discover app experiences on the Webex platform. Stay tuned to see what new Webex Meeting integrations we add to the Webex App Hub.
  2. New Webex Meetings APIs Are on the Way
    • Heads up: Soon you'll be able to easily add powerful Cisco Webex Meetings capabilities to any or all of your apps or services using new modern RESTful APIs. Our initial release coming this summer, will enable you to perform key tasks, including:
      • Authentication: Retrieve tokens needed to call other API's
      • User Management: Create, delete, and retrieve host accounts; manage properties
      • Scheduling Meetings: Schedule, edit, and list meetings
      • Site Privilege Retrieval: Retrieve info on enabled features and privileges
  3. Additional Key Functionalities and APIs
    • A fresh platform, several new API's, and that's not all - for us, this is only the beginning. Moving forward, we'll continue to build momentum with additional functionalities and API's across the Webex platform. So, stay tuned, and make sure to check back here for more dev-centric updates!

Questions about the rebrand or what it means it means for you as a developer? Join our Cisco Webex developer community, visit Webex.com for more product information or follow us on Twitter.

https://developer.webex.com/blog/the-new-cisco-webex-for-developers-is-here---what-developers-need-to-know-from-our-rebrand https://developer.webex.com/blog/the-new-cisco-webex-for-developers-is-here---what-developers-need-to-know-from-our-rebrand Wed, 18 Apr 2018 00:00:00 GMT
<![CDATA[Announcing Change to @mentions in 1-1 Cisco Spark Spaces]]>

As a Cisco Spark developer, we want to give you a heads up regarding a key functionality change in the Spark Message API endpoint.

Currently, the Message API endpoint accepts @mentions in 1-1 Spark spaces. Soon, though, the API will return an error if an @mention is used in a 1-1 space. What this means is that, moving forward, @mentions should only be used in Spark group spaces.

If your app has been @mentioning in 1-1 spaces, please update it now to remove the mention.

We'll keep you posted on any other changes on this, and, of course, will continue to update you on other refinements we make to further improve and enhance the Cisco Spark developer ecosystem.

https://developer.webex.com/blog/announcing-change-to-mentions-in-1-1-cisco-spark-spaces https://developer.webex.com/blog/announcing-change-to-mentions-in-1-1-cisco-spark-spaces Mon, 16 Apr 2018 00:00:00 GMT
<![CDATA[Announcing Cisco Spark License API Changes]]>

As a Cisco Spark Developer, we want to give you a heads up that the Licenses API endpoint for Cisco Spark will soon be updated to include all hybrid services available for an organization.

Currently, the Licenses API endpoint provides information about only those hybrid services which have been enabled for an organization. After this update, all hybrid services which are available for an organization, both enabled and disabled, will be returned and available for clients to review.

This change allows organization administrators to assign hybrid services to users before a particular service is activated. It should be a great time-saver for organizations' IT departments, allowing them to focus time and resources on other tasks. Hybrid Services can be enabled or disabled via the Cisco Spark Control Hub. We encourage you to utilize this new flexibility.

https://developer.webex.com/blog/announcing-cisco-spark-license-api-changes https://developer.webex.com/blog/announcing-cisco-spark-license-api-changes Tue, 10 Apr 2018 00:00:00 GMT
<![CDATA[Vbrick Leverages Cisco Spark APIs to Help Transform Video Comms and Distribution in the Workplace]]>

Ever consider that corporate 'town halls' and 'all-hands' meetings create invaluable content your company can leverage in other ways for continued business success? Ever consider your other various meeting activities - e.g., sales presentations, customer training sessions, and product roadmap discussions - are just as invaluable? If so, realizing that they can be amplified, shared, and edited into other content, providing more value to you and your business?

If you have (and we believe you should!), what would you need to accomplish that? Video streaming, recording, content storage and management - necessities for sure, but how do you acquire all of those tools in an integrated package with an easy to use interface? Especially because this must be delivered without a hitch, even amidst the many challenges and obstacles of network compatibility and stability, with the ability to do it at scale, for potentially thousands of participants.

That's where long time Cisco Integrator Partner Vbrick comes into play. They offer a compelling, next-generation enterprise video platform that integrates with and leverages Cisco Spark to provide what we believe is a true solution, and thus is better than anything else currently available. Vbrick has been using the power of video to transform the workplace for a long time, too, in a wide variety of industries. Check out their customer list, organized across verticals, which includes premier clients like Pfizer, Novo Nordisk, Western Digital, Chevron, and Cisco (yep, we use them).

vbrick logo

Vbrick has embraced our strategic direction with integration to our cloud collaboration API's - specifically, our Cisco Spark API's. Vbrick is a great example of a long time Cisco partner that's embraced Cisco API's from the start. Why? Because they've recognized the advantages of being aligned with the superb cloud-based collaboration platform that Cisco Spark provides. Cloud-based video communications is clearly the future, and we're thrilled that Vbrick, along with many other long-time Cisco partners, are fast-tracking features that integrate with Cisco Spark.

live stream image

Figure 1: Live streaming to global audiences directly from Cisco Spark

vbrick record imageFigure 2: Automatically record and upload videos to Vbrick REV

Vbrick uses Cisco Spark API's to enable features like the recording of services from any Cisco Spark-enabled device, using the Vbrick "Rev" bot. Rev enables you to start and stop a new recording. Additionally, Rev enables you to search the recording database for content. Accessing Vbrick from within Cisco Spark is simple, too.

vbrick access within spark

Add to this the fact that Cisco Spark hardware endpoints provide movie studio quality. For example, when you do a session utilizing a Cisco DX70 system or Cisco Spark Board, it looks truly amazing.

If your company already is using Vbrick, you'll definitely want to check out these integrated Spark capabilities. If not, review the entire Vbrick offering. Together, we're a powerful, next-gen, cloud-based video collaboration, management and distribution solution for the enterprise.

https://developer.webex.com/blog/vbrick-leverages-spark-api-s-to-help-transform-video-communication-and-distribution-in-the-workplace https://developer.webex.com/blog/vbrick-leverages-spark-api-s-to-help-transform-video-communication-and-distribution-in-the-workplace Sun, 08 Apr 2018 00:00:00 GMT
<![CDATA[Cisco Spark Developers can roll out Better and Faster App Experiences with Rollbar]]>

Back in the day when I was a hard core developer working on 'complex networked multi-threaded cross platform scheduling systems' (yeah, 20 years ago, and yeah, trying to get as many of the old buzz words in…) we were concerned with the quality and stability of our code.

At the time, I was working at a start-up, and we were also required to test our own code. We got instrumentation tools, (can't remember the names) created tests, ran more tests, checked code coverage and memory usage. Then our demo 'guru' deployed the code for initial use in our demo environment.

Over the next month, even after all that work, testing, and pressure from other developers to get 'er done- problems cropped up. Problems that forced us to backtrack, by poring over days, or sometimes even weeks, of log data to try to find what the problems were. That process always took at least another week to complete. Then, we'd spend a long time trying to recreate the issue, guessing at the workflow or timing which invoked it. That was yet another big chunk of time spent.

Our development process was completely bogged down. The delays in reporting, communication, and assessment caused even more problems.

That's why I was stoked when I found out about Cisco Spark partner Rollbar.

Rollbar logo

Rollbar allows for instrumentation of code, and all the major languages like Java, Ruby, Node.js, DotNET, etc. that monitor the system. When an error or warning triggers, it takes action. What's the Cisco Spark tie-in? Rollbar integrates with Cisco Spark to provide real time communication when an issue occurs.

Rollbar Error UI

Now, in real time, as a developer, you can be directly connected with the code. With Rollbar, when an error pops up, your team gets instant messages and you can immediately look into and investigate the code with a single click to understand what the problem(s) is/are.

Rollbar image

You're no longer waiting weeks for someone else to let you know about problems. You're no longer spending a lot of time looking back at tons of logs. As an additional benefit, with Rollbar's integration with Spark, you're also tied into your development group, leveraging Cisco Spark collaboration tools to help address issues.

Rollbar Video

Send Rollbar Error Alerts to Cisco Spark

The integration with Spark gets even better. Rollbar, like Cisco, believes that security and compliance are critical components to their software story - so there's great philosophical alignment with our Cisco collaboration team. Log/error data can contain sensitive information, which Rollbar has architected key features for to protect it. Rollbar is also compliant with HIPAA and ISO27001.

Bottom line-with Cisco, Rollbar helps you develop and roll out better software faster, without compromising on security.

So if you're a Spark developer, check out Rollbar. It'll be time well-spent.

https://developer.webex.com/blog/cisco-spark-developers-can-roll-out-better-and-faster-app-experiences-with-rollbar https://developer.webex.com/blog/cisco-spark-developers-can-roll-out-better-and-faster-app-experiences-with-rollbar Sun, 08 Apr 2018 00:00:00 GMT
<![CDATA[Better Employee Communication and Engagement with Cisco Spark and Dynamic Signal]]>

-- This post is guest authored by Russ Fradin, CEO of Dynamic Signal. --

The way we consume information is different today. That's because mobile devices, over the past decade, have dramatically changed how we communicate. We text. We get alerts. We play, record and share video. In fact, 85 percent of adults now get their news from their smartphone.

Shouldn't employees also receive important information from their company on their mobiles devices, too? Dynamic Signal and Cisco makes sure you do.

Dynamic Signal logo

We're an Employee Communication and Engagement (ECE) Platform that ensures that organizations always get timely and relevant content to workers, wherever they are, with our mobile app. That's why we're announcing a new, powerful integration of Dynamic Signal with Cisco Spark.

Together, we connect organizations via mobile devices with their most valuable asset - their employees.

Cisco Spark ensures that knowledge workers (employees whose jobs involve handling or using information), who typically are employees collaborating on various projects, can quickly and easily share information. But what about other workers in an organization who are more geographically dispersed, and often aren't on laptops or desktops?

For example, let's look at a major banking institution. Half of the employees work in the corporate headquarters and collaborate using Cisco Spark. Life is good. They're armed with the information they need to succeed. The other half of the workforce, like the bank tellers, who might not use Spark, but still require critical information to do their jobs, may not have the same easy ability to access that information.

Dynamic Signal ends this "information access inequity" by delivering needed content to all employees - via whatever delivery pipeline they prefer - whether it's via Cisco Spark, the company intranet or, as is more and more frequently these days, delivered directly to them on their mobile devices.

With Dynamic Signal, communicators have the ability to deliver the same content to both the knowledge workers and the dispersed workers - keeping every employee engaged, informed, and productive. The entire organization can now be aligned around a singular vision, mission, goal.

spark image

Every employee gets what they need, in the manner they prefer, through a streamlined and modernized communication process. The Dynamic Signal Platform integrated with Cisco Spark enables employees to access content in whatever manner is most convenient to them.

Organizations can also now better measure employee engagement, and then optimize their communication strategy, so they can reach employees even better and more efficiently. It's simply a modern, streamlined solution - both for the organization and the employee.

This is the power of Dynamic Signal, now magnified with our integration with Cisco Spark.

Cisco and Dynamic Signal are a natural fit. In fact, Cisco has invested in Dynamic Signal because it sees this power of connecting all employees, wherever they are, and however they access information.

"We recognize the urgent need for Employee Communication and Engagement Platforms among our own customers and the world at large, so we're thrilled to invest in Dynamic Signal, and further our commitment to meeting the business needs of the enterprise," said Rob Salvagno, Cisco Vice President and Head of Corporate Development and Investments.

Cisco Spark enables employees to create, share, and collaborate. Dynamic Signal ensures all employees have the information they need to succeed.

Together, we are changing how work gets done.

-- This post is guest authored by Russ Fradin, CEO of Dynamic Signal. --

https://developer.webex.com/blog/better-employee-communication-and-engagement-with-cisco-spark-and-dynamic-signal https://developer.webex.com/blog/better-employee-communication-and-engagement-with-cisco-spark-and-dynamic-signal Tue, 03 Apr 2018 00:00:00 GMT
<![CDATA[ICYMI: Cisco Live! Recap for Webex Developers]]>

Imagine Intuitive

If you have not been to a Cisco Live event, you are missing out. Thousands of people attend at least one of four Cisco Live! events every year. Cisco welcomes all developers and programmers to participate in hackathons, get hands-on in labs, learn in numerous sessions, network with Cisco engineers, and enjoy a spectacular customer appreciation event. Here’s a brief recap of the last three:

Cisco Live! Cancun – November 6 – 9, 2017 ¡Bienvenido a Cancún! We showcased our APIs, SDKs, and even widgets in Mexico to many developers and partnered closely with our DevNet friends to continue educating attendees on how to learn more. Check out DevNet’s learning labs!

Cisco Live

Cisco Live! Barcelona – January 29 – February 2, 2018 ¡Gracias por todo Barcelona! Attendees ate tapas and hacked away using our APIs to build unique workflows. Check out some of the highlights, including the Keynotes and Innovation Showcase sessions. Adam Kalsey

Cisco Live! Melbourne – March 6 – 9, 2018 Bonza, Melbourne! It was a warm week in Australia and a productive one as we went onstage to talk more about our open platform and growing ecosystem. Check out the videos! Melbourne

Be sure to join us at the next Cisco Live! near you! If you cannot attend in person, there are sessions available online.

https://developer.webex.com/blog/icymi-cisco-live-recap-for-webex-developers https://developer.webex.com/blog/icymi-cisco-live-recap-for-webex-developers Thu, 15 Mar 2018 00:00:00 GMT
<![CDATA[Approved Contact and Cisco Solve the Scheduling Merry-Go-Round]]>

If you have a corporate job, I'm sure you've experienced the following 'merry-go-round' conversation when trying to set up a meeting:

_"George, can you meet at Thursday at 1?" _

_"No, Jane, sorry-how about Friday at 3?" _

"I'm in the air at that time, George. What about Monday at 4?"

"Yeah, book it, Jane. Wait, what time zone? I'm in Central."

"I'm Pacific, so it'd be 4 Pacific."

"Um, that's 6 PM my time, so no, I can't. I have a violin recital I have to be at."

"What about Tuesday at 1 Pacific, 3 Central instead, then?"

"Yes, that works-book it!"

"Oops. Wait, I have to check Bill's calendar…"

Kind of reminds you of this classic cartoon scenario, doesn't it?

Stop the scheduling merry-go-round. Booking meetings, checking calendars, and finding time windows that work for invitees is a classic, time consuming operation. It's hard enough when two people in the same company are trying to find time--it's even more frustrating when trying to coordinate between people at three or four companies--all of whom use different calendaring systems. How much time per week do you spend (more like waste) on this problem? I know I spend at least a few hours.

Cisco has invested heavily in making it easier to start meetings with our "one touch meeting" concept. Of course, it's not "one touch" to schedule a meeting.

Enter Approved Contact.

approved contact logo

Approved Contact is a Cisco Integrator Partner that has solved the 'merry-go-round' of scheduling meetings. Approved Contact has integrated with all the leading cloud calendaring solutions - Office 365, Google Calendars, Apple iCloud, and more - and enables sharing of your calendar across your list of approved contacts.

Even better, Approved Contact has also developed integrations into Cisco Spark utilizing our Spark API's, enabling participants in a Cisco Spark Space to easily book a meeting with the team using the Approved Contact calendar bot. You can search availability in different ways, find next available, and schedule your meeting quickly and easily. End result - you're way more efficient with your time and scheduling meetings! It doesn't matter if the room members are in different companies, with different calendaring systems, and/or in different time zones - Approved Contact makes it simple and fast.

approved contact image

The ROI for this solution is huge. Just run the numbers. If you save an employee an hour a month, taking into account their hourly pay rate, the Approved Contact solution for Cisco Spark can pay for itself very quickly.

For me, although while obviously important, it's actually less about the ROI, though, and more about removing the friction and inherent frustration that comes with the scheduling merry-go-round we all perform. Plus, with Approved Contact, I have more time now to get other important things done.

As a Cisco Spark developer, keep in mind that our Spark ISV development program has a specific goal to foster start-ups. Approved Contact is one of those companies we're working closely with. They're live with a few customers, offering a great solution that solves a huge problem. It's a great example of how our team supports new, innovative solutions.

So what's your call to action? If you're just getting started as a Cisco Spark developer and think you have a cool Cisco Spark integration like Approved Contact, we definitely want to hear about it.

Get started now by submitting a Cisco Spark integration to the Cisco Spark Depot.

https://developer.webex.com/blog/approved-contact-and-cisco-solve-the-scheduling-merry-go-round https://developer.webex.com/blog/approved-contact-and-cisco-solve-the-scheduling-merry-go-round Tue, 13 Mar 2018 00:00:00 GMT
<![CDATA[Waiting Is The Hard Part, But Not Anymore with Cisco Spark and Envoy]]>

When traveling for business, you know the routine: You arrive at your destination, walk in the front door, and you're greeted by the receptionist, who typically needs you to check-in, which can often be a frustrating, time consuming experience.

waiting gif

Everything from waiting thirty minutes (behind a parade of people returning), to seemingly the entire world seeing your name on the visitor list on a sign-in sheet, to missing your meeting because you thought the receptionist let the person you were meeting with know you arrived, but the receptionist thought you notified them -- yep, checking in can be a source of friction and frustration. Not the way you want to do business, right?

Well, we're happy to say that the waiting for a solution is over.

Meet Envoy**.**

Envoy logo

Envoy is a Cisco Spark Integrator partner that has developed a suite of solutions that not only take the friction out of office visits, they actually make them a pleasant experience.

integrator partner

One of these solutions is Envoy Visitors, an iPad® application that enables a digital kiosk sign-in that's quick, seamless, and easy to use.

Envoy iPad

Upon arriving, simply enter your name, your company, and the name of the person you're meeting with. Your badge, if needed, prints automatically. Once you sign in, the iPad returns to a custom home screen, so your visitor data is kept confidential-a key benefit over paper sign-in sheets.

How does Cisco Spark come into the solution equation? The person you're visiting is automatically contacted via Cisco Spark or Tropo's SMS messaging. Envoy Visitors can be deployed on more than one iPad per location, too. This is an easy way to add sign-in capacity for large organizations with multiple buildings on-site, and effectively reduce wait times for all visitors.

Cisco Spark and Envoy Visitors streamlines the sign-in process, so everyone involved can focus on the business at hand. This solution gives receptionists the space and time to be welcoming and warm while waiting for the visitor's host to arrive-which, with this integration, isn't long!

By the way, you may have used Envoy Visitors if you've visited Cisco's Meraki office in San Francisco. I first experienced their iPad sign-in at a startup in Austin, Texas.

global footprint

Many of the world's top companies choose Envoy Visitors as their sign-in solution, and since many of those same companies also depend on Cisco solutions, we think this partnership is one that can greatly improve efficiency for businesses everywhere.

trusted image

At this point you might be thinking, "Hey, nice solution, but how does this help me as a Cisco Spark Developer?"

Our goal of making Cisco Spark an open platform allows for a range of new use cases. We believe there are a plethora of solutions that would benefit from interesting integrations like this one. These types of communication integrations enforce workflow, support security, and help to ensure fast responses in connecting parties during critical situations (e.g., like having to look up the phone number for the doctor on call when someone goes into a medical emergency).

With this in mind, the Envoy Visitors use case is a great one. Envoy is in the breed of the new generation of enterprise companies that understand the value of API's. The company integrates with a range of systems such as Box, Okta, and Zapier-all of whom have open API's. Plus, Envoy has opened up their system with their own API's, allowing for their solution to be customized to fit just about any facility, location, and/or environment-another reason why their solutions are being used by so many companies.

We love that Envoy has also integrated with Cisco Meraki, since there are quite a few use cases we're seeing where Cisco Spark and Cisco Meraki go well together.

Bottom line-if you're looking to add value to the solutions you're developing for Cisco Spark, and it's the right fit for what you're developing, we enthusiastically encourage you to get a demonstration of Envoy Visitors. Let us know if you're interested in finding out more.

https://developer.webex.com/blog/waiting-is-the-hard-part-but-not-anymore-with-cisco-spark-and-envoy https://developer.webex.com/blog/waiting-is-the-hard-part-but-not-anymore-with-cisco-spark-and-envoy Wed, 21 Feb 2018 00:00:00 GMT
<![CDATA[Cisco Spark Disabling TLS 1.0]]>

Update: This change will now be implemented beginning March 17, 2018 03:30 UTC.

The Cisco Spark platform will require API clients to use TLS 1.1 or higher beginning March 17, 2018 UTC. The TLS 1.0 encryption protocol will be disabled on all endpoints to align with industry best practices for transport security. Additionally, the Cisco Spark API will require the use of clients which support the Server Name Indication (SNI) extension to TLS/SSL.

Our internal telemetry of API connections indicates that very few apps are using TLS 1.0. To prevent any service disruption after March 2 between your apps and Cisco Spark, ensure that your app’s server operating system, libraries, and frameworks support at least TLS 1.1 and the SNI extension. Consult the documentation for your app’s libraries and frameworks to ensure that they support TLS 1.1.

The following minimum versions of common libraries and tools support the SNI extension:

  • Java 1.7
  • PHP 5.3
  • Python 2.7.9, Python 3
  • Ruby (net/http) 2.0
  • cURL 7.18.1
  • wget 1.14

If you have any questions about this change, our Cisco Spark DevSupport Team is available 24/7 to help. Please contact them with your question or concern.

https://developer.webex.com/blog/cisco-spark-disabling-tls-1-0 https://developer.webex.com/blog/cisco-spark-disabling-tls-1-0 Thu, 08 Feb 2018 00:00:00 GMT
<![CDATA[Email Address Update API for Cisco Spark Now Available]]>

Continuing to provide useful APIs for our Cisco Spark Developer ecosystem, we want to give you a heads up that Cisco Spark Organization Administrators now have the ability to update email addresses for people within their organization via the Update a Person API endpoint.

Simple and easy to incorporate, to update email addresses of a person, developers just need to use the API endpoint with an authentication token, which has the spark-admin:people_write scope associated with it.

Important note: If an organization uses the Cisco Directory Connector to synchronize user accounts with Active Directory, you cannot update information for Cisco Spark users via this API. For those situations, you will still need to make changes in Active Directory.

Again, this new feature for Cisco Spark developers is now available via the Update a Person API endpoint, so we encourage you to incorporate it into your integrations for Cisco Spark today!

https://developer.webex.com/blog/email-address-update-api-for-cisco-spark-now-available https://developer.webex.com/blog/email-address-update-api-for-cisco-spark-now-available Tue, 06 Feb 2018 00:00:00 GMT
<![CDATA[Picking Your Framework to Build Bots on Cisco Spark]]>


Whether you are new to bot building or not, there is typically a big question you ask yourself whenever you start a new bot project: "How will I build it?"

That question usually begs a few more like: "Which messaging platform should I build it for?" "What programming language will I use to build it?," "Where will I host it?," and "Which bot framework should I use?"

Let's help by providing you with an overview of some of the different frameworks that are available for you to start building bots.

In today's development ecosystem, you are almost always using some kind of framework, especially for web development. If not, you would basically be manually sending cUrl requests to the different messaging platform APIs.

It's also important to specify what we mean by "framework." In this case, we consider "frameworks" as an additional layer of abstraction to a framework like ExpressJS, for example, with added features embedded within that framework to cater to bot developers solely - i.e., a bot framework or SDK.

Additionally, most bot frameworks are usually tied to a specific messaging service such as Facebook Messenger's Bot SDK or Microsoft's Bot Framework; or even Line, WeChat, Slack, and Viber's SDKs. The advantage here is that you know that the SDK is specifically thought out for that particular platform. However, it also means your bot will be tied solely to that specific messaging platform.

However, some bot SDKs like "Botkit", give you the ability to integrate your bot with multiple messaging platforms. This allows you to "build it once, deploy to all." Additionally, services like Message.io act as a gateway between your bot and the different messaging platforms' APIs to give you cross-platform interoperability.

It is true these bot frameworks provide simplicity and allow you to rapidly prototype a complex bot faster than if you were to solely rely on backend frameworks like ExpressJS. The main reason is that they bundle the requests (e.g., send message, receive message, send a file) into simple methods (that look almost like English!) and provide easy callback structure so as to create simple "hear-say" functions.

Take the example of a simple '/hello' command on Flint:


Another reason these bot frameworks provide added simplicity is they usually integrate at their core with middleware services and plugins, and take the hassle out of having to integrate them yourself with your backend framework (like ExpressJS).

For example, Botkit's available plugins span NLP, Storage, Stats, and CRM solutions with the popular API.AI (now DialogFlow), Wit.ai, IBM Watson, MongoDB, Firebase, or Keen.io. These "native" plugin integrations eliminate the hassle of having to import and integrate them yourself in a coherent logic (and ordered code!), as opposed to if you were to use more "bare bones" backend frameworks like ExpressJS.

The choice is yours, of course, and choosing to use these plugins and SDKs will most likely depend on your level of comfort with these services' APIs, the framework you're implementing them with, and how fast you write clean and ordered code.

On the other hand, the main advantage of NOT using these SDKs is that you get to organize and structure your code the way you choose to from the ground up. This can give you more flexibility - especially if you are planning to build an extremely complex bot - and also would likely make your codebase more lightweight (assuming you are actively refactoring to make it so or that you care at all about clean code!). Additionally, choosing not to use these bot frameworks allows you to not be tied to the plugin services that are available on them, and to import the ones of your choice as you please.

Comparing the Bot SDKs for Cisco Spark

As we've stated, you've got lots of options to work with. Here are three frameworks that you can use to build bots on the Cisco Spark platform, one specifically for use with Cisco Spark, the other two, multi-platform.


Language: NodeJS

Description: NodeJS bot SDK specifically for Cisco Spark with native persistent storage.

Available Messaging Platforms: Cisco Spark only

Available Plugins: Persistent storage (native)

Example of a hear-say command:

hear-say command1


Language: NodeJS

Description: Fully fledged multi-platform bot SDK and framework with connectors to various services for NLP, Stats, and CRM.

Available Messaging Platforms: Cisco Spark, Slack, Facebook Messenger, Twilio SMS, Microsoft Teams

Available Plugins: Microsoft Luis, Api.ai, IBM Watson, Recast.ai, Wit.ai, Rasa, Mongo, Redis, Datastore, Firebase, Postgres, CouchDB, Botimize, Botkit Studio Metrics, Botmetrics, Dashbot Facebook, Dashbot Slack, Keen, Wordhop

Example of a hear-say command:

hear-say command2


Language: NodeJS & Java

Description: The particularity of Gupshup is that it also provides you with a fully hosted development environment - like a Bot Builder IDE. It does a lot more than we need to cover here, but Gupshup also has a NodeJS SDK, hence the reason why we count it among the frameworks covered here.

Available Messaging Platforms: : Cisco Spark, Telegram, Hipchat, Skype, Kik, Line, Slack, and many more.

Available Plugins: API.AI (DialogFlow), Gupshup AI, Serverless Webview

Example of a hear-say command: Gupshup works a little differently than the other frameworks. In fact, Gupshup lets you create your own conversation logic as a scripting language.


The messaging handler will actually invoke the scripting handler method.


To wrap it all up, if you are satisfied with the plugin services offered by any of these bot frameworks we've referenced, AND that your bot uses many or most of the capabilities of these services, AND you are not too concerned about being 'lightweight', or, you just like the way they have structured the requests into something that sounds almost like English - go ahead and use them. Pick your framework and go build that new bot for Cisco Spark!

https://developer.webex.com/blog/picking-your-framework-to-build-bots-on-cisco-spark https://developer.webex.com/blog/picking-your-framework-to-build-bots-on-cisco-spark Mon, 05 Feb 2018 00:00:00 GMT
<![CDATA[Driving Positive Change in Higher Education Student Retention]]>

Ask leaders of higher education across North America about their biggest challenge. You’ll get a consistent answer: student retention. The impact of a student dropping out can be staggering for both the institution and the student. The school has invested in that student’s educational development. And the student often leaves burdened by loans without the earning potential needed to address them.

For schools, a key to improving student retention lies in leveraging big data analytics. Specifically, using data to identify the students most likely to drop out and finding a way to intervene before it’s too late. But intervention isn’t easy.

  • How do you identify which students are most at risk?
  • How do you know which students are slipping away?
  • How can administrators provide support to students at crucial points?

This is the exact problem that Involvio, a Cisco Spark integrator partner, solves for institutions around the world. Involvio offers a compelling combination of mobile applications, AI, and communication capabilities designed to improve student engagement and retention. And it’s all built on Cisco Spark APIs.

Involvio’s app integrates with leading student information and learning management systems to simplify student access to services. Schools can customize the app with branding, programs, student activities, sporting events, financial aid, public safety, housing, and more.

Involvio app

The app can identify which students are taking advantage of particular services and how engagement is increasing—or fading. With this information, Involvio can programmatically check up on students. By comparing current engagement to that of students who have dropped out, Involvio’s AI builds rules that help predict which students may be at risk and automate critical intervention processes.

Here’s where Cisco comes in. Schools communicate with students through the Cisco Spark platform. Staff can initiate a high-quality video interaction from within the Involvio app, such as connecting an advisor with a student at a time when she or he needs it most.

student connection

Personal interaction could make the difference between a student staying or dropping out, so video connectivity is critical. Busy students can find it challenging to set up walk-in appointments. And at-risk students may consider an in-person meeting intimidating. Video on a mobile device is more comfortable for the student, while providing both student and advisor with an opportunity to get to the root of the problem. (All while capturing rich utilization data).

With a Cisco video device such as a Cisco DX80 or Cisco Spark Board in an administrator’s office, the images are crystal clear. Combining Cisco Spark technology with Involvio’s app provides the best remote interaction possible, reinforcing the school’s brand and showcasing its ability to more effectively interact with students in today’s mobile-enabled world.

Involvio’s solution can not only help higher education address student retention challenges, but also help students have a more fulfilling experience by keeping them engaged. Cisco is proud to play a key role in enabling this solution.

https://developer.webex.com/blog/driving-positive-change-in-higher-education-student-retention https://developer.webex.com/blog/driving-positive-change-in-higher-education-student-retention Mon, 22 Jan 2018 00:00:00 GMT
<![CDATA[Why You Should Join the Cisco Spark Developer Ecosystem]]>

Happy New Year! A New Year brings the promise of new possibilities for all of us, and as we roll into 2018, have you thought about the possibility of joining the Cisco Spark developer ecosystem? If not, here is why collaborating with us should be one of your top resolutions for the New Year.

First off, Cisco is the global leader in collaboration, with an unparalleled sales organization that supports a global network of exceptional channel partners. We market and sell to almost every company in the world, and have undisputed global reach. In fact, 95 percent of Fortune 500 companies are using video-enabled Cisco collaboration solutions* (like Cisco Spark).

In 2017 alone, we introduced Cisco Spark Assistant, the industry’s first voice assistant designed specifically for the enterprise, adding artificial intelligence (AI) capabilities to Cisco Spark. Plus, we added new complementary services, launched new supporting hardware like the Cisco Spark Room 70, and showcased more use cases for Spark.

Spark Room 70

From a development perspective, Cisco Spark was designed from the start with API enablement at its core, so as a Spark development partner, you can integrate this powerful Cisco collaboration solution into your own solutions in ways never before imagined.

What else will you gain by joining?

Get started by listing your app on the Cisco Spark Depot, our growing catalog of integrations and bots for businesses of all shapes and sizes. The depot is where Cisco Spark users go to take advantage of our extensive developer partner ecosystem. It’s free for you to list your app there, where it will be prominently featured. In addition, Cisco sales teams are updated on new and improved solutions as they’re introduced.

Cisco Spark Innovator

Go to market with us – a Massive Market Opportunity

Cisco Spark Integrator Programis one of our newest partnership designations. This is an invitation-only program for select developers, recognizing the solutions you develop, and acts as a front door for you to market your solution to the entire Cisco partner and sales channel.

Integrator Partner

Additional benefits include:

  • Joint marketing - We drive your marketing content through our channels, using the same go-to-market vehicles we use with our own products. Educate the Cisco sales teams on your solution and how it adds tremendous value to Cisco Spark.
  • Digital marketing package - Our digital marketing package includes a Cisco Integrator logo, logo guidelines, email templates, brochure templates, and more. Showcase your partnership with one of the leading enterprise software companies in the world.
  • Event prioritization - Our ISVs receive prioritized conference booth space, speaking opportunities, and joint messaging at industry and Cisco only events.
  • Joint sales incentives and contests - We continually offer ecosystem-focused incentive programs to our sales teams to keep our integration partners like you top of mind.
  • Account connections - We proactively reach out to account teams to support joint Cisco and ISV sales activities. You can connect with our Cisco sales teams in a way no other program can provide.

Cisco Spark Ecosystem Sales Program

This is another invitation-only initiative that will get your integrated offer on the Cisco price list with your very own SKU through the Cisco SolutionsPlus process. Every Cisco seller (all 20,000 of them!) and channel partner has the ability to resell your product. This is another great program we offer to Cisco Spark developers for mutual benefit.

The power of collaboration

I can’t emphasize it enough—when you join the Cisco Spark developer ecosystem, not only will you join a community of innovators, but you’ll also be able to add enterprise-grade collaboration to your own platform and services in a cost- effective, high-quality manner.

113 million professionals around the world are utilizing Cisco collaboration solutions like Cisco Spark and WebEx, enabling:

Ready to get started?

If some or all of the above sounds good to you, then I hope you’ll join us in providing the best collaboration user experience possible for Cisco Spark users in 2018 and beyond. Start by discovering the Cisco Spark Depot, build an integration or bot using our APIs, embed video into your app using our SDKs. For more info on our invitation-only programs, email us at sparkecosystempartner@cisco.com.

If you are using Cisco Spark today, become a Spark Ambassador.

Jason Goecke, VP/GM Cisco Spark

https://developer.webex.com/blog/why-you-should-join-the-cisco-spark-developer-ecosystem https://developer.webex.com/blog/why-you-should-join-the-cisco-spark-developer-ecosystem Wed, 10 Jan 2018 00:00:00 GMT
<![CDATA[Android SDK Beta Release for Cisco Spark Now Available]]>

Good news for Android developers — the Android SDK for Cisco Spark is now available as a public beta!

spark android

If you’re an Android developer, our new Cisco Spark Android SDK lets you integrate secure and convenient Cisco Spark features in your apps, including:

  • Calling: Make and receive audio and/or video calls to Cisco Spark users
    • Supports calling SIP endpoints and PSTN numbers
  • Messaging: Send and receive messages, and participate in 1:1 and group spaces

video call

Check out our Android SDK Example App to start coding faster. It’s open source and it demos all the SDK features.

The Cisco Spark Android SDK gives you the ability to customize your app and to seamlessly access Cisco Spark’s powerful collaboration features without ever having to leave your mobile app. Use the Android SDK to apply your own UI for customization and still use client-side API calls to embed Cisco Spark voice and video calling directly into your application. With the Cisco Spark Android SDK, you can also connect end users from your app to any Cisco Spark app/device and SIP device.

We’re looking forward to the apps you create with the new SDK!

If you have any questions or feedback about the new Android SDK for Cisco Spark, or if you run into any issues during development, our Cisco Spark DevSupport Team is available 24/7 to help. Feel free to reach out to them at any time.

Happy coding!

https://developer.webex.com/blog/android-sdk-beta-release-for-cisco-spark-now-available https://developer.webex.com/blog/android-sdk-beta-release-for-cisco-spark-now-available Wed, 20 Dec 2017 00:00:00 GMT
<![CDATA[Events API for Cisco Spark Now Available]]>

This past August, we announced limited availability of the Events API for Cisco Spark. We’re now making it available to all Cisco Spark developers!

The Events API provides access to user activities within Cisco Spark after they have occurred. For example, perhaps you need to retrieve every message sent by a particular user to comply with a legal discovery process, or you need to know which Cisco Spark rooms someone joined or left. The Events API will give authorized users access to this information quickly and securely.

Additional features include integrating the Events API with your existing Data Loss Prevention (DLP) software to check for policy violations and to take action to resolve issues. Events available for monitoring include activities such as posting messages, sending content such as files, and group space membership changes. You can also integrate the Events API with your existing archiving software to archive an unlimited amount of Cisco Spark data. (Note: For access to events older than 90 days, you will need the Pro Pack for Cisco Spark Control Hub).

With the addition of the new Compliance Officer role in Cisco Spark Control Hub, we’ve also added several new authorization scopes, which give compliance users access to more information about their organization’s usage of Cisco Spark.


Now, an organization’s compliance officer will have access to retrieve and delete messages and space memberships, and retrieve information about spaces and teams.

For more information about the Events API for Cisco Spark and the new compliance scopes, check out the Compliance Guide in our Cisco Spark API documentation.

Finally, a special thank you to all of our Cisco Spark partners, developers, and customers who participated in early trials of our Events API. Your great feedback helped us resolve issues and add product enhancements, making this release of our Events API an excellent product for everyone. Enjoy!

https://developer.webex.com/blog/events-api-for-cisco-spark-now-available https://developer.webex.com/blog/events-api-for-cisco-spark-now-available Mon, 11 Dec 2017 00:00:00 GMT
<![CDATA[SDK and Widget Updates for Cisco Spark are Now Available]]>

We’ve been hard at work developing brand new ways to use our SDKs and Widgets in your Cisco Spark applications. This month, we’re releasing new versions of our iOS SDK, Browser SDK, and Widgets. Each one of them is jam-packed with new features and benefits. Let’s take a look!

Cisco Spark iOS SDK Updates

In addition to the current calling features, you can now use the Cisco Spark iOS SDK to participate in multi-party, group space calls and see shared presentation content. We’ve also developed another example app to demonstrate how you can harness the power of the Cisco Spark platform in your apps. Additional details include:

  • iOS 11 support: Develop for the latest iOS release from Apple.
  • Group space calling: Start or join meetings in group spaces right from within the SDK. Receive notifications for new meetings and join them easily.
  • View shared content: Now, shared meeting content, such as presentations, can be viewed. Also, you’ll be able to view shared content and video from Cisco Spark meeting participants simultaneously.
  • Buddies sample application: See a real-world example of using Cisco Spark messaging and meeting features in a brand new demo app, Buddies.

phone app

Browser SDK Updates

The Cisco Spark Browser SDK already lets you make and take calls with your Cisco Spark contacts, but now you can call anyone with an SIP address. On top of that, you can also participate in multi-party, group space calls. Here’s what else is new:

  • Group space calling: Start or join meetings in group spaces right from within a browser.
  • SIP and DTMF support: Call anyone with a SIP address. Plus, if you find yourself in an IVR menu, you can now use DTMF to navigate your way through it.
  • Bandwidth controls: Limit the amount of bandwidth used by the SDK for calling features.

App browser

A Widening Array of Cisco Spark Widget Features

Utilizing Cisco Spark Widgets, you can already easily add messaging and meeting features into your web apps. Now, our widgets are getting some new features to make them even more powerful, including:

  • Group space messaging: Say goodbye to being limited to just 1:1 chats. With our new Cisco Spark Space Widget, now users can join group spaces, chat with multiple people, and even @mention them.
  • Manage people in group spaces: Users can now see who’s in a group space and add/remove people from spaces.

spark widget

  • Group space calling: Users can also now start or join meetings in group spaces right from within the Space Widget.
  • SIP calling: The Cisco Spark Space Widget can now place calls directly to SIP endpoints.

So What’s Up Next?

Stay tuned, because we’ll soon be releasing a public beta of the Cisco Spark Android SDK. Be sure to watch the blog for updates or check out the Android SDK in early December.

In the meantime, get started with these great new SDK features in your applications today!

https://developer.webex.com/blog/sdk-and-widget-updates-for-cisco-spark-are-now-available https://developer.webex.com/blog/sdk-and-widget-updates-for-cisco-spark-are-now-available Mon, 27 Nov 2017 00:00:00 GMT
<![CDATA[New and Improved Submission Form for Cisco Spark Depot is Here!]]>

We’ve been working hard to make it easier than ever for you as a Cisco Spark developer to submit new integrations and bots to Cisco Spark Depot, the home for innovative and useful integrations and bots to enhance Cisco Spark and accelerate business outcomes.

The fruits of our labor, you ask? A new, improved submission form, now available on the Cisco Spark for Developers portal.

We think our new form offers you a much better user experience. It also speeds up our review process, empowering the Cisco Spark review team with the ability to review and approve new integrations and bots you’ve developed for posting to the Cisco Spark Depot faster.

New submission form features and benefits

  • You can now easily upload and edit custom files directly, including images and screenshots, instead of having to create Content Delivery Network (CDN) URLs (yes, we’ve felt your pain there).
  • You can also now submit your new integrations and/or bots directly from the My Apps section where you provisioned them, so you no longer need to worry about searching and submitting the correct app ID.
  • There are also instant checks now for most of the submission fields. This reduces the overall time of the review process, since our reviewers don’t have to make as many fixes after submission.
  • After you make a submission, you can edit and check on its status directly within the My Apps section in the Cisco Spark for Developers portal at any time.
  • A submission ticket is now instantly created and assigned to our 24x7 Review team to immediately start the review process. This eliminates delays using the previous, manual ‘hand off’ review process, ensuring that your submissions are now reviewed instantly. Plus, you can easily communicate with the review team now through the ticket itself.


Simple and fast, right?

Finally, we also appreciate that it can be difficult to select an icon, in addition to choosing the correct size and generate a CDN URL–all while you are in the midst of provisioning a bot and primarily thinking of how to build your functionality. So, as icing on the cake, we’ve introduced default icons to choose from. Translation? Now it takes just five seconds to provision your bot!


We’re confident you’ll want to take advantage of our new submission form. As you know, not only do Cisco Spark integrations and bots help end users work smarter while they work together, we’re helping you work smarter and better together with us.

Our new submission form to accelerate the pace of adding new Cisco Spark integrations and bots means further accelerating business outcomes for everyone. So, go forth, submit away, and prosper!

https://developer.webex.com/blog/new-and-improved-submission-form-for-cisco-spark-depot-is-here- https://developer.webex.com/blog/new-and-improved-submission-form-for-cisco-spark-depot-is-here- Mon, 20 Nov 2017 00:00:00 GMT
<![CDATA[Building the Perfect Bot for Cisco Spark]]>

You may recall Don Henley of Eagles fame, who crafted one of the best rock albums of all time, “Building the Perfect Beast.” At the time, Rolling Stone magazine referred to it as “meticulously crafted and programmed.” The title song’s refrain goes:

“And now the day is come

Soon he will be released

Glory hallelujah!

We're building the perfect beast.”

So indulging this metaphorical theme (thanks, Don), if you will, how do you, as a Cisco Spark Developer, embark on “Building the Perfect Bot?”


We’ve got the answers here on Cisco for Spark Developers. These include Cisco best practices when building a new bot that will help you and your bot improve the functionality and overall usefulness of Cisco Spark.

What are bots in Cisco Spark?

Many Cisco Spark bots reside on the Cisco Spark Depot and are identified by a “bot badge” that’s overlaid on the bot’s thumbnail:

Datadog logo

DataDog by Kore.ai, Inc.

Just click on the title, and the hyperlink takes you to the bot and further details on it.

Users can add bots in Cisco Spark via the Spark Depot or in Cisco Spark using the bot’s e-mail ID (e.g. ToChineseSimplified@sparkbot.io). Users can create a private conversation to talk with a bot directly or can add it to an existing space with others. In the latter, for security reasons, bots can only see messages in which they are @mentioned.

How to Build the Perfect Bot

The bots you create for Cisco Spark should always be focused on improving the user experience. With that in mind, beyond creating the bot, it’s crucial that you include/provide clear instructions to guide users on how to use your bot.


As you know, bots started out as very simple, very basic tools for people to interact with (e.g., chatbots) to complete simple, basic tasks. As bots have increased in sophistication and capabilities, Cisco wants to ensure those you are planning to build will effectively enhance the capabilities and usefulness of Cisco Spark.

With that in mind, check out these Cisco Spark ‘bot building’ best practices below.

For Effective User Interaction, we recommend:

  • Create a help guide for users – Don’t assume they’ll immediately know what your bot is for and/or how to use it. Building and providing a simple, companion help menu is a great way to achieve this.
  • Ensure users have control over the bot – If it is a broadcast or notification bot, be sure to have a command like “edit notifications” that can easily allow users to edit or delete their bot activity, including how to unsubscribe from the bot, if desired. Be sure to list this command in your help menu, too. If you need help building this key component, check out this previously posted Cisco blog explaining how to accomplish this.
  • Listen to what your bot’s users have to say – Include a “feedback” command to accept feedback directly from Cisco Spark users. In addition, we encourage you to include a “support” command so you can receive bug reports.
  • Include basic commands – Your bot needs to be able to respond to basic and common commands, such as “@BotName help” and “@BotName hi.” For Cisco Spark users, it’s a common, intuitive way they start an interaction with a bot.
  • Include error handling – Your bot also needs to be able to respond to any commands it doesn’t recognize. For example, a response to an error could be, “I’m sorry, I don’t recognize that command,” followed by a list of sample commands to try to resolve the error.
  • Consider utilizing NLP – Natural Language Processing (NLP) is an alternative to creating a command driven bot. Services like API.ai and Zenbot integrate with Cisco Spark to enable you to incorporate NLP into your bot. Another option is Botkit, which has plugins including IBM Watson, API.ai, WIT.ai, and Luis.ai that you can leverage.
  • Communicate new features – As you add new functionality and/or commands to your bot, enable it to inform users by including a special command or broadcast.
  • Simplify option selection – Number your options instead of just naming them, so the user can choose and act on one without having to type out the full word or phrase.
  • Create effective message posting to spaces – Several tips in this regard include:
    • Use Markdown to format all links as hyperlinks, and to format your messages with spacing, line breaks, and bullets for better readability, eliminating ‘mashed up’ walls of text. The Spark for Developers website’s Formatting Messages page is chock full of examples to help you.
    • Avoid hammering spaces with many successive messages, since a bot that takes over a space will often be quickly kicked out. Instead, either group them together in larger, formatted messages or insert delays so they’re delivered more slowly/methodically.
    • Since the Spark user community is global, consider giving the user customization options for things vital to interacting with your bot, but that may vary globally (e.g., metric versus imperial measurements). Communicating the wrong terminology can create user misunderstandings and confusion of what the bot is posting, rendering it useless.
    • Communicate when your bot encounters an error message (e.g., whenever Spark API calls (e.g., GET, POST on /X resource) are down and throwing out specifically 5xx error codes (i.e., excluding/messages), so users are aware there is/are (a) problem(s).

For Creating Naming Conventions, we recommend:

  • Naming what it does – Name your bot to what it does (e.g., “SparkHelp”). If you prefer to personalize your naming, avoid using actual personal names, such as John Doe, to avoid your bot being confused with an individual.
  • Name clearly and simply – Abbreviated names when your bot is mentioned, e.g., “The Best Bot,” might be tagged as just “The” when mentioned in a group space, which could make reference to it unclear. We recommend that bot names contain at least three unique letters in the first word (i.e., don’t use “The”), so that they accurately display for “quick tagging.”

Finally, be prepared to effectively address and resolve potential issues with using/interacting with your bot by considering and providing solutions for these bot edge test cases, including:

  • In a space with many users (e.g., 20 or more), what happens if multiple users @mention your bot simultaneously?
  • What happens if your bot is added to a space from which it was previously removed?
  • What happens if a user talks to your bot using similar words as your commands, but not the exact matches?
  • What happens if a user sends an extraordinary amount of requests (e.g., 1,000 messages a minute) to your bot?
  • If your bot has an auto-reply feature, does it prevent looping between other bots with a similar feature?

Make the Metaphor a Reality

In conclusion, remember good communication is essential to building a useful and successful bot for Cisco Spark. If your bot is hard to understand and communicate with, it makes it difficult to use, and that means Spark users will stop using it. That’s why we’re here to help. You’re a vital part of the Cisco Spark ecosystem, and thus we encourage you to consider implementing these suggested best practices for our continued mutual success.

To learn more, we also recommend you visit https://developer.ciscospark.com/bots.html


So go forth and meticulously craft, program, and build that perfect bot for Cisco Spark, so you can paraphrase Don Henley’s refrain:

“And now the day is come

Soon it will be released

Glory hallelujah!

We're building the perfect bot.”

https://developer.webex.com/blog/building-the-perfect-bot-for-cisco-spark https://developer.webex.com/blog/building-the-perfect-bot-for-cisco-spark Wed, 15 Nov 2017 00:00:00 GMT
<![CDATA[Introducing Open Source Starter Kits]]>

Since the launch of the Cisco Spark for Developers program in December 2015, we have seen an explosion of developers building innovative and unique solutions on top of Cisco Spark. Many of our customers use the Cisco Spark Depot to discover turnkey integrations and bots to enhance their Spark experience. At the same time, we have seen huge demand for bots built custom to the needs of the organization and deployed in environments controlled by that organization. In fact, approximately 50 percent of all new chatbots used on Cisco Spark today are developed and hosted directly by our customers.

The reason for this surge in custom bots is primarily because the line of business applications that our enterprise customers have deployed are often heavily customized from a standard offering. This could be something as simple as adding new custom field mappings but in many cases, this involves bespoke API changes. In addition to customization, certain customers choose to host their chatbots in their preferred cloud (public or private), or even on premise.

We want the process of building custom bots on Cisco Spark to be as frictionless as possible, so today we are announcing a new initiative called Cisco Spark Starter Kits. Cisco has worked with the Cisco Spark Ambassador community to provide Open Source Starter Kits for some of the most popular lines of business applications, all of which can be freely customized and deployed in your preferred cloud.

The aim of these Starter Kits is to provide Spark developers like you access to the source code of well-written Bots/Integrations that work with the standard configuration of popular third-party applications. You can then take the source code and customize it to suit your purposes. All Starter Kits are licensed under the MIT License, so they are as permissible as possible, allowing you to make changes and use them however you wish.

Each Starter Kit Listing consists of a GitHub repository link to the source code. The language, bot framework, and storage technologies are also outlined in each listing. To make it easy for you to get up and running, each Starter Kit has a pre-composed Dockerfile and a Deploy to Heroku button, enabling you to deploy a Starter Kit in less than 10 minutes.

Initially there are 12 Starter Kits available, these range from popular enterprise applications like Service Now and Jira to Polling and HR Onboarding use cases.



As a member of the Cisco Spark for Developers community, we encourage you to get involved with Open Source. If you develop an enhancement for any of the Starter Kits which you believe would benefit the community, and you want to share it, we'd love to see you submit a pull request. Alternatively, if you want to develop something new and want to list it as a Starter Kit, you can review the contributing guidelines here.


Open Source Starter Kits are not a Cisco product, but a collection of awesome projects which have been built by your peers, namely, the Spark Developer community. They are provided 'as is', so if you need support or have a feature request, you can raise it in the issues section of the respective GitHub repository. We would ask that you don't raise issues or feature requests with the Cisco Spark for Developers support team, as they will direct you to the relevant repository.

Go forth and prosper!

https://developer.webex.com/blog/introducing-open-source-starter-kits https://developer.webex.com/blog/introducing-open-source-starter-kits Tue, 07 Nov 2017 00:00:00 GMT
<![CDATA[Introducing the Cisco Spark Events API]]>

The new Pro Pack for Cisco Spark™ Control Hub released this week provides you with advanced security, compliance, and analytics functionality right in the Cisco Spark Control Hub. Along with this release, a new Events API has been added to give developers access to events happening with their Cisco Spark organization.

You can use the Events API to integrate with your existing Data Loss Prevention (DLP) software to check for policy violations and take action to resolve any issues. The events you can monitor include posting messages, sending content such as files, and adding users to spaces. You can also use the Events API to integrate with your existing archiving software to archive an unlimited amount of Cisco Spark data. For access to events older than 90 days, you will need the Pro Pack.

The Events API provides access to activities within Cisco Spark after they have occurred. Perhaps you need to retrieve every message sent by a particular user to comply with a legal discovery process, or you need to know which rooms someone joined and left. The Events API will give you access to this information quickly and securely.

The Events API is currently in Limited Availability. To gain access to the API, please submit a ticket to our Cisco Spark DevSupport team by emailing devsupport@ciscospark.com with your organization information.

We focus on providing you the best features and experience. If you have any questions, feel free to reach out to us at devsupport@ciscospark.com or join the DevSupport Cisco Spark room. Follow us on Twitter to stay updated.

https://developer.webex.com/blog/introducing-the-cisco-spark-events-api https://developer.webex.com/blog/introducing-the-cisco-spark-events-api Thu, 24 Aug 2017 00:00:00 GMT
<![CDATA[Adding an Unsubscribe Feature to Your Bot]]>

When you’re in a Spark space with a bot and you want to stop getting notifications from that bot, you can simply leave the space or remove the bot from the space. As a developer, your bot even can subscribe to a membership webhook to get notified when someone leaves or removes your bot, allowing you to handle subscription status updates in your backend.

Have you ever had trouble leaving a 1:1 Spark space with an unrelenting bot? Since a Spark user can never truly leave a 1:1 space (whether it is with another user or a bot account), it can become frustrating when there is no way for them to stop a bot from sending automatic messages to the space. For example, if a Spark user enters a 1:1 space with a bot that continuously posts messages every time an RSS feed is updated.

In 1:1 spaces, those kind of Spark bots can continue to generate messages even if you close or attempt to leave the space. This can become even more confusing since the user will still receive a response that implies that the space has been left successfully.

In a group space, you’d be able to use the membership deleted webhook to get notified that someone doesn’t want to talk to your bot anymore, but in a 1:1, the membership deleted webhook never fires, since the person isn’t actually leaving the 1:1 or ejecting your bot from it. Your applications get no notification at all that the user even attempted to leave the space.

To remedy this issue, the onus is on the developer to ensure there is a way for a Spark user to stop receiving messages. Incorporating a UI and workflow option in the bot application to handle an unsubscribe feature is especially necessary when a bot is designed to send unprompted messages.

One way this can be done is shown in the node.js snippet below. This is a simple example, showing a bot application that updates a database to keep track of the users' subscription status and can make changes as necessary, depending on what their status is. The code is broken down and briefly explained here. However, to see the code snippet in its entirety, please scroll down to the end.

To begin this example, you will first want make sure that the Express library is installed, as well as a RESTful and database library of your choice.

// This code is under the assumption that you have installed:   
//  \- Express   
//  \- A RESTful library   
//  \- A database library

Next, include the two general functions for this application. You will want a SendRequest function to send the requests and an UpdateTable function, which will continuously update the table that tracks the status of each user. Inside the curly brackets, you will write what you would like the function to handle.

// General Functions   
// Handles Sending Requests  
var sendRequest (myURL, myMethod, myHeaders, myBody, callback) { /\* ... */ };  

// Handles Updating Database Table  
var updateTable (myTableID, myKey, myValue) { /\* ... */ };

The previous steps are completed before your endpoint is generated. Once they are complete you will add the following portion to generate the endpoint for your webhook, call the sendRequest function, and use GET to set Token as the environmental variable.

app.post('/spark/receive', function (req, res) { // Endpoint for your webhook   
   sendRequest( // Get message details   
      '[https://api.ciscospark.com/v1/messages/](https://api.ciscospark.com/v1/messages/)' + req.body.data.id,       
      // GET TOKEN as environmental variable   
      {'Content-type':'application/json; charset=utf-8', 'Authorization':'Bearer ' + process.env.TOKEN;}, {}, // No body needed for GET request

Within the sendRequest function, you will also define the myResponseBody function, which sends the request to get the message content and controls the unsubscribe feature.

function(myResponseBody) { // Sends request to get the message contents   
         // Additional conditional code to handle other message contents   
         // Handle 'Unsubscribe' -- Start   
         if (myResponseBody.text == 'Unsubscribe') {         
               'subscribed', // Key indicates subscribed  
               'no' // New value to indicate subscription status as "no"   
         // Additional conditional code to handle other message contents   

Below is the full snippet in its entirety.

// This code is under the assumption that you have installed:   
//  \- Express   
//  \- A RESTful library   
//  \- A database library  

// General Functions   
// Handles Sending Requests  
var sendRequest (myURL, myMethod, myHeaders, myBody, callback) { /\* ... */ };  

// Handles Updating Database Table  
var updateTable (myTableID, myKey, myValue) { /\* ... */ };  

app.post('/spark/receive', function (req, res) { // Endpoint for your webhook   
   sendRequest( // Get message details   
      '[https://api.ciscospark.com/v1/messages/](https://api.ciscospark.com/v1/messages/)' + req.body.data.id,       
      // GET TOKEN as environmental variable   
      {'Content-type':'application/json; charset=utf-8', 'Authorization':'Bearer ' +    process.env.TOKEN;}, {}, // No body needed for GET request   

      function(myResponseBody) { // Sends request to get the message contents   
         // Additional conditional code to handle other message contents   
         // Handle 'Unsubscribe' -- Start   
         if (myResponseBody.text == 'Unsubscribe') {         
               'subscribed', // Key indicates subscribed  
               'no' // New value to indicate subscription status as "no"   
         // Additional conditional code to handle other message contents   

We hope this information is helpful. If you have any questions about this snippet or others, please feel free to contact us at the Spark space #spark4devs.

Phil Bellanti and Timothy Scheuering also contributed to this post.

https://developer.webex.com/blog/adding-an-unsubscribe-feature-to-your-bot https://developer.webex.com/blog/adding-an-unsubscribe-feature-to-your-bot Tue, 25 Jul 2017 00:00:00 GMT
<![CDATA[Visit the Cisco Spark Ecosystem at Cisco Live in Las Vegas]]>

Cisco Live!

At Cisco Live! US 2017, many of our Cisco Spark Ecosystem Partners will be participating in full force whether that is exhibiting in the Collaboration Partner Village, in the World of Solutions or showcasing the technical abilities of their offers in the DevNet Zone. Each vendor will be able to take Cisco partners and customers through full demos and be able to discuss the business critical problems their solutions help solve. If you happened to attend Cisco Live US last year, you may have noticed a handful of partners exhibiting a solution. This year we have 20+ Cisco Spark integrated sponsors on site!

Check out a few of these incredible ecosystem apps with the links below before you go to the show. And of course, if you’re interested in learning more feel free to reach out to us on Cisco Spark or Twitter!

  • Local Measure - With the integration of Local Measure, Cisco Spark is a powerful customer experience tool, enabling teams to receive real-time feedback from their customers and engage with those VIPs to provide a best-in-class customer experience. With Cisco Spark, customer alerts from Local Measure are seamlessly pushed into a Cisco Spark Space, allowing front-line teams to respond or engage as necessary.
  • VBrick - Think of VBrick as the ‘YouTube of the Enterprise’ for all your SaaS video needs. VBrick has a video creation, management, and distribution platform that works perfectly in a number of Cisco Collaboration environments including Cisco Spark. Record or live stream your meetings, post updates to Spark, Search for your videos in Spark and utilize Cisco’s award winning line of video endpoints as your recording or live streaming studio.
  • Approved Contact - Identify available meeting times for everyone in a Cisco Spark space instantly, even across organizations. Approved Contact works with any business calendaring solution including cloud based O365, Google Apps, iCloud as well as premise based Exchange and Lotus Notes.
  • Singlewire - Comprehensive emergency notification and incident management using InformaCast and Cisco Spark. Send or receive mass/emergency alerts within Cisco Spark and tie to CUCM / HCS devices for an ideal solution for customers who are leveraging a hybrid environment or may be great candidates to upgrade to a Cisco Spark Flex Plan.
  • Qwasi - Qwasi is mobile user engagement platform that ties inbound SMS messages to the appropriate Cisco Spark Spaces for a variety of loyalty or expert use cases.
  • Altocloud - Solution that uses customer journey analytics to identify prospects of interest on a company’s website and instantly alert team members via Cisco Spark. Sales reps can immediately engage prospects matching interesting personas, directly from within Cisco Spark via messaging or real-time video calling.
  • Actiance - The Actiance Alcatraz product provides a modern, cloud-based content archival solution that captures and preserves Cisco Spark events ideal for compliance-minded customers in highly regulated industries.
  • Kore - Kore.ai specializes in AI-rich conversational solutions designed to bring faster, actionable, more human-like communication back into the daily interactions enterprises have with their customers, workforce, systems, and things. Kore offers dozens of Cisco Spark bots to be connected with popular business or productivity applications.
  • Bucher+Suter - b+s Connects for Salesforce is an integration between Cisco Spark and Salesforce CRM that allows agents to handle calling and messaging interactions within a gadget embedded in the Salesforce GUI.
  • Vyopta - Vyopta empowers you to monitor and optimize your entire WebEx and Cisco Spark conferencing and collaboration environment. Improve performance, encourage employee adoption, and ensure you get the most from your video investments.
  • Built.io - Flow enables anyone to connect any tool – across any department and any industry - through their cloud based integration solution. Connect Cisco Spark to hundreds of business, productivity, and IoT apps in minutes without coding.
  • Kurmi - Kurmi alleviates the juggling of various administration tools to provision and manage your Cisco Spark users. You have a single point of control from which to administer your end-users on your whole communications stack including CUCM / HCS and WebEx.
  • BlueLine Grid - Monitor user location, send notifications, and immediately initiate global conference calls for various use cases all within Cisco Spark.
  • PromptWorks - See how PromptWorks assisted with Cisco Spark solutions including Doorman, a JIRA Bot, and custom widgets. Learn how they used natural language processing and artificial intelligence in the development of these bots that can be applied to your custom development needs.
  • Stack8 - Stack8 is building virtual assistant chatbots to automate tasks and integrate into other admin/business tools. Meet Octo at booth 1041 to find out more.
  • CallPlease - CallPlease offers a collaboration app that enables individuals and teams of any size to manage calls, call logs, history and activity from any device, anytime, with real-time syncing.
  • Voicebase - Voicebase solution enables voice analytics on all Cisco Spark meetings. All Cisco Spark meetings can now be recorded, transcribed and searchable by key words. Just add their Voicebase bot integration with Cisco Spark into any meeting and initiate it via @voicebasebot recording command.
  • Jive Communications - Jive Communications has a full-featured Cloud PBX offering that, combined with the Cisco MPP handsets and Cisco Spark Meetings powered by the Cisco Spark SDK, provides a comprehensive collaboration experience for commercial and public sector customers.

Many more Ecosystem Partners have proven to solve critical line of business problems for customers and are a great way to add stickiness to a Cisco Spark environment. We will be actively sharing more information about these vendors and others that will not be at Cisco Live next week as we have even more innovative apps come through Cisco Spark for Developers.

So if you are at Cisco Live, make sure to stop by the many partner booths throughout the week. And if you're lucky enough to be a Cisco Spark Ambassador that participated in our Twitter contest, our Ecosystem Partners and I will be seeing you at the Cisco Spark After Dark event!

https://developer.webex.com/blog/visit-the-cisco-spark-ecosystem-at-cisco-live-in-las-vegas https://developer.webex.com/blog/visit-the-cisco-spark-ecosystem-at-cisco-live-in-las-vegas Thu, 22 Jun 2017 00:00:00 GMT
<![CDATA[Building a More Secure Bot]]>

This tutorial shows how to make an existing Spark bot more secure.

If you are building your first bot, it is recommended you start with this tutorial.

Then come back here once it’s up and running!

If someone outside of your organization never interacted with your bot, they can’t just run a simple search to find it. However, if they know or guess the ‘email’ address of your bot, they will be able to add it to a space (formerly called room) and send it messages. The more bots that are out there, the higher the possibility of that happening! To prevent unwanted attention, there are three main ways to control access to your bot:

1. You can setup a space (formerly called room) filter when you create a webhook, which points to your bot application’s server. If someone adds your bot to a Cisco Spark space, and the space does not fit the filter rule for any of the bot’s webhooks, the bot application server will not receive any messages from Spark. For large enterprise bots that need access to many different spaces, that might not work out. That’s okay— you can setup one webhook for your bot, with no filter, to receive all messages from any space to which it belongs, and use the following two methods to secure the bot.

2. Filter at the bot’s code level - JSON Payloads are sent from Cisco Spark via HTTP POST to your webserver, which is defined in your webhook (see Handling Requests from Cisco Spark). When the JSON payload comes in, you can begin your server’s code by checking the incoming message’s data[“personId”] or data[“personEmail”], compare it to a predefined list in your code or database, and handle accordingly. You can also make a request to Spark with data[“personId”] to check other details, like the organization, to only allow people of a specific org.

Note: the OrgId that comes in with the webhook JSON Payload is the OrgId of the person that created the webhook.

auth_users = \['tahanson@cisco.com'\]
my\_org\_id = "Y2lzY29zcGFyazovL3VzL09SR0FOSVpBVElPTi8xZWI2NWZkZi05NjQzLTQxN2YtOTk3NC1hZDcyY2FlMGUxMGY"

def index(request):
 webhook = json.loads(request.body)
 requester = webhook\['data'\]\['personEmail'\]
 if requester != bot_email:
 if requester in auth_users:
            print "Authorized user!"
            #Do stuff
            print "Unauthorized user!"

 #AND/OR check person's org:
 person = sendSparkGET('https://api.ciscospark.com/v1/people/{0}'.format(webhook\['data'\]\['personId'\]))
 if json.loads(person)\['orgId'\] == my\_org\_id:
            print "User is a member of Org!"
            #Do stuff
            print "User it NOT a member of Org!"
return "true"

Note: Above code uses a function defined here.

3. Last, but not least, we have the webhook secret. This should be used to prevent your bot from processing any POST request that does not come from your specific webhook. This will block any of your other Spark webhooks, or Spark webhooks setup by other users trying to send to your bot’s webserver location.

Here is a brief tutorial on using a webhook secret in Python.

Everything together, here is a code snippet of all of these features combined:

def index(request):
 raw = request.body
 hashed = hmac.new(key, raw, hashlib.sha1)
 validatedSignature = hashed.hexdigest()
 print 'validatedSignature', validatedSignature
 print 'X-Spark-Signature', request.headers.get('X-Spark-Signature')
 returnVal = ""
 if validatedSignature == request.headers.get('X-Spark-Signature'):
 webhook = json.loads(raw)
 print webhook\['data'\]\['id'\]
 requester = webhook\['data'\]\['personEmail'\]
 if requester != bot_email:
            #get person information, specifically need the person's orgId
            person = sendSparkGET('https://api.ciscospark.com/v1/people/{0}'.format(webhook\['data'\]\['personId'\]))
            if json.loads(person)\['orgId'\] == my\_org\_id or requester in auth_users:
                result = sendSparkGET('https://api.ciscospark.com/v1/messages/{0}'.format(webhook\['data'\]\['id'\]))
                result = json.loads(result)
                in_message = result.get('text', '').lower()
                in\_message = in\_message.replace(bot_name, '')
                #echo the message back to the same room
                sendSparkPOST("https://api.ciscospark.com/v1/messages", {"roomId": webhook\['data'\]\['roomId'\], "text": in_message})
                returnVal = "success"
                print "orgId does not match or person not in list of authorized users"
 print "Secret does not match!"
 return returnVal

You can get the full, working example on Github. You’ll just need to replace your desired orgId, bot name, and token values in the variables at the bottom of the file. Let us know if you have any questions!

https://developer.webex.com/blog/building-a-more-secure-bot https://developer.webex.com/blog/building-a-more-secure-bot Sat, 10 Jun 2017 00:00:00 GMT
<![CDATA[Integrate Audio and Video Features into an iOS app using the Cisco Spark SDK]]>

Let’s say you want to develop an app on the iOS platform that allows you and your customers to easily communicate with each other. You want to show your products, but also want to provide live support to them when they need help. Wouldn’t it be amazing if you could add audio and video into the app, and make the connections with a few simple touches?

Now, this becomes possible and much simpler - Cisco has released an iOS Spark SDK which allows any iOS developer to easily integrate Spark audio and video calling features into an iOS app.

We will provide a sample app here to get you started, including a demo video, which explains how the SDK exactly works, so you can expand and modify it for any usecase or idea. There is no complex code to learn, and Cisco takes care of all underlying audio and media flows, so it’s very quick to learn and implement.

The following app is for a “VIP Help Centre” where a user can get not only chat support but also audio and video assistance. To start, please watch this video for a demonstration of the app functionality – once you’ve completed the video, move on to the rest of the blog for an explanation of the code.

You’ll need Xcode installed and open in order to access the built-in simulator used in the video – just go to “Xcode -> Open Developer Tool -> Simulator” in the menu. The demo app works well with both the simulators for iPhone 6 and 7 series.

Ok, time to get started on the code itself.

Preparation Work:

At the first step, we have to get the SDK installed, which is outlined here, so we won’t talk much about it. Once the SparkSDK is imported into the app without issue, we are ready for the next step.

Secondly, we need to create an OAuth app. It’s used for the iOS app to get an access token so that it can operate on behalf of a user (security and authentication). Here is the document for how Spark OAuth works, and this is the place to create an OAuth app. The redirectUri has to be “Sparkdemoapp://response”, the scope has to be “spark:all”. Then we get the clientId and clientSecret.

Lastly, we need a simple UI. Since this is just a demo, we won’t do much decoration work, and just show the main UI elements.

Sign in, Authorize and Sign out:

After the app loads, we need to see whether the user has already authorized his app or not. The below two lines are to get an initialized authenticator, then get a Spark object:

authenticator = OAuthAuthenticator.init(clientId: clientId, clientSecret: clientSecret, scope: scope, redirectUri: redirectUri)

spark = Spark.init(authenticator: authenticator!)

We can use the “authorized” attribute of “authenticator” to see if the user has authorized or not. If no, go to the beforeLoginAndAuth() function to show a button asking the user to log in and authorize, otherwise, let him pass the step and go to the main board. The whole script would be:

override func viewDidLoad() {
        self.spaceName.delegate = self // set up textField delegate

        authenticator = OAuthAuthenticator.init(clientId: clientId, clientSecret: clientSecret, scope: scope, redirectUri: redirectUri)
        spark = Spark.init(authenticator: authenticator!)
        if  !authenticator!.authorized {
        } else {
            spark!.authenticator.accessToken(){ token in
                print("token :\\(token!))")

In the view where users log in and authorize, we will add a button so they can click to start the process. We will show how to add a button and associate a function to the “touch-up” event on it next.

From the “Object library”, drag a button into the main board and give it a name like “Log in and Authorize” (in the “Attributes inspector”):

Attributes inspector

Then click the “Assistant editor”. Now we need to associate the touch-up action on the button with a function – press the “control” key on the keyboard (do not release), use the mouse to drag the button into the “ViewController” class in the script area, release the mouse, then a pop-up window will appear (we now can release the “control” key):


Choose the “connection” as “action”, give it a name, and set the “Event” as “Touch Up Inside”. Then after we click the “Connect”, it will automatically create a function in the “ViewController” class, and associate the function with the touch-up event on the button:


And under it we do the login and authorization work:

// sign in and do the authorization via Oauth
authenticator!.authorize(parentViewController: self) { success in
            if success {
                self.spark!.authenticator.accessToken(){ token in
                    print("token :\\(token!))")

In this demo app, it is:


The authorize() method starts the signing in and OAuth process. It redirects the user to Spark interface to let him input username and password and accept the requested permissions defined in the OAuth scope. If it succeeds, the access token will be stored in environmental variables so that other actions can use it. Here we print out the token string for logging, then redirect to the afterLoginAndAuth(). In the view, we also have a “sign out” button which allows a user to de-authorize to sign out:

//sign out

Chat Support Channel:

Now, we’re in the main board. The “Chat Support” channel allows a user to create a Spark space with a custom space name. On the “Create a space” button, we register a “Touch Up Inside” event to it (same procedure as the above):


And under it we create a space:

// Create a new space
        spark!.rooms.create(title: spaceTitle){ response in
            switch response.result {
            case .success(let space):
                print("\\(space.title!), created \\(space.created!): \\(space.id!)")
            case .failure(let error):
                print("Error: \\(error.localizedDescription)")
                self.spaceSuccessLabel.text = "Failed to create a space, pls retry later!"

And add a support rep into the space by email:

// Add a support rep to the space
    func addMember(space:Room) {
        if let email = EmailAddress.fromString(supportRepEmail){
            spark!.memberships.create(roomId: space.id!, personEmail: email) { response in
                switch response.result {
                case .success(let membership):
                    print("A member \\(self.supportRepEmail) has been added into the space. membershipID:\\(membership)")
                case .failure(let error):
                    print("Adding a member to the space has been failed: \\(error.localizedDescription)")
                    self.spaceSuccessLabel.text = "Failed to add a rep, pls retry later!"

Post a message to the space:

// Post a text message to the space
    func sendMessage(space:Room) {
        spark!.messages.post(roomId: space.id!, text: "Hello, anyone can help me?") { response in
            switch response.result {
            case .success(let message):
                print("Message: \\"\\(message)\\" has been sent to the space!")
                self.spaceSuccessLabel.text = "The Spark space and rep are ready!"
            case .failure(let error):
                print("Got error when posting a message: \\(error.localizedDescription)")
                self.spaceSuccessLabel.text = "Failed to post a message, pls retry later!"

The complete sample script is:

//create a space when a user clicks the "create a space" button
    @IBAction func createSpace(_ sender: Any) {

        spaceName.isHidden = true
        createSpaceButton.isHidden = true
        spaceSuccessLabel.isHidden = false
        spaceSuccessLabel.text = "Creating a space, please wait!"

        var spaceTitle:String
        if spaceName.text == nil {
            spaceTitle = "Help Space"
        } else {
            spaceTitle = spaceName.text!
            if spaceTitle.trimmingCharacters(in: .whitespaces) == "" {
                spaceTitle = "Help Space"
        print("space title is: \\(spaceTitle)")

        // Create a new space
        spark!.rooms.create(title: spaceTitle){ response in
            switch response.result {
            case .success(let space):
                print("\\(space.title!), created \\(space.created!): \\(space.id!)")
            case .failure(let error):
                print("Error: \\(error.localizedDescription)")
                self.spaceSuccessLabel.text = "Failed to create a space, pls retry later!"

    // Add a support rep to the space
    func addMember(space:Room) {
        if let email = EmailAddress.fromString(supportRepEmail){
            spark!.memberships.create(roomId: space.id!, personEmail: email) { response in
                switch response.result {
                case .success(let membership):
                    print("A member \\(self.supportRepEmail) has been added into the space. membershipID:\\(membership)")
                case .failure(let error):
                    print("Adding a member to the space has been failed: \\(error.localizedDescription)")
                    self.spaceSuccessLabel.text = "Failed to add a rep, pls retry later!"

    // Post a text message to the space
    func sendMessage(space:Room) {
        spark!.messages.post(roomId: space.id!, text: "Hello, anyone can help me?") { response in
            switch response.result {
            case .success(let message):
                print("Message: \\"\\(message)\\" has been sent to the space!")
                self.spaceSuccessLabel.text = "The Spark space and rep are ready!"
            case .failure(let error):
                print("Got error when posting a message: \\(error.localizedDescription)")
                self.spaceSuccessLabel.text = "Failed to post a message, pls retry later!"

All the actions use the access token we get in the authorization step at the backend. If you want to know how exactly a space is created, how a message is posted, etc., please refer to this document for detailed information. They’re all REST requests, and the doc shows how to set the method, header and body.

Audio and Video Channel:

In the “Audio & Video Support” channel, we can send audio and video calls. If you want to dial SIP or PSTN destinations, you will need the correct privileges – contact your Spark org admin or your Cisco partner to confirm.

In the “call” buttons, we register a “Touch Up Inside” event (the same procedure as the “Log In and Authorize” step):


And under that we start doing the actual call.

The first step is to register a device:


If it succeeds, do the actual call:

// Make a call
var outboundCall:Call? = nil
                self.spark?.phone.dial(dest, option:MediaOption.audioVideo(local: self.callerView, remote: self.calledView)) { response in
                    switch response {
                    case .success(let call):
                        outboundCall = call
                        print("Call succeeded!")
                    case .failure(let error):
                        print("Call failed: \\(error.localizedDescription)")

Note the “MediaOption.audioVideo”, it allows “audio” or “video” or both, and we can choose it based on requirement. It requires two parameters which specify the local and remote media views. In my demo, they’re the “callerView” and “calledView” views, defined as below:

@IBOutlet weak var callerView: MediaRenderView!
@IBOutlet weak var calledView: MediaRenderView!

Monitor call status:

In the call method, you may notice the initCallCallBack() method, and it defines the callback functions, as below:


We can implement them and reflect the status to the UI. For example, in this demo we implement the .onRinging method:

call.onRinging = {
            self.callStatusLabel.text = "Call is ringing"

and reflect the status to the callStatusLabel label then users can see “_Call is ringing_” when it rings on the called side.

So the whole script is like:

func initCallCallBack(_ call:Call){

        call.onRinging = {
            self.callStatusLabel.text = "Call is ringing"

        call.onConnected = {
            self.callStatusLabel.text = "Called is connected"

        call.onDisconnected = { event in

            switch event {
            case .localCancel:
                self.callStatusLabel.text = "Local Cancel"
                print("Local Cancel!")
            case .localDecline:
                self.callStatusLabel.text = "Local Decline"
                print("Local Decline")
                print("Disconnected - No Reason")

        call.onMediaChanged = { event in
            switch event {
            case .cameraSwitched:
                self.callStatusLabel.text = "Camera Switched"
                print("Camera Switched")
            case .localVideoViewSize:
                self.callStatusLabel.text = "Local Video View Size"
                print("Local Video View Size")

                print("Media Changed - No Reason")

Now, we have finished the coding work, and the complete code can be found on Github. If you have any questions, please contact devsupport@ciscospark.com 24/7/365 - we’re happy to help all the time!

https://developer.webex.com/blog/integrate-audio-and-video-features-into-an-ios-app-using-the-cisco-spark-sdk https://developer.webex.com/blog/integrate-audio-and-video-features-into-an-ios-app-using-the-cisco-spark-sdk Sat, 10 Jun 2017 00:00:00 GMT
<![CDATA[There is a New Integration Scope in Town!]]>

Recently we added a new integration scope called spark:all. The spark:all scope acts as an overall aggregate for the rest of the user scopes. It basically requests full access to a Spark account, i.e. reading/writing messages, creating/deleting spaces, making/receiving calls, and so on.

From an integrations standpoint, this makes it really simple to communicate to a user that the app requires full access without needing to select individual user scopes (such as spark:messages_read, spark:messages_write, spark:people_read). This is particularly useful for heavy-duty integrations, such as Cisco Spark calling apps. Prior to spark:all, individual user scopes were grouped and presented to the user for approval; with spark:all it requires approval for just one 'super' scope.

When spark:all is selected, the rest of the user scopes will be disabled for selection:


Even though spark:all acts as an aggregate scope, it is important to note that in the grant flow, the spark:all scope only aggregates user scopes – admin scopes are not part of spark:all and can be applied as add-ons, but no other user scope should be added when spark:all is selected.

Users will be presented with the following screen in the grant flow when the integration requires spark:all:


The spark:all scope is optional for the majority of the integrations. However, it is required for any app that uses calling features – you're effectively replicating a large portion (if not all) of a native Spark client at that point and need the complete set of scopes in order for your integration to function correctly.

To learn more about integrations, please see the Authentication guide.

We focus on providing you the best features and experience. If you have any questions, feel free to reach out to us at devsupport@ciscospark.com or join the DevSupport Spark room. Follow us on Twitter to stay updated.

https://developer.webex.com/blog/there-is-a-new-integration-scope-in-town- https://developer.webex.com/blog/there-is-a-new-integration-scope-in-town- Sat, 10 Jun 2017 00:00:00 GMT
<![CDATA[Cisco Spark Messages with Emoji Characters]]>

Anyone that utilizes text messages on mobile devices are likely familiar with emojis. There's certainly good reason for this, since emojis help convey reactions and the feelings of a message better than just plain text. For example, it can be much easier to decipher the intent or tone of a message depending on the emojis used.


Cisco Spark can send & receive messages that contain emoji characters, and not just on mobile devices, but also on Mac and Windows machines. Go ahead and try it now on your laptop or workstation. When typing in Cisco Spark on a Mac, to send a message with emoji characters, the emoji quick-type panel shortcut can be accessed by simultaneously pressing Command + Control + Spacebar. To access emoji selections on Windows, the on-screen (touch) keyboard will first need to be enabled. To do this, right click the taskbar and select the Show touch keyboard button option. This will place a keyboard icon within the Windows taskbar notification area. Click this icon and a keyboard will appear on the screen. Next to space and Ctrl, click the smiling face to access the emoji selections.

Cisco Spark bots can also send and receive emoji characters. There's some different ways this can be done. One method is to simply use the actual emoji characters directly in the content of an API call or application code, since they’re perfectly valid characters in the Spark API. It’s important to note, the API call will need to include charset=utf-8 in the Content-type header. Here’s an example jQuery code snippet and resulting Spark message when sending actual emoji characters in a /messages API call:

messages API call


Some programmers may want to automate things further by referencing the actual Unicode value for a corresponding emoji in their bot code. The code points for the available emoji characters and sequences are listed on the Unicode reference site and can also be found in several public GitHub repositories. As you see listed on the reference website, the corresponding Unicode hex value for “ ” is U+1F916 and for “ ” is U+1F984. However, in order to utilize these codes in a Spark bot application, we’ll need to find the surrogate pair for each of those hex values.

The reason for surrogate pairs is that in a hex value, u+FFFF is as big as you can get, and represents 65535 in base10 encoding. That's the biggest integer that exists; there's no valid number larger than it. In other words, imagine a computer that can't count any higher than 65535. So, once we got to more than 65535 characters, we need to start combining two characters. To make an analogy, the computer ran out of fingers to count on, so it started counting toes – as in the number 11 is "10 fingers and one toe". A very helpful primer on the subject of character sets and why encoding is needed can be found here.

To quickly test Unicode emojis in Spark, there’s a handy surrogate pair calculator available on this website. However, this operation can be done programmatically by using something like this example JavaScript function:

JavaScript function

Taking those surrogate pair values inside a REST call request to the Spark /messages API, the corresponding emojis will display inside the Spark message, just like the first example:

messages api


Remember, emojis are not only fun, but can really help make your Spark bot messages have a more human touch. Feel empowered to use them abundantly! Or, if you’re a bot, “abundantly \uD83E\uDD21\uD83D\uDC3F\uD83C\uDF55”! If you have any questions, feel free to reach out to us at devsupport@ciscospark.com or join the DevSupport Spark space. Follow us on Twitter to stay updated.

https://developer.webex.com/blog/cisco-spark-messages-with-emoji-characters https://developer.webex.com/blog/cisco-spark-messages-with-emoji-characters Mon, 05 Jun 2017 00:00:00 GMT
<![CDATA[Cisco Spark Online Hackathon: Change the Way Teams Collaborate, Get Rewarded!]]>

Pupper coder

Calling all developers!

Our first EVER online hackathon just hit the 1 month mark and there are 2 more months to go!

Experiment with the Cisco Spark developer tools to reimagine the way healthcare, education, and sales professionals interact with each other and their customers. Build an app using our Video SDK, an integration, or chatbot with our REST APIs that transforms communication in these industries for a chance to snag $25,000 in total cash prizes and pitch your idea to a panel of execs (plus the potential to make a huge impact on billion-dollar marketplaces).

Need some ideas? Check out our categories page and start thinking about how your code can upgrade collaboration in hospitals, classrooms, and sales-driven businesses.

Submissions are open until July 28th! Register here --> http://ciscospark.devpost.com

We'll also be hosting a live webinar on June 14th so you can ask all your questions and get some help with your ideas. So stay tuned!

https://developer.webex.com/blog/cisco-spark-online-hackathon-change-the-way-teams-collaborate-get-rewarded- https://developer.webex.com/blog/cisco-spark-online-hackathon-change-the-way-teams-collaborate-get-rewarded- Fri, 02 Jun 2017 00:00:00 GMT
<![CDATA[Introducing Cisco Spark SDKs and Widgets!]]>

It just got much easier to integrate Cisco Spark functionalities into your application. Introducing Cisco Spark SDKs for iOS and JavaScript and Cisco Spark Widgets for messaging and calling. With these new releases, you and your end users should be able to seamlessly access the powerful collaboration features offered by Cisco Spark — without having to ever leave your mobile application or website. The SDKs and widgets accomplish this in different ways. The SDKs give an impressive amount of UI flexibility, while the widgets are the simplest, fastest way to get up and running.

One of the main benefit to both the SDKs and widgets is the simplified user experience. For example, let’s say you have a banking application. You want to use the secure communication capabilities of Cisco Spark so end users can connect directly with your support team. Previously, you had to send users out of your application to achieve this connection. Now, users never have to leave your application.

app widget

Cisco Spark Widgets

Our new widgets handle the heavy lifting of coordinating between your application and the Cisco Spark APIs, and provide components of the Cisco Spark experience without you having to build all of the front-end UI yourself.


Two widgets are available for immediate use:

  • Space Widget – 1:1 audio/video calling, 1:1 and space messaging
  • Recents Widget – list of recent Cisco Spark conversations

Embed a Cisco Spark space in your app or connect two single users so they can exchange messages, share files, or conduct a video call. To speed deployment, the widgets come with Cisco Spark UI elements built in, enabling you to focus on the functionality.

The widgets currently support JavaScript clients and leverage WebRTC, so there are never any plug-ins to install. (A browser that supports WebRTC is required.) To get started, visit the Cisco Spark SDKs and widgets page. You can also check out this demo application and view all the open-source widget code for inspiration.

Cisco Spark SDKs

While the widgets are a fantastic way to connect quickly, you may need to customize the experience. That’s why we created the iOS and JavaScript SDKs. They allow you to apply your own UI and still use client-side API calls to embed Cisco Spark voice and video calling directly in your application. With the SDKs, you can connect end users from your app to any Cisco Spark app/devices and SIP URI devices.


Like the widgets, the JavaScript SDK leverages WebRTC to ensure that your users are never prompted for browser plug-ins. The iOS SDK is built on Swift 3.0 and both SDKs are open source, so anyone can contribute. To get you up to speed fast, we’ve compiled Getting Started packages for both iOS and JavaScript.

We want to make it easy for you to add collaboration capabilities inside all your workflows. While these new releases are an exciting step in that direction, we’re already expanding the functionality and supported platforms. Android support is in the works, as are powerful new features. Follow us on Twitter to stay up to date with all the latest releases.

We’re here to help if you have any questions. Email us at devsupport@ciscospark.com or join the DevSupport Spark space.

https://developer.webex.com/blog/introducing-cisco-spark-sdks-and-widgets- https://developer.webex.com/blog/introducing-cisco-spark-sdks-and-widgets- Tue, 23 May 2017 00:00:00 GMT
<![CDATA[SIP Address for Cisco Spark Spaces]]>

Coming soon you'll be able to see SIP URIs for group Cisco Spark spaces! Now anyone can join a Cisco Spark meeting. All Cisco Spark spaces will have a SIP URI, allowing people to join meetings in those spaces from any standards-based SIP hardware or software client. The SIP URI will be returned for group spaces (not 1:1) via the Get Room Details API endpoint.

We focus on providing you the best features and experience. If you have any questions, feel free to reach out to us at devsupport@ciscospark.com or join the DevSupport Spark space. Follow us on Twitter to stay updated!

https://developer.webex.com/blog/sip-address-for-cisco-spark-spaces https://developer.webex.com/blog/sip-address-for-cisco-spark-spaces Mon, 22 May 2017 00:00:00 GMT
<![CDATA[Managing Hybrid Services Licenses]]>

Managing Cisco Spark Hybrid Services licenses is about to get easier with the Spark API. Organization Administrators will soon have the ability to list Hybrid Services licenses for an organization and use them to enable or disable services for users via the Spark API.

The Licenses and People APIs make it easy to programmatically update people to add and remove various Spark licenses. With the addition of Hybrid Services licenses, administrators can quickly identify users who have these services enabled or disabled. License changes for a user can be made with a simple PUT request containing a list of licenses which should be enabled for the user.

For more information about how to manage Hybrid Services licenses with users, see this guide in our developer documentation. We focus on providing you the best features and experience. If you have any questions, feel free to reach out to us at devsupport@ciscospark.com or join the DevSupport Spark space. Follow us on Twitter to stay updated.

https://developer.webex.com/blog/managing-hybrid-services-licenses https://developer.webex.com/blog/managing-hybrid-services-licenses Wed, 26 Apr 2017 00:00:00 GMT
<![CDATA[Provisioning Statuses for People]]>

Cisco Spark Organization Administrators will soon have access to two additional fields for People to determine a user’s provisioning status. When new users are invited to join Cisco Spark, an email is sent to them to continue the sign-up process. Now you will be able to determine via the People API if users have completed the sign-up process and if they are able to log into Spark.

Two new Boolean-type fields will be returned for People to represent the user’s account provisioning status:






The user has been sent an invite, but has not completed the sign-up process



The user has been sent an invite, and has completed the sign-up process



The user is not allowed to log in



The user is allowed to log in

These two additional read-only fields will be available when listing all People and when getting details for one person. This update will only add additional fields, and will not remove or rename any current fields.

We focus on providing you the best features and experience. If you have any support questions, feel free to reach out to us at devsupport@ciscospark.com or join the DevSupport Spark space. Follow us on Twitter to stay updated.

https://developer.webex.com/blog/provisioning-statuses-for-people https://developer.webex.com/blog/provisioning-statuses-for-people Fri, 07 Apr 2017 00:00:00 GMT
<![CDATA[Additional statuses for the People API]]>

A few months ago we added the ability to retrieve a person’s status from the People API. The available status options are expanding to include a few more in addition to active and inactive.

People can now also be Out of Office (OutOfOffice) or Do Not Disturb (DoNotDisturb):

  • Out of Office (OutOfOffice) is available to organizations who have Calendar Integration enabled. Ask your organization administrator for details about your organization’s calendar integration settings.
  • Do Not Disturb (DoNotDisturb) is a temporary status set by the user via the Spark desktop, mobile, or web clients.

The Spark status field is read-only; Spark determines the appropriate status for the person automatically. With the new additions, a person can now be active, inactive, OutOfOffice, or DoNotDisturb.

We focus on providing you the best features and experience. If you have any questions, feel free to reach out to us at devsupport@ciscospark.com or join the DevSupport Spark room. Follow us on Twitter to stay updated.

https://developer.webex.com/blog/additional-statuses-for-the-people-api https://developer.webex.com/blog/additional-statuses-for-the-people-api Thu, 09 Mar 2017 00:00:00 GMT
<![CDATA[Welcome to Berlin: Cisco Spark ISV Partners at Cisco Live!]]>

At Cisco Live Berlin 2017, Cisco Spark ISV Partners will be participating in full force whether that is exhibiting in the Collaboration Partner Village in the World of Solutions or showcasing the technical abilities of their offers in the DevNet Zone. Each vendor will be able to take Cisco partners and customers through full demos and be able to discuss the business critical problems their solutions help solve. Check out a few of these incredible ecosystem apps with the videos below before you go to the show. And of course, if you’re interested in learning more feel free to reach out to me on Spark!

Local Measure

Cisco Spark makes it more efficient for teams to communicate and collaborate with one another. With the integration of Local Measure, Cisco Spark is also a powerful customer experience tool, enabling teams to receive real-time feedback from their customers and engage with those customers to provide best-in-class customer experience. With Cisco Spark, customer alerts from Local Measure are seamlessly pushed into a Cisco Spark room, allowing front-line teams to click through to respond to customers, escalate and manage the situation in real-time and on the go, from anywhere on any device. Check out this video!

Envoy logo

Envoy is the digital visitor registration system that’s changing how visitors are greeted in workplaces around the world. Instead of signing in using a paper sign-in sheet, visitors simply sign in on an iPad and envoy will send the appropriate employee(s) a Cisco Spark message when their visitors arrive. Envoy streamlines the sign-in process to give visitors a better experience. No more writing down information, signing paper documents and waiting for the receptionist to track down their host. Check out this video!

VBrick Logo

Think of VBrick as the ‘YouTube of the Enterprise’ for all your video needs. VBrick has a video creation/management/distribution platform that works perfectly in a number of Cisco Collaboration environments including Cisco Spark. Record your meetings, post updates to Spark, Search for your videos in Spark and utilize Cisco’s award winning line of video endpoints as your recording/live streaming studio. Check out this video!

Kurmi logo

Kurmi allows for seamless management of your Cisco Spark users across your entire Cisco UCM or HCS environment. Based on their profile (function, teams, sites), users are automatically provisioned or migrated to the right bundle of communications services and assigned to their Spark teams. Kurmi enables you to benefit the most from the collaboration features of Cisco Spark, such as web conferencing, video or integrated calls. The provisioning process, which can be painful and time-consuming without a unified management platform, is fully automated. Integrating Cisco Spark into your communication infrastructure takes a matter of seconds with Kurmi! Check out this video.

built.io logo

Built.io Flow delivers end-to-end integration for both Business and IT. Built.io Flow enables anyone to connect Cisco Spark to any tool – across any department and any industry - through their cloud-based integration Platform-as-a-Service (iPaaS). Built.io Flow now offers two integration products with the ability to export Flows and share across each of them as the first end-to-end integration solution. Learn more at: https://www.built.io/products/flow

FocusCura logo

FocusCura provides a simple yet powerful telemedicine application for healthcare customers and their end users enabled by Cisco Spark video calls on mobile devices. Less travel time means more time for health care. It also means more direct contact between health care providers and patients, which leaves extra time to check a stoma, to check the use of an insulin pen, or to chat about the day. With FocusCura, you can use telemonitoring with a secure video connection via Cisco Spark to improve health care communication. Check out this video.

Bulpros logo

Bulpros (Intracol) Voice Control for Cisco Spark allows you to stay engaged with your conversations in situations where using other applications is inconvenient or inappropriate, for example, while driving or jogging. It is an interface to Cisco Spark utilizing Tropo-based text-to-speech and speech-to-text technologies allowing you to use your voice to establish two-way communication. Also check out their solution that interfaces to Office 365 or Google calendar utilizing Tropo-based text-to-speech and speech-to-text technologies. This allows customers to call and make an appointment in the first available and suitable for them slot without the need of human interaction. Check out this video!

These ISV Partners have proven to solve critical line of business problems for customers and are a great way to add stickiness to a Cisco Spark environment. We will be actively be sharing more information about these vendors and others as we have even more innovative apps come through Cisco Spark for Developers. So if you are at Cisco Live Berlin, make sure to attend the dedicated session we have on the Cisco Spark Video SDK or stop by the many partner booths throughout the week. Prost!

https://developer.webex.com/blog/welcome-to-berlin-cisco-spark-isv-partners-at-cisco-live- https://developer.webex.com/blog/welcome-to-berlin-cisco-spark-isv-partners-at-cisco-live- Fri, 17 Feb 2017 00:00:00 GMT
<![CDATA[Hello, Botkit! A Very Warm Welcome to Botkit.ai]]>

One of our favorite parts of the Cisco Spark dev community is how open it is. There’s something exciting for devs at every stage of their journey, whether they’re old pros in the Cisco Spark Depot or just starting out — and that makes for a diverse ecosystem of innovators.

But for all these unique voices, there’s one thing we hear all the time: “Got any bot-building shortcuts?” Now, thanks to the Botkit from botkit.ai, the answer is a resounding yes.

So, friendly Cisco Spark Devs, please give a warm welcome to Botkit, the leading open source bot framework. Botkit is a free, MIT-licensed, open-source framework that simplifies the bot-building process by providing a semantic interface for sending and receiving messages so developers can focus on creating novel applications and experiences. With support for Cisco Spark, Botkit developers now have access to one of the largest network of collaboration customers and partners on the planet. Together, we can transform the collaboration experience.

In 2016, BotKit was downloaded over 100,000 times and there are over 25,000 production Bots that are powered by BotKit from companies such as, PayPal, Concur and Hotels.com. All of which can now take advantage of this new Botkit release and add support for Cisco Spark.

Botkit makes it easy for you to create bots for Facebook Messenger, Slack, the Microsoft Bot Framework, and more. And because Botkit bots — both new and existing — are now compatible with Cisco Spark, you can share the majority of your existing code between platforms.

Ben Brown, CEO of Botkit.ai, says:

“Our goal in building Botkit was to give developers an easy-to-use tool that let’s them take advantage of all the best resources for building bots. Bots on Cisco Spark have exciting capabilities that we haven’t seen before, and we’re excited to see where the developers lead us”

With Botkit, you can choose to work in either the code-level framework, written in Node.js, or the soon-to-be-unveiled IDE for Visual Bot Building — which will allow you to spend less time worrying about how the Cisco Spark API works, and more time actually building your bot. There are even free plugins that allow Botkit to interact with services like IBM Watson, API.ai, Wit.ai, or Luis.ai for an instant boost to your bot’s conversation skills.

One of the major benefits of building your Bots on Botkit is the ability to share code between Bots designed to work on different platforms. Let’s take a look at a simple code example that shows how to port a Botkit project from Slack to Cisco Spark:

\# Slack Hello World

var Botkit = require('botkit');

var controller = Botkit.slackbot({
    clientId: process.env.clientId,
    clientSecret: process.env.clientSecret,
    scopes: \['bot'\],

controller.setupWebserver(process.env.port,function(err,webserver) {

controller.hears('hello','direct\_message,direct\_mention', function(bot, message) {

    bot.reply(message, 'Howdy!');


\# Steps to port

Change 4 lines where Botkit controller is created.

Add 1 line to spawn the bot in Cisco Spark.

\> var bot = controller.spawn();

Change the webhook signature by adding bot parameter.

>  controller.createWebhookEndpoints(controller.webserver, bot);

\# Cisco Spark Hello World

var Botkit = require('botkit');

var controller = Botkit.sparkbot({
    public\_address: process.env.public\_address,
    ciscospark\_access\_token: process.env.access_token,
    secret: process.env.secret, // this is an RECOMMENDED but optional setting that enables validation of incoming webhooks

var bot = controller.spawn();

controller.setupWebserver(process.env.port,function(err,webserver) {
  controller.createWebhookEndpoints(controller.webserver, bot);

controller.hears('hello','direct\_message,direct\_mention', function(bot, message) {

    bot.reply(message, 'Howdy!');


Simple enough, right?

If you’d like to start your own Botkit adventure, head on over to Github to get started. Our Cisco DevNet team have been busy working on sample code and have a developer community to help you work on your Cisco Spark bot to help you become a Botkit expert in no time! And after that, head over to the Cisco Spark Depot to submit your finished bot.

We can’t wait to see what you build!

To get all the latest updates about Cisco Spark for Developers, follow @CiscoSparkDev.

https://developer.webex.com/blog/hello-botkit-a-very-warm-welcome-to-botkit-ai https://developer.webex.com/blog/hello-botkit-a-very-warm-welcome-to-botkit-ai Wed, 15 Feb 2017 00:00:00 GMT
<![CDATA[Testing the Administration APIs]]>

Since we introduced Administration APIs this past October, you have asked how you can build and test with these APIs without being an administrator in your organization. To help with this, we have created a Administrator Sandbox organization that we can make you an administrator of. Then, using this new organization, you can develop and test your integration.

There’s a few rules and things you need to know about using this Sandbox organization, so read the documentation for details.

https://developer.webex.com/blog/testing-the-administration-apis https://developer.webex.com/blog/testing-the-administration-apis Wed, 01 Feb 2017 00:00:00 GMT
<![CDATA[You are likely to be eaten by a bot: Behind the scenes with Zork.]]>

Last week, we introduced a bot that allows you to play the classic text adventure game Zork in Cisco Spark rooms or over SMS through Tropo.

Here’s how the bot works (links to the source code repo are at the end of this post).

First, a little history. Back in the 1980s, Infocom created a virtual machine called a Z-machine that Zork would run on. Writing new games was a matter of creating a game file that the virtual machine could read. This made porting the game to various computer platforms simpler, as they’d only have to port the virtual machine, not the entire library of games.

Once Infocom closed down and had their assets absorbed into Activision, game enthusiasts reverse engineered the Z-machine internals by studying the game files and ultimately created replacement Z-machines. One of these, Frotz, is the Z-machine driving this bot. Eventually, Infocom’s owner made Zork 1-3 available for free download, and the Zork 1 game file is installed in the bot.

Frotz runs as a Linux command-line process, and has a mode where you can pipe game commands on stdin and get the results on stdout. The zmachine-api project, created by some engineers at OpenDNS, uses node.js to wrap a REST API around this project and manages starting and stopping the Frotz processes as needed. The Spark bot uses this API.

The Spark bot relies on two Webhooks. One on message creation, is set up without a roomId filter, so all messages that @mention the bot or are in a direct conversation with the bot are delivered to this webhook. The second is a memberships created webhook, also without any filters, so that the bot is notified any time it is added to a Spark room.

When the bot is notified by the Memberships webhook that it’s been added to a room, it immediately posts to the room, introducing itself. It explains what it is, and reminds room participants that they need to @mention the bot if they want to play. This small on boarding mechanism can help room participants understand why a bot was just added to a room and what it can do. This exact on boarding method isn’t appropriate for all bots, but when you are creating a bot, you should think about what a bot should do when it first becomes alive in a room.

Each Spark room is a separate instance of the game. Move around the Zork world in one room, and then go to a different room, and you’ll find your Zork game there is still in the same place it was when you left it.

Another bit of Membership webhook magic is used when the bot is added to a room that already has a game running. If you started playing, remove the bot, and then add it back in again, the game should pick up right where you left off. But the bot should still introduce itself, and also remind the players where they are in the game. Zork has a command called “look” that causes it to tell you what your current surroundings are. So when the bot is added to a room and sees there’s already a game for that room ID, it issues the Look command and shows the players what is going on.

The messages Webhook is how the bot gets the commands from players in the game. When the bot is mentioned, or when someone speaks to it in a one-on-one room, the bot takes the exact input from the player and sends it to Zork. The Webhook triggers the bot, the bot uses the message ID from the webhook to fetch the message content, and then that message content is sent to the game.

One thing that isn’t immediately obvious when creating a Spark bot is how to strip the bot’s name from messages when it’s mentioned. For many bots, this can be as simple as a string match on the bot name and strip that string out. But because this bot has a two word name (“Text Adventure”), the mechanics of Spark mentions means that other people in the room could affect how the mention appears in a message. Spark puts the person’s first name in the message when you mention them, unless there are several people in the room with the same first name. Then to avoid ambiguity, Spark puts the full name in. For a bot like Text Adventure, the presence of another bot in the room called “Text Mom” could mean that sometimes the @mentioned name is “Text” and sometimes it’s “Text Adventure”.

To handle this issue, when the bot server first starts, the bot gets /people/me to find out who it is. It then stores its own personID and uses that to remove mentions by running a regular expression on the HTML markup that wraps a mention.

if (message.html) {
  // strip the mention & HTML from the message
  var pattern = new RegExp('\]\*data-object-id="' + sparkbotself + '"\[^>\]\*>\[^');
  action = message.html.replace(pattern,'');
  action = action.replace(/\]*>/g,'');
} else {
  action = message.text;

Another thing the bot needs to do when processing the message webhook is ignore its own messages. A bot’s message to a room will trigger the webhook from Spark, and you don’t want the bot getting caught in a loop where it is answering its own message, with each answer triggering a new message. When the message webhook arrives, the bot compares the personId that sent the message to its own personId and ignores it if they match.

To keep different instances of the game separate, zmachine-api uses a “label” to tag a Frotz process and later find the process ID that a command should be sent to. Each label becomes a different instance of the game. The bot uses the Spark room ID as the label, regardless if you’re playing in a direct or group room.

Because we’re starting lots of games, in order to keep from having thousands of idle Frotz processes running, the bot starts a new process for every in-game command, then saves the game and shuts down the process when the command is completed. This also ensures that if the server is restarted, all of the games can pick up where they left off. This has the side effect of the “moves” counter in the game appearing to increment by two on every in-game move, since Zork considers saving the game to be a move.

Here’s a flowchart of the bot’s logic. Spark-specific bits are in green, Tropo-specific operations for SMS are in blue, and interactions with the Zork engine and zmachine-api are in orange.

enter image description here

And finally, the code behind the Zork bot is available for your own use. Grab it from my GitHub repository. It’s all written for Node.js, using the Express framework. Included in the repository is a Dockerfile for spinning up a container with the game, and a docker-compose example that will start up multiple containers with the game and all its dependencies.

https://developer.webex.com/blog/you-are-likely-to-be-eaten-by-a-bot-behind-the-scenes-with-zork- https://developer.webex.com/blog/you-are-likely-to-be-eaten-by-a-bot-behind-the-scenes-with-zork- Wed, 11 Jan 2017 00:00:00 GMT
<![CDATA[Play Zork by Spark and Text Message]]>

You can now play Zork in Cisco Spark. Add adventure@sparkbot.io to a Spark room, or start a direct conversation with it, and you’ll be invited to play the classic text adventure game Zork: The Great Underground Empire - Part I.

Each room you add the bot to is a different game of Zork. All the participants of the room can play the game together.

The bot also has SMS support through Tropo. If you’re in the US, you can play Zork over text message by texting something to +1-844-373-9675. Outside the US, try +1-541-936-9675, but this has a lower capacity and may not work as well during busy times. In either case, your carrier's normal text or data rates apply.

Next week, we’ll explain how the bot works, show some code, and walk through some of the helpful user interface things you can do in your own bot.

https://developer.webex.com/blog/play-zork-by-spark-and-text-message https://developer.webex.com/blog/play-zork-by-spark-and-text-message Sat, 07 Jan 2017 00:00:00 GMT
<![CDATA[Presence comes to the People API]]>

Earlier this week, a new feature was added to Spark to tell you if a person is available or not. Based on your usage, we determine if you're actively using Spark and then in the client, help people understand if you're online or not by saying something like "Active 10 minutes ago" next to your name.

Now the Spark APIs have this same information available to you. The People API has two new fields, lastActivity and status that help your integration or bot determine if a Person is active or not. The lastActivity field gives you the date and time that Spark last saw the person doing something - writing a message or having a call, for example. The status field tells you if the person is "active" or "inactive".

These fields are read-only; there's no way to set a person's status through the API. Spark determines their status automatically, with no input needed from your side.

In the future, as Spark gets more presence options, the status field will gain those same options. So while you'll only see "active" and "inactive" today, you'll want to make sure your application doesn't break or behave oddly if you get a different status entirely.

https://developer.webex.com/blog/presence-comes-to-the-people-api https://developer.webex.com/blog/presence-comes-to-the-people-api Tue, 20 Dec 2016 00:00:00 GMT
<![CDATA[The Big Cisco Spark for Developers Fall Events Wrap-up]]>

We have had a pretty busy couple of months around here at Spark for Devs. We've been spreading the good word about Cisco Spark to events around the world. I just wanted to take a minute here in this blog post to wrap up what we've been up to lately.

October 27 - TechCrunch Meetup in Seoul

TechCrunch held a very successful meetup in Seoul, South Korea, where many of the attendees were involved in a pitch-off. The winner of the pitch-off was the AI-powered scheduling assistant, Konolabs. You can click the link above to see a video with highlights and here are a couple of pictures from the night...


November 7 - Cisco Live in Cancun

Cisco Live is always a good time, and especially when it's in beautiful Cancun. People from all over Latin America gathered in Cancun to get an taste of what Cisco is up to and get hands-on with Cisco Spark and Tropo. Here are a few pictures from that event.

cl cancun

November 14 - LAUNCH Scale in SF

Back in San Francisco, California, USA, startup founders gathered to put their ideas to the test and learn from the best at LAUNCH Scale. We were there to hear the speakers and let everyone know how great Spark can be for a growing company.

November 15 - TADSummit in Lisbon

In Lisbon, telcom app developers gathered around to show off their stuff and exchange ideas with the best and brightest that the telcom industry has to offer. Proving that telcom isn't a tired, old industry, TADHack also hosted hackers putting together full apps in under two days. Cisco Spark and Tropo were there sponsor, learn, and help. Click on the link above to watch some video, see some pictures, and read a full write-up of the event.

November 17 - Spark Open House in NYC

In NYC, customers were invited to attend the first Spark Open House event. This one-day event included eight Cisco Spark stations covering Cisco Spark Message, Meet, Call, and APIs. The Spark APIs station covered integrations, bots, and open source development. Cisco Spark Depot partners Status Hero, Talos Digital, and Cumberland Group joined us to showcase the integrations and bots they have created. Connecting customers with our partners is our mission!

Spark House

November 20 - Geektime TechFest in Tel Aviv

If you're at all interested in tech and were in Isreal on November 20th, this is exactly where you wanted to be! On top of a conference and a hackathon, Geektime TechFest also hosted a startup competition that boasted some pretty fabulous ideas including the winner of the competition, Imperson, which is a chat bot that promotes and sells products and services. There were so many fun times and too many pictures to pick just a few to post here. Check out their Facebook Page to see a bunch of fabulous moments from the event!


November 22 - Chatbot Summit in Tel Aviv

Speaking of chatbots, Chatbot Summit featured some of the greatest minds in the chatbot world who came together to talk, teach, and learn about the future of automated messaging. Taking place as part of Geektime TechFest, it was a simple to go back and forth and include Chatbots in the realm of technology as a whole. Check the Facebook page linked above for more info and pictures of the events!

November 25 - Codemotion in Milan

Who doesn't enjoy food and wine in Italy? Many tech evangelists presented at Codemotion ranging from IoT to Big Data. Jason Goecke opened up the event with an inspirational presentation focusing on developers and introducing attendees to Cisco DevNet. Steve Sfartz and Angelo Fienga dug into the interaction between IoT and humans.


https://developer.webex.com/blog/the-big-cisco-spark-for-developers-fall-events-wrap-up https://developer.webex.com/blog/the-big-cisco-spark-for-developers-fall-events-wrap-up Mon, 05 Dec 2016 00:00:00 GMT
<![CDATA[Notice: Cisco Spark Depot Replaces the Cisco Spark for Web Integrations]]>

With the recent launch of the Cisco Spark Depot, the Cisco Spark Depot replaces the Cisco Spark for web integrations. So you will no longer see the Add Integrations option in Cisco Spark for Web. In each room, you will now see a link to the Cisco Spark Depot. Check out the Depot for all the latest integrations and bots for the Cisco Spark app.

The Cisco Spark Depot includes the same integrations that you used to access using Cisco Spark for Web, and more. Integrations that you've already set up using Cisco Spark for Web will continue sending you notifications as configured until November 30, 2016.

On November 30, 2016, we will ramp down those integrations and they will stop sending notifications. We suggest you to replace your existing integrations with new integrations from the Depot immediately after November 30th. It takes only a few minutes. If you enable the replacement integrations before November 30th, you may get duplicate notifications: one from the Depot integration and another one from the integration that was set up using Cisco Spark for Web. Incoming and outgoing web hooks will be available soon from the Depot.

Visit the Cisco Spark Depot today!


https://developer.webex.com/blog/notice-cisco-spark-depot-replaces-the-cisco-spark-for-web-integrations https://developer.webex.com/blog/notice-cisco-spark-depot-replaces-the-cisco-spark-for-web-integrations Mon, 28 Nov 2016 00:00:00 GMT
<![CDATA[Changes to the Download Limit]]>

This update applies to those sending or retrieving message attachments using the Spark API. Download and upload limits of message attachments are limited to 100MB in size - this effectively means you can upload a file 100MB or smaller, or download a file 100MB or smaller, but won't be able to upload OR download files that are larger. Larger files can be uploaded or downloaded via the Spark clients, this is specifically an API limit intended to prevent oversaturation of resources. Previously we documented files 2GB or smaller were supported, but that limit had to be scaled back after reviewing traffic patterns and load averages.

We focus on providing you the best experience and we apologize for any impact this has on you, your business and customers. We are working closely with teams to ensure any changes are known in advance.

If you have any support questions, feel free to reach out to us at devsupport@ciscospark.com or join the DevSupport Spark room. Follow us on Twitter to keep updated.

Related blogs:

- Spark for Developers Team

https://developer.webex.com/blog/changes-to-the-download-limit https://developer.webex.com/blog/changes-to-the-download-limit Sun, 06 Nov 2016 00:00:00 GMT
<![CDATA[Spark Apps Community]]>

Say “hello” to my little friend...


Since bots have been the popular buzzword this year, we want to make sure you’re not missing out on all the action. Collaboration tools are evolving and integrating fast. Whether you’re interested in building your own bot or integrating Spark with another app, here at Cisco we’ve got you covered.

I’m happy to announce the Cisco Spark Apps Community of Interest. This is where you can start your journey as a “DevNet Sparker”. You can explore integrations in DevNet Creations, learn how to build an app in the Learning Labs, connect with peers in #spark4dev room, and promote your own app in the Spark Depot. From the Spark Depot, your Spark app will get global visibility and hopefully the success it deserves.

Ready to get started? We have a ton of resources to help you build your first bot or integration.

  1. Check out the Spark Depot to start integrating Spark with popular tools like Box, GitHub, Salesforce and more.
  2. Learn how to use the Spark APIs to create your own bot and/or integration in the Cloud Collaboration Learning Track
  3. Jump straight into the code with SDKs and sample code in Awesome Cisco Spark

We hope you have fun creating some awesome apps. If you’re an engineer or developer wishing you could do something a little more creative, now is your time. Turn off a lightbulb from a Spark room, get notifications from a Jira update, find an available meeting room in your building. The sky’s the limit!

If you already have a bot that can be inspiring for others, go to DevNet Creations to share the code with the community. So glad to have you in the community

P.S. Don’t forget to check out the Spark Apps Community

https://developer.webex.com/blog/spark-apps-community https://developer.webex.com/blog/spark-apps-community Tue, 01 Nov 2016 00:00:00 GMT
<![CDATA[The Cisco Spark Depot: Bots and Integrations Have Arrived]]>

We’ll admit it: the Cisco Collaboration team is a little obsessed. When we’re not rolling out new products to help transform the way you work, we’re busy improving platforms you already use. Why? We believe in the power of continuously simplifying communication in all its forms, because we know the more intuitive and intelligent your tools are, the better you’re able to focus on the work that matters to you.

We’re especially excited to unveil the Cisco Spark Depot, our latest, greatest expansion to Cisco Spark. Simply put, the Spark Depot is an ever-growing catalog of integrations and bots for businesses of all shapes and sizes. Now, the apps you rely on, like Salesforce, Trello, Jira, Box, and more, can be instantly configured to connect to the Spark team-rooms of your choosing. This means less flipping between applications. But it also means that the work you do in one tool is seen by the rest of your team. With a little help from the Cisco Spark Depot, you’ll work smarter while you work together.

Depot home

First, some clarification is in order. Bots versus integrations: What’s the difference? An integration provides basic notifications for a service, acting on behalf of a Spark user. On the other hand, a bot can perform tasks for any of the users in the room, presenting itself as another user or machine account. In addition to sending messages, a bot can post files and respond to messages — even join calls.

If you’re a developer, partner, or ISV, you might be wondering how you can contribute your own bot or integration to the Spark Depot. You can easily submit your ideas through the Cisco Spark for Developers portal here. Once you do, we’ll run both a business and technical review. Users can submit feedback, report issues, and even request new integrations and bots through the support link in your app page. Now that the Spark Depot is live, why wait to submit? You’ll help make Cisco Spark even better, and become an early, visible player in our expanding platform ecosystem.

Simple for consumers, simple for developers. Those are just two of the many strengths of the Cisco Spark Depot, and we can’t wait to see how you use it. Though the Spark Depot launched today, we’re already thinking about what’s next. Stay tuned and follow @CiscoSparkDev for the latest news.

https://developer.webex.com/blog/the-cisco-spark-depot-bots-and-integrations-have-arrived https://developer.webex.com/blog/the-cisco-spark-depot-bots-and-integrations-have-arrived Tue, 01 Nov 2016 00:00:00 GMT
<![CDATA[Enhancements to the People API]]>

This update applies to those using the People API. We are making enhancements to support one’s own avatar. This will be available in the coming weeks with more details.

We focus on providing you the best features and experience. If you have any support questions, feel free to reach out to us at devsupport@ciscospark.com or join the DevSupport Spark room. Follow us on Twitter to keep updated.

- Spark for Developers Team

https://developer.webex.com/blog/enhancements-to-the-people-api https://developer.webex.com/blog/enhancements-to-the-people-api Tue, 25 Oct 2016 00:00:00 GMT
<![CDATA[Changes to the People API]]>

Hello everyone!

This update applies to those using the People API. We are adding additional attributes to the /people resource. New attributes include firstName, lastName, and timeZone information of the people.

We focus on providing you the best features and experience. If you have any support questions, feel free to reach out to us at devsupport@ciscospark.com or join the DevSupport Spark room. Follow us on Twitter to keep updated.

- Spark for Developers Team

https://developer.webex.com/blog/changes-to-the-people-api https://developer.webex.com/blog/changes-to-the-people-api Fri, 21 Oct 2016 00:00:00 GMT
<![CDATA[Announcing Admin APIs]]>

Hello everyone,

We have received feedback from our growing partner community about Admin APIs. We are happy to announce the upcoming availability of Admin APIs. You may tentatively see them on the Spark for Developers portal in the next few weeks. With Admin APIs, an admin will be able to provision a user, assign roles, assign licenses, and view license usage of an organization.

We focus on providing you the best features and experience. If you have any support questions, feel free to reach out to us at devsupport@ciscospark.com or join the DevSupport Spark room. Follow us on Twitter to keep updated.

- Spark for Developers Team

https://developer.webex.com/blog/announcing-admin-apis https://developer.webex.com/blog/announcing-admin-apis Fri, 21 Oct 2016 00:00:00 GMT
<![CDATA[Import a postman collection for Cisco Spark, or contribute your own!]]>

Cisco Spark APIs comes with a great companion — its interactive documentation - that lets you quickly experiment with the API. If you have not tested it yet, take a minute to create a room.. and don’t miss the “Test Mode" toggle button where magic happens when you switch it on!

endpoint rooms


This documentation may fall short when it comes to code generation or if you need to experiment with more advanced features such as pagination. This is where a REST client tool such as Postman that can help.

We’re happy to announce the postman-ciscospark is now available on Github.

The project contains a Postman collection that let you generate code for any Cisco Spark API resources: pick a resource and get a code snippet for the language of your choice.

generate code snippets Nodejs code snippet to list Spark Rooms

Now you’re just a few clicks away from this new superpower: import and configure the collection to try it for yourself!

Note that this collection leverages the scripting capability of Postman, so that you can run queries with no need to copy-paste identifiers as you create new resources.

Not a Postman user yet? The REST tool comes with a free basic plan! Simply download a Chrome or Desktop version. If you have personal collections that prove to be handy over time, please feel free to add your contribution.

https://developer.webex.com/blog/import-a-postman-collection-for-cisco-spark-or-contribute-your-own- https://developer.webex.com/blog/import-a-postman-collection-for-cisco-spark-or-contribute-your-own- Tue, 11 Oct 2016 00:00:00 GMT
<![CDATA[Cisco Spark at TechCrunch Disrupt San Francisco]]>

This year in San Francisco, the Spark4Devs team was there to watch as some talented coders used our APIs to hack their way through the competition and emerge with some pretty amazing projects!

Take for example, PepperHealth which uses Cisco Spark and other platforms including the Pepper humanoid robot to detect, monitor and alert healthcare workers to patients' conditions.

Or FoodWagon, a bot which uses the Sparkbot framework, "flint," to bring co-workers together during lunch time!

Both of these projects won prizes for their innovative uses of Spark during the TechCrunch Disrupt Hackathon. But even if the developers didn't win a prize, there was pizza for all, and that makes everyone feel like a winner.


After the hackathon, we spread the good news about Cisco Spark around the convention floor while startups competed for tech dominance, and we listened to some giants of the industry explain just a little bit about how they got so big.


Thanks to everyone who supported us during TCDisrupt! Until next time, check out the other teams that utilized Cisco Spark and give all of them some love!

stage love

https://developer.webex.com/blog/cisco-spark-at-techcrunch-disrupt-san-francisco https://developer.webex.com/blog/cisco-spark-at-techcrunch-disrupt-san-francisco Tue, 27 Sep 2016 00:00:00 GMT
<![CDATA[The Gupshup-Spark Integration: Bot-Building for Your Business]]>

Today’s business world is filled with applications that deliver unprecedented ease, simplicity, and speed to users in the workforce. At least that’s what they’re meant to do. The best apps – those that get the most use and offer the highest return — are those that are most accessible to users. The easier it is for a user to access and implement an app, the more the app can provide the benefits it’s designed to deliver.

And that’s where the Gupshup integration with Cisco Spark comes in. Gupshup is a user-friendly platform that enables developers to easily create bots that allow users to interact with their most important business applications. Gupshup’s integration with Cisco Spark means users can use and access business applications without ever leaving their Spark rooms.

Let’s look at an example of how this works. Say the users in your procurement department regularly use an automated app to track inventory. Using Gupshup, you can build out a bot that lets your procurement team access this app easily from inside Cisco Spark. Instead of leaving Spark to enter the app, a procurement team member can input a simple slash command into Spark, like /inventory. The bot receives this command and pulls the relevant information from the inventory app to be viewed within Spark.

One of the great things about Gupshup is that it’s so easy to use. To get a bot up and running, just follow the simple steps below:

  • Using your existing GitHub account, create a free Gupshup account.
  • Use the Gupshup code template and test screen for rapid code development.
  • With just a few lines of code, instruct your bot to do what you need it to do.
  • Finally, make the connection to Spark by simply copying and pasting your Spark bot access token.

And that’s that. Check out Gupshup, get busy building bots, and have fun!

Using Gupshup with Cisco Spark from Cisco Spark for Developers on Vimeo.

https://developer.webex.com/blog/the-gupshup-spark-integration-bot-building-for-your-business https://developer.webex.com/blog/the-gupshup-spark-integration-bot-building-for-your-business Mon, 12 Sep 2016 00:00:00 GMT
<![CDATA[Make Your Spark Bot Smart: The New API.AI-Spark Integration]]>

We’re very excited to announce one of the newest integrations with Cisco Spark: API.AI. With this integration, developers can use Spark and API.AI to configure their Spark bot with customized, nuanced, human language that enables users to interact more easily and effectively with their bot. With natural language understanding, API.AI lets developers create simple, fluid communications that increase efficiency and improve self-service.

Let’s take a look at how this works. Say you want to configure your Spark bot to help your users manage their schedules and set reminders. There are lots of ways a person could ask a bot to set a reminder. Using API.AI, you can create a category defining your request type. You might call this request type “Reminders.” You can then use API.AI to establish some of the different phrases and language that might be used when a user makes a request for a schedule reminder. For example, a user might type:

  • Remind me to call Evan at 3 p.m.
  • Set a meeting with Evan at 3 p.m.
  • Appointment with Evan at 3 p.m.
  • Set a reminder for me to call Evan at 3 p.m.

After you’ve filled out the possible ways a person might request to set a reminder, you can program a specific action so the bot knows what to do when it encounters this request. For instance, any of the above requests may prompt the bot to send a reply to the user that says, “I have set an automatic reminder for this request. Is there anything else I can help you with?”

One of the key benefits of the API.AI integration with Spark is that it creates an outstanding, easy user experience. Users can interact with the Spark bot intuitively without having to memorize things like slash commands, and developers can have the bot up and running with just one click!

Using Api.ai with Cisco Spark from Cisco Spark for Developers on Vimeo.

https://developer.webex.com/blog/make-your-spark-bot-smart-the-new-api-ai-spark-integration https://developer.webex.com/blog/make-your-spark-bot-smart-the-new-api-ai-spark-integration Mon, 12 Sep 2016 00:00:00 GMT
<![CDATA[Spark GitHub Bot]]>

To help with the understanding of bots, we put together a walkthrough of a Github to Spark integration – official integrations with Github exist now, and will be expanded, so this is purely for demonstration purposes (but you can use the code now if you want an integration you can more directly control).

The bot we outline in this blog listens for commits and comments on a particular repo, and then posts the details into a group or team room. The below parameters will be included in the message to a Spark room:

  • Author Name
  • Committer Name
  • Pusher Name
  • Commit id
  • Commit time
  • Repository
  • Link to the Commit
  • Comment
  • Comment Link
  • Comment User
  • Repo
  • Commit id

Refer to the Github docs on Event Types for more information on the parameters themselves.

Now we’ll go through the steps to build the bot.

Step 1: Create the bot

To have a bot account, you will need to log into Spark with an actual user account (a real email and password) and then create the bot under that account: https://developer.ciscospark.com/add-app.html

Step 2: Add the bot to a dedicated Room

The bot needs to be in the room in order to POST messages to it – you can add the bot via the client (just search for the bot email) or you can add it using an API call.

Step 3: Create a Github Webhook

We’ll assume you already have a repository on Github, as how to create and upload files to Github is outside the scope of this blog, so the next step is to get a Github Webhook (not a Spark webhook – similar concept, just going the other direction).

To set up a repository webhook on GitHub, you can either use the Github GUI or the API. If using the GUI, navigate to the Settings page of your repository and click on Webhooks & services. After that, click on Add Webhook.

Alternatively, you can choose to build and manage a webhook through the Webhooks API, which is what we’ll use. Before we proceed, we recommend reviewing the links below for more details on using the API to create a webhook:

Once you’ve reviewed those links, we can start making the actual API calls. First one will be a POST to /repos/:owner/:repo/hooks. Make sure to update the :owner and :repo fields with your Github username and the name of your repository respectively:

Here’s how the body of our request should look:


  "name": "web",

  "active": true,

  "events": \[




  "config": {

    "url": "[https://example.io](https://example.io)",  #Replace this with Your\_POST\_Server_URL

    "content_type": "json",

"secret":"EventsToSparkRoom"  #Webhook secret which is used to validate requests



Once it’s been successfully created, you should get a response similar to this:


  "type": "Repository",

  "id": 9415141,

  "name": "web",

  "active": true,

  "events": \[




  "config": {

    "url":  "[https://example.io](https://example.io)",

    "content_type": "json",

    "secret": "********"


  "updated_at": "2016-08-06T22:38:05Z",

  "created_at": "2016-08-06T22:38:05Z",

  "url": "[https://api.github.com/repos/Colbyter/TestWebhook/hooks/9415141](https://api.github.com/repos/Colbyter/TestWebhook/hooks/9415141)",

  "test_url": "[https://api.github.com/repos/Colbyter/TestWebhook/hooks/9415141/test](https://api.github.com/repos/Colbyter/TestWebhook/hooks/9415141/test)",

  "ping_url": "[https://api.github.com/repos/Colbyter/TestWebhook/hooks/9415141/pings](https://api.github.com/repos/Colbyter/TestWebhook/hooks/9415141/pings)",

  "last_response": {

    "code": null,

    "status": "unused",

    "message": null



You also have the option of securing your webhook using a secret, to validate the payload is really coming from Github; you would need to do a quick signature check if you elected to go that route. Check this link for more details on securing your Github webhooks.

With the webhook created, we’ll move on to configuring your server.

Step 4: Configure Your Server

We will now set up a simple Flask Server with a Python application, which receives incoming payloads from Github and sends them to Spark:

In this example, the server code is hosted on Cloud9 (C9). However, you can run locally and expose it to the web using ngrok, host it on an Amazon EC2 instance, or use any other hosting solution of your choice. We’ll first import the various dependencies:

from flask import Flask, request, abort

import json

import urllib, urllib2

import hmac

import hashlib

Then we’ll define a couple variables – one for the server setup and one for a webhook secret:

app = Flask(\_\_name\_\_)

#Secret provided in the Github webhook config.Change this to your own secret phrase

SECRET_TOKEN = "EventsToSparkRoom"

Next we’ll setup the function that validates the secret with a fairly straightforward if/else (the docs on the Github site about securing your webhook will explain most of this logic) and then establish some message formatting (using Markdown) so our POST to the Spark room is readable:

@app.route('/', methods =\['POST'\])

def githubCommits():

    ''' This function validates if the request is properly signed by Github. (If not, this is a spoofed webhook.). Then collects the webhook payload sent from Github and parses the parameters you want to send to Spark Room


    headers = request.headers

    incoming_signature = headers.get('X-Hub-Signature')

    signature = 'sha1=' + hmac.new(SECRET_TOKEN, request.data, hashlib.sha1).hexdigest()

    if incoming_signature is None:


    elif signature == incoming_signature:

        json_file = request.json

        if 'push' == headers.get('X-GitHub-Event'):

            commit = json_file\['commits'\]\[0\]

            commit_id = commit\['id'\]

            commit_message = commit\['message'\]

            commit_time = commit\['timestamp'\]

            commit_url = commit\['url'\]

            commit\_author\_name = commit\['author'\]\['name'\]

            committer_name = commit\['committer'\]\['name'\]

            pusher\_name = json\_file\['pusher'\]\['name'\]

            repo\_name = json\_file\['repository'\]\['name'\]

            results = """\*\*Author\*\*: %s\\n\\n\*\*Committer\*\*: %s\\n\\n\*\*Pusher\*\*: %s\\n\\n\*\*Commit Message\*\*: %s\\n\\n\*\*Commit id\*\*: %s\\n\\n\*\*Time\*\*: %s\\n\\n\*\*Repository\*\*: %s\\n\\n\*\*Commit Link\*\*: %s<br><br>""" % (commit\_author\_name,committer\_name,pusher\_name,commit\_message,commit\_id,commit\_time,repo\_name,commit_url)


            return 'Ok'

        elif 'commit_comment' == headers.get('X-GitHub-Event'):

            comment\_raw = json\_file\['comment'\]

            comment\_url = comment\_raw\['html_url'\]

            comment\_user = comment\_raw\['user'\]\['login'\]

            commit\_id = comment\_raw\['commit_id'\]

            comment = comment_raw\['body'\]

            comment\_repo = json\_file\['repository'\]\['name'\]

            results = """\*\*User\*\*: %s\\n\\n\*\*Comment on Commit\*\*: %s\\n\\n\*\*Comment url\*\*: %s\\n\\n\*\*Commit id\*\*: %s\\n\\n\*\*Repository\*\*: %s<br><br>""" % (comment\_user,comment,comment\_url,commit\_id,comment\_repo)


            return 'Ok'           


        print "Spoofed Hook"


Then here we will extract the content from the Github webhook and POST it back to a Spark room – note you will need to populate BOT_TOKEN with your bot’s access token, so the message will post from the bot user in the room, and “YOUR_ROOM_ID” with the actual Spark roomId:

\# POST Function that sends the commits & comments in markdown to a Spark room   

def toSpark(commits):

    url = '[https://api.ciscospark.com/v1/messages](https://api.ciscospark.com/v1/messages)'

    headers = {'accept':'application/json','Content-Type':'application/json','Authorization': 'Bearer  BOT_TOKEN'}

    values = {'roomId':'YOUR\_ROOM\_ID', 'markdown': commits }

    data = json.dumps(values)

    req = urllib2.Request(url = url , data = data , headers = headers)

    response = urllib2.urlopen(req)

    the_page = response.read()

    return the_page

if \_\_name\_\_ == '\_\_main\_\_':

    app.run(host='' , port=8080, debug =True)

Put it all together and you have an application that takes data from a Github webhook, validates it’s from Github, formats the content using Markdown, and POSTs the easily readable content to the Spark room from a bot. Here’s an example of the formatted content:


The complete code can be found on Github and if you have any questions, please contact devsupport@ciscospark.com or join us in the #spark4devs room.

For additional information on using Spark bots, check out this blog.

https://developer.webex.com/blog/spark-github-bot https://developer.webex.com/blog/spark-github-bot Mon, 29 Aug 2016 00:00:00 GMT
<![CDATA[Built.io Bot Webinar part 2]]>

It was awesome to see experts come together in a special webinar to teach us all about making a bot in Cisco Spark using Built.io! On August 10th, Steve Greenburg from our team and Kurt Collins from Built.io joined up to teach the Internet everything they needed to know, and they’re coming back for more on Wednesday, August 31 at 9:30 am.

Join us again for more insight into the world of bots! Be sure to sign up early right here so you don’t miss it, and if you missed the last one, you can read the blog post about it here.

https://developer.webex.com/blog/built-io-bot-webinar-part-2 https://developer.webex.com/blog/built-io-bot-webinar-part-2 Tue, 23 Aug 2016 00:00:00 GMT
<![CDATA[IRC to Spark and Back Again]]>

With the recent release of bot functionality for Cisco Spark’s API, we’ve explored methods to integrate Spark rooms with older legacy technology, to bring them into the next generation. With this in mind, we built a Spark bot application that transmits messaging and state information between Cisco Spark and an IRC channel – effectively linking one of the original bot platforms to one of the most recent.

The first major step to building any multi-function application is to set a roadmap for the application’s functionality. The application that we are developing will:

Now that we have a basic idea of what our application needs, let’s locate some resources that will help us accomplish our end goal. NodeJS has a default webserver library, http, that fulfills the needs for our receiving portion perfectly, but we will need to install two additional libraries for NodeJS. One handles IRC, and the other handles sending RESTful requests. To install on OSX or Linux, use npm:

npm install irc

npm install request

Since we now have these two libraries installed, let’s generate a script file that includes the libraries we’ll be using:

// External libraries
var request = require('request');
var http = require('http');
var irc = require('irc');

At this point, we are ready to start building our bot application. Since our application is based around events that occur in both Cisco Spark and a specific IRC channel, we will need to make event listeners for both. Let’s start by generating the IRC connection, and the event listeners associated with it:

var botName = 'IRCToSparkBot'; // The name of your bot
var myChannel = '#mychan'; // The channel your bot is active on

var bot = new irc.Client('irc.freenode.net', botName, { //Create Bot
    channels: \[myChannel\]

bot.addListener('message' + myChannel, function (from, message) { // Add listener for channel


bot.addListener('pm', function (from, message) { // Add listener for PM


bot.addListener('join', function(channel, who) { // Add listener for user joins


bot.addListener('part', function(channel, who, reason) { // Add listener for user parts


Now that the framework for our IRC connection is set up, we can begin generating a way for it to communicate with our Spark Bot. Since Spark Bots communicate via REST calls, we will need to generate a function that handles sending these calls:

function sendRequest(myURL, myMethod, myHeaders, myData, callback) { // Sends RESTful requests

  var options = {
    url: myURL,
    method: myMethod,
    json: true,
    headers: myHeaders,
    body: myData

  var res = '';

  request(options, function optionalCallback(error, response, body) {
    if (error) {
      res = "Request Failed: " + error;
    } else {
      res = body;

You may notice that the function we created supports multiple methods, headers and URLs. We are building our request function this way so that it can be used universally throughout our application, if we ever decide to expand upon the systems it’s integrated with. Additionally, we also include a callback function; this will allow us to effectively receive and parse the information returned from our requests.

With the request function built, we can begin collecting commonly used global variables that will be reused throughout our application:

  • Spark Bot's Bearer Token
  • Spark Bot's Target Room ID
  • Spark's Required Headers
  • Spark's Message URL for Sending and Receiving Messages

We’ll define them globally in the application:

var myToken = ''; // user/bot bearer token
var myRoomID = ''; // Spark RoomId for bot
var sparkHeaders = {'content-type': 'application/json; charset=utf-8', 'Authorization':'Bearer ' + myToken}; // Basic Cisco Spark Header
var messagesURL = 'https://api.ciscospark.com/v1/messages/'; // Spark Messages API URL, do not modify

With a few more additions to the IRC listeners, we can effectively receive information with our bot in IRC and send it into Cisco Spark. In the next code section, we add calls to our sendRequest from each of the listeners POSTing messages to the Spark room:

// External libraries
var request = require('request');
var http = require('http');
var irc = require('irc');

var botName = {irc:'IRCToSparkBot', spark:'IRCToSparkBot', sparkEmail:'IRCToSparkBot@sparkbot.io'}; // The name of your bot
var myChannel = '#mychan'; // The channel your bot is active on
var myToken = ''; // user/bot bearer token
var myRoomID = ''; // Spark RoomId for bot
var sparkHeaders = {'content-type': 'application/json; charset=utf-8', 'Authorization':'Bearer ' + myToken}; // Basic Cisco Spark Header
var messagesURL = 'https://api.ciscospark.com/v1/messages/'; // Spark Messages API URL, do not modify

function sendRequest(myURL, myMethod, myHeaders, myData, callback) { // Sends RESTful requests

  var options = {
    url: myURL,
    method: myMethod,
    json: true,
    headers: myHeaders,
    body: myData

  var res = '';

  request(options, function optionalCallback(error, response, body) {
    if (error) {
      res = "Request Failed: " + error;
    } else {
      res = body;

var bot = new irc.Client('irc.freenode.net', botName, { //Connect to IRC
    channels: \[myChannel\]

bot.addListener('message' + myChannel, function (from, message) { // Add listener for channel

  sendRequest(messagesURL, "POST", sparkHeaders, { roomId: myRoomID, text: from + ': ' + message}, function(resp){});

bot.addListener('pm', function (from, message) { // Add listener for PM

  sendRequest(messagesURL, "POST", sparkHeaders, { roomId: myRoomID, text: 'PM from ' + from + ': ' + message}, function(resp){});

bot.addListener('join', function(channel, who) { // Add listener for user joins

  sendRequest(messagesURL, "POST", sparkHeaders, { roomId: myRoomID, text: who + ' has joined ' + channel + ' - '}, function(resp){});

bot.addListener('part', function(channel, who, reason) { // Add listener for user parts

  sendRequest(messagesURL, "POST", sparkHeaders, { roomId: myRoomID, text: who + ' has left ' + channel + ' - '}, function(resp){});

The first half of our application is complete, so it’s time to start on the rest - sending messages received in Cisco Spark to the IRC channel where our bot resides. During this portion, we need to set up a listener (which will require us to declare a port), and parse the REST body received by our application. To do this, we will use the http library and create the listener, as well as a catch to handle all unsupported information:

var portNumber = 8080; // Set listen port number

http.createServer(function (req, res) { // Set up web listener to receive Webhook POST / Relaying. AKA the magic.

  if (req.method == 'POST') {

    req.on('data', function(chunk) {
      var resObj = JSON.parse(chunk.toString());


    req.on('end', function() {
      res.writeHead(200, "OK", {'Content-Type': 'text/html'});

  } else {
    console.log("\[405\] " + req.method + " to " + req.url);
    res.writeHead(405, "Method not supported", {'Content-Type': 'text/html'});
    res.end('405 - Method not supported');
}).listen(portNumber); // listen on tcp portNumber value (all interfaces)

Notice that we pass in the port number via a global variable when creating our http server. This will allow us to easily set up different instances of the same application as new processes at a later time. Be sure to define the port number for the http server to access globally.

Our application is ready to receive requests. It’s time to generate the webhook that will translate Spark messages into requests sent to the IRC room. First, we must create a bot. To create a bot, go to this page and select the button “Create a Bot”.

On the page to follow, you are given the choice to name your bot, address it, and add an icon to its spark profile. Now that the bot has been created, we can collect the bot’s bearer token, which will be used throughout our application as we develop it. Proceed to the bots page by going to the “My Apps” page, selecting the bot and then clicking “Regenerate Access Token”.

With the bot’s bearer token recorded, it’s time to create a webhook. To do this, we are going to send a POST request to https://api.ciscospark.com/v1/webhooks with the following headers and body:

      'content-type': 'application/json; charset=utf-8',
      'Authorization':'Bearer MYTOKEN'

      "name": "IRCToSparkBot",
      "targetUrl": "http://www.myboturl.com/",
      "resource": "messages",
      "event": "created",
      "filter": "roomId=MYROOMID"

With the webhook created using the bot’s token, Spark will send a POST request to our defined target URL whenever the bot is explicitly mentioned in the designated room.

We can now safely assign values to the myRoomID and myToken global variables in our application - they had placeholders earlier:

var myToken = ''; // user/bot bearer token
var myRoomID = ''; // Spark RoomId for bot

These values should reflect the roomId and bearer token of the bot.

Now that our webhook is configured, we can begin interpreting the received JSON body. For security purposes, the JSON body sent by the webhook does not include the message text, it contains an encrypted ID. We need to set up logic within our http listener to collect the encrypted message ID from the received JSON and send an authenticated GET request to grab the message text from Spark using the bot Bearer Token:

http.createServer(function (req, res) { // Set up web listener to receive Webhook POST / Relaying. AKA the magic.

  if (req.method == 'POST') {

    req.on('data', function(chunk) {
      var resObj = JSON.parse(chunk.toString());
      sendRequest(messagesURL + resObj.data.id, "GET", sparkHeaders, '', function(resp){});


    req.on('end', function() {
      res.writeHead(200, "OK", {'Content-Type': 'text/html'});

  } else {
    console.log("\[405\] " + req.method + " to " + req.url);
    res.writeHead(405, "Method not supported", {'Content-Type': 'text/html'});
    res.end('405 - Method not supported');
}).listen(portNumber); // listen on tcp portNumber value (all interfaces)

It’s time to do something with our returned message text. We are going to make our bot in IRC send a message to the channel it resides in based off the text received from the JSON GET response body:

http.createServer(function (req, res) { // Set up web listener to receive Webhook POST / Relaying. AKA the magic.

  if (req.method == 'POST') {

    req.on('data', function(chunk) {
      var resObj = JSON.parse(chunk.toString());
      sendRequest(messagesURL + resObj.data.id, "GET", sparkHeaders, '', function(resp){

        var myMessageObj = {};
        if (resp.personEmail != botName.sparkEmail) {bot.say(myChannel, resp.text);}



    req.on('end', function() {
      res.writeHead(200, "OK", {'Content-Type': 'text/html'});

  } else {
    console.log("\[405\] " + req.method + " to " + req.url);
    res.writeHead(405, "Method not supported", {'Content-Type': 'text/html'});
    res.end('405 - Method not supported');
}).listen(portNumber); // listen on tcp portNumber value (all interfaces)

If you’re testing the code as we’re walking through it, you might notice the bot’s name is included in the message, due to the mention requirement discussed earlier. This won’t look right to IRC users, as they won’t know anything about the Spark bot, so we’ll create a String filter to remove the mention (note this may change in the future where the mention will be omitted, which may require a code change). While we are making that filter, let’s also look at other functionality our bot will need to be fully operational:

  • Sending and receiving private messages
  • Determining whether to send a private message, or a channel message
  • Displaying a help message for new chat room users

Our solution to overcoming these obstacles is a function - this function will take the initial string received and search for a command, such as a short character combo like “m” or “pm” and then parse the individual words to follow. A message command may be as simple as “m MESSAGE” while a private message may be as complex as “pm USER MESSAGE”. This means each of the commands will require a different number of arguments so we should create an object that defines how many arguments each command has:

var commands = {

Phrasing can be pretty flexible since the bot needs to be mentioned before it will act, so accidental typing of letters like just “m” won’t trigger any action unless preceded by the botname.

Now that the object contains each command and their argument count, let’s generate the function that will decipher the message text and output an object that contains all the necessary values to send the correct text to the correct destination in IRC:

function messageInterpreter(myMessage) {

  var myReturnObj = {};
  var preProcessedString = myMessage;
  var index = 0;

  if (myMessage === undefined) {
    return '';

  //Determines Command
  preProcessedString = myMessage.slice(myMessage.search(botName.spark) + botName.spark.length + 1);
  if (preProcessedString.includes(' ')) {
    index = preProcessedString.search(' ');
    myReturnObj.command = preProcessedString.slice(0, index);
    preProcessedString = preProcessedString.slice(index + 1);
  } else {
    myReturnObj.command = preProcessedString.slice(0);
    return myReturnObj;

  if (commands.hasOwnProperty(myReturnObj.command)) {
    myReturnObj.argument = {};
    for (i = 0; i < commands\[myReturnObj.command\].args; i++) {
      index = preProcessedString.search(' ');
      myReturnObj.argument\[i\] = preProcessedString.slice(0, index);
      preProcessedString = preProcessedString.slice(index + 1);
    myReturnObj.value = preProcessedString;
  return myReturnObj;

The final step is to create the switch that controls what to do in response to each of the commands. This will be done from within the http server’s logic:

http.createServer(function (req, res) { // Set up web listener to receive Webhook POST / Relaying. AKA the magic.

  if (req.method == 'POST') {

    req.on('data', function(chunk) {
      var resObj = JSON.parse(chunk.toString());
      sendRequest(messagesURL + resObj.data.id, "GET", sparkHeaders, '', function(resp){
        var myMessageObj = {};
        if (resp.personEmail != botName.sparkEmail) {myMessageObj = messageInterpreter(resp.text);}

        switch (myMessageObj.command) {
          case 'pm': 
            if (bot.chans\[myChannel\].users.hasOwnProperty(myMessageObj.argument\[0\]) && myMessageObj.value !== '') {
              bot.say(myMessageObj.argument\[0\], myMessageObj.value);
            } else if (myMessageObj.value === '') {
              sendRequest(messagesURL, "POST", sparkHeaders, { roomId: myRoomID, text: 'PM FAILED TO ' + myMessageObj.argument\[0\] + ' FAILED: NO VALUE TO SEND'}, function(resp){});
            } else {
              sendRequest(messagesURL, "POST", sparkHeaders, { roomId: myRoomID, text: 'PM FAILED: USER ' + myMessageObj.argument\[0\] + ' DOESNT EXIST '}, function(resp){});

          case 'm':
            bot.say(myChannel, myMessageObj.value);

          case 'help':
            sendRequest(messagesURL, "POST", sparkHeaders, { roomId: myRoomID, text: helpMessage}, function(resp){});


    req.on('end', function() {
      res.writeHead(200, "OK", {'Content-Type': 'text/html'});

  } else {
    console.log("\[405\] " + req.method + " to " + req.url);
    res.writeHead(405, "Method not supported", {'Content-Type': 'text/html'});
    res.end('405 - Method not supported');
}).listen(portNumber); // listen on tcp portNumber value (all interfaces)

And with that, you have the complete IRC to Cisco Spark and back demo bot. The complete code can be located on our Github, and if you have any questions or need any help, please feel free to reach out via devsupport@ciscospark.com!

https://developer.webex.com/blog/irc-to-spark-and-back-again https://developer.webex.com/blog/irc-to-spark-and-back-again Sat, 20 Aug 2016 00:00:00 GMT
<![CDATA[Rate Limiting with Spark API]]>

To protect the Spark environment, the API has rate limits in place for the different resources available for use, such as /messages and /rooms. These limits will vary depending on the calls being made, how resource intensive that call is on the servers, and how many servers are actively in routing – and is subject to change as needed to protect all use cases from failing in the event of a large batch of requests. So, what should be done if you want to make API calls very frequently, but don’t want to hit errors and lose requests by going over the rate limit? The answer is to use the Retry-After Header that is returned with an HTTP 429 error. The Retry-After header defines the number of seconds you’ll need to wait before sending API requests again.

The app that follows pulls the list of rooms available to the user (using a single user or bot’s bearer token), as fast as possible. Normally, it would be recommended to put some kind of wait time between continuous looping requests, to avoid hitting the rate limit entirely. However, since that rate limit might be reached anyway depending on the resource availability, it’s important to handle for the likely possibility you’ll catch a 429 here and there.

Basically, we make a call to https://api.ciscospark.com/v1/rooms continuously and look for an error. If the error is a status code 429, we check the wait time relayed to us in the Retry-After header and sleep for the time specified before starting again. If there’s an error, but it isn’t a 429, we break out of the loop because something else is wrong. Maybe you had a bad bearer token, or maybe there is a general error with the format of the request.

Since this code can run forever if implemented properly, you’ll need to Ctrl+C to kill it in the Terminal itself – make sure you don’t let it go on indefinitely or you could be flagged depending on how many requests are made and for how long. The initial portion of the application is making the call to the rooms resource to get the rooms over and over, whereas the latter section beginning with the line:

except urllib2.HTTPError as e:

defines what to do if a 429 error is encountered – print out the content of the error, and then extract the value of the Retry-After header for use in the sleep. Here’s the full app (it’s short so we’ll put the whole thing):

import urllib2
import json
import time

def sendSparkGET(url):
    request = urllib2.Request(url,
 headers={"Accept" : "application/json",
 request.add_header("Authorization", "Bearer "+bearer)
    response = urllib2.urlopen(request)
    return response

bearer = "BEARER\_TOKEN\_HERE"

while True:
        result = sendSparkGET('https://api.ciscospark.com/v1/rooms')
        print result.code, time.time(), result.headers\['Trackingid'\]
    except urllib2.HTTPError as e:
        if e.code == 429:
            print 'code', e.code
            print 'headers', e.headers
            print 'Sleeping for', e.headers\['Retry-After'\], 'seconds'
 sleep_time = int(e.headers\['Retry-After'\])
            while sleep_time > 10:
 sleep_time -= 10
                print 'Asleep for', sleep_time, 'more seconds'
            print e, e.code

It’s important to note that it’s possible to send a request after receiving a 429 without getting an error; there are many servers involved with handling a request, so just because you’ve hit the rate limit of one, does not mean you’ve hit the rate limit of all. However, you’re probably pretty close to failing on every server, so it’s best to wait for the time described by Retry-After upon detecting the very first 429.

The full code can be found on our Github.

As always, if you have any questions, please contact devsupport@ciscospark.com 24/7/365 - we’re happy to help!

https://developer.webex.com/blog/rate-limiting-with-spark-api https://developer.webex.com/blog/rate-limiting-with-spark-api Wed, 17 Aug 2016 00:00:00 GMT
<![CDATA[Downloading a File from a Spark Room]]>

If you’ve ever wondered, “How do I retrieve a file using the API – it’s just a URL with an encrypted ID!”, this example should hold the answer. It uses a bot to download a file sent to a 1:1 room (a conversation between the bot and a single user), using a webhook. If your bot is in a group room, it will only be able to retrieve files where the bot is explicitly mentioned, like @botname.

For additional help creating a webhook, we recommend checking out our webhook blog and our simple (but complete) bot demo.

Alternatively, if you’re using an access token retrieved using Oauth, you can retrieve the messages in a room with this function.

In the Webhooks Explained page, the section titled Handling Requests from Spark describes the format of webhook messages. When a file is sent to the 1:1 room with the bot, the webhook will send JSON to your server containing a files key, under the data element, in addition to the other attributes such as personEmail:

{"resource": "messages", "name": "Web hook name", "created": "2016-07-12T18:24:17.179Z", "id": "Y2lzY29zcGFyazovL3VzL1dFQkhPT0svMWU3Y2Y4OGMtYTE4My00ZGQyL123456789", "filter": "roomId=Y2lzY29zcGFyazovL3VzL1JPT00vNmFjNjA0OTAtMDU3YS0xMW123456789", "targetUrl": "[http://myurl.com](http://myurl.com/)", "data": {"files": \["[https://api.ciscospark.com/v1/contents/Y2lzY29zcGFyazovL3VzL0NPTlRFTlQvY2IyZDNhYjAtNWEzZS0xMWU2L12345678](https://api.ciscospark.com/v1/contents/Y2lzY29zcGFyazovL3VzL0NPTlRFTlQvY2IyZDNhYjAtNWEzZS0xMWU2L12345678)"\], "roomType": "group", "created": "2016-08-04T12:27:22.459Z", "personId": "Y2lzY29zcGFyazovL3VzL1BFT1BMRS84ZDUwY2M5NS0wMWMyLTQwZmUtOTU5OC1mZmE4M1234567", "personEmail": "[person@example.com](mailto:person@example.com)", "roomId": "Y2lzY29zcGFyazovL3VzL1JPT00vNmFjNjA0OTAtMDU3YS0xMWU2LWEw123456789", "id": "Y2lzY29zcGFyazovL3VzL01FU1NBR0UvY2IyZDNhYjAtNWEzZS0xMWU123456789"}, "event": "created"}

The files attribute is a list of URLs (one URL if only one file is sent in a single message, multiple URLs if more than one file is sent at the same time) that will be used to retrieve the actual files. The URL for the file will be the request URL in your REST GET, and you’d just need to then pass the bot’s authentication token in a Bearer authorization header to retrieve the details (because who can view the file is limited to who is in the room – again though, in a group room, a bot’s permission is limited to messages in which it is also mentioned).

Information and additional examples on retrieving messages is detailed here.

The “Content-Disposition” header in the GET response is used to determine the file’s name and file type to be saved. The file data is the entire body of the GET response. There is no base 64 or other special encoding of the file data, so it can be written directly to the destination. So if we were retrieving an image from our example above, we would run the GET on:


and we would get back:

Cache-Control: no-cache

Content-Disposition: attachment; filename="04\_12\_02.jpg"

Content-Length: 264178

Content-Type: image/jpeg

Date: Thu, 04 Aug 2016 20:09:05 GMT

Server: Redacted

Trackingid: NA_028c214f-a7dc-44e8-a8bd-f82373fbc860

X-Cf-Requestid: 317eaaad-b2cf-4651-5ce0-4dbdcc700abd

Connection: close

The below code is an app that receives the data from the webhook and - if the data contains a files key - attempts to download the files directly to the source folder from where it is run (so if the app is located in your /Documents/Files folder, it will download the file to /Documents/Files).

from itty import *
import urllib2
import json

def sendSparkGET(url):
 request = urllib2.Request(url,
                            headers={"Accept" : "application/json",
 request.add_header("Authorization", "Bearer "+bearer)
 contents = urllib2.urlopen(request)
return contents

def index(request):
 webhook = json.loads(request.body)
if webhook\['data'\].has_key('files'):
for file_url in webhook\['data'\]\['files'\]:
            response = sendSparkGET(file_url)
            content_disp = response.headers.get('Content-Disposition', None)
            if content_disp is not None:
                filename = content_disp.split("filename=")\[1\]
                filename = filename.replace('"', '')
                with open(filename, 'w') as f:
                    print 'Saved-', filename
                print "Cannot save file- no Content-Disposition header received."
print "No files attached to retrieve!"
return "true"

bearer = "BOT\_TOKEN\_HERE"

run_itty(server='wsgiref', host='', port=10002)

The full code can be found on our Github.

As always, If you have any questions, please contact devsupport@ciscospark.com 24/7/365 - we’re happy to help!

https://developer.webex.com/blog/downloading-a-file-from-a-spark-room https://developer.webex.com/blog/downloading-a-file-from-a-spark-room Sun, 14 Aug 2016 00:00:00 GMT
<![CDATA[Uploading Local Files to Spark]]>

Uploading a remote file to a Cisco Spark room using a web-accessible URL is fairly self explanatory - just supply the URL in the “files” field of a create message request: https://developer.ciscospark.com/endpoint-messages-post.html

But this only works for files that are on the public Internet and can be downloaded by Spark's servers. Spark pulls the files down. However, if you want to push the file to Spark, for example to upload a file from your local hard drive, it gets a little more complicated.

We’re making all of that easier now because we now support file upload via the Messages API. This means you no longer have to put your files on the public Internet for them to be attached.

How it Works:

The Spark API accepts file uploads as a MIME upload in the same way your web browser would upload a file in a web form. The two most important aspects are 1) to name the field to which you send "files" and 2) to set your Content-Type header to be multipart/form-data including a boundary.

The boundary is part of the MIME specification and is essentially any string that won't appear in the binary encoding of the file; it’s used by the server to determine where the file content ends and the request starts.

The final header would look something like this:

**Content-Type: multipart/form-data; boundary=12345678901234567890123456789012**

In Python, it’s difficult to do everything required without the help of a couple of third party libraries. We’ll use requests (http://docs.python-requests.org/en/master/user/install/#install) and requests-toolbelt (https://github.com/sigmavirus24/requests-toolbelt).

pip install requests

pip install requests-toolbelt

Once you have those installed, the script itself is simple.

from requests_toolbelt import MultipartEncoder
import requests

filepath    = '/Users/taylorhanson/Desktop/screenshot.png'
filetype    = 'image/png'
roomId      = 'SOME ROOM'
url         = "https://api.ciscospark.com/v1/messages"

my_fields={'roomId': roomId, 
           'text': 'Hello World',
           'files': ('screenshot', open(filepath, 'rb'), filetype)
m = MultipartEncoder(fields=my_fields)
r = requests.post(url, data=m,
                  headers={'Content-Type': m.content_type,
                           'Authorization': 'Bearer ' + token})
print r.json()

Above, you’ll need to replace the variables with ones suitable for you, with the exception of the url. The filetype and filepath are totally dependent on the file you are attempting to upload - a full path to the file is expected, and the first slash in the above filepath value represents root, so it’s “root” followed by ‘/Users/taylorhanson/Desktop/screenshot.png'. The roomId value can be found from the developer portal: https://developer.ciscospark.com/endpoint-rooms-get.html

Your bearer token can be your personal one for testing, or one for a specific user via integrations: https://developer.ciscospark.com/authentication.html

Or a bot: https://developer.ciscospark.com/add-app.html

The complete code for the upload can be found on Github.

If you have any questions, please contact devsupport@ciscospark.com 24/7/365 - we’re happy to help!

https://developer.webex.com/blog/uploading-local-files-to-spark https://developer.webex.com/blog/uploading-local-files-to-spark Mon, 25 Jul 2016 00:00:00 GMT
<![CDATA[Using a Webhook Secret]]>

The recently released advanced webhooks include the ability to define a “secret” in your webhook, which will pass along with your webhook as a header called “X-Spark-Signature”. This can be used to validate a request is coming from the Spark API and not from some other origin – more info can be found at the bottom of this page.

In this blog, we’ll walk you through using the secret field, so you can start locking down your webhooks ASAP.

First, you’ll need to create a webhook.

Note the “secret” field in the list of options; to make it easy, we’ll use the passphrase listed in the example and set it to:


Next you’ll need to code up some logic that checks the secret when the webhook’s data is received. The following script shows very simple validation – just prints out a true if the secret matches. Here’s the Python code:

from itty import *
import hashlib
import hmac

def index(request):
    When messages come in from the webhook, they are processed here.
    X-Spark-Signature - The header containing the sha1 hash we need to validate
    request.body - the Raw JSON String we need to use to validate the X-Spark-Signature

    raw = request.body
    #Let's create the SHA1 signature 
    #based on the request body JSON (raw) and our passphrase (key)
    hashed = hmac.new(key, raw, hashlib.sha1)
    validatedSignature = hashed.hexdigest()

    print 'validatedSignature', validatedSignature
    print 'X-Spark-Signature', request.headers.get('X-Spark-Signature')
    print 'Equal?', validatedSignature == request.headers.get('X-Spark-Signature')

    return "true"

#Replace this with the secret phrase you used in the webhook creation
key = "somesupersecretphrase"
port = 10007
run_itty(server='wsgiref', host='', port=port)

Which can also be grabbed from Github.

Note the “key” field is the secret defined earlier when the webhook was created, which if it matches what’s sent in the webhook, will print ‘True’.

This app alone won’t do much – all it’s going to do is confirm “Yep, that’s the right secret!” and then end. But if we combo it with our recent Bot example (Spark bot demo blog | Github repo) then we can validate the secret and use it in an if / else statement. If the secret matches, keep going, if it does not, end immediately. The complete code combining the above validation script and the bot script can be found on Github as well.

From that app, here’s a snippet showing the relevant logic using validation:

raw = request.body
    #Let's create the SHA1 signature 
    #based on the request body JSON (raw) and our passphrase (key)
    hashed = hmac.new(key, raw, hashlib.sha1)
    validatedSignature = hashed.hexdigest()

    print 'validatedSignature', validatedSignature
    print 'X-Spark-Signature', request.headers.get('X-Spark-Signature')

    if validatedSignature == request.headers.get('X-Spark-Signature'):

        …RUN THE APP…

        print "Secret does not match, verboten!"

You can expand on all of the logic extensively, but for the basic use of a secret in a functional bot app, this covers what you need to know. If you have any questions, please contact devsupport@ciscospark.com 24/7/365 and we’ll be happy to help!

https://developer.webex.com/blog/using-a-webhook-secret https://developer.webex.com/blog/using-a-webhook-secret Sun, 24 Jul 2016 00:00:00 GMT
<![CDATA[Using Webhooks - Rooms, Messages, Memberships and More!]]>

Webhooks are nearly universally implemented and loved in APIs of all shapes and sizes, and the Spark API is no exception. While we launched with just an outbound messaging webhook, the advanced webhook expansion reflects a plethora of options (even a genuine firehose for all events) sure to satisfy nearly any need or want!

We’ll do a quick walkthrough of the more common use cases here, just to get you started, and look forward to the wide range of implementations our developer community puts together. Let us know on Twitter @CiscoSparkDev when you've created something cool!

We’ll start with our first (and most likely to be used) messaging webhook. You can send data showing all created messages, all deleted messages, or both. We’ll focus on created messages, as that’s the more common use. Go here.

Which will bring you to a page with these parameters:

request headers

It’s fairly straightforward – name is whatever you want to identify this webhook (really only seen when you list all your webhooks via the API), your targetUrl (in this case, a demo link from webhook.info), the resource (messages, because obviously), and created since we want all the new messages in the room vs all the deleted messages (or both). You can also define a filter – for our purposes, we’ll go with just the roomId, but you can also combo so you only get messages in a specific room from a specific person by adding multiple filters like:


When you hit Run, the sidebar should look like this:

request response

When a new message is posted to the room, you should get the following content at your targetUrl:

{"id":"Y2lzY29zcGFyazovL3VzL1dFQkhPT0svYjI5NTk2NzAtMTIwZi00OT1234567890asdfghjkl","name":"My Messaging Webhook","targetUrl":"[http://webhook.info/post/PVDYLYKPNB](http://webhook.info/post/PVDYLYKPNB)","resource":"messages","event":"created","filter":"roomId=Y2lzY29zcGFyazovL3VzL1JPT00vYTRmMzA2ZDAtNDQ3ZC0xMWU2LTk1234567890asdfghjkl","created":"2016-07-08T02:27:52.191Z","data":{"id":"Y2lzY29zcGFyazovL3VzL01FU1NBR0UvYWE2NTllODAtNDRiMy0xM1234567890asdfghjkl","roomId":"Y2lzY29zcGFyazovL3VzL1JPT00vYTRmMzA2ZDAtNDQ3ZC0xMWU2L1234567890asdfghjkl","personId":"Y2lzY29zcGFyazovL3VzL1BFT1BMRS9lM2EyNjA4OC1hNmRiLTQxZ1234567890asdfghjkl","personEmail":"[example@cisco.com](mailto:example@cisco.com)","created":"2016-07-08T02:28:33.000Z"}}

You can probably tell the message is encrypted, and therefore fairly useless at the moment. You’ll need to make a secondary, authorized call back to the API with the messageId (and personId, potentially, if you need that info) in order to retrieve the actual content of the message body. This page discusses that in more detail.

Once you retrieve the message content, you can do a variety of things with it – track commonly used phrases/questions, see which rooms are most active, use trigger words to post back responses via a bot, quite a wide range of possibilities. For the last one, we posted a recent blog about Spark bots that provides a Python example showing how to retrieve the message content and post a message back to a room; check out the blog post for that example.

Next we’ll cover adding a webhook for created rooms – this is particularly useful if you’re running a bot that can create rooms for various purposes, and want to keep track of the rooms that are generated. Back to the developer portal we go, but this time we’ll change the parameters a bit:

request headers2

Note: the resource is now ‘rooms’, instead of ‘messages’ and we added a new filter – ‘type=direct’ which means we’ll get a notification every time a 1:1 room is created using the defined Bearer token. After you hit Run, the response should look something like this:

request response 2

When I create a new 1:1 room, the content sent to my webhook will look like this:

{"id":"Y2lzY29zcGFyazovL3VzL1dFQkhPT0svMDIyNmY2MWEtZWRmYi00OT1234567890asdfghjkl","name":"My Rooms Webhook","targetUrl":"[http://webhook.info/post/PVDYLYKPNB](http://webhook.info/post/PVDYLYKPNB)","resource":"rooms","event":"created","filter":"type=direct","created":"2016-07-08T03:29:14.877Z","data":{"id":"Y2lzY29zcGFyazovL3VzL1JPT00vMzBjMzNhMjAtNDRiYy0xMWU2LThmN2It1234567890asdfghjkl","type":"direct","isLocked":false,"lastActivity":"2016-07-08T03:29:34.460Z","created":"2016-07-08T03:29:34.402Z"}}

Like the messages, most of that is encrypted, so you’ll need to make an authenticated call back to the API to get the room details; this doc page explains in more detail.

Last we’ll show webhooks for both created and deleted memberships, so you know if someone joined or left a room you’re already in. To start, the webhook for created memberships:

request headers3

We’re setting the resource to ‘memberships’, leaving the event as ‘created’ like the others, and defining a specific roomId for the filter so we know who joins one particular room. After you hit Run, your response should look like this:

request response3

Now once someone joins the room, we’ll get data sent to our targetUrl that looks like this:

{"id":"Y2lzY29zcGFyazovL3VzL1dFQkhPT0svYTNiMTZkMzctNjNlNi00ZDU2L1234567890asdfghjkl","name":"My Membership Webhook","targetUrl":"[http://webhook.info/post/PVDYLYKPNB](http://webhook.info/post/PVDYLYKPNB)","resource":"memberships","event":"created","filter":"roomId=Y2lzY29zcGFyazovL3VzL1JPT00vOTczZmQ3MzAtNDRiZC0xMWU1234567890asdfghjkl","created":"2016-07-08T03:42:00.672Z","data":{"id":"Y2lzY29zcGFyazovL3VzL01FTUJFUlNISVAvMmQxYjhiN2YtZWM0Ny00MTk5LTkzYjUtYjQyMjczM2JiMzZlOjk3M2ZkNzMwLTQ0Y1234567890asdfghjkl","roomId":"Y2lzY29zcGFyazovL3VzL1JPT00vOTczZmQ3MzAtNDRiZC0xMWU2L1234567890asdfghjkl","personId":"Y2lzY29zcGFyazovL3VzL1BFT1BMRS8yZDFiOGI3Zi1lYzQ3LTQ1234567890asdfghjkl","personEmail":"[example@cisco.com](mailto:example@cisco.com)","personDisplayName":"Example Person","isModerator":false,"isMonitor":false,"created":"2016-07-08T03:42:57.054Z"}}

You may not need to make any additional callbacks on this one – the personEmail and personDisplayName are both in plain text and may be all you need, along with the date. If you have a bunch of webhooks pointing to the same place, you may need to get the room details to know which room someone joined, but beyond that most of what you need is available in the clear.

To run a webhook on deleted memberships – some leaving or booted out of the room – it’s mostly the same steps as the last example, just set “deleted” as the event value (and make sure you name it something unique for easier review). When you Run that request, the response on the right should look like this:

request response 4

After someone leaves the room, the JSON sent to the targetUrl will look something like this:

{"id":"Y2lzY29zcGFyazovL3VzL1dFQkhPT0svNWFhNmFmMWQtZDM2Mi001234567890asdfghjkl","name":"Deleted Membership Webhook","targetUrl":"[http://webhook.info/post/PVDYLYKPNB](http://webhook.info/post/PVDYLYKPNB)","resource":"memberships","event":"deleted","filter":"roomId=Y2lzY29zcGFyazovL3VzL1JPT00vZThhOTQ3MzAt1234567890asdfghjkl","created":"2016-07-10T16:48:15.995Z","data":{"id":"Y2lzY29zcGFyazovL3VzL01FTUJFUlNISVAvNmE2MmU5Y2EtOGNkMi00NTZkLTlkOWQtOWYzZDE0OWExYjkxOmU4YTk0NzMwLTQ2Ym1234567890asdfghjkl","roomId":"Y2lzY29zcGFyazovL3VzL1JPT00vZThhOTQ3MzA1234567890asdfghjkl","personId":"Y2lzY29zcGFyazovL3VzL1BFT1BMRS82YTYyZTljYS04Y2Q1234567890asdfghjkl","personEmail":"[example@cisco.com](mailto:example@cisco.com)","personDisplayName":"Example Person","isModerator":false,"isMonitor":false,"created":"2016-07-10T16:49:16.325Z"}}

With those examples to get you started, you should be able to add all kinds of functionality to your integrations and applications using the vastly expanded options. Please give them a run and if you have any questions, please don’t hesitate to shoot us an email via devsupport@ciscospark.com!

https://developer.webex.com/blog/using-webhooks---rooms-messages-memberships-and-more- https://developer.webex.com/blog/using-webhooks---rooms-messages-memberships-and-more- Tue, 19 Jul 2016 00:00:00 GMT
<![CDATA[Spark Bot Demo]]>

This quick walkthrough is intended to give you a very simple Spark bot that responds to commands typed into a room with a few example responses – nothing too fancy, but easy to build on. The commands will be passed to the bot using mentions – so if I type into a room where the bot is a participant:

@MrWayne batsignal

The bot will retrieve that command, process it, and send us back a message. We’ll go step by step from bot registration to code upload and testing.

Step 1: Create the Bot

To register a Bot, you’ll need to be logged in to Spark with a “real” user – each bot needs to be tied to an actual user account. Adding one is extra simple, however – just click here \and select “Create a Bot”; there’s only a couple fields to fill out:

enter image description here

Display Name is how you want the bot to show up in a room (like “Mr. Wayne”); Bot Username is the email address, since every Spark user is registered under an email – this should be similar to the Display Name, but it can be unique. Note that you are not populating the entire email – they will always end with @sparkbot.io, can’t make on with a gmail.com email or anything similar, so you’re just adding the prefix. The username prefix does need to be unique; if you don’t get a green check at the end of the @sparkbot.io reference, then the username was already taken. The Icon is the avatar for the bot, which will also show inside a room.

Once the bot is created, you’ll need to save the access token that is provided – keep it someplace safe. The token effectively never expires (it’s good for 100 years) but if you forget it, you’ll have to generate a new one. There’s no way to get it back.

Note: Because this is a bot, OAuth is not used in this process; no need to refresh tokens any specific period. Only time you’d need to do the regeneration is if you lose the token, as mentioned above.

Step 2: Add the Bot to a Room

Pick a room, any room! Either add the bot to a room you’re already in or have the bot create a new room using its access token – whatever you prefer. The bot just needs to be present in a room in order to read messages and send messages back to it.

Step 3: Create an Outbound Webhook

Your webhook URL needs to be accessible on the public Internet – if you want to use your local machine, you can use a service like Ngrok to make your personal machine accessible to the world on a specific port for free.

But that means the webhook only works when you machine is up and live. Alternatively, Amazon Web Services offers a free EC2 micro instance for 1 year and more professional tiers at varied pricing.

Once you have an endpoint to use, create the webhook using the request on this page.

Make sure that the bearer token used in creating the webhook is the bearer token of the bot. You’ll need to know the ‘roomId’ of the room the bot is hanging out in, and you’ll need to know your own ‘targetUrl’ (the Ngrok link or the AWS link in our examples above); you’ll also want to set the ‘resource’ to messages and the ‘event’ to created. Here’s what the Webhook should look like once it’s been created:

"id": "Y2lz111111112222222233333333",
"name": "BotDemo Project ROOMNAME",
"targetUrl": "http://ec2-10-20-30-40.us-west-2.compute.amazonaws.com:10010",
"resource": "messages",
"event": "created",
"filter": "roomId=Y2lz12345678901234567890"

Check out the section in this link titled “Handling Requests from Spark” for more background info on webhooks.

Step 3b: The Code

The example webhook we just built sends all newly created messages in which the bot is mentioned to the server on port 10010 (all messages not directed to the bot are filtered out); we’ll use a simple Python program to handle them:

from itty import *
import urllib2
import json

def sendSparkGET(url):
    request = urllib2.Request(url,
                            headers={"Accept" : "application/json",
    request.add_header("Authorization", "Bearer "+bearer)
    contents = urllib2.urlopen(request).read()
    return contents

def index(request):
    webhook = json.loads(request.body)
    print webhook\['data'\]\['id'\]
    result = sendSparkGET('https://api.ciscospark.com/v1/messages/{0}'.format(webhook\['data'\]\['id'\]))
    result = json.loads(result)
    print result
    return "true"


run_itty(server='wsgiref', host='', port=10010)

For each message that is sent (‘created’), the data that hits your server is in a JSON format, so parsing them is easy, thanks to the built-in ‘json’ python library. We have a ‘result’ object that has been JSON parsed and should contain a ‘text’ field, unless it’s something like an image someone posts in the Spark room. That means that we can now use the ‘text’ attribute of the result object to start looking for specific commands or messages! We want our bot to reply to a few commands, and everyone loves Batman, so how about these three:




Right after we print the result object, let’s add:

print result
if 'batman' in result.get('text', '').lower():
    print "I'm Batman!"
elif 'batcave' in result.get('text', '').lower():
    print "The Batcave is silent..."
elif 'batsignal' in result.get('text', '').lower():

While it’s bat-tastic that our batbot can now recognize different commands, we want it to actually do something. Let’s have it reply to the Spark room if any of our three commands are found in the text of the Spark message. First, we’ll need a slightly different function (for HTTP POST), to send messages to a room. Add this below the “sendSparkGET” function:

def sendSparkPOST(url, data):
    request = urllib2.Request(url, json.dumps(data),
                            headers={"Accept" : "application/json",
    request.add_header("Authorization", "Bearer "+bearer)
    contents = urllib2.urlopen(request).read()
    return contents

This function is almost identical to "sendSparkGET", except that it also sends data, as POST requests do - now we can reply to the Spark room! Let’s go back to our if-else block and make some changes.

msg = None
if webhook\['data'\]\['personEmail'\] != bot_email:
    if 'batman' in result.get('text', '').lower():
        msg = "I'm Batman!"
    elif 'batcave' in result.get('text', '').lower():
        msg = "The Batcave is silent..."
    elif 'batsignal' in result.get('text', '').lower():
        msg = "NANA NANA NANA NANA"
    if msg != None:
        print msg
        sendSparkPOST("https://api.ciscospark.com/v1/messages", {"roomId": webhook\['data'\]\['roomId'\], "text": msg})

With the above code added, we now have a reply to each of our commands! Even better, the use of our sendSparkPOST function passes the roomId of the room that issued the command, so we don’t have to worry about multiple webhooks from different rooms getting mixed up! To really make this bat worthy, we might want our functions to act a little differently from each other. Let’s have batcave echo the message, if any text is sent after batcave. For example, @MrWayne batcave Hello!, should send “Hello!” back to the room… and maybe we want the batsignal to really light up the Spark room with an image. Here’s the full code to make all the magic happen:

from itty import *
import urllib2
import json

def sendSparkGET(url):
    This method is used for:
        -retrieving message text, when the webhook is triggered with a message
        -Getting the username of the person who posted the message if a command is recognized
    request = urllib2.Request(url,
                            headers={"Accept" : "application/json",
    request.add_header("Authorization", "Bearer "+bearer)
    contents = urllib2.urlopen(request).read()
    return contents

def sendSparkPOST(url, data):
    This method is used for:
        -posting a message to the Spark room to confirm that a command was received and processed
    request = urllib2.Request(url, json.dumps(data),
                            headers={"Accept" : "application/json",
    request.add_header("Authorization", "Bearer "+bearer)
    contents = urllib2.urlopen(request).read()
    return contents

def index(request):
    When messages come in from the webhook, they are processed here.  The message text needs to be retrieved from Spark,
    using the sendSparkGet() function.  The message text is parsed.  If an expected command is found in the message,
    further actions are taken. i.e.
    /batman    - replies to the room with text
    /batcave   - echoes the incoming text to the room
    /batsignal - replies to the room with an image
    webhook = json.loads(request.body)
    print webhook\['data'\]\['id'\]
    result = sendSparkGET('https://api.ciscospark.com/v1/messages/{0}'.format(webhook\['data'\]\['id'\]))
    result = json.loads(result)
    msg = None
    if webhook\['data'\]\['personEmail'\] != bot_email:
        in_message = result.get('text', '').lower()
        in\_message = in\_message.replace(bot_name, '')
        if 'batman' in in\_message or "whoareyou" in in\_message:
            msg = "I'm Batman!"
        elif 'batcave' in in_message:
            message = result.get('text').split('batcave')\[1\].strip(" ")
            if len(message) > 0:
                msg = "The Batcave echoes, '{0}'".format(message)
                msg = "The Batcave is silent..."
        elif 'batsignal' in in_message:
            print "NANA NANA NANA NANA"
            sendSparkPOST("https://api.ciscospark.com/v1/messages", {"roomId": webhook\['data'\]\['roomId'\], "files": bat_signal})
        if msg != None:
            print msg
            sendSparkPOST("https://api.ciscospark.com/v1/messages", {"roomId": webhook\['data'\]\['roomId'\], "text": msg})
    return "true"

bot_email = "yourbot@sparkbot.io"
bot_name = "yourBotDisplayName"
bat\_signal  = "https://upload.wikimedia.org/wikipedia/en/c/c6/Bat-signal\_1989_film.jpg"
run_itty(server='wsgiref', host='', port=10010)

Don’t forget to fill in your Bot’s auth token above. For Mac and Linux systems, Python is installed by default. For Windows, it’s a pretty easy install, just make sure you look for version 2.7. To run the server application, open a command terminal, and navigate to the folder where you saved this Python script - we named ours bot_demo.py - then run:

python bot_demo.py

As long as all of the right ports are available, you should see this in the terminal:

Listening on [](

Use Ctrl-C to quit.

Holy Spark-Bot, Batman! We’re done!

Enjoy the example - you can also get the complete code on Github ! Let us know if you have any questions.

https://developer.webex.com/blog/spark-bot-demo https://developer.webex.com/blog/spark-bot-demo Mon, 18 Jul 2016 00:00:00 GMT