Okta Workflows makes it easy to build automations that notify or alert your teams with connectors to services like Slack and MS Teams.
Someone recently asked, "Why can't I add line-breaks to my MS Teams messages?"
As it turns out, we need to leverage the Custom API Action card so that we can specify that our content is HTML, rather than text.
With the default Send Message to Channel
card, our content is sent as text and line-breaks are ignored. Writing our message in HTML allows us to include line-breaks, lists, headers, style our text with fonts & colors, and more.
We can use the Text - Compose
card to write our HTML message.
We can use a pair of Object - Construct
cards to construct our request payload. We create a message object that contains our message content
and specifies our contentType
as html
. We then nest the message object in an object called body
.
The payload should look something like:
{
"body": {
"contentType": "html",
"content": "<h1 style=\"color:#FF0000;font-weight:bold\">Attention!</h1> <p>Thanks for reading! 🍻</p>"
}
}
Finally, we use the Custom API Action
card to
POST /teams/{team-id}/channels/{channel-id}/messages
Additional Resources:
Feel free to download my example, import it and try it out - just update the Relative URL in the Custom API Action to point at your own Team and Channel:
{"type":"flopack","version":"1.3.0","created":"2022-10-14T18:33:43.431Z","flags":{"auto-transform":true,"looseBooleans":true,"looseStrings":true,"looseNulls":true},"data":{"flos":{"f838207c-ea09-41bb-9d2f-b44bbe482a37":{"id":"f838207c-ea09-41bb-9d2f-b44bbe482a37","name":"MS Teams HTML CAPIA","description":"How to construct a body and use the Custom API Action card to send customized messages with MS Teams. ","data":{"id":null,"uuid":"f838207c-ea09-41bb-9d2f-b44bbe482a37","display":{"preview":[{"module":"string","name":"compose","kernel":true},{"module":"microsoftteams","name":"customAPIAction","kernel":false},{"module":"object","name":"construct","kernel":true},{"module":"object","name":"construct","kernel":true},{"module":"control","name":"noop","kernel":true},{"module":"control","name":"comment","kernel":true},{"module":"control","name":"comment","kernel":true},{"module":"control","name":"comment","kernel":true}],"isCallable":false},"tree":{"id":2,"name":"empty","description":"This flow has been build w/o a tree and uses the newer, async, Addressing module."},"methods":[{"joins":{},"address":"root:kernel:string:0.0.1:compose","parents":{"version":{"address":"root:kernel:string:0.0.1","key":"0.0.1","data":{"name":"0.0.1"}},"channel":{"address":"root:kernel:string","key":"string","data":{"name":"string"}}},"uuid":"kt1sryRSk","branches":{},"node":{"key":"compose","data":{"name":"Compose"},"model":{"type":"method","_v":2,"key":"compose","executable":false,"displayed":true,"async":false,"cooperative":false,"mirrored":false,"inlined":false,"dependencies":[],"timeout":90000,"idempotent":false,"monitor":false,"webhook":false,"webhookList":false,"webhookConditions":false,"mobile":false,"hooks":{},"policy":{"error":{"type":"finish"}},"metadata":{"id":null,"name":"Compose","description":"Enter free form text and optionally drag fields into your text like a mail merge."},"meta":{},"config":null,"partnerChannelKeys":null,"inputs":{"extensible":true,"rules":{"*":{"types":["string"],"collection":false}},"data":{"wfVtqsFzE7":{"id":"wfVtqsFzE7","group":null,"key":"_text_","value":{"type":"string","collection":false,"data":"<h1 style=\"color:#FF0000;font-weight:bold\">Attention!</h1>\n<h2>You can style your Teams messages 🎉</h2>\n<p> Try it out yourself, you can: </p>\n<ul>\n<li>Include bullet-point lists.</li>\n<li>Include line-breaks :) Here, we'll try one <br> out</li>\n<li>Style your text with <span style=\"color:blue\">color</span>, <span style=\"font:courier\">fonts, <i>italics</i>, etc. </li>\n</ul>\n<p>Thanks for reading! 🍻</p>","available":[],"error":false},"required":true,"ref":false,"metadata":{"index":0},"flags":"d"}}},"outputs":{"extensible":false,"data":{"WrkEos1mBl":{"id":"WrkEos1mBl","group":null,"key":"output","value":{"type":"string","collection":false,"data":"","available":[],"error":false},"ref":false,"metadata":{"index":0,"description":"","displayname":"HTML Message Content"},"_used":true}}},"runtime":{}}},"pins":{"WrkEos1mBl":{"jBP-u5Pg0":[{"input":"TdpOmJU6a","transform":null}]}}},{"joins":{},"address":"root:channels:http:microsoftteams:1.0.372:customAPIAction","parents":{"version":{"address":"root:channels:http:microsoftteams:1.0.372","key":"1.0.372","data":{"name":"1.0.372","id":736}},"channel":{"address":"root:channels:http:microsoftteams","key":"microsoftteams","data":{"name":"microsoftteams","id":113}}},"uuid":"tXhEuIzlo","branches":{},"node":{"key":"customAPIAction","data":{"name":"Custom API Action"},"model":{"type":"method","_v":2,"key":"customAPIAction","executable":true,"displayed":true,"async":true,"cooperative":false,"mirrored":false,"compat":false,"inlined":false,"dependencies":[],"timeout":30000,"idempotent":false,"monitor":false,"webhook":false,"webhookList":false,"webhookConditions":false,"mobile":false,"hooks":{},"policy":{"error":{"type":"finish"}},"metadata":{"id":33604,"name":"Custom API Action","description":null},"meta":{"703e4b3e-08e5-4e3f-a85b-e43984235aa1":{"id":"_A1bWv5mAW7","address":{"key":null,"group":"Request","fieldIndex":0,"defaultValue":{"path":[],"method":"getHttpInputs","data":{}},"namespace":"input"}}},"config":"4de3d294-ac61-48ef-af42-6aa336042eda","partnerChannelKeys":227,"inputs":{"extensible":false,"rules":{},"groupRules":{"Request":{"extensible":false,"reserved":{},"index":0,"type":"object"}},"data":{"r8Cf5gTtV6":{"id":"r8Cf5gTtV6","group":"parameters","key":"requestType","value":{"error":false,"proxy":false,"check":false,"type":"string","collection":false,"data":"POST","available":[]},"required":false,"ref":false,"metadata":{"type":"list","displayname":"Request Type","choices":[{"label":"GET","value":"GET"},{"label":"POST","value":"POST"},{"label":"PUT","value":"PUT"},{"label":"PATCH","value":"PATCH"},{"label":"DELETE","value":"DELETE"}],"dependencies":[],"optional":false,"ordering":0,"index":0},"flags":"p"},"Ss6eCzWP_":{"id":"Ss6eCzWP_","group":"Request","key":"Relative URL","value":{"error":false,"proxy":false,"check":false,"type":"string","collection":false,"data":"/teams/3ca570b9-93bb-4433-8119-afd971d64443/channels/19:a2a94a4f46334c2da2533c17152a9b78@thread.tacv2/messages","available":["string"]},"required":true,"ref":false,"metadata":{"index":1,"optional":false},"flags":"d"},"q-qI9mugPz":{"id":"q-qI9mugPz","group":"Request","key":"Query","value":{"error":false,"proxy":false,"check":false,"type":"object","collection":false,"data":{},"available":["string","object"]},"required":false,"ref":false,"metadata":{"index":2,"optional":false},"flags":"d"},"S2E33emtLq":{"id":"S2E33emtLq","group":"Request","key":"Headers","value":{"error":false,"proxy":false,"check":false,"type":"object","collection":false,"data":{},"available":["object"]},"required":false,"ref":false,"metadata":{"index":3,"optional":false},"flags":"d"},"1WW0uTBJ9":{"id":"1WW0uTBJ9","group":"Request","key":"Body","value":{"error":false,"proxy":false,"check":false,"type":"object","collection":false,"data":{},"available":["string","object"]},"required":false,"ref":false,"metadata":{"index":4,"optional":false},"flags":"d"}}},"outputs":{"extensible":false,"rules":{},"groupRules":{"Response":{"extensible":false,"reserved":{},"index":0,"type":"object"}},"data":{"SmRRJwggPQ":{"id":"SmRRJwggPQ","group":"Response","key":"Status Code","value":{"error":false,"type":"number","collection":false,"data":0,"available":["number"]},"ref":false,"metadata":{"index":0}},"_Mb5AqkPe0":{"id":"_Mb5AqkPe0","group":"Response","key":"Headers","value":{"error":false,"type":"object","collection":false,"data":{},"available":["object"]},"ref":false,"metadata":{"index":1}},"6QJmTFgOC_":{"id":"6QJmTFgOC_","group":"Response","key":"Body","value":{"error":false,"type":"object","collection":false,"data":{},"available":["object"]},"ref":false,"metadata":{"index":2}}}},"runtime":{},"display":{},"comments":"Makes an authenticated HTTP request to the Microsoft Teams Microsoft Graph API.","enableNewMetadata":true}},"pins":{}},{"joins":{},"address":"root:kernel:object:0.0.1:construct","parents":{"version":{"address":"root:kernel:object:0.0.1","key":"0.0.1","data":{"name":"0.0.1"}},"channel":{"address":"root:kernel:object","key":"object","data":{"name":"object"}}},"uuid":"jBP-u5Pg0","branches":{},"node":{"key":"construct","data":{"name":"Construct"},"model":{"type":"method","_v":2,"key":"construct","executable":false,"displayed":true,"async":false,"cooperative":false,"mirrored":false,"inlined":false,"dependencies":[],"timeout":90000,"idempotent":false,"monitor":false,"webhook":false,"webhookList":false,"webhookConditions":false,"mobile":false,"hooks":{},"policy":{"error":{"type":"finish"}},"metadata":{"id":null,"name":"Construct","description":"Create an object from multiple inputs."},"meta":{},"config":null,"partnerChannelKeys":null,"inputs":{"extensible":true,"rules":{"*":{"types":["*"],"collection":"*"}},"data":{"BMYu42Vjm":{"id":"BMYu42Vjm","group":null,"key":"contentType","value":{"error":false,"proxy":false,"check":false,"type":"string","collection":false,"data":"html","available":["string","number","boolean","Date","Array","object","file","flo","folder"]},"required":false,"ref":false,"metadata":{"index":0,"custom":true},"flags":"d"},"TdpOmJU6a":{"id":"TdpOmJU6a","group":null,"key":"content","value":{"error":false,"proxy":false,"check":false,"type":"string","collection":false,"data":"","available":["string","number","boolean","Date","Array","object","file","flo","folder"]},"required":false,"ref":false,"metadata":{"index":1,"custom":true},"flags":"d"}}},"outputs":{"extensible":false,"data":{"Oc0SwZZIe2":{"id":"Oc0SwZZIe2","group":null,"key":"output","value":{"type":"object","collection":false,"data":{},"available":[],"error":false},"ref":false,"metadata":{"index":0,"description":"","displayname":"messageObject"},"_used":true}}},"runtime":{}}},"pins":{"Oc0SwZZIe2":{"YXOCDErQE":[{"input":"scnMgWv2y","transform":null}]}}},{"joins":{},"address":"root:kernel:object:0.0.1:construct","parents":{"version":{"address":"root:kernel:object:0.0.1","key":"0.0.1","data":{"name":"0.0.1"}},"channel":{"address":"root:kernel:object","key":"object","data":{"name":"object"}}},"uuid":"YXOCDErQE","branches":{},"node":{"key":"construct","data":{"name":"Construct"},"model":{"type":"method","_v":2,"key":"construct","executable":false,"displayed":true,"async":false,"cooperative":false,"mirrored":false,"inlined":false,"dependencies":[],"timeout":90000,"idempotent":false,"monitor":false,"webhook":false,"webhookList":false,"webhookConditions":false,"mobile":false,"hooks":{},"policy":{"error":{"type":"finish"}},"metadata":{"id":null,"name":"Construct","description":"Create an object from multiple inputs."},"meta":{},"config":null,"partnerChannelKeys":null,"inputs":{"extensible":true,"rules":{"*":{"types":["*"],"collection":"*"}},"data":{"scnMgWv2y":{"id":"scnMgWv2y","group":null,"key":"body","value":{"error":false,"proxy":false,"check":false,"type":"object","collection":false,"data":{},"available":["string","number","boolean","Date","Array","object","file","flo","folder"]},"required":false,"ref":false,"metadata":{"index":0,"custom":true},"flags":"d"}}},"outputs":{"extensible":false,"data":{"Z6W6YHlW-N":{"id":"Z6W6YHlW-N","group":null,"key":"output","value":{"type":"object","collection":false,"data":{},"available":[],"error":false},"ref":false,"metadata":{"index":0,"description":"","displayname":"requestBody"},"_used":true}}},"runtime":{}}},"pins":{"Z6W6YHlW-N":{"tXhEuIzlo":[{"input":"1WW0uTBJ9","transform":null}]}}},{"joins":{},"address":"root:kernel:control:0.0.1:noop","parents":{"version":{"address":"root:kernel:control:0.0.1","key":"0.0.1","data":{"name":"0.0.1"}},"channel":{"address":"root:kernel:control","key":"control","data":{"name":"control"}}},"uuid":"mgE-yllLA","branches":{},"node":{"key":"noop","data":{"name":"Noop"},"model":{"type":"method","_v":2,"key":"noop","executable":false,"displayed":true,"async":false,"cooperative":false,"mirrored":false,"inlined":false,"dependencies":[],"timeout":90000,"idempotent":false,"monitor":false,"webhook":false,"webhookList":false,"webhookConditions":false,"mobile":false,"hooks":{},"policy":{"error":{"type":"finish"}},"metadata":{"id":null,"name":"Noop","description":"No-op. Does not do anything."},"meta":{},"config":null,"partnerChannelKeys":null,"inputs":{"extensible":true,"data":{}},"outputs":{"extensible":true,"data":{}},"runtime":{}}},"pins":{}},{"joins":{},"address":"root:kernel:control:0.0.1:comment","parents":{"version":{"address":"root:kernel:control:0.0.1","key":"0.0.1","data":{"name":"0.0.1"}},"channel":{"address":"root:kernel:control","key":"control","data":{"name":"control"}}},"uuid":"vTBPWs7-s","branches":{},"node":{"key":"comment","data":{"name":"Comment"},"model":{"type":"method","_v":2,"key":"comment","executable":false,"displayed":true,"async":false,"cooperative":false,"mirrored":false,"inlined":false,"dependencies":[],"timeout":90000,"idempotent":false,"monitor":false,"webhook":false,"webhookList":false,"webhookConditions":false,"mobile":false,"hooks":{},"policy":{"error":{"type":"finish"}},"metadata":{"id":null,"name":"Comment","description":"Leave a comment."},"meta":{},"config":null,"partnerChannelKeys":null,"inputs":{"extensible":false,"data":{}},"outputs":{"extensible":false,"data":{}},"runtime":{},"display":{},"comments":{"title":"POST to your relative URL:","markdown":"**POST** `/teams/{team-id}/channels/{channel-id}/messages`"}}},"pins":{}},{"joins":{},"address":"root:kernel:control:0.0.1:comment","parents":{"version":{"address":"root:kernel:control:0.0.1","key":"0.0.1","data":{"name":"0.0.1"}},"channel":{"address":"root:kernel:control","key":"control","data":{"name":"control"}}},"uuid":"8R0gMwUDr","branches":{},"node":{"key":"comment","data":{"name":"Comment"},"model":{"type":"method","_v":2,"key":"comment","executable":false,"displayed":true,"async":false,"cooperative":false,"mirrored":false,"inlined":false,"dependencies":[],"timeout":90000,"idempotent":false,"monitor":false,"webhook":false,"webhookList":false,"webhookConditions":false,"mobile":false,"hooks":{},"policy":{"error":{"type":"finish"}},"metadata":{"id":null,"name":"Comment","description":"Leave a comment."},"meta":{},"config":null,"partnerChannelKeys":null,"inputs":{"extensible":false,"data":{}},"outputs":{"extensible":false,"data":{}},"runtime":{},"display":{},"comments":{"title":"Write HTML, Construct JSON","markdown":"We use the `Text - Compose` Card to craft our message. Feel free to experiment with the styles, there are a number of HTML editors you can find online that should help."}}},"pins":{}},{"joins":{},"address":"root:kernel:control:0.0.1:comment","parents":{"version":{"address":"root:kernel:control:0.0.1","key":"0.0.1","data":{"name":"0.0.1"}},"channel":{"address":"root:kernel:control","key":"control","data":{"name":"control"}}},"uuid":"k6yRJO1Ha","branches":{},"node":{"key":"comment","data":{"name":"Comment"},"model":{"type":"method","_v":2,"key":"comment","executable":false,"displayed":true,"async":false,"cooperative":false,"mirrored":false,"inlined":false,"dependencies":[],"timeout":90000,"idempotent":false,"monitor":false,"webhook":false,"webhookList":false,"webhookConditions":false,"mobile":false,"hooks":{},"policy":{"error":{"type":"finish"}},"metadata":{"id":null,"name":"Comment","description":"Leave a comment."},"meta":{},"config":null,"partnerChannelKeys":null,"inputs":{"extensible":false,"data":{}},"outputs":{"extensible":false,"data":{}},"runtime":{},"display":{},"comments":{"title":"Why is this useful?","markdown":"Currently, the MS Teams connector only sends messages as `text` which means things like line breaks are ignored. \n\nWith a little extra work, we can create much more exciting and customized messages in MS Teams."}}},"pins":{}}],"model":{},"orderings":{"ilyygFurh":["mgE-yllLA","k6yRJO1Ha"],"HZYj0tWMme":["k6yRJO1Ha","kt1sryRSk"],"M7h57cjqoi":["kt1sryRSk","8R0gMwUDr"],"6OXHMIuk_h":["8R0gMwUDr","jBP-u5Pg0"],"tIQGRugoCR":["jBP-u5Pg0","YXOCDErQE"],"AUn80p85N1":["YXOCDErQE","vTBPWs7-s"],"Zeon6zilPd":["vTBPWs7-s","tXhEuIzlo"]},"cron":{},"security_level":null,"log":true,"inheritLog":true,"scheduled":false,"group":"704635ef-4f68-4dda-8f85-c990ff0c3b65","templateName":null,"connector_method_meta":{"inputs":{},"outputs":{},"options":{}},"monitor_flo":false}}},"configs":{"4de3d294-ac61-48ef-af42-6aa336042eda":{"id":"4de3d294-ac61-48ef-af42-6aa336042eda","name":"Microsoft Teams","module":"microsoftteams","data":null}},"tables":{},"groups":{"704635ef-4f68-4dda-8f85-c990ff0c3b65":{"id":"704635ef-4f68-4dda-8f85-c990ff0c3b65","data":{"name":"OIG Test","description":"","media_uri":""}}}},"checksum":"fb2d34a3d53132ae8072e97c3f0be49d57f73710073b7be606c731d44cf4ce04"} |
Download steps:
- right click "view raw" in the panel above on the right
- click "Save Link As"
- be sure the filename ends in
.flow
or check out my other guides and Workflows content (more coming soon!) here:
bbarrows89
/
oktaworkflows
tips, flows, and more related to Okta Workflows
Okta Workflows Guides and Resources
Free Training - Foundations for Flowgrammers
- Self-paced training to get started with Workflows
- Foundations for Flowgrammers
Guides
Office Hours
- Come join us in Community Office Hours!
- We meet 3x a week and are here to help answer questions and get you unblocked while you're building.
- Come with questions or just listen in to what other folks are building and working on.
- Book a session
Dev.to
- Posts by Workflows staff and community builders
- https://dev.to/oktaworkflows
Max Katz
- Max Katz blog
- Max Katz is in charge of Community for Okta Workflows and has an excellent collection of tips and guides.
IAMSE.blog
- IAMSE.blog/workflows
- A blog run by Okta Sales Engineers that covers various Okta topics.
Contact Bryan
- Feel free to contact me via LinkedIn
Hope this helps! Find me on LinkedIn or shoot me an email if you have any questions.
You can also join us at a Community Office Hours session to work through problems and ask questions - I'd love to see you there.
Top comments (0)