Sending interactive message via Knit Communication APIs
Interactive messages, like normal text messages, have not only text part but also an interactive component like button or dropdown. Most messaging applications support interactive messaging. For better understanding on Teams/Slack see the below links:
If you visited the above links, you can see that there is substantial difference between the two tools in sending interactive messages. Through Knit, you can unify your messaging stack for Teams and Slack. Let's find out more firstly by looking at Knit interactive message structure. There are two important message sections, non-interactive and interactive.
1. Non interactive section
This section can be used for describing motive and inner details of a message. Currently we support following types of non interactive sections:
- Text area - This is simple text box section where you can provide your text in markdown format supported by Knit text formatting .
- Key Value section - This can be used to highlight some key points of message.
These sections can be arranged in input array to design your message with Knit. See the code snippet below:
{
"sectionType": "textBlock",
"text": "This is a sample text area section"
}
{
"sectionType": "keyValueSet",
"values": [
{
"key": "Key 1",
"value": "Value 1"
},
{
"key": "Key 2",
"value": "Value 2"
}
]
}
2. Interactive components
This part is includes buttons, dropdown etc. where user can interact with message by making selection among one of the option. Currently we support only one interactive component:
- Buttons - Every button in a message is treated as single interactive component. It has following fields:
- Interactive component type
- id -> user passed id for button.
- label-> text shown to user on button
- value -> user passed value string.
- style (optional)
Button style can only be applied to Slack Buttons
There are three button styles supported by Slack:
- primary -> Green button
- danger -> Red button
- default -> No colour
Use an unique component id
Users should pass id and value of component in such way so that it can make sense of these once it is received in payload after user interacts with component.
Our suggestion would be use an unique id for each button. This can help you in routing the Knit's webhook payload to the the right business logic at your end. The value field can be looked at as metadata for the action/interaction and can be used to help with processing the interaction at your end.
3. Destination
This is the end point where user wants Knit to send interaction payload so that it can be further processed.
{
"sections": [
{
"sectionType": "textBlock",
"text": "This is a sample text"
},
{
"sectionType": "keyValueSet",
"values": [
{
"key": "Key 1",
"value": "value 1"
},
{
"key": "Key 2",
"value": "value 2"
}
]
}
],
"interactiveComponents": [
{
"id": "approveBtn",
"label": "Approve",
"value": "value1",
"style": "primary",
"interactiveComponentType": "button"
},
{
"label": "Deny",
"id": "denyBtn",
"value": "value2",
"style": "danger",
"interactiveComponentType": "button"
},
{
"label": "Neutral",
"id": "neutralBtn",
"value": "value3",
"interactiveComponentType": "button"
}
],
"destination": "https://sample-destination.com"
}
Few checks on different keys
- Destination must be an "http" or "https" link and should be less than 160 characters.
- Component id must be less than 100 characters.
- Component value must be less than 70 characters.
Designing your first interactive message workflow
Before we start
- You should have all necessary setup that is needed for sending plain text. Click on Sending plain text with Knit
- For slack you must setup Slack Interactive Endpoint in slack app management dashboard under interactivity section.
Let's try to understand interactive messages with a real life scenario. Let's assume that Knit wants to start flexible benefit plan for employees and they want to get response from all employees. Let's crack on and design this workflow.
A reminder before we begin, message can have:
- Text block describing flexible benefit plan.
- Key value section to highlight important points of the plan.
- Key value section to highlight important points of the plan.
- Destination URL so that interaction payload can be sent .
Below code sample shows example for our use case. It can be tweaked as per user need.
"interactiveMessage": {
"sections": [
{
"sectionType": "textBlock",
"text": "Hey!! we are planning to start **flexible benefit plan** across the org to help you save more tax.This can be used to restructure you existing salary into different allowances."
},
{
"sectionType": "keyValueSet",
"values": [
{
"key": "Food allownace(pm)",
"value": "3300"
},
{
"key": "Telephone allowance(pm)",
"value": "2000"
},
{
"key": "Gift allowance(pm)",
"value": "500"
}
]
},
{
"sectionType": "textBlock",
"text": "If you want to opt for this benefit from coming month, choose the appropriate button below."
}
],
"interactiveComponents": [
{
"id": "approveBtn||flex_benifit",
"label": "Approve",
"value": "emp_123",
"style": "primary",
"interactiveComponentType": "button"
},
{
"label": "Deny",
"id": "denyBtn||flex_benifit",
"value": "emp_123",
"style": "danger",
"interactiveComponentType": "button"
},
{
"label": "Not Sure",
"id": "neutralBtn||flex_benifit",
"value": "emp_123",
"interactiveComponentType": "button"
}
],
"destination": "https://sample-url.com/flexi"
}
Button Id and value naming
- Button id is made up of functionality (flexible benefit) and button type.
- Button value gives employee id who have responded
- Note that button id is unique for each button.
Sending the message using Knit APIs
To send we will be using existing Send Message API with query parameter messageType = "interactive". The below code sample will show the same interactive message payload in Java.
public static void sendInteractiveMessage(String channelId) {
OkHttpClient client = new OkHttpClient();
Map<String, Object> map = new HashMap<>();
String interactiveMessageBody = "{\"sections\":[{\"sectionType\":\"textBlock\",\"text\":\"Hey!! we are planning to start **flexible benifit plan** across the org to help you save more tax.This can be used to restructure you existing salary into different allowances.\"},{\"sectionType\":\"keyValueSet\",\"values\":[{\"key\":\"Food allownace(pm)\",\"value\":\"3300\"},{\"key\":\"Telephone allowance(pm)\",\"value\":\"2000\"},{\"key\":\"Gift allowance(pm)\",\"value\":\"500\"}]},{\"sectionType\":\"textBlock\",\"text\":\"If you want to opt for this benifit from coming month, choose the appropriate button below.\"}],\"interactiveComponents\":[{\"id\":\"approveBtn||flex_benifit\",\"label\":\"Approve\",\"value\":\"emp_123\",\"style\":\"primary\",\"interactiveComponentType\":\"button\"},{\"label\":\"Deny\",\"id\":\"denyBtn||flex_benifit\",\"value\":\"emp_123\",\"style\":\"danger\",\"interactiveComponentType\":\"button\"},{\"label\":\"Not Sure\",\"id\":\"neutralBtn||flex_benifit\",\"value\":\"emp_123\",\"interactiveComponentType\":\"button\"}],\"destination\":\"https://sample-url.com/flexi\"}";
JsonObject jsonObject = JsonParser.parseString(interactiveMessageBody).getAsJsonObject();
map.put("interactiveMessage", jsonObject);
map.put("channelId", channelId);
map.put("channelType", "dm");
String body = toJson(map); // convert to json
System.out.println(body);
Request request = new Request.Builder()
.url("https://api.getknit.dev/v1.0/comm.msg.send?messageType=interactive")
.addHeader("Authorization", "Bearer " + "API_KEY")
.addHeader("X-Knit-Integration-Id", "Integration Id")
.post(RequestBody.create(body, JSON))
.build();
Response response = client.newCall(request).execute();
JsonNode jsonNode = mapper.readTree(response.body().string());
String messageId = jsonNode.at("/data/messageId").asText();
}
The below images will show how this will look in different messaging platforms:
Slack
MS Teams
Processing payload after interaction
As soon as user clicks on any interactive component, Knit will send you payload on destination set in interactive message. Let's assume user has clicked on Approve and your backend receives the adequate payload. This payload can be further used to store users response and send acknowledgement message back to user using either Send Message API or Update Message API.
{
"eventId": "ev_vfSGMAUsvRZG6mG6HuI1Fu",
"eventData": {
"componentId": "approveBtn||flex_benifit",
"componentValue": "emp_123",
"channelId": "D04M0KAD093",
"messageId": "MTY3OTA0NTYyOS41MDE3Mzk6RDA0TTBLQUQwOTM="
},
"eventType": "bot.interactive"
}
public static void handleInteractiveMessage(String payload) throws IOException {
JsonNode jsonNode = mapper.readTree(payload);
String compId = jsonNode.at("/eventData/componentId").asText();
String compValue = jsonNode.at("/eventData/componentValue").asText();
String channelId = jsonNode.at("/eventData/channelId").asText();
String messageId = jsonNode.at("/eventData/messageId").asText();
// CompValue = employeeId , compId = response String can be fetched using it
registerFlexiBenifitsResp(compId, compValue);
// Further You can update the same message calling Knit API
Map<String, Object> map = new HashMap<>();
map.put("message", "Your response has been registered!!");
map.put("channelId", channelId);
map.put("channelType", "dm");
map.put("messageId", messageId);
String body = toJson(map);
Request request = new Request.Builder()
.url("https://api.getknit.dev/v1.0/comm.msg.update")
.addHeader("Authorization", "Bearer " + "API_KEY")
.addHeader("X-Knit-Integration-Id", "Integration Id")
.post(RequestBody.create(body, JSON))
.build();
Response response = client.newCall(request).execute();
JsonNode jsonNode = mapper.readTree(response.body().string());
}
public static void registerFlexiBenifitsResp(String empId, String responseStr) {
//put your business logic here
}
Now we will acknowledge user response by sending acknowledgement message. We will update the same message with a plain text message.
public static void sendAcknowledgementMessage(String channelId) {
OkHttpClient client = new OkHttpClient();
Map<String, Object> map = new HashMap<>();
map.put("message", "Your response has been submitted.");
map.put("channelId", "D04M0KAD093");
map.put("channelType", "dm");
map.put("messageId", "MTY3OTA0NTYyOS41MDE3Mzk6RDA0TTBLQUQwOTM=")
String body = toJson(map); // convert to json
Request request = new Request.Builder()
.url("https://api.getknit.dev/v1.0/comm.msg.update")
.addHeader("Authorization", "Bearer " + "API_KEY")
.addHeader("X-Knit-Integration-Id", "Integration Id")
.post(RequestBody.create(body, JSON))
.build();
Response response = client.newCall(request).execute();
JsonNode jsonNode = mapper.readTree(response.body().string());
String messageId = jsonNode.at("/data/messageId").asText();
// This message Id can be used for further updating message
}
Here's how it looks in MSTeams:
Here's how it looks in Slack:
That's it. We can't wait to see what you build with Knit's interactive message support!
Updated over 1 year ago