snapshot of https://github.com/mattermost/mattermost.git (master, 2026-09-16; blobs > 131072B omitted)
Some checks failed
Server CI / Postgres (shard 0) (push) Has been skipped
Server CI / Postgres (shard 3) (push) Has been skipped
BuildEnv Docker Image / build-image (push) Failing after 4s
BuildEnv Docker Image / build-image-fips (push) Failing after 4s
Migration Review & Release Notes / Generate migration review & release notes (push) Failing after 3s
Server CI / Build Environment (push) Failing after 3s
Server CI / Postgres (shard 1) (push) Has been skipped
Tools CI / check-style (mattermost-govet) (push) Failing after 4s
Server CI / Postgres (shard 2) (push) Has been skipped
Tools CI / check-style (mmgotool) (push) Failing after 3s
Server CI / Elasticsearch v8 Compatibility (push) Has been skipped
Server CI / OpenSearch v2 Compatibility (push) Has been skipped
Server CI / Postgres FIPS (shard 0) (push) Has been skipped
Tools CI / Test (mattermost-govet) (push) Failing after 3s
Server CI / Postgres FIPS (shard 1) (push) Has been skipped
Server CI / Postgres FIPS (shard 2) (push) Has been skipped
Tools CI / Test (mmgotool) (push) Failing after 3s
Server CI / Postgres FIPS (shard 3) (push) Has been skipped
Server CI / Run mmctl tests (push) Has been skipped
Server CI / Run mmctl tests (FIPS) (push) Has been skipped
Server CI / Merge Postgres Test Results (push) Has been skipped
Server CI / Merge Postgres FIPS Test Results (push) Has been skipped
Server CI / Check backport migrations (push) Has been skipped
Server CI / Check generated files (push) Has been skipped
Server CI / check-style (push) Has been skipped
Server CI / Vet API (push) Has been skipped
Server CI / Build mattermost server app (push) Has been skipped
Server CI / Server CI Complete (push) Failing after 2s
Server CI / Server CI Artifacts (push) Has been skipped
Server CI / Sentry Upload (push) Has been skipped
Server CI / Server CI Report (push) Failing after 5m1s
Server CI Nightly Race / Race Detector (push) Has been skipped
CodeQL / Analyze (go) (push) Has been cancelled
CodeQL / Analyze (javascript) (push) Has been cancelled
Webapp CI Cache Warm / Warm Webapp node_modules Cache (push) Has been cancelled
E2E CI Cache Warm / Warm E2E npm Registry Cache (push) Has been cancelled
API / build (push) Has been cancelled
Web App CI / check-types (push) Has been cancelled
Web App CI / check-lint (push) Has been cancelled
Web App CI / check-i18n (push) Has been cancelled
Web App CI / check-external-links (push) Has been cancelled
Web App CI / test (platform) (push) Has been cancelled
Web App CI / test (mattermost-redux) (push) Has been cancelled
Web App CI / test (channels shard 1/4) (push) Has been cancelled
Web App CI / test (channels shard 2/4) (push) Has been cancelled
Web App CI / test (channels shard 3/4) (push) Has been cancelled
Web App CI / test (channels shard 4/4) (push) Has been cancelled
Web App CI / upload-coverage (push) Has been cancelled
Web App CI / build (push) Has been cancelled
YAML Lint / yamllint (push) Has been cancelled
Push mirrored docker images / cd/Push mirrored docker images (push) Has been cancelled
docs-cd / Build and deploy docs (push) Has been cancelled
Docs CI / build (push) Has been cancelled
E2E Cache Warm: Cypress deps / Warm Cypress deps cache (push) Has been cancelled
Scorecards supply-chain security / Scorecard analysis (push) Has been cancelled
Server CI Weekly / Postgres FIPS (push) Has been skipped
Server CI Weekly / Run mmctl tests (FIPS) (push) Has been skipped
Server CI Weekly / Postgres with binary parameters (push) Has been skipped
Server CI Weekly / Build Environment (push) Failing after 1s
Server CI Nightly Race / Build Environment (push) Failing after 1s
Server CI Cache Warm / Warm Go Module and Build Cache (push) Failing after 2s
187
docs/develop/integrate/reference/bot-accounts/index.md
Normal file
@@ -0,0 +1,187 @@
|
||||
---
|
||||
title: "Bot accounts"
|
||||
sidebar_position: 30
|
||||
---
|
||||
|
||||
Bot accounts access the Mattermost [RESTful API](https://api.mattermost.com) on behalf of a bot through the use of the [personal access tokens feature](/developers/integrate/reference/personal-access-token). Bot accounts are just like user accounts, except they:
|
||||
|
||||
- Can't be logged into.
|
||||
- Can't be used to create other bot accounts.
|
||||
- Can't be used to upload files to a channel, unless they are also added to the channel as a channel member.
|
||||
- Don't count as a registered user and therefore don't count towards the total number of users for an Enterprise Edition license.
|
||||
|
||||
Additional benefits include:
|
||||
|
||||
- System Admins can enable bot accounts to post to any channel in the system, including private teams, Private channels, or Direct Messages.
|
||||
- Integrations created by a user and tied to a bot account no longer break if the user leaves the company.
|
||||
- Once created, bot accounts behave just like regular user accounts and can be added to teams and channels similar to users.
|
||||
- Bot accounts are a safer way to integrate with Mattermost through the RESTful API and Plugin API because there is no need to manage shared logins with these accounts.
|
||||
- A `BOT` tag is used throughout Mattermost where bot accounts are referenced, including messages and user lists.
|
||||
|
||||
Note that currently:
|
||||
|
||||
- Only System Admins or plugins can create or manage bot accounts.
|
||||
- In Mattermost Enterprise Edition, service accounts without an email address pulled from LDAP or SAML systems are not yet supported.
|
||||
|
||||
If you would like to see improvements to bot accounts, [let us know in the Feature Proposal Forum](https://mattermost.uservoice.com).
|
||||
|
||||
## Configuration settings
|
||||
|
||||
By default, plugins can create and manage bot accounts. To enable bot account creation through the user interface or the RESTful API:
|
||||
|
||||
1. Go to **System Console > Integrations > Bot Accounts**.
|
||||
2. Set **Enable Bot Account Creation** to **true**.
|
||||
|
||||
Once set, System Admin can create bot accounts for integrations using the **Integrations > Bot Accounts** link in the description provided.
|
||||
|
||||
## Bot account creation
|
||||
|
||||
Below are different ways to create bot accounts. After the bot account is created, make sure to:
|
||||
|
||||
1. Copy the generated bot access token for your integration.
|
||||
2. To add the bot account to teams and channels you want it to interact in, select the team drop-down menu, then select **Invite People**. Next, select **Invite Member** and enter the bot account in the **Add or Invite People** field. Then select **Invite Members**. You should now be able to add the bot account to channels like any other user.
|
||||
|
||||
### User interface (UI)
|
||||
|
||||
1. Go to the Product menu and select **Integrations > Bot Accounts**.
|
||||
2. Select **Add Bot Account**.
|
||||
3. Set the **Username** of the bot. The username must begin with a letter, and contain between 3 and 22 lowercase characters made up of numbers, letters, and symbols including ".", "-", or "\_".
|
||||
4. (Optional) Upload an image for the **Bot Icon**. This will be used as the profile image of the bot throughout Mattermost.
|
||||
5. (Optional) Set a **Display Name** and **Description**.
|
||||
6. (Optional) Choose what role the bot should have. Defaults to **Member**. If you assign **System Admin**, the bot will have read and write access for any Public channels, Private channels, and Direct Messages.
|
||||
7. (Optional) Select additional permissions for the account. Enable the bot to post to all Mattermost channels, or post to all Mattermost Public channels.
|
||||
8. Select **Create Bot Account**.
|
||||
9. Copy the token displayed on the **Setup Successful** page before you select **Done** as you won't have access to the token again once you close the screen.
|
||||
|
||||
### RESTful API
|
||||
|
||||
Use the RESTful API `POST /bots` to create a bot. You must have permissions to create bots.
|
||||
|
||||
See our [API documentation](https://api.mattermost.com/#tag/bots) to learn more about creating and managing bots through the API.
|
||||
|
||||
To authorize your bot via RESTful API use `curl -i -H 'authorization: Bearer <Access Token>' http://localhost:8065/api/v4/users/me`. **Access Token** is not the `Token ID` and won't be visible again once created.
|
||||
|
||||
### Command line interface (CLI)
|
||||
|
||||
You can use the following CLI command to convert an existing user account to a bot:
|
||||
|
||||
```shell
|
||||
user convert user@example.com --bot
|
||||
```
|
||||
|
||||
In addition to email, you can identify the user by its username or user ID.
|
||||
|
||||
Bot accounts which were converted from user accounts will have their authentication data cleared if they were email/password accounts. Those synchronized from LDAP/SAML will not have their authentication data cleared so that LDAP/SAML synchronization performs correctly.
|
||||
|
||||
### Plugins
|
||||
|
||||
Plugins can create bot accounts through an `EnsureBot` helper function. For an example, see [the Demo Plugin](https://github.com/mattermost/mattermost-plugin-demo/blob/master/server/configuration.go#L210-L217).
|
||||
|
||||
Bots created by a plugin use the plugin's ID as the creator, unless otherwise specified by the plugin.
|
||||
|
||||
## Technical notes
|
||||
|
||||
### Data model
|
||||
|
||||
Each bot account has a row in the **Users** table and the **Bots** table. The entries are tied together by `User.Id = Bot.UserId`.
|
||||
|
||||
The Bots table schema is described as follows:
|
||||
|
||||
| Field | Description | Type | Required |
|
||||
|-------------|---------------------------------|--------|----------|
|
||||
| UserId | User ID of the bot user | string | Y |
|
||||
| Username | Username of the bot account | string | Y |
|
||||
| DisplayName | Display name of the bot account | string | N |
|
||||
| Description | Description of the bot account | string | N |
|
||||
| OwnerId | User ID of the owner of the bot | string | Y |
|
||||
| CreateAt | Unix timestamp of creation time | int64 | Y |
|
||||
| UpdateAt | Unix timestamp of update time | int64 | Y |
|
||||
| DeleteAt | Unix timestamp of deletion time | int64 | Y |
|
||||
|
||||
## Frequently asked questions
|
||||
|
||||
### Should I migrate all my integrations to use bot accounts?
|
||||
|
||||
For your integrations using RESTful API and plugins, yes. To do so, you can either convert an existing account to a bot, or create a new bot account using the steps outlined above.
|
||||
|
||||
Once you create a bot account, use the generated token to access the RESTful API on behalf of a bot and interact in the Mattermost server.
|
||||
|
||||
For your webhook and slash command integrations, you cannot migrate them to use bot accounts, as they require a user account at this time. However, an option is to migrate the webhooks or slash commands to a plugin, which in turn can use bot accounts.
|
||||
|
||||
### What happens if a plugin is using a bot account that already exists as a user account?
|
||||
|
||||
For a concrete example, suppose you enable the [Mattermost GitHub plugin](https://github.com/mattermost/mattermost-plugin-github), which uses a `github` bot account, while an existing `github` user account was created for webhook integrations.
|
||||
|
||||
Once the plugin is enabled, the plugin posts as the `github` account but without a `BOT` tag. An error message is logged to the server logs recommending the System Admin to convert the `github` user to a bot account by running `mattermost user convert <username> --bot` in the CLI.
|
||||
|
||||
If the user is an existing user account you want to preserve, change its username and restart the Mattermost server, after which the plugin will create a bot account with the name `github`.
|
||||
|
||||
### How do I convert an existing account to a bot account?
|
||||
|
||||
Use the following CLI command to convert an existing user account to a bot:
|
||||
|
||||
`user convert user@example.com --bot`
|
||||
|
||||
In addition to email, you may identify the user by its username or user ID.
|
||||
|
||||
Bot accounts which were converted from user accounts will have their authentication data cleared if they were email/password accounts. Those synchronized from LDAP/SAML will not have their authentication data cleared so that LDAP/SAML synchronization performs correctly.
|
||||
|
||||
### How can I quickly test if my bot account is working?
|
||||
|
||||
Add the bot to a team and channel you belong to, then use the following curl command to post with the bot:
|
||||
|
||||
`curl -i -X POST -H 'Content-Type: application/json' -d '{"channel_id":"<channel-id>", "message":"This is a message from a bot", "props":{"attachments": [{"pretext": "Look some text","text": "This is text"}]}}' -H 'Authorization: Bearer <bot-access-token>' <mattermost-url>/api/v4/posts`
|
||||
|
||||
Replace the following parameters:
|
||||
|
||||
- `<channel-id>` with the channel you added the bot to
|
||||
- `<bot-access-token>` with the bot access token generated when you created the bot account
|
||||
- `<mattermost-url>` with your Mattermost domain, e.g. ``https://example.mattermost.com``
|
||||
|
||||
### Do bot access tokens expire?
|
||||
|
||||
No, but you can automate your integration to cycle its token through the REST API:
|
||||
1. Use [GetUserAccessTokensForUser](https://api.mattermost.com/#operation/GetUserAccessTokensForUser) to list the existing tokens for the `bot` user.
|
||||
2. Use [CreateUserAccessToken](https://api.mattermost.com/#operation/CreateUserAccessToken) to generate a new token.
|
||||
3. Update the services that leverage the token with the new `token` value from step 1.
|
||||
4. Use [RevokeUserAccessToken](https://api.mattermost.com/#operation/RevokeUserAccessToken) to revoke the old token based on the `token_id`.
|
||||
|
||||
For more information about access tokens, see [the personal access tokens documentation](/developers/integrate/reference/personal-access-token).
|
||||
|
||||
### Do bot accounts make it easier to impersonate someone else such as the CEO or an HR coordinator?
|
||||
|
||||
Possibly yes. Currently a System Admin can disable overriding the profile picture and the username from integrations to help prevent impersonation, but this is not the case for bot accounts.
|
||||
|
||||
Mitigations:
|
||||
|
||||
- `BOT` tag is used everywhere in the UI where bot accounts are referenced, including messages and user lists.
|
||||
- For Direct Message channels, the channel header distinguishes the bot from a regular user account with a `BOT` tag.
|
||||
|
||||
### What happens when a user who owns bot accounts is disabled?
|
||||
|
||||
By default, bot accounts managed by the deactivated user are disabled for enhanced security. Those with permissions to manage bot accounts can re-enable them via the **Product menu > Integrations > Bot Accounts**.
|
||||
|
||||
We strongly recommend creating new tokens for the bot, to ensure the user who was deactivated no longer has access to read or write data in the system via the bot access token.
|
||||
|
||||
If you prefer to have bot accounts remain enabled after user deactivation, set `DisableBotsWhenOwnerIsDeactivated` to `false` in your `config.json` file.
|
||||
|
||||
### Can bot accounts edit messages through the RESTful API?
|
||||
|
||||
Yes. By default, bot accounts can update their own posts.
|
||||
|
||||
If you find yourself unable to edit posts as a bot, check the following:
|
||||
|
||||
1. Instead of using a slash command to respond directly, use an an API call for the initial interaction with a user to enable message edits.
|
||||
2. If your system is using [advanced permissions](https://docs.mattermost.com/onboard/advanced-permissions.html), then post edits could be disabled for users.
|
||||
|
||||
If neither of the above help resolve your issue, you also have the option to choose what role the bot account has. If System Admin is chosen, then the bot can update any posts in the system. Note that giving the System Admin role to a bot account enables the bot with other System Admin privileges so this should be done with care.
|
||||
|
||||
### If AD/LDAP or SAML synchronization is enabled, do bot accounts need to have an associated email address in AD/LDAP or SAML?
|
||||
|
||||
When AD/LDAP or SAML synchronization is enabled, you can create bot accounts using the steps outlined above. These bot accounts won't require an email address.
|
||||
|
||||
If you need to sync service accounts from AD/LDAP or SAML to Mattermost and use them as bot accounts, [please reach out to us](https://mattermost.com/contact-us) to discuss in detail. You may not need to sync service accounts and use them as bot accounts to meet your use case.
|
||||
|
||||
### How are bot accounts identified in compliance exports?
|
||||
|
||||
As of v5.14, a field named `UserType` is added to Compliance Exports, including Global Relay, Actiance, and CSV. The field identifies whether a message was posted by a `user` or by a `bot` account.
|
||||
6
docs/develop/integrate/reference/index.md
Normal file
@@ -0,0 +1,6 @@
|
||||
---
|
||||
title: "Quick reference"
|
||||
sidebar_position: 90
|
||||
---
|
||||
|
||||
This reference section contains information on integrating plugins with Mattermost, including Server SDK, Web App SDK, and REST API references.
|
||||
250
docs/develop/integrate/reference/markdown-actions/index.md
Normal file
@@ -0,0 +1,250 @@
|
||||
---
|
||||
title: "Use markdown action buttons"
|
||||
description: "Markdown action buttons let an integration turn an inline post-markdown link into an action affordance. Clicking the link dispatches a post action to the integration's endpoint instead of navigating away, expanding interactivity beyond message attachments."
|
||||
sidebar_label: "Markdown action buttons"
|
||||
sidebar_position: 45
|
||||
---
|
||||
|
||||
:::note[Part of the Interactive Messages framework]
|
||||
Markdown action buttons are one binding surface in the Interactive Messages framework alongside [Mattermost Blocks](/developers/integrate/reference/mm-blocks). All surfaces share the same `mm_blocks_actions` action registry.
|
||||
:::
|
||||
|
||||
Use markdown action buttons to add inline, in-text affordances to a post — without using a message attachment. They're useful when:
|
||||
|
||||
- A short message reads naturally with an "Approve" or "Reject" inline link.
|
||||
- An integration wants to mix narrative text and action affordances in the same post body.
|
||||
- The visual weight of a full message attachment isn't warranted.
|
||||
|
||||
For block-style buttons and menus, see [Mattermost Blocks](/developers/integrate/reference/mm-blocks). For legacy attachment actions, see [interactive messages](/developers/integrate/plugins/interactive-messages).
|
||||
|
||||
## How it works
|
||||
|
||||
A markdown action has two parts:
|
||||
|
||||
1. A markdown link in the post body using the `mmaction://` scheme, where the link host is the action ID:
|
||||
|
||||
```text
|
||||
[Approve](mmaction://approve?ticket=ISS-101)
|
||||
```
|
||||
|
||||
2. A matching entry in the post's `props.mm_blocks_actions` registry that tells the server what to do when the link is clicked:
|
||||
|
||||
```json
|
||||
{
|
||||
"mm_blocks_actions": {
|
||||
"approve": {
|
||||
"type": "external",
|
||||
"url": "https://integration.example.com/hook/approve",
|
||||
"context": {"project": "Demo Project"}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The client renders the link as a button. Clicking it dispatches a request to the Mattermost server, which forwards the call to the integration's `url` along with merged query parameters and any server-side context.
|
||||
|
||||
## Example post payload
|
||||
|
||||
The following payload posts a message with two markdown action buttons. The body markdown references action IDs defined in `mm_blocks_actions`.
|
||||
|
||||
```json
|
||||
{
|
||||
"channel_id": "qmd5oqtwoibz8cuzxzg5ekshgr",
|
||||
"message": "Ticket ISS-101 needs review: [Approve](mmaction://approve?ticket=ISS-101) [Reject](mmaction://reject?ticket=ISS-101)",
|
||||
"props": {
|
||||
"mm_blocks_actions": {
|
||||
"approve": {
|
||||
"type": "external",
|
||||
"url": "https://integration.example.com/hook/approve",
|
||||
"context": {"project": "Demo Project"}
|
||||
},
|
||||
"reject": {
|
||||
"type": "external",
|
||||
"url": "https://integration.example.com/hook/reject",
|
||||
"context": {"project": "Demo Project"}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
You can send this payload using the [create post REST API](https://api.mattermost.com/#operation/CreatePost), an [incoming webhook](/developers/integrate/webhooks/incoming), or from a [plugin](/developers/integrate/plugins/components/server).
|
||||
|
||||
### Submit using the REST API
|
||||
|
||||
```bash
|
||||
curl -X POST $MM_URL/api/v4/posts \
|
||||
-H "Authorization: Bearer $BOT_TOKEN" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"channel_id": "'$CHANNEL_ID'",
|
||||
"message": "Ticket ISS-101 needs review: [Approve](mmaction://approve?ticket=ISS-101) [Reject](mmaction://reject?ticket=ISS-101)",
|
||||
"props": {
|
||||
"mm_blocks_actions": {
|
||||
"approve": {
|
||||
"type": "external",
|
||||
"url": "https://integration.example.com/hook/approve",
|
||||
"context": {"project": "Demo Project"}
|
||||
},
|
||||
"reject": {
|
||||
"type": "external",
|
||||
"url": "https://integration.example.com/hook/reject",
|
||||
"context": {"project": "Demo Project"}
|
||||
}
|
||||
}
|
||||
}
|
||||
}'
|
||||
```
|
||||
|
||||
### Submit from a plugin
|
||||
|
||||
A server-side plugin creates posts with markdown actions through the existing `API.CreatePost` / `API.UpdatePost` interfaces. The action `url` typically points at the plugin's own HTTP handler.
|
||||
|
||||
```go
|
||||
post := &model.Post{
|
||||
ChannelId: channelID,
|
||||
UserId: p.botID,
|
||||
Message: "Ticket ISS-101 needs review: " +
|
||||
"[Approve](mmaction://approve?ticket=ISS-101) " +
|
||||
"[Reject](mmaction://reject?ticket=ISS-101)",
|
||||
Props: model.StringInterface{
|
||||
"mm_blocks_actions": map[string]any{
|
||||
"approve": map[string]any{
|
||||
"type": "external",
|
||||
"url": fmt.Sprintf("/plugins/%s/inline_action/approve", manifest.Id),
|
||||
"context": map[string]any{"project": "Demo Project"},
|
||||
},
|
||||
"reject": map[string]any{
|
||||
"type": "external",
|
||||
"url": fmt.Sprintf("/plugins/%s/inline_action/reject", manifest.Id),
|
||||
"context": map[string]any{"project": "Demo Project"},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
_, err := p.API.CreatePost(post)
|
||||
```
|
||||
|
||||
A plugin can also change markdown actions later via `API.UpdatePost`. See [Updating and removing actions](#updating-and-removing-actions) for who may change `mm_blocks_actions` and how actions are removed.
|
||||
|
||||
## Link syntax
|
||||
|
||||
```text
|
||||
[<label>](mmaction://<action_id>?<query_string>)
|
||||
```
|
||||
|
||||
**`<label>`**<br/>
|
||||
The link text rendered as the button label.
|
||||
|
||||
**`<action_id>`**<br/>
|
||||
The host portion of the URL. Must match a key in `props.mm_blocks_actions`. Must contain only letters, numbers, underscores, or hyphens (`[A-Za-z0-9_-]+`), matched case-sensitively, and may be up to 64 characters long.
|
||||
|
||||
**`<query_string>`** (optional)<br/>
|
||||
`key=value` pairs that are forwarded with the dispatched action and merged into the target URL's query string by the server. Link-supplied values override registry-supplied values on key conflict. Up to 50 entries; each key may be up to 128 characters and each value up to 2048 characters.
|
||||
|
||||
## The `mm_blocks_actions` registry
|
||||
|
||||
The `mm_blocks_actions` post prop is a map keyed by action ID. Each entry describes how the server should handle clicks on that action. The registry supports up to 50 action entries.
|
||||
|
||||
```json
|
||||
{
|
||||
"mm_blocks_actions": {
|
||||
"<action_id>": {
|
||||
"type": "<action_type>",
|
||||
"url": "...",
|
||||
"context": { ... },
|
||||
"query": { ... }
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
| Field | Required | Description |
|
||||
| --- | --- | --- |
|
||||
| `type` | yes | Action type. See [Action types](#action-types) below. |
|
||||
| `url` | depends on type | Target URL for the integration's callback endpoint. Required for `external`. |
|
||||
| `context` | no | Object of server-side context values forwarded to the integration in the post-action request body. Not visible to the client. Up to 50 entries; each key may be up to 128 characters. |
|
||||
| `query` | no | Static `string -> string` map merged into the target URL's query string by the server. Combined with any query parameters supplied in the `mmaction://` link — link values win on key conflict. Up to 50 entries; each key may be up to 128 characters and each value up to 2048 characters. |
|
||||
|
||||
### Action types
|
||||
|
||||
| Type | Behaviour |
|
||||
| --- | --- |
|
||||
| `external` | The server sends a POST request to `url` with the dispatched action, including `context`, `query` (after merging), and any link-supplied query parameters. The integration responds with a standard post-action response. |
|
||||
|
||||
Additional action types may be introduced as the broader Interactive Messages framework lands. Entries with an unknown `type` value are rejected at post-create time.
|
||||
|
||||
## Click dispatch flow
|
||||
|
||||
The diagram below describes the lifecycle of a single click on a markdown action button.
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant Integration
|
||||
participant Server as Mattermost server
|
||||
participant Client
|
||||
Integration->>Server: Create post (mmaction link + mm_blocks_actions)
|
||||
Server->>Server: Validate post and store action registry
|
||||
Server->>Client: Deliver post
|
||||
Client->>Client: Render link as button
|
||||
Client->>Server: POST /api/v4/posts/{id}/actions/{action_id}
|
||||
Server->>Server: Merge query parameters into action URL
|
||||
Server->>Integration: POST action callback
|
||||
Integration->>Server: Post-action response
|
||||
Server->>Client: Update post / ephemeral message
|
||||
```
|
||||
|
||||
1. **Integration** creates a post with an `mmaction://<id>` link and a matching `mm_blocks_actions[<id>]` entry.
|
||||
2. **Mattermost server** validates the post (`mm_blocks_actions` schema and limits) and stores it.
|
||||
3. **Client** renders the link as a button. Clicking it dispatches `POST /api/v4/posts/{post_id}/actions/{action_id}` with the link's query string in the request body.
|
||||
4. **Mattermost server** looks up `mm_blocks_actions[<id>]`, merges the registry's static `query` with the request body's query (request body wins on conflict), merges the result into the action URL's query string, and POSTs the integration endpoint.
|
||||
5. **Integration** responds with a standard post-action response.
|
||||
|
||||
## Receiving action callbacks
|
||||
|
||||
When a user clicks a markdown action button, the Mattermost server sends an HTTP POST request to the `url` configured in the matching `mm_blocks_actions` entry. The request body follows the same `PostActionIntegrationRequest` shape used by [Mattermost Blocks](/developers/integrate/reference/mm-blocks) and legacy [message attachment](/developers/integrate/reference/message-attachments) buttons — the integration responds with the same post-action response format.
|
||||
|
||||
## Updating and removing actions
|
||||
|
||||
- An integration session (bot account, personal access token, or OAuth app) may add, replace, or remove `mm_blocks_actions` on a post **it authored**, via the update and patch post endpoints. Other sessions can edit the message but not another author's actions.
|
||||
- `mm_blocks_actions` is an exception to the usual update rule that omitted fields are cleared: the server preserves the post's existing actions when an update leaves the prop out, so a message-only edit never wipes buttons. (Sending an empty or altered value still replaces them.)
|
||||
- Removing a button's `mmaction://` link from the message revokes its action: the entry is pruned and later clicks return a not-found error.
|
||||
|
||||
## Validation limits
|
||||
|
||||
Posts that exceed any of the following limits are rejected at create or update time.
|
||||
|
||||
| Limit | Value |
|
||||
| --- | --- |
|
||||
| Maximum entries in `mm_blocks_actions` | 50 |
|
||||
| Maximum length of an action ID (map key) | 64 characters |
|
||||
| Action ID character set | `[A-Za-z0-9_-]+` |
|
||||
| Maximum entries in `query` (link or registry) | 50 |
|
||||
| Maximum length of a query key | 128 characters |
|
||||
| Maximum length of a query value | 2048 characters |
|
||||
|
||||
## Error reference
|
||||
|
||||
The following error IDs may be returned by the post-action and post-create APIs when processing markdown action requests.
|
||||
|
||||
| Error ID | Cause |
|
||||
| --- | --- |
|
||||
| `api.post.do_action.query.app_error` | The query parameters supplied with the action click exceeded one of the limits described in [Link syntax](#link-syntax) or [The `mm_blocks_actions` registry](#the-mm_blocks_actions-registry). |
|
||||
| `api.post.do_action.merge_query.app_error` | The server could not merge the supplied query parameters into the action's target URL — typically because the URL is malformed. |
|
||||
|
||||
## Security considerations
|
||||
|
||||
Markdown action buttons follow the same security model as message attachment actions:
|
||||
|
||||
- The action `url` is invoked server-to-server, never directly from the client.
|
||||
- `context` values are server-only and are not exposed to the rendering client.
|
||||
- Action IDs must match the pattern `[A-Za-z0-9_-]+` — alphanumerics, underscore, and hyphen — and are matched case-sensitively.
|
||||
- Action entries with malformed or unknown `type` values are rejected at post-create time and never reach the click-dispatch path.
|
||||
|
||||
## See also
|
||||
|
||||
- [Mattermost Blocks](/developers/integrate/reference/mm-blocks) — block-based buttons, menus, and layout.
|
||||
- [Interactive messages](/developers/integrate/plugins/interactive-messages) — overview and legacy attachment actions.
|
||||
- [Message attachments](/developers/integrate/reference/message-attachments) — broader message format reference.
|
||||
- [Incoming webhooks](/developers/integrate/webhooks/incoming) — submitting posts via webhooks.
|
||||
- [REST API: create post](https://api.mattermost.com/#operation/CreatePost)
|
||||
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 9.0 KiB |
|
After Width: | Height: | Size: 70 KiB |
|
After Width: | Height: | Size: 23 KiB |
|
After Width: | Height: | Size: 32 KiB |
|
After Width: | Height: | Size: 27 KiB |
|
After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 49 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 12 KiB |
196
docs/develop/integrate/reference/message-attachments/index.md
Normal file
@@ -0,0 +1,196 @@
|
||||
---
|
||||
title: "Use message attachments"
|
||||
description: "Message attachments provide rich formatting options for integrations, including bold and italic text, headings, inline images, and tables."
|
||||
sidebar_label: "Message attachments"
|
||||
sidebar_position: 40
|
||||
---
|
||||
|
||||
For additional formatting options, and for compatibility with Slack non-markdown integrations, an `attachments` array can be sent by integrations and rendered by Mattermost.
|
||||
|
||||
:::note[Legacy interactive content]
|
||||
For new integrations, prefer [Mattermost Blocks](/developers/integrate/reference/mm-blocks) over attachment `actions` for buttons and menus. Legacy attachments remain fully supported — Mattermost translates them into Mattermost Blocks at render time — but native Mattermost Blocks give you more layout control and a unified action registry in `props.mm_blocks_actions`.
|
||||
:::
|
||||
|
||||
You can also add interactive message buttons as part of attachments. They help make your integrations richer by completing common tasks inside Mattermost conversations, increasing user engagement and productivity. For more information, see [interactive messages](/developers/integrate/plugins/interactive-messages) and [Mattermost Blocks](/developers/integrate/reference/mm-blocks).
|
||||
|
||||
## Attachment options
|
||||
|
||||
When sending an attachment, you can use any of the following to format how you want the posted message to look.
|
||||
|
||||
`fallback`: A required plain-text summary of the attachment. This is used in notifications, and in clients that don’t support formatted text (e.g. IRC).
|
||||
|
||||
`color`: A hex color code that will be used as the left border color for the attachment. If not specified, it will default to match the channel sidebar header background color.
|
||||
|
||||

|
||||
|
||||
`pretext`: An optional line of text that will be shown above the attachment. Supports @mentions.
|
||||
|
||||

|
||||
|
||||
`text`: The text to be included in the attachment. It can be formatted using [Markdown](https://docs.mattermost.com/help/messaging/formatting-text.html). For long texts, the message is collapsed and a “Show More” link is added to expand the message. Supports @mentions.
|
||||
|
||||

|
||||
|
||||
### Author details
|
||||
|
||||
`author_name`: An optional name used to identify the author. It will be included in a small section at the top of the attachment.
|
||||
|
||||
`author_link`: An optional URL used to hyperlink the `author_name`. If no `author_name` is specified, this field does nothing.
|
||||
|
||||
`author_icon`: An optional URL used to display a 16x16 pixel icon beside the `author_name`.
|
||||
|
||||

|
||||
|
||||
### Titles
|
||||
|
||||
`title`: An optional title displayed below the author information in the attachment.
|
||||
|
||||
`title_link`: An optional URL used to hyperlink the `title`. If no `title` is specified, this field does nothing.
|
||||
|
||||

|
||||
|
||||
### Fields
|
||||
|
||||
Fields can be included as an optional array within `attachments`, and are used to display information in a table format inside the attachment.
|
||||
|
||||
`title`: A title shown in the table above the `value`. As of v5.14 a title will render emojis properly.
|
||||
|
||||
`value`: The text value of the field. It can be formatted using [Markdown](https://docs.mattermost.com/help/messaging/formatting-text.html). Supports @mentions.
|
||||
|
||||
`short`: Optionally set to true or false (boolean) to indicate whether the `value` is short enough to be displayed beside other values.
|
||||
|
||||

|
||||
|
||||
### Images
|
||||
|
||||
`image_url`: An optional URL to an image file (GIF, JPEG, PNG, BMP, or SVG) that is displayed inside a message attachment.
|
||||
|
||||
Large images are resized to a maximum width of 400px or a maximum height of 300px, while still maintaining the original aspect ratio.
|
||||
|
||||

|
||||
|
||||
`thumb_url`: An optional URL to an image file (GIF, JPEG, PNG, BMP, or SVG) that is displayed as a 75x75 pixel thumbnail on the right side of an attachment. We recommend using an image that is already 75x75 pixels, but larger images will be scaled down with the aspect ratio maintained.
|
||||
|
||||

|
||||
|
||||
## Example message attachment
|
||||
|
||||
Here is an example message attachment:
|
||||
|
||||
```json
|
||||
{
|
||||
"attachments": [
|
||||
{
|
||||
"fallback": "test",
|
||||
"color": "#FF8000",
|
||||
"pretext": "This is optional pretext that shows above the attachment.",
|
||||
"text": "This is the text of the attachment. It should appear just above an image of the Mattermost logo. The left border of the attachment should be colored orange, and below the image it should include additional fields that are formatted in columns. At the top of the attachment, there should be an author name followed by a bolded title. Both the author name and the title should be hyperlinks.",
|
||||
"author_name": "Mattermost",
|
||||
"author_icon": "https://mattermost.com/wp-content/uploads/2022/02/icon_WS.png",
|
||||
"author_link": "https://mattermost.org/",
|
||||
"title": "Example Attachment",
|
||||
"title_link": "https://developers.mattermost.com/integrate/reference/message-attachments/",
|
||||
"fields": [
|
||||
{
|
||||
"short":false,
|
||||
"title":"Long Field",
|
||||
"value":"Testing with a very long piece of text that will take up the whole width of the table. And then some more text to make it extra long."
|
||||
},
|
||||
{
|
||||
"short":true,
|
||||
"title":"Column One",
|
||||
"value":"Testing"
|
||||
},
|
||||
{
|
||||
"short":true,
|
||||
"title":"Column Two",
|
||||
"value":"Testing"
|
||||
},
|
||||
{
|
||||
"short":false,
|
||||
"title":"Another Field",
|
||||
"value":"Testing"
|
||||
}
|
||||
],
|
||||
"image_url": "https://mattermost.com/wp-content/uploads/2022/02/icon_WS.png"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
And here is how it renders in Mattermost:
|
||||
|
||||

|
||||
|
||||
### Footer
|
||||
|
||||
`footer`: An optional line of text that will be displayed at the bottom of the attachment. Footers with more than 300 characters will be truncated with an ellipsis (``…``).
|
||||
|
||||
`footer_icon`: An optional URL to an image file (GIF, JPEG, PNG, BMP, or SVG) that is displayed as a 16x16 pixel thumbnail before the footer text.
|
||||
|
||||

|
||||
|
||||
## Known issues
|
||||
|
||||
1. The footer timestamp field (`ts`) is not yet supported.
|
||||
2. Message Attachment contents do not show up in search.
|
||||
|
||||
## Trigger AI agent responses
|
||||
|
||||
To have Mattermost AI agents respond to a post created by a bot or plugin integration, set the `activate_ai` property to `"true"` in the post's `props` field.
|
||||
|
||||
```json
|
||||
{
|
||||
"channel_id": "qmd5oqtwoibz8cuzxzg5ekshgr",
|
||||
"message": "Summarize the latest deployment status.",
|
||||
"props": {
|
||||
"activate_ai": "true"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Frequently asked questions
|
||||
|
||||
### Can I send a message attachment via the API?
|
||||
|
||||
Yes, you can use the [create post RESTful API](https://api.mattermost.com/#operation/CreatePost).
|
||||
|
||||
You need to add an `attachments` key to the post's `props` JSON field. The value is an array of message attachments you want attached to the post. See below for an example curl command.
|
||||
|
||||
For new interactive content, prefer `props.mm_blocks` and `props.mm_blocks_actions` instead. See [Mattermost Blocks](/developers/integrate/reference/mm-blocks).
|
||||
|
||||
`curl -i -X POST -H 'Content-Type: application/json' -d '{"channel_id":"qmd5oqtwoibz8cuzxzg5ekshgr", "message":"Test message #testing", "props":{"attachments": [{"pretext": "This is the attachment pretext.","text": "This is the attachment text."}]}}' https://{your-mattermost-site}/api/v4/posts`
|
||||
|
||||
Below is an example HTTP request:
|
||||
|
||||
```http request
|
||||
POST /api/v4/posts HTTP/1.1
|
||||
Host: {your-mattermost-site}
|
||||
User-Agent: curl/7.63.0
|
||||
Accept: */*
|
||||
Content-Type: application/json
|
||||
Content-Length: 192
|
||||
|
||||
{"channel_id":"qmd5oqtwoibz8cuzxzg5ekshgr", "message":"Test message #testing", "props":{"attachments": [{"pretext": "This is the attachment pretext.","text": "This is the attachment text."}]}}
|
||||
```
|
||||
|
||||
### Can I post a message attachment using a webhook?
|
||||
|
||||
Yes, you can also use an [incoming webhook](/developers/integrate/webhooks/incoming) to post a message attachment.
|
||||
|
||||
You need to add an `attachments` key to the post's JSON. The value is an array of message attachments you want attached to the post. See below for an example curl command.
|
||||
|
||||
`curl -i -X POST -H 'Content-Type: application/json' -d '{"text":"Test message #testing", "attachments": [{"pretext": "This is the attachment pretext.","text": "This is the attachment text."}]}' https://{your-mattermost-site}/hooks/{your-webhook-id}`
|
||||
|
||||
Below is an example HTTP request:
|
||||
|
||||
```http request
|
||||
POST /hooks/{your-webhook-id} HTTP/1.1
|
||||
Host: {your-mattermost-site}
|
||||
User-Agent: curl/7.63.0
|
||||
Accept: */*
|
||||
Content-Type: application/json
|
||||
Content-Length: 192
|
||||
|
||||
{"text":"Test message #testing", "attachments": [{"pretext": "This is the attachment pretext.","text": "This is the attachment text."}]}
|
||||
```
|
||||
52
docs/develop/integrate/reference/message-priority/index.md
Normal file
@@ -0,0 +1,52 @@
|
||||
---
|
||||
title: "Use message priority"
|
||||
description: "Set message priority levels so users can identify important messages and optionally request acknowledgments or persistent notifications."
|
||||
sidebar_label: "Message priority"
|
||||
sidebar_position: 50
|
||||
---
|
||||
|
||||
Messages can be sent with a priority level to help users identify the importance of the message. For more information about message priority, see [formatting text](https://docs.mattermost.com/collaborate/message-priority.html).
|
||||
|
||||
## Priority options
|
||||
|
||||
When sending a message, you can use any of the following to format how you want the posted message to look.
|
||||
|
||||
`priority`: A required plain-text summary of the message. This is used in notifications, and in clients that don’t support formatted text (e.g. IRC).
|
||||
|
||||
`requested_ack`: If set to `true`, the message will be marked as requiring an acknowledgment from the users by displaying a checkmark icon next to the message. Keep in mind that this requires the message priority to be set to _Important_ or _Urgent_.
|
||||
|
||||
`persistent_notifications`: Only for _Urgent_ messages. If set to `true` recipients will receive a persistent notification every five minutes until they acknowledge the message. Mutually exclusive with the [`silent`](/developers/integrate/webhooks/incoming#parameters) field on incoming webhooks — a post cannot be both persistent and silent.
|
||||
|
||||
## Example of post priority
|
||||
|
||||
```json
|
||||
{
|
||||
"priority": {
|
||||
"priority": "urgent",
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
And this is how it renders on Mattermost:
|
||||
|
||||

|
||||
|
||||
## Example of post priority with requested acknowledgment
|
||||
|
||||
```json
|
||||
{
|
||||
"priority": {
|
||||
"priority": "important",
|
||||
"requested_ack": true
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
And this is how it renders on Mattermost:
|
||||
|
||||

|
||||
|
||||
## Related documentation
|
||||
|
||||
- [Message priority](https://docs.mattermost.com/collaborate/message-priority.html)
|
||||
- [CreatePost API](https://api.mattermost.com/#operation/CreatePost)
|
||||
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 11 KiB |
496
docs/develop/integrate/reference/mm-blocks/index.md
Normal file
@@ -0,0 +1,496 @@
|
||||
---
|
||||
title: "Mattermost Blocks"
|
||||
description: "Mattermost Blocks are the canonical format for structured, interactive integration posts. Use props.mm_blocks for layout and controls, and props.mm_blocks_actions for server-side action dispatch."
|
||||
sidebar_label: "Mattermost Blocks"
|
||||
sidebar_position: 42
|
||||
---
|
||||
|
||||
Mattermost Blocks are the structured post format for integration messages. An integration sends a block tree in `props.mm_blocks` to define layout, text, images, buttons, and menus, and registers action handlers in `props.mm_blocks_actions` so the server can dispatch clicks and menu selections back to the integration.
|
||||
|
||||
:::note[Feature flag]
|
||||
Mattermost Blocks are controlled by the `MmBlocksEnabled` feature flag (enabled by default). When disabled, Mattermost Blocks payloads are not rendered and Mattermost Blocks action cookies are rejected.
|
||||
:::
|
||||
|
||||
## How it works
|
||||
|
||||
An interactive Mattermost Blocks post has two parts:
|
||||
|
||||
1. **`props.mm_blocks`** — an array of block objects that define layout, text, images, buttons, and menus. A post may contain up to 100 blocks in total, counting nested blocks throughout the tree.
|
||||
2. **`props.mm_blocks_actions`** — a map keyed by action ID. Each entry tells the server what to do when a user clicks a button, selects a menu option, or activates a [markdown action button](/developers/integrate/reference/markdown-actions).
|
||||
|
||||
When the post is stored, the server validates that every referenced action ID has a matching registry entry (and no unused entries remain). It then encrypts the action registry into an opaque cookie string that clients send back when dispatching actions.
|
||||
|
||||
## Example post payload
|
||||
|
||||
The following payload posts a message with text, a primary button, and a static select menu:
|
||||
|
||||
```json
|
||||
{
|
||||
"channel_id": "qmd5oqtwoibz8cuzxzg5ekshgr",
|
||||
"message": "Deployment #42 finished.",
|
||||
"props": {
|
||||
"mm_blocks": [
|
||||
{
|
||||
"type": "text",
|
||||
"text": "Deployed `main` to **staging**. Choose a follow-up action:"
|
||||
},
|
||||
{
|
||||
"type": "container",
|
||||
"flow": "horizontal",
|
||||
"gap": "small",
|
||||
"content": [
|
||||
{
|
||||
"type": "button",
|
||||
"text": "View logs",
|
||||
"style": "primary",
|
||||
"action_id": "view_logs"
|
||||
},
|
||||
{
|
||||
"type": "button",
|
||||
"text": "Rollback",
|
||||
"style": "danger",
|
||||
"action_id": "rollback"
|
||||
},
|
||||
{
|
||||
"type": "static_select",
|
||||
"action_id": "next_step",
|
||||
"placeholder": "Select next step…",
|
||||
"options": [
|
||||
{"text": "Promote to production", "value": "promote"},
|
||||
{"text": "Run smoke tests", "value": "smoke"}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"mm_blocks_actions": {
|
||||
"view_logs": {
|
||||
"type": "external",
|
||||
"url": "https://integration.example.com/actions/view-logs",
|
||||
"context": {"deployment_id": "42"}
|
||||
},
|
||||
"rollback": {
|
||||
"type": "external",
|
||||
"url": "https://integration.example.com/actions/rollback",
|
||||
"context": {"deployment_id": "42"}
|
||||
},
|
||||
"next_step": {
|
||||
"type": "external",
|
||||
"url": "https://integration.example.com/actions/next-step",
|
||||
"context": {"deployment_id": "42"}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
You can send this payload using the [create post REST API](https://api.mattermost.com/#operation/CreatePost), an [incoming webhook](/developers/integrate/webhooks/incoming), a [custom slash command](/developers/integrate/slash-commands/custom), or from a [plugin](/developers/integrate/plugins/components/server).
|
||||
|
||||
### Submit using an incoming webhook
|
||||
|
||||
```bash
|
||||
curl -X POST $MM_URL/hooks/$WEBHOOK_ID \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"text": "Deployment #42 finished.",
|
||||
"props": {
|
||||
"mm_blocks": [
|
||||
{"type": "text", "text": "Deployed `main` to **staging**."},
|
||||
{
|
||||
"type": "button",
|
||||
"text": "View logs",
|
||||
"style": "primary",
|
||||
"action_id": "view_logs"
|
||||
}
|
||||
],
|
||||
"mm_blocks_actions": {
|
||||
"view_logs": {
|
||||
"type": "external",
|
||||
"url": "https://integration.example.com/actions/view-logs",
|
||||
"context": {"deployment_id": "42"}
|
||||
}
|
||||
}
|
||||
}
|
||||
}'
|
||||
```
|
||||
|
||||
For webhook payloads, place `mm_blocks` and `mm_blocks_actions` inside `props`. The top-level `attachments` array remains available for legacy integrations.
|
||||
|
||||
### Submit from a plugin
|
||||
|
||||
```golang
|
||||
post := &model.Post{
|
||||
ChannelId: channelID,
|
||||
UserId: p.botID,
|
||||
Message: "Deployment #42 finished.",
|
||||
Props: model.StringInterface{
|
||||
"mm_blocks": []any{
|
||||
map[string]any{
|
||||
"type": "text",
|
||||
"text": "Deployed `main` to **staging**.",
|
||||
},
|
||||
map[string]any{
|
||||
"type": "button",
|
||||
"text": "View logs",
|
||||
"style": "primary",
|
||||
"action_id": "view_logs",
|
||||
},
|
||||
},
|
||||
"mm_blocks_actions": map[string]any{
|
||||
"view_logs": map[string]any{
|
||||
"type": "external",
|
||||
"url": fmt.Sprintf("/plugins/%s/actions/view-logs", manifest.Id),
|
||||
"context": map[string]any{"deployment_id": "42"},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
_, err := p.API.CreatePost(post)
|
||||
```
|
||||
|
||||
## Block types
|
||||
|
||||
Each element of `props.mm_blocks` is an object with a required `type` field. The supported block types are:
|
||||
|
||||
| Type | Purpose |
|
||||
| --- | --- |
|
||||
| [`text`](#text) | Markdown-formatted text |
|
||||
| [`image`](#image) | Remote image with optional sizing and alignment |
|
||||
| [`divider`](#divider) | Horizontal rule between blocks |
|
||||
| [`button`](#button) | Interactive button |
|
||||
| [`static_select`](#static-select) | Dropdown menu with static options or dynamic data sources |
|
||||
| [`container`](#container) | Groups blocks with optional border, accent bar, background, and layout flow |
|
||||
| [`collapsible`](#collapsible) | Expandable section with separate header and content block arrays |
|
||||
| [`column_set`](#column-set-and-column) | Horizontal row of columns |
|
||||
| [`column`](#column-set-and-column) | Column inside a `column_set` (not valid as a top-level block) |
|
||||
|
||||
Nested layout blocks (`container`, `collapsible`, `column_set`, and `column`) may nest up to 32 levels deep.
|
||||
|
||||
Malformed blocks are omitted at render time; valid sibling blocks still display.
|
||||
|
||||
### Text
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "text",
|
||||
"text": "Hello **from** Mattermost Blocks.",
|
||||
"is_subtle": false,
|
||||
"size": "default"
|
||||
}
|
||||
```
|
||||
|
||||
| Field | Required | Description |
|
||||
| --- | --- | --- |
|
||||
| `text` | yes | Markdown-formatted content. Supports @mentions. All `text` and [button](#button) `text` fields in a post share a combined limit of 16,000 characters. |
|
||||
| `is_subtle` | no | When `true`, renders in a muted color. Does not change font size. |
|
||||
| `size` | no | Typography scale: `small` or `default`. Omitted is equivalent to `default`. |
|
||||
|
||||
### Image
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "image",
|
||||
"url": "https://example.com/logo.png",
|
||||
"alt_text": "Company logo",
|
||||
"title": "Logo",
|
||||
"size": "medium",
|
||||
"max_width": 400,
|
||||
"max_height": 300,
|
||||
"image_style": "default",
|
||||
"horizontal_alignment": "center"
|
||||
}
|
||||
```
|
||||
|
||||
| Field | Required | Description |
|
||||
| --- | --- | --- |
|
||||
| `url` | yes | Image URL (GIF, JPEG, PNG, BMP, or SVG). |
|
||||
| `alt_text` | no | Accessible description. |
|
||||
| `title` | no | Plain-text tooltip shown on hover. |
|
||||
| `size` | no | Preset sizing: `auto`, `xsmall`, `small`, `medium`, `large`, or `stretch`. Defaults to `stretch`. |
|
||||
| `max_width` | no | Maximum width in pixels. |
|
||||
| `max_height` | no | Maximum height in pixels. |
|
||||
| `image_style` | no | `default` or `person` (avatar-style crop). |
|
||||
| `horizontal_alignment` | no | `left`, `center`, or `right`. |
|
||||
|
||||
### Divider
|
||||
|
||||
```json
|
||||
{"type": "divider"}
|
||||
```
|
||||
|
||||
### Button
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "button",
|
||||
"text": "Approve",
|
||||
"action_id": "approve",
|
||||
"style": "primary",
|
||||
"tooltip": "Approve this change",
|
||||
"disabled": false,
|
||||
"query": {"ticket": "ISS-101"}
|
||||
}
|
||||
```
|
||||
|
||||
| Field | Required | Description |
|
||||
| --- | --- | --- |
|
||||
| `text` | yes | Button label. Supports Markdown. Counts toward the combined 16,000-character limit for [text](#text) and button blocks. |
|
||||
| `action_id` | yes | Must match a key in `mm_blocks_actions`. |
|
||||
| `style` | no | Semantic color: `default`, `primary`, `danger`, `good`, `success`, or `warning`. Hex colors such as `#2d81ff` are also accepted. |
|
||||
| `tooltip` | no | Help text shown on hover. |
|
||||
| `disabled` | no | When `true`, the button renders but cannot be clicked. |
|
||||
| `query` | no | Static query parameters merged into the action URL when clicked. Up to 50 entries; each key may be up to 128 characters and each value up to 2048 characters. |
|
||||
|
||||
### Static select
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "static_select",
|
||||
"action_id": "pick_region",
|
||||
"placeholder": "Pick a region",
|
||||
"options": [
|
||||
{"text": "North", "value": "north"},
|
||||
{"text": "South", "value": "south"}
|
||||
],
|
||||
"initial_option": "north",
|
||||
"disabled": false,
|
||||
"data_source": "channels"
|
||||
}
|
||||
```
|
||||
|
||||
| Field | Required | Description |
|
||||
| --- | --- | --- |
|
||||
| `action_id` | yes | Must match a key in `mm_blocks_actions`. |
|
||||
| `placeholder` | yes | Placeholder text for the menu. |
|
||||
| `options` | depends on | Array of `{text, value}` pairs. Required unless `data_source` is set. |
|
||||
| `initial_option` | no | Pre-selected option value. |
|
||||
| `disabled` | no | When `true`, the menu renders but cannot be used. |
|
||||
| `data_source` | no | Dynamic option source: `channels` or `users`. When set, `options` is optional. Users can only select public channels in their teams. |
|
||||
|
||||
When a user selects an option, the integration callback receives `selected_option` in the request `context` with the chosen value (or user/channel ID for dynamic data sources).
|
||||
|
||||
### Container
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "container",
|
||||
"content": [
|
||||
{"type": "text", "text": "Container title"},
|
||||
{"type": "divider"},
|
||||
{"type": "text", "text": "Body copy", "is_subtle": true, "size": "small"}
|
||||
],
|
||||
"border": true,
|
||||
"accent_color": "primary",
|
||||
"background": "gray",
|
||||
"flow": "vertical",
|
||||
"gap": "small",
|
||||
"max_height": "medium"
|
||||
}
|
||||
```
|
||||
|
||||
| Field | Required | Description |
|
||||
| --- | --- | --- |
|
||||
| `content` | yes | Array of nested blocks. |
|
||||
| `border` | no | When `true`, draws a border around the container. |
|
||||
| `accent_color` | no | Left accent bar color. Semantic values: `default`, `primary`, `good`, `warning`, or `danger`. CSS colors such as `#439FE0` are also accepted. |
|
||||
| `background` | no | `none` (default) or `gray`. |
|
||||
| `flow` | no | Child layout direction: `horizontal` or `vertical`. Defaults to `vertical`. |
|
||||
| `gap` | no | Spacing between children: `none`, `small`, `medium`, `large`, or `xlarge`. Defaults to `none`. |
|
||||
| `max_height` | no | Maximum height preset: `none`, `small`, `medium`, or `large`. Overflowing content scrolls inside the container. On mobile, users can open scrollable content in a dedicated full-screen view. |
|
||||
|
||||
### Collapsible
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "collapsible",
|
||||
"collapsed": false,
|
||||
"header": [
|
||||
{"type": "text", "text": "**Details**"}
|
||||
],
|
||||
"content": [
|
||||
{"type": "text", "text": "Expanded content goes here."}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
| Field | Required | Description |
|
||||
| --- | --- | --- |
|
||||
| `header` | yes | Blocks shown in the always-visible header row. |
|
||||
| `content` | yes | Blocks shown when expanded. |
|
||||
| `collapsed` | no | Initial collapsed state. Defaults to `false`. |
|
||||
|
||||
### Column set and column
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "column_set",
|
||||
"gap": "medium",
|
||||
"columns": [
|
||||
{
|
||||
"type": "column",
|
||||
"width": "stretch",
|
||||
"gap": "small",
|
||||
"items": [
|
||||
{"type": "text", "text": "Left column"}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "column",
|
||||
"width": "auto",
|
||||
"items": [
|
||||
{"type": "text", "text": "Right column"}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
`column` blocks are only valid inside a `column_set`. Each column has an `items` array of nested blocks.
|
||||
|
||||
## The `mm_blocks_actions` registry
|
||||
|
||||
The `mm_blocks_actions` post prop is a map keyed by action ID. Each entry describes how the server handles clicks on that action. The registry supports up to 50 action entries. Each action ID must match `[A-Za-z0-9_-]+`, may be up to 64 characters long, and is matched case-sensitively.
|
||||
|
||||
```json
|
||||
{
|
||||
"mm_blocks_actions": {
|
||||
"<action_id>": {
|
||||
"type": "<action_type>",
|
||||
"url": "...",
|
||||
"context": { ... },
|
||||
"query": { ... }
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
| Field | Required | Description |
|
||||
| --- | --- | --- |
|
||||
| `type` | yes | Action type. See [Action types](#action-types) below. |
|
||||
| `url` | depends on type | Target URL. Required for `external` and `openURL`. |
|
||||
| `context` | no | Server-side context forwarded to the integration in the post-action request body. Not visible to clients. Up to 50 entries; each key may be up to 128 characters. |
|
||||
| `query` | no | Static `string → string` map merged into the target URL's query string. Combined with any per-control `query` on the block — block values win on key conflict. Up to 50 entries; each key may be up to 128 characters and each value up to 2048 characters. |
|
||||
|
||||
Every action ID referenced by interactive content — Mattermost Blocks controls, markdown `mmaction://` links, Block Kit actions, or Adaptive Card actions — must have a matching registry entry. Unused registry entries are rejected at post-create time.
|
||||
|
||||
After the post is stored, clients receive an encrypted cookie string in place of the plaintext registry map.
|
||||
|
||||
### Action types
|
||||
|
||||
| Type | Behavior |
|
||||
| --- | --- |
|
||||
| `external` | The server sends an HTTP POST request to `url` with the standard post-action request body. The integration responds with a post-action response (update, ephemeral message, or navigation). Relative plugin paths such as `/plugins/myplugin/action` are supported. |
|
||||
| `openURL` | Navigates the user without calling an integration. Relative paths (for example `/myteam/channels/off-topic`) navigate inside Mattermost. `http://` and `https://` URLs open in a new browser tab. Plugin paths are not allowed. |
|
||||
|
||||
Additional action types may be introduced in future releases. Entries with an unknown `type` value are rejected at post-create time.
|
||||
|
||||
## Action dispatch flow
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant Integration
|
||||
participant Server as Mattermost server
|
||||
participant Client
|
||||
Integration->>Server: Create post (mm_blocks + mm_blocks_actions)
|
||||
Server->>Server: Validate and encrypt action registry
|
||||
Server->>Client: Store and deliver post
|
||||
Client->>Client: Render blocks
|
||||
Client->>Server: POST /api/v4/posts/{id}/actions/{action_id}
|
||||
alt openURL
|
||||
Server->>Client: Navigate user
|
||||
else external
|
||||
Server->>Integration: POST action callback
|
||||
Integration->>Server: Post-action response
|
||||
Server->>Client: Update post / ephemeral message
|
||||
end
|
||||
```
|
||||
|
||||
1. **Integration** creates a post with `mm_blocks` controls and matching `mm_blocks_actions` entries.
|
||||
2. **Mattermost server** validates the pairing, encrypts the action registry, and stores the post.
|
||||
3. **Client** renders the blocks. When the user clicks a button or selects a menu option, the client sends `POST /api/v4/posts/{post_id}/actions/{action_id}` with the encrypted cookie, optional `query`, `selected_option` (for menus), and `integration_format: "mm_block"`.
|
||||
4. **Mattermost server** decrypts the cookie, resolves the action, merges query parameters, and either navigates (`openURL`) or POSTs to the integration endpoint (`external`).
|
||||
5. **Integration** responds with a standard post-action response.
|
||||
|
||||
Action IDs in the URL path must match `[A-Za-z0-9_-]+`.
|
||||
|
||||
## Receiving action callbacks
|
||||
|
||||
When a user activates an `external` action, the Mattermost server sends an HTTP POST request to the configured `url`. The request body uses the same `PostActionIntegrationRequest` shape as [legacy message attachment](/developers/integrate/reference/message-attachments) buttons:
|
||||
|
||||
```json
|
||||
{
|
||||
"user_id": "rd49ehbqyjytddasoownkuqrxe",
|
||||
"user_name": "alice",
|
||||
"channel_id": "j6j53p28k6urx15fpcgsr20psq",
|
||||
"channel_name": "town-square",
|
||||
"team_id": "5xxzt146eax4tul69409opqjlf",
|
||||
"team_domain": "myteam",
|
||||
"post_id": "gqrnh3675jfxzftnjyjfe4udeh",
|
||||
"trigger_id": "...",
|
||||
"type": "button",
|
||||
"context": {
|
||||
"deployment_id": "42",
|
||||
"selected_option": "promote"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
For static select menus, the selected value is added to `context.selected_option`.
|
||||
|
||||
Integrations respond with the same post-action response format used by attachment actions:
|
||||
|
||||
```json
|
||||
{
|
||||
"update": {
|
||||
"message": "Updated!",
|
||||
"props": {
|
||||
"mm_blocks": [
|
||||
{"type": "text", "text": "Deployment promoted to production."}
|
||||
]
|
||||
}
|
||||
},
|
||||
"ephemeral_text": "Promotion started.",
|
||||
"goto_location": "/myteam/channels/releases"
|
||||
}
|
||||
```
|
||||
|
||||
| Response field | Description |
|
||||
| --- | --- |
|
||||
| `update` | Replaces the original post message and props. Use `update.props.mm_blocks` to refresh the block layout. |
|
||||
| `ephemeral_text` | Sends a private message visible only to the user who clicked. |
|
||||
| `goto_location` | Navigates the user to a URL after the action completes. Supports in-app paths and external URLs. |
|
||||
| `error` | Returns a custom error message displayed below the interactive content. |
|
||||
| `skip_slack_parsing` | Set to `true` to bypass Slack-compatibility parsing of `ephemeral_text`. |
|
||||
|
||||
See [interactive messages](/developers/integrate/plugins/interactive-messages) for error handling details and `update.props` semantics.
|
||||
|
||||
## Legacy format compatibility
|
||||
|
||||
Mattermost continues to accept these older payload formats:
|
||||
|
||||
| Prop | Format | Notes |
|
||||
| --- | --- | --- |
|
||||
| `attachments` | Legacy [message attachments](/developers/integrate/reference/message-attachments) | Attachment `actions` arrays are translated into Mattermost Blocks buttons and selects at render time. |
|
||||
| `blocks` | Slack Block Kit | Translated into Mattermost Blocks. Interactive Block Kit elements require matching `mm_blocks_actions` entries keyed by `action_id`. |
|
||||
| `cards` | Microsoft Adaptive Cards | Translated into Mattermost Blocks. Interactive card actions require matching `mm_blocks_actions` entries keyed by action `id`. |
|
||||
|
||||
New integrations should prefer native `mm_blocks` for full control over layout and action registration.
|
||||
|
||||
## Security considerations
|
||||
|
||||
Mattermost Blocks follow the same security model as legacy interactive messages:
|
||||
|
||||
- Integration `url` values are invoked server-to-server, never directly from the client.
|
||||
- `context` values are server-only and are not exposed to rendering clients.
|
||||
- After create, the plaintext `mm_blocks_actions` map is replaced with an encrypted cookie.
|
||||
- Action IDs are validated and must match referenced interactive content exactly.
|
||||
- `openURL` actions reject plugin paths and path-traversal segments.
|
||||
|
||||
## See also
|
||||
|
||||
- [Troubleshoot Mattermost Blocks](/developers/integrate/reference/mm-blocks/troubleshooting) — common rendering, action, and mobile issues.
|
||||
- [Interactive messages](/developers/integrate/plugins/interactive-messages) — overview, error handling, and legacy attachment actions.
|
||||
- [Markdown action buttons](/developers/integrate/reference/markdown-actions) — inline `mmaction://` links using the same action registry.
|
||||
- [Message attachments](/developers/integrate/reference/message-attachments) — legacy attachment format reference.
|
||||
- [Incoming webhooks](/developers/integrate/webhooks/incoming) — submitting posts via webhooks.
|
||||
- [REST API: create post](https://api.mattermost.com/#operation/CreatePost)
|
||||
@@ -0,0 +1,88 @@
|
||||
---
|
||||
title: "Troubleshoot Mattermost Blocks"
|
||||
description: "Common issues when Mattermost Blocks posts do not render or respond as expected, with guidance for integration developers and mobile client behavior."
|
||||
sidebar_label: "Troubleshoot Mattermost Blocks"
|
||||
sidebar_position: 43
|
||||
---
|
||||
|
||||
Integration posts that use Mattermost Blocks show structured content—including text, images, buttons, and menus—directly in a channel. This page covers common issues when Mattermost Blocks do not render or respond as expected. Use it alongside the [Mattermost Blocks reference](/developers/integrate/reference/mm-blocks) when debugging payloads, action handlers, and client rendering.
|
||||
|
||||
## Mattermost Blocks content does not appear
|
||||
|
||||
**Symptoms:** A post shows only plain text (or no content) and the expected buttons, images, or content blocks are missing.
|
||||
|
||||
**Try the following:**
|
||||
|
||||
1. **Confirm the integration payload.** The post must include a non-empty `props.mm_blocks` array (or a legacy format such as [message attachments](/developers/integrate/reference/message-attachments) that the client translates). Verify the webhook, bot, plugin, or REST API payload before testing in a client.
|
||||
2. **Check the feature flag (self-hosted admins).** Mattermost Blocks are controlled by the `MmBlocksEnabled` feature flag (enabled by default). Self-hosted deployments can disable Mattermost Blocks by setting `MM_FEATUREFLAGS_MMBLOCKSENABLED=false`. When disabled, native Mattermost Blocks payloads are not rendered and their actions are rejected.
|
||||
3. **Update the client.** Mattermost Blocks require a current Mattermost web, desktop, or mobile app. See [client availability](https://docs.mattermost.com/end-user-guide/access/client-availability.html) in the product documentation for platform support.
|
||||
4. **Reload the channel.** Pull to refresh on mobile, or switch channels and return, to fetch the latest post data.
|
||||
|
||||
## Buttons or menus do not respond
|
||||
|
||||
**Symptoms:** Buttons appear disabled, or tapping a button or menu option has no effect.
|
||||
|
||||
**Try the following:**
|
||||
|
||||
1. **Validate the action registry.** Every `action_id` on a button, `static_select`, or markdown action must have a matching entry in `props.mm_blocks_actions`. Unused registry entries and unreferenced action IDs are rejected at post-create time. See [The `mm_blocks_actions` registry](/developers/integrate/reference/mm-blocks#the-mm_blocks_actions-registry).
|
||||
2. **Wait for the action to finish.** Some integrations show a loading state while Mattermost calls an external service. Slow integrations may time out based on your server's [integration request timeout](https://docs.mattermost.com/configure/configuration-settings.html#integration-request-timeout) setting.
|
||||
3. **Check whether the control is disabled.** Integrations can send buttons and menus with `"disabled": true`. Disabled controls cannot be activated.
|
||||
4. **Verify outbound server connectivity.** External actions require Mattermost **server nodes** (not end-user devices) to make **outbound** requests to each integration action endpoint URL configured in the post. These endpoints typically use **HTTPS on TCP port 443**; if a URL uses another scheme or port, that destination must be reachable outbound from the server. Allow only the specific integration endpoints your organization uses—this is not an inbound connection requirement. For server-side 400 errors, see [Why does an interactive button or menu return a 400 error?](/developers/integrate/plugins/interactive-messages#why-does-an-interactive-button-or-menu-return-a-400-error).
|
||||
5. **Look for follow-up messages.** Successful actions may update the original post or return an ephemeral reply visible only to the user who clicked. Check the thread panel if the post is part of a thread.
|
||||
|
||||
## Scrollable content issues on mobile
|
||||
|
||||
**Symptoms:** Clipped integration content cannot be expanded, or the **Scrollable content** screen is empty.
|
||||
|
||||
Some integration posts limit the height of a content region using a container `max_height` value. When content overflows, Mattermost mobile shows a clipped preview with an expand control in the corner of the region.
|
||||
|
||||
**To view the full content on mobile:**
|
||||
|
||||
1. Locate the clipped region in the post (a fade at the bottom indicates more content below).
|
||||
2. Select the expand control in the bottom-right corner of the clipped area.
|
||||
3. Mattermost opens a full-screen **Scrollable content** view where you can scroll through the complete block content.
|
||||
4. Use the back gesture or navigation control to return to the channel.
|
||||
|
||||
**If the Scrollable content screen shows "Cannot display content":**
|
||||
|
||||
- Return to the channel and open the expand control again. This screen appears when the expanded payload is no longer available (for example, after navigating away before the view loaded).
|
||||
- Update to the latest mobile app build if the issue persists across multiple posts.
|
||||
|
||||
On web and desktop, the same clipped regions scroll inside the post; a separate full-screen view is not used.
|
||||
|
||||
## Collapsible sections or images look wrong
|
||||
|
||||
**Symptoms:** A section will not expand, an image fails to load, or part of the layout is missing.
|
||||
|
||||
**Try the following:**
|
||||
|
||||
1. **Collapsible sections:** Select the section header to toggle between expanded and collapsed states. If the header is missing or empty, the integration payload may be incomplete. Both `header` and `content` arrays are required on `collapsible` blocks.
|
||||
2. **Images:** External images require a valid URL and may be blocked by your server's image proxy or SVG settings. Contact your system admin if images from other integrations load but Mattermost Blocks images do not.
|
||||
3. **Partial content:** Clients skip individual malformed blocks and still render valid ones in the same post. If only some elements are missing, the integration payload likely contains invalid block entries. Compare the payload against the [block types](/developers/integrate/reference/mm-blocks#block-types) reference.
|
||||
|
||||
## Not all blocks appear or text is cut off
|
||||
|
||||
**Symptoms:** Only part of an integration post renders, blocks at the end of the post are missing, or text in a block or on a button label ends abruptly.
|
||||
|
||||
Mattermost enforces size limits on Mattermost Blocks payloads. Content that exceeds a limit is truncated when the post is rendered.
|
||||
|
||||
**Try the following:**
|
||||
|
||||
1. **Review payload limits.** A single post is limited to:
|
||||
- **100 blocks** in the `props.mm_blocks` array
|
||||
- **32 levels** of nesting depth across nested block structures
|
||||
- **16,000 characters** total across all text in the payload, including text blocks and button labels
|
||||
2. **Reduce payload size.** Split long content across multiple posts, shorten labels, flatten deeply nested structures, or remove optional blocks.
|
||||
3. **Validate after content changes.** If truncation appears only for certain posts or started after an integration update, compare the payload against these limits.
|
||||
|
||||
## Legacy message attachments
|
||||
|
||||
Older integrations that use [message attachments](/developers/integrate/reference/message-attachments) are translated into the Mattermost Blocks UI at render time. Button and menu behavior should match native Mattermost Blocks posts. If an attachment-based post behaves differently from a native Mattermost Blocks post, compare the attachment `actions` array and callback URLs against an equivalent `mm_blocks` payload.
|
||||
|
||||
## Get more help
|
||||
|
||||
- **Payload format and actions:** See the [Mattermost Blocks reference](/developers/integrate/reference/mm-blocks) for block schema, action types, and migration guidance.
|
||||
- **Interactive message errors:** See [interactive messages](/developers/integrate/plugins/interactive-messages) for post-action responses, error handling, and legacy attachment actions.
|
||||
- **Mobile deployment issues:** See [mobile deployment troubleshooting](https://docs.mattermost.com/deploy/mobile-troubleshoot.html) for connectivity, push notification, and app install problems unrelated to Mattermost Blocks content.
|
||||
|
||||
If you continue to experience issues, visit the [Mattermost Troubleshooting forum](https://forum.mattermost.com/c/trouble-shoot/16) or contact your system administrator.
|
||||
|
After Width: | Height: | Size: 51 KiB |
|
After Width: | Height: | Size: 36 KiB |
|
After Width: | Height: | Size: 20 KiB |
|
After Width: | Height: | Size: 70 KiB |
|
After Width: | Height: | Size: 49 KiB |
|
After Width: | Height: | Size: 29 KiB |
|
After Width: | Height: | Size: 57 KiB |
|
After Width: | Height: | Size: 50 KiB |
@@ -0,0 +1,88 @@
|
||||
---
|
||||
title: "Personal access tokens"
|
||||
sidebar_position: 20
|
||||
---
|
||||
Personal access tokens function similar to session tokens and can be used by integrations to [authenticate against the REST API.](https://api.mattermost.com/#tag/authentication) It is the most commonly used type of token for integrations.
|
||||
|
||||
## Create a personal access token
|
||||
|
||||
1. Enable personal access tokens in **System Console > Integrations > Integration Management**.
|
||||
|
||||

|
||||
|
||||
2. Identify the account you want to create a personal access token with. You may optionally create a new user account for your integration, such as for a bot account. By default, only System Admins have permissions to create a personal access token.
|
||||
3. To create an access token with a non-admin account, you must first give it the appropriate permissions. Go to **System Console > User Management > Users**, search for the user account, then select **Manage Roles** from the dropdown.
|
||||
|
||||

|
||||
|
||||
4. Select **Allow this account to generate personal access tokens.**
|
||||
|
||||

|
||||
|
||||
```text
|
||||
You may optionally allow the account to post to any channel in your Mattermost server, including direct messages by choosing the **post:all** role. **post:channels** role allows the account to post to any public channel in the Mattermost server.
|
||||
|
||||
Then select **Save**.
|
||||
```
|
||||
|
||||
5. Sign in to the user account to create a personal access token.
|
||||
6. Go to **Profile > Security > Personal Access Tokens**, then select **Create Token**.
|
||||
|
||||

|
||||
|
||||
7. Enter a description for the token, so you remember what it's used for. Then select **Save**.
|
||||
|
||||

|
||||
|
||||
|
||||
<Note title="Note">
|
||||
If you create a personal access token for a System Admin account, be extra careful who you share it with. The token enables a user to have full access to the account, including System Admin privileges. It's recommended to create a personal access token for non-admin accounts.
|
||||
</Note>
|
||||
|
||||
|
||||
8. Copy the access token now for your integration and store it in a secure location. You won't be able to see it again!
|
||||
9. You're all set! You can now use the personal access token for integrations to interact with your Mattermost server and [authenticate against the REST API](https://api.mattermost.com/#tag/authentication).
|
||||
|
||||

|
||||
|
||||
## Revoke a personal access token
|
||||
|
||||
A personal access token can be revoked by deleting the token from either the user's profile settings or from the System Console. Once deleted, all sessions using the token are deleted, and any attempts to use the token to interact with the Mattermost server are blocked.
|
||||
|
||||
Tokens can also be temporarily deactivated from the user's profile. Once deactivated, all sessions using the token are deleted, and any attempts to use the token to interact with the Mattermost server are blocked. However, the token can be reactivated at any time.
|
||||
|
||||
### User's profile
|
||||
|
||||
1. Sign in to the user account, select the user avatar, then select **Profile > Security > Personal Access Tokens**.
|
||||
2. Identify the access token you want to revoke, then select **Delete** and confirm the deletion.
|
||||
|
||||

|
||||
|
||||
### System Console
|
||||
|
||||
1. Go to **System Console > User Management > Users**, search for the user account which the token belongs to, then select **Manage Tokens** from the dropdown.
|
||||
2. Identify the access token you want to revoke, then select **Delete** and confirm the deletion.
|
||||
|
||||

|
||||
|
||||
## Frequently asked questions (FAQ)
|
||||
|
||||
### How do personal access tokens differ from regular session tokens?
|
||||
|
||||
- Personal access tokens do not expire. As a result, you can more easily integrate with Mattermost, bypassing the [session length limits set in the System Console](https://docs.mattermost.com/configure/environment-configuration-settings.html#session-lengths).
|
||||
- Personal access tokens can be used to authenticate against the API more easily, including with AD/LDAP and SAML accounts.
|
||||
- You can optionally assign additional roles for the account creating personal access tokens. This lets the account post to any channel in Mattermost, including direct messages.
|
||||
|
||||
Besides the above differences, personal access tokens are exactly the same as regular session tokens. They are cryptic random IDs and are not different from a user's regular session token created after logging in to Mattermost.
|
||||
|
||||
### Can I set personal access tokens to expire?
|
||||
|
||||
Not in Mattermost, but you can automate your integration to cycle its token [through the REST API](https://api.mattermost.com/#operation/CreateUserAccessToken).
|
||||
|
||||
### How do I identify a badly behaving personal access token?
|
||||
|
||||
The best option is to go to **System Console > Logs** and finding error messages relating to a particular token ID. Once identified, you can search which user account the token ID belongs to in **System Console > Users** and revoke it through the **Manage Tokens** dropdown option.
|
||||
|
||||
### Do personal access tokens continue to work if the user is deactivated?
|
||||
|
||||
No. The session used by the personal access token is revoked immediately after a user is deactivated, and a new session won't be created. The tokens are preserved and continue to function if the user account is re-activated. This is useful when a bot account is temporarily deactivated for troubleshooting, for instance.
|
||||
6
docs/develop/integrate/reference/rest-api/index.md
Normal file
@@ -0,0 +1,6 @@
|
||||
---
|
||||
title: "REST API reference"
|
||||
sidebar_position: 19
|
||||
---
|
||||
|
||||
The Mattermost REST API is documented here: [Mattermost REST API](https://api.mattermost.com)
|
||||
12
docs/develop/integrate/reference/server/index.md
Normal file
@@ -0,0 +1,12 @@
|
||||
---
|
||||
title: "Server plugin SDK reference"
|
||||
sidebar_position: 10
|
||||
---
|
||||
|
||||
This is the documentation for the Go <code>github.com/mattermost/mattermost/server/public/plugin</code> package. It can also be found on [GoDoc](https://godoc.org/github.com/mattermost/mattermost/server/public/plugin).
|
||||
|
||||
Visit the [Plugins](/developers/integrate/plugins) section to learn more about [developing Mattermost plugins](/developers/integrate/plugins/developer-setup) and our recommended [developer workflow](/developers/integrate/plugins/developer-workflow) for Mattermost plugins.
|
||||
|
||||
***
|
||||
|
||||
<PluginGoDocs />
|
||||
210
docs/develop/integrate/reference/webapp/index.md
Normal file
@@ -0,0 +1,210 @@
|
||||
---
|
||||
title: "Web app plugin SDK reference"
|
||||
sidebar_position: 10
|
||||
---
|
||||
|
||||
Visit the [Plugins](/developers/integrate/plugins) section to learn more about [developing Mattermost plugins](/developers/integrate/plugins/developer-setup) and our recommended [developer workflow](/developers/integrate/plugins/developer-workflow) for Mattermost plugins.
|
||||
|
||||
## Table of contents
|
||||
|
||||
- [PluginClass](#pluginclass)
|
||||
* [Example](#example)
|
||||
- [Registry](#registry)
|
||||
- [Theme](#theme)
|
||||
- [Exported Libraries and Functions](#exported-libraries-and-functions)
|
||||
+ [post-utils](#post-utils)
|
||||
- [`formatText(text, options)`](#formattexttext-options)
|
||||
- [`messageHtmlToComponent(html, isRHS, options)`](#messagehtmltocomponenthtml-isrhs-options)
|
||||
- [Usage Example](#usage-example)
|
||||
|
||||
## PluginClass
|
||||
|
||||
The PluginClass interface defines two methods used by the Mattermost Web App to `initialize` and `uninitialize` your plugin:
|
||||
|
||||
```javascript
|
||||
class PluginClass {
|
||||
/**
|
||||
* initialize is called by the webapp when the plugin is first loaded.
|
||||
* Receives the following:
|
||||
* - registry - an instance of the registry tied to your plugin id
|
||||
* - store - the Redux store of the web app.
|
||||
*/
|
||||
initialize(registry, store)
|
||||
|
||||
/**
|
||||
* uninitialize is called by the webapp if your plugin is uninstalled
|
||||
*/
|
||||
uninitialize()
|
||||
}
|
||||
```
|
||||
|
||||
<a id="registerPlugin"></a>
|
||||
|
||||
Your plugin should implement this class and register it using the global `registerPlugin` method defined on the window by the webapp:
|
||||
|
||||
```javascript
|
||||
window.registerPlugin('myplugin', new PluginClass());
|
||||
```
|
||||
|
||||
Use the provided [registry](#registry) to register components, post type overrides and callbacks. Use the store to access the global state of the web app, but note that you should use the registry to register any custom reducers your plugin might require.
|
||||
|
||||
### Example
|
||||
|
||||
The entry point `index.js` of your application might contain:
|
||||
|
||||
```javascript
|
||||
import UserPopularity from './components/profile_popover/user_popularity';
|
||||
import SomePost from './components/some_post';
|
||||
import MenuIcon from './components/menu_icon';
|
||||
import {openExampleModal} from './actions';
|
||||
|
||||
class PluginClass {
|
||||
initialize(registry, store) {
|
||||
registry.registerPopoverUserAttributesComponent(
|
||||
UserPopularity,
|
||||
);
|
||||
registry.registerPostTypeComponent(
|
||||
'custom_somepost',
|
||||
SomePost,
|
||||
);
|
||||
registry.registerMainMenuAction(
|
||||
'Plugin Menu Item',
|
||||
() => store.dispatch(openExampleModal()),
|
||||
mobile_icon: MenuIcon,
|
||||
);
|
||||
}
|
||||
|
||||
uninitialize() {
|
||||
// No clean up required.
|
||||
}
|
||||
}
|
||||
|
||||
window.registerPlugin('myplugin', new PluginClass());
|
||||
```
|
||||
|
||||
This will add a custom `UserPopularity` component to the profile popover, render a custom `SomePost` component for any post with the type `custom_somepost`, and insert a custom main menu item.
|
||||
|
||||
## Registry
|
||||
|
||||
An instance of the plugin registry is passed to each plugin via the `initialize` callback.
|
||||
|
||||
|
||||
<PluginJsDocs />
|
||||
|
||||
### Theme
|
||||
|
||||
In Mattermost, users are able to set custom themes that change the color scheme of the UI. It's important that plugins have access to a user's theme so that they can set their styling to match and not look out of place.
|
||||
|
||||
Every pluggable component in the web app will have the theme object as a prop.
|
||||
|
||||
The colors are exposed via CSS variables as well.
|
||||
|
||||
The theme object has the following properties:
|
||||
|
||||
| Property | CSS Variable | Description |
|
||||
|-------------------------|------------------------------|-------------------------------------------------------------------------------------|
|
||||
| sidebarBg | --sidebar-bg | Background color of the left-hand sidebar |
|
||||
| sidebarText | --sidebar-text | Color of text in the left-hand sidebar |
|
||||
| sidebarUnreadText | --sidebar-unread-text | Color of text for unread channels in the left-hand sidebar |
|
||||
| sidebarTextHoverBg | --sidebar-text-hover-bg | Background color of channels when hovered in the left-hand sidebar |
|
||||
| sidebarTextActiveBorder | --sidebar-text-active-border | Color of the selected indicator channel indicator in the left-hand siebar |
|
||||
| sidebarTextActiveColor | --sidebar-text-active-color | Color of the text for the selected channel in the left-hand sidebar |
|
||||
| sidebarHeaderBg | --sidebar-header-bg | Background color of the left-hand sidebar header |
|
||||
| sidebarHeaderTextColor | --sidebar-header-text-color | Color of text in the left-hand sidebar header |
|
||||
| onlineIndicator | --online-indicator | Color of the online status indicator |
|
||||
| awayIndicator | --away-indicator | Color of the away status indicator |
|
||||
| dndIndicator | --dnd-indicator | Color of the do not disturb status indicator |
|
||||
| mentionBg | --mention-bg | Background color for mention jewels in the left-hand sidebar |
|
||||
| mentionColor | --mention-color | Color of text for mention jewels in the left-hand sidebar |
|
||||
| centerChannelBg | --center-channel-bg | Background color of channels, right-hand sidebar and modals/popovers |
|
||||
| centerChannelColor | --center-channel-color | Color of text in channels, right-hand sidebar and modals/popovers |
|
||||
| newMessageSeparator | --new-message-separator | Color of the new message separator in channels |
|
||||
| linkColor | --link-color | Color of text for links |
|
||||
| buttonBg | --button-bg | Background color of buttons |
|
||||
| buttonColor | --button-color | Color of text for buttons |
|
||||
| errorTextColor | --error-text | Color of text for errors |
|
||||
| mentionHighlightBg | --mention-highlight-bg | Background color of mention highlights in posts |
|
||||
| mentionHighlightLink | --mention-highlight-link | Color of text for mention links in posts |
|
||||
| codeTheme | NA | Code block theme, either 'github', 'monokai', 'solarized-dark' or 'solarized-light' |
|
||||
|
||||
## Exported libraries and functions
|
||||
|
||||
The web app exposes a number of [exported libraries and functions](https://github.com/mattermost/mattermost/blob/master/webapp/channels/src/plugins/export.js) on the `window` object for plugins to use. To avoid bloating your plugin, we recommend depending on these using [Webpack externals](https://webpack.js.org/configuration/externals/) or importing them manually from the window. Below is a list of the exposed libraries and functions:
|
||||
|
||||
| Library | Exported Name | Description |
|
||||
|-----------------|-----------------------|--------------------------------------------------------------------|
|
||||
| react | window.React | [ReactJS](https://react.dev/) |
|
||||
| react-dom | window.ReactDOM | [ReactDOM](https://react.dev/docs/react-dom.html) |
|
||||
| redux | window.Redux | [Redux](https://redux.js.org/) |
|
||||
| react-redux | window.ReactRedux | [React bindings for Redux](https://github.com/reactjs/react-redux) |
|
||||
| react-bootstrap | window.ReactBootstrap | [Bootstrap for React](https://react-bootstrap.github.io/) |
|
||||
| prop-types | window.PropTypes | [PropTypes](https://www.npmjs.com/package/prop-types) |
|
||||
| post-utils | window.PostUtils | Mattermost post utility functions (see below) |
|
||||
|
||||
|
||||
<Note title="Note">
|
||||
Some sets of functions like "Functions exposed on window for plugin to use" and "Components exposed on window for internal plugin use only" are not listed here. You can refer to [export.js](https://github.com/mattermost/mattermost/blob/master/webapp/channels/src/plugins/export.js) file which contains all the exports.
|
||||
</Note>
|
||||
|
||||
|
||||
|
||||
#### post-utils
|
||||
|
||||
Contains the following post utility functions:
|
||||
|
||||
##### `formatText(text, options)`
|
||||
Performs formatting of text including Markdown, highlighting mentions and search terms and converting URLs, hashtags, @mentions and ~channels to links by taking a string and returning a string of formatted HTML.
|
||||
|
||||
* `text` - String of text to format, e.g. a post's message.
|
||||
* `options` - (Optional) An object containing the following formatting options
|
||||
* `searchTerm` - If specified, this word is highlighted in the resulting HTML. Defaults to nothing.
|
||||
* `mentionHighlight` - Specifies whether or not to highlight mentions of the current user. Defaults to true.
|
||||
* `mentionKeys` - A list of mention keys for the current user to highlight.
|
||||
* `singleline` - Specifies whether or not to remove newlines. Defaults to false.
|
||||
* `emoticons` - Enables emoticon parsing with a data-emoticon attribute. Defaults to true.
|
||||
* `markdown` - Enables markdown parsing. Defaults to true.
|
||||
* `siteURL` - The origin of this Mattermost instance. If provided, links to channels and posts will be replaced with internal links that can be handled by a special click handler.
|
||||
* `atMentions` - Whether or not to render "@" mentions into spans with a data-mention attribute. Defaults to false.
|
||||
* `channelNamesMap` - An object mapping channel display names to channels. If `channelNamesMap` and `team` are provided, ~channel mentions will be replaced with links to the relevant channel.
|
||||
* `team` - The current team object.
|
||||
* `proxyImages` - If specified, images are proxied. Defaults to false.
|
||||
|
||||
##### `messageHtmlToComponent(html, isRHS, options)`
|
||||
Converts HTML to React components.
|
||||
|
||||
* `html` - String of HTML to convert to React components.
|
||||
* `isRHS` - Boolean indicating if the resulting components are to be displayed in the right-hand sidebar. Has some minor effects on how UI events are triggered for components in the RHS.
|
||||
* `options` - (Optional) An object containing options
|
||||
* `mentions` - If set, mentions are replaced with the AtMention component. Defaults to true.
|
||||
* `emoji` - If set, emoji text is replaced with the PostEmoji component. Defaults to true.
|
||||
* `images` - If set, markdown images are replaced with the PostMarkdown component. Defaults to true.
|
||||
* `latex` - If set, latex is replaced with the LatexBlock component. Defaults to true.
|
||||
|
||||
##### Usage example
|
||||
|
||||
A short usage example of a `PostType` component using the post utility functions to format text.
|
||||
|
||||
```jsx
|
||||
import React from 'react'; // accessed through webpack externals
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
const PostUtils = window.PostUtils; // must be accessed through `window`
|
||||
|
||||
export default class PostTypeFormatted extends React.PureComponent {
|
||||
|
||||
// ...
|
||||
|
||||
render() {
|
||||
const post = this.props.post;
|
||||
|
||||
const formattedText = PostUtils.formatText(post.message); // format the text
|
||||
|
||||
return (
|
||||
<div>
|
||||
{'Formatted text: '}
|
||||
{PostUtils.messageHtmlToComponent(formattedText)} // convert the html to components
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
```
|
||||