SAMA 0.37 API 详解

SAMA 0.37.2 双通道 API 详解:WebSocket JSON 包协议(60+ 路由按用户/会话/消息/文件/联系人/状态/加密/推送分域)与 HTTP 端点(/login、/health、/admin/*),全部给出 2026-10-30 实测请求与响应回显,覆盖认证链路、错误格式、预签名文件传输与包路由总表,注册/登录/频道/消息/文件 12 步全链路实测通过。

SAMA即时通讯SAMAWebSocketREST API2026/10/30

SAMA 0.37 API 详解

目标:面向要把 SAMA 集成进自己产品的开发者,讲清 0.37.2 的两套 API:WebSocket JSON 包协议(业务主体)与 HTTP 端点(认证 + 管理)。本文所有请求/响应均为 2026-10-30 实测回显(环境见 《SAMA 0.37 Docker Compose 部署指南》),路由定义与 APIs/JSON/routes/routes.js 逐条核对。

1. 协议总览

通道地址(实测映射)用途
WebSocket JSONws://<host>:8162(nginx → server 9001/9002 负载均衡)业务全量:用户/会话/消息/文件/联系人等 60+ 路由
HTTPhttp://<host>:8162GET /health、POST /login、POST /logout、GET /health-stats、/admin/* 管理域
TCPAPP_TCP_PORT 启用时(默认关)非 WS 客户端的透传通道

包格式:一条 WS 文本消息 = 一个 JSON 对象,键名即路由名(如 user_create、message)。服务端成功响应包裹在 {"response": {...}} 或动作专属键(如 {"ask": {...}})中,失败统一为 {"<路由名>":{"error":{"status":422,"message":"..."}}}。

2. 认证链路(实测完整时序)

① WS user_create(注册,免鉴权)
② HTTP POST /login → access_token(JWT)+ refresh_token HttpOnly Cookie
③ WS connect(携 token + device_id)→ 会话绑定
④ 之后所有 WS 路由经 authGuardMiddleware 鉴权

① 注册(organization_id 首次部署默认 default,见 《SAMA 0.37 Docker Compose 部署指南》 坑一):

→ {"user_create": {"organization_id": "default", "login": "alice",
    "password": "Passw0rd123", "email": "alice@test.local", "device_id": "dev-alice-1"}}
← {"response": {"user": {"native_id": "6ae3e58b...", "_id": "6ae3e58b...",
    "login": "alice", "email": "alice@test.local", "recent_activity": 1793320331,
    "created_at": "2026-10-30T00:32:11.081Z", "updated_at": "..."}}}

② 登录(旧 WS user_login 路由已标弃用,官方推荐 HTTP):

curl -s -X POST http://localhost:8162/login -H 'Content-Type: application/json' \
  -d '{"organization_id":"default","login":"alice","password":"Passw0rd123","device_id":"dev-alice-1"}'
← 200 {"user": {"_id": "6ae3e58b...", "login": "alice", ...},
       "access_token": "eyJhbGciOi...", "expired_at": "..."}
   Set-Cookie: refresh_token=s%3A...(HttpOnly; Secure; SameSite=Lax;有效期 JWT_REFRESH_TOKEN_EXPIRES_IN)

缺少 device_id 时实测报 'device_id' is required.。

③ WS 连接绑定会话:

→ {"connect": {"token": "<access_token>", "device_id": "dev-alice-1"}}
← {"response": {"success": true}}

token 过期实测回显:{"connect":{"error":{"status":422,"message":"The token has expired."}}},重新 /login 即可。登出用 POST /logout(读 Authorization 头或 refresh cookie),最后一个会话登出会广播离线状态。

3. 消息与会话(核心域实测)

创建频道(type:u 单聊 / g 群聊 / c 频道;g/c 必须带 name 与至少 1 个参与者,否则实测 422 Please select at least one user.):

→ {"conversation_create": {"type": "c", "name": "quzuo-test-channel",
    "description": "forensics channel", "participants": ["<bob _id>"]}}
← {"response": {"conversation": {"subscribers_count": 2,
    "_id": "6ae3e66a7b884607708c85d7", "type": "c", "name": "quzuo-test-channel",
    "description": "forensics channel", "owner_id": "<alice _id>",
    "organization_id": "default", "created_at": "...", "updated_at": "..."}}}

发消息(消息体平铺:id 为客户端消息号,cid 为会话 ID,x 为自定义扩展字段;响应键 ask):

→ {"message": {"id": "mid-001", "cid": "6ae3e66a...", "x": {}, "body": "Hello SAMA from quzuo!"}}
← {"ask": {"mid": "mid-001", "server_mid": "6ae3e66a7b884607708c85d8",
    "t": 1793320555, "modified": null, "bot_message": null}}

拉取消息(bob 端):

→ {"message_list": {"cid": "6ae3e66a...", "limit": 10}}
← {"message": {"_id": "6ae3e66a7b884607708c85d8", "cid": "6ae3e66a...",
    "c_type": "c", "from": "<alice _id>", "t": 1793320555,
    "body": "Hello SAMA from quzuo!", "x": {}, "updated_at": "...", "created_at": "..."}}

频道订阅(仅 type=c 且必须先订阅才能收后续推送):

→ {"conversation_subscribe": {"cid": "6ae3e66a..."}}   ← {"response": {"success": true}}

4. 文件传输(预签名 URL,实测)

① create_files  →  返回 upload_url(预签名 PUT)
② HTTP PUT 文件到 upload_url(实测 200)
③ message 携带 attachments(file_id = 返回的 object_id)
④ 接收方 get_file_urls → 预签名下载 URL(默认 7 天)
→ {"create_files": [{"name": "hello.txt", "size": 27, "content_type": "text/plain"}]}
← {"response": {"files": [{"_id": "6ae3e66a7b884607708c85d9",
    "name": "hello.txt", "size": 27, "content_type": "text/plain",
    "object_id": "2efc4cb0bbfdc0dab83c83f0", "organization_id": "default",
    "user_id": "<alice _id>", "upload_url": "http://<minio>:9000/samabucket/2efc4cb0...?X-Amz-Algorithm=AWS4-HMAC-SHA256&..."}]}}

注意:get_file_urls 按 object_id 查文件(源码 FileRepository.findByIdWithOrgScope 查询字段为 object_id),传 _id 会报 Can't find file(实测踩坑)。下载 URL 有效期由 FILE_DOWNLOAD_URL_EXPIRES_IN 控制(实测回显 X-Amz-Expires=604800)。

→ {"get_file_urls": {"file_ids": ["2efc4cb0bbfdc0dab83c83f0"]}}
← {"response": {"file_urls": {"2efc4cb0bbfdc0dab83c83f0": "http://<minio>:9000/samabucket/2efc4cb0...?X-Amz-Expires=604800&..."}}}

带附件发消息(attachments 数组,file_id 用 object_id):

→ {"message": {"id": "mid-002", "cid": "6ae3e66a...", "body": "",
    "attachments": [{"file_id": "2efc4cb0...", "file_name": "hello.txt",
                     "file_content_type": "text/plain", "file_size": 27}]}}
← {"ask": {"mid": "mid-002", "server_mid": "6ae3e66a7b884607708c85da", "t": 1793320555, ...}}

5. WS 路由总表(与 routes.js 逐条核对)

域路由
连接/探活ping、connect
用户user_create、user_edit、user_delete、user_login(弃用)、user_logout(弃用)、user_search、user_send_otp、user_reset_password、get_users_by_ids、user_last_activity、user_last_activity_subscribe、user_last_activity_unsubscribe
设备device_register、device_list、device_delete
会话conversation_create、conversation_list、conversation_update、conversation_delete、conversation_search、conversation_subscribe、conversation_unsubscribe、conversation_handler_create、conversation_handler_delete、get_conversation_handler、get_participants_by_cids、get_admins_by_cids
消息message、message_edit、message_delete、message_list、message_read、message_summary、message_tone、message_reactions_update、message_reactions_list、message_decryption_failed、system_message
文件create_files、get_file_urls
联系人contact_add、contact_batch_add、contact_update、contact_delete、contact_list
拉黑block_user、unblock_user、block_list_enable、list_blocked_users
状态typing、online_list、activity_status
加密request_keys(Signal 风格设备密钥交换)
推送push_subscription_create、push_subscription_delete、push_subscription_list、push_event_create
日志op_log_list

公共字段:ping → {"response":{"pong":{}}}(实测心跳保活);分页类路由支持 limit/offset;带 id 字段的路由会在响应中回带请求号。

6. HTTP 管理端点(/admin/*,实测结构)

以 Authorization: Bearer <HTTP_ADMIN_API_KEY> 调用,Key 错误实测 401。路由定义于 app/networking/protocol_processors/http.js:

端点方法用途
/healthGET健康检查,实测 {"status":"ok","hostname":"..."}
/health-statsGET无鉴权运行统计
/login / /logoutPOST用户认证(见 §2)
/admin/organizationPOST创建组织(多租户)
/admin/messagePOST/PUT/DELETE以管理员身份发/改/删消息
/admin/message/systemPOST发系统消息
/admin/message/readPUT标记已读
/admin/message/reactionPUT更新表情回应
/admin/activity/onlinePOST查询在线用户
/admin/server-statsGET服务器统计

7. 错误格式与排障

{"message": {"error": {"status": 422, "message": "'cid' field is required."}}}

实测高频错误:422 The token has expired.(token 过期重登)、422 Please select at least one user.(会话参与者为空)、422 'cid' field is required.(消息缺会话 ID)、401 Unauthorized.(未 connect 或未订阅即操作)、Can't find file(get_file_urls 误用 _id)。服务端日志 docker compose logs -f sama-server,日志级别见 《SAMA 0.37 配置参数详解》。

选型与架构背景:《SAMA 0.37 介绍与选型指南》。