Create and send messages

Important

Microsoft 365 Connectors (previously called Office 365 Connectors) are nearing deprecation, and the creation of new Microsoft 365 Connectors will soon be blocked. For more information on the schedule and how the Workflows app provides a more flexible and secure experience, see retirement of Microsoft 365 connectors within Microsoft Teams.

How can you create a webhook in Teams?

If you've already built Office 365 Connectors:

  • Create a Power Automate connector: Power Automate enhances the widely used Workflows apps in Teams. It's the scalable and secure approach to transmit data programmatically into and out of Teams. If you adopt this method, you can create workflow templates for posting alerts from your product to Teams channels. This approach simplifies user adoption of the new method. For more information, see Power Automate for enterprise developers, ISVs, and partners.

  • Update your Teams app: You can enhance your current Teams app. For example, you can enable users to set up proactive messages based on trigger events within your system. For more information, see how bots can post to channels through proactive messages.

Known issues

  • Workflows app can't post in private channels as a flow bot. However, it can post on behalf of a user.
  • Workflows support Adaptive Cards only. It doesn't support the older message card format that Office 365 Connectors use. The support for the use of message card format within Workflows becomes available from mid-October. For more information, see how to convert connector message card format to Adaptive Card.
  • Workflows don't offer third-party connectors such as DataDog and Jenkins.
  • Workflows can only be created in your default environment.

Limitations

Workflows are linked only to specific users (referred to as owners of the workflow) and not to a Teams team or channel. Workflows can become orphan flows in the absence of an owner if no co-owners assigned. To maintain continuity in the business process automated by the flow, admins can add one or more co-owners and grant them full control over the workflow. They can also add authentication for connections, if any, and enable the flow if it has been disabled. For more information, see manage orphan flows.

To create and send actionable messages, use either an Incoming Webhook or a Microsoft 365 connector. However, the actionable messages are accessible only to users with an Exchange Online license.

Create actionable messages

The actionable messages include six visible buttons on the card. Each button is defined in the potentialAction property of the message by using ActionCard actions, each with an input type, a text field, a date picker, or a multiple-choice list. Each ActionCard has an associated action, for example HttpPOST.

The connector cards support the following actions:

  • ActionCard: Presents one or more input types and associated actions.
  • HttpPOST: Sends POST request to a URL.
  • OpenUri: Opens URI in a separate browser or app. Optionally, targets different URIs based on operating systems.

The ActionCard action supports three input types:

  • TextInput: A single line or multiline text field with an optional length limit.
  • DateInput: A date selector with an optional time selector.
  • MultichoiceInput: An 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 as follows:

isMultiSelect default style
false or not specified compact
true expanded

To display the multiple-selection list in the compact style, specify "isMultiSelect": true and "style": true.

For more information on connector card actions, see Actions.

Note

  • Specifying compact for the style property in Microsoft Teams is the same as specifying normal for the style property in Microsoft Outlook.
  • For the HttpPOST action, the bearer token is included with the requests. This token includes the Microsoft Entra identity of the Microsoft 365 user who took the action.

Send a message through Incoming Webhook or connector for Microsoft 365 Groups

To send a message through your Incoming Webhook or connector for Microsoft 365 Groups, post a JSON payload to the webhook URL. This payload must be in the form of a connector card for Microsoft 365 Groups.

You can also use this JSON to create cards containing rich inputs, such as text entry, multiselect, or selecting date and time. The code that generates the card and posts it to the webhook URL can run on any hosted service. These cards are defined as part of actionable messages and are also supported in cards used in Teams bots and message extensions.

Example of connector message

An example of connector message is as follows:

{
    "@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://adaptivecards.io/content/cats/3.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": "https://zcusa.951200.xyz/outlook/actionable-messages"
        }]
    }, {
        "@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": "https://zcusa.951200.xyz/outlook/actionable-messages"
        }]
    }, {
        "@type": "OpenUri",
        "name": "Learn More",
        "targets": [{
            "os": "default",
            "uri": "https://zcusa.951200.xyz/outlook/actionable-messages"
        }]
    }, {
        "@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": "https://zcusa.951200.xyz/outlook/actionable-messages"
        }]
    }]
}

The following image is an example of the connector message card in a channel:

Screenshot shows an example of a connector card in a channel.

Send messages using cURL and PowerShell

To post a message in the webhook with cURL, follow these steps:

  1. Install cURL from cURL website.

  2. From the command line, enter the following cURL command:

    // on macOS or Linux
    curl -H 'Content-Type: application/json' -d '{"text": "Hello World"}' <YOUR WEBHOOK URL>
    
    // on Windows
    curl.exe -H "Content-Type:application/json" -d "{'text':'Hello World'}" <YOUR WEBHOOK URL>
    

    Note

    If the POST succeeds, you must see a simple 1 output by curl.

  3. Check the Teams client for the new card posted.

Send Adaptive Cards using an Incoming Webhook

Note

To send Adaptive Cards with text or a Base64 encoded image through an Incoming Webhook, follow these steps:

  1. Set up a custom webhook in Teams.
  2. Create Adaptive Card JSON file using the following code:
    {
       "type":"message",
       "attachments":[
          {
             "contentType":"application/vnd.microsoft.card.adaptive",
             "contentUrl":null,
             "content":{
                "$schema":"http://adaptivecards.io/schemas/adaptive-card.json",
                "type":"AdaptiveCard",
                "version":"1.2",
                "body":[
                    {
                    "type": "TextBlock",
                    "text": "For Samples and Templates, see [https://adaptivecards.io/samples](https://adaptivecards.io/samples)"
                    }
                ]
             }
          }
       ]
    }

The properties for Adaptive Card JSON file are as follows:

  • The "type" field must be "message".
  • The "attachments" array contains a set of card objects.
  • The "contentType" field must be set to Adaptive Card type.
  • The "content" object is the card formatted in JSON.
  1. Test your Adaptive Card with Postman:

    1. Test the Adaptive Card using Postman to send a POST request to the URL, created to set up Incoming Webhook.
    2. Paste the JSON file in the body of the request and view the Adaptive Card message in Teams.

Tip

Use Adaptive Card code samples and templates to test the body of POST request.

Rate limiting for connectors

Application rate limits control the traffic that a connector or an Incoming Webhook is permitted to generate on a channel. Teams tracks requests using a fixed rate window and incremental counter measured in seconds. If more than four requests are made in a second, the client connection is throttled until the window refreshes for the duration of the fixed rate.

Transactions per second thresholds

The following table provides the time based transaction details:

Time in seconds Maximum allowed requests
1 4
30 60
3600 100
7200 150
86400 1800

Note

A retry logic with exponential back-off can mitigate rate limiting for cases where requests are exceeding the limits within a second. Refer HTTP 429 responses 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 users.

See also