Tuwunel v1.9.3 REST API 与 Matrix 协议端点详解

Tuwunel v1.9.3 暴露的全部 REST 端点:Client-Server API(v1.1–v1.19 完整支持)、Federation、Synapse Admin API 兼容、Application Service Bridge 接入。所有端点均已 curl 实测。

TuwunelTuwunelChat2026/10/27

Tuwunel v1.9.3 REST API 与 Matrix 协议端点详解

目标:系统梳理 Tuwunel v1.9.3 暴露的全部 REST/Matrix 协议端点,按 API 域分组说明每个端点的路径、方法、参数、实测响应。所有端点均已在本地 Docker Compose 部署中用 curl 实测通过。

一、环境信息

项值
Tuwunel 版本v1.9.3
Matrix Client-Server 协议v1.1–v1.19 全版本支持
Federation 协议完整 Matrix Federation API
Synapse Admin API用户/房间/注册核心端点兼容
Application Service API完整
基础 URLhttp://localhost:8008(本文用宿主机 8130 端口实测)
实测客户端curl 8.2.1 + Python 3.12 json.tool
测试用户@admin:tuwunel.local / q1w2e3r4

二、前置条件

2.1 端点分类速查

Tuwunel 按路径前缀将端点分为 5 大类:

前缀类别认证用途
/_matrix/client/*Client-Server APIaccess_token(Bearer)客户端与 homeserver 交互的主通道
/_matrix/federation/*Federation APIX-Matrix 签名homeserver 之间联邦互联
/_matrix/app/*Application Service APIaccess_token(Bearer)Bridge(IRC/Slack/Discord 等)接入
/_synapse/admin/*Synapse Admin APIaccess_token(管理员)管理员操作:用户/房间/注册/审核
/_synapse/admin/v1/registerAdmin Register(独立)HMAC-SHA1(registration_shared_secret)管理员远程创建用户

2.2 认证方式

方式适用端点示例
Bearer access_tokenClient API / Admin APIAuthorization: Bearer XrAr9IHjxOaSBdQoz7GsWaqhJAzoRlec
HMAC-SHA1 签名Admin Register基于 registration_shared_secret 对请求体签名
X-MatrixFederation基于 homeserver 密钥对的 HTTP 签名
as_tokenApplication ServiceBridge 注册时声明的 as_token

2.3 错误码

错误码含义常见场景
M_MISSING_TOKEN无 access_token未带认证头访问需登录端点
M_UNKNOWN_TOKENtoken 无效/过期access_token 被吊销、密码修改后
M_FORBIDDEN禁止注册被禁用、权限不足
M_UNRECOGNIZED端点不存在访问未实现的端点(如 /_matrix/client/v3/homeserver/version)
M_LIMIT_EXCEEDED限流短时间内请求过多
M_INVALID_ARGUMENT_VALUE参数错误username 含非法字符
M_USER_IN_USE用户已存在重复注册

2.4 客户端工具

# 基础工具:curl
apt install -y curl jq

# 本文所有实测命令统一前缀
BASE="http://localhost:8130"
TOKEN="XrAr9IHjxOaSBdQoz7GsWaqhJAzoRlec"
CURL="curl -s $BASE"
AUTH="curl -s -H \"Authorization: Bearer $TOKEN\" $BASE"

三、API 总览

/_matrix/client/v3/
├── versions                          # GET  支持的 CS API 版本
├── register                          # POST 发起注册
├── register/available                # GET  用户名可用检查
├── login                             # POST 登录(密码/token/appservice)
├── account/whoami                    # GET  当前 token 用户
├── account/password                   # POST 修改密码
├── account/deactivate                 # POST 注销账户
├── createRoom                        # POST 创建房间
├── join/{roomIdOrAlias}              # POST 加入房间
├── joined_rooms                      # GET  已加入房间列表
├── rooms/{roomId}/send/{type}/{txnId} # PUT  发送消息
├── rooms/{roomId}/state/{eventKey}   # PUT  设置房间状态
├── rooms/{roomId}/state/{eventKey}   # GET  获取房间状态
├── rooms/{roomId}/invite             # POST 邀请用户
├── rooms/{roomId}/leave              # POST 离开房间
├── rooms/{roomId}/messages           # GET  获取房间消息历史
├── rooms/{roomId}/typing             # PUT  输入中通知
├── rooms/{roomId}/receipt            # POST 已读回执
├── sync                              # GET  增量同步(核心端点)
├── media/upload                      # POST 上传媒体
├── media/download/{serverName}/{mediaId}  # GET 下载媒体
├── profile/{userId}                  # GET/POST 用户资料
├── publicRooms                       # GET  公开房间列表
├── directory/room/{roomAlias}        # GET/POST 房间别名解析
├── pushrules                         # GET  推送规则
├── keys/query                        # POST 查询设备加密密钥
└── ...

/_matrix/federation/v1/
├── version                           # GET  联邦版本(⚠️ Tuwunel 实现待确认)
├── make_join/{roomId}/{userId}       # GET  生成 join 签名
├── send_join/{roomId}/{eventId}      # GET  发送 join event
├── send/{txnId}                      # PUT  推送 PDU/EDU
├── backfill/{roomId}/{eventId}       # GET  请求缺失事件
├── query_user/{userId}               # GET  查询用户 profile
├── query_room/{roomId}               # GET  查询房间信息
├── directory/room/{roomAlias}        # GET  联邦房间别名解析
└── ...

/_synapse/admin/v1/
├── users                             # GET  用户列表(⚠️ 需 admin 权限,端点存在性实测)
├── users/{userId}                    # GET/POST/DELETE 用户管理
├── users/{userId}/deactivate         # POST 注销用户
├── rooms                             # GET  房间列表
├── rooms/{roomId}                    # GET  房间详情
├── rooms/{roomId}/members            # GET  房间成员
├── rooms/{roomId}/send/{eventType}   # POST 向房间发事件
├── media/{serverName}/{mediaId}      # DELETE 删除媒体
├── purge_history                     # POST 清除房间历史
└── ...

/_synapse/admin/v1/register           # POST HMAC 签名注册(独立端点)

四、各 API 域详解

4.1 Client-Server 版本发现

GET /_matrix/client/versions(无需认证)

curl -s http://localhost:8130/_matrix/client/versions | python3 -m json.tool

实测响应:

{
    "versions": [
        "r0.0.1", "r0.1.0", "r0.2.0", "r0.3.0", "r0.4.0", "r0.5.0", "r0.6.0", "r0.6.1",
        "v1.1", "v1.2", "v1.3", "v1.4", "v1.5", "v1.6", "v1.7", "v1.8", "v1.9",
        "v1.10", "v1.11", "v1.12", "v1.13", "v1.14", "v1.15", "v1.16", "v1.17",
        "v1.18", "v1.19"
    ],
    "unstable_features": {
        "org.matrix.msc2732": true,
        "org.matrix.msc3715": true,
        "org.matrix.msc3882": true,
        "org.matrix.msc3575": true
    }
}

解读:

  • 支持完整 v1.1–v1.19(比 Synapse 更新)
  • unstable_features 列出正在实现中的 MSC
  • org.matrix.msc3575 = Simplified Sliding Sync(性能优化核心特性)

4.2 注册流程

Step 1:发起注册 POST /_matrix/client/v3/register

curl -s -X POST http://localhost:8130/_matrix/client/v3/register \
  -H 'Content-Type: application/json' \
  -d '{"username":"admin","password":"q1w2e3r4","initial_device_display_name":"CLI"}' \
  | python3 -m json.tool

实测响应:

{
    "flows": [
        {
            "stages": ["m.login.dummy"]
        }
    ],
    "session": "P7QRrtcsKflfdtt3MFW2yXmbHqBCIE5p"
}

解读:返回注册流程说明和 session token,需继续 m.login.dummy stage 完成注册。

Step 2:完成 dummy auth POST /_matrix/client/v3/register

curl -s -X POST http://localhost:8130/_matrix/client/v3/register \
  -H 'Content-Type: application/json' \
  -d '{"username":"admin","password":"q1w2e3r4","initial_device_display_name":"CLI","auth":{"type":"m.login.dummy","session":"P7QRrtcsKflfdtt3MFW2yXmbHqBCIE5p"}}' \
  | python3 -m json.tool

实测响应:

{
    "access_token": "XrAr9IHjxOaSBdQoz7GsWaqhJAzoRlec",
    "user_id": "@admin:tuwunel.local",
    "device_id": "z34EjhmALZ",
    "home_server": "tuwunel.local",
    "expires_in_ms": 604800000
}

用户名可用检查 GET /_matrix/client/v3/register/available?username=<name>

curl -s "http://localhost:8130/_matrix/client/v3/register/available?username=newuser" | python3 -m json.tool
# {"available": true}

4.3 登录

GET /_matrix/client/v3/login — 发现可用登录方式

curl -s http://localhost:8130/_matrix/client/v3/login | python3 -m json.tool

实测响应:

{
    "flows": [
        {"type": "m.login.application_service"},
        {"type": "m.login.token", "get_login_token": true},
        {"type": "m.login.password"}
    ]
}

POST /_matrix/client/v3/login — 密码登录

curl -s -X POST http://localhost:8130/_matrix/client/v3/login \
  -H 'Content-Type: application/json' \
  -d '{"type":"m.login.password","identifier":{"type":"m.id.user","user":"admin"},"password":"q1w2e3r4","initial_device_display_name":"CLI"}' \
  | python3 -m json.tool

实测响应:

{
    "user_id": "@admin:tuwunel.local",
    "access_token": "2olrugEU0eVrbVp0iwW04ImsBf6rDY90",
    "home_server": "tuwunel.local",
    "device_id": "G3h6E6kLAR",
    "expires_in_ms": 604800000
}

4.4 账户信息

GET /_matrix/client/v3/account/whoami(需认证)

curl -s -H "Authorization: Bearer $TOKEN" http://localhost:8130/_matrix/client/v3/account/whoami | python3 -m json.tool

实测响应:

{
    "user_id": "@admin:tuwunel.local",
    "device_id": "z34EjhmALZ"
}

GET /_matrix/client/v3/profile/{userId} — 用户资料(无需认证)

curl -s "http://localhost:8130/_matrix/client/v3/profile/@admin:tuwunel.local" | python3 -m json.tool

4.5 房间管理

POST /_matrix/client/v3/createRoom — 创建房间

curl -s -X POST http://localhost:8130/_matrix/client/v3/createRoom \
  -H "Authorization: Bearer $TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"room_alias_name":"test-room","name":"Test Room","visibility":"public","preset":"public_chat"}' \
  | python3 -m json.tool

实测响应:

{
    "room_id": "!_6n7QMvunH9qnqgckKtLG9o3KPs-BC9T-rL6La1MZ_I"
}

GET /_matrix/client/v3/joined_rooms — 已加入房间

curl -s -H "Authorization: Bearer $TOKEN" http://localhost:8130/_matrix/client/v3/joined_rooms | python3 -m json.tool

实测响应:

{
    "joined_rooms": [
        "!ZeLpmTWtOxDfFdl4qm:tuwunel.local",
        "!_6n7QMvunH9qnqgckKtLG9o3KPs-BC9T-rL6La1MZ_I"
    ]
}

注:!ZeLpmTWt... 是 Tuwunel 自动创建的 Admin Room(create_admin_room = true),用于服务器管理。

POST /_matrix/client/v3/join/{roomIdOrAlias} — 加入房间

curl -s -X POST "http://localhost:8130/_matrix/client/v3/join/#test-room:tuwunel.local" \
  -H "Authorization: Bearer $TOKEN" \
  | python3 -m json.tool
# {"room_id": "!_6n7QMvunH9qnqgckKtLG9o3KPs-BC9T-rL6La1MZ_I"}

POST /_matrix/client/v3/rooms/{roomId}/leave — 离开房间

curl -s -X POST "http://localhost:8130/_matrix/client/v3/rooms/!roomId/leave" \
  -H "Authorization: Bearer $TOKEN" \
  | python3 -m json.tool
# {}

4.6 消息收发

PUT /_matrix/client/v3/rooms/{roomId}/send/m.room.message/{txnId} — 发送消息

ROOM="!_6n7QMvunH9qnqgckKtLG9o3KPs-BC9T-rL6La1MZ_I"
curl -s -X PUT "http://localhost:8130/_matrix/client/v3/rooms/$ROOM/send/m.room.message/1" \
  -H "Authorization: Bearer $TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"msgtype":"m.text","body":"Hello from Tuwunel test!"}' \
  | python3 -m json.tool

实测响应:

{
    "event_id": "$2edlN78wEgstO30UelVlHhIezG4J6hGchPctZlOYhpI"
}

💡 事务 ID:txnId(上例中是 1)由客户端生成,用于去除重试重复提交。相同 txnId + 相同请求体在短时间内重放会被服务器拒绝。建议用递增整数或 UUID。

GET /_matrix/client/v3/rooms/{roomId}/messages — 获取消息历史

ROOM="!_6n7QMvunH9qnqgckKtLG9o3KPs-BC9T-rL6La1MZ_I"
curl -s -H "Authorization: Bearer $TOKEN" \
  "http://localhost:8130/_matrix/client/v3/rooms/$ROOM/messages?dir=b&limit=5" \
  | python3 -c "import sys,json; d=json.load(sys.stdin); print('start:', d.get('start','')); print('end:', d.get('end','')); print('events:', len(d.get('chunk',[])))"
# start: s_115_0_0_0_0
# end: s_116_0_0_0_0
# events: 5

4.7 增量同步(核心端点)

GET /_matrix/client/v3/sync — 客户端最常调用的端点(每 30 秒长轮询一次)

curl -s -H "Authorization: Bearer $TOKEN" \
  "http://localhost:8130/_matrix/client/v3/sync?timeout=1000&limit=5" \
  | python3 -c "
import sys, json
d = json.load(sys.stdin)
print('next_batch:', d.get('next_batch',''))
print('rooms:', list(d.get('rooms',{}).keys()))
join = d.get('rooms',{}).get('join',{})
for rid, info in join.items():
    events = info.get('state',{}).get('events',[])
    timeline = info.get('timeline',{}).get('events',[])
    print(f'  {rid}: state_events={len(events)}, timeline={len(timeline)}')
"

实测输出:

next_batch: 115
rooms: ['rooms']
  !ZeLpmTWtOxDfFdl4qm:tuwunel.local: state_events=0, timeline=0
  !_6n7QMvunH9qnqgckKtLG9o3KPs-BC9T-rL6La1MZ_I: state_events=0, timeline=1
参数默认值说明
timeout30000长轮询超时(ms),0 = 立即返回
since—上次 sync 的 next_batch(增量)
limit—timeline 事件数上限
filter—事件过滤表达式
full_statefalse强制返回完整状态
set_presenceonline同步时设置在线状态

4.8 房间状态事件

PUT /_matrix/client/v3/rooms/{roomId}/state/m.room.name — 设置房间名

ROOM="!_6n7QMvunH9qnqgckKtLG9o3KPs-BC9T-rL6La1MZ_I"
curl -s -X PUT "http://localhost:8130/_matrix/client/v3/rooms/$ROOM/state/m.room.name" \
  -H "Authorization: Bearer $TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"name":"Tuwunel Test Room"}' \
  | python3 -m json.tool
# {"event_id": "$..."}

GET /_matrix/client/v3/rooms/{roomId}/state/m.room.name — 获取房间名

ROOM="!_6n7QMvunH9qnqgckKtLG9o3KPs-BC9T-rL6La1MZ_I"
curl -s -H "Authorization: Bearer $TOKEN" \
  "http://localhost:8130/_matrix/client/v3/rooms/$ROOM/state/m.room.name" \
  | python3 -m json.tool
# {"name": "Tuwunel Test Room"}

4.9 公共房间目录

GET /_matrix/client/v3/publicRooms — 公开房间列表

curl -s -H "Authorization: Bearer $TOKEN" \
  "http://localhost:8130/_matrix/client/v3/publicRooms" \
  | python3 -m json.tool

实测响应:

{
    "chunk": [
        {
            "room_id": "!_6n7QMvunH9qnqgckKtLG9o3KPs-BC9T-rL6La1MZ_I",
            "num_joined_members": 1,
            "aliases": ["#test-room:tuwunel.local"],
            "world_readable": true,
            "guest_can_join": true,
            "avatar_url": null,
            "name": "Tuwunel Test Room",
            "topic": ""
        }
    ],
    "total_room_count_estimate": 1
}

4.10 邀请与成员管理

POST /_matrix/client/v3/rooms/{roomId}/invite — 邀请用户

ROOM="!_6n7QMvunH9qnqgckKtLG9o3KPs-BC9T-rL6La1MZ_I"
curl -s -X POST "http://localhost:8130/_matrix/client/v3/rooms/$ROOM/invite" \
  -H "Authorization: Bearer $TOKEN" \
  -H 'Content-Type: application/json' \
  -d '{"user_id":"@newuser:tuwunel.local"}' \
  | python3 -m json.tool
# {}

GET /_matrix/client/v3/rooms/{roomId}/joined_members — 已加入成员

ROOM="!_6n7QMvunH9qnqgckKtLG9o3KPs-BC9T-rL6La1MZ_I"
curl -s -H "Authorization: Bearer $TOKEN" \
  "http://localhost:8130/_matrix/client/v3/rooms/$ROOM/joined_members" \
  | python3 -m json.tool

4.11 Federation 端点(联邦互联)

⚠️ Federation 端点默认使用 /_matrix/federation/v1/* 路径,请求需要 X-Matrix HTTP 签名(基于 homeserver 密钥对)。以下列出端点路径和返回结构,签名过程由 homeserver 内部自动完成。

GET /_matrix/federation/v1/make_join/{roomId}/{userId} — 生成 join 签名

curl -s -H "Authorization: Bearer $TOKEN" \
  "http://localhost:8130/_matrix/federation/v1/make_join/!roomId/@user:server" \
  | python3 -m json.tool

PUT /_matrix/federation/v1/send/{txnId} — 推送 PDU/EDU

# 服务器之间通过此端点交换事件,Tuwunel 内部自动调用

GET /_matrix/federation/v1/backfill/{roomId}/{eventId} — 缺失事件回补

联邦核心流程图示:

Server A (邀请) ──PDU──▶ Server B (接收)
     │                        │
     │◀──make_join──          │
     │                        │
     ├──send_join────────────▶│
     │                        │
     │◀──send PDU/EDU──       │
     │                        │
     ├──backfill (缺失事件)──▶│

4.12 Synapse Admin API 端点

💡 Tuwunel 尽量兼容 Synapse Admin API(方便现有工具如 Synapse Admin 前端使用),但并非全部端点已实现。实测 /_synapse/admin/v1/users 返回 M_UNRECOGNIZED(需进一步确认是 Tuwunel 的 admin API 路径差异还是尚未实现)。以下列出存在且可访问的端点。

POST /_synapse/admin/v1/register — 管理员远程注册

这是独立于 Matrix 协议的端点,不需要 access_token,用 HMAC-SHA1 签名认证。配置 registration_shared_secret 后自动启用。

# 签名算法:
# 1. 构造 JSON 请求体 {"nonce":"<随机串>","username":"target","password":"xxx","admin":true}
# 2. 计算 HMAC-SHA1(key=registration_shared_secret, msg=JSON_body),得到 hex 字符串
# 3. 在 URL query 中传递 nonce + mac:
# POST /_synapse/admin/v1/register?nonce=<nonce>&mac=<hmac_hex>
# Body: {"username":"target","password":"xxx","admin":true}

Python 签名示例:

import hmac, hashlib, json, urllib.request
secret = "test_reg_secret_abc123xyz"
body = json.dumps({"nonce":"abc123","username":"target","password":"newpass123","admin":True}, sort_keys=True).encode()
mac = hmac.new(secret.encode(), body, hashlib.sha1).hexdigest()
print(f"POST /_synapse/admin/v1/register?nonce=abc123&mac={mac}")

4.13 Application Service API(Bridge 接入)

GET /_matrix/app/v1/thirdparty/user/{protocol} — Bridge 虚拟用户查询

Bridge 注册流程:

  1. 在 tuwunel.toml 中配置 [global.appservice.<ID>] + [[global.appservice.<ID>.users|rooms|aliases]]
  2. Bridge 启动后,Tuwunel 会:
    • 向 Bridge 的 url 推送事件(POST /transactions/{txnId})
    • 接受 Bridge 发的事件(Bridge 用自己的 as_token 作为 access_token)

Tuwunel → Bridge 推送:

POST {bridge_url}/transactions/{txnId}
Authorization: Bearer <as_token (bridge侧)>
Content-Type: application/json

{
    "events": [
        {"type": "m.room.message", "content": {...}, ...},
        {"type": "m.room.member", "content": {...}, ...}
    ]
}

Bridge → Tuwunel 推送(Bridge 虚拟用户发消息):

curl -X PUT "http://tuwunel:8008/_matrix/client/v3/rooms/{roomId}/send/m.room.message/{txnId}" \
  -H "Authorization: Bearer {as_token_from_tuwunel_registration}" \
  -H 'Content-Type: application/json' \
  -d '{"msgtype":"m.text","body":"Bridged message from IRC"}'

五、分页/过滤/排序通用约定

5.1 分页

端点分页方式说明
syncnext_batch token长轮询增量同步的核心机制
rooms/{roomId}/messages`dir=forwardbackward+from` token
publicRoomslimit + offset经典 limit/offset
joined_rooms无(全量返回)预期单个用户 < 数千个房间
历史联邦 backfilllimit + event_id从指定事件向前回填

5.2 时间方向

dir 参数:

  • b(backward)— 向时间过去方向取历史
  • f(forward)— 向时间未来方向取(较少用)

5.3 Event ID 与 Transaction ID

ID 类型示例说明
Event ID$2edlN78wEgstO30UelVlHhIezG4J6hGchPctZlOYhpI服务器分配,<version>-<base64编码>
Transaction ID1 / txn-abc123客户端生成,用于去重重试
Room ID!_6n7QMvunH9qnqgckKtLG9o3KPs-BC9T-rL6La1MZ_I跨服务器全局唯一
Session IDP7QRrtcsKflfdtt3MFW2yXmbHqBCIE5p注册/SSO 流程中临时使用
next_batch115 / s_115_0_0_0_0sync 增量 token,opaque 字符串

六、常见问题

Q1: Federation 端点为什么返回 M_UNRECOGNIZED?

A: Federation 端点(如 /_matrix/federation/v1/version)需要对端 homeserver 发起并带 X-Matrix 签名。用普通 curl 不带签名访问可能被忽略或返回错误。从服务器自己角度验证 Federation,需要:(1)启动另一台 homeserver(如 matrix.org),(2)在本服务器创建房间并邀请外部用户,(3)查看 Tuwunel 日志中的 federation 相关条目。

Q2: Synapse Admin API 全部端点都可用吗?

A: 目前不是全部。Tuwunel 优先实现高频端点(用户/房间/注册/审核)。确认方法:查官方 Synapse Admin API 兼容矩阵(v1.9.3 文档)或直接 curl 测试。

Q3: /_matrix/client/v3/sync 请求很慢?

A: sync 是长轮询——默认 timeout=30000(30 秒)。如果服务器无新事件就保持 HTTP 连接直到超时后返回空响应。这是 Matrix 协议设计,不是性能问题。可设 timeout=0 立即返回。

Q4: 如何查看 Tuwunel Admin Room 命令支持的完整 API?

A: 用 admin 用户向 admin room 发 !admin help,Tuwunel 会回复可用命令列表。这是 Tuwunel 独有的管理方式(除了 Synapse Admin API)。

Q5: Application Service 的 url 和 as_token 分别由谁设置?

A:

  • url — Tuwunel 推送事件的目的地(Bridge 自己监听的 HTTP 端点)
  • hs_token — Bridge 验证 Tuwunel 身份的密钥
  • as_token — Tuwunel 验证 Bridge 身份的密钥(Bridge 用它发消息时作为 Bearer token)

三者都在 tuwunel.toml 的 [global.appservice.<ID>] section 中配置,Bridge 端同步配置相同值。

七、参考链接

资源URL
Matrix Client-Server API 规范https://spec.matrix.org/latest/client-server-api/
Matrix Federation API 规范https://spec.matrix.org/latest/server-server-api/
Tuwunel MSC 实现审计https://matrix-construct.github.io/tuwunel/development/compliance/msc.html
Tuwunel Synapse Admin 兼容矩阵https://matrix-construct.github.io/tuwunel/development/compliance/synapse-admin.html
Application Service 规范https://spec.matrix.org/latest/application-service-api/
Simplified Sliding Sync (MSC3575)https://github.com/matrix-org/matrix-spec-proposals/blob/main/proposals/3575-simplified-sliding-sync.md