REST API

Усі дії, які виконують застосунки Antimatter, проходять через той самий HTTP API, тому ваші скрипти можуть робити те саме. На цій сторінці описано, як автентифікуватися, які ресурси ви використовуватимете найчастіше, як виглядають відповіді та помилки, а також як отримувати події в реальному часі через WebSocket.

Основи

  • Базовий URL: https://chat.example.com/api/v4. Усі наведені нижче адреси відносні до нього.
  • Формат: JSON на вході та на виході, окрім завантаження файлів (multipart). Надсилайте Content-Type: application/json.
  • Ідентифікатори: кожен об’єкт має id з 26 символів. Час вимірюється в мілісекундах від епохи Unix (create_at, update_at, delete_at; 0 означає «не видалено»).
  • Спільноти — це команди: API називає їх teams, з team_id.
  • Себе: будьде, де шлях приймає user_id, me означає користувача, який увійшов в систему, як у GET /users/me.

Повний список кінцевих точок міститься в коді сервера: маршрути оголошено в server/channels/api4/*.go, а типи — в server/public/model. Опис OpenAPI у папці api/v4/source репозиторію покриває кінцеві точки, успадковані від Mattermost, а також деякі доповнення Antimatter: переміщення обговорень, з’єднання з моделями та дії з повідомленнями. Решта доступні лише в коді.

Автентифікація

Кожен запит, окрім входу в систему та кількох публічних адрес, потребує токену в заголовку Authorization:

curl -H "Authorization: Bearer $TOKEN" https://chat.example.com/api/v4/users/me

Там приймаються три види токенів: особисті токени доступу, сесійні токени та OAuth-токени доступу. Також приймається Authorization: Token …. Токени в рядку запитів (?access_token=) приймаються лише для OAuth-токенів доступу.

Особисті токени доступу (рекомендовано для скриптів)

Особистий токен доступу діє від вашого імені, не закінчує дію, якщо ви не вкажете дату закінчення, і може бути відкликано в будь-який момент. Особисті токени доступу вимкнено за замовчуванням:

  1. Системний адміністратор вмикає Увімкніть персональні токени доступу в Системна консоль › Інтеграції › Управління інтеграцією (ServiceSettings.EnableUserAccessTokens, AM_SERVICESETTINGS_ENABLEUSERACCESSTOKENS).
  2. Для кожної особи, яка може створювати токени, системний адміністратор відкриває Системна консоль › Керування користувачами › Користувачі, обирає Керування ролями у меню цієї особи та позначає Дозволити цьому обліковому запису генерувати персональні токени доступу. Системні адміністратори завжди можуть їх створювати.
  3. Особа відкриває свій аватар у правому верхньому куті, потім Профіль і налаштування › Безпека. У розділі Персональні токени доступу вона описує, для чого потрібен токен, і обирає Створити токен. Токен показується лише один раз: скопіюйте його.

Через API: POST /users/{user_id}/tokens з {"description": "backup script", "expires_at": 0} (expires_at у мілісекундах; 0 — безстроковий). Поле token у відповіді містить секрет; його id використовується для відкликання (POST /users/tokens/revoke з {"token_id": "…"}). З командного рядка: amctl token generate <user> <description>.

Системний адміністратор може обмежити термін дії токенів за допомогою Максимальний термін дії особистого токена доступу (дні) на тій самій сторінці Системної консолі.

Токени сесій

Увійшовши за допомогою пароля, ви отримуєте токен сесії у заголовку відповіді Token, той самий тип сесії, який використовують додатки:

curl -i -X POST https://chat.example.com/api/v4/users/login \
  -H 'Content-Type: application/json' \
  -d '{"login_id": "maya", "password": "…"}'

Для облікового запису з багатокроковою автентифікацією додайте "token": "123456". Сесії завершуються відповідно до налаштувань сесій сервера, а точка входу має обмеження частоти (5 запитів за секунду). POST /users/logout завершує сесію.

Браузер автентифікується за допомогою куки. Запит, автентифікований кукою, також має надсилати заголовок X-CSRF-Token для будь-яких дій, окрім GET; токен у заголовку Authorization не потребує CSRF-заголовка.

Додатки OAuth 2.0

Щоб дозволити людям вхід до вашого застосунку за допомогою їхнього облікового запису Antimatter, зареєструйте додаток OAuth 2.0. Antimatter тоді виступає провайдером OAuth:

  1. Увімкнути постачальника послуг OAuth 2.0 має бути увімкнено (Системна консоль › Інтеграції › Управління інтеграцією, ServiceSettings.EnableOAuthServiceProvider, за замовчуванням увімкнено).
  2. Хтось із правом керування додатками OAuth (за замовчуванням — системні адміністратори) відкриває свій аватар, потім Інтеграції › Додатки OAuth 2.0 і додає додаток із його URL-адресами зворотного виклику. Вони отримують ідентифікатор клієнта та секрет клієнта.
  3. Ваша застосунка пересилає людей на https://chat.example.com/oauth/authorize з response_type=code, client_id, redirect_uri та state. Підтримується PKCE з code_challenge_method=S256.
  4. Вона обмінює код на POST https://chat.example.com/oauth/access_token (grant_type=authorization_code, потім refresh_token для оновлення) і викликає API з Authorization: Bearer <access token>.

Користувачі бачать додатки, які вони дозволили, в Профіль і налаштування › Безпека › Дозволені вами додатки.

Основні ресурси

ЩоКінцеві точки
Ви та інші людиGET /users/me, GET /users/{user_id}, GET /users/username/{username}, POST /users/ids (список ID), POST /users/search, GET /users?in_team=…&in_channel=…
СпільнотиGET /users/me/teams, GET /teams/{team_id}, GET /teams/name/{name}, PUT /teams/{team_id}/patch, GET /teams/{team_id}/members, POST /teams/{team_id}/members
КаналиGET /users/me/teams/{team_id}/channels, GET /teams/name/{team}/channels/name/{channel}, POST /channels, POST /channels/direct (два ID користувачів), POST /channels/group, POST /channels/{channel_id}/members
ПовідомленняPOST /posts, GET /posts/{post_id}, PUT /posts/{post_id}/patch, DELETE /posts/{post_id}, GET /channels/{channel_id}/posts, GET /posts/{post_id}/thread, POST /teams/{team_id}/posts/search
РеакціїPOST /reactions з {"user_id", "post_id", "emoji_name"}, DELETE /users/{user_id}/posts/{post_id}/reactions/{emoji_name}
ФайлиPOST /files (multipart: channel_id та files), потім вставте повернуті ID у file_ids повідомлення; GET /files/{file_id}
ПараметриGET /users/me/preferences, PUT /users/me/preferences
Інтеграції/hooks/incoming, /hooks/outgoing, /commands, /bots, /oauth/apps (див. наступні сторінки)
СерверGET /system/ping (стан, токен не потрібен), GET /config/client?format=old (налаштування, які бачать клієнти)

Опублікувати повідомлення

curl -X POST https://chat.example.com/api/v4/posts \
  -H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' \
  -d '{"channel_id": "'$CHANNEL_ID'", "message": "Backup finished: **42 GB** in 3 min"}'

Повідомлення форматовано за Markdown. Додайте "root_id" (перше повідомлення обговорення), щоб відповісти в обговоренні, "file_ids" для файлів та "props" для вкладень і інших додаткових даних (див. Вкладення).

Знайти ID каналу

curl -H "Authorization: Bearer $TOKEN" \
  https://chat.example.com/api/v4/teams/name/lumen-labs/channels/name/ops-alerts

Назви — це ті, що в посиланні на канал: /lumen-labs/channels/ops-alerts.

Пагінація

Кінцеві точки списків приймають page (з 0) та per_page (за замовчуванням 60, максимум 200). Продовжуйте запитувати наступну сторінку, доки сторінка не повернеться коротшою за per_page.

Повідомлення каналу (GET /channels/{channel_id}/posts) також приймають since (час: все, що змінилося з того моменту), або before та after (ID повідомлення). Результат повертається як список повідомлень: {"order": [IDs, newest first], "posts": {ID: post}, "next_post_id", "prev_post_id"}.

Помилки

Помилки використовують стандартні HTTP-коди стану (400 — некоректний вхід, 401 — не авторизовано, 403 — заборонено, 404 — не знайдено, 501 — функцію вимкнено) та JSON-тіло:

{
  "id": "api.context.permissions.app_error",
  "message": "You do not have the appropriate permissions.",
  "detailed_error": "",
  "request_id": "jz8zm5nunpbt8f3gpqsz5dq6so",
  "status_code": 403
}

У коді використовуйте id: message перекладено мовою користувача. detailed_error є порожнім, якщо сервер не працює в режимі розробника (ServiceSettings.EnableDeveloper). Передайте request_id адміністратору сервера: він міститься в журналах.

Обмеження частоти

Обмеження швидкості вимкнено за замовчуванням. Коли системний адміністратор вмикає його (Системна консоль › Середовище › Обмеження швидкості), кожен клієнт отримує 10 запитів на секунду з викидами до 100 за замовчуванням, що рахується за IP-адресою або за користувачем. Відповіді містять X-RateLimit-Limit, X-RateLimit-Remaining та X-RateLimit-Reset; якщо ліміт перевищено, сервер відповідає 429 з заголовком Retry-After у секундах. Деякі точки кінцевого доступу, наприклад вхід в систему, мають власний ліміт незалежно від налаштувань.

Пишіть скрипти, які чекають і повторюють запити при 429, та уникайте опитування: використовуйте WebSocket замість цього.

Потік подій WebSocket

Підключіться до wss://chat.example.com/api/v4/websocket. Авторизуйтесь за допомогою заголовка Authorization: Bearer у запиті на підключення або надішліть це як перше повідомлення:

{"seq": 1, "action": "authentication_challenge", "data": {"token": "…"}}

Сервер надсилає подію hello, а потім подію для всього, що вам дозволено переглядати:

{
  "event": "posted",
  "data": {"channel_id": "…", "channel_type": "O", "post": "{\"id\":\"…\",\"message\":\"Hello\",…}"},
  "broadcast": {"channel_id": "…", "team_id": "", "user_id": "", "omit_users": null},
  "seq": 4
}

Зверніть увагу, що data.post — це повідомлення як JSON-рядок. Типові події: posted, post_edited, post_deleted, reaction_added, reaction_removed, typing, status_change, user_added, direct_added. Додатки надсилають власні події, названі custom_<app id>_<event>.

Ви також можете надсилати дії, кожна з яких має зростаючий seq: user_typing із {"channel_id", "parent_id"} або get_statuses. Перепідключайтесь, коли з’єднання розривається, і отримуйте те, що ви пропустили, за допомогою since (див. Пагінація).

Antimatter додає такі події: community_attributes_updated, member_timeouts_updated, post_put_on_top, post_removed_from_top, server_categories_updated, channel_overrides_updated та category_overrides_updated.

Клієнтські бібліотеки

  • Перейти: model.Client4 в server/public/model (імпорт github.com/mattermost/mattermost/server/public/model). model.NewAPIv4Client(url), потім client.SetToken(token); model.NewWebSocketClient4(wsURL, token) стежить за подіями. Копія Antimatter додає методи для власних точок кінцевого доступу, наприклад UpdateMessageRequest, PutPostOnTop та ExportChannel.
  • TypeScript: клас Client4 з @mattermost/client, у webapp/platform/client, з типами у webapp/platform/types. Копія в репозиторії Antimatter містить кінцеві точки Antimatter; пакет, опублікований Mattermost на npm, — ні.
package main

import (
	"context"
	"log"

	"github.com/mattermost/mattermost/server/public/model"
)

func main() {
	client := model.NewAPIv4Client("https://chat.example.com")
	client.SetToken("…")
	post, _, err := client.CreatePost(context.Background(), &model.Post{
		ChannelId: "…",
		Message:   "Hello from Go",
	})
	if err != nil {
		log.Fatal(err)
	}
	log.Println("posted", post.Id)
}

Що Antimatter додає до API

Ці кінцеві точки та поля не існують на сервері Mattermost. Усі вони потребують сесії.

Кінцева точкаПризначення
GET /teams/{team_id}/user_attributes/fields
POST той самий шлях
PATCH, DELETE …/fields/{field_id}
Атрибути спільноти: поля профілю, які адміністратори спільноти визначають для її учасників (до 20). Учасники можуть їх читати; адміністратори спільноти створюють і змінюють їх.
GET /teams/{team_id}/members/{user_id}/user_attributes
PATCH той самий шлях
POST /teams/{team_id}/user_attributes/values/search
Значення атрибутів учасника, у форматі {field_id: value}. Учасники встановлюють власні (крім тих, що керуються адміністраторами); адміністратори встановлюють значення для будь-кого. Пошук приймає {"user_ids": [...]} (до 200).
GET /teams/{team_id}/timeouts
PUT /teams/{team_id}/members/{user_id}/timeout
GET /teams/{team_id}/members/{user_id}/moderation
Таймаути: {"until": time, "reason": "…"} забороняє комусь публікувати, реагувати та завантажувати у спільноті до зазначеного часу (не більше 28 днів); "until": 0 знімає обмеження. Перегляд модерації показує, коли учасник приєднався та скільки він нещодавно опублікував.
GET /channels/{channel_id}/on_top
PUT, DELETE /posts/{post_id}/on_top
Повідомлення, закріплені нагорі каналу (до 10). {"duration": ms}, максимум 30 днів; 0 означає, що повідомлення залишиться, доки його не знімуть. Усі, хто може читати канал, бачать їх у списку. Щоб закріпити повідомлення нагорі або зняти його, потрібне право публікувати в каналі, а в каналі спільноти — бути адміністратором каналу або спільноти або мати там Керування повідомленнями (delete_others_posts). У приватному або груповому повідомленні це можуть робити його учасники. У архівованих каналах закріплення заборонено.
POST /channels/{channel_id}/message_requestДіє на вашому запиті щодо повідомлення: {"action": "accept"}, "dismiss" або "request", щоб повернути обговорення до списку запитів. Повертає вашого учасника каналу.
GET, PUT /channels/{channel_id}/overrides
GET /channels/{channel_id}/overrides/effective
GET, PUT /channels/{channel_id}/role_access
Що роль або особа може робити в каналі, а також які ролі бачать канал із обмеженнями за ролями.
GET, PUT /teams/{team_id}/server_categories
GET, PUT …/server_categories/overrides
Спільні категорії каналів спільноти, а також перевизначення, що застосовуються до всіх каналів у категорії.
GET /groups/{group_id}/team_role
PUT …/team_role/permissions
Дозволи, які надає роль спільноти.
POST /teams/{team_id}/autolinks/previewПеревіряє правила автопосилань спільноти на тексті.
POST /channels/{channel_id}/export?format=csv&since=&until=Завантажує повідомлення каналу у форматі CSV (до 50 000) для тих, хто може читати канал.
GET /posts/{post_id}/speechПовідомлення, озвучене як аудіо, коли налаштовано перетворення тексту в мовлення.
POST /posts/{post_id}/move_to_channelПереміщує обговорення в інший канал тієї ж спільноти: див. Переміщення обговорення.
GET, POST /ai/connections
GET, PATCH, DELETE /ai/connections/{connection_id}
GET /ai/connections/usable
З’єднання з моделями, тобто провайдери ШІ, які використовуються функціями ШІ сервера та додатками: див. З’єднання з моделями.
GET /channels/{channel_id}/message_actions
POST /posts/{post_id}/message_actions/{hook_id}
GET, POST /hooks/outgoing/{hook_id}/icon
Дії з повідомленнями: вихідні вебхуки, які користувачі запускають із меню повідомлення. Див. Дії з повідомленнями.

Нові поля

  • Спільноти (Team, і PUT /teams/{team_id}/patch): all_channels_membership (кожен учасник належить до всіх каналів, які може бачити), default_channel_id (канал, куди потрапляють новачки; порожнє значення означає General), kind (community або workplace: у workplace адміністратори каналів можуть архівувати свої канали; нові спільноти отримують TeamSettings.DefaultCommunityKind сервера, за замовчуванням community), member_list_view (як список учасників групує їх: choice, за замовчуванням, дозволяє кожному учаснику обирати; roles або teams фіксують групування), hide_role_colors, require_team_badges, onboarding та autolinks (обидва — рядки JSON).
  • Типовий канал нової спільноти — general (Загальний), а не town-square. Оновлення до 0.9.0 перейменовує town-square кожної спільноти на general, зберігаючи його ID, якщо у спільноти ще немає каналу general. Старі назви продовжують працювати: GET /teams/{team_id}/channels/name/town-square, GET /teams/name/{team}/channels/name/town-square та channel вхідного вебхука вказують на типовий канал спільноти, якщо каналу з такою назвою немає. У новому коді використовуйте default_channel_id або назву general.
  • Посилання на канали: #channel-name створює посилання на канал, як і ~channel-name. Властивість channel_mentions публікації містить список каналів, на які є посилання будь-яким із цих способів; #word, що не відповідає назві каналу, залишається хештегом. Веб-інтерфейс Antimatter та мобільний застосунок використовують формат #name.
  • Архівні канали можуть отримувати нових учасників (POST /channels/{channel_id}/members), які можуть переглядати їхню історію. Ніхто не може публікувати, додавати реакції, закріплювати, переміщати повідомлення на початок, перейменовувати канал або змінювати ролі учасників у ньому.
  • Вбудовані відповіді: публікація з "props": {"reply_to": "<post id>"} цитує це повідомлення з того самого каналу. Додайте "reply_to_mention": false, щоб не сповіщати автора. Сервер заповнює metadata.reply_to коротким описом процитованого повідомлення.
  • Спойлери: "props": {"spoiler": true} приховує текст та файли публікації, доки читач не вирішить їх переглянути.
  • Ігнорування та блокування — це налаштування: категорія user_block, названа за ID іншої особи, зі значенням ignore або block. Чи чекає приватне повідомлення як запит, визначається у notify_props.dm_request вашого учасника каналу (pending, accepted або dismissed).
  • Вкладення до повідомлень можуть містити stages та chart: див. Картки.

Переміщення обговорення

POST /posts/{post_id}/move_to_channel переміщує обговорення, його перше повідомлення та всі відповіді в інший канал тієї ж спільноти. post_id може бути ID першого повідомлення або будь-якої відповіді.

curl -X POST https://chat.example.com/api/v4/posts/$POST_ID/move_to_channel \
  -H "Authorization: Bearer $TOKEN" -H 'Content-Type: application/json' \
  -d '{"channel_id": "'$TARGET_CHANNEL_ID'", "flatten": false}'
  • channel_id (обов’язковий): канал, куди переміщується обговорення.
  • flatten (за замовчуванням false): true перетворює відповіді на звичайні повідомлення цільового каналу замість обговорення. У Fusion для цього використовується Make it a channel.

Повідомлення зберігають авторів, час, реакції та файли. Їхні копії містять властивість silent_notification, тому не надсилають сповіщень. Оригінальні повідомлення видаляються. У відповіді повертається перше повідомлення обговорення з його новим ID.

Хто може переміщати обговорення

  • Ви повинні мати доступ до читання обговорення та до публікації в цільовому каналі.
  • Адміністратори каналу, адміністратори спільноти, користувачі з правом Керування повідомленнями (delete_others_posts) у каналі та системні адміністратори можуть переміщати будь-яке обговорення.
  • Автор обговорення може перемістити його, якщо обидва канали є відкритими, або якщо всі повідомлення в обговоренні належать йому. Інакше відповідь буде 403 з ID api.post.move_thread.private_needs_moderator.app_error.
  • Обидва канали мають належати до одного робочого середовища (приватні та групові повідомлення не підтримуються), бути різними та не архівованими. Системні повідомлення та повідомлення, що знищуються після прочитання, неможливо перемістити.
  • Обговорення з кількістю повідомлень, що перевищує WranglerSettings.MoveThreadMaxCount (за замовчуванням 100; 0 означає відсутність обмеження), відхиляється.

Показник та нотатка

Після переміщення залишаються два системні повідомлення типу system_wrangler: показник у старому каналі («Обговорення з 13 повідомленнями переміщено до #target») та нотатка в цільовому каналі («Це обговорення переміщено з #source»), під переміщеним обговоренням або, за використання flatten, після його повідомлень. Окрім тексту повідомлення, їхні властивості дозволяють клієнту відображати назву каналу як посилання:

  • Показник: MovedThreadPermalink, NumMessages, MovedThreadChannelId, MovedThreadTeamName, MovedThreadPostId та, для відкритого цільового каналу, MovedThreadChannelName і MovedThreadChannelDisplayName.
  • Нотатка: MovedFromChannelId, MovedFromTeamName, MovedFromPostId (показник), MovedFromPermalink та, для відкритого початкового каналу, MovedFromChannelName і MovedFromChannelDisplayName.

Обидва також містять TranslationID. Назву приватного каналу не вказано: читачі бачать «інший канал». Власний POST /posts/{post_id}/move у Mattermost вимкнено в Antimatter; використовуйте цей endpoint.

Підключення моделей

Модельне з’єднання — це адреса та ключ постачальника ШІ, які налаштовує адміністратор. Серверні функції ШІ та додатки, що викликають службу ШІ, використовують ці з’єднання. Системні адміністратори керують серверними з’єднаннями (manage_ai_connections); адміністратори робочого середовища керують з’єднаннями свого середовища (manage_team_ai_connections). Ключі є лише для запису: у відповідях вони не передаються, лише api_key_set та api_key_last4.

Кінцева точкаПризначення
GET /ai/connections?scope=З’єднання, якими ви керуєте. scope — це server або ID робочого середовища; якщо його не вказано, повертаються всі з’єднання, якими ви керуєте.
POST /ai/connectionsДодає з’єднання (відповідає 201).
POST /ai/connections/test, POST /ai/connections/modelsПеревіряє з’єднання або перелічує його моделі перед збереженням. Тіло запиту таке саме, як при додаванні; нічого не зберігається.
GET, PATCH (або PUT), DELETE /ai/connections/{connection_id}Читає, змінює або видаляє з’єднання. Патч містить лише поля, які потрібно змінити; якщо не вказати api_key, ключ збережеться.
POST /ai/connections/{connection_id}/testПеревіряє збережене з’єднання: {"ok", "error", "status_code", "latency_ms", "model_count"}.
GET /ai/connections/{connection_id}/modelsМоделі, які пропонує провайдер.
GET /ai/connections/{connection_id}/usageЗапити та токени за поточний місяць.
GET /ai/connections/usable?channel_id=&team_id=Для всіх, хто увійшов: з’єднання, які можна там використовувати, з їхніми моделями та можливостями, але ніколи з їхніми ключами чи адресами.

Тіло нового з’єднання:

{
  "name": "Local models",
  "scope": "server",
  "provider": "openai_compatible",
  "base_url": "http://llm.internal:8000/v1",
  "api_key": "…",
  "extra_headers": {},
  "models": {"chat": "qwen3-32b", "embeddings": "", "transcription": "", "decisions": ""},
  "limits": {"requests_per_minute": 0, "monthly_token_budget": 0, "per_user_requests_per_minute": 0, "per_user_monthly_token_budget": 0},
  "sharing": {"all_teams": true, "team_ids": []},
  "audience": {"everyone": true, "group_ids": [], "roles": [], "allow_guests": false}
}

provider — це openai_compatible або anthropic. scope за замовчуванням дорівнює server; ідентифікатор спільноти робить його з’єднанням цієї спільноти. У limits значення 0 означає відсутність обмежень; запити на хвилину рахуються на кожному сервері, а бюджети токенів — на календарний місяць (UTC) для всієї кластерної системи. sharing визначає, які спільноти можуть використовувати серверне з’єднання (для приватних та групових повідомлень потрібен all_teams), а audience — хто може ним користуватися; гості — лише за наявності allow_guests. Зміни записуються в журнал аудиту. Налаштування описано в адміністративному посібнику: див. ШІ.