
For information on interactive dialogs, see here.
Use interactive messages to simplify complex workflows by allowing users to take quick actions directly through your integration post. For example, they enable your integration to:
To try it out, you can use this Matterpoll plugin to add polling to Mattermost channels via a /poll slash command.

Add message buttons as actions in your integration message attachments.
The following payload gives an example that uses message buttons.
{
"attachments": [
{
"pretext": "This is the attachment pretext.",
"text": "This is the attachment text.",
"actions": [
{
"id": "message",
"name": "Ephemeral Message",
"tooltip": "Send a message only visible to you",
"integration": {
"url": "http://127.0.0.1:7357",
"context": {
"action": "do_something_ephemeral"
}
}
}, {
"id": "update",
"name": "Update",
"tooltip": "Update this message",
"integration": {
"url": "http://127.0.0.1:7357",
"context": {
"action": "do_something_update"
}
}
}
]
}
]
}
In the HTTP response for this request, the integration can choose to update the original post, and/or respond with an ephemeral message:
{
"update": {
"message": "Updated!",
"props": {}
},
"ephemeral_text": "You updated the post!"
}
To return a custom error message to the user, your integration can respond with an error object:
{
"error": {
"message": "Unable to complete action. Please check your permissions."
}
}
The error message will be displayed to the user below the message attachment. If no custom error message is provided, a default “Action failed to execute” message is shown. This feature is available in Mattermost v10.5 and later.

Button actions support a style parameter to change the color of the button. The possible values for style are: good, warning, danger, default, primary, and success. It’s also possible to pass a theme variable or a hex color, but we discourage this approach because it won’t be resilient against theme changes.

The actions used in the previous example include the following:
[
{
"id": "vote0",
"type": "button",
"name": "Yes",
"style": "default"
},
{
"id": "vote1",
"type": "button",
"name": "No",
"style": "primary"
},
{
"id": "addOption",
"type": "button",
"name": "Add Option",
"style": "warning"
},
{
"id": "deletePoll",
"type": "button",
"name": "Delete Poll",
"style": "success"
},
{
"id": "endPoll",
"type": "button",
"name": "End Poll",
"style": "danger"
}
]
You can add tooltips to provide helpful information when users hover over action buttons:
{
"attachments": [
{
"pretext": "Review this pull request",
"text": "Pull request #1234: Add new feature",
"actions": [
{
"id": "approve",
"type": "button",
"name": "Approve",
"tooltip": "Click to approve this pull request",
"style": "primary",
"integration": {
"url": "http://127.0.0.1:7357",
"context": {
"action": "approve",
"pr_id": 1234
}
}
},
{
"id": "reject",
"type": "button",
"name": "Reject",
"tooltip": "Click to reject this pull request",
"style": "danger",
"integration": {
"url": "http://127.0.0.1:7357",
"context": {
"action": "reject",
"pr_id": 1234
}
}
}
]
}
]
}
Similar to buttons, add message menus as actions in your integration message attachments.

The following payload gives an example that uses message menus (where id in the actions array may only consist of letters and numbers, no other characters are allowed):
{
"attachments": [
{
"pretext": "This is the attachment pretext.",
"text": "This is the attachment text.",
"actions": [
{
"id": "actionoptions",
"name": "Select an option...",
"integration": {
"url": "http://127.0.0.1:7357/actionoptions",
"context": {
"action": "do_something"
}
},
"type": "select",
"options": [
{
"text": "Option1",
"value": "opt1"
},
{
"text": "Option2",
"value": "opt2"
},
{
"text": "Option3",
"value": "opt3"
}
]
}
]
}
]
}
The integration can respond with an update to the original post, or with an ephemeral message:
{
"update": {
"message": "Updated!",
"props": {}
},
"ephemeral_text": "You updated the post!"
}
You can provide a list of channels for message menus for users to select from. Users can only select from public channels in their teams.
Specify channels as your action’s data_source as follows:
{
"attachments": [
{
"pretext": "This is the attachment pretext.",
"text": "This is the attachment text.",
"actions": [
{
"id": "actionoptions",
"name": "Select an option...",
"integration": {
"url": "http://127.0.0.1:7357/actionoptions",
"context": {
"action": "do_something"
}
},
"type": "select",
"data_source": "channels"
}
]
}
]
}
Similar to channels, you can also provide a list of users for message menus. The user can choose the user who is part of the Mattermost system.
Specify users as your action’s data_source as follows:
{
"attachments": [
{
"id": "actionoptions",
"pretext": "This is the attachment pretext.",
"text": "This is the attachment text.",
"actions": [
{
"name": "Select an option...",
"integration": {
"url": "http://127.0.0.1:7357/actionoptions",
"context": {
"action": "do_something"
}
},
"type": "select",
"data_source": "users"
}
]
}
]
}
Below is a brief description of each parameter to help you customize the interactive message button and menu in Mattermost. For more information on message attachments, see our documentation.
ID
A per post unique identifier.
Name
Give your action a descriptive name.
Tooltip (optional)
Display helpful text when users hover over the button. Available in Mattermost v10.5 and later.
URL
The actions are backed by an integration that handles HTTP POST requests when users select the message button. The URL parameter determines where this action is sent. The request contains an application/json JSON string. As of 5.14, relative URLs are accepted, simplifying the workflow when a plugin handles the action.
Context
The requests sent to the specified URL contain the user ID, post ID, channel ID, team ID, and any context that was provided in the action definition. If the post was of type Message Menus, then context also contains the selected_option field with the user-selected option value. The post ID can be used to, for example, delete or edit the post after selecting a message button.
A simple example of a request is given below:
{
"user_id": "rd49ehbqyjytddasoownkuqrxe",
"post_id": "gqrnh3675jfxzftnjyjfe4udeh",
"channel_id": "j6j53p28k6urx15fpcgsr20psq",
"team_id": "5xxzt146eax4tul69409opqjlf",
"context": {
"action": "do_something"
}
}
In most cases, your integration will do one or both of these things:
Identifying which action was triggered. For example, a GitHub integration might store something like this in the context:
{
"user_id": "rd49ehbqyjytddasoownkuqrxe",
"post_id": "gqrnh3675jfxzftnjyjfe4udeh",
"channel_id": "j6j53p28k6urx15fpcgsr20psq",
"team_id": "5xxzt146eax4tul69409opqjlf",
"context": {
"repo": "mattermost/mattermost",
"pr": 1234,
"action": "merge"
}
}
In the example above, when the message button is selected, your integration sends a request to the specified URL with the intention to merge the pull request identified by the context.
Authenticating the server. An important property of the context parameter is that it’s kept confidential. If your integration is not behind a firewall, you could add a token to your context without users ever being able to see it:
{
"user_id": "rd49ehbqyjytddasoownkuqrxe",
"post_id": "gqrnh3675jfxzftnjyjfe4udeh",
"channel_id": "j6j53p28k6urx15fpcgsr20psq",
"team_id": "5xxzt146eax4tul69409opqjlf",
"context": {
"repo": "mattermost/mattermost",
"pr": 1234,
"action": "merge",
"token": "somerandomlygeneratedsecret"
}
}
Then, when your integration receives the request, it can verify that the token matches one that you previously generated and know that the request is legitimately coming from the Mattermost server and is not forged.
Depending on the application, integrations can also perform authentication statelessly with cryptographic signatures such as:
{
"user_id": "rd49ehbqyjytddasoownkuqrxe",
"post_id": "gqrnh3675jfxzftnjyjfe4udeh",
"channel_id": "j6j53p28k6urx15fpcgsr20psq",
"team_id": "5xxzt146eax4tul69409opqjlf",
"context": {
"repo": "mattermost/mattermost",
"pr": 1234,
"action": "merge",
"signature": "mycryptographicsignature"
}
}
It’s also possible for integrations to do both of these things with a single token and use something like this as context:
{
"user_id": "rd49ehbqyjytddasoownkuqrxe",
"post_id": "gqrnh3675jfxzftnjyjfe4udeh",
"channel_id": "j6j53p28k6urx15fpcgsr20psq",
"team_id": "5xxzt146eax4tul69409opqjlf",
"context": {
"action_id": "someunguessableactionid"
}
}
Then, when the integration receives the request, it can act based on the action ID.
When an action button integration fails, Mattermost automatically displays an error message to the user below the message attachment. This provides immediate feedback when button actions don’t work as expected.

Key behaviors:
This feature is available in Mattermost v10.5 and later.
Automatic error display scenarios:
When your integration returns an error response with a custom message, that message is displayed to the user. For system-level errors where no custom message can be returned, a default error message is shown:
For troubleshooting integration errors from the server side, see the FAQ section “Why does an interactive button or menu return a 400 error?” below.
/poll slash command.If you’ve built an integration for Mattermost, please consider sharing your work in our app directory.
The app directory lists open source integrations developed by the Mattermost community and are available for download, customization, and deployment to your private cloud or self-hosted infrastructure.
Like Slack, actions are specified in an Actions list within the message attachment. Moreover, your integrations can react with ephemeral messages or message updates similar to Slack.
However, the schema for these objects is slightly different given Slack requires a Slack App and action URL to be pre-configured beforehand. Mattermost instead allows an integration to create an interactive message without pre-configuration.
If your ephemeral_text gets incorrectly handled by the Slack-compatibility logic, send "skip_slack_parsing":true along your ephemeral_text to bypass it.
{
"update": {
"message": "Updated!"
},
"ephemeral_text": "You updated the post!",
"skip_slack_parsing": true
}
Yes, message buttons and menus are supported in ephemeral messages in Mattermost 5.10 and later. This applies to integrations using plugins, the RESTful API and webhooks, across the browser and Desktop App.
As an advanced feature, you can also use plugins to update the contents of an ephemeral message with message buttons or menus with the UpdateEphemeralMessage plugin API.
It is likely for one of three reasons:
err=address forbidden in the error message.status=XXX in the error message.err=some json error message in the error message.Use update.Props in the following ways to manage properties (Props) of an interactive message after a user performs an action via an interactive button or menu:
update.Props == nil - Do not update Props field.update.Props == {} - Clear all properties, except the username and icon of the original message, as well as whether the message was pinned to channel or contained emoji reactions.update.Props == some_props - Post will be updated to some_props. Username and icon of the original message, and whether the message was pinned to channel or contained emoji reactions will not be updated.Did you find what you were looking for?