Sending messages to Connectors and Webhooks
To send a message through your Office 365 Connector or incoming webhook, you post a JSON payload to the webhook URL. Typically this payload will be in the form of an Office 365 Connector Card.
You can also use this JSON to create cards containing rich inputs, such as text entry, multi-select, or picking a date and time. The code that generates the card and posts to the webhook URL can be running on any hosted service. These cards are defined as part of actionable messages, and are also supported in cards used in Teams bots and Messaging extensions.
Example Connector message
{
"@type": "MessageCard",
"@context": "http://schema.org/extensions",
"themeColor": "0076D7",
"summary": "Larry Bryant created a new task",
"sections": [{
"activityTitle": "Larry Bryant created a new task",
"activitySubtitle": "On Project Tango",
"activityImage": "https://teamsnodesample.azurewebsites.net/static/img/image5.png",
"facts": [{
"name": "Assigned to",
"value": "Unassigned"
}, {
"name": "Due date",
"value": "Mon May 01 2017 17:07:18 GMT-0700 (Pacific Daylight Time)"
}, {
"name": "Status",
"value": "Not started"
}],
"markdown": true
}],
"potentialAction": [{
"@type": "ActionCard",
"name": "Add a comment",
"inputs": [{
"@type": "TextInput",
"id": "comment",
"isMultiline": false,
"title": "Add a comment here for this task"
}],
"actions": [{
"@type": "HttpPOST",
"name": "Add comment",
"target": "http://..."
}]
}, {
"@type": "ActionCard",
"name": "Set due date",
"inputs": [{
"@type": "DateInput",
"id": "dueDate",
"title": "Enter a due date for this task"
}],
"actions": [{
"@type": "HttpPOST",
"name": "Save",
"target": "http://..."
}]
}, {
"@type": "ActionCard",
"name": "Change status",
"inputs": [{
"@type": "MultichoiceInput",
"id": "list",
"title": "Select a status",
"isMultiSelect": "false",
"choices": [{
"display": "In Progress",
"value": "1"
}, {
"display": "Active",
"value": "2"
}, {
"display": "Closed",
"value": "3"
}]
}],
"actions": [{
"@type": "HttpPOST",
"name": "Save",
"target": "http://..."
}]
}]
}
This message produces the following card in the channel.
Creating actionable messages
The example in the preceding section includes three visible buttons on the card. Each button is defined in the potentialAction
property of the message by using ActionCard
actions, each containing an input type: a text field, a date picker, or a multi-choice list. Each ActionCard
action has an associated action, for example HttpPOST
.
Connector cards support three types of actions:
ActionCard
Presents one or more input types and associated actionsHttpPOST
Sends a POST request to a URLOpenUri
Opens a URI in a separate browser or app; optionally targets different URIs based on operating systems
(A fourth action, ViewAction
, is still supported but no longer needed; use OpenUri
instead.)
The ActionCard
action supports three input types:
TextInput
A single-line or multiline text field with an optional length limitDateInput
A date selector with an optional time selectorMultichoiceInput
A enumerated list of choices offering either a single selection or multiple selections
MultichoiceInput
supports a style
property that controls whether the list initially appears fully expanded. The default value of style
depends on the value of isMultiSelect
.
isMultiSelect |
style default |
---|---|
false or not specified |
compact |
true |
expanded |
If you want a multiselect list initially displayed in the compact style, you must specify both "isMultiSelect": true
and "style": true
.
Note
Specifying compact
for the style
property in Microsoft Teams is the same as specifying normal
for the style
property in Microsoft Outlook.
For all other details about Connector card actions, see Actions in the actionable message card reference.
Setting up a custom incoming webhook
Follow these steps to see how to send a simple card to a Connector.
- In Microsoft Teams, choose More options (⋯) next to the channel name and then choose Connectors.
- Scroll through the list of Connectors to Incoming Webhook, and choose Add.
- Enter a name for the webhook, upload an image to associate with data from the webhook, and choose Create.
- Copy the webhook to the clipboard and save it. You'll need the webhook URL for sending information to Microsoft Teams.
- Choose Done.
Post a message to the webhook using cURL
The following steps use cURL. We assume that you have this installed and are familiar with its basic usage.
From the command line, enter the following cURL command:
curl -H "Content-Type: application/json" -d "{\"text\": \"Hello World\"}" <YOUR WEBHOOK URL>
If the POST succeeds, you should see a simple 1 output by
curl
.Check the Microsoft Team client. You should see the new card posted to the team.
Post a message to the webhook using PowerShell
The following steps use PowerShell. We assume that you have this installed and are familiar with its basic usage.
From the PowerShell prompt, enter the following command:
Invoke-RestMethod -Method post -ContentType 'Application/Json' -Body '{"text":"Hello World!"}' -Uri <YOUR WEBHOOK URL>
If the POST succeeds, you should see a simple 1 output by
Invoke-RestMethod
.Check the Microsoft Teams channel associated with the webhook URL. You should see the new card posted to the channel.
- Include two icons, following the instructions in Icons.
- Modify the
icons
portion of the manifest to refer to the file names of the icons instead of URLs.
The following manifest.json file contains the basic elements needed to test and submit your app.
Note
Replace id
and connectorId
in the following example with the GUID of your Connector.
Example manifest.json with Connector
{
"$schema": "https://developer.microsoft.com/en-us/json-schemas/teams/v1.5/MicrosoftTeams.schema.json",
"manifestVersion": "1.5",
"id": "e9343a03-0a5e-4c1f-95a8-263a565505a5",
"version": "1.0",
"packageName": "com.sampleapp",
"developer": {
"name": "Publisher",
"websiteUrl": "https://www.microsoft.com",
"privacyUrl": "https://www.microsoft.com",
"termsOfUseUrl": "https://www.microsoft.com"
},
"description": {
"full": "This is a small sample app we made for you! This app has samples of all capabilities Microsoft Teams supports.",
"short": "This is a small sample app we made for you!"
},
"icons": {
"outline": "sampleapp-outline.png",
"color": "sampleapp-color.png"
},
"connectors": [
{
"connectorId": "e9343a03-0a5e-4c1f-95a8-263a565505a5",
"scopes": [
"team"
]
}
],
"name": {
"short": "Sample App",
"full": "Sample App"
},
"accentColor": "#FFFFFF",
"needsIdentity": "true"
}
Testing your Connector
To test your Connector, upload it to a team as you would with any other app. You can create a .zip package using the manifest file from the Connectors Developer Dashboard (modified as directed in the preceding section) and the two icon files.
After you upload the app, open the Connectors list from any channel. Scroll to the bottom to see your app in the Uploaded section.
You can now launch the configuration experience. Be aware that this flow occurs entirely within Microsoft Teams through a pop-up window. Currently, this behavior differs from the configuration experience in Connectors that we created; we are working on unifying the experiences.
To verify that an HttpPOST
action is working correctly, use your custom incoming webhook.
Rate limiting for Connectors
This limit controls the traffic that a connector or an incoming webhook is allowed to generate on a channel.
Time-period (sec) | Max allowed message requests |
---|---|
1 | 4 |
30 | 60 |
3600 | 100 |
7200 | 150 |
A retry logic with exponential back-off like below would mitigate rate limiting for cases where requests are exceeding the limits within a second. Please follow best practices to avoid hitting the rate limits.
// Please note that response body needs to be extracted and read
// as Connectors do not throw 429s
try
{
// Perform Connector POST operation
var httpResponseMessage = await _client.PostAsync(IncomingWebhookUrl, new StringContent(content));
// Read response content
var responseContent = await httpResponseMessage.Content.ReadAsStringAsync();
if (responseContent.Contains("Microsoft Teams endpoint returned HTTP error 429"))
{
// initiate retry logic
}
}
These limits are in place to reduce spamming a channel by a connector and ensures an optimal experience to your end users.
Feedback
Loading feedback...