Top

Adaptive Cards in Outlook – ultimate guide


It has been a while since I first thought about writing this post. Recently I had more questions around this topic and somehow realized, that indeed this is something about Adaptive Cards that I haven’t yet written about. So let me fix it with this ultimate guide.

See it in action!

Actionable Messages using Adaptive Cards

First you need to understand, that although this is still Adaptive Cards that are sent to Outlook they are called Actionable Messages sometimes too. They are fairly similar, but have some differences:

 Adaptive CardsActionable Messages
Version1.31.0 (source)
Actions
  • Http,
  • Submit,
  • ShowCard,
  • ToggleVisibility
  • Http (for get and post),
  • OpenUrl.
  • InvokeAddInCommand to open an Outlook add-in task pane.
  • DisplayMessageForm to open the read form of a message
  • DisplayAppointmentForm to open the read form of a calendar item
  • ToggleVisibility
Target for submitNot supported, must be handled by hostSupported. You can define target URL, headers and body.
ActionSetYesYes
RefreshingYes, but via host requestYes, as a response from target URL
AuthenticationSecurity handled by the host, that sends card and receives response.Service that sends cards must be registered and approved by Microsoft. Responses must be validated by client to confirm submitter's validity.
Other differencesAll goodies coming from versions 1.0+
  • Input.Time not working,
  • hideOriginalBody parameter to hide contents of the mail others than card,
  • originator to pass GUID of the authenticated provider.
  • correlationId to set own unique ID to track card
Source: https://docs.microsoft.com/en-us/outlook/actionable-messages/adaptive-card#outlook-specific-adaptive-card-properties-and-features

Note! As you can see from the comparison above, Actionable Messages are some kind of a hybrid between Adaptive Cards and old, legacy Message Cards. Still, you can send Actionable Message following Message Card JSON schema, but that’s not the goal for this post.

Requirements

The technology wouldn’t be itself if there weren’t any limitations to when and how it can be used. Basically there are certain versions of Outlook and Office 365 that supports Actionable Messages using either Message Cards or Adaptive Cards schema. Find out more here: https://docs.microsoft.com/en-us/outlook/actionable-messages/#outlook-version-requirements-for-actionable-messages.

Important! Actionable Messages as a technology, works only inside Office 365 Outlook clients.

Send Actionable Message

Step 1, create Adaptive Card

To send Adaptive Card as an Actionable Message first go to https://adaptivecards.io/designer/ and switch “host app” to “Outlook Actionable Messages”:

This will automatically set version to 1.0 and change schema validation to allow you to insert all those exceptions I mentioned above. Now design your card.

Important! You need to define Id properties to each input fields in your card. They will be used to grab inserted values and send them to the target URL:

You can alternatively design card using Actionable Messages Designer: https://amdesigner.azurewebsites.net/ – using that tool you can not only preview the card to see how it looks, but you can as well send it to your inbox. And there is a set of ready-to-use templates. Awesome!

Step 2, define actions

Remember, there are couple more actions available for Actionable Messages. Lets focus on Http action. Take this one for an example:

{
            "type": "Action.Http",
            "title": "Approve",
            "url": "https://[URL-OF-TARGET-APP]",
            "id": "ac_approve",
            "style": "positive",
            "method": "POST",
            "body": "{\"comments\":\"{{ac_comments.value}}\",\"outcome\":\"approve\"}",
            "headers": [
                {
                    "name": "Authorization",
                    "value": ""
                },
                {
                    "name": "Content-type",
                    "value": "application/json"
                }
            ]
        }

You need to define the following attributes:

  • url – where contents from the form will be sent. In my case this will be another Power Automate flow triggered by Web Request action.
  • method – POST or GET? In case of form, naturally POST.
  • body – this has to be a serialized JSON. Note, you can refer to fields in your card by using {{field_id.value}} placeholder.
  • headers – define content type AND put empty “Authorization” header, since this will assure your request won’t interfere with target system authorization mechanism (source).

Step 3, build flow to handle response

Now you need to build flow triggered by “When a HTTP request is received” trigger. Define value of the request Body JSON Schema to the one, that you will be sending from Adaptive Card. In my case its simple:

{
    "type": "object",
    "properties": {
        "comments": {
            "type": "string"
        },
        "outcome": {
            "type": "string"
        }
    }
}

Now you can define any logic inside the flow, what is important though is to add action “Response” that will send confirmation to the Actionable Message.

Replace existing Adaptive Card with confirmation Adaptive Card

If you’d like to simply replace existing in user’s inbox Adaptive Card with a confirmation one, design it and then configure “Response” action as following:

  1. Add header: content-type – application/json,
  2. Add header: CARD-UPDATE-IN-BODY – true
    This header will tell Actionable Message, to rep[lace existing card with the one sent in Response body.
  3. In Body copy-paste your confirmation Adaptive Card JSON.

Source: https://docs.microsoft.com/en-us/outlook/actionable-messages/adaptive-card#refresh-cards

Send notification back to user

If you’d like to send notification back to user, but without actually closing the card, use Status Code 4xx (as per your scenario) and:

  1. Add header: content-type – application/json,
  2. Add header: CARD-ACTION-STATUS – information to be displayed to user.

Source: https://docs.microsoft.com/en-us/outlook/actionable-messages/adaptive-card#reporting-actionhttp-execution-success-or-failure

Step 4, publish flow handling response

And grab its URL, then paste in the “url” attribute of your post actions in the Adaptive Card.

Step 5, compose and send Actionable Message

Now put action Compose inside the flow that will be used to send Actionable Message. Inside the compose action, put Adaptive Card’s JSON between the <script> tags (source):

<script type="application/adaptivecard+json">
{ YOUR ADAPTIVE CARD'S JSON }
</script>

Finally add “Send an email (V2)” action, switch it into code mode and put outcomes of the “Compose” action:

Send message to yourself and test how it works! Voilla, easy scenario done.

Actionable Messages Debugger

To check and validate Actionable Message what you could find useful is the add-in to Microsoft Outlook called “Actionable Messages Debugger”. It will help you to identify issues with your message. To get it, click the “Get Add-ins” button, then search for debugger and finally hit “Add”:

Now once you open it for a message containing Actionable Message it will show you all the issues with it. For Like in the below example, where I sent Actionable Message without originator ID, so not from a registered provider:

Send Actionable Message to others

There are basically four scenarios how you can send the e-mail with Actionable Message (source):

  1. Send it from your inbox to the same inbox – no provider registration needed, generally described above.
  2. Defined test users within the same tenant – self-service provider registration and approval.
  3. Organization Exchange admins – approval sent to your tenant’s Exchange admins. Allows you to send Actionable Messages to any user within your tenant.
  4. Global – allow Actionable Message to be sent to any user in Office 365. Requires Microsoft approval.

To be able to send Actionable Message to other users inside Office 365 tenants, first thing you have to do is to open “Actionable Email Developer Dashboard” (https://outlook.office.com/connectors/oam/publish) and then register new provider.

Note! Registration of provider for the “Global” scope requires Microsoft approval and may take couple of days.

Once your provider is approved (it will be done automatically for test users and admins), copy “Provider Id” value:

And add it as an additional attribute to your Adaptive Card JSON code:

{
  "$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
  "type": "AdaptiveCard",
  "version": "1.0",
  "hideOriginalBody": true,
  "originator": "f6f1d226-abcd-asdaa-asdasd-123123123123",
  "body": [

Now depending on a chosen scope, you will be able to distribute your messages to a wider audience.

Message response verification

To verify that the sender of the Actionable Message response is the one who we expect, see the techniques in the second part of this post: https://poszytek.eu/en/microsoft-en/office-365-en/powerautomate-en/securing-responses-from-actionable-messages/.

And that’s all! If you have any questions, feel free to leave them in the comments below. Thank you 🙂


Tomasz Poszytek

Hi, I am Tomasz. I am expert in the field of process automation and business solutions' building using Power Platform. I am Microsoft MVP and Nintex vTE.

31 Comments
  • Nandha kumar

    Thanks for the great explanation.
    I have a created a flow to trigger mail. I can see adaptive card is getting rendered properly in Outlook office 365(App) and in browser(Outlook).
    But not in Windows mail client(Office 365 Configured).
    Is it something like windows mail client does not support adaptive card or am i missing something?
    Can you help on this?

    September 30, 2020 at 2:30 pm Reply
  • Anatolii

    Awesome tutorial!
    One thing I struggle to understand – are guest account emails within Organization scope or Global scope?

    December 3, 2020 at 5:04 pm Reply
    • Tomasz Poszytek

      Well, you’re sending mails to their “home” inboxes, aren’t you? So guests do have access to your data via local-guest accounts, however they don’t use the local inboxes. So in such case you need to use the Global scope, since these users are actually not form your tenant.

      December 8, 2020 at 4:24 pm Reply
  • oliver

    hi Tomasz, what could possibly trigger this error The remote endpoint returned an error (HTTP 401)?

    December 9, 2020 at 10:29 am Reply
    • Tomasz Poszytek

      Well, definitely some kind of missing permissions. What’s your case?

      December 9, 2020 at 11:54 pm Reply
  • Steve

    Awesome blog here!
    I am getting confused on versioning and how it applies to Actionable Messages / Adaptive Cards. I have a card that I send out through Outlook that works just great. I’m trying to add an iconURL to an Action button which was introduced in v1.1. If I change the version in the card to 1.1 it still doesn’t show up. It seems like Cards sent via Outlook can only use elements that existed in v1.0 of Adaptive Cards. Is that a correct assumption?

    December 9, 2020 at 3:32 pm Reply
    • Tomasz Poszytek

      Exactly. See here: https://docs.microsoft.com/en-us/adaptive-cards/resources/partners what are the Adaptive Cards versions you can use with each partner.

      December 9, 2020 at 11:55 pm Reply
      • Steve

        Thanks, any idea if they will update that in the near future to allow a more recent version for Outlook Actionable Messages?

        December 10, 2020 at 4:11 pm Reply
        • Purvi Parmar

          Hi Tomasz Poszytek,

          Awesome blog. Thank you.
          Even I get The remote endpoint returned an error (HTTP 401). I am using logic app http POST request.

          March 18, 2021 at 10:46 pm Reply
          • Tomasz Poszytek

            Have you registered the provider and used it’s id in card? Also, does the provider has the right scope? Please use Actionable Messages Debugger addin in Outlook to check potential issues.

            March 25, 2021 at 10:03 pm
  • Priya

    Hi Tomasz, Great blog.. I have created an adaptive card that is sent to multiple users. Is there any way to get user info like user email ID on click of submit action, to check which user actioned on response!!

    February 21, 2021 at 10:22 am Reply
  • Brandon Langford

    Tomasz,

    Thank you for the great video. I would like to use adaptive cards in an e-mail with approve or reject feature similar to your example, but with my application, there is a lot of logic that has to be processed which may require further approval based on an approver’s signature authority etc.. Is there a way for outlook to notify your application of the response and allow me to process the response and then send a response back to outlook with a new confirmation adaptive card?

    March 29, 2021 at 9:25 pm Reply
    • Tomasz Poszytek

      Thank you. Sure it is. If you use Power Automate to handle the response, you can then program whatever logic you need together with sending new Actionable Messages.

      April 3, 2021 at 7:14 am Reply
  • Christos A.

    Hi! My case is based on a youtube video and info from your site. I want to understand adaptive cards and to be able to apply a similar process inside my organization. My main problem is “The remote endpoint returned an error (HTTP 400). Please try again later.” when I choose the Action.Http from the adaptive card. I cannot find a solution nowhere. “When a HTTP request is received” action , is not triggered. Thank you in advance.

    April 7, 2021 at 3:05 pm Reply
    • Tomasz Poszytek

      Just check if the JSON body you are sending is valid. If you are using long text field, where user can type breaks, check if without new lines you are also getting 400. Also, be sure to escape quotes.

      April 28, 2021 at 11:21 am Reply
  • Vijay

    I have a naive question here. We use offline excel to collect feedback from partners / oems /customer / vendors who are not on our o365 tenant. But if we adopt to using actionable emails we can reduce the excel overhead. Will this still work? We are not sure of customer mail provider. The may or not be on Microsoft based products.

    But assuming most of them are on outlook client from a decision perspective do you suggest we adapt actionable emails? Any thoughts

    April 23, 2021 at 5:00 am Reply
    • Tomasz Poszytek

      Hi, this technology indeed works only in Outlook mail clients. So if partner is using other client, like gmail, Adaptive Cards won’t display. Also, you need to register a global provider and get approval for it from Microsoft: https://outlook.office.com/connectors/oam/publish, so that you will be able to send cards outside of your tenant.

      April 28, 2021 at 11:30 am Reply
  • Yuri Lima

    Good afternoon,

    Thanks for the awesome tutorial.

    In my case, I want to create a confirmation via Outlook for creating items in Microsoft Lists, for example: User receives email with Adaptive Card, when he clicks Approve, it will automatically generate an item in Microsoft Lists. To do this I am using Logic Apps and Microsoft Forms. Can you give me a light?

    April 30, 2021 at 9:27 pm Reply
    • Tomasz Poszytek

      You need to seal in logic that creates item in MS Lists inside that Logic App, that will be called after user hits approve button. The Logic App must be triggered using HTTP Request trigger.

      May 12, 2021 at 8:17 am Reply
  • Kyle

    Hi Tomasz, great tutorial. I’m still confused about how to correlate the Approval Request in Approval to the actual Adaptive Card so that when they click on submit in outlook email, it approves it automatically through the email. So the users will rely on outlook email to approve instead of using approvals format.

    Thanks,

    Kyle

    May 14, 2021 at 6:09 pm Reply
    • Tomasz Poszytek

      The key point is the “Actions” section of Adaptive Card. It contains elements, with definitions telling AC where to send data if user clicks specific button. And that destination then can reply with a new AC code.

      June 2, 2021 at 1:15 pm Reply
  • Adam Pospíšil

    Hi, I cannot open the https://outlook.office.com/connectors/oam/publish
    It always says an error. Is there some new way to do it, or it’s just broken?
    Thanks,
    Adam

    May 15, 2021 at 7:06 pm Reply
  • James Bruford

    Hi, If I want to send the actionable card to Teams (using the wait for approval connector) as well as Outlook, and I approve the card in Outlook, how can i ensure the Teams card is updated to read only and the flow ends?
    thanks
    James

    July 29, 2021 at 5:39 pm Reply
  • Varun Kumar Kammakolu

    In my scenario I have Email field which is a user input in adaptive card, so I want to send error message on adaptive card if user doesn’t enter an email address from Http response. How should I use the output of Email field in IF condition

    August 10, 2021 at 2:40 am Reply
    • Tomasz Poszytek

      Basically validate if it contains contents. Just try to implement something like empty(body('Contents_from_Adaptive_Card')['data']?['evaluated_field']) eq true.

      August 30, 2021 at 10:40 am Reply
  • Tomas

    Hello,

    how can I take input.toggle selection title as result in email. This expression is returning only true or false: body(‘test’)[‘data’]?[‘idtoggle’]

    August 26, 2021 at 12:06 pm Reply
    • Tomasz Poszytek

      Yes, toggle results in either true or false. But since you know the field ID, you can hardcode it in your flow, right? If not, you can as well add it’s label as one of the elements returned in response body.

      August 30, 2021 at 10:38 am Reply

Post a Comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.