Webhooks Explained

Overview

Use webhooks to notify your apps when specific activities occur in Webex Teams. A webhook is an HTTP callback, or an HTTP POST, to a specified URL that notifies your app when a particular activity or “event” has occurred in one of your resources on the Webex Teams platform. The benefit of using webhooks is that they allow your application to receive real-time data from Webex Teams, so you can keep up with the state of your resources (i.e. rooms, messages, memberships, etc.).

For instance, let’s say you want to be notified when someone posts a message in a room that you’re interested in. You can create a webhook to have Webex Teams notify you whenever new messages are posted into that room. So, instead of your app having to make repeated calls to the API to determine if a new message has been posted into the room, the webhook will automatically notify you of their occurrence.

Webhooks work well for your integrations and bots. For example, let’s say that you are creating a weather bot for Webex Teams where users can ask your bot for the weather forecast in any city. You would want to use webhooks to let your app know when someone has sent a new weather request to your app. Your app can then take action, such as looking up the weather forecast for the requested city, and sending it back to the user.

You can create, or register, a webhook, via the Webex Teams Webhooks API, to subscribe to the events in Webex Teams that you would like to receive notifications for.

Incoming Webhooks

For information about Incoming Webhooks, where you can send information to Webex Teams from outside services, see the Incoming Webhooks Integration by Cisco Systems in the Webex App Hub.

To learn more about webhooks and how to create them, keep reading. For a step-by-step tutorial that shows you how to create a webhook, see Experiment with Webex Teams Webhooks DevNet Learning Lab.

Webex Teams Webhooks

You can use the Webex Teams Webhooks API to create a new webhook, to update an existing webhook or to delete a webhook once it's no longer needed.

When you create a webhook for a particular event, the notification data will be sent as an HTTP POST, in JSON format, to a URL of your choosing, each time it is triggered. Please note, that this URL must be publicly reachable and Internet-accessible by Webex Teams, where your application will be listening for inbound HTTP requests. A response is also required from the web server for delivery. If Webex Teams does not receive a successful HTTP response in the 2xx range from the server, your webhook will be disabled after 100 failed attempts within a five minute period.

In order to create a webhook for a resource, make sure that the auth token has a read scope for that resource. For example, to create a webhook that receives messages, the application must have the spark:messages_read scope enabled. Likewise, to create a webhook for notification of membership changes to a room, the application must have the spark:memberships_read scope. For more information on auth scopes and how to enable them, see Scopes.

Filtering Webhooks

In order to narrow down the data that you receive from webhooks, you can add filters to your webhooks. To do this, you can create a webhook for a resource that applies to an event, and then add a filter or a combination of filters to send you only notification content that is based on the added filter restrictions. For example, you can register a webhook for a membership resource and then add filters so that the webhook only applies to a specific room, by using the roomId or roomType filter.

You can also use more than one filter for a webhook. For instance you can create a webhook and add a combination of filters so the webhook sends notifications only when a specific person (by personId or personEmail) posts a message in a specific room (by roomId or roomType). To add multiple filters for a resource, separate them by using the “&” symbol. For a reference table of available filters you can use, see Resources, Events & Filters below.

Note: You can only use ID filters for resources you have access to. If you do not have access to a particular resource or ID filter, you will receive an error (such as invalid value for filter: roomId) from the Webhooks API.

Alternatively, Webex Teams Webhooks also supports what is commonly known as a “firehose” or “wildcard” webhook, which allows your app to subscribe to all resources and/or events with a single webhook. For more information, see Using the Firehose Webhook.

Resources, Events, & Filters

Below is a table of Webex Teams events which webhooks can monitor for a given resource, the actions that will trigger these events, and the various filters you can add to narrow down the specific event notifications you would like to receive. Use an “&” between each filter to combine them.

Resource Event Trigger Filters (optional)
callMemberships created You have been added to a call personId — limit to a particular person, by ID
status — limit to a particular status (such as notified, joined, declined, left, waiting)
callStatus — limit to a particular call status (such as initializing, connected, terminating, disconnected)
isInitiator — limit to your call memberships
callMemberships updated Your call membership was updated for a call you're a member of personId — limit to a particular person, by ID
status — limit to a particular status (such as notified, joined, declined, left, waiting)
callStatus — limit to a particular call status (such as initializing, connected, terminating, disconnected)
isInitiator — limit to your call memberships
callMemberships deleted You left a call personId — limit to a particular person, by ID
status — limit to a particular status (such as notified, joined, declined, left, waiting)
callStatus — limit to a particular call status (such as initializing, connected, terminating, disconnected)
isInitiator — limit to your call memberships
calls created A new call was started in a room that you're in roomId — limit to a particular room, by ID
personId — limit to calls initiated by a particular person, by ID
status — limit to a particular call status (such as initializing, connected, terminating, disconnected)
calls updated A call state change has occurred roomId — limit to a particular room, by ID
personId — limit to calls initiated by a particular person, by ID
status — limit to a particular call status (such as initializing, connected, terminating, disconnected)
memberships created Someone joined a room that you're in or you've been added to a new room roomId — limit to a particular room, by ID
personId — limit to a particular person, by ID
personEmail — limit to a particular person, by email
isModerator — limit to moderators of a room
memberships updated Someone's membership was updated in a room that you're in; primarily used to detect moderator changes roomId — limit to a particular room, by ID
personId — limit to a particular person, by ID
personEmail — limit to a particular person, by email
isModerator — limit to moderators of a room
memberships deleted Someone left or was kicked out of a room that you're in, or you left or were removed from a room; only triggers for group rooms, not 1-to-1 rooms roomId — limit to a particular room, by ID
personId — limit to a particular person, by ID
personEmail — limit to a particular person, by email
isModerator — limit to moderators of a room
messages created New message posted into a room that you're in roomId — limit to a particular room, by ID
roomType — limit to a particular room type (such as direct or group)
personId — limit to a particular person, by ID
personEmail — limit to a particular person, by email
mentionedPeople — limit to messages which contain these mentioned people, by person ID; accepts me as a shorthand for your own person ID; separate multiple values with commas
hasFiles — limit to messages which contain file content attachments
messages deleted A message was deleted from a room that you're in roomId — limit to a particular room, by room ID
roomType — limit to a particular room type (such as direct or group)
personId — limit to a particular person, by ID
personEmail — limit to a particular person, by email
mentionedPeople — limit to messages which contain these mentioned people, by person ID; accepts me as a shorthand for your own person ID; separate multiple values with commas
hasFiles — limit to messages which contain file content attachments
rooms created A new room was created by you or one of your integrations type — limit to a particular room type (such as direct or group)
isLocked — limit to rooms that are locked
rooms updated A room that you're in was updated; primarily used to detect when a room becomes Locked or Unlocked type — limit to a particular room type (such as direct or group)
isLocked — limit to rooms that are locked

Remember, bots can only see messages in which they're specifically mentioned. See Differences Between Bots & People in the Bots guide for more details.

For more examples of uses for webhooks and filtering, see our blog post Using Webhooks - Rooms, Messages, Memberships and more. For a step-by-step tutorial that shows you how to create a webhook and add filters, see Experiment with Webex Teams Webhooks over in Cisco DevNet.

The Firehose Webhook

The Webhooks API supports what is commonly known as a “firehose” or “wildcard” webhook, which allows your app to subscribe to all events with a single webhook. There are two types of firehoses. One is a single resource firehose and the other is an all resource fire hose.

Single Resource Firehose

A single resource firehose webhook will send a notification for any event using all activities as a trigger for a given resource type. For example, to subscribe to all events for the messages resource, your app can create a webhook as shown below:

{
  "name": "Messages Firehose",
  "targetUrl": "https://example.com/message-events",
  "resource": "messages",
  "event": "all"
}

All Resource Firehose

An all resource firehose webhook will send a notification for any event for all supported resource types. For example, to subscribe to all events that occur on all supported resources, create a webhook with the resource set to all and the event set to all as shown below:

{
  "name": "Awesome Bot Webhook Firehose",
  "targetUrl": "https://example.com/spark-events",
  "resource": "all",
  "event": "all"
}

Note: Creating a webhook for all resources requires that you have read scopes for all resources.

Creating a Webhook

To begin receiving platform events, you first need to register a webhook with Webex Teams. To create a webhook, make an HTTP POST to /webhooks with some basic information as shown in the example below:

{
  "name": "New message in 'Project Unicorn' room",
  "targetUrl": "https://example.com/spark-hook",
  "resource": "messages",
  "event": "created",
  "filter": "roomId=Y2lzY29zcGFyazovL3VzL1JPT00vYmJjZWIxYWQtNDNmMS0zYjU4LTkxNDctZjE0YmIwYzRkMTU0"
}

Request Parameters

Parameter Explanation
name A label to remember why it was created. Use it for whatever purpose you'd like.
targetUrl Tell Webex Teams where you'd like to receive platform events. See the following Handling Requests from Webex Teams section for detailed information about the webhook request format and best practices for scaling your infrastructure.
resource Indicates the noun being observed and will generally match the plural form of one of the Webex Teams APIs (i.e. messages).
event Further narrows the events by specifying the action that would trigger a notification to your backend.
filter A set of filtering critera. Generally speaking, webhook filters will be a subset of the query parameters available when GETing a list of the target resource. It is an optional property. To add multiple filters, separate them with the “&” symbol. For more information about filters, see Filtering Webhooks.
secret An optional field used to generate a payload signature. See Handing Sensitive Data for more information.

A valid OAuth token is only required to create a webhook. As long as the webhook receives a successful HTTP response it will run indefinitely, even if the OAuth token has expired. However, since initial webhook notifications only contain metadata and encrypted information, sensitive data will always remain secure. See Handling Sensitive Data for more information.

Handling Requests from Webex Teams

When one of your webhooks is triggered by an event, Webex Teams will send an HTTP POST to the backend targetUrl that you've specified. The body of the POST will look something like this:

{
  "id": "Y2lzY29zcGFyazovL3VzL1dFQkhPT0svZjRlNjA1NjAtNjYwMi00ZmIwLWEyNWEtOTQ5ODgxNjA5NDk3",
  "name": "New message in 'Project Unicorn' room",
  "resource": "messages",
  "event": "created",
  "filter": "roomId=Y2lzY29zcGFyazovL3VzL1JPT00vYmJjZWIxYWQtNDNmMS0zYjU4LTkxNDctZjE0YmIwYzRkMTU0",
  "orgId": "OTZhYmMyYWEtM2RjYy0xMWU1LWExNTItZmUzNDgxOWNkYzlh",
  "createdBy": "Y2lzY29zcGFyazovL3VzL1BFT1BMRS9mNWIzNjE4Ny1jOGRkLTQ3MjctOGIyZi1mOWM0NDdmMjkwNDY",
  "appId": "Y2lzY29zcGFyazovL3VzL0FQUExJQ0FUSU9OL0MyNzljYjMwYzAyOTE4MGJiNGJkYWViYjA2MWI3OTY1Y2RhMzliNjAyOTdjODUwM2YyNjZhYmY2NmM5OTllYzFm",
  "ownedBy": "creator",
  "status": "active",
  "actorId": "Y2lzY29zcGFyazovL3VzL1BFT1BMRS9mNWIzNjE4Ny1jOGRkLTQ3MjctOGIyZi1mOWM0NDdmMjkwNDY",
  "data":{
    "id": "Y2lzY29zcGFyazovL3VzL01FU1NBR0UvOTJkYjNiZTAtNDNiZC0xMWU2LThhZTktZGQ1YjNkZmM1NjVk",
    "roomId": "Y2lzY29zcGFyazovL3VzL1JPT00vYmJjZWIxYWQtNDNmMS0zYjU4LTkxNDctZjE0YmIwYzRkMTU0",
    "personId": "Y2lzY29zcGFyazovL3VzL1BFT1BMRS9mNWIzNjE4Ny1jOGRkLTQ3MjctOGIyZi1mOWM0NDdmMjkwNDY",
    "personEmail": "matt@example.com",
    "created": "2015-10-18T14:26:16.000Z"
  }
}

The first few properties shown above are called the “envelope.” They identify all webhooks that are sent. This envelope contains the following information:

Parameter Explanation
id The webhook ID. This is the same ID returned when you created the webhook and is what you would use to view the webhook configuration or delete the webhook.
name The name you gave your webhook when you created it.
resource The resource the webhook data is about.
event The type of event this webhook is for.
filter Lists any filters that you applied that triggered this webhook.
orgId The organization that owns the webhook. This usually is the organization the user that added the webhook belongs to. This ID can be used to view the Organization details with the API.
createdBy The personId of the user that added the webhook.
appId The ID of the Webex Teams app that was used to create the webhook. This could be one of your apps, an app from the Webex App Hub, a privately developed app, or this Webex for Developers site if the webhook was created with your personal access token.
ownedBy Indicates if the webhook is owned by the org or the creator. Webhooks owned by the creator can only receive events that are accessible to the creator of the webhook. Those owned by the organization will receive events that are visible to anyone in the organization.
status Indicates if the webhook is active. A webhook that cannot reach your URL is disabled. Thus, for all webhooks you receive, the status will always read ‘active.’
actorId The personId of the user that caused the webhook to be sent. For example, on a messsage created webhook, the author of the message will be the actor. On a membership deleted webhook, the actor is the person who removed a user from a room.
data Contains the JSON representation of the resource that triggered the webhook. Note: the data property's id is not the same ID as the webhook ID. For more information about the data property, see Using the Data Property below.

Using the Data Property

The webhook's data property contains the JSON representation of the resource event that triggered the webhook. For example, if you created a webhook that triggers when messages are created (i.e. posted into a room), then the data property will contain the JSON representation for a message resource, as specified in the Messages API documentation.

If the webhook's resource event contains sensitive data, the data property will only contain “metadata” about the event. See Handling Sensitive Data below for more information about how to retrieve the entire resource.

Handling Sensitive Data

Webex Teams encrypts sensitive room content such as titles and message text using keys only available to the members of that room. This means that not even the Webex Teams operations team can read your messages, making it one of the most secure communications platforms on the planet. This level of security has a subtle impact on webhooks.

You'll notice in the above message webhook example that the text property is missing. That's because room messages are considered sensitive information and since Webex Teams initiated the request to your backend, it did not have your Access Token with which to decrypt the message. In order to get the sensitive information, your app needs to use the resource id to fetch the full resource. Using the above messages example, your app could fetch the complete message object along with the text by doing an authenticated (via your Bearer Token) GET request to /messages/{id} as shown below:

GET https://api.ciscospark.com/v1/messages/Y2lzY29zcGFyazovL3VzL01FU1NBR0UvMzIzZWUyZjAtOWFhZC0xMWU1LTg1YmYtMWRhZjhkNDJlZjlj

{
  "id": "Y2lzY29zcGFyazovL3VzL01FU1NBR0UvMzIzZWUyZjAtOWFhZC0xMWU1LTg1YmYtMWRhZjhkNDJlZjlj",
  "roomId": "Y2lzY29zcGFyazovL3VzL1JPT00vYmJjZWIxYWQtNDNmMS0zYjU4LTkxNDctZjE0YmIwYzRkMTU0",
  "personId": "Y2lzY29zcGFyazovL3VzL1BFT1BMRS9mNWIzNjE4Ny1jOGRkLTQ3MjctOGIyZi1mOWM0NDdmMjkwNDY",
  "personEmail": "matt@example.com",
  "text": "Something interesting and potentially sensitive",
  "created": "2015-12-04T17:33:56.767Z"
}

Authenticating Requests

Webhooks require that the Webex Teams Cloud be able to reach your backend over HTTP. One common question from enterprise IT is how to authenticate that a request is coming from Cisco. We are continuously adding infrastructure to the Webex Teams Cloud so only listing IPs that are allowed is not practical. To solve this, we introduced a technique for cryptographically verifying the JSON payload based on a shared secret of your choosing.

When creating a webhook you can now supply a secret parameter. If specified, every message sent to your backend will contain a new HTTP header called X-Spark-Signature containing an HMAC-SHA1 signature of the JSON payload.

The secret parameter can be specified when creating a webhook.

Disabled Webhooks

A webhook's targetUrl specifies the server endpoint that will receive the webhook payload. If Webex Teams attempts to deliver 100 webhook notifications within five minutes and the server either becomes unreachable or does not respond with a successful HTTP code in the 2xx range, the webhook will be disabled. Once a webhook is disabled, it will not be reenabled automatically.

To see the current status of a webhook, use the Get Webhook Details API endpoint. To reactivate a disabled webhook, use the Update a Webhook API endpoint with the status parameter set to ‘active’.