服务器-服务器 API

本页面的翻译未经核对,可能存在翻译质量不佳、错翻、漏翻等情况。您可以在 Forgejo 存储库 打开 Issue、提交 Pull Request 或邮件联系我们提出改进建议和参与翻译与核对。

Matrix 家服务器(homeservers)之间通过联邦 API(亦称为服务器-服务器 API)进行通信。家服务器利用这些 API 实时互投消息、检索彼此的历史消息,并查询关于对方服务器上用户的资料和在线状态等信息。

这些 API 通过各服务器之间的 HTTPS 请求实现。HTTPS 请求在 TLS 传输层和 HTTP 层的 Authorization 头内均需使用公钥签名进行强认证。

家服务器之间主要有三种通信方式:

持久化数据单元(PDU): 这些事件会从一个家服务器广播到加入同一房间(由房间 ID 标识)的其他任意服务器。它们会被持久化用于记录房间消息和状态的历史。

类似电子邮件,PDU 的原始服务器负责将该事件传递给目标服务器。然而,PDU 使用原始服务器的私钥签名,因此可以通过第三方服务器进行传递。

短暂数据单元(EDU): 这些事件在家服务器对之间点对点推送。它们不会被持久化,也不是房间历史的一部分,接收的家服务器也无需回复。

查询请求(Queries): 这是由一方发起、向另一方发送 HTTPS GET 请求以获取某些信息,并由对方应答的单次请求/响应交互。不会被持久化,也不包含任何长期历史,仅请求查询发起瞬间的快照状态。

EDU 和 PDU 进一步被封装在一个称为事务(Transaction)的信封中,通过 HTTPS PUT 请求从源服务器传送至目标家服务器。

API 标准

Matrix 服务器-服务器通信的强制基准是通过 HTTPS API 交换 JSON 对象。未来可能会指定更高效的传输方式作为可选扩展。

所有的 POSTPUT 端点要求请求服务器在请求体中提供一个(可能为空的)JSON 对象。请求服务器应为所有带有 JSON 请求体的请求提供 Content-Type: application/json 头,但不是强制性的。

同理,本规范中的所有端点要求目标服务器返回一个 JSON 对象。服务器必须在所有 JSON 响应中包含 Content-Type: application/json 头。

所有请求和响应中的 JSON 数据都必须使用 UTF-8 编码。

TLS

服务器-服务器通信必须通过 HTTPS 实现。

目标服务器必须提供由已知证书机构签署的 TLS 证书。

请求服务器最终负责确定信任的证书机构,强烈建议依赖操作系统的判断。服务器可以为管理员提供覆盖信任机构列表的方法。服务器还可以针对白名单中的域名或网段跳过证书验证,用于测试或在其他地方完成验证(如 .onion 地址)的网络环境下。

在发起请求时,服务器应尽可能遵守 SNI(服务器名称指示):发送期望证书的 SNI,除非证书预期是 IP 地址(IP 地址不支持 SNI,不应发送)。

建议服务器利用 证书透明计划

不支持的端点

若收到对不支持(或未知)端点的请求,服务器必须返回 404 M_UNRECOGNIZED 错误。

同样,405 M_UNRECOGNIZED 错误用于指示对已知端点的不支持 HTTP 方法。

服务器发现

解析服务器名称

每个 Matrix 家服务器通过一个包含主机名和可选端口的服务器名称唯一标识,详见 语法说明。如适用,委托服务器名采用相同语法。

服务器名需解析为可连接的 IP 地址与端口,解析过程中涉及不同证书和 Host 头的设置。整体流程如下:

  1. 如果主机名是 IP 字面量,则应直接使用该 IP 与指定端口(未指定则为 8448)。目标服务器必须呈现对应 IP 地址的有效证书。请求中的 Host 头应设为服务器名称(若含端口也需带端口)。
  2. 若主机名不是 IP 字面量,且服务器名称中包含明确端口,需通过 CNAME、AAAA 或 A 记录解析主机名为 IP 地址;请求将发至解析得到的 IP 和端口,Host 头为原始服务器名称(含端口)。目标服务器必须呈现该主机名的有效证书。
  3. 若主机名非 IP 字面量,无明确端口,则向 https://<hostname>/.well-known/matrix/server 发起常规 HTTPS 请求,期望返回本节后续定义的模式。须跟随 30x 跳转,但需避免重定向循环。/.well-known 端点的响应(无论成功与否)应由请求服务器进行缓存。服务器应遵守响应内的缓存控制头,如无则使用合理默认值(建议 24 小时)。另外应限制响应最大缓存时间,建议为 48 小时。错误建议缓存最多一小时,并对重复失败采用指数退避。/.well-known 返回的响应模式详见本节后续。若响应无效(JSON 无效、字段缺失、返回非 200 等)则跳转到步骤 4。若响应有效,解析 m.server 字段(格式 <delegated_hostname>[:<delegated_port>])并按如下处理:
    1. <delegated_hostname> 为 IP 字面量,则用该 IP 和 <delegated_port>(未提供则 8448)。目标服务器必须有对应 IP 的有效 TLS 证书。请求 Host 头为该 IP(若含端口亦包含端口)。
    2. <delegated_hostname> 非 IP 字面量,且 <delegated_port> 存在,查找其 CNAME、AAAA 或 A 记录,得出 IP,连同 <delegated_port> 使用。请求 Host 头为 <delegated_hostname>:<delegated_port>。目标服务器需有 <delegated_hostname> 的有效证书。
    3. [Added in v1.8]<delegated_hostname> 不是 IP 字面量,且未指定 <delegated_port>,则查找 _matrix-fed._tcp.<delegated_hostname> 的 SRV 记录,可能带来新的主机名(需 AAAA 或 A 记录解析)及端口。请求应发往解析出的 IP 与端口,Host 头为 <delegated_hostname>。目标服务器需有 <delegated_hostname> 的有效证书。
    4. [已废弃]<delegated_hostname> 不是 IP 字面量,未指定 <delegated_port>,且找不到 _matrix-fed._tcp.<delegated_hostname> SRV 记录,则查 _matrix._tcp.<delegated_hostname>,同样可能得到主机名和端口。请求应发往解析到的 IP 和端口,Host 头为 <delegated_hostname>。目标服务器需有 <delegated_hostname> 的有效证书。
    5. 若未找到 SRV 记录,通过 CNAME、AAAA 或 A 记录解析 IP,之后用 8448 端口发请求,Host 头为 <delegated_hostname>。目标服务器须有 <delegated_hostname> 的有效证书。
  4. [Added in v1.8]/.well-known 请求返回错误,则尝试解析 _matrix-fed._tcp.<hostname> 的 SRV 记录,或得主机名和端口。请求发往解析到的 IP 与端口,Host 头为 <hostname>,目标服务器需有 <hostname> 的有效证书。
  5. [已废弃]/.well-known 请求错误且找不到 _matrix-fed._tcp.<hostname> SRV 记录,则解析 _matrix._tcp.<hostname> SRV 记录,同样可能获主机名和端口。请求发往解析到的 IP 和端口,Host 头为 <hostname>,目标服务器需有 <hostname> 的有效证书。
  6. /.well-known 返回错误,且未找到 SRV 记录,则用 CNAME、AAAA、A 记录解析 IP,发往 8448 端口,Host 头为 <hostname>,目标服务器需有 <hostname> 有效证书。

我们强制要求 SRV 委托使用 <hostname> 而非 <delegated_hostname> 的原因:

  1. DNS 并不安全(并非所有域名都部署 DNSSEC),因此委托目标必须通过 TLS 证明自己是 <hostname> 的合法代理。
  2. RFC6125 以及 XMPP 等其他使用 SRV 记录的应用保持一致。

注意,根据 RFC2782 要求,SRV 记录的目标不能是 CNAME:

the name MUST NOT be an alias (in the sense of RFC 1034 or RFC 2181)

步骤 3.4 与 5 已废弃,因为采用了 IANA 未注册的服务名,未来可能被规范移除。鼓励服务器管理员优先使用 .well-known,不要依赖任何形式的 SRV 记录。

关于 8448 端口与 matrix-fed 的 IANA 注册见 此处

GET /.well-known/matrix/server


Gets information about the delegated server for server-server communication between Matrix homeservers. Servers should follow 30x redirects, carefully avoiding redirect loops, and use normal X.509 certificate validation.

Rate-limited: No
Requires authentication: No

Request

No request parameters or request body.


Responses

Status Description
200 The delegated server information. The Content-Type for this response SHOULD be application/json, however servers parsing the response should assume that the body is JSON regardless of type. Failures parsing the JSON or invalid data provided in the resulting parsed JSON should not result in discovery failure - consult the server discovery process for information on how to continue.

200 response

Name Type Description
m.server string

The server name to delegate server-server communications to, with optional port. The delegated server name uses the same grammar as server names in the appendices.

{
  "m.server": "delegated.example.com:1234"
}

服务器实现

GET /_matrix/federation/v1/version


Get the implementation name and version of this homeserver.

Rate-limited: No
Requires authentication: No

Request

No request parameters or request body.


Responses

Status Description
200 The implementation name and version of this homeserver.

200 response

Name Type Description
server Server
Server
Name Type Description
name string

Arbitrary name that identify this implementation.

version string

Version of this implementation. The version format depends on the implementation.

{
  "server": {
    "name": "My_Homeserver_Implementation",
    "version": "ArbitraryVersionNumber"
  }
}

获取服务器公钥

曾经存在“版本 1”密钥交换,已因意义不大被规范移除。可在 历史草案 查阅。

每个家服务器通过 /_matrix/key/v2/server 发布自身公钥。家服务器可直接请求 /_matrix/key/v2/server 获取公钥,也可借助中间公证服务器通过 /_matrix/key/v2/query/{serverName} API 查询。公证服务器会代表其他服务器查询目标服务器的 /_matrix/key/v2/server API,然后用自己的密钥为响应签名。服务器可同时查询多个公证服务器,确保它们返回的公钥一致。

该方法借鉴了 Perspectives Project,但增加了 NACL 密钥并采用 JSON 而非 XML。其优势是不依赖单一信任根,每台服务器可自由选择信任哪些公证,且能通过交叉查询验证密钥一致性。

公钥发布

家服务器在 /_matrix/key/v2/server 以 JSON 对象发布其签名密钥。响应包含一组 verify_keys,用于签名联邦请求以及事件。还包含一组仅可用于事件签名的 old_verify_keys

GET /_matrix/key/v2/server


Gets the homeserver’s published signing keys. The homeserver may have any number of active keys and may have a number of old keys.

Intermediate notary servers should cache a response for half of its lifetime to avoid serving a stale response. Originating servers should avoid returning responses that expire in less than an hour to avoid repeated requests for a certificate that is about to expire. Requesting servers should limit how frequently they query for certificates to avoid flooding a server with requests.

If the server fails to respond to this request, intermediate notary servers should continue to return the last response they received from the server so that the signatures of old events can still be checked.

Rate-limited: No
Requires authentication: No

Request

No request parameters or request body.


Responses

Status Description
200 The homeserver’s keys

200 response

Server Keys
Name Type Description
old_verify_keys {string: Old Verify Key}

The public keys that the server used to use and when it stopped using them.

The object’s key is the algorithm and version combined (ed25519 being the algorithm and 0ldK3y being the version in the example below). Together, this forms the Key ID. The version must have characters matching the regular expression [a-zA-Z0-9_].

server_name string

Required: The homeserver’s server name.

signatures {string: {string: string}}

Required: Digital signatures for this object signed using the verify_keys.

The signature is calculated using the process described at Signing JSON.

valid_until_ts integer

Required: POSIX timestamp in milliseconds when the list of valid keys should be refreshed. This field MUST be ignored in room versions 1, 2, 3, and 4. Keys used beyond this timestamp MUST be considered invalid, depending on the room version specification.

Servers MUST use the lesser of this field and 7 days into the future when determining if a key is valid. This is to avoid a situation where an attacker publishes a key which is valid for a significant amount of time without a way for the homeserver owner to revoke it.

verify_keys {string: Verify Key}

Required: Public keys of the homeserver for verifying digital signatures.

The object’s key is the algorithm and version combined (ed25519 being the algorithm and abc123 being the version in the example below). Together, this forms the Key ID. The version must have characters matching the regular expression [a-zA-Z0-9_].

Old Verify Key
Name Type Description
expired_ts integer

Required: POSIX timestamp in milliseconds for when this key expired.

key string

Required: The Unpadded base64 encoded key.

Verify Key
Name Type Description
key string

Required: The Unpadded base64 encoded key.

{
  "old_verify_keys": {
    "ed25519:0ldk3y": {
      "expired_ts": 1532645052628,
      "key": "VGhpcyBzaG91bGQgYmUgeW91ciBvbGQga2V5J3MgZWQyNTUxOSBwYXlsb2FkLg"
    }
  },
  "server_name": "example.org",
  "signatures": {
    "example.org": {
      "ed25519:auto2": "VGhpcyBzaG91bGQgYWN0dWFsbHkgYmUgYSBzaWduYXR1cmU"
    }
  },
  "valid_until_ts": 1652262000000,
  "verify_keys": {
    "ed25519:abc123": {
      "key": "VGhpcyBzaG91bGQgYmUgYSByZWFsIGVkMjU1MTkgcGF5bG9hZA"
    }
  }
}

通过其他服务器查询密钥

服务器可通过公证服务器查询目标服务器公钥。公证服务器可能也是别的家服务器。其会使用 /_matrix/key/v2/server 从目标服务器取得密钥,并在响应前对结果再签名。

对于离线或无法提供密钥的服务器,公证服务器可利用缓存返回密钥。为防止 DNS 欺骗,可同时向多台服务器查询密钥。

POST /_matrix/key/v2/query


Query for keys from multiple servers in a batch format. The receiving (notary) server must sign the keys returned by the queried servers.

Rate-limited: No
Requires authentication: No

Request

Request body

Name Type Description
server_keys {string: {string: Query Criteria}}

Required: The query criteria. The outer string key on the object is the server name (eg: matrix.org). The inner string key is the Key ID to query for the particular server. If no key IDs are given to be queried, the notary server should query for all keys. If no servers are given, the notary server must return an empty server_keys array in the response.

The notary server may return multiple keys regardless of the Key IDs given.

Query Criteria
Name Type Description
minimum_valid_until_ts integer

A millisecond POSIX timestamp in milliseconds indicating when the returned certificates will need to be valid until to be useful to the requesting server.

If not supplied, the current time as determined by the notary server is used.

Request body example

{
  "server_keys": {
    "example.org": {
      "ed25519:abc123": {
        "minimum_valid_until_ts": 1234567890
      }
    }
  }
}

Responses

Status Description
200 The keys for the queried servers, signed by the notary server. Servers which are offline and have no cached keys will not be included in the result. This may result in an empty array.

200 response

Name Type Description
server_keys [Server Keys]

The queried server’s keys, signed by the notary server.

Server Keys
Name Type Description
old_verify_keys {string: Old Verify Key}

The public keys that the server used to use and when it stopped using them.

The object’s key is the algorithm and version combined (ed25519 being the algorithm and 0ldK3y being the version in the example below). Together, this forms the Key ID. The version must have characters matching the regular expression [a-zA-Z0-9_].

server_name string

Required: The homeserver’s server name.

signatures {string: {string: string}}

Required: Digital signatures for this object signed using the verify_keys.

The signature is calculated using the process described at Signing JSON.

valid_until_ts integer

Required: POSIX timestamp in milliseconds when the list of valid keys should be refreshed. This field MUST be ignored in room versions 1, 2, 3, and 4. Keys used beyond this timestamp MUST be considered invalid, depending on the room version specification.

Servers MUST use the lesser of this field and 7 days into the future when determining if a key is valid. This is to avoid a situation where an attacker publishes a key which is valid for a significant amount of time without a way for the homeserver owner to revoke it.

verify_keys {string: Verify Key}

Required: Public keys of the homeserver for verifying digital signatures.

The object’s key is the algorithm and version combined (ed25519 being the algorithm and abc123 being the version in the example below). Together, this forms the Key ID. The version must have characters matching the regular expression [a-zA-Z0-9_].

Old Verify Key
Name Type Description
expired_ts integer

Required: POSIX timestamp in milliseconds for when this key expired.

key string

Required: The Unpadded base64 encoded key.

Verify Key
Name Type Description
key string

Required: The Unpadded base64 encoded key.

{
  "server_keys": [
    {
      "old_verify_keys": {
        "ed25519:0ldk3y": {
          "expired_ts": 1532645052628,
          "key": "VGhpcyBzaG91bGQgYmUgeW91ciBvbGQga2V5J3MgZWQyNTUxOSBwYXlsb2FkLg"
        }
      },
      "server_name": "example.org",
      "signatures": {
        "example.org": {
          "ed25519:abc123": "VGhpcyBzaG91bGQgYWN0dWFsbHkgYmUgYSBzaWduYXR1cmU"
        },
        "notary.server.com": {
          "ed25519:010203": "VGhpcyBpcyBhbm90aGVyIHNpZ25hdHVyZQ"
        }
      },
      "valid_until_ts": 1652262000000,
      "verify_keys": {
        "ed25519:abc123": {
          "key": "VGhpcyBzaG91bGQgYmUgYSByZWFsIGVkMjU1MTkgcGF5bG9hZA"
        }
      }
    }
  ]
}

GET /_matrix/key/v2/query/{serverName}


Query for another server’s keys. The receiving (notary) server must sign the keys returned by the queried server.

Rate-limited: No
Requires authentication: No

Request

Request parameters

path parameters
Name Type Description
serverName string

Required: The server name to query

query parameters
Name Type Description
minimum_valid_until_ts integer

A millisecond POSIX timestamp in milliseconds indicating when the returned certificates will need to be valid until to be useful to the requesting server.

If not supplied, the current time as determined by the notary server is used.


Responses

Status Description
200 The keys for the server, or an empty array if the server could not be reached and no cached keys were available.

200 response

Name Type Description
server_keys [Server Keys]

The queried server’s keys, signed by the notary server.

Server Keys
Name Type Description
old_verify_keys {string: Old Verify Key}

The public keys that the server used to use and when it stopped using them.

The object’s key is the algorithm and version combined (ed25519 being the algorithm and 0ldK3y being the version in the example below). Together, this forms the Key ID. The version must have characters matching the regular expression [a-zA-Z0-9_].

server_name string

Required: The homeserver’s server name.

signatures {string: {string: string}}

Required: Digital signatures for this object signed using the verify_keys.

The signature is calculated using the process described at Signing JSON.

valid_until_ts integer

Required: POSIX timestamp in milliseconds when the list of valid keys should be refreshed. This field MUST be ignored in room versions 1, 2, 3, and 4. Keys used beyond this timestamp MUST be considered invalid, depending on the room version specification.

Servers MUST use the lesser of this field and 7 days into the future when determining if a key is valid. This is to avoid a situation where an attacker publishes a key which is valid for a significant amount of time without a way for the homeserver owner to revoke it.

verify_keys {string: Verify Key}

Required: Public keys of the homeserver for verifying digital signatures.

The object’s key is the algorithm and version combined (ed25519 being the algorithm and abc123 being the version in the example below). Together, this forms the Key ID. The version must have characters matching the regular expression [a-zA-Z0-9_].

Old Verify Key
Name Type Description
expired_ts integer

Required: POSIX timestamp in milliseconds for when this key expired.

key string

Required: The Unpadded base64 encoded key.

Verify Key
Name Type Description
key string

Required: The Unpadded base64 encoded key.

{
  "server_keys": [
    {
      "old_verify_keys": {
        "ed25519:0ldk3y": {
          "expired_ts": 1532645052628,
          "key": "VGhpcyBzaG91bGQgYmUgeW91ciBvbGQga2V5J3MgZWQyNTUxOSBwYXlsb2FkLg"
        }
      },
      "server_name": "example.org",
      "signatures": {
        "example.org": {
          "ed25519:abc123": "VGhpcyBzaG91bGQgYWN0dWFsbHkgYmUgYSBzaWduYXR1cmU"
        },
        "notary.server.com": {
          "ed25519:010203": "VGhpcyBpcyBhbm90aGVyIHNpZ25hdHVyZQ"
        }
      },
      "valid_until_ts": 1652262000000,
      "verify_keys": {
        "ed25519:abc123": {
          "key": "VGhpcyBzaG91bGQgYmUgYSByZWFsIGVkMjU1MTkgcGF5bG9hZA"
        }
      }
    }
  ]
}

认证

请求认证

家服务器发起的每个 HTTP 请求都需使用公钥数字签名进行认证。请求方法、目标和体被封装进 JSON 对象后签名,签名采用 JSON 签名算法,最终以 X-Matrix 认证方式添加至 Authorization 头。注意,target 字段需包含以 /_matrix/... 为首的全路径(包括 ? 和各参数),不含前导 https: 与目标服务器主机名。

步骤 1,签名 JSON:

{
    "method": "POST",
    "uri": "/target",
    "origin": "origin.hs.example.com",
    "destination": "destination.hs.example.com",
    "content": <JSON-parsed request body>,
    "signatures": {
        "origin.hs.example.com": {
            "ed25519:key1": "ABCDEF..."
        }
    }
}

上例中的服务器名称是相关家服务器的服务器名,不受 服务器名称解析 中委托影响,始终用委托前的名称。此规则在后续签名流程中也适用。

步骤 2,添加 Authorization 头:

POST /target HTTP/1.1
Authorization: X-Matrix origin="origin.hs.example.com",destination="destination.hs.example.com",key="ed25519:key1",sig="ABCDEF..."
Content-Type: application/json

<JSON-encoded request body>

Python 示例代码:

def authorization_headers(origin_name, origin_signing_key,
                          destination_name, request_method, request_target,
                          content=None):
    request_json = {
         "method": request_method,
         "uri": request_target,
         "origin": origin_name,
         "destination": destination_name,
    }

    if content is not None:
        # 假定内容已为解析好的 JSON
        request_json["content"] = content

    signed_json = sign_json(request_json, origin_name, origin_signing_key)

    authorization_headers = []

    for key, sig in signed_json["signatures"][origin_name].items():
        authorization_headers.append(bytes(
            "X-Matrix origin=\"%s\",destination=\"%s\",key=\"%s\",sig=\"%s\"" % (
                origin_name, destination_name, key, sig,
            )
        ))

    return ("Authorization", authorization_headers[0])

Authorization 头格式见 RFC 9110 第 11.4 节。简言之,头以授权机制 X-Matrix 开始,后跟一或多空格,再跟一组用逗号隔开的 name=value 参数对。各参数对两侧允许有零个或多个空格及制表符。名称大小写不敏感,顺序无关。value 含非法 token 字符时必须加引号,若合法可省略引号。用引号的 value 可包含反斜杠转义字符。解析时须将转义字符还原。

为兼容旧服务器,发送端应:

  • 只在 X-Matrix 后加一个空格;
  • 只用小写参数名;
  • 避免值中含反斜杠;
  • 避免参数对间有额外空白字符。

兼容旧服务器的接收端应允许参数值中含冒号,无需加引号。

可用的授权参数包含:

  • origin:发送服务器的服务器名,与上文 JSON 的 origin 字段一致。
  • destination[Added in v1.3] 接收服务器名,与 JSON 的 destination 字段一致。为兼容旧服务器,允许无此参数,但必须始终发送;若有且值与接收服务器名不符,接收端须以 401 Unauthorized 拒绝请求。
  • key:用于签名请求的发送服务器密钥 ID(含算法名)。
  • signature:步骤 1 中 JSON 的签名。

未知参数应被忽略。

[Changed in v1.11] 本节原引用了 RFC 7235RFC 7230,已被 RFC 9110 替代,但相关内容未变。

响应认证

响应通过 TLS 服务器证书认证。家服务器不应在确认已认证对方服务器前发送请求,以防消息泄漏。

客户端 TLS 证书

因如 Matrix 这样的 HTTP 服务常部署在负责 TLS 的负载均衡器之后,因此建议在 HTTP 层而非 TLS 层进行请求认证,这样 TLS 客户端证书难以校验。

家服务器可提供 TLS 客户端证书,接收方可校验是否与原始服务器证书一致。

事务

家服务器之间通过事务消息(Transaction)交换 EDU 和 PDU。这些事务以 JSON 对象编码,通过 HTTP PUT 请求传输。事务仅对交换的两台服务器有意义,不具备全局意义。

事务有限制:每个最多可含 50 个 PDU 和 100 个 EDU。

PUT /_matrix/federation/v1/send/{txnId}


Push messages representing live activity to another server. The destination name will be set to that of the receiving server itself. Each embedded PDU in the transaction body will be processed.

The sending server must wait and retry for a 200 OK response before sending a transaction with a different txnId to the receiving server.

Note that events have a different format depending on the room version - check the room version specification for precise event formats.

Rate-limited: No
Requires authentication: Yes

Request

Request parameters

path parameters
Name Type Description
txnId string

Required: The transaction ID.

Request body

Transaction
Name Type Description
edus [Ephemeral Data Unit]

List of ephemeral messages. May be omitted if there are no ephemeral messages to be sent. Must not include more than 100 EDUs.

origin string

Required: The server_name of the homeserver sending this transaction.

origin_server_ts integer

Required: POSIX timestamp in milliseconds on originating homeserver when this transaction started.

pdus [PDU]

Required: List of persistent updates to rooms. Must not include more than 50 PDUs. Note that events have a different format depending on the room version - check the room version specification for precise event formats.

Ephemeral Data Unit
Name Type Description
content object

Required: The content of the ephemeral message.

edu_type string

Required: The type of ephemeral message.

Request body example

{
  "origin": "matrix.org",
  "origin_server_ts": 1234567890,
  "pdus": [
    {
      "content": {
        "see_room_version_spec": "The event format changes depending on the room version."
      },
      "room_id": "!somewhere:example.org",
      "type": "m.room.minimal_pdu"
    }
  ]
}

Responses

Status Description
200 The result of processing the transaction. The server is to use this response even in the event of one or more PDUs failing to be processed.

200 response

PDU Processing Results
Name Type Description
pdus {Event ID: PDU Processing Result}

Required: The PDUs from the original transaction. The string key represents the ID of the PDU (event) that was processed.

PDU Processing Result
Name Type Description
error string

A human readable description about what went wrong in processing this PDU. If no error is present, the PDU can be considered successfully handled.

{
  "pdus": {
    "$failed_event:example.org": {
      "error": "You are not allowed to send a message to this room."
    },
    "$successful_event:example.org": {}
  }
}

PDUs

每个 PDU 包含一个房间事件,原服务器希望将其发送至目标服务器。

PDU 中的 prev_events 字段标识事件的“父事件”,并通过将事件链接为有向无环图(DAG)在房间内建立事件的部分顺序。发送服务器应填充所有自己尚未看到其子事件的事件,从而表明此事件紧随所有已知事件之后。

例如,设房间事件形成下述 DAG。新事件应以 E4E6 作为 prev_events,因为两者尚无子事件:

E1
^
|
E2 <--- E5
^       ^
|       |
E3      E6
^
|
E4

完整的 PDU 模式见 房间版本规范

PDU 接收时的校验

服务器接收到远端事件时,必须确保该事件:

  1. 是一个有效事件,否则直接丢弃。有效事件必须含有 room_id,并符合该 房间版本 的事件格式。
  2. 签名校验通过,否则丢弃。
  3. 哈希校验通过,否则事件被裁剪(redacted)后再继续处理。
  4. 基于认证事件(auth events)的授权规则校验通过,否则拒绝。
  5. 基于事件前状态的授权规则校验通过,否则拒绝。
  6. 基于房间当前状态的授权规则校验通过,否则“软失败”(soft failed)。

各项校验及失败处理详述如下。

关于事件需要包含哪些哈希及签名及其计算,详见 事件签名

定义

所需权限等级(Required Power Level)

:每类事件类型对应一个 权限等级,由当前 m.room.power_levels 事件指定。若事件类型在 events 块未显式列出,则根据是否为状态事件,分别使用 state_defaultevents_default

邀请/踢出/封禁/撤回等级(Invite Level, Kick Level, Ban Level, Redact Level)

:由当前 m.room.power_levels 状态内的 invitekickbanredact 指定。邀请默认为 0,踢出、封禁、撤回均默认为 50。

目标用户(Target User)

:对于 m.room.member 状态事件,由事件的 state_key 指定的用户。

部分 房间版本 允许权限等级为字符串,仅为向后兼容。家服务器应合理防止用户发送带字符串值权限事件(如直接拒绝 API 请求),且默认权限值绝不可为字符串。

详情见 房间版本规范

授权规则

授权与状态有关。单个事件需多次用不同状态集校验,具体规则和适用算法由房间版本决定。详细内容见 房间版本规范

认证事件选择(Auth events selection)

PDU 的 auth_events 字段标识允许发起发送的事件集。房间中的 m.room.create 事件无 auth_events;其他事件应按照以下房间状态子集选取:

  • m.room.create 事件
  • 当前的 m.room.power_levels 事件(如有)
  • 发送方当前的 m.room.member 事件(如有)
  • 若类型为 m.room.member
    • 目标用户当前的 m.room.member 事件(如有)
    • membershipjoininviteknock,则为当前 m.room.join_rules
    • membershipinvitecontentthird_party_invite,则加入当前 m.room.third_party_invite 事件,其 state_key 匹配 content.third_party_invite.signed.token
    • content.join_authorised_via_users_server 存在,且 房间版本支持受限房间,则加入 state_key 匹配 content.join_authorised_via_users_serverm.room.member 事件

拒绝(Rejection)

被拒绝事件不应下发给客户端,也不可作为新事件的前序事件。后续如有其他服务器发出的引用被拒绝事件的新事件,只要其授权校验通过也可被接受。授权校验状态正常更新,除针对被拒绝事件(若为状态事件)不更新。

若事务中的事件被拒绝,不应以错误码响应整个事务请求。

这意味着某些被拒绝事件依然可出现在房间事件 DAG 中。

区别于裁剪事件(redacted event),裁剪事件依然可影响房间状态。如,取消内容的 join 事件依然会使用户视为已加入房间。

软失败(Soft failure)

为防止用户通过指向旧 DAG 分支的事件规避封禁或其他权限限制,例如被封禁用户通过发送引用被封禁前分支的事件继续发言。此类事件本身合法,不应单纯以拒绝处理,因为无法区分延迟事件和规避事件。因此,此类事件需正常参与状态解析与联邦协议,但服务器可选择不将其下发至客户端。

通常服务器会发现此类事件基于“当前状态”无法授权(即综合所有前沿节点的解析状态),此时服务器可选择不通知客户端。

这样可阻止恶意服务器向客户端投递规避事件,因最终用户不会看到。例如:

  A
 /
B

B 为用户 X 的封禁事件。若 X 试图通过发送事件 C 修改话题以规避封禁,则

  A
 / \
B   C

若服务器先见到 B 后见到 C,应对 C 软失败,即不通知客户端,也不再引用 C

若后来有服务器发送同时引用 BC 的事件 D(如其先见到了 C 后到的 B):

  A
 / \
B   C
 \ /
  D

D 可正常处理(前提授权通过)。D 处的状态可能包含 C,客户端应当收到包含 C 的新状态。(注意:实际取决于具体状态解析算法,对应 CB 优先。)

若所有服务器都先收到 B,所有对 C 软失败,则后续新事件 D' 不再引用 C

  A
 / \
B   C
|
D'

通过联邦收到新事件后,应在基于事件自身状态校验通过后,再以房间当前状态校验。不通过时则“软失败”。

“软失败”事件不应下发至客户端,也不应被新事件引用或加入到前沿事件集中。其余处理同常规事件。

如有其他事件引用该软失败事件,则其可照常参与状态解析;状态解析算法须防止此机制下恶意事件注入房间状态。

软失败的状态事件如在状态解析中被选为当前状态,客户端应常规方式收到该事件(例如在 sync 响应的 state 部分推送)。

若联邦请求需返回软失败事件(如 /event/<event_id>),应正常返回。/backfill/get_missing_events 仅当请求中包含引用该软失败事件的事件时才会返回。

检索事件授权信息

家服务器可能缺失事件授权信息,或需从其他服务器验证授权链。通过以下 API 获取所需信息。

GET /_matrix/federation/v1/event_auth/{roomId}/{eventId}


Retrieves the complete auth chain for a given event.

Rate-limited: No
Requires authentication: Yes

Request

Request parameters

path parameters
Name Type Description
eventId string

Required: The event ID to get the auth chain of.

roomId string

Required: The room ID to get the auth chain for.


Responses

Status Description
200 The auth chain for the event.

200 response

Name Type Description
auth_chain [PDU]

Required: The PDUs forming the auth chain of the given event. The event format varies depending on the room version - check the room version specification for precise event formats.

{
  "auth_chain": [
    {
      "content": {
        "see_room_version_spec": "The event format changes depending on the room version."
      },
      "room_id": "!somewhere:example.org",
      "type": "m.room.minimal_pdu"
    }
  ]
}

EDUs

EDU 相比 PDU 没有事件 ID、房间 ID 或“前序事件”列表。通常用于非持久化数据,如用户在线状态、正在输入提示等。

Ephemeral Data Unit


An ephemeral data unit.

Ephemeral Data Unit
Name Type Description
content object

Required: The content of the ephemeral message.

edu_type string

Required: The type of ephemeral message.

Examples

{
  "content": {
    "key": "value"
  },
  "edu_type": "m.presence"
}

房间状态解析

状态(event_type, state_key)event_id 的映射。每个房间初始状态为空,每有状态事件加入即更新房间状态。

若每个事件只有一个 prev_event,其后状态唯一;若事件图分支合并,可能存在不同状态,此时需用 状态解析算法 决定合并结果。

如下事件图(顶部为最早的 E0):

  E0
  |
  E1
 /  \
E2  E4
|    |
E3   |
 \  /
  E5

若 E3 和 E4 都是 m.room.name 事件,E5 处房间名称如何确定?

状态解析算法由房间版本决定,详见 房间版本规范

回溯填充与缺失事件获取

家服务器加入房间后,会收到所有在房间内其他家服务器产生的事件,因此近期历史不会丢失。用户可通过 /messages 客户端 API 端点查历史,如倒退到加入房间前,其服务器本地无历史。

为此,联邦 API 提供类似 /messages 的服务器-服务器历史获取接口 /backfill

如需历史,家服务器可选一已存有最早历史用户的家服务器发起 /backfill 请求。

类似回溯,服务器可能缺失某些事件,可通过 /get_missing_events 获取缺失事件。

GET /_matrix/federation/v1/backfill/{roomId}


Retrieves a sliding-window history of previous PDUs that occurred in the given room. Starting from the PDU ID(s) given in the v argument, the PDUs given in v and the PDUs that preceded them are retrieved, up to the total number given by the limit.

Rate-limited: No
Requires authentication: Yes

Request

Request parameters

path parameters
Name Type Description
roomId string

Required: The room ID to backfill.

query parameters
Name Type Description
limit integer

Required: The maximum number of PDUs to retrieve, including the given events.

v [string]

Required: The event IDs to backfill from.


Responses

Status Description
200

A transaction containing the PDUs that preceded the given event(s), including the given event(s), up to the given limit.

Note: Though the PDU definitions require that prev_events and auth_events be limited in number, the response of backfill MUST NOT be validated on these specific restrictions.

Due to historical reasons, it is possible that events which were previously accepted would now be rejected by these limitations. The events should be rejected per usual by the /send, /get_missing_events, and remaining endpoints.

200 response

Transaction
Name Type Description
origin string

Required: The server_name of the homeserver sending this transaction.

origin_server_ts integer

Required: POSIX timestamp in milliseconds on originating homeserver when this transaction started.

pdus [PDU]

Required: List of persistent updates to rooms. Note that events have a different format depending on the room version - check the room version specification for precise event formats.

{
  "origin": "matrix.org",
  "origin_server_ts": 1234567890,
  "pdus": [
    {
      "content": {
        "see_room_version_spec": "The event format changes depending on the room version."
      },
      "room_id": "!somewhere:example.org",
      "type": "m.room.minimal_pdu"
    }
  ]
}

POST /_matrix/federation/v1/get_missing_events/{roomId}


Retrieves previous events that the sender is missing. This is done by doing a breadth-first walk of the prev_events for the latest_events, ignoring any events in earliest_events and stopping at the limit.

Rate-limited: No
Requires authentication: Yes

Request

Request parameters

path parameters
Name Type Description
roomId string

Required: The room ID to search in.

Request body

Name Type Description
earliest_events [string]

Required: The latest event IDs that the sender already has. These are skipped when retrieving the previous events of latest_events.

latest_events [string]

Required: The event IDs to retrieve the previous events for.

limit integer

The maximum number of events to retrieve. Defaults to 10.

min_depth integer

The minimum depth of events to retrieve. Defaults to 0.

Request body example

{
  "earliest_events": [
    "$missing_event:example.org"
  ],
  "latest_events": [
    "$event_that_has_the_missing_event_as_a_previous_event:example.org"
  ],
  "limit": 10
}

Responses

Status Description
200 The previous events for latest_events, excluding any earliest_events, up to the provided limit.

200 response

Name Type Description
events [PDU]

Required: The missing events. The event format varies depending on the room version - check the room version specification for precise event formats.

{
  "events": [
    {
      "content": {
        "see_room_version_spec": "The event format changes depending on the room version."
      },
      "room_id": "!somewhere:example.org",
      "type": "m.room.minimal_pdu"
    }
  ]
}

检索事件

在某些情况下,家服务器可能缺失特定事件或无法简单通过回溯获取的房间信息。相关 API 允许家服务器获取指定时间点的事件及状态。

GET /_matrix/federation/v1/event/{eventId}


Retrieves a single event.

Rate-limited: No
Requires authentication: Yes

Request

Request parameters

path parameters
Name Type Description
eventId string

Required: The event ID to get.


Responses

Status Description
200 A transaction containing a single PDU which is the event requested.

200 response

Transaction
Name Type Description
origin string

Required: The server_name of the homeserver sending this transaction.

origin_server_ts integer

Required: POSIX timestamp in milliseconds on originating homeserver when this transaction started.

pdus [PDU]

Required: A single PDU. Note that events have a different format depending on the room version - check the room version specification for precise event formats.

{
  "origin": "matrix.org",
  "origin_server_ts": 1234567890,
  "pdus": [
    {
      "content": {
        "see_room_version_spec": "The event format changes depending on the room version."
      },
      "room_id": "!somewhere:example.org",
      "type": "m.room.minimal_pdu"
    }
  ]
}

GET /_matrix/federation/v1/state/{roomId}


Retrieves a snapshot of a room’s state at a given event.

Rate-limited: No
Requires authentication: Yes

Request

Request parameters

path parameters
Name Type Description
roomId string

Required: The room ID to get state for.

query parameters
Name Type Description
event_id string

Required: An event ID in the room to retrieve the state at.


Responses

Status Description
200 The fully resolved state for the room, prior to considering any state changes induced by the requested event. Includes the authorization chain for the events.

200 response

Name Type Description
auth_chain [PDU]

Required: The full set of authorization events that make up the state of the room, and their authorization events, recursively. Note that events have a different format depending on the room version - check the room version specification for precise event formats.

pdus [PDU]

Required: The fully resolved state of the room at the given event. Note that events have a different format depending on the room version - check the room version specification for precise event formats.

{
  "auth_chain": [
    {
      "content": {
        "see_room_version_spec": "The event format changes depending on the room version."
      },
      "room_id": "!somewhere:example.org",
      "type": "m.room.minimal_pdu"
    }
  ],
  "pdus": [
    {
      "content": {
        "see_room_version_spec": "The event format changes depending on the room version."
      },
      "room_id": "!somewhere:example.org",
      "type": "m.room.minimal_pdu"
    }
  ]
}

GET /_matrix/federation/v1/state_ids/{roomId}


Retrieves a snapshot of a room’s state at a given event, in the form of event IDs. This performs the same function as calling /state/{roomId}, however this returns just the event IDs rather than the full events.

Rate-limited: No
Requires authentication: Yes

Request

Request parameters

path parameters
Name Type Description
roomId string

Required: The room ID to get state for.

query parameters
Name Type Description
event_id string

Required: An event ID in the room to retrieve the state at.


Responses

Status Description
200 The fully resolved state for the room, prior to considering any state changes induced by the requested event. Includes the authorization chain for the events.
403 The requesting host is not in the room, or is excluded from the room via m.room.server_acl.
404 The given event_id was not found or the server doesn’t know about the state at that event to return anything useful.

200 response

Name Type Description
auth_chain_ids [string]

Required: The full set of authorization events that make up the state of the room, and their authorization events, recursively.

pdu_ids [string]

Required: The fully resolved state of the room at the given event.

{
  "auth_chain_ids": [
    "$an_event:example.org"
  ],
  "pdu_ids": [
    "$an_event:example.org"
  ]
}

403 response

Error
Name Type Description
errcode string

Required: An error code.

error string

A human-readable error message.

{
  "errcode": "M_FORBIDDEN",
  "error": "You do not have permission to access the state at the requested event."
}

404 response

Error
Name Type Description
errcode string

Required: An error code.

error string

A human-readable error message.

{
  "errcode": "M_NOT_FOUND",
  "error": "Could not find event $Rqnc-F-dvnEYJTyHq_iKxU2bZ1CI92-kuZq3a5lr5Zg"
}

GET /_matrix/federation/v1/timestamp_to_event/{roomId}


Added in v1.6

Get the ID of the event closest to the given timestamp, in the direction specified by the dir parameter.

This is primarily used when handling the corresponding client-server endpoint when the server does not have all of the room history, and does not have an event suitably close to the requested timestamp.

The heuristics for deciding when to ask another homeserver for a closer event if your homeserver doesn’t have something close, are left up to the homeserver implementation, although the heuristics will probably be based on whether the closest event is a forward/backward extremity indicating it’s next to a gap of events which are potentially closer.

A good heuristic for which servers to try first is to sort by servers that have been in the room the longest because they’re most likely to have anything we ask about.

After the local homeserver receives the response, it should determine, using the origin_server_ts property, whether the returned event is closer to the requested timestamp than the closest event that it could find locally. If so, it should try to backfill this event via the /event/{event_id} endpoint so that it is available to for a client to query.

Rate-limited: No
Requires authentication: Yes

Request

Request parameters

path parameters
Name Type Description
roomId string

Required: The ID of the room to search

query parameters
Name Type Description
dir string

Required: The direction in which to search. f for forwards, b for backwards.

One of: [f, b].

ts integer

Required: The timestamp to search from, as given in milliseconds since the Unix epoch.


Responses

Status Description
200 An event was found matching the search parameters.
404 No event was found.

200 response

Name Type Description
event_id string

Required: The ID of the event found

origin_server_ts integer

Required: The event’s timestamp, in milliseconds since the Unix epoch.

{
  "event_id": "$143273582443PhrSn:example.org",
  "origin_server_ts": 1432735824653
}

404 response

Error
Name Type Description
errcode string

Required: An error code.

error string

A human-readable error message.

{
  "errcode": "M_NOT_FOUND",
  "error": "Unable to find event from 1432684800000 in forward direction"
}

加入房间

当新用户想加入本服务器已知的房间时,服务器可直接检查房间状态判断能否加入。若可以,则生成签名并发出新的 m.room.member 状态事件加入用户。若服务器尚未知该房间,则需通过更长的多阶段握手流程,先选定一个已在该房间的远程家服务器协助加入,即远程加入握手。

握手涉及三个角色:发起加入用户的家服务器(“加入服务器”)、托管用户请求别名的目录服务器,以及房间中已有成员所属家服务器(“常驻服务器”)。

概述如下,加入服务器先向目录服务器查询别名,获取房间 ID 及加入候选服务器,继而请求其中一个常驻服务器查询房间信息,再用这些资料构建并签名 m.room.member 加入事件,最终发往常驻服务器。

概念上为三个家服务器角色,实际通常目录服务器本身即为房间成员;实际流程也常只有两台服务器参与。

+---------+          +---------------+            +-----------------+ +-----------------+
| Client  |          | JoiningServer |            | DirectoryServer | | ResidentServer  |
+---------+          +---------------+            +-----------------+ +-----------------+
     |                       |                             |                   |
     | join request          |                             |                   |
     |---------------------->|                             |                   |
     |                       |                             |                   |
     |                       | directory request           |                   |
     |                       |---------------------------->|                   |
     |                       |                             |                   |
     |                       |          directory response |                   |
     |                       |<----------------------------|                   |
     |                       |                             |                   |
     |                       | make_join request           |                   |
     |                       |------------------------------------------------>|
     |                       |                             |                   |
     |                       |                             |make_join response |
     |                       |<------------------------------------------------|
     |                       |                             |                   |
     |                       | send_join request           |                   |
     |                       |------------------------------------------------>|
     |                       |                             |                   |
     |                       |                             |send_join response |
     |                       |<------------------------------------------------|
     |                       |                             |                   |
     |         join response |                             |                   |
     |<----------------------|                             |                   |
     |                       |                             |                   |

第一步,通常通过目录服务器的 /query/directory 端点查询房间 ID 与加入候选服务器。若为被邀请后加入,则可直接选用邀请事件源服务器为候选,提高效率。但需考虑邀请服务器可能已不再是房间成员,因此失败时须回退到通常流程。

获得房间 ID 和候选服务器后,加入服务器选一常驻服务器,通过 GET /make_join 获取房间事件模板。常驻服务器返回填充事件各项所需信息。

加入服务器需补充完善 originorigin_server_tsevent_id,然后签名。

最后,加入服务器通过 PUT /send_join 将新事件送往常驻服务器。

常驻服务器为事件加签,接受并将其写入房间事件图,并将新事件及房间全状态(含刚签出的事件)发送给房间内其他服务器。

GET /_matrix/federation/v1/make_join/{roomId}/{userId}


Asks the receiving server to return information that the sending server will need to prepare a join event to get into the room.

Rate-limited: No
Requires authentication: Yes

Request

Request parameters

path parameters
Name Type Description
roomId string

Required: The room ID that is about to be joined.

userId string

Required: The user ID the join event will be for.

query parameters
Name Type Description
ver [string]

The room versions the sending server has support for. Defaults to [1].


Responses

Status Description
200 A template to be used for the rest of the Joining Rooms handshake. Note that events have a different format depending on the room version - check the room version specification for precise event formats. The response body here describes the common event fields in more detail and may be missing other required fields for a PDU.
400

The request is invalid, the room the server is attempting to join has a version that is not listed in the ver parameters, or the server was unable to validate restricted room conditions.

The error should be passed through to clients so that they may give better feedback to users.

New in v1.2, the following error conditions might happen:

If the room is restricted and none of the conditions can be validated by the server then the errcode M_UNABLE_TO_AUTHORISE_JOIN must be used. This can happen if the server does not know about any of the rooms listed as conditions, for example.

M_UNABLE_TO_GRANT_JOIN is returned to denote that a different server should be attempted for the join. This is typically because the resident server can see that the joining user satisfies one or more conditions, such as in the case of restricted rooms, but the resident server would be unable to meet the auth rules governing join_authorised_via_users_server on the resulting m.room.member event.

403 The room that the joining server is attempting to join does not permit the user to join.
404 The room that the joining server is attempting to join is unknown to the receiving server.

200 response

Name Type Description
event Event Template

An unsigned template event. Note that events have a different format depending on the room version - check the room version specification for precise event formats.

room_version string

The version of the room where the server is trying to join. If not provided, the room version is assumed to be either “1” or “2”.

Event Template
Name Type Description
content Membership Event Content

Required: The content of the event.

origin string

Required: The name of the resident homeserver.

origin_server_ts integer

Required: A timestamp added by the resident homeserver.

sender string

Required: The user ID of the joining member.

state_key string

Required: The user ID of the joining member.

type string

Required: The value m.room.member.

Membership Event Content
Name Type Description
join_authorised_via_users_server string

Required if the room is restricted and is joining through one of the conditions available. If the user is responding to an invite, this is not required.

An arbitrary user ID belonging to the resident server in the room being joined that is able to issue invites to other users. This is used in later validation of the auth rules for the m.room.member event.

Added in v1.2

membership string

Required: The value join.

{
  "event": {
    "content": {
      "join_authorised_via_users_server": "@anyone:resident.example.org",
      "membership": "join"
    },
    "origin": "example.org",
    "origin_server_ts": 1549041175876,
    "room_id": "!somewhere:example.org",
    "sender": "@someone:example.org",
    "state_key": "@someone:example.org",
    "type": "m.room.member"
  },
  "room_version": "2"
}

400 response

Error
Name Type Description
errcode string

Required: An error code.

error string

A human-readable error message.

room_version string

The version of the room. Required if the errcode is M_INCOMPATIBLE_ROOM_VERSION.

{
  "errcode": "M_INCOMPATIBLE_ROOM_VERSION",
  "error": "Your homeserver does not support the features required to join this room",
  "room_version": "3"
}

403 response

Error
Name Type Description
errcode string

Required: An error code.

error string

A human-readable error message.

{
  "errcode": "M_FORBIDDEN",
  "error": "You are not invited to this room"
}

404 response

Error
Name Type Description
errcode string

Required: An error code.

error string

A human-readable error message.

{
  "errcode": "M_NOT_FOUND",
  "error": "Unknown room"
}

PUT /_matrix/federation/v1/send_join/{roomId}/{eventId}


This API is deprecated and will be removed from a future release.

Note: Servers should instead prefer to use the v2 /send_join endpoint.

Submits a signed join event to the resident server for it to accept it into the room’s graph. Note that events have a different format depending on the room version - check the room version specification for precise event formats. The request and response body here describe the common event fields in more detail and may be missing other required fields for a PDU.

Rate-limited: No
Requires authentication: Yes

Request

Request parameters

path parameters
Name Type Description
eventId string

Required: The event ID for the join event.

roomId string

Required: The room ID that is about to be joined.

Request body

Name Type Description
content Membership Event Content

Required: The content of the event.

origin string

Required: The name of the joining homeserver.

origin_server_ts integer

Required: A timestamp added by the joining homeserver.

sender string

Required: The user ID of the joining member.

state_key string

Required: The user ID of the joining member.

type string

Required: The value m.room.member.

Membership Event Content
Name Type Description
join_authorised_via_users_server string

Required if the room is restricted and is joining through one of the conditions available. If the user is responding to an invite, this is not required.

An arbitrary user ID belonging to the resident server in the room being joined that is able to issue invites to other users. This is used in later validation of the auth rules for the m.room.member event.

The resident server which owns the provided user ID must have a valid signature on the event. If the resident server is receiving the /send_join request, the signature must be added before sending or persisting the event to other servers.

Added in v1.2

membership string

Required: The value join.

Request body example

{
  "content": {
    "membership": "join"
  },
  "origin": "matrix.org",
  "origin_server_ts": 1234567890,
  "sender": "@someone:example.org",
  "state_key": "@someone:example.org",
  "type": "m.room.member"
}

Responses

Status Description
200 The join event has been accepted into the room.

200 response

Array of integer, Room State.

Room State
Name Type Description
auth_chain [PDU]

Required: The auth chain for the entire current room state prior to the join event.

Note that events have a different format depending on the room version - check the room version specification for precise event formats.

state [PDU]

Required: The resolved current room state prior to the join event.

The event format varies depending on the room version - check the room version specification for precise event formats.

[
  200,
  {
    "auth_chain": [
      {
        "content": {
          "see_room_version_spec": "The event format changes depending on the room version."
        },
        "room_id": "!somewhere:example.org",
        "type": "m.room.minimal_pdu"
      }
    ],
    "event": {
      "auth_events": [
        "$urlsafe_base64_encoded_eventid",
        "$a-different-event-id"
      ],
      "content": {
        "join_authorised_via_users_server": "@arbitrary:resident.example.com",
        "membership": "join"
      },
      "depth": 12,
      "hashes": {
        "sha256": "thishashcoversallfieldsincasethisisredacted"
      },
      "origin_server_ts": 1404838188000,
      "prev_events": [
        "$urlsafe_base64_encoded_eventid",
        "$a-different-event-id"
      ],
      "room_id": "!UcYsUzyxTGDxLBEvLy:example.org",
      "sender": "@alice:example.com",
      "signatures": {
        "example.com": {
          "ed25519:key_version": "these86bytesofbase64signaturecoveressentialfieldsincludinghashessocancheckredactedpdus"
        },
        "resident.example.com": {
          "ed25519:other_key_version": "a different signature"
        }
      },
      "state_key": "@alice:example.com",
      "type": "m.room.member",
      "unsigned": {
        "age": 4612
      }
    },
    "state": [
      {
        "content": {
          "see_room_version_spec": "The event format changes depending on the room version."
        },
        "room_id": "!somewhere:example.org",
        "type": "m.room.minimal_pdu"
      }
    ]
  }
]

PUT /_matrix/federation/v2/send_join/{roomId}/{eventId}


Note: This API is nearly identical to the v1 API with the exception of the response format being fixed.

This endpoint is preferred over the v1 API as it provides a more standardised response format. Senders which receive a 400, 404, or other status code which indicates this endpoint is not available should retry using the v1 API instead.

Submits a signed join event to the resident server for it to accept it into the room’s graph. Note that events have a different format depending on the room version - check the room version specification for precise event formats. The request and response body here describe the common event fields in more detail and may be missing other required fields for a PDU.

Rate-limited: No
Requires authentication: Yes

Request

Request parameters

path parameters
Name Type Description
eventId string

Required: The event ID for the join event.

roomId string

Required: The room ID that is about to be joined.

query parameters
Name Type Description
omit_members boolean

If true, indicates that that calling server can accept a reduced response, in which membership events are omitted from state and redundant events are omitted from auth_chain.

If the room to be joined has no m.room.name nor m.room.canonical_alias events in its current state, the resident server should determine the room members who would be included in the m.heroes property of the room summary as defined in the Client-Server /sync response. The resident server should include these members’ membership events in the response state field, and include the auth chains for these membership events in the response auth_chain field.

Added in v1.6

Request body

Name Type Description
content Membership Event Content

Required: The content of the event.

origin string

Required: The name of the joining homeserver.

origin_server_ts integer

Required: A timestamp added by the joining homeserver.

sender string

Required: The user ID of the joining member.

state_key string

Required: The user ID of the joining member.

type string

Required: The value m.room.member.

Membership Event Content
Name Type Description
join_authorised_via_users_server string

Required if the room is restricted and is joining through one of the conditions available. If the user is responding to an invite, this is not required.

An arbitrary user ID belonging to the resident server in the room being joined that is able to issue invites to other users. This is used in later validation of the auth rules for the m.room.member event.

The resident server which owns the provided user ID must have a valid signature on the event. If the resident server is receiving the /send_join request, the signature must be added before sending or persisting the event to other servers.

Added in v1.2

membership string

Required: The value join.

Request body example

{
  "content": {
    "join_authorised_via_users_server": "@anyone:resident.example.org",
    "membership": "join"
  },
  "origin": "example.org",
  "origin_server_ts": 1549041175876,
  "sender": "@someone:example.org",
  "state_key": "@someone:example.org",
  "type": "m.room.member"
}

Responses

Status Description
200 The join event has been accepted into the room.
400

The request is invalid in some way.

The error should be passed through to clients so that they may give better feedback to users.

New in v1.2, the following error conditions might happen:

If the room is restricted and none of the conditions can be validated by the server then the errcode M_UNABLE_TO_AUTHORISE_JOIN must be used. This can happen if the server does not know about any of the rooms listed as conditions, for example.

M_UNABLE_TO_GRANT_JOIN is returned to denote that a different server should be attempted for the join. This is typically because the resident server can see that the joining user satisfies one or more conditions, such as in the case of restricted rooms, but the resident server would be unable to meet the auth rules governing join_authorised_via_users_server on the resulting m.room.member event.

403 The room that the joining server is attempting to join does not permit the user to join.

200 response

Name Type Description
auth_chain [PDU]

Required: All events in the auth chain for the new join event, as well as those in the auth chains for any events returned in state.

If the omit_members query parameter was set to true, then any events that are returned in state may be omitted from auth_chain, whether or not membership events are omitted from state.

Note that events have a different format depending on the room version - check the room version specification for precise event formats.

Changed in v1.6: reworded to include only consider state events returned in state, and to allow elision of redundant events.

event SignedMembershipEvent

The membership event sent to other servers by the resident server including a signature from the resident server. Required if the room is restricted and the joining user is authorised by one of the conditions.

Added in v1.2

members_omitted boolean

true if m.room.member events have been omitted from state.

Added in v1.6

servers_in_room [string]

Required if members_omitted is true.

A list of the servers active in the room (ie, those with joined members) before the join.

Added in v1.6

state [PDU]

Required: The resolved current room state prior to the join event.

If the request had omit_members set to true, events of type m.room.member may be omitted from the response to reduce the size of the response. If this is done, members_omitted must be set to true.

Changed in v1.6: permit omission of membership events.

{
  "auth_chain": [
    {
      "content": {
        "see_room_version_spec": "The event format changes depending on the room version."
      },
      "room_id": "!somewhere:example.org",
      "type": "m.room.minimal_pdu"
    }
  ],
  "event": {
    "auth_events": [
      "$urlsafe_base64_encoded_eventid",
      "$a-different-event-id"
    ],
    "content": {
      "join_authorised_via_users_server": "@arbitrary:resident.example.com",
      "membership": "join"
    },
    "depth": 12,
    "hashes": {
      "sha256": "thishashcoversallfieldsincasethisisredacted"
    },
    "origin_server_ts": 1404838188000,
    "prev_events": [
      "$urlsafe_base64_encoded_eventid",
      "$a-different-event-id"
    ],
    "room_id": "!UcYsUzyxTGDxLBEvLy:example.org",
    "sender": "@alice:example.com",
    "signatures": {
      "example.com": {
        "ed25519:key_version": "these86bytesofbase64signaturecoveressentialfieldsincludinghashessocancheckredactedpdus"
      },
      "resident.example.com": {
        "ed25519:other_key_version": "a different signature"
      }
    },
    "state_key": "@alice:example.com",
    "type": "m.room.member",
    "unsigned": {
      "age": 4612
    }
  },
  "members_omitted": true,
  "servers_in_room": [
    "matrix.org",
    "example.com"
  ],
  "state": [
    {
      "content": {
        "see_room_version_spec": "The event format changes depending on the room version."
      },
      "room_id": "!somewhere:example.org",
      "type": "m.room.minimal_pdu"
    }
  ]
}

400 response

Error
Name Type Description
errcode string

Required: An error code.

error string

A human-readable error message.

{
  "errcode": "M_UNABLE_TO_GRANT_JOIN",
  "error": "This server cannot send invites to you."
}

403 response

Error
Name Type Description
errcode string

Required: An error code.

error string

A human-readable error message.

{
  "errcode": "M_FORBIDDEN",
  "error": "You are not invited to this room"
}

受限房间

受限房间详细描述见 客户端-服务器 API,仅在 支持受限加入的房间版本 下启用。

处理请求加入受限房间时,常驻服务器需确保加入服务器满足 m.room.join_rules 所定义的至少一项条件。若无条件、或者无条件符合所需模式,则视为全部校验失败。

校验条件失败时,/make_join/send_join 应返回 400 M_UNABLE_TO_AUTHORISE_JOIN(通常因无法获知所需房间的状态信息)。

若加入用户满足某些条件,但常驻服务器自身不满足生成 join_authorised_via_users_server 所需的权限,则返回 400 M_UNABLE_TO_GRANT_JOIN,表明需换服务器尝试。

所有条件均未满足时,常驻服务器返回 403 M_FORBIDDEN

敲门加入房间

房间可通过 join rules 允许敲门。允许时,用户可请求加入房间(即被邀请)。本地已在房间服务器可直接发送敲门事件,否则需如 加入房间 一样,通过握手流程让远端协助发送。

敲门握手同加入握手基本一致,区别在于角色变为“敲门服务器”,API 包括 /make_knock/send_knock

服务器间敲门可通过离开房间取消,见下述邀请拒绝相关说明。

GET /_matrix/federation/v1/make_knock/{roomId}/{userId}


Added in v1.1

Asks the receiving server to return information that the sending server will need to prepare a knock event for the room.

Rate-limited: No
Requires authentication: Yes

Request

Request parameters

path parameters
Name Type Description
roomId string

Required: The room ID that is about to be knocked.

userId string

Required: The user ID the knock event will be for.

query parameters
Name Type Description
ver [string]

Required: The room versions the sending server has support for.


Responses

Status Description
200 A template to be used for the rest of the Knocking Rooms handshake. Note that events have a different format depending on room version - check the room version specification for precise event formats. The response body here describes the common event fields in more detail and may be missing other required fields for a PDU.
400

The request is invalid or the room the server is attempting to knock upon has a version that is not listed in the ver parameters.

The error should be passed through to clients so that they may give better feedback to users.

403 The knocking server or user is not permitted to knock on the room, such as when the server/user is banned or the room is not set up for receiving knocks.
404 The room that the knocking server is attempting to knock upon is unknown to the receiving server.

200 response

Name Type Description
event Event Template

Required: An unsigned template event. Note that events have a different format depending on the room version - check the room version specification for precise event formats.

room_version string

Required: The version of the room where the server is trying to knock.

Event Template
Name Type Description
content Membership Event Content

Required: The content of the event.

origin string

Required: The name of the resident homeserver.

origin_server_ts integer

Required: A timestamp added by the resident homeserver.

sender string

Required: The user ID of the knocking member.

state_key string

Required: The user ID of the knocking member.

type string

Required: The value m.room.member.

Membership Event Content
Name Type Description
membership string

Required: The value knock.

{
  "event": {
    "content": {
      "membership": "knock"
    },
    "origin": "example.org",
    "origin_server_ts": 1549041175876,
    "room_id": "!somewhere:example.org",
    "sender": "@someone:example.org",
    "state_key": "@someone:example.org",
    "type": "m.room.member"
  },
  "room_version": "7"
}

400 response

Error
Name Type Description
errcode string

Required: An error code.

error string

A human-readable error message.

room_version string

The version of the room. Required if the errcode is M_INCOMPATIBLE_ROOM_VERSION.

{
  "errcode": "M_INCOMPATIBLE_ROOM_VERSION",
  "error": "Your homeserver does not support the features required to knock on this room",
  "room_version": "7"
}

403 response

Error
Name Type Description
errcode string

Required: An error code.

error string

A human-readable error message.

{
  "errcode": "M_FORBIDDEN",
  "error": "You are not permitted to knock on this room"
}

404 response

Error
Name Type Description
errcode string

Required: An error code.

error string

A human-readable error message.

{
  "errcode": "M_NOT_FOUND",
  "error": "Unknown room"
}

PUT /_matrix/federation/v1/send_knock/{roomId}/{eventId}


Added in v1.1

Submits a signed knock event to the resident server for it to accept into the room’s graph. Note that events have a different format depending on the room version - check the room version specification for precise event formats. The request and response body here describe the common event fields in more detail and may be missing other required fields for a PDU.

Rate-limited: No
Requires authentication: Yes

Request

Request parameters

path parameters
Name Type Description
eventId string

Required: The event ID for the knock event.

roomId string

Required: The room ID that is about to be knocked upon.

Request body

Name Type Description
content Membership Event Content

Required: The content of the event.

origin string

Required: The name of the knocking homeserver.

origin_server_ts integer

Required: A timestamp added by the knocking homeserver.

sender string

Required: The user ID of the knocking member.

state_key string

Required: The user ID of the knocking member.

type string

Required: The value m.room.member.

Membership Event Content
Name Type Description
membership string

Required: The value knock.

Request body example

{
  "content": {
    "membership": "knock"
  },
  "origin": "example.org",
  "origin_server_ts": 1549041175876,
  "sender": "@someone:example.org",
  "state_key": "@someone:example.org",
  "type": "m.room.member"
}

Responses

Status Description
200 Information about the room to pass along to clients regarding the knock.
403 The knocking server or user is not permitted to knock on the room, such as when the server/user is banned or the room is not set up for receiving knocks.
404 The room that the knocking server is attempting to knock upon is unknown to the receiving server.

200 response

Name Type Description
knock_room_state [StrippedStateEvent]

Required: A list of stripped state events to help the initiator of the knock identify the room.

StrippedStateEvent
Name Type Description
content EventContent

Required: The content for the event.

sender string

Required: The sender for the event.

state_key string

Required: The state_key for the event.

type string

Required: The type for the event.

{
  "knock_room_state": [
    {
      "content": {
        "name": "Example Room"
      },
      "sender": "@bob:example.org",
      "state_key": "",
      "type": "m.room.name"
    },
    {
      "content": {
        "join_rule": "knock"
      },
      "sender": "@bob:example.org",
      "state_key": "",
      "type": "m.room.join_rules"
    }
  ]
}

403 response

Error
Name Type Description
errcode string

Required: An error code.

error string

A human-readable error message.

{
  "errcode": "M_FORBIDDEN",
  "error": "You are not permitted to knock on this room"
}

404 response

Error
Name Type Description
errcode string

Required: An error code.

error string

A human-readable error message.

{
  "errcode": "M_NOT_FOUND",
  "error": "Unknown room"
}

房间邀请

同一服务器用户间发起邀请时,服务器可直接签署并跳过此处流程。跨服务器邀请时,必须向被邀服务器请求事件签名和校验。

邀请事件同样用于通知之前的敲门请求被接受。因此,接收服务器应准备好将此前敲门事件与邀请事件关联(即使邀请未直接引用敲门)。

PUT /_matrix/federation/v1/invite/{roomId}/{eventId}


Invites a remote user to a room. Once the event has been signed by both the inviting homeserver and the invited homeserver, it can be sent to all of the servers in the room by the inviting homeserver.

Servers should prefer to use the v2 API for invites instead of the v1 API. Servers which receive a v1 invite request must assume that the room version is either "1" or "2".

Note that events have a different format depending on the room version - check the room version specification for precise event formats. The request and response bodies here describe the common event fields in more detail and may be missing other required fields for a PDU.

Rate-limited: No
Requires authentication: Yes

Request

Request parameters

path parameters
Name Type Description
eventId string

Required: The event ID for the invite event, generated by the inviting server.

roomId string

Required: The room ID that the user is being invited to.

Request body

InviteEvent
Name Type Description
content Membership Event Content

Required: The content of the event, matching what is available in the Client-Server API. Must include a membership of invite.

origin string

Required: The name of the inviting homeserver.

origin_server_ts integer

Required: A timestamp added by the inviting homeserver.

sender string

Required: The matrix ID of the user who sent the original m.room.third_party_invite.

state_key string

Required: The user ID of the invited member.

type string

Required: The value m.room.member.

unsigned UnsignedData

Information included alongside the event that is not signed. May include more than what is listed here.

Membership Event Content
Name Type Description
membership string

Required: The value invite.

UnsignedData
Name Type Description
invite_room_state [StrippedStateEvent]

An optional list of stripped state events to help the receiver of the invite identify the room.

StrippedStateEvent
Name Type Description
content EventContent

Required: The content for the event.

sender string

Required: The sender for the event.

state_key string

Required: The state_key for the event.

type string

Required: The type for the event.

Request body example

{
  "content": {
    "membership": "invite"
  },
  "origin": "matrix.org",
  "origin_server_ts": 1234567890,
  "sender": "@someone:example.org",
  "state_key": "@joe:elsewhere.com",
  "type": "m.room.member",
  "unsigned": {
    "invite_room_state": [
      {
        "content": {
          "name": "Example Room"
        },
        "sender": "@bob:example.org",
        "state_key": "",
        "type": "m.room.name"
      },
      {
        "content": {
          "join_rule": "invite"
        },
        "sender": "@bob:example.org",
        "state_key": "",
        "type": "m.room.join_rules"
      }
    ]
  }
}

Responses

Status Description
200 The event with the invited server’s signature added. All other fields of the events should remain untouched. Note that events have a different format depending on the room version - check the room version specification for precise event formats.
403

The invite is not allowed. This could be for a number of reasons, including:

  • The sender is not allowed to send invites to the target user/homeserver.
  • The homeserver does not permit anyone to invite its users.
  • The homeserver refuses to participate in the room.

200 response

Array of integer, Event Container.

Event Container
Name Type Description
event InviteEvent

Required: An invite event. Note that events have a different format depending on the room version - check the room version specification for precise event formats.

InviteEvent
Name Type Description
content Membership Event Content

Required: The content of the event, matching what is available in the Client-Server API. Must include a membership of invite.

origin string

Required: The name of the inviting homeserver.

origin_server_ts integer

Required: A timestamp added by the inviting homeserver.

sender string

Required: The matrix ID of the user who sent the original m.room.third_party_invite.

state_key string

Required: The user ID of the invited member.

type string

Required: The value m.room.member.

Membership Event Content
Name Type Description
membership string

Required: The value invite.

[
  200,
  {
    "event": {
      "content": {
        "membership": "invite"
      },
      "origin": "example.org",
      "origin_server_ts": 1549041175876,
      "room_id": "!somewhere:example.org",
      "sender": "@someone:example.org",
      "signatures": {
        "elsewhere.com": {
          "ed25519:k3y_versi0n": "SomeOtherSignatureHere"
        },
        "example.com": {
          "ed25519:key_version": "SomeSignatureHere"
        }
      },
      "state_key": "@someone:example.org",
      "type": "m.room.member",
      "unsigned": {
        "invite_room_state": [
          {
            "content": {
              "name": "Example Room"
            },
            "sender": "@bob:example.org",
            "state_key": "",
            "type": "m.room.name"
          },
          {
            "content": {
              "join_rule": "invite"
            },
            "sender": "@bob:example.org",
            "state_key": "",
            "type": "m.room.join_rules"
          }
        ]
      }
    }
  }
]

403 response

Error
Name Type Description
errcode string

Required: An error code.

error string

A human-readable error message.

{
  "errcode": "M_FORBIDDEN",
  "error": "User cannot invite the target user."
}

PUT /_matrix/federation/v2/invite/{roomId}/{eventId}


Note: This API is nearly identical to the v1 API with the exception of the request body being different, and the response format fixed.

Invites a remote user to a room. Once the event has been signed by both the inviting homeserver and the invited homeserver, it can be sent to all of the servers in the room by the inviting homeserver.

This endpoint is preferred over the v1 API as it is more useful for servers. Senders which receive a 400 or 404 response to this endpoint should retry using the v1 API as the server may be older, if the room version is “1” or “2”.

Note that events have a different format depending on the room version - check the room version specification for precise event formats. The request and response bodies here describe the common event fields in more detail and may be missing other required fields for a PDU.

Rate-limited: No
Requires authentication: Yes

Request

Request parameters

path parameters
Name Type Description
eventId string

Required: The event ID for the invite event, generated by the inviting server.

roomId string

Required: The room ID that the user is being invited to.

Request body

Name Type Description
event InviteEvent

Required: An invite event. Note that events have a different format depending on the room version - check the room version specification for precise event formats.

invite_room_state [StrippedStateEvent]

An optional list of stripped state events to help the receiver of the invite identify the room.

room_version string

Required: The version of the room where the user is being invited to.

InviteEvent
Name Type Description
content Membership Event Content

Required: The content of the event, matching what is available in the Client-Server API. Must include a membership of invite.

origin string

Required: The name of the inviting homeserver.

origin_server_ts integer

Required: A timestamp added by the inviting homeserver.

sender string

Required: The matrix ID of the user who sent the original m.room.third_party_invite.

state_key string

Required: The user ID of the invited member.

type string

Required: The value m.room.member.

Membership Event Content
Name Type Description
membership string

Required: The value invite.

StrippedStateEvent
Name Type Description
content EventContent

Required: The content for the event.

sender string

Required: The sender for the event.

state_key string

Required: The state_key for the event.

type string

Required: The type for the event.

Request body example

{
  "event": {
    "content": {
      "membership": "invite"
    },
    "origin": "matrix.org",
    "origin_server_ts": 1234567890,
    "sender": "@someone:example.org",
    "state_key": "@joe:elsewhere.com",
    "type": "m.room.member"
  },
  "invite_room_state": [
    {
      "content": {
        "name": "Example Room"
      },
      "sender": "@bob:example.org",
      "state_key": "",
      "type": "m.room.name"
    },
    {
      "content": {
        "join_rule": "invite"
      },
      "sender": "@bob:example.org",
      "state_key": "",
      "type": "m.room.join_rules"
    }
  ],
  "room_version": "2"
}

Responses

Status Description
200 The event with the invited server’s signature added. All other fields of the events should remain untouched. Note that events have a different format depending on the room version - check the room version specification for precise event formats.
400

The request is invalid or the room the server is attempting to join has a version that is not listed in the ver parameters.

The error should be passed through to clients so that they may give better feedback to users.

403

The invite is not allowed. This could be for a number of reasons, including:

  • The sender is not allowed to send invites to the target user/homeserver.
  • The homeserver does not permit anyone to invite its users.
  • The homeserver refuses to participate in the room.

200 response

Event Container
Name Type Description
event InviteEvent

Required: An invite event. Note that events have a different format depending on the room version - check the room version specification for precise event formats.

InviteEvent
Name Type Description
content Membership Event Content

Required: The content of the event, matching what is available in the Client-Server API. Must include a membership of invite.

origin string

Required: The name of the inviting homeserver.

origin_server_ts integer

Required: A timestamp added by the inviting homeserver.

sender string

Required: The matrix ID of the user who sent the original m.room.third_party_invite.

state_key string

Required: The user ID of the invited member.

type string

Required: The value m.room.member.

Membership Event Content
Name Type Description
membership string

Required: The value invite.

{
  "event": {
    "content": {
      "membership": "invite"
    },
    "origin": "example.org",
    "origin_server_ts": 1549041175876,
    "room_id": "!somewhere:example.org",
    "sender": "@someone:example.org",
    "signatures": {
      "elsewhere.com": {
        "ed25519:k3y_versi0n": "SomeOtherSignatureHere"
      },
      "example.com": {
        "ed25519:key_version": "SomeSignatureHere"
      }
    },
    "state_key": "@someone:example.org",
    "type": "m.room.member",
    "unsigned": {
      "invite_room_state": [
        {
          "content": {
            "name": "Example Room"
          },
          "sender": "@bob:example.org",
          "state_key": "",
          "type": "m.room.name"
        },
        {
          "content": {
            "join_rule": "invite"
          },
          "sender": "@bob:example.org",
          "state_key": "",
          "type": "m.room.join_rules"
        }
      ]
    }
  }
}

400 response

Error
Name Type Description
errcode string

Required: An error code.

error string

A human-readable error message.

room_version string

The version of the room. Required if the errcode is M_INCOMPATIBLE_ROOM_VERSION.

{
  "errcode": "M_INCOMPATIBLE_ROOM_VERSION",
  "error": "Your homeserver does not support the features required to join this room",
  "room_version": "3"
}

403 response

Error
Name Type Description
errcode string

Required: An error code.

error string

A human-readable error message.

{
  "errcode": "M_FORBIDDEN",
  "error": "User cannot invite the target user."
}

离开房间(拒绝邀请)

家服务器可主动发送 m.room.member 事件令用户离开房间、拒绝本地邀请或撤销敲门。针对其他家服务器发出的远程邀请或敲门,由于图谱中未参与,需采用特殊方式拒绝邀请。直接先加入再离开并不可取,因为客户端会认为用户先接受邀请再主动退出,这和拒绝邀请有本质区别。

加入房间 握手类似,发起离开的服务器需先向常驻服务器发 /make_leave。拒绝邀请时,常驻服务器可为邀请发起方。收到 /make_leave 模板事件后,发起服务器签名并设置自己的 event_id,通过 /send_leave 发送给常驻服务器,常驻服务器再下发给房间内其他服务器。

GET /_matrix/federation/v1/make_leave/{roomId}/{userId}


Asks the receiving server to return information that the sending server will need to prepare a leave event to get out of the room.

Rate-limited: No
Requires authentication: Yes

Request

Request parameters

path parameters
Name Type Description
roomId string

Required: The room ID that is about to be left.

userId string

Required: The user ID the leave event will be for.


Responses

Status Description
200 A template to be used to call /send_leave. Note that events have a different format depending on the room version - check the room version specification for precise event formats. The response body here describes the common event fields in more detail and may be missing other required fields for a PDU.
403 The request is not authorized. This could mean that the user is not in the room.

200 response

Name Type Description
event Event Template

An unsigned template event. Note that events have a different format depending on the room version - check the room version specification for precise event formats.

room_version string

The version of the room where the server is trying to leave. If not provided, the room version is assumed to be either “1” or “2”.

Event Template
Name Type Description
content Membership Event Content

Required: The content of the event.

origin string

Required: The name of the resident homeserver.

origin_server_ts integer

Required: A timestamp added by the resident homeserver.

sender string

Required: The user ID of the leaving member.

state_key string

Required: The user ID of the leaving member.

type string

Required: The value m.room.member.

Membership Event Content
Name Type Description
membership string

Required: The value leave.

{
  "event": {
    "content": {
      "membership": "leave"
    },
    "origin": "example.org",
    "origin_server_ts": 1549041175876,
    "room_id": "!somewhere:example.org",
    "sender": "@someone:example.org",
    "state_key": "@someone:example.org",
    "type": "m.room.member"
  },
  "room_version": "2"
}

403 response

Error
Name Type Description
errcode string

Required: An error code.

error string

A human-readable error message.

{
  "errcode": "M_FORBIDDEN",
  "error": "User is not in the room."
}

PUT /_matrix/federation/v1/send_leave/{roomId}/{eventId}


This API is deprecated and will be removed from a future release.

Note: Servers should instead prefer to use the v2 /send_leave endpoint.

Submits a signed leave event to the resident server for it to accept it into the room’s graph. Note that events have a different format depending on the room version - check the room version specification for precise event formats. The request and response body here describe the common event fields in more detail and may be missing other required fields for a PDU.

Rate-limited: No
Requires authentication: Yes

Request

Request parameters

path parameters
Name Type Description
eventId string

Required: The event ID for the leave event.

roomId string

Required: The room ID that is about to be left.

Request body

Name Type Description
content Membership Event Content

Required: The content of the event.

depth integer

Required: This field must be present but is ignored; it may be 0.

origin string

Required: The name of the leaving homeserver.

origin_server_ts integer

Required: A timestamp added by the leaving homeserver.

sender string

Required: The user ID of the leaving member.

state_key string

Required: The user ID of the leaving member.

type string

Required: The value m.room.member.

Membership Event Content
Name Type Description
membership string

Required: The value leave.

Request body example

{
  "content": {
    "membership": "leave"
  },
  "depth": 12,
  "origin": "matrix.org",
  "origin_server_ts": 1234567890,
  "sender": "@someone:example.org",
  "state_key": "@someone:example.org",
  "type": "m.room.member"
}

Responses

Status Description
200 An empty response to indicate the event was accepted into the graph by the receiving homeserver.

200 response

Array of integer, Empty Object.

[
  200,
  {}
]

PUT /_matrix/federation/v2/send_leave/{roomId}/{eventId}


Note: This API is nearly identical to the v1 API with the exception of the response format being fixed.

This endpoint is preferred over the v1 API as it provides a more standardised response format. Senders which receive a 400, 404, or other status code which indicates this endpoint is not available should retry using the v1 API instead.

Submits a signed leave event to the resident server for it to accept it into the room’s graph. Note that events have a different format depending on the room version - check the room version specification for precise event formats. The request and response body here describe the common event fields in more detail and may be missing other required fields for a PDU.

Rate-limited: No
Requires authentication: Yes

Request

Request parameters

path parameters
Name Type Description
eventId string

Required: The event ID for the leave event.

roomId string

Required: The room ID that is about to be left.

Request body

Name Type Description
content Membership Event Content

Required: The content of the event.

depth integer

Required: This field must be present but is ignored; it may be 0.

origin string

Required: The name of the leaving homeserver.

origin_server_ts integer

Required: A timestamp added by the leaving homeserver.

sender string

Required: The user ID of the leaving member.

state_key string

Required: The user ID of the leaving member.

type string

Required: The value m.room.member.

Membership Event Content
Name Type Description
membership string

Required: The value leave.

Request body example

{
  "content": {
    "membership": "leave"
  },
  "depth": 0,
  "origin": "example.org",
  "origin_server_ts": 1549041175876,
  "sender": "@someone:example.org",
  "state_key": "@someone:example.org",
  "type": "m.room.member"
}

Responses

Status Description
200 An empty response to indicate the event was accepted into the graph by the receiving homeserver.

200 response

{}

第三方邀请

有关第三方邀请的更多信息请见 客户端-服务器 API 的对应模块。

用户欲邀请不知道 Matrix ID 的用户进房间时,可使用第三方标识(如邮箱或手机号)发起邀请。

此标识及其与 Matrix ID 的绑定由实现 身份服务 API 的身份服务器验证。

第三方标识已有绑定时

若标识已绑定 Matrix ID,身份服务器查询会返回。邀请将作为普通 m.room.member 事件处理。

第三方标识尚无绑定时

若标识尚未绑定 Matrix ID,则邀请服务器将请求身份服务器存储并待有人绑定该标识后推送。邀请服务器还需在房间发 m.room.third_party_invite 事件,写入显示名、令牌及身份服务器返回的公钥。

当某个 Matrix ID 绑定此标识后,身份服务器会按 邀请存储 的说明 POST 至对应家服务器。

每次邀请,家服务器会创建携带特殊 third_party_invite 节点的 m.room.member 事件,内含令牌及签名对象。

如接收家服务器已在房间,可直接授权发事件;否则需向房间家服务器发授权请求。

PUT /_matrix/federation/v1/3pid/onbind


Used by identity servers to notify the homeserver that one of its users has bound a third-party identifier successfully, including any pending room invites the identity server has been made aware of.

Rate-limited: No
Requires authentication: No

Request

Request body

Name Type Description
address string

Required: The third-party identifier itself. For example, an email address.

invites [Third-party Invite]

Required: A list of pending invites that the third-party identifier has received.

medium string

Required: The type of third-party identifier. Currently only “email” is a possible value.

mxid string

Required: The user that is now bound to the third-party identifier.

Third-party Invite
Name Type Description
address string

Required: The third-party identifier that received the invite.

medium string

Required: The type of third-party invite issues. Currently only “email” is used.

mxid string

Required: The now-bound user ID that received the invite.

room_id string

Required: The room ID the invite is valid for.

sender string

Required: The user ID that sent the invite.

signed Identity Server Signatures

Required: Signature from the identity server using a long-term private key.

Identity Server Signatures
Name Type Description
mxid string

Required: The user ID that has been bound to the third-party identifier.

signatures {string: Identity Server Domain Signature}

Required: The signature from the identity server. The string key is the identity server’s domain name, such as vector.im

token string

Required: A token.

Identity Server Domain Signature
Name Type Description
ed25519:0 string

Required: The signature.

Request body example

{
  "address": "alice@example.com",
  "invites": [
    {
      "address": "alice@example.com",
      "medium": "email",
      "mxid": "@alice:matrix.org",
      "room_id": "!somewhere:example.org",
      "sender": "@bob:matrix.org",
      "signed": {
        "mxid": "@alice:matrix.org",
        "signatures": {
          "vector.im": {
            "ed25519:0": "SomeSignatureGoesHere"
          }
        },
        "token": "Hello World"
      }
    }
  ],
  "medium": "email",
  "mxid": "@alice:matrix.org"
}

Responses

Status Description
200 The homeserver has processed the notification.

200 response

{}

PUT /_matrix/federation/v1/exchange_third_party_invite/{roomId}


The receiving server will verify the partial m.room.member event given in the request body. If valid, the receiving server will issue an invite as per the Inviting to a room section before returning a response to this request.

Rate-limited: No
Requires authentication: Yes

Request

Request parameters

path parameters
Name Type Description
roomId string

Required: The room ID to exchange a third-party invite in

Request body

Name Type Description
content Event Content

Required: The event content

room_id string

Required: The room ID the event is for. Must match the ID given in the path.

sender string

Required: The user ID of the user who sent the original m.room.third_party_invite event.

state_key string

Required: The user ID of the invited user

type string

Required: The event type. Must be m.room.member

Event Content
Name Type Description
membership string

Required: The membership state. Must be invite

third_party_invite Third-party Invite

Required: The third-party invite

Third-party Invite
Name Type Description
display_name string

Required: A name which can be displayed to represent the user instead of their third-party identifier.

signed Invite Signatures

Required: A block of content which has been signed, which servers can use to verify the event.

Invite Signatures
Name Type Description
mxid string

Required: The invited matrix user ID

signatures {string: {string: string}}

Required: The server signatures for this event.

The signature is calculated using the process described at Signing JSON.

token string

Required: The token used to verify the event

Request body example

{
  "content": {
    "membership": "invite",
    "third_party_invite": {
      "display_name": "alice",
      "signed": {
        "mxid": "@alice:localhost",
        "signatures": {
          "magic.forest": {
            "ed25519:3": "fQpGIW1Snz+pwLZu6sTy2aHy/DYWWTspTJRPyNp0PKkymfIsNffysMl6ObMMFdIJhk6g6pwlIqZ54rxo8SLmAg"
          }
        },
        "token": "abc123"
      }
    }
  },
  "room_id": "!abc123:matrix.org",
  "sender": "@joe:matrix.org",
  "state_key": "@someone:example.org",
  "type": "m.room.member"
}

Responses

Status Description
200 The invite has been issued successfully.

200 response

{}

邀请校验

家服务器收到带 third_party_invite 对象的 m.room.member 邀请事件后,须在无需第三方服务器的情况下验证受邀 Matrix ID 与标识已有验证关系。

需从房间状态取出 m.room.third_party_invite 事件,其 state_keym.room.member 事件内容内 third_party_invite 里的 token 字段匹配,获得身份服务器提供的公钥。

用该公钥校验 m.room.member 事件 content.third_party_invite.signed 对象的签名,保证创建邀请事件的确为拥有此第三方标识的用户。

鉴于该签名对象仅能在绑定标识与 Matrix ID 时由身份服务器发送一次,且内含指明 Matrix ID 及令牌,因此能保证为真实所有者。

公共房间目录

为配合 客户端-服务器 API 的房间目录,家服务器需要可从远端查询目标服务器的公共房间。请求目标服务器的 /publicRooms 端点即可。

GET /_matrix/federation/v1/publicRooms


Gets all the public rooms for the homeserver. This should not return rooms that are listed on another homeserver’s directory, just those listed on the receiving homeserver’s directory.

Rate-limited: No
Requires authentication: Yes

Request

Request parameters

query parameters
Name Type Description
include_all_networks boolean

Whether or not to include all networks/protocols defined by application services on the homeserver. Defaults to false.

limit integer

The maximum number of rooms to return. Defaults to 0 (no limit).

since string

A pagination token from a previous call to this endpoint to fetch more rooms.

third_party_instance_id string

The specific third-party network/protocol to request from the homeserver. Can only be used if include_all_networks is false.

This is the instance_id of a Protocol Instance returned by GET /_matrix/client/v3/thirdparty/protocols.


Responses

Status Description
200 The public room list for the homeserver.

200 response

Name Type Description
chunk [PublicRoomsChunk]

Required: A paginated chunk of public rooms.

next_batch string

A pagination token for the response. The absence of this token means there are no more results to fetch and the client should stop paginating.

prev_batch string

A pagination token that allows fetching previous results. The absence of this token means there are no results before this batch, i.e. this is the first batch.

total_room_count_estimate integer

An estimate on the total number of public rooms, if the server has an estimate.

PublicRoomsChunk
Name Type Description
avatar_url URI

The URL for the room’s avatar, if one is set.

canonical_alias string

The canonical alias of the room, if any.

guest_can_join boolean

Required: Whether guest users may join the room and participate in it. If they can, they will be subject to ordinary power level rules like any other user.

join_rule string

The room’s join rule. When not present, the room is assumed to be public. Note that rooms with invite join rules are not expected here, but rooms with knock rules are given their near-public nature.

name string

The name of the room, if any.

num_joined_members integer

Required: The number of members joined to the room.

room_id string

Required: The ID of the room.

room_type string

The type of room (from m.room.create), if any.

Added in v1.4

topic string

The topic of the room, if any.

world_readable boolean

Required: Whether the room may be viewed by guest users without joining.

{
  "chunk": [
    {
      "avatar_url": "mxc://bleecker.street/CHEDDARandBRIE",
      "guest_can_join": false,
      "join_rule": "public",
      "name": "CHEESE",
      "num_joined_members": 37,
      "room_id": "!ol19s:bleecker.street",
      "room_type": "m.space",
      "topic": "Tasty tasty cheese",
      "world_readable": true
    }
  ],
  "next_batch": "p190q",
  "prev_batch": "p1902",
  "total_room_count_estimate": 115
}

POST /_matrix/federation/v1/publicRooms


Lists the public rooms on the server, with optional filter.

This API returns paginated responses. The rooms are ordered by the number of joined members, with the largest rooms first.

Note that this endpoint receives and returns the same format that is seen in the Client-Server API’s POST /publicRooms endpoint.

Rate-limited: No
Requires authentication: Yes

Request

Request body

Name Type Description
filter Filter

Filter to apply to the results.

include_all_networks boolean

Whether or not to include all known networks/protocols from application services on the homeserver. Defaults to false.

limit integer

Limit the number of results returned.

since string

A pagination token from a previous request, allowing servers to get the next (or previous) batch of rooms. The direction of pagination is specified solely by which token is supplied, rather than via an explicit flag.

third_party_instance_id string

The specific third-party network/protocol to request from the homeserver. Can only be used if include_all_networks is false.

This is the instance_id of a Protocol Instance returned by GET /_matrix/client/v3/thirdparty/protocols.

Filter
Name Type Description
generic_search_term string

An optional string to search for in the room metadata, e.g. name, topic, canonical alias, etc.

room_types [string|null]

An optional list of room types to search for. To include rooms without a room type, specify null within this list. When not specified, all applicable rooms (regardless of type) are returned.

Added in v1.4

Request body example

{
  "filter": {
    "generic_search_term": "foo",
    "room_types": [
      null,
      "m.space"
    ]
  },
  "include_all_networks": false,
  "limit": 10,
  "third_party_instance_id": "irc-freenode"
}

Responses

Status Description
200 A list of the rooms on the server.

200 response

Name Type Description
chunk [PublicRoomsChunk]

Required: A paginated chunk of public rooms.

next_batch string

A pagination token for the response. The absence of this token means there are no more results to fetch and the client should stop paginating.

prev_batch string

A pagination token that allows fetching previous results. The absence of this token means there are no results before this batch, i.e. this is the first batch.

total_room_count_estimate integer

An estimate on the total number of public rooms, if the server has an estimate.

PublicRoomsChunk
Name Type Description
avatar_url URI

The URL for the room’s avatar, if one is set.

canonical_alias string

The canonical alias of the room, if any.

guest_can_join boolean

Required: Whether guest users may join the room and participate in it. If they can, they will be subject to ordinary power level rules like any other user.

join_rule string

The room’s join rule. When not present, the room is assumed to be public. Note that rooms with invite join rules are not expected here, but rooms with knock rules are given their near-public nature.

name string

The name of the room, if any.

num_joined_members integer

Required: The number of members joined to the room.

room_id string

Required: The ID of the room.

room_type string

The type of room (from m.room.create), if any.

Added in v1.4

topic string

The topic of the room, if any.

world_readable boolean

Required: Whether the room may be viewed by guest users without joining.

{
  "chunk": [
    {
      "avatar_url": "mxc://bleecker.street/CHEDDARandBRIE",
      "guest_can_join": false,
      "join_rule": "public",
      "name": "CHEESE",
      "num_joined_members": 37,
      "room_id": "!ol19s:bleecker.street",
      "room_type": "m.space",
      "topic": "Tasty tasty cheese",
      "world_readable": true
    }
  ],
  "next_batch": "p190q",
  "prev_batch": "p1902",
  "total_room_count_estimate": 115
}

空间(Spaces)

为配合 客户端-服务器 API Spaces 模块,家服务器需可从远端服务器查询空间信息。

GET /_matrix/federation/v1/hierarchy/{roomId}


Added in v1.2

Federation version of the Client-Server GET /hierarchy endpoint. Unlike the Client-Server API version, this endpoint does not paginate. Instead, all the space-room’s children the requesting server could feasibly peek/join are returned. The requesting server is responsible for filtering the results further down for the user’s request.

Only m.space.child state events of the room are considered. Invalid child rooms and parent events are not covered by this endpoint.

Responses to this endpoint should be cached for a period of time.

Rate-limited: No
Requires authentication: Yes

Request

Request parameters

path parameters
Name Type Description
roomId string

Required: The room ID of the space to get a hierarchy for.

query parameters
Name Type Description
suggested_only boolean

Optional (default false) flag to indicate whether or not the server should only consider suggested rooms. Suggested rooms are annotated in their m.space.child event contents.


Responses

Status Description
200 The space room and its children.
404 The room is not known to the server or the requesting server is unable to peek/join it (if it were to attempt this).

200 response

Name Type Description
children [SpaceHierarchyChildRoomsChunk]

Required: A summary of the space’s children. Rooms which the requesting server cannot peek/join will be excluded.

inaccessible_children [string]

Required: The list of room IDs the requesting server doesn’t have a viable way to peek/join. Rooms which the responding server cannot provide details on will be outright excluded from the response instead.

Assuming both the requesting and responding server are well behaved, the requesting server should consider these room IDs as not accessible from anywhere. They should not be re-requested.

room SpaceHierarchyParentRoom

Required: A summary of the room requested.

SpaceHierarchyChildRoomsChunk
Name Type Description
allowed_room_ids [string]

If the room is a restricted room, these are the room IDs which are specified by the join rules. Empty or omitted otherwise.

avatar_url URI

The URL for the room’s avatar, if one is set.

canonical_alias string

The canonical alias of the room, if any.

guest_can_join boolean

Required: Whether guest users may join the room and participate in it. If they can, they will be subject to ordinary power level rules like any other user.

join_rule string

The room’s join rule. When not present, the room is assumed to be public.

name string

The name of the room, if any.

num_joined_members integer

Required: The number of members joined to the room.

room_id string

Required: The ID of the room.

room_type string

The type of room (from m.room.create), if any.

Added in v1.4

topic string

The topic of the room, if any.

world_readable boolean

Required: Whether the room may be viewed by guest users without joining.

SpaceHierarchyParentRoom
Name Type Description
allowed_room_ids [string]

If the room is a restricted room, these are the room IDs which are specified by the join rules. Empty or omitted otherwise.

avatar_url URI

The URL for the room’s avatar, if one is set.

canonical_alias string

The canonical alias of the room, if any.

children_state [StrippedStateEvent]

Required: The m.space.child events of the space-room, represented as Stripped State Events with an added origin_server_ts key.

If the room is not a space-room, this should be empty.

guest_can_join boolean

Required: Whether guest users may join the room and participate in it. If they can, they will be subject to ordinary power level rules like any other user.

join_rule string

The room’s join rule. When not present, the room is assumed to be public.

name string

The name of the room, if any.

num_joined_members integer

Required: The number of members joined to the room.

room_id string

Required: The ID of the room.

room_type string

The type of room (from m.room.create), if any.

Added in v1.4

topic string

The topic of the room, if any.

world_readable boolean

Required: Whether the room may be viewed by guest users without joining.

StrippedStateEvent
Name Type Description
content EventContent

Required: The content for the event.

origin_server_ts integer

Required: The origin_server_ts for the event.

sender string

Required: The sender for the event.

state_key string

Required: The state_key for the event.

type string

Required: The type for the event.

{
  "children": [
    {
      "allowed_room_ids": [
        "!upstream:example.org"
      ],
      "avatar_url": "mxc://example.org/abcdef2",
      "canonical_alias": "#general:example.org",
      "children_state": [
        {
          "content": {
            "via": [
              "remote.example.org"
            ]
          },
          "origin_server_ts": 1629422222222,
          "sender": "@alice:example.org",
          "state_key": "!b:example.org",
          "type": "m.space.child"
        }
      ],
      "guest_can_join": false,
      "join_rule": "restricted",
      "name": "The ~~First~~ Second Space",
      "num_joined_members": 42,
      "room_id": "!second_room:example.org",
      "room_type": "m.space",
      "topic": "Hello world",
      "world_readable": true
    }
  ],
  "inaccessible_children": [
    "!secret:example.org"
  ],
  "room": {
    "allowed_room_ids": [],
    "avatar_url": "mxc://example.org/abcdef",
    "canonical_alias": "#general:example.org",
    "children_state": [
      {
        "content": {
          "via": [
            "remote.example.org"
          ]
        },
        "origin_server_ts": 1629413349153,
        "sender": "@alice:example.org",
        "state_key": "!a:example.org",
        "type": "m.space.child"
      }
    ],
    "guest_can_join": false,
    "join_rule": "public",
    "name": "The First Space",
    "num_joined_members": 42,
    "room_id": "!space:example.org",
    "room_type": "m.space",
    "topic": "No other spaces were created first, ever",
    "world_readable": true
  }
}

404 response

Error
Name Type Description
errcode string

Required: An error code.

error string

A human-readable error message.

{
  "errcode": "M_NOT_FOUND",
  "error": "Room does not exist."
}

正在输入通知

当服务器用户发正在输入通知时,需将该通知同步到房间内其他服务器,令其用户获得同样状态。接收服务器应确保用户确已在房间,且为发送方服务器的用户。

m.typing


A typing notification EDU for a user in a room.

m.typing
Name Type Description
content Typing Notification

Required: The typing notification.

edu_type string

Required: The string m.typing

One of: [m.typing].

Typing Notification
Name Type Description
room_id string

Required: The room where the user’s typing status has been updated.

typing boolean

Required: Whether the user is typing in the room or not.

user_id string

Required: The user ID that has had their typing status changed.

Examples

{
  "content": {
    "room_id": "!somewhere:matrix.org",
    "typing": true,
    "user_id": "@john:matrix.org"
  },
  "edu_type": "m.typing"
}

在线状态(Presence)

服务器 API 的在线状态完全基于下述 EDU 交换。不涉及 PDU 或联邦查询。

服务器应仅为对方感兴趣的用户发送在线状态更新,例如对方正与本地用户共处一房间。

m.presence


An EDU representing presence updates for users of the sending homeserver.

m.presence
Name Type Description
content Presence Update

Required: The presence updates and requests.

edu_type string

Required: The string m.presence

One of: [m.presence].

Presence Update
Name Type Description
push [User Presence Update]

Required: A list of presence updates that the receiving server is likely to be interested in.

User Presence Update
Name Type Description
currently_active boolean

True if the user is likely to be interacting with their client. This may be indicated by the user having a last_active_ago within the last few minutes. Defaults to false.

last_active_ago integer

Required: The number of milliseconds that have elapsed since the user last did something.

presence string

Required: The presence of the user.

One of: [offline, unavailable, online].

status_msg string

An optional description to accompany the presence.

user_id string

Required: The user ID this presence EDU is for.

Examples

{
  "content": {
    "push": [
      {
        "currently_active": true,
        "last_active_ago": 5000,
        "presence": "online",
        "status_msg": "Making cupcakes",
        "user_id": "@john:matrix.org"
      }
    ]
  },
  "edu_type": "m.presence"
}

回执

回执为 EDU,用于指示对某事件的操作“标记”。目前仅支持“已读回执“(read receipt,表示用户已读到事件处)。

本用户自己发的事件不必发送读回执,因发事件即视为已读。

m.receipt


An EDU representing receipt updates for users of the sending homeserver. When receiving receipts, the server should only update entries that are listed in the EDU. Receipts previously received that do not appear in the EDU should not be removed or otherwise manipulated.

m.receipt
Name Type Description
content {Room ID: Room Receipts}

Required: Receipts for a particular room. The string key is the room ID for which the receipts under it belong.

edu_type string

Required: The string m.receipt

One of: [m.receipt].

Room Receipts
Name Type Description
m.read {User ID: User Read Receipt}

Required: Read receipts for users in the room. The string key is the user ID the receipt belongs to.

User Read Receipt
Name Type Description
data Read Receipt Metadata

Required: Metadata for the read receipt.

event_ids [string]

Required: The extremity event IDs that the user has read up to.

Read Receipt Metadata
Name Type Description
thread_id string

The root thread event’s ID (or main) for which thread this receipt is intended to be under. If not specified, the read receipt is unthreaded (default).

Added in v1.4

ts integer

Required: A POSIX timestamp in milliseconds for when the user read the event specified in the read receipt.

Examples

{
  "content": {
    "!some_room:example.org": {
      "m.read": {
        "@john:matrix.org": {
          "data": {
            "ts": 1533358089009
          },
          "event_ids": [
            "$read_this_event:matrix.org"
          ]
        }
      }
    }
  },
  "edu_type": "m.receipt"
}

信息查询

查询是指向家服务器检索资源(如用户或房间)的信息。常与客户端向客户端-服务器 API 发起请求配合实现。

可进行多种查询。下文先是通用查询端点,后跟具体类型。

GET /_matrix/federation/v1/query/directory


Performs a query to get the mapped room ID and list of resident homeservers in the room for a given room alias. Homeservers should only query room aliases that belong to the target server (identified by the server name in the alias).

Servers may wish to cache the response to this query to avoid requesting the information too often.

Rate-limited: No
Requires authentication: Yes

Request

Request parameters

query parameters
Name Type Description
room_alias string

Required: The room alias to query.


Responses

Status Description
200 The corresponding room ID and list of known resident homeservers for the room.
404 The room alias was not found.

200 response

Name Type Description
room_id string

Required: The room ID mapped to the queried room alias.

servers [string]

Required: An array of server names that are likely to hold the given room. This list may or may not include the server answering the query.

{
  "room_id": "!roomid1234:example.org",
  "servers": [
    "example.org",
    "example.com",
    "another.example.com:8449"
  ]
}

404 response

Error
Name Type Description
errcode string

Required: An error code.

error string

A human-readable error message.

{
  "errcode": "M_NOT_FOUND",
  "error": "Room alias not found."
}

GET /_matrix/federation/v1/query/profile


Performs a query to get profile information, such as a display name or avatar, for a given user. Homeservers should only query profiles for users that belong to the target server (identified by the server name in the user ID).

Servers may wish to cache the response to this query to avoid requesting the information too often.

Servers MAY deny profile look-up over federation by responding with 403 and an error code of M_FORBIDDEN.

Rate-limited: No
Requires authentication: Yes

Request

Request parameters

query parameters
Name Type Description
field string

The field to query. If specified, the server will only return the given field in the response. If not specified, the server will return the full profile for the user.

One of: [displayname, avatar_url].

user_id string

Required: The user ID to query. Must be a user local to the receiving homeserver.


Responses

Status Description
200

The profile for the user. If a field is specified in the request, only the matching field should be included in the response. If no field was specified, the response should include the fields of the user’s profile that can be made public, such as the display name and avatar.

If the user does not have a particular field set on their profile, the server should exclude it from the response body or give it the value null.

403 The server is unwilling to disclose whether the user exists and/or has profile information.
404 The user does not exist or does not have a profile.

200 response

Name Type Description
avatar_url string

The avatar URL for the user’s avatar. May be omitted if the user does not have an avatar set.

displayname string

The display name of the user. May be omitted if the user does not have a display name set.

{
  "avatar_url": "mxc://matrix.org/MyC00lAvatar",
  "displayname": "John Doe"
}

403 response

Error
Name Type Description
errcode string

Required: An error code.

error string

A human-readable error message.

{
  "errcode": "M_FORBIDDEN",
  "error": "Profile lookup over federation is disabled on this homeserver"
}

404 response

Error
Name Type Description
errcode string

Required: An error code.

error string

A human-readable error message.

{
  "errcode": "M_NOT_FOUND",
  "error": "User does not exist."
}

GET /_matrix/federation/v1/query/{queryType}


Performs a single query request on the receiving homeserver. The query string arguments are dependent on which type of query is being made. Known query types are specified as their own endpoints as an extension to this definition.

Rate-limited: No
Requires authentication: Yes

Request

Request parameters

path parameters
Name Type Description
queryType string

Required: The type of query to make


Responses

Status Description
200 The query response. The schema varies depending on the query being made.

OpenID

第三方服务可用由 客户端-服务器 API 预生成的访问令牌交换获取用户信息。“OpenID” 可用于验证用户身份而无需授予账户全部访问权限。

由 OpenID API 生成的访问令牌仅对 OpenID API 有效,在其他用途无效。

GET /_matrix/federation/v1/openid/userinfo


Exchanges an OpenID access token for information about the user who generated the token. Currently this only exposes the Matrix User ID of the owner.

Rate-limited: No
Requires authentication: No

Request

Request parameters

query parameters
Name Type Description
access_token string

Required: The OpenID access token to get information about the owner for.


Responses

Status Description
200 Information about the user who generated the OpenID access token.
401 The token was not recognized or has expired.

200 response

Name Type Description
sub string

Required: The Matrix User ID who generated the token.

{
  "sub": "@alice:example.com"
}

401 response

Error
Name Type Description
errcode string

Required: An error code.

error string

A human-readable error message.

{
  "errcode": "M_UNKNOWN_TOKEN",
  "error": "Access token unknown or expired"
}

设备管理

用户设备详情需高效公开并及时更新,以保证端到端加密可靠,让用户知晓房间内涉及的设备;同时设备间消息需要筛选并分发。下述内容补充 客户端-服务器 API 设备管理模块

Matrix 目前采用自定义的发布/订阅机制同步用户设备列表(联邦同步)。服务器首次获取远端用户设备列表时,通过 /user/keys/query 接口结果填本地缓存。后续通过 m.device_list_update EDU 增量更新。每次新 EDU 针对给定用户的一台设备(含唯一 stream_id),并在 prev_id 字段指向增量更新参考。为便于多实例并发,prev_id 可包含所有当前尚未被引用的 key,若依次发送一条记录,prev_id 仅有一个。

这样形成了 m.device_list_update EDU 的有向无环图,指明更新某用户设备列表前必须已接收哪些 EDU。若引用了本地未知的 prev_id,服务器需重新调用 /user/keys/query API 后继续处理。响应返回 stream_id,供后续同步使用。

GET /_matrix/federation/v1/user/devices/{userId}


Gets information on all of the user’s devices

Rate-limited: No
Requires authentication: Yes

Request

Request parameters

path parameters
Name Type Description
userId string

Required: The user ID to retrieve devices for. Must be a user local to the receiving homeserver.


Responses

Status Description
200 The user’s devices.

200 response

Name Type Description
devices [User Device]

Required: The user’s devices. May be empty.

master_key CrossSigningKey

The user's master cross-signing key.

self_signing_key CrossSigningKey

The user's self-signing key.

stream_id integer

Required: A unique ID for a given user_id which describes the version of the returned device list. This is matched with the stream_id field in m.device_list_update EDUs in order to incrementally update the returned device_list.

user_id string

Required: The user ID devices were requested for.

User Device
Name Type Description
device_display_name string

Optional display name for the device.

device_id string

Required: The device ID.

keys DeviceKeys

Required: Identity keys for the device.

DeviceKeys
Name Type Description
algorithms [string]

Required: The encryption algorithms supported by this device.

device_id string

Required: The ID of the device these keys belong to. Must match the device ID used when logging in.

keys {string: string}

Required: Public identity keys. The names of the properties should be in the format <algorithm>:<device_id>. The keys themselves should be encoded as specified by the key algorithm.

signatures {User ID: {string: string}}

Required: Signatures for the device key object. A map from user ID, to a map from <algorithm>:<device_id> to the signature.

The signature is calculated using the process described at Signing JSON.

user_id string

Required: The ID of the user the device belongs to. Must match the user ID used when logging in.

CrossSigningKey
Name Type Description
keys {string: string}

Required: The public key. The object must have exactly one property, whose name is in the form <algorithm>:<unpadded_base64_public_key>, and whose value is the unpadded base64 public key.

signatures Signatures

Signatures of the key, calculated using the process described at Signing JSON. Optional for the master key. Other keys must be signed by the user's master key.

usage [string]

Required: What the key is used for.

user_id string

Required: The ID of the user the key belongs to.

{
  "devices": [
    {
      "device_display_name": "Alice's Mobile Phone",
      "device_id": "JLAFKJWSCS",
      "keys": {
        "algorithms": [
          "m.olm.v1.curve25519-aes-sha2",
          "m.megolm.v1.aes-sha2"
        ],
        "device_id": "JLAFKJWSCS",
        "keys": {
          "curve25519:JLAFKJWSCS": "3C5BFWi2Y8MaVvjM8M22DBmh24PmgR0nPvJOIArzgyI",
          "ed25519:JLAFKJWSCS": "lEuiRJBit0IG6nUf5pUzWTUEsRVVe/HJkoKuEww9ULI"
        },
        "signatures": {
          "@alice:example.com": {
            "ed25519:JLAFKJWSCS": "dSO80A01XiigH3uBiDVx/EjzaoycHcjq9lfQX0uWsqxl2giMIiSPR8a4d291W1ihKJL/a+myXS367WT6NAIcBA"
          }
        },
        "user_id": "@alice:example.com"
      }
    }
  ],
  "master_key": {
    "keys": {
      "ed25519:base64+master+public+key": "base64+master+public+key"
    },
    "usage": [
      "master"
    ],
    "user_id": "@alice:example.com"
  },
  "self_signing_key": {
    "keys": {
      "ed25519:base64+self+signing+public+key": "base64+self+signing+master+public+key"
    },
    "signatures": {
      "@alice:example.com": {
        "ed25519:base64+master+public+key": "signature+of+self+signing+key"
      }
    },
    "usage": [
      "self_signing"
    ],
    "user_id": "@alice:example.com"
  },
  "stream_id": 5,
  "user_id": "@alice:example.org"
}

m.device_list_update


Added in v1.1

An EDU that lets servers push details to each other when one of their users adds a new device to their account, required for E2E encryption to correctly target the current set of devices for a given user. This event will also be sent when an existing device gets a new cross-signing signature.

m.device_list_update
Name Type Description
content Device List Update

Required: The description of the device whose details has changed.

edu_type string

Required: The string m.device_list_update.

One of: [m.device_list_update].

Device List Update
Name Type Description
deleted boolean

True if the server is announcing that this device has been deleted.

device_display_name string

The public human-readable name of this device. Will be absent if the device has no name.

device_id string

Required: The ID of the device whose details are changing.

keys DeviceKeys

The updated identity keys (if any) for this device. May be absent if the device has no E2E keys defined.

prev_id [integer]

The stream_ids of any prior m.device_list_update EDUs sent for this user which have not been referred to already in an EDU’s prev_id field. If the receiving server does not recognise any of the prev_ids, it means an EDU has been lost and the server should query a snapshot of the device list via /user/keys/query in order to correctly interpret future m.device_list_update EDUs. May be missing or empty for the first EDU in a sequence.

stream_id integer

Required: An ID sent by the server for this update, unique for a given user_id. Used to identify any gaps in the sequence of m.device_list_update EDUs broadcast by a server.

user_id string

Required: The user ID who owns this device.

DeviceKeys
Name Type Description
algorithms [string]

Required: The encryption algorithms supported by this device.

device_id string

Required: The ID of the device these keys belong to. Must match the device ID used when logging in.

keys {string: string}

Required: Public identity keys. The names of the properties should be in the format <algorithm>:<device_id>. The keys themselves should be encoded as specified by the key algorithm.

signatures {User ID: {string: string}}

Required: Signatures for the device key object. A map from user ID, to a map from <algorithm>:<device_id> to the signature.

The signature is calculated using the process described at Signing JSON.

user_id string

Required: The ID of the user the device belongs to. Must match the user ID used when logging in.

Examples

{
  "content": {
    "device_display_name": "Mobile",
    "device_id": "QBUAZIFURK",
    "keys": {
      "algorithms": [
        "m.olm.v1.curve25519-aes-sha2",
        "m.megolm.v1.aes-sha2"
      ],
      "device_id": "JLAFKJWSCS",
      "keys": {
        "curve25519:JLAFKJWSCS": "3C5BFWi2Y8MaVvjM8M22DBmh24PmgR0nPvJOIArzgyI",
        "ed25519:JLAFKJWSCS": "lEuiRJBit0IG6nUf5pUzWTUEsRVVe/HJkoKuEww9ULI"
      },
      "signatures": {
        "@alice:example.com": {
          "ed25519:JLAFKJWSCS": "dSO80A01XiigH3uBiDVx/EjzaoycHcjq9lfQX0uWsqxl2giMIiSPR8a4d291W1ihKJL/a+myXS367WT6NAIcBA"
        }
      },
      "user_id": "@alice:example.com"
    },
    "prev_id": [
      5
    ],
    "stream_id": 6,
    "user_id": "@john:example.com"
  },
  "edu_type": "m.device_list_update"
}

端到端加密

本节补充 客户端-服务器 API 端到端加密模块。详细加密流程可见该模块。

此处 API 主要用于代客户端通过联邦转发请求,并原样转发响应。

POST /_matrix/federation/v1/user/keys/claim


Claims one-time keys for use in pre-key messages.

The request contains the user ID, device ID and algorithm name of the keys that are required. If a key matching these requirements can be found, the response contains it. The returned key is a one-time key if one is available, and otherwise a fallback key.

One-time keys are given out in the order that they were uploaded via /keys/upload. (All keys uploaded within a given call to /keys/upload are considered equivalent in this regard; no ordering is specified within them.)

Servers must ensure that each one-time key is returned at most once, so when a key has been returned, no other request will ever return the same key.

Rate-limited: No
Requires authentication: Yes

Request

Request body

Name Type Description
one_time_keys {User ID: {string: string}}

Required: The keys to be claimed. A map from user ID, to a map from device ID to algorithm name. Requested users must be local to the receiving homeserver.

Request body example

{
  "one_time_keys": {
    "@alice:example.com": {
      "JLAFKJWSCS": "signed_curve25519"
    }
  }
}

Responses

Status Description
200 The claimed keys.

200 response

Name Type Description
one_time_keys {User ID: {string: {string: string|KeyObject}}}

Required: One-time keys for the queried devices. A map from user ID, to a map from devices to a map from <algorithm>:<key_id> to the key object.

See the Client-Server Key Algorithms section for more information on the Key Object format.

KeyObject
Name Type Description
key string

Required: The key, encoded using unpadded base64.

signatures {string: {string: string}}

Required: Signature of the key object.

The signature is calculated using the process described at Signing JSON.

{
  "one_time_keys": {
    "@alice:example.com": {
      "JLAFKJWSCS": {
        "signed_curve25519:AAAAHg": {
          "key": "zKbLg+NrIjpnagy+pIY6uPL4ZwEG2v+8F9lmgsnlZzs",
          "signatures": {
            "@alice:example.com": {
              "ed25519:JLAFKJWSCS": "FLWxXqGbwrb8SM3Y795eB6OA8bwBcoMZFXBqnTn58AYWZSqiD45tlBVcDa2L7RwdKXebW/VzDlnfVJ+9jok1Bw"
            }
          }
        }
      }
    }
  }
}

POST /_matrix/federation/v1/user/keys/query


Returns the current devices and identity keys for the given users.

Rate-limited: No
Requires authentication: Yes

Request

Request body

Name Type Description
device_keys {User ID: [string]}

Required: The keys to be downloaded. A map from user ID, to a list of device IDs, or to an empty list to indicate all devices for the corresponding user. Requested users must be local to the receiving homeserver.

Request body example

{
  "device_keys": {
    "@alice:example.com": []
  }
}

Responses

Status Description
200 The device information.

200 response

Name Type Description
device_keys {User ID: {string: DeviceKeys}}

Required: Information on the queried devices. A map from user ID, to a map from device ID to device information. For each device, the information returned will be the same as uploaded via /keys/upload, with the addition of an unsigned property.

master_keys {User ID: CrossSigningKey}

Information on the master cross-signing keys of the queried users. A map from user ID, to master key information. For each key, the information returned will be the same as uploaded via /keys/device_signing/upload, along with the signatures uploaded via /keys/signatures/upload that the user is allowed to see.

Added in v1.1

self_signing_keys {User ID: CrossSigningKey}

Information on the self-signing keys of the queried users. A map from user ID, to self-signing key information. For each key, the information returned will be the same as uploaded via /keys/device_signing/upload.

Added in v1.1

DeviceKeys
Name Type Description
algorithms [string]

Required: The encryption algorithms supported by this device.

device_id string

Required: The ID of the device these keys belong to. Must match the device ID used when logging in.

keys {string: string}

Required: Public identity keys. The names of the properties should be in the format <algorithm>:<device_id>. The keys themselves should be encoded as specified by the key algorithm.

signatures {User ID: {string: string}}

Required: Signatures for the device key object. A map from user ID, to a map from <algorithm>:<device_id> to the signature.

The signature is calculated using the process described at Signing JSON.

unsigned UnsignedDeviceInfo

Additional data added to the device key information by intermediate servers, and not covered by the signatures.

user_id string

Required: The ID of the user the device belongs to. Must match the user ID used when logging in.

UnsignedDeviceInfo
Name Type Description
device_display_name string

The display name which the user set on the device.

CrossSigningKey
Name Type Description
keys {string: string}

Required: The public key. The object must have exactly one property, whose name is in the form <algorithm>:<unpadded_base64_public_key>, and whose value is the unpadded base64 public key.

signatures Signatures

Signatures of the key, calculated using the process described at Signing JSON. Optional for the master key. Other keys must be signed by the user's master key.

usage [string]

Required: What the key is used for.

user_id string

Required: The ID of the user the key belongs to.

{
  "device_keys": {
    "@alice:example.com": {
      "JLAFKJWSCS": {
        "algorithms": [
          "m.olm.v1.curve25519-aes-sha2",
          "m.megolm.v1.aes-sha2"
        ],
        "device_id": "JLAFKJWSCS",
        "keys": {
          "curve25519:JLAFKJWSCS": "3C5BFWi2Y8MaVvjM8M22DBmh24PmgR0nPvJOIArzgyI",
          "ed25519:JLAFKJWSCS": "lEuiRJBit0IG6nUf5pUzWTUEsRVVe/HJkoKuEww9ULI"
        },
        "signatures": {
          "@alice:example.com": {
            "ed25519:JLAFKJWSCS": "dSO80A01XiigH3uBiDVx/EjzaoycHcjq9lfQX0uWsqxl2giMIiSPR8a4d291W1ihKJL/a+myXS367WT6NAIcBA"
          }
        },
        "unsigned": {
          "device_display_name": "Alice's mobile phone"
        },
        "user_id": "@alice:example.com"
      }
    }
  }
}

m.signing_key_update


Added in v1.1

An EDU that lets servers push details to each other when one of their users updates their cross-signing keys.

m.signing_key_update
Name Type Description
content Signing Key Update

Required: The updated signing keys.

edu_type string

Required: The string m.signing_update.

One of: [m.signing_key_update].

Signing Key Update
Name Type Description
master_key CrossSigningKey

Cross signing key

self_signing_key CrossSigningKey

Cross signing key

user_id string

Required: The user ID whose cross-signing keys have changed.

CrossSigningKey
Name Type Description
keys {string: string}

Required: The public key. The object must have exactly one property, whose name is in the form <algorithm>:<unpadded_base64_public_key>, and whose value is the unpadded base64 public key.

signatures Signatures

Signatures of the key, calculated using the process described at Signing JSON. Optional for the master key. Other keys must be signed by the user's master key.

usage [string]

Required: What the key is used for.

user_id string

Required: The ID of the user the key belongs to.

Examples

{
  "content": {
    "master_key": {
      "keys": {
        "ed25519:base64+master+public+key": "base64+master+public+key"
      },
      "usage": [
        "master"
      ],
      "user_id": "@alice:example.com"
    },
    "self_signing_key": {
      "keys": {
        "ed25519:base64+self+signing+public+key": "base64+self+signing+master+public+key"
      },
      "signatures": {
        "@alice:example.com": {
          "ed25519:base64+master+public+key": "signature+of+self+signing+key"
        }
      },
      "usage": [
        "self_signing"
      ],
      "user_id": "@alice:example.com"
    },
    "user_id": "@alice:example.com"
  },
  "edu_type": "m.signing_key_update"
}

发送到设备消息

发送到设备的消息通过 m.direct_to_device EDU 实现,不涉及 PDU 或联邦查询。

每条“发给设备”消息须以以下 EDU 发送到目标服务器:

m.direct_to_device


An EDU that lets servers push send events directly to a specific device on a remote server - for instance, to maintain an Olm E2E encrypted message channel between a local and remote device.

m.direct_to_device
Name Type Description
content To Device Message

Required: The description of the direct-to-device message.

edu_type string

Required: The string m.direct_to_device.

One of: [m.direct_to_device].

To Device Message
Name Type Description
message_id string

Required: Unique ID for the message, used for idempotence. Arbitrary utf8 string, of maximum length 32 codepoints.

messages {User ID: {string: Device Message Contents}}

Required: The contents of the messages to be sent. These are arranged in a map of user IDs to a map of device IDs to message bodies. The device ID may also be *, meaning all known devices for the user.

sender string

Required: User ID of the sender.

type string

Required: Event type for the message.

Examples

{
  "content": {
    "message_id": "hiezohf6Hoo7kaev",
    "messages": {
      "@alice:example.org": {
        "IWHQUZUIAH": {
          "algorithm": "m.megolm.v1.aes-sha2",
          "room_id": "!Cuyf34gef24t:localhost",
          "session_id": "X3lUlvLELLYxeTx4yOVu6UDpasGEVO0Jbu+QFnm0cKQ",
          "session_key": "AgAAAADxKHa9uFxcXzwYoNueL5Xqi69IkD4sni8LlfJL7qNBEY..."
        }
      }
    },
    "sender": "@john:example.com",
    "type": "m.room_key_request"
  },
  "edu_type": "m.direct_to_device"
}

内容仓库

事件附件(图片、文件等)通过 客户端-服务器 API 的内容仓库 上传至家服务器。当服务器需获取远端服务器存储的媒体数据时,需从远端下载。

服务器必须基于 Matrix 内容 URI 的服务地址(格式 mxc://{ServerName}/{MediaID}),始终应从 {ServerName} 服务器下载,利用下述端点。

[Changed in v1.11] 之前推荐使用 /client-server-api/#content-repository 内描述的 /_matrix/media/* 端点,如今这些端点已废弃,新端点需认证。服务器(而非用户)无法提供所需访问令牌。因此服务器应优先尝试新端点,遇到 404 M_UNRECOGNIZED 时再尝试废弃端点,并确保设置 allow_remotefalse

GET /_matrix/federation/v1/media/download/{mediaId}


Added in v1.11

Rate-limited: Yes
Requires authentication: Yes

Request

Request parameters

path parameters
Name Type Description
mediaId string

Required: The media ID from the mxc:// URI (the path component).

query parameters
Name Type Description
timeout_ms integer

The maximum number of milliseconds that the client is willing to wait to start receiving data, in the case that the content has not yet been uploaded. The default value is 20000 (20 seconds). The content repository SHOULD impose a maximum value for this parameter. The content repository MAY respond before the timeout.

Added in v1.7


Responses

Status Description
200 The content that was previously uploaded.
429 This request was rate-limited.
502 The content is too large for the server to serve.
504 The content is not yet available. A standard error response will be returned with the errcode M_NOT_YET_UPLOADED.

200 response

Headers
Name Type Description
Content-Type string

Must be multipart/mixed.

Content-Type Description
multipart/mixed

Required. MUST contain a boundary (per RFC 2046) delineating exactly two parts:

The first part has a Content-Type header of application/json and describes the media’s metadata, if any. Currently, this will always be an empty object.

The second part is either:

  1. the bytes of the media itself, using Content-Type and Content-Disposition headers as appropriate;

  2. or a Location header to redirect the caller to where the media can be retrieved. The URL at Location SHOULD have appropriate Content-Type and Content-Disposition headers which describe the media.

    When Location is present, servers SHOULD NOT cache the URL. The remote server may have applied time limits on its validity. If the caller requires an up-to-date URL, it SHOULD re-request the media download.

429 response

RateLimitError
Name Type Description
errcode string

Required: The M_LIMIT_EXCEEDED error code

error string

A human-readable error message.

retry_after_ms integer

The amount of time in milliseconds the client should wait before trying the request again.

{
  "errcode": "M_LIMIT_EXCEEDED",
  "error": "Too many requests",
  "retry_after_ms": 2000
}

502 response

Error
Name Type Description
errcode string

Required: An error code.

error string

A human-readable error message.

{
  "errcode": "M_TOO_LARGE",
  "error": "Content is too large to serve"
}

504 response

Error
Name Type Description
errcode string

Required: An error code.

error string

A human-readable error message.

{
  "errcode": "M_NOT_YET_UPLOADED",
  "error": "Content has not yet been uploaded"
}

GET /_matrix/federation/v1/media/thumbnail/{mediaId}


Added in v1.11

Download a thumbnail of content from the content repository. See the Client-Server API Thumbnails section for more information.

Rate-limited: Yes
Requires authentication: Yes

Request

Request parameters

path parameters
Name Type Description
mediaId string

Required: The media ID from the mxc:// URI (the path component).

query parameters
Name Type Description
animated boolean

Indicates preference for an animated thumbnail from the server, if possible. Animated thumbnails typically use the content types image/gif, image/png (with APNG format), image/apng, and image/webp instead of the common static image/png or image/jpeg content types.

When true, the server SHOULD return an animated thumbnail if possible and supported. When false, the server MUST NOT return an animated thumbnail. For example, returning a static image/png or image/jpeg thumbnail. When not provided, the server SHOULD NOT return an animated thumbnail.

Servers SHOULD prefer to return image/webp thumbnails when supporting animation.

When true and the media cannot be animated, such as in the case of a JPEG or PDF, the server SHOULD behave as though animated is false.

Added in v1.11

height integer

Required: The desired height of the thumbnail. The actual thumbnail may be larger than the size specified.

method string

The desired resizing method. See the Client-Server API Thumbnails section for more information.

One of: [crop, scale].

timeout_ms integer

The maximum number of milliseconds that the client is willing to wait to start receiving data, in the case that the content has not yet been uploaded. The default value is 20000 (20 seconds). The content repository SHOULD impose a maximum value for this parameter. The content repository MAY respond before the timeout.

Added in v1.7

width integer

Required: The desired width of the thumbnail. The actual thumbnail may be larger than the size specified.


Responses

Status Description
200 A thumbnail of the requested content.
400 The request does not make sense to the server, or the server cannot thumbnail the content. For example, the caller requested non-integer dimensions or asked for negatively-sized images.
413 The local content is too large for the server to thumbnail.
429 This request was rate-limited.
502 The remote content is too large for the server to thumbnail.
504 The content is not yet available. A standard error response will be returned with the errcode M_NOT_YET_UPLOADED.

200 response

Headers
Name Type Description
Content-Type string

Must be multipart/mixed.

Content-Type Description
multipart/mixed

Required. MUST contain a boundary (per RFC 2046) delineating exactly two parts:

The first part has a Content-Type header of application/json and describes the media’s metadata, if any. Currently, this will always be an empty object.

The second part is either:

  1. the bytes of the media itself, using Content-Type and Content-Disposition headers as appropriate;

  2. or a Location header to redirect the caller to where the media can be retrieved. The URL at Location SHOULD have appropriate Content-Type and Content-Disposition headers which describe the media.

    When Location is present, servers SHOULD NOT cache the URL. The remote server may have applied time limits on its validity. If the caller requires an up-to-date URL, it SHOULD re-request the media download.

The Content-Type for the second part SHOULD be one of:

  • image/png (possibly of the APNG variety)
  • image/apng
  • image/jpeg
  • image/gif
  • image/webp

400 response

Error
Name Type Description
errcode string

Required: An error code.

error string

A human-readable error message.

{
  "errcode": "M_UNKNOWN",
  "error": "Cannot generate thumbnails for the requested content"
}

413 response

Error
Name Type Description
errcode string

Required: An error code.

error string

A human-readable error message.

{
  "errcode": "M_TOO_LARGE",
  "error": "Content is too large to thumbnail"
}

429 response

RateLimitError
Name Type Description
errcode string

Required: The M_LIMIT_EXCEEDED error code

error string

A human-readable error message.

retry_after_ms integer

The amount of time in milliseconds the client should wait before trying the request again.

{
  "errcode": "M_LIMIT_EXCEEDED",
  "error": "Too many requests",
  "retry_after_ms": 2000
}

502 response

Error
Name Type Description
errcode string

Required: An error code.

error string

A human-readable error message.

{
  "errcode": "M_TOO_LARGE",
  "error": "Content is too large to thumbnail"
}

504 response

Error
Name Type Description
errcode string

Required: An error code.

error string

A human-readable error message.

{
  "errcode": "M_NOT_YET_UPLOADED",
  "error": "Content has not yet been uploaded"
}

服务器访问控制列表(ACL)

服务器 ACL 及其用途详见 客户端-服务器 API 的服务器 ACL 部分

远端服务器发起请求时,必须验证其是否有权限访问指定房间。被拒绝的服务器必须以 403 HTTP 状态码及 errcode: M_FORBIDDEN 响应。

以下端点前缀必须受保护:

  • /_matrix/federation/v1/make_join
  • /_matrix/federation/v1/make_leave
  • /_matrix/federation/v1/send_join
  • /_matrix/federation/v2/send_join
  • /_matrix/federation/v1/send_leave
  • /_matrix/federation/v2/send_leave
  • /_matrix/federation/v1/invite
  • /_matrix/federation/v2/invite
  • /_matrix/federation/v1/make_knock
  • /_matrix/federation/v1/send_knock
  • /_matrix/federation/v1/state
  • /_matrix/federation/v1/state_ids
  • /_matrix/federation/v1/backfill
  • /_matrix/federation/v1/event_auth
  • /_matrix/federation/v1/get_missing_events

此外,/_matrix/federation/v1/send/{txnId} 端点必须按以下规则保护:

  • 对所有 PDU 逐个应用 ACL,若发送服务器被拒绝访问 room_id 房间,则应忽略该 PDU,并在各自事件 ID 对应响应项中注明错误。

  • 所有房间相关的 EDU 也须应用 ACL:

事件签名

事件签名过程受事件被裁剪(redact)带来的复杂性影响。

为出站事件添加哈希和签名

签名前,需先计算事件的内容哈希(content hash),使用 Unpadded Base64 编码,放入事件 hashes.sha256 字段。

随后,执行裁剪(redaction)算法(见 裁剪规则),再用 JSON 签名 算法及服务器签名密钥签名,生成的签名再拷贝回原事件对象。

签名事件范例见 房间版本规范

校验接收事件的哈希和签名

服务器收到联邦事件后,应立即校验哈希及签名。

首查签名,先裁剪事件,然后按 校验签名流程 检查签名(可接受完整或已裁剪事件)。

期望签名包括:

  • sender 服务器(如为第三方邀请则例外。否则 sender 要与第三方邀请吻合,而实际发事件或为不同服务器)。
  • 若为房间版本 1/2,还包括事件 ID 创建方服务器。其他房间版本事件 ID 不在联邦传递,因此无需额外签名。

签名正确后,计算期望的内容哈希。hashes 字段的内容解码后与期望值比对。

如哈希校验失败,表明只收到裁剪后事件,故直接用裁剪结果。

计算事件引用哈希(Reference Hash)

引用哈希(reference hash)覆盖事件重要字段,包括内容哈希。部分房间版本用于事件标识符,具体见房间版本规范。计算过程如下:

  1. 事件经过裁剪算法处理。
  2. 移除 signaturesunsigned 字段。
  3. 转为 规范化 JSON
  4. 计算 sha256 哈希。

计算事件内容哈希(Content Hash)

内容哈希 覆盖原始未裁剪的完整事件。计算步骤:

  1. 移除已有的 unsignedsignatureshashes 字段。
  2. 规范化 JSON 编码后做 SHA-256 哈希。

示例代码

def hash_and_sign_event(event_object, signing_key, signing_name):
    # 首先计算事件内容哈希
    content_hash = compute_content_hash(event_object)
    event_object["hashes"] = {"sha256": encode_unpadded_base64(content_hash)}

    # 裁剪事件,移除非必要字段
    stripped_object = strip_non_essential_keys(event_object)

    # 对裁剪后的 JSON 做签名(只签关键字段和哈希)
    signed_object = sign_json(stripped_object, signing_key, signing_name)

    # 把签名从裁剪后事件拷贝回原事件
    event_object["signatures"] = signed_object["signatures"]

def compute_content_hash(event_object):
    # 复制事件对象
    event_object = dict(event_object)

    # "unsigned" 字段可由他服务器更改,需排除
    event_object.pop("unsigned", None)

    # 签名相关依赖当下 "hashes",因此须排除
    event_object.pop("signatures", None)
    event_object.pop("hashes", None)

    # 编码为规范化 JSON 取得一致字节输出
    event_json_bytes = encode_canonical_json(event_object)

    return hashlib.sha256(event_json_bytes)

安全注意事项

当域名所有权变更,接手人可冒充前任所有者接收消息(类似邮件)并请求其他服务器转发历史。未来,如 MSC1228 方案将解决此类问题。