You can implement user interaction with Outlook adaptive cards (a.k.a. Actionable messages) within Torq workflows. After the user has responded to the adaptive card form, the content of the adaptive card will automatically be updated.
Create an application in Azure
Open Microsoft Azure: Navigate to your Azure portal and go to Azure services > Microsoft Entra ID.
Register a new application: Go to Manage > App registrations and click New registration if a relevant app assigned to an Azure resource does not exist.
Enter a unique and meaningful name, such as
Torq-Outlook-ActionableMessages.Give the account Accounts in this organization directory only access.
Click Register.
Copy the application ID: Go to the application's Overview page and copy both the Application (client) ID to save it for later.
Open Certificates & secrets: In the application, go to Manage > Certificates & secrets.
Create a client secret: Select the Client secrets tab and click New client secret.
Enter a meaningful description/name.
Select an expiration date according to your organization's best practices.
Click Add.
Register a new provider in the Actionable Email Developer Dashboard
If you do not register a new provider, you can embed adaptive cards in Outlook emails but they will not be displayed.
Create a provider: Go to the Actionable Email Developer Dashboard and click New Provider.
Enter your company name.
Copy the Provider Id (originator)—you will need it later to build the adaptive card form.
For MsEntra Application Id, paste the application ID you copied earlier.
For Sender email address, enter at least one email address.
For Target URLs, enter
https://hooks.torq.io/for US-based workspaces orhttps://hooks.eu.torq.io/for EU-based workspaces.For Scope of submission, select the relevant scope. Test Users suffices for automation purposes and is automatically approved.
For Test user email addresses, enter at least one email address from the same tenant.
Accept the terms and conditions.
Click Save.
Create an adaptive card form
You must use the Actionable Message Designer for Microsoft Outlook rather than the Adaptive Cards Designer for Microsoft Teams to build adaptive cards for Outlook emails.
Open the designer: Navigate to the Actionable Message Designer and click Blank Card.
Enter the JSON payload: Click Edit JSON Payload and paste the relevant code. The following is an example payload for an Outlook adaptive card.
{
"type": "AdaptiveCard",
"body": [
{
"type": "ColumnSet",
"style": "emphasis",
"columns": [
{
"type": "Column",
"items": [
{
"type": "TextBlock",
"text": "Case Update",
"wrap": true
}
],
"width": "stretch",
"padding": "None"
},
{
"type": "Column",
"items": [
{
"type": "TextBlock",
"horizontalAlignment": "Right",
"color": "Accent",
"text": "[Case #{{ $.metadata.case.id }}](<https://app.torq.io/cases?account=*********&preset=All%20cases&payload=8&caseId=>{{ $.metadata.case.id }}&expanded=true&workspace=ee1071e4-*************-364f33e3c009)",
"wrap": true
}
],
"width": "stretch",
"padding": "None"
}
],
"padding": "Default",
"spacing": "None"
},
{
"type": "Container",
"items": [
{
"type": "TextBlock",
"size": "Large",
"weight": "Bolder",
"text": "{{ $.get_case_details.case.title }}",
"wrap": true,
"style": "heading"
}
],
"padding": "Default",
"spacing": "None",
"separator": true
},
{
"type": "Container",
"id": "7d00f965-40bb-9fc3-ff7b-a9b82a09ead4",
"padding": "Default",
"items": [
{
"type": "ColumnSet",
"columns": [
{
"type": "Column",
"items": [
{
"type": "Image",
"style": "Person",
"url": "<https://raw.githubusercontent.com/acitatorq/vendor_icons/main/Cabeca-Lego.png>",
"size": "Small",
"altText": "Lego Head"
}
],
"width": "auto",
"padding": "None"
},
{
"type": "Column",
"items": [
{
"type": "TextBlock",
"text": "{{ $.metadata.user_email }}",
"wrap": true
},
{
"type": "TextBlock",
"spacing": "None",
"color": "Light",
"text": "Security Analyst",
"wrap": true,
"size": "Small"
},
{
"type": "TextBlock",
"spacing": "None",
"color": "Light",
"text": "Security Operations Center",
"wrap": true,
"size": "Small"
}
],
"width": "stretch",
"padding": "None"
}
],
"spacing": "None",
"padding": "None"
}
],
"spacing": "None",
"separator": true
},
{
"type": "Container",
"items": [
{
"type": "TextBlock",
"text": "**Please fill in and submit the form below so that we can have the information required to progress on the investigation of this incient.**",
"wrap": true
},
{
"type": "TextBlock",
"id": "af6389c1-3218-a1fd-54c1-8e2217a3c4ee",
"text": "**Work Location**",
"wrap": true
},
{
"type": "Input.ChoiceSet",
"id": "work_location",
"placeholder": "Select your location",
"choices": [
{
"title": "EU",
"value": "europe"
},
{
"title": "USA",
"value": "usa"
}
],
"spacing": "None",
"isRequired": true
},
{
"type": "TextBlock",
"id": "6a867daf-c689-5bdf-1850-ce7f687d3b9b",
"text": "**Select your role**",
"wrap": true
},
{
"type": "Input.ChoiceSet",
"id": "employee_role",
"placeholder": "Role",
"choices": [
{
"title": "Analyst",
"value": "analyst"
},
{
"title": "SOC Operator",
"value": "operator"
},
{
"title": "Something Else",
"value": "something_else"
}
],
"spacing": "None",
"isRequired": true
},
{
"type": "TextBlock",
"id": "e124bcdf-c5b4-0efc-12f0-f0d5a4da6d92",
"text": "**Select your date of birth**",
"wrap": true
},
{
"type": "Input.Date",
"id": "selected_date",
"isRequired": true,
"spacing": "None"
},
{
"type": "TextBlock",
"id": "0ded56de-1232-6b57-2688-1985679aeb13",
"text": "**Type \\\"approve\\\" if you approve us, the SOC, to check your profile information for Cyber Security Operations Purposes to safeguard the integrity of the company assets.**",
"wrap": true
},
{
"type": "Input.Text",
"id": "approval",
"placeholder": "Type approve or leave blank",
"spacing": "None"
}
],
"padding": {
"top": "None",
"bottom": "Default",
"left": "Default",
"right": "Default"
},
"spacing": "None"
},
{
"type": "Container",
"id": "353b659f-b668-fac0-5b7f-5d2f1bdb46ac",
"padding": "Default",
"items": [
{
"type": "ActionSet",
"actions": [
{
"type": "Action.Http",
"id": "accept",
"title": "Accept",
"method": "POST",
"url": "{{ $.workflow_parameters.response_webhook }}",
"body": "{\\n \\"case_id\\": \\"{{ $.metadata.case.id }}\\",\\n \\"message_id\\": \\"MID_{{ $.generate_random_id_to_key_unique_message.result }}\\",\\n \\"analyst\\": \\"{{ $.metadata.user_email }}\\",\\n \\"user\\": \\"{{ $.event.recipient }}\\",\\n \\"clicked_action\\": \\"accept\\",\\n \\"work_location\\": \\" {{`{{work_location.value}}`}}\\",\\n \\"employee_role\\": \\"{{`{{employee_role.value}}`}}\\",\\n \\"selected_date\\": \\"{{`{{selected_date.value}}`}}\\",\\n \\"approval\\": \\"{{`{{approval.value}}`}}\\"\\n}",
"isPrimary": true,
"style": "positive",
"headers": [
{
"name": "X-Torq-Auth",
"value": "{{ $.secrets.outlook_actionable_webhook_secret }}"
}
]
},
{
"type": "Action.Http",
"id": "reject",
"title": "Reject",
"method": "POST",
"url": "{{ $.workflow_parameters.response_webhook }}",
"body": "{\\n \\"case_id\\": \\"{{ $.metadata.case.id }}\\",\\n \\"message_id\\": \\"MID_{{ $.generate_random_id_to_key_unique_message.result }}\\",\\n \\"analyst\\": \\"{{ $.metadata.user_email }}\\",\\n \\"user\\": \\"{{ $.event.recipient }}\\",\\n \\"clicked_action\\": \\"reject\\",\\n \\"work_location\\": \\"{{`{{work_location.value}}`}}\\",\\n \\"employee_role\\": \\"{{`{{employee_role.value}}`}}\\",\\n \\"selected_date\\": \\"{{`{{selected_date.value}}`}}\\",\\n \\"approval\\": \\"{{`{{approval.value}}`}}\\"\\n}",
"headers": [
{
"name": "X-Torq-Auth",
"value": "{{ $.secrets.outlook_actionable_webhook_secret }}"
}
]
}
],
"spacing": "None"
}
],
"spacing": "None",
"separator": true
}
],
"$schema": "<http://adaptivecards.io/schemas/adaptive-card.json>",
"version": "1.0",
"padding": "None",
"@type": "AdaptiveCard",
"@context": "<http://schema.org/extensions>",
"originator": "<provider ID (originator)>"
}Edit the payload: For the
originatorkey, replace<provider ID (originator)>with the provider ID you copied earlier.Preview the card: Close the editor and click Preview to review the card.
Embed the adaptive card in a Microsoft Outlook Send Message step
To embed an adaptive card in an Outlook message, it must be sent in HTML format in the <head></head> section of the message body.
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
<script type="application/adaptivecard+json">
{
"type": "AdaptiveCard",
"body": [
{
"type": "ColumnSet",
"style": "emphasis",
"columns": [
{
"type": "Column",
"items": [
{
"type": "TextBlock",
"text": "Case Update",
"wrap": true
}
],
"width": "stretch",
"padding": "None"
},
{
"type": "Column",
"items": [
{
"type": "TextBlock",
"horizontalAlignment": "Right",
"color": "Accent",
"text": "[Case {{ $.metadata.case.id }}](<https://app.torq.io/cases?account=********&preset=All%20cases&payload=8&caseId=>{{ $.metadata.case.id }}&expanded=true&workspace=ee1071e4-*************-364f33e3c009)",
"wrap": true
}
],
"width": "stretch",
"padding": "None"
}
],
"padding": "Default",
"spacing": "None"
},
{
"type": "Container",
"items": [
{
"type": "TextBlock",
"size": "Large",
"weight": "Bolder",
"text": "{{ $.get_case_details.case.title }}",
"wrap": true,
"style": "heading"
}
],
"padding": "Default",
"spacing": "None",
"separator": true
},
{
"type": "Container",
"id": "7d00f965-40bb-9fc3-ff7b-a9b82a09ead4",
"padding": "Default",
"items": [
{
"type": "ColumnSet",
"columns": [
{
"type": "Column",
"items": [
{
"type": "Image",
"style": "Person",
"url": "<https://raw.githubusercontent.com/acitatorq/vendor_icons/main/Cabeca-Lego.png>",
"size": "Small",
"altText": "Lego Head"
}
],
"width": "auto",
"padding": "None"
},
{
"type": "Column",
"items": [
{
"type": "TextBlock",
"text": "{{ $.metadata.user_email }}",
"wrap": true
},
{
"type": "TextBlock",
"spacing": "None",
"color": "Light",
"text": "Security Analyst",
"wrap": true,
"size": "Small"
},
{
"type": "TextBlock",
"spacing": "None",
"color": "Light",
"text": "Security Operations Center",
"wrap": true,
"size": "Small"
}
],
"width": "stretch",
"padding": "None"
}
],
"spacing": "None",
"padding": "None"
}
],
"spacing": "None",
"separator": true
},
{
"type": "Container",
"items": [
{
"type": "TextBlock",
"text": "**Please fill in and submit the form below so that we can have the information required to progress on the investigation of this incient.**",
"wrap": true
},
{
"type": "TextBlock",
"id": "af6389c1-3218-a1fd-54c1-8e2217a3c4ee",
"text": "**Work Location**",
"wrap": true
},
{
"type": "Input.ChoiceSet",
"id": "work_location",
"placeholder": "Select your location",
"choices": [
{
"title": "EU",
"value": "europe"
},
{
"title": "USA",
"value": "usa"
}
],
"spacing": "None",
"isRequired": true
},
{
"type": "TextBlock",
"id": "6a867daf-c689-5bdf-1850-ce7f687d3b9b",
"text": "**Select your role**",
"wrap": true
},
{
"type": "Input.ChoiceSet",
"id": "employee_role",
"placeholder": "Role",
"choices": [
{
"title": "Analyst",
"value": "analyst"
},
{
"title": "SOC Operator",
"value": "operator"
},
{
"title": "Something Else",
"value": "something_else"
}
],
"spacing": "None",
"isRequired": true
},
{
"type": "TextBlock",
"id": "e124bcdf-c5b4-0efc-12f0-f0d5a4da6d92",
"text": "**Select your date of birth**",
"wrap": true
},
{
"type": "Input.Date",
"id": "selected_date",
"isRequired": true,
"spacing": "None"
},
{
"type": "TextBlock",
"id": "0ded56de-1232-6b57-2688-1985679aeb13",
"text": "**Type \"approve\" if you approve us, the SOC, to check your profile information for Cyber Security Operations Purposes to safeguard the integrity of the company assets.**",
"wrap": true
},
{
"type": "Input.Text",
"id": "approval",
"placeholder": "Type approve or leave blank",
"spacing": "None"
}
],
"padding": {
"top": "None",
"bottom": "Default",
"left": "Default",
"right": "Default"
},
"spacing": "None"
}
],
"$schema": "<http://adaptivecards.io/schemas/adaptive-card.json>",
"version": "1.0",
"padding": "None",
"@type": "AdaptiveCard",
"@context": "<http://schema.org/extensions>",
"originator": "<provider ID (originator)>"
}
</script>
</head>
<body>
<hr />
<p><strong>This is a new case update message for <a href="<https://app.torq.io/cases?account=********&preset=All%20cases&payload=8&caseId=>{{ $.metadata.case.id }}&expanded=true&workspace=ee1071e4-*************-364f33e3c009" target="_blank">Case {{ $.metadata.case.id }}</a></strong></p>
<hr />
<p><strong>Message generated by: <a href="mailto:{{ $.metadata.user_email }}">{{ $.metadata.user_email }}</a></strong></p>
<hr />
<p><strong>Message Body:</strong></p>
<hr />
<p><em>{{ $.event.message_body }}</em></p>
<hr />
</body>
</html>
The generated email message will look like:
Once the adaptive card form has been submitted, it is refreshed. This records the provided answers and prevents you from resubmitting the form.
Refresh an Outlook adaptive card on submission
To refresh the content of an Outlook adaptive card on submission, the endpoint (Torq Webhook) receiving the POST request generated by Action.http must respond in 2 seconds or less with the JSON of the refreshed card in the response body and the response header CARD-UPDATE-IN-BODY: true.
The following is an example workflow implementing a synchronous webhook trigger to refresh the adaptive card. Most of the workflow's process has been moved to an asynchronous nested workflow to ensure that a response can be returned in under 2 seconds. The JSON payload of the refreshed adaptive card has been added to the Exit operator's body parameter.
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
<script type="application/adaptivecard+json">
{
"type": "AdaptiveCard",
"body": [
{
"type": "ColumnSet",
"style": "emphasis",
"columns": [
{
"type": "Column",
"items": [
{
"type": "TextBlock",
"text": "Case Update",
"wrap": true
}
],
"width": "stretch",
"padding": "None"
},
{
"type": "Column",
"items": [
{
"type": "TextBlock",
"horizontalAlignment": "Right",
"color": "Accent",
"text": "[Case {{ $.metadata.case.id }}](<https://app.torq.io/cases?account=********&preset=All%20cases&payload=8&caseId=>{{ $.metadata.case.id }}&expanded=true&workspace=ee1071e4-*************-364f33e3c009)",
"wrap": true
}
],
"width": "stretch",
"padding": "None"
}
],
"padding": "Default",
"spacing": "None"
},
{
"type": "Container",
"items": [
{
"type": "TextBlock",
"size": "Large",
"weight": "Bolder",
"text": "{{ $.get_case_details.case.title }}",
"wrap": true,
"style": "heading"
}
],
"padding": "Default",
"spacing": "None",
"separator": true
},
{
"type": "Container",
"id": "7d00f965-40bb-9fc3-ff7b-a9b82a09ead4",
"padding": "Default",
"items": [
{
"type": "ColumnSet",
"columns": [
{
"type": "Column",
"items": [
{
"type": "Image",
"style": "Person",
"url": "<https://raw.githubusercontent.com/acitatorq/vendor_icons/main/Cabeca-Lego.png>",
"size": "Small",
"altText": "Lego Head"
}
],
"width": "auto",
"padding": "None"
},
{
"type": "Column",
"items": [
{
"type": "TextBlock",
"text": "{{ $.metadata.user_email }}",
"wrap": true
},
{
"type": "TextBlock",
"spacing": "None",
"color": "Light",
"text": "Security Analyst",
"wrap": true,
"size": "Small"
},
{
"type": "TextBlock",
"spacing": "None",
"color": "Light",
"text": "Security Operations Center",
"wrap": true,
"size": "Small"
}
],
"width": "stretch",
"padding": "None"
}
],
"spacing": "None",
"padding": "None"
}
],
"spacing": "None",
"separator": true
},
{
"type": "Container",
"items": [
{
"type": "TextBlock",
"text": "**Please fill in and submit the form below so that we can have the information required to progress on the investigation of this incient.**",
"wrap": true
},
{
"type": "TextBlock",
"id": "af6389c1-3218-a1fd-54c1-8e2217a3c4ee",
"text": "**Work Location**",
"wrap": true
},
{
"type": "Input.ChoiceSet",
"id": "work_location",
"placeholder": "Select your location",
"choices": [
{
"title": "EU",
"value": "europe"
},
{
"title": "USA",
"value": "usa"
}
],
"spacing": "None",
"isRequired": true
},
{
"type": "TextBlock",
"id": "6a867daf-c689-5bdf-1850-ce7f687d3b9b",
"text": "**Select your role**",
"wrap": true
},
{
"type": "Input.ChoiceSet",
"id": "employee_role",
"placeholder": "Role",
"choices": [
{
"title": "Analyst",
"value": "analyst"
},
{
"title": "SOC Operator",
"value": "operator"
},
{
"title": "Something Else",
"value": "something_else"
}
],
"spacing": "None",
"isRequired": true
},
{
"type": "TextBlock",
"id": "e124bcdf-c5b4-0efc-12f0-f0d5a4da6d92",
"text": "**Select your date of birth**",
"wrap": true
},
{
"type": "Input.Date",
"id": "selected_date",
"isRequired": true,
"spacing": "None"
},
{
"type": "TextBlock",
"id": "0ded56de-1232-6b57-2688-1985679aeb13",
"text": "**Type \"approve\" if you approve us, the SOC, to check your profile information for Cyber Security Operations Purposes to safeguard the integrity of the company assets.**",
"wrap": true
},
{
"type": "Input.Text",
"id": "approval",
"placeholder": "Type approve or leave blank",
"spacing": "None"
}
],
"padding": {
"top": "None",
"bottom": "Default",
"left": "Default",
"right": "Default"
},
"spacing": "None"
}
],
"$schema": "<http://adaptivecards.io/schemas/adaptive-card.json>",
"version": "1.0",
"padding": "None",
"@type": "AdaptiveCard",
"@context": "<http://schema.org/extensions>",
"originator": "{{ $.workflow_parameters.outlook_originator_id }}"
}
</script>
</head>
<body>
<hr />
<p><strong>This is a new case update message for <a href="<https://app.torq.io/cases?account=********&preset=All%20cases&payload=8&caseId=>{{ $.metadata.case.id }}&expanded=true&workspace=ee1071e4-*************-364f33e3c009" target="_blank">Case {{ $.metadata.case.id }}</a></strong></p>
<hr />
<p><strong>Message generated by: <a href="mailto:{{ $.metadata.user_email }}">{{ $.metadata.user_email }}</a></strong></p>
<hr />
<p><strong>Message Body:</strong></p>
<hr />
<p><em>{{ $.event.message_body }}</em></p>
<hr />
</body>
</html>




