Ang REST API

Lahat ng ginagawa ng mga Antimatter app ay pumapasa sa iisang HTTP API, kaya maaari ring gawin ng iyong scripts. Inilalarawan ng pahinang ito kung paano mag-authenticate, ang mga resource na madalas mong gagamitin, ang anyo ng mga response at errors, at kung paano sundan ang mga event live sa pamamagitan ng WebSocket.

Mga Batayan

  • Base URL: https://chat.example.com/api/v4. Ang lahat ng endpoint sa ibaba ay nakabatay dito.
  • Format: JSON ang pumasok at lumalabas, maliban sa mga file upload (multipart). Ipadala ang Content-Type: application/json.
  • IDs: bawat object ay may 26-karakter na id. Ang mga oras ay mga millisecond mula sa Unix epoch (create_at, update_at, delete_at; 0 ang ibig sabihin ay "hindi tinanggal").
  • Ang mga komunidad ay mga team: tinatawag ng API na teams, na may team_id.
  • Sarili mo: saan man may user_id ang isang path, ang me ay tumutukoy sa naka-sign-in na user, gaya ng GET /users/me.

Ang buong listahan ng mga endpoint ay nasa code ng server: ang mga route ay nakadagdag sa server/channels/api4/*.go at ang mga type ay nasa server/public/model. Ang OpenAPI description sa folder na api/v4/source ng repository ay sumasaklaw sa mga endpoint na pinagmulan mula sa Mattermost, at sa ilang dagdag ng Antimatter: paglipat ng mga thread, model connections, at mga message actions. Ang iba ay nasa code lamang.

Pag-authenticate

Kailangan ng bawat request, maliban sa pag-sign in at ilang pampublikong endpoint, ng token sa Authorization header:

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

Tatlong uri ng token ang tinatanggap doon: personal access tokens, session tokens at OAuth access tokens. Tinatanggap din ang Authorization: Token …. Ang mga token sa query string (?access_token=) ay tinatanggap lamang para sa mga OAuth access tokens.

Personal access tokens (inirerekomenda para sa mga scripts)

Ang personal access token ay kumikilos bilang ikaw, hindi nag-e-expire maliban kung bibigyan mo ito ng expiry date, at maaaring i-revoke anumang oras. Ang mga personal access tokens ay naka-off sa default:

  1. Ipinapanagot ng isang system admin ang I-enable ang mga Personal Access Tokens sa System Console › Mga Integration › Pamamahala ng Integration (ServiceSettings.EnableUserAccessTokens, AM_SERVICESETTINGS_ENABLEUSERACCESSTOKENS).
  2. Para sa bawat taong maaaring lumikha ng token, binubuksan ng isang system admin ang System Console › Pamamahala ng Mga User › Mga User, pumipili ng Pamahalaan ang mga role sa menu ng taong iyon, at tinatagpo ang Payagan ang account na itong lumikha ng mga personal access token. Maaari laging lumikha ng token ang mga system admin.
  3. Binubuksan ng taong iyon ang kanyang avatar sa itaas na kanan, tapos ang Profile & settings › Seguridad. Sa ilalim ng Mga Personal Access Token, inilalarawan nito kung para saan ang token at pumipili ng Lumikha ng Token. Ipinapakita lamang isang beses ang token: i-copy ito.

Gamit ang API: POST /users/{user_id}/tokens na may {"description": "backup script", "expires_at": 0} (ang expires_at ay nasa milliseconds; 0 kung walang expiration). Ang token field ng response ang secret; ang id nito ang gagamitin upang ito ay ma-revoke (POST /users/tokens/revoke na may {"token_id": "…"}). Mula sa command line: amctl token generate <user> <description>.

Maaaring limitahan ng isang system admin ang tagal ng validity ng mga token gamit ang Pinakamataas na Tagal ng Validity ng Personal Access Token (araw) sa parehong pahina ng System Console.

Mga session token

Kapag nag-sign in gamit ang password, may session token na naaalis sa Token response header, ang parehong uri ng session na ginagamit ng mga app:

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

Magdagdag ng "token": "123456" para sa account na may multi-factor authentication. Ang mga session ay mag-e-expire ayon sa mga setting ng session ng server, at ang login endpoint ay may rate limit (5 requests bawat segundo). Ang POST /users/logout ay nagtatapos ng session.

Nag-a-authenticate ang mga browser gamit ang cookie. Ang request na naka-authenticate gamit ang cookie ay dapat magpadala rin ng X-CSRF-Token header para sa anumang bagay maliban sa GET; ang token sa Authorization header ay hindi nangangailangan ng CSRF header.

Mga OAuth 2.0 app

Upang payagan ang mga tao na mag-sign in sa iyong application gamit ang kanilang Antimatter account, i-register ang isang OAuth 2.0 app. Ang Antimatter ang magiging OAuth provider:

  1. Naka-on ang Paganahin ang OAuth 2.0 Service Provider (System Console › Mga Integration › Pamamahala ng Integration, ServiceSettings.EnableOAuthServiceProvider, naka-on sa default).
  2. Ang taong may karapatang pamahalaan ang mga OAuth app (mga system admin sa default) ay binubuksan ang kanyang avatar, tapos ang Mga Integration › Mga OAuth 2.0 app, at idinadagdag ang app kasama ang mga callback URL nito. Nakakakuha siya ng client ID at client secret.
  3. Ang iyong application ay nagpapadala ng mga tao sa https://chat.example.com/oauth/authorize gamit ang response_type=code, client_id, redirect_uri, at state. Sinusuportahan ang PKCE gamit ang code_challenge_method=S256.
  4. Pinagpapalit nito ang code sa POST https://chat.example.com/oauth/access_token (gamit ang grant_type=authorization_code, at pagkatapos ay refresh_token upang ma-renew), at tumatawag sa API gamit ang Authorization: Bearer <access token>.

: Nakikita ng mga tao ang mga app na pinahintulutan nila sa Profile & settings › Seguridad › Mga app na pinahintulutan mo.

Pangunahing mga resource

AnoMga Endpoint
Ikaw at iba pang taoGET /users/me, GET /users/{user_id}, GET /users/username/{username}, POST /users/ids (isang listahan ng mga ID), POST /users/search, GET /users?in_team=…&in_channel=…
Mga komunidadGET /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
Mga ChannelGET /users/me/teams/{team_id}/channels, GET /teams/name/{team}/channels/name/{channel}, POST /channels, POST /channels/direct (dalawang user ID), POST /channels/group, POST /channels/{channel_id}/members
Mga mensahe (posts)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
Mga ReaksyonPOST /reactions gamit ang {"user_id", "post_id", "emoji_name"}, DELETE /users/{user_id}/posts/{post_id}/reactions/{emoji_name}
Mga filePOST /files (multipart: channel_id at files), pagkatapos ay ilagay ang mga naibalik na ID sa file_ids ng post; GET /files/{file_id}
Mga PreferenceGET /users/me/preferences, PUT /users/me/preferences
Mga Integration/hooks/incoming, /hooks/outgoing, /commands, /bots, /oauth/apps (tingnan ang mga sumusunod na pahina)
ServerGET /system/ping (health, hindi kailangan ng token), GET /config/client?format=old (ang mga setting na nakikita ng mga client)

Mag-post ng mensahe

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"}'

Ang mga mensahe ay Markdown. Idagdag ang "root_id" (ang unang post ng isang thread) upang sumagot sa loob ng thread, "file_ids" para sa mga file, at "props" para sa mga attachment at iba pang karagdagang impormasyon (tingnan ang Attachments).

Hanapin ang ID ng isang channel

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

Ang mga pangalan ay ang mga nasa link ng channel: /lumen-labs/channels/ops-alerts.

Pagination

Tumatanggap ang mga list endpoint ng page (mula 0) at per_page (60 ang default, hanggang 200). Ituloy ang paghingi ng susunod na pahina hanggang sa mas maikli ang isang pahina kaysa sa per_page.

Ang mga mensahe ng isang channel (GET /channels/{channel_id}/posts) ay tumatanggap din ng since (isang oras: lahat ng nagbago mula noon), o ng before at after (isang ID ng post). Ibinabalik ito bilang listahan ng mga post: {"order": [IDs, newest first], "posts": {ID: post}, "next_post_id", "prev_post_id"}.

Mga Error

Ginagamit ng mga error ang karaniwang HTTP status codes (400 maling input, 401 hindi naka-sign in, 403 hindi pinapayagan, 404 hindi nakita, 501 patay ang feature) at isang JSON body:

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

Gumamit ng id sa iyong code: ang message ay isasalin sa wika ng user. Walang laman ang detailed_error maliban kung naka-developer mode ang server (ServiceSettings.EnableDeveloper). I-quote ang request_id sa admin ng server: nasa logs ito.

Mga Rate Limit

Patay ang rate limiting sa default. Kapag pinag-on nito ng system admin (System Console › Environment › Rate Limiting), bawat client ay may 10 requests bawat segundo na may bursts ng 100 sa default, na binibilang ayon sa IP address o user. May kasama sa mga sagot ang X-RateLimit-Limit, X-RateLimit-Remaining at X-RateLimit-Reset; kung sobra sa limit, sasagutin ng server ang 429 na may Retry-After header sa mga segundo. May sariling limit ang ilang endpoints, tulad ng pag-sign in, anuman ang setting.

Mag-isulat ng mga script na naghihintay at nagre-retry sa 429, at iwasan ang polling: sundan ang WebSocket sa halip.

Ang WebSocket event stream

Kumonekta sa wss://chat.example.com/api/v4/websocket. I-authenticate gamit ang Authorization: Bearer header sa connection request, o ipadala ito bilang unang mensahe:

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

Ipadala ng server ang hello event, tapos isang event para sa lahat ng makikita mo:

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

Tandaan na ang data.post ay ang post bilang JSON string. Karaniwang mga event: posted, post_edited, post_deleted, reaction_added, reaction_removed, typing, status_change, user_added, direct_added. Ipadala ng mga Apps ang kanilang sariling mga event, na tinatawag na custom_<app id>_<event>.

Maaari mo ring magpadala ng mga action, bawat isa na may lumalaking seq: user_typing na may {"channel_id", "parent_id"}, o get_statuses. Umuulit ng koneksyon kapag nawala ito, at kunin ang natapos gamit ang since (tingnan ang Pagination).

Idinagdag ng Antimatter ang mga sumusunod na kaganapan: community_attributes_updated, member_timeouts_updated, post_put_on_top, post_removed_from_top, server_categories_updated, channel_overrides_updated at category_overrides_updated.

Mga library ng client

  • Pumunta: model.Client4 sa server/public/model (i-import ang github.com/mattermost/mattermost/server/public/model). model.NewAPIv4Client(url), tapos client.SetToken(token); sumusunod ang model.NewWebSocketClient4(wsURL, token) sa mga kaganapan. Ang kopya ng Antimatter ay may mga method para sa sariling endpoint nito, tulad ng UpdateMessageRequest, PutPostOnTop at ExportChannel.
  • TypeScript: ang klase ng Client4 ng @mattermost/client, sa webapp/platform/client, kasama ang mga type nito sa webapp/platform/types. Ang kopya sa repository ng Antimatter ay kasama ang mga endpoint ng Antimatter; ang package na ipinagbili sa npm ng Mattermost ay hindi.
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)
}

Ang idinagdag ng Antimatter sa API

Ang mga endpoint at field na ito ay wala sa isang server ng Mattermost. Lahat ng ito ay nangangailangan ng session.

EndpointGinagawa nito
GET /teams/{team_id}/user_attributes/fields
POST sa parehong path
PATCH, DELETE …/fields/{field_id}
Mga attribute ng komunidad: ang mga profile field na tinatakda ng mga admin ng komunidad para sa mga miyembro nito (hanggang 20). Maaabutan ng mga miyembro ang mga ito; nilikha at binabago ng mga admin ng komunidad.
GET /teams/{team_id}/members/{user_id}/user_attributes
PATCH sa parehong path
POST /teams/{team_id}/user_attributes/values/search
Ang mga halaga ng attribute ng isang miyembro, bilang {field_id: value}. Ipinapalagay ng mga miyembro ang kanilang sarili (maliban sa mga pinangangasiwaan ng admin); ipinapalagay ng mga admin ang sinumang miyembro. Ang search ay tumatanggap ng {"user_ids": [...]} (hanggang 200).
GET /teams/{team_id}/timeouts
PUT /teams/{team_id}/members/{user_id}/timeout
GET /teams/{team_id}/members/{user_id}/moderation
Mga timeout: ang {"until": time, "reason": "…"} ay pinalilimitahan ang isang tao mula sa pag-post, pag-reaction, at pag-upload sa komunidad hanggang sa oras na iyon (hanggang 28 araw); ang "until": 0 ay nagpapahina nito. Ang view ng moderation ay nagpapakita kailan sila sumali at gaano karami ang post nila kamakailan.
GET /channels/{channel_id}/on_top
PUT, DELETE /posts/{post_id}/on_top
Mga mensahe na naka-pin sa itaas ng isang channel (hanggang 10). {"duration": ms}, hanggang 30 araw; ang 0 ay mananatili hangga't hindi tanggalin. Ang sinumang makabasa sa channel ay makikita ang mga ito. Ang pag-pin o pagtanggal ng isang mensahe ay nangangailangan ng karapatan na mag-post sa channel, at, sa channel ng isang komunidad, na maging admin ng channel o ng komunidad, o may Pamahalaan ang mga mensahe (delete_others_posts) doon. Sa direct o group message, ang mga miyembro nito ay maaari. Tinatanggihan sa mga archived channel.
POST /channels/{channel_id}/message_requestNag-aakto sa iyong sariling request: {"action": "accept"}, "dismiss", o "request" upang ibalik ang isang usapan sa mga request. Ibinabalik ang iyong miyembro ng channel.
GET, PUT /channels/{channel_id}/overrides
GET /channels/{channel_id}/overrides/effective
GET, PUT /channels/{channel_id}/role_access
Ang mga gawain na maaari gawin ng isang role o tao sa isang channel, at ang mga role na makikita ang role-gated channel.
GET, PUT /teams/{team_id}/server_categories
GET, PUT …/server_categories/overrides
Ang mga shared na kategorya ng channel ng komunidad, at ang mga override na nakaka-apply sa bawat channel sa loob ng isang kategorya.
GET /groups/{group_id}/team_role
PUT …/team_role/permissions
Ang mga pahintulot na ibinibigay ng isang role ng komunidad.
POST /teams/{team_id}/autolinks/previewSinusubukan ang mga autolink rules ng komunidad sa isang text.
POST /channels/{channel_id}/export?format=csv&since=&until=Iin-download ang mga mensahe ng isang channel bilang CSV (hanggang 50,000), para sa mga taong makabasa ng channel.
GET /posts/{post_id}/speechAng binasa nang malakas na mensahe, bilang audio, kapag nakaset up ang text-to-speech.
POST /posts/{post_id}/move_to_channelNaglipat ng isang thread sa ibang channel ng parehong komunidad: tingnan ang Paglipat ng thread.
GET, POST /ai/connections
GET, PATCH, DELETE /ai/connections/{connection_id}
GET /ai/connections/usable
Model connections, ang mga AI provider na ginagamit ng mga AI feature at apps ng server: tingnan ang Model connections.
GET /channels/{channel_id}/message_actions
POST /posts/{post_id}/message_actions/{hook_id}
GET, POST /hooks/outgoing/{hook_id}/icon
Mga message actions: mga outgoing webhook na pinapatakbo ng mga tao mula sa menu ng mensahe. Tingnan ang Mga message actions.

Mga bagong field

  • Mga Komunidad (Team, at PUT /teams/{team_id}/patch): all_channels_membership (lahat ay nasa bawat channel na makikita nila), default_channel_id (saan darating ang mga bagong miyembro; ang walang laman ay ibig sabihin General), kind (community o workplace: sa workplace, ang mga admin ng channel ay maaari ring i-archive ang kanilang mga channel; ang mga bagong komunidad ay nakukuha ang TeamSettings.DefaultCommunityKind ng server, community bilang default), member_list_view (paano nag-uugnay ang listahan ng miyembro: choice, ang default, ay nagpapahintulot sa bawat miyembro na pumili; roles o teams ay pinaliliit), hide_role_colors, require_team_badges, onboarding at autolinks (parehong JSON string).
  • Ang default channel ng isang bagong community ay general (General), hindi naman town-square. Sa upgrade na 0.9.0, ipapalit ang pangalan ng town-square ng bawat community sa general, na mananatili ang ID nito, maliban kung mayroon na ang community ng general channel. Patuloy na gagana ang lumang mga pangalan: ang GET /teams/{team_id}/channels/name/town-square, GET /teams/name/{team}/channels/name/town-square, at ang channel ng isang incoming webhook ay ibinibigay ang default channel ng community kapag walang channel na may ganitong pangalan. Gamitin ang default_channel_id, o ang pangalan na general, sa bagong code.
  • Mga link ng channel: ang #channel-name ay naglilink ng channel, katulad ng ~channel-name. Ang channel_mentions prop ng post ay naglilista ng mga channel na naka-link sa anumang paraan; ang #word na hindi tumutukoy sa anumang channel ay mananatiling hashtag. Ang web interface at mobile app ng Antimatter ay nagbabasa ng #name.
  • Ang mga naka-archive na channel ay tumatanggap pa rin ng mga bagong miyembro (POST /channels/{channel_id}/members), na maaari basahin ang history nito. Walang makakapag-post, mag-reaction, mag-pin, ilagay ang mensahe sa itaas, palitan ang pangalan ng channel, o baguhin ang mga role ng miyembro nito.
  • Inline replies: isang post na may "props": {"reply_to": "<post id>"} ay nagqu-quote ng mensaheng iyon mula sa parehong channel. Magdagdag ng "reply_to_mention": false upang hindi maabot ng notisikasyon ang may-akda nito. Pupunan ng server ang metadata.reply_to ng maikling paglalarawan ng na-quote na mensahe.
  • Spoilers: ang "props": {"spoiler": true} ay nagtatago ng teksto at mga file ng post hanggang sa piliin ng mambabasa na ipakita.
  • Ang pag-i-ignore at pag-block ay mga preference: kategorya user_block, pinangalanan ayon sa ID ng ibang tao, na may halaga na ignore o block. Kung ang isang direct message ay naghihintay bilang request, nasa notify_props.dm_request ng iyong channel member (pending, accepted o dismissed).
  • Ang mga attachment ng mensahe ay maaaring magdala ng stages at chart: tingnan ang Cards.

Igalaw ang thread

Ang POST /posts/{post_id}/move_to_channel ay nagagalaw ng thread, ang unang mensahe nito, at lahat ng sagot, sa ibang channel ng parehong community. Ang post_id ay maaaring ang unang mensahe o anumang sagot.

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 (kailangan): ang channel na dadaan doon ang thread.
  • flatten (default false): ang true ay nagpapakita ng mga sagot bilang mga mensahe ng target channel sa halip na thread. Ginagamit ito ng Make it a channel ng Fusion.

Mananatili ang mga mensahe sa kanilang mga manunulat, oras, reaksyon, at mga file. Ang mga kopya nito ay may silent_notification prop, kaya hindi nagpapadala ng notisikasyon sa sinuman. Tinatanggal ang orihinal na mga mensahe. Ang sagot ay ang naipaglipat na unang mensahe, na may bagong ID.

Sino ang maaaring magalaw ng thread

  • Kailangan mong makabasa ng thread at makapag-post sa target channel.
  • Ang mga admin ng channel, ang mga admin ng community, ang mga taong may Pamahalaan ang mga mensahe (delete_others_posts) sa channel, at ang mga system admin ay maaaring magalaw ng anumang thread.
  • Ang may-akda ng thread ay maaari itong galawin kapag pampubliko ang parehong channel, o kapag ang lahat ng mensahe ng thread ay kanya. Kung hindi, ang sagot ay 403 na may ID na api.post.move_thread.private_needs_moderator.app_error.
  • Ang dalawang channel ay dapat nasa iisang community (walang direct o group messages), magkakaiba, at hindi naka-archive. Hindi maaaring ilipat ang mga system message at burn-on-read message.
  • Ang thread na mas mahaba sa WranglerSettings.MoveThreadMaxCount na mensahe (100 ang default; 0 para walang limit) ay hindi tatanggapin.

Ang pointer at ang tala

Ang paglipat ay nag-iwan ng dalawang system message ng uri system_wrangler: isang pointer sa lumang channel ("A thread with 13 messages has been moved to #target") at isang tala sa target ("This thread was moved from #source"), sa ilalim ng naipapatong thread o, gamit ang flatten, pagkatapos ng mga mensahe nito. Bukod sa teksto ng mensahe, ang props nito ay nagpapahintulot sa client na iguhit ang pangalan ng channel bilang link:

  • Ang pointer: MovedThreadPermalink, NumMessages, MovedThreadChannelId, MovedThreadTeamName, MovedThreadPostId, at, para sa pampublikong target, MovedThreadChannelName at MovedThreadChannelDisplayName.
  • Ang tala: MovedFromChannelId, MovedFromTeamName, MovedFromPostId (ang pointer), MovedFromPermalink, at, para sa pampublikong source, MovedFromChannelName at MovedFromChannelDisplayName.

May TranslationID rin sila. Ang pangalan ng pribadong channel ay hindi isasama: nakikita ng mga mambabasa ang "another channel". Ang sariling POST /posts/{post_id}/move ng Mattermost ay patuloy na hindi gagamitin sa Antimatter; gamitin ang endpoint na ito.

Mga model connection

Ang model connection ay ang address at key ng isang AI provider, na itinatag ng admin. Ginagamit ng mga AI feature ng server at ng mga app na tumatawag sa AI service. Inaangkin ng mga system admin ang mga server-wide na connection (manage_ai_connections); inaangkin ng mga admin ng isang community ang kanilang sariling connection (manage_team_ai_connections). Ang mga key ay write-only: walang sagot na may kasamang key, kundi api_key_set at api_key_last4.

EndpointGinagawa nito
GET /ai/connections?scope=Ang mga connection na inaangkin mo. Ang scope ay server o ang ID ng isang community; kung wala ito, lahat ng scope na inaangkin mo.
POST /ai/connectionsNagdaragdag ng connection (nagsasagot ng 201).
POST /ai/connections/test, POST /ai/connections/modelsSinusubok ang connection, o nakikita ang listahan ng mga model nito, bago ito na-save. Iisa ang body sa pagdaragdag; wala ang na-save.
GET, PATCH (o PUT), DELETE /ai/connections/{connection_id}Binabasa, binabago o tinatanggal ang connection. Ang patch ay may kasamang mga field na babagayin lamang; huwag isama ang api_key para manatili ang key.
POST /ai/connections/{connection_id}/testSinusubok ang na-save na connection: {"ok", "error", "status_code", "latency_ms", "model_count"}.
GET /ai/connections/{connection_id}/modelsMga modelong inaalok ng provider.
GET /ai/connections/{connection_id}/usageMga request at token ng buwan na ito.
GET /ai/connections/usable?channel_id=&team_id=Para sa sinumang naka-sign in: ang mga koneksyon na maaari mong gamitin doon, kasama ang kanilang mga model at kakayahan, ngunit hindi ang kanilang mga key o address.

Ang katawan ng bagong koneksyon:

{
  "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}
}

Ang provider ay openai_compatible o anthropic. Ang scope ay default na server; ang ID ng isang community ay nagpapatuloy na ito ay koneksyon ng community na iyon. Sa limits, ang 0 ay nangangahulugang walang limit; ang mga request bawat minuto ay binibilang sa bawat server, at ang token budget ay bawat buwan ng kalendaryo (UTC) para sa buong cluster. Ang sharing ay nagpapakita ng mga community na maaaring gumamit ng koneksyon sa buong server (ang mga direct at group message ay nangangailangan ng all_teams), at ang audience ay sinasabi kung sino ang maaari itong gamitin; ang mga bisita ay lamang kung may allow_guests. Ang mga pagbabago ay isinusulat sa audit log. Inuunawa ng admin guide ang mga setting: tingnan ang AI.