Send Message Cards with Microsoft Teams

Microsoft Teams has a feature that I don’t see used or talked about a whole lot - Cards.

Cards allow you to post a container to a Teams channel. The type of card I will use here is a Message Card. These can contain text, images, links etc.

Message Cards are not to be confused with Adaptive Cards. These are entirely different and are not exclusive to Teams. Adaptive cards are more flexible and interactive than Message Cards but unfortunately, do not support the method I employ here - Incoming Webhook.

Create Incoming Webhook in a Team Channel

The first action you need to undertake is creating an Incoming Webhook within Teams. An Incoming Webhook is a way to deliver data into a service using HTTP calls.

To create an Incoming Webhook:

Find the Team you want to use for the Message Cards and click Manage team:

Next, go to Apps and click Go to store:

In the Store, search for Incoming Webhook and click on it. The Team should already be selected. Click Install:

Select the Channel to receive the Webhooks and click Set up:

You will be taken to a list of connectors, click Configure next to Incoming Webhook.

Give the Webhook a name and upload an icon (if desired) and click Create:

The next step is important - copy the Webhook URL and keep it safe - this will be needed later and this is the only time it is shown. Once copied, click Done.

You have now setup an Incoming Webhook in Teams

Create a Message Card

A Card is structured using JSON. I won’t go over all permutations of a Card (as they differ between Card types) - the Mircosoft Docs do a pretty good job explaining it, though - https://docs.microsoft.com/en-us/microsoftteams/platform/concepts/cards/cards-reference

If you wish to test your JSON for a Message Card before using in Teams, I recommend using the Message Card Playground website - https://messagecardplayground.azurewebsites.net/ - it allows you to visualise the layout and view sample code.

For this article, I’m going to post tweets containing the hashtag #MicrosoftTeams as a Message Card. Here is the JSON without any values assigned:

{
    "@context": "https://schema.org/extensions",
    "@type": "MessageCard",
    "potentialAction": [
        {
            "@type": "OpenUri",
            "name": "View All Tweets",
            "targets": [
                {
                    "os": "default",
                    "uri": "https://twitter.com/search?q=%23MicrosoftTeams"
                }
            ]
        }
    ],
    "sections": [
        {
            "facts": [
                {
                    "name": "Posted By:",
                    "value": ""
                },
                {
                    "name": "Posted At:",
                    "value": ""
                },
                {
                    "name": "Tweet:",
                    "value": ""
                }
            ],
            "text": "A tweet with #MicrosoftTeams has been posted:"
        }
    ],
    "summary": "Tweet Posted",
    "themeColor": "0072C6",
    "title": "Tweet Posted"
}

How the Message Card looks in Message Card Playground

Send Message Card in to Teams

Now there is an Incoming Webhook defined and the Team channel and there is a Message Card JSON to use, the next step is to send the JSON via an Incoming Webhook. I’ll first demonstrate how this can be done via a manual HTTP POST and afterwards how this could be automated.

Send Message Card using HTTP POST

An Incoming Webhook is expecting the body (Message Card in this case) in JSON format using a HTTP POST method. As the URL of the Incoming Webhook is intended to be kept secret, there is no authentication required. I am going to demonstrate how to send to an Incoming Webhook using PowerShell, but ultimately any language that support HTTP POST should work.

$body = @"
{
    "@context": "https://schema.org/extensions",
    "@type": "MessageCard",
    "potentialAction": [
        {
            "@type": "OpenUri",
            "name": "View All Tweets",
            "targets": [
                {
                    "os": "default",
                    "uri": "https://twitter.com/search?q=%23MicrosoftTeams"
                }
            ]
        }
    ],
    "sections": [
        {
            "facts": [
                {
                    "name": "Posted By:",
                    "value": ""
                },
                {
                    "name": "Posted At:",
                    "value": ""
                },
                {
                    "name": "Tweet:",
                    "value": ""
                }
            ],
            "text": "A tweet with #MicrosoftTeams has been posted:"
        }
    ],
    "summary": "Tweet Posted",
    "themeColor": "0072C6",
    "title": "Tweet Posted"
}
"@

$uri = <IncomingWebhookURL>

Invoke-RestMethod -uri $uri -Method Post -body $body -ContentType 'application/json'

Essentially the script is running a HTTP POST method to the Incoming Webhook URL, setting the HTTP ContentType (body) as JSON and attaching the JSON as the body. Here is the output in Teams:

Automating the Process

The script has proved that everything is now in place, but ideally you want this to be automated with dynamic data inside. Enter Microsoft Flow (or Azure Logic Apps if you prefer).

I’ve set up a Flow to look for new #MicrosoftTeams posts on Twitter and post an HTTP POST request when one is found. This will contain the user, time posted and the tweet itself. Additionally, there is a link to view all tweets with #MicrosoftTeams in.

When creating the body, I’ve populated the values with values from the tweet itself. Special care has to be taken to ensure any @ values contain two @ symbols otherwise the flow will not save.

Once saved, it should start flowing in to Teams…

And there you are, Message Cards posted in to Teams.