REST API
ทุกสิ่งที่แอป Antimatter ทำจะผ่าน HTTP API เดียวกัน ดังนั้นสคริปต์ของคุณก็สามารถทำได้เช่นกัน หน้านี้จะอธิบายวิธีการยืนยันตัวตน ทรัพยากรที่คุณจะใช้งานบ่อยที่สุด รูปแบบของคำตอบและข้อผิดพลาด และวิธีการติดตามเหตุการณ์แบบเรียลไทม์ผ่าน WebSocket
พื้นฐาน
- URL ฐาน:
https://chat.example.com/api/v4ปลายทางทั้งหมดด้านล่างนี้จะเป็นค่าสัมพัทธ์จาก URL นี้ - ฟอร์แมต: รับและส่งออกข้อมูลเป็น JSON ยกเว้นการอัปโหลดไฟล์ (multipart) ส่ง
Content-Type: application/json - ID: ทุกออบเจกต์จะมี
idยาว 26 ตัวอักษร เวลาจะเป็นมิลลิวินาทีนับตั้งแต่ Unix epoch (create_at,update_at,delete_at; 0 หมายถึง "ไม่ถูกลบ") - ชุมชนคือทีม: API เรียกสิ่งเหล่านี้ว่า
teamsพร้อมteam_id - ตัวคุณเอง: ในทุกเส้นทางที่รับ
user_idคำว่าmeหมายถึงผู้ใช้ที่เข้าสู่ระบบ เช่นGET /users/me
รายการ endpoint ทั้งหมดอยู่ในโค้ดของเซิร์ฟเวอร์: routes ถูกประกาศใน server/channels/api4/*.go และ types อยู่ใน server/public/model คำอธิบาย OpenAPI ในโฟลเดอร์ api/v4/source ของ repository ครอบคลุม endpoint ที่สืบทอดมาจาก Mattermost และส่วนเพิ่มเติมบางส่วนของ Antimatter: การย้ายเธรด, การเชื่อมต่อโมเดล และการดำเนินการกับข้อความ ส่วนที่เหลือมีอยู่ในโค้ดเท่านั้น
การยืนยันตัวตน
ทุกคำขอ ยกเว้นการเข้าสู่ระบบและปลายทางสาธารณะบางรายการ ต้องมีโทเคนในหัว Authorization:
curl -H "Authorization: Bearer $TOKEN" https://chat.example.com/api/v4/users/me
ยอมรับโทเคนสามประเภท: โทเคนการเข้าถึงส่วนบุคคล, โทเคนเซสชัน และโทเคนการเข้าถึง OAuth Authorization: Token … ก็ถูกยอมรับเช่นกัน โทเคนในสตริงคำขอ (?access_token=) จะถูกยอมรับเฉพาะสำหรับโทเคนการเข้าถึง OAuth เท่านั้น
โทเคนการเข้าถึงส่วนบุคคล (แนะนำสำหรับสคริปต์)
โทเคนการเข้าถึงส่วนบุคคลจะทำงานในนามของคุณ ไม่หมดอายุเว้นแต่คุณกำหนดวันหมดอายุ และสามารถเพิกถอนได้ตลอดเวลา โทเคนการเข้าถึงส่วนบุคคลจะปิดอยู่เป็นค่าเริ่มต้น:
- ผู้ดูแลระบบเปิดใช้งาน เปิดใช้งานโทเคนการเข้าถึงส่วนตัว ใน คอนโซลระบบ › อินทิเกรชัน › การจัดการอินทิเกรชัน (
ServiceSettings.EnableUserAccessTokens,AM_SERVICESETTINGS_ENABLEUSERACCESSTOKENS) - สำหรับแต่ละบุคคลที่อาจสร้างโทเคน ผู้ดูแลระบบเปิด คอนโซลระบบ › การจัดการผ้้ใช้ › ผู้ใช้งาน เลือก จัดการบทบาท ในเมนูของบุคคลนั้น และทำเครื่องหมาย Allow this account to generate personal access tokens ผู้ดูแลระบบสามารถสร้างโทเคนได้เสมอ
- บุคคลนั้นเปิดอวตารที่มุมขวาบน จากนั้นไปที่ Profile & settings › ความปลอดภัย ภายใต้ โทเคนการเข้าถึงส่วนตัว ระบุวัตถุประสงค์ของโทเคนและเลือก สร้างโทเคน โทเคนจะแสดงเพียงครั้งเดียว: คัดลอกไว้
ผ่าน 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:
- ต้องเปิดใช้งาน เปิดใช้งานผู้ให้บริการ OAuth 2.0 (คอนโซลระบบ › อินทิเกรชัน › การจัดการอินทิเกรชัน,
ServiceSettings.EnableOAuthServiceProvider, เปิดใช้งานโดยค่าเริ่มต้น) - บุคคลที่มีสิทธิ์จัดการแอป OAuth (ผู้ดูแลระบบโดยค่าเริ่มต้น) เปิดอวตาร จากนั้นไปที่ อินทิเกรชัน › แอป OAuth 2.0 และเพิ่มแอปพร้อม URL สำหรับ callback พวกเขาจะได้รับ client ID และ client secret
- แอปพลิเคชันของคุณจะส่งผู้ใช้ไปยัง
https://chat.example.com/oauth/authorizeพร้อมresponse_type=code,client_id,redirect_uriและstateระบบรองรับ PKCE โดยใช้code_challenge_method=S256 - จากนั้นจะแลกเปลี่ยน code ที่
POST https://chat.example.com/oauth/access_token(ใช้grant_type=authorization_codeและใช้refresh_tokenเพื่อต่ออายุ) และเรียกใช้ API ด้วยAuthorization: Bearer <access token>
ผู้ใช้สามารถดูแอปที่พวกเขาอนุญาตใน Profile & settings › ความปลอดภัย › แอปที่คุณให้สิทธิ์
ทรัพยากรหลัก
| รายการ | Endpoints |
|---|---|
| คุณและผู้ใช้คนอื่น | 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 |
| ข้อความ (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 |
| รีแอคชัน | 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 (ตรวจสอบสถานะระบบ ไม่ต้องใช้ token), 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
การแบ่งหน้า
Endpoints แบบรายการจะรับ 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 ให้แก่ผู้ดูแลระบบของเซิร์ฟเวอร์: มันอยู่ในบันทึกเหตุการณ์ (logs).
การจำกัดอัตรา
การจำกัดอัตรามีค่าเริ่มต้นเป็นปิด เมื่อผู้ดูแลระบบเปิดใช้งาน (คอนโซลระบบ › สภาพแวดล้อม › การจำกัดอัตร) แต่ละไคลเอนต์จะได้รับ 10 คำขอต่อวินาทีพร้อมการกระแทก (bursts) 100 ครั้งโดยค่าเริ่มต้น นับตามที่อยู่ IP หรือตามผู้ใช้ คำตอบจะประกอบด้วย X-RateLimit-Limit, X-RateLimit-Remaining และ X-RateLimit-Reset; เมื่อเกินขีดจำกัด เซิร์ฟเวอร์จะตอบกลับด้วย 429 พร้อม header Retry-After ในหน่วยวินาที บาง endpoint เช่น การเข้าสู่ระบบ มีขีดจำกัดของตัวเองไม่ว่าการตั้งค่าจะเป็นอย่างไร
เขียนสคริปต์ที่รอและลองใหม่เมื่อได้รับ 429 และหลีกเลี่ยงการโพล (polling): ใช้การติดตาม 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>.
คุณยังสามารถส่งการกระทำ (actions) ได้ด้วย แต่ละอย่างมี 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(importgithub.com/mattermost/mattermost/server/public/model).model.NewAPIv4Client(url), แล้วclient.SetToken(token);model.NewWebSocketClient4(wsURL, token)ติดตามเหตุการณ์ Antimatter เพิ่มเมธอดสำหรับ endpoint ของตัวเอง เช่นUpdateMessageRequest,PutPostOnTopและExportChannel. - TypeScript: คลาส
Client4ของ@mattermost/clientในwebapp/platform/clientพร้อม type ในwebapp/platform/typesคัดลอกในคลัง Antimatter รวม endpoint ของ 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
endpoint และฟิลด์เหล่านี้ไม่มีในเซิร์ฟเวอร์ Mattermost ทุกตัวต้องมีการเซสชัน
| Endpoint | สิ่งที่ทำ |
|---|---|
GET /teams/{team_id}/user_attributes/fieldsPOST ทางเดียวกันPATCH, DELETE …/fields/{field_id} | คุณลักษณะของชุมชน: ฟิลด์โปรไฟล์ที่ผู้ดูแลระบบของชุมชนกำหนดให้กับสมาชิก (สูงสุด 20 ฟิลด์) สมาชิกสามารถอ่านได้; ผู้ดูแลระบบของชุมชนเป็นผู้สร้างและแก้ไข |
GET /teams/{team_id}/members/{user_id}/user_attributesPATCH ทางเดียวกันPOST /teams/{team_id}/user_attributes/values/search | ค่าของคุณลักษณะของสมาชิก ในรูปแบบ {field_id: value} สมาชิกตั้งค่าของตัวเองได้ (ยกเว้นฟิลด์ที่ผู้ดูแลระบบจัดการ); ผู้ดูแลระบบตั้งค่าของใครก็ได้ การค้นหาใช้ {"user_ids": [...]} (สูงสุด 200) |
GET /teams/{team_id}/timeoutsPUT /teams/{team_id}/members/{user_id}/timeoutGET /teams/{team_id}/members/{user_id}/moderation | Timeout: {"until": time, "reason": "…"} ป้องกันไม่ให้ใครบางคนโพสต์, ทำรีแอคชัน และอัปโหลดในชุมชนจนกว่าจะถึงเวลานั้น (สูงสุด 28 วัน); "until": 0 ยกเลิกการป้องกันนี้ มุมมองการดูแลระบบแสดงว่าพวกเขาเข้าร่วมเมื่อไหร่และโพสต์ไปมากแค่ไหนเมื่อไม่นานมานี้ |
GET /channels/{channel_id}/on_topPUT, 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}/overridesGET /channels/{channel_id}/overrides/effectiveGET, PUT /channels/{channel_id}/role_access | บทบาทหรือบุคคลสามารถทำอะไรได้บ้างในช่อง และบทบาทใดบ้างที่เห็นช่องท่ีถูกกั้นดวยบทบาท |
GET, PUT /teams/{team_id}/server_categoriesGET, PUT …/server_categories/overrides | หมวดหมู่ช่องท่ีชุมชนใช้ร่วมกัน และข้อยกเว้นท่ีใช้กวยช่องทุกช่องในหมวดหมู่นั้น |
GET /groups/{group_id}/team_rolePUT …/team_role/permissions | สิทธิ์ท่ีบทบาทของชุมชนให |
POST /teams/{team_id}/autolinks/preview | ทดสอบกฎการเชื่อมโยงอัตโนมัติ (autolink) ของชุมชนกวยข้อความ |
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/connectionsGET, PATCH, DELETE /ai/connections/{connection_id}GET /ai/connections/usable | การเชื่อมต่อโมเดล, ผู้ให้บริการ AI ที่ฟีเจอร์ AI และแอปของเซิร์ฟเวอร์ใช้: ดู การเชื่อมต่อโมเดล |
GET /channels/{channel_id}/message_actionsPOST /posts/{post_id}/message_actions/{hook_id}GET, POST /hooks/outgoing/{hook_id}/icon | การดำเนินการกับข้อความ: outgoing webhooks ที่ผู้ใช้เรียกใช้จากเมนูข้อความ ดู การดำเนินการกับข้อความ |
ฟิลด์ใหม่
- ชุมชน (
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 string) - ช่องเริ่มต้นของชุมชนใหม่คือ
general(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ของ webhook ที่เข้ามายังชี้ไปยังช่องเริ่มต้นของชุมชนเมื่อไม่มีช่องที่มีชื่อนั้น ใช้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ได้: ดู Cards.
ย้ายเธรด
POST /posts/{post_id}/move_to_channel ใช้ย้ายเธรด, ข้อความแรก และข้อความตอบกลับทั้งหมด ไปยังช่องอื่นในชุมชนเดียวกัน post_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ทำให้ข้อความตอบกลับกลายเป็นข้อความของช่องปลายทางแทนที่จะเป็นเธรด Make it a channel ของ Fusion ใช้ค่านี้
ข้อความยังคงผู้เขียน, เวลา, รีแอคชัน และไฟล์แนบไว้ สำเนาของข้อความเหล่านี้จะมีฟิลด์ silent_notification ทำให้ไม่มีการแจ้งเตือนให้ใคร ข้อความเดิมจะถูกลบไป คำตอบคือข้อความแรกที่ถูกย้าย พร้อม ID ใหม่
ใครสามารถย้ายเธรดได้
- คุณต้องสามารถอ่านเธรดนั้นได้ และสามารถโพสต์ในช่องปลายทางได้
- ผู้ดูแลระบบของช่อง, ผู้ดูแลระบบของชุมชน, ผู้ที่มีสิทธิ์ จัดการข้อความ (
delete_others_posts) ในช่อง และผู้ดูแลระบบระดับระบบ สามารถย้ายเธรดใดก็ได้ - ผู้เขียนเธรดสามารถย้ายได้เมื่อช่องทั้งสองเป็นช่องสาธารณะ หรือเมื่อข้อความทุกข้อในเธรดเป็นของผู้เขียนนั้น หากไม่เป็นไปตามเงื่อนไข คำตอบจะเป็น
403พร้อม IDapi.post.move_thread.private_needs_moderator.app_error - ช่องทั้งสองต้องอยู่ในชุมชนเดียวกัน (ไม่รวมข้อความส่วนตัวหรือข้อความกลุ่ม) ต้องเป็นคนละช่อง และต้องไม่ได่เก็บถาวรแล้ว ไม่สามารถเคลื่อนข้อความระบบหรือข้อความที่หายหลังหว่้อ่านแล้วได้
- เธรดที่ยาวกว่่า
WranglerSettings.MoveThreadMaxCountข้อความ (ค่าเริ่มต้น 100; 0 หมายถิงไม่มีขั้่น) จะถูกปัดถอย
พอย์เตอร์และโน้ต
การเคลื่อนข้่าจะทิ้่งข้อความระบบ 2 ข้อความประเภท system_wrangler: พอย์เตอร์ในช่องเดิม ("เธรดที่มี 13 ข้อความได่ถูกเคลื่อนไป #target") และโน้ตในช่องปลายทาง ("เธรดนี้ได่ถูกเคลื่อนมาจาก #source") ท่ีอย่ใตเธรดท่ีถูกเคลื่อน หรือ, เม่อใช flatten, ท่ีอย่หลั่้งข้อความของเธรด นอ่กจากเนื้่อความของข้อความแล้ว, props ของข้อความเหล่านี้ยอมให้ไคลเอนต์วาดเนื้่อความของช่องเป็นลิงก์ได้:
- พอย์เตอร์:
MovedThreadPermalink,NumMessages,MovedThreadChannelId,MovedThreadTeamName,MovedThreadPostIdและ, สำหรับช่องปลายทางสาธารณะ,MovedThreadChannelNameและMovedThreadChannelDisplayName. - โน้ต:
MovedFromChannelId,MovedFromTeamName,MovedFromPostId(พอย์เตอร์),MovedFromPermalinkและ, สำหรับช่องต้นตอสวนสาธารณะ,MovedFromChannelNameและMovedFromChannelDisplayName.
ทั้งสองย้งมี TranslationID ด้วย เนื้่อความของช่องส่วนตัวจะไม่ถูกแสดง: ผู้อ่านจะเห็น "ช่องอื่่น" POST /posts/{post_id}/move ของ Mattermost เองจะปิดอย่ใน Antimatter; ให่ใชเอนดพอยต์นี้
การเชื่อมต่อโมเดล
การเชื่อมต่อโมเดลคือที่อยู่และคีย์ของผู้ใหบริการ AI ท่ีผู้ดูลแลระบบตั้้งค่าไว้ ฟีเจอร์ AI ของเซิร์ฟเวอร์และแอปท่ีเรียกใช้บริการ AI ใชสิ่งเหล่านี้ ผู้ดูลแลระบบจัดการการเชื่อมต่อท่ีใชทั้้งเซิร์ฟเวอร์ (manage_ai_connections); ผู้ดูลแลของชุมชนจัดการการเชื่อมต่อของชุมชนตนเอง (manage_team_ai_connections). คีย์เขียนเท่านั้้น: คำตอบไม่มีคีย์, มีเพี่่ง api_key_set และ api_key_last4 เท่านั้้น
| Endpoint | สิ่งที่ทำ |
|---|---|
GET /ai/connections?scope= | การเชื่อมต่อท่ีคุณจัดการ scope คือ server หรือ ID ของชุมชน; เม่อไม่มี, ทุ่ก scope ท่ีคุณจัดการ |
POST /ai/connections | เพิ่่มการเชื่อมต่อ (ตอบ 201). |
POST /ai/connections/test, POST /ai/connections/models | ทดสอบการเชื่อมต่อ หรือลิสต์โมเดลของมัน, ก่อนท่ีจะบันทึกลง. ใช body เดียวกับการเพิ่่ม; ไม่มีสิ่่งใดถูกบันทึก |
GET, PATCH (หรือ PUT), DELETE /ai/connections/{connection_id} | อ่าน, เปลี่่ยน หรือลบการเชื่อมต่อ. patch ใชเพี่่งฟิลด์ท่ีจะเปลี่่ยน; ให่ละ 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; ID ของชุมชนท่ีตง้ั จะทำใหเ้ป็นการเช่ือมตอ่ ของชุมชนนั้ น ใน limits 0 หมายถงึ ไม่มขี ีดจำกัด; คำขอตอ่ นาทีจะนับบนแตล่ะเซิร์ฟเวอร์ และงบประมาณโทเคนตอ่ เดือนปฏิทิน (UTC) สำหรบัคลัสเตอร์ทัง้ หมด sharing ระบุว่าชุมชนใดสามารถใชก้ ารเช่ือมตอ่ ท่ีทัว่ เซิร์ฟเวอร์ได้ (ข้้อความสว่ นตวัและข้้อความกลุ่่มตอ้ งการ all_teams), และ audience ระบุว่าใครสามารถใชไ้ ด้; แขกไดเ้พยีงในกรณทีี่ allow_guests การเปลยี่ นแปลงจะถกู บันทึกลงในบันทึกการตรวจสอบ (audit log) คู่มือผ้ดู แลระบบอธิบายการตัง้ ค่า: ดู AI