“Can I build Adaptive cards for existing Approval tasks to send reminders to approvers? Including the approval buttons?”
Approval task reminders are a topic I already published a few articles about – how to build a basic reminder, send them via email, or trigger a Teams follow up. This time it’ll be another approach, more specifically Adaptive cards.
How do you build an adaptive card for an existing approval task? A card with the clickable buttons that’ll complete the task upon a click?
Don’t store the adaptive cards
The easiest way could be to store the adaptive card after you create the task. But this approach is not ideal – it must be implemented in each of the flows, you’ll have to store the adaptive card somewhere, and it’s valid only for the original approver. If you reassign the task to somebody else, the adaptive card turns useless.

Nevertheless, you can take the adaptive card to see what it looks like.
Build the adaptive cards instead
That’s why I believe it’s better to build the card when needed. You can search for all tasks directly in Dataverse and if there’re any opened for too long, you can prepare the adaptive card.
What do you need to build it? Again, a combination of rows from the Approval and Approval Request table.
From the Approval table the general information about the task like the Title, Item link, or the requestor.

From the Approval Request table the specific request details – owner of the task, response options, etc.

Additionally, as each of the buttons represents one of the available responses, you’ll need a variable to keep track of their number.

Prepare the buttons
The JSON structure is as below, everything between ## are placeholders to replace:
{
"type": "Action.ShowCard",
"card": {
"type": "AdaptiveCard",
"version": "1.0",
"body": [
{
"type": "TextBlock",
"text": "Comments",
"wrap": true
},
{
"type": "Input.Text",
"id": "comments##NUMBER##",
"placeholder": "Enter comments",
"isMultiline": true,
"maxLength": 2048
}
],
"actions": [
{
"type": "Action.Submit",
"data": {
"Environment": "##ENVIRONMENTID##",
"ApprovalTitle": "##TASKTITLE##",
"ApprovalLink": "https://make.powerautomate.com/environments/##ENVIRONMENTID##/approvals/received/##APPROVALID##",
"ApprovalName": "##APPROVALID##",
"OnBehalfOfNotice": "Requested for ##APPROVALOWNERNAME## <##APPROVALOWNEREMAIL##>",
"CreatorName": "##TASKOWNERNAME##",
"CreatorEmail": "##TASKOWNEREMAIL##",
"CreationTime": "\"##CREATIONDATE##\"",
"MessageTitle": "##TASKTITLE##",
"Details": "##APPROVALDETAILS##",
"Options": [##RESPONSEOPTIONS##],
"SelectedOption": "##CURRENTITEM##",
"ActionType": 1
},
"title": "Submit"
}
]
},
"title": "##CURRENTITEM##"
}
Since you need an array where each button is a separate object, add an ‘Apply to each’ and loop through all the response options. To turn the string with options into an array use the JSON(…) expression.
Input:
json(outputs('Get_a_row_by_ID_-_approval_request')?['body/msdyn_flow_approvalrequest_options'])

Follow with a ‘Compose’ action and replace the placeholders in the buttons JSON. Some can be replaced by expressions, like the environment id, others come from the Dataverse rows. The CreationTime format it expects is:
formatDateTime(outputs('Get_a_row_by_ID_-_approval_request')?['body/createdon'], 'dddd, dd MMMM yyyy HH:mm')
Increment the index variable by 1 with each loop.

Add them to the adaptive card
Take the output array and use it as the ActionSet in the adaptive card. The code below will create an adaptive card that’ll contain only the buttons.
{
"type": "AdaptiveCard",
"version": "1.0",
"body": [
{
"type": "ActionSet",
"actions": ##BUTTONSJSON##
}
]
}

Feel free to add also the content before the buttons that’s available in the ‘Create an approval’ action output. Just don’t forget to replace the placeholders – task title, date, link, etc.

All that’s left is to send the adaptive card.

Summary
As you can see, it’s not that complicated to build adaptive cards for existing Approval tasks, to let users approve directly from Teams. The adaptive cards have a given structure, a piece of JSON code that you can replicate and adjust to your specific needs. Load all the necessary data from the Approval and Approval Request tables, prepare JSON objects for each button, add the texts around it, and send it as a Teams message.
I’m doing tests on this right now – but trying to do it from the existing card that the “create approval” action generates.
Regardless, I’m also stuck doing the next step, which is also sending an email with the same approval. I tried to send an approval to my email, inspect on the network tab and saw that it uses the action Action.Http, and uses the following URL to POST:
“https://emea.api.flow.microsoft.com/callbacks/actionableEmail/environments//approvals//approvalResponses?api-version=1”
However, it also sends additional info, including clientTelemetry, adaptiveCardSignature and adaptiveCardHash, connectorSenderGuid, etc., that are outside the Action.Http and are probably validated in a table somewhere. Using a different user, I got a 401 error (fair, that user didn’t have any rights to approve/deny the request), and using my own user I had a “the action cannot be completed” in outlook.
So I’m kinda stuck. Really wanted to have more control over the card (comments field only on some options, send the email as an internal user, etc) but I don’t think it’s possible right now.