microsoft-teamspower-automate

Converting Teams Webhook with payload type MessageCard to be used in Power Automate "Post to channel when a webhook request is received" workflow


Microsoft decided to deprecate Office 365 connectors. They announced the change on Jul. 3rd, 2024 and all existing connectors will stop working on Oct. 1st, 2024, a quick 3 month turnaround: https://devblogs.microsoft.com/microsoft365dev/retirement-of-office-365-connectors-within-microsoft-teams/

We use a Teams Webhook connector to send ticketing info into a Teams channel so our support team gets notifications of a new ticket. The payload from the ticketing system looks like this:

{  
   "@context": "https://schema.org/extensions",  
   "@type": "MessageCard",  
   "themeColor": "0072C6",  
   "title": "Title text....",  
   "text": "Body test...",  
   "potentialAction": []
}

We followed the process placed in Teams to convert our Webhook to a Power Automate workflow, and we receive the following error:

Action 'Send_each_adaptive_card' failed: The execution of template action 'Send_each_adaptive_card' failed: the result of the evaluation of 'foreach' expression '@triggerOutputs()?['body']?['attachments']' is of type 'Null'. The result must be a valid array.

This is because it expects the following format:

{
    "type": "message",
    "attachments": [
        {
            "contentType": "application/vnd.microsoft.card.adaptive",
            "content": {
                "$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
                "type": "AdaptiveCard",
                "version": "1.0",
                "body": [
                    {
                        "type": "TextBlock",
                        "text": ""
                    }
                ]
            }
        }
    ]
}

This is an image of the workflow:

https://i.sstatic.net/6H1co2UB.png

When reviewing the workflow, it expects the following schema:

{
    "schema": {
        "type": "object",
        "properties": {
            "type": {
                "type": "string"
            },
            "attachments": {
                "type": "array",
                "items": {
                    "type": "object",
                    "properties": {
                        "contentType": {
                            "type": "string"
                        },
                        "content": {
                            "type": "object",
                            "properties": {
                                "$schema": {
                                    "type": "string"
                                },
                                "type": {
                                    "type": "string"
                                },
                                "version": {
                                    "type": "string"
                                },
                                "body": {
                                    "type": "array",
                                    "items": {
                                        "type": "object",
                                        "properties": {
                                            "type": {
                                                "type": "string"
                                            }
                                        },
                                        "required": [
                                            "type"
                                        ]
                                    }
                                }
                            }
                        }
                    },
                    "required": [
                        "contentType",
                        "content"
                    ]
                }
            }
        }
    }
}

And then the "Send each adaptive card" node parses the object in the following way:

{
  "type": "Foreach",
  "foreach": "@triggerOutputs()?['body']?['attachments']",
  "actions": {
    "Post_your_own_adaptive_card_as_the_Flow_bot_to_a_channel": {
      "type": "OpenApiConnection",
      "inputs": {
        "parameters": {
          "poster": "Flow bot",
          "location": "Channel",
          "body/recipient/groupId": "bf7cf33f-40a6-4621-a8db-c942c38dbe75",
          "body/recipient/channelId": "19:ceb7fa98527f44d18372571c9a3e42dc@thread.tacv2",
          "body/messageBody": "@item()?['content']"
        },
        "host": {
          "apiId": "/providers/Microsoft.PowerApps/apis/shared_teams",
          "connection": "shared_teams",
          "operationId": "PostCardToConversation"
        }
      }
    }
  },
  "runAfter": {}
}

So it is looking for the attachments array and iterating through.

I tried several changes to alter the "foreach" code and parse the MessageCard object, but none were successful. Is there a way to alter the schema or to change the foreach code to properly parse the MessageCard object?

The alternative is for us to take the MessageCard object that we are receiving from the API and convert it to the appropriate format as an object with an array of attachments. We would like to avoid doing this if possible, but it may be the best approach.

Update:

For those that are curious how to transform their payload from MessageCard to AdaptiveCard (which is what our team ended up doing to avoid trying to figure this out in the PowerAutomate workflow), our new payload looks like this now:

    {
        "type": "message",
        "attachments": [
            {
                "contentType": "application/vnd.microsoft.card.adaptive",
                "content": {
                    "$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
                    "type": "AdaptiveCard",
                    "version": "1.0",
                    "msteams": {
                        "width": "Full"
                    },
                    "body": [
                        {
                            "type": "TextBlock",
                            "text": {Title},
                            "weight": "bolder",
                            "size": "medium",
                            "wrap": "true"
                        },
                        {
                            "type": "TextBlock",
                            "text": {Body},
                            "wrap": "true"
                        }
                    ]
                }
            }
        ]
    }

Solution

  • I also posted this in the Microsoft support channel, and I received an answer there: https://answers.microsoft.com/en-us/msoffice/forum/all/converting-teams-webhooks-to-power-automate/23704b44-aa49-4b5d-84a3-2c760d195f3e

    The answer: " What you can do is add a compose step immediately after the webhook received trigger, and perform the transformation into what you want there, e.g.

    https://i.sstatic.net/ywukRj0w.png

    I got that working from the guidance here - https://github.com/prometheus/alertmanager/issues/3920#issuecomment-2219950227 "

    I did not confirm this works, as I have already adapted my payload instead of editing the Workflow, but it seems to be a sound approach.