Merge branch 'main' into as-meta-schema

This commit is contained in:
Kai A. Hiller 2025-08-08 17:19:44 +02:00
commit 7506e9ab89
91 changed files with 2920 additions and 917 deletions

View file

@ -2,6 +2,7 @@ name: "Spec"
env:
HUGO_VERSION: 0.139.0
PYTHON_VERSION: 3.13
on:
push:
@ -40,7 +41,7 @@ jobs:
- name: " Setup Python"
uses: actions/setup-python@v5
with:
python-version: '3.9'
python-version: ${{ env.PYTHON_VERSION }}
cache: 'pip'
cache-dependency-path: scripts/requirements.txt
- name: " Install dependencies"
@ -59,7 +60,7 @@ jobs:
- name: " Setup Python"
uses: actions/setup-python@v5
with:
python-version: '3.9'
python-version: ${{ env.PYTHON_VERSION }}
cache: 'pip'
cache-dependency-path: scripts/requirements.txt
- name: " Install dependencies"
@ -78,7 +79,7 @@ jobs:
- name: " Setup Python"
uses: actions/setup-python@v5
with:
python-version: '3.9'
python-version: ${{ env.PYTHON_VERSION }}
cache: 'pip'
cache-dependency-path: scripts/requirements.txt
- name: " Install dependencies"
@ -120,7 +121,7 @@ jobs:
- name: " Setup Python"
uses: actions/setup-python@v5
with:
python-version: '3.9'
python-version: ${{ env.PYTHON_VERSION }}
cache: 'pip'
cache-dependency-path: scripts/requirements.txt
- name: " Install dependencies"
@ -154,6 +155,11 @@ jobs:
--api server-server \
-r "$RELEASE" \
-o spec/server-server-api/api.json
scripts/dump-openapi.py \
--base-url "https://spec.matrix.org${{ needs.calculate-baseurl.outputs.baseURL }}" \
--api identity \
-r "$RELEASE" \
-o spec/identity-service-api/api.json
tar -czf openapi.tar.gz spec
- name: "📤 Artifact upload"
uses: actions/upload-artifact@v4
@ -172,7 +178,7 @@ jobs:
- name: " Setup Python"
uses: actions/setup-python@v5
with:
python-version: '3.9'
python-version: ${{ env.PYTHON_VERSION }}
- name: " Install towncrier"
run: "pip install 'towncrier'"
- name: "Generate changelog"
@ -283,10 +289,11 @@ jobs:
npm i
npm run get-proposals
- name: "⚙️ hugo"
env:
HUGO_PARAMS_VERSION_STATUS: "historical"
# Create a baseURL like `/v1.2` out of the `v1.2` tag
run: |
echo -e '[params.version]\nstatus="historical"' > historical.toml
hugo --config config.toml,historical.toml --baseURL "/${GITHUB_REF/refs\/tags\//}" -d "spec"
hugo --baseURL "/${GITHUB_REF/refs\/tags\//}" -d "spec"
- name: "📥 Spec definition download"
uses: actions/download-artifact@v4

View file

@ -316,13 +316,19 @@ Custom SCSS for the Matrix spec
h2 {
font-weight: $font-weight-bold;
font-size: 1.3rem;
margin: 3rem 0 .5rem 0;
margin: 1.5rem 0 1rem 0;
}
h3 {
font-weight: $font-weight-bold;
font-size: 1.1rem;
margin: 1.5rem 0 .75rem 0;
margin: 1.5rem 0 1rem 0;
}
/* Reduce top margin of h3 if previous sibling is a h2 */
h2 + h3 {
margin-top: 1rem;
}
hr {
@ -367,11 +373,6 @@ Custom SCSS for the Matrix spec
}
}
// add some space between two tables when they are right next to each other
& + table {
margin-top: 4rem;
}
caption {
caption-side: top;
color: $dark;
@ -443,6 +444,17 @@ Custom SCSS for the Matrix spec
}
}
/* Have consistent spacing around tables and examples */
table, .highlight {
margin-top: 0;
margin-bottom: 2rem;
/* We don't need the margin on the last child of the .rendered-data block */
&:last-child {
margin-bottom: 0;
}
}
pre {
border: 0;
border-left: solid 5px $secondary;

View file

@ -0,0 +1 @@
Minor fixes to JSON schemas.

View file

@ -0,0 +1 @@
Clarify that `format` is required if `formatted_body` is specified.

View file

@ -0,0 +1 @@
The `latest_event` in an aggregated set of thread events uses the same format as the event itself.

View file

@ -0,0 +1 @@
Add `format` query parameter to `GET /state/{eventType}/{stateKey}` to allow fetching metadata of a specific state event.

View file

@ -0,0 +1 @@
Fix various typos throughout the specification.

View file

@ -0,0 +1 @@
Minor fixes to JSON schemas.

View file

@ -0,0 +1 @@
Add the `use_state_after` query parameter and `state_after` response property to `GET /sync`, as per [MSC4222](https://github.com/matrix-org/matrix-spec-proposals/issues/4222).

View file

@ -1 +0,0 @@
Add [well-known funding manifest urls](https://floss.fund/funding-manifest/) to spec to authorise https://matrix.org/funding.json. Contributed by @HarHarLinks.

View file

@ -0,0 +1 @@
Add "placeholder MSC" process definition.

View file

@ -0,0 +1 @@
GitHub actions are now building the OpenAPI `spec/identity-service-api/api.json` file.

View file

@ -0,0 +1 @@
Specify a correct spelling for "display name".

View file

@ -0,0 +1 @@
Clarify that clients should replace events with the most recent replacement by origin_server_ts.

View file

@ -23,15 +23,15 @@ description = "Home of the Matrix specification for decentralised communication"
[menus]
[[menus.main]]
name = 'Foundation'
url = 'https://matrix.org/foundation/'
url = 'https://matrix.org/foundation/about/'
weight = 10
[[menus.main]]
name = 'FAQs'
url = 'https://matrix.org/faq'
name = 'User Docs'
url = 'https://matrix.org/docs/'
weight = 20
[[menus.main]]
name = 'Blog'
url = 'https://matrix.org/blog/posts'
url = 'https://matrix.org/blog/'
weight = 30
[markup]
@ -67,7 +67,7 @@ current_version_url = "https://spec.matrix.org/latest"
# The following is used when status = "stable", and is displayed in various UI elements on a released version
# of the spec.
# major = "1"
# minor = "14"
# minor = "15"
# User interface configuration
[params.ui]

View file

@ -492,10 +492,10 @@ via the query string). It is expected that the application service use
the transactions pushed to it to handle events rather than syncing with
the user implied by `sender_localpart`.
#### Application service room directories
#### Published room directories
Application services can maintain their own room directories for their
defined third-party protocols. These room directories may be accessed by
Application services can maintain their own published room directories for
their defined third-party protocols. These directories may be accessed by
clients through additional parameters on the `/publicRooms`
client-server endpoint.

View file

@ -0,0 +1,97 @@
---
title: v1.15 Changelog
linkTitle: v1.15
type: docs
layout: changelog
outputs:
- html
- checklist
date: 2025-06-26
---
## Client-Server API
**New Endpoints**
- Add `GET /_matrix/client/v1/room_summary/{roomIdOrAlias}`, as per [MSC3266](https://github.com/matrix-org/matrix-spec-proposals/pull/3266). ([#2125](https://github.com/matrix-org/matrix-spec/issues/2125))
- Add `GET /_matrix/client/v1/auth_metadata`, as per [MSC2965](https://github.com/matrix-org/matrix-spec-proposals/pull/2965). ([#2147](https://github.com/matrix-org/matrix-spec/issues/2147))
**Backwards Compatible Changes**
- Add `m.topic` content block to enable rich text in `m.room.topic` events as per [MSC3765](https://github.com/matrix-org/matrix-spec-proposals/pull/3765). ([#2095](https://github.com/matrix-org/matrix-spec/issues/2095))
- Include device keys with Olm-encrypted events as per [MSC4147](https://github.com/matrix-org/matrix-spec-proposals/pull/4147). ([#2122](https://github.com/matrix-org/matrix-spec/issues/2122))
- Add `/_matrix/client/v1/room_summary/{roomIdOrAlias}` and extend `/_matrix/client/v1/rooms/{roomId}/hierarchy` with the new optional properties `allowed_room_ids`, `encryption` and `room_version` as per [MSC3266](https://github.com/matrix-org/matrix-spec-proposals/pull/3266). ([#2125](https://github.com/matrix-org/matrix-spec/issues/2125), [#2158](https://github.com/matrix-org/matrix-spec/issues/2158))
- Add the OAuth 2.0 based authentication API, as per [MSC3861](https://github.com/matrix-org/matrix-spec-proposals/pull/3861) and its sub-proposals. ([#2141](https://github.com/matrix-org/matrix-spec/issues/2141), [#2148](https://github.com/matrix-org/matrix-spec/issues/2148), [#2149](https://github.com/matrix-org/matrix-spec/issues/2149), [#2150](https://github.com/matrix-org/matrix-spec/issues/2150), [#2151](https://github.com/matrix-org/matrix-spec/issues/2151), [#2159](https://github.com/matrix-org/matrix-spec/issues/2159), [#2164](https://github.com/matrix-org/matrix-spec/issues/2164))
**Spec Clarifications**
- Clarify behaviour when the `topic` key of a `m.room.topic` event is absent, null, or empty. ([#2068](https://github.com/matrix-org/matrix-spec/issues/2068))
- Fix the example of the `GET /sync` endpoint and the `m.room.member` example used in several places. ([#2077](https://github.com/matrix-org/matrix-spec/issues/2077))
- Clarify the format of third-party invites, including the fact that identity server public keys can be encoded using standard or URL-safe base64. ([#2083](https://github.com/matrix-org/matrix-spec/issues/2083))
- "Public" rooms in profile look-ups are defined through their join rule and history visibility. ([#2101](https://github.com/matrix-org/matrix-spec/issues/2101))
- "Public" rooms in user directory queries are defined through their join rule and history visibility. ([#2102](https://github.com/matrix-org/matrix-spec/issues/2102))
- Rooms published in `/publicRooms` don't necessarily have `public` join rules or `world_readable` history visibility. ([#2104](https://github.com/matrix-org/matrix-spec/issues/2104))
- "Public" rooms with respect to call invites are defined through their join rule. ([#2106](https://github.com/matrix-org/matrix-spec/issues/2106))
- "Public" rooms have no specific meaning with respect to moderation policy lists. ([#2107](https://github.com/matrix-org/matrix-spec/issues/2107))
- "Public" rooms with respect to presence are defined through their join rule. ([#2108](https://github.com/matrix-org/matrix-spec/issues/2108))
- Spaces are subject to the same access mechanisms as rooms. ([#2109](https://github.com/matrix-org/matrix-spec/issues/2109))
- Fix various typos throughout the specification. ([#2121](https://github.com/matrix-org/matrix-spec/issues/2121), [#2144](https://github.com/matrix-org/matrix-spec/issues/2144))
- Clarify that Well-Known URIs are available on the server name's hostname. Contributed by @HarHarLinks. ([#2140](https://github.com/matrix-org/matrix-spec/issues/2140))
- Add missing fields in example for `ExportedSessionData`. ([#2154](https://github.com/matrix-org/matrix-spec/issues/2154))
## Server-Server API
**Backwards Compatible Changes**
- Add `m.topic` content block to enable rich text in `m.room.topic` events as per [MSC3765](https://github.com/matrix-org/matrix-spec-proposals/pull/3765). ([#2095](https://github.com/matrix-org/matrix-spec/issues/2095))
- Extend `/_matrix/federation/v1/hierarchy/{roomId}` with the new optional properties `encryption` and `room_version` as per [MSC3266](https://github.com/matrix-org/matrix-spec-proposals/pull/3266). ([#2125](https://github.com/matrix-org/matrix-spec/issues/2125))
**Spec Clarifications**
- Add a note to the invite endpoints that invites to local users may be received twice over federation if the homeserver is already in the room. ([#2067](https://github.com/matrix-org/matrix-spec/issues/2067))
- Clarify the format of third-party invites, including the fact that identity server public keys can be encoded using standard or URL-safe base64. ([#2083](https://github.com/matrix-org/matrix-spec/issues/2083))
- Clarify that auth event of `content.join_authorised_via_users_server` is only necessary for `m.room.member` with a `membership` of `join`. ([#2100](https://github.com/matrix-org/matrix-spec/issues/2100))
- Rooms published in `/publicRooms` don't necessarily have `public` join rules or `world_readable` history visibility. ([#2104](https://github.com/matrix-org/matrix-spec/issues/2104))
- Fix various typos throughout the specification. ([#2128](https://github.com/matrix-org/matrix-spec/issues/2128))
- Clarify that Well-Known URIs are available on the server name's hostname. Contributed by @HarHarLinks. ([#2140](https://github.com/matrix-org/matrix-spec/issues/2140))
## Application Service API
**Spec Clarifications**
- Clarify in the application service registration schema the `url: null` behaviour. ([#2130](https://github.com/matrix-org/matrix-spec/issues/2130))
## Identity Service API
**Spec Clarifications**
- Clarify that public keys can be encoded using standard or URL-safe base64. ([#2083](https://github.com/matrix-org/matrix-spec/issues/2083))
## Push Gateway API
No significant changes.
## Room Versions
No significant changes.
## Appendices
No significant changes.
## Internal Changes/Tooling
**Spec Clarifications**
- Adjust margins in rendered endpoints. ([#2081](https://github.com/matrix-org/matrix-spec/issues/2081))
- Replace Hugo shortcodes in OpenAPI output. ([#2088](https://github.com/matrix-org/matrix-spec/issues/2088))
- Add [well-known funding manifest urls](https://floss.fund/funding-manifest/) to spec to authorise https://matrix.org/funding.json. Contributed by @HarHarLinks. ([#2115](https://github.com/matrix-org/matrix-spec/issues/2115))
- Fix the historical info box when generating the historical spec in CI. ([#2123](https://github.com/matrix-org/matrix-spec/issues/2123))
- Update the header navigation menu with links to modern matrix.org. Contributed by @HarHarLinks. ([#2137](https://github.com/matrix-org/matrix-spec/issues/2137))

File diff suppressed because it is too large Load diff

View file

@ -528,7 +528,7 @@ messages, Alice only sends one request event (an event with type
`m.room.message` with `msgtype: m.key.verification.request`, rather than an
event with type `m.key.verification.request`), to the room. In addition, Alice
does not send an `m.key.verification.cancel` event to tell Bob's other devices
that the request as already been accepted; instead, when Bob's other devices
that the request has already been accepted; instead, when Bob's other devices
see his `m.key.verification.ready` event, they will know that the request has
already been accepted, and that they should ignore the request.
@ -1124,7 +1124,7 @@ The process between Alice and Bob verifying each other would be:
framework as described above.
3. Alice's client displays a QR code that Bob is able to scan if Bob's client
indicated the ability to scan, an option to scan Bob's QR code if her client
is able to scan. Bob's client prompts displays a QR code that Alice can
is able to scan. Bob's client displays a QR code that Alice can
scan if Alice's client indicated the ability to scan, and an option to scan
Alice's QR code if his client is able to scan. The format for the QR code
is described below. Other options, like starting SAS Emoji verification,
@ -1512,40 +1512,11 @@ message.
The plaintext payload is of the form:
```json
{
"type": "<type of the plaintext event>",
"content": "<content for the plaintext event>",
"sender": "<sender_user_id>",
"recipient": "<recipient_user_id>",
"recipient_keys": {
"ed25519": "<our_ed25519_key>"
},
"keys": {
"ed25519": "<sender_ed25519_key>"
}
}
```
{{% definition path="api/client-server/definitions/olm_payload" %}}
The type and content of the plaintext message event are given in the
payload.
Other properties are included in order to prevent an attacker from
publishing someone else's curve25519 keys as their own and subsequently
claiming to have sent messages which they didn't. `sender` must
correspond to the user who sent the event, `recipient` to the local
user, and `recipient_keys` to the local ed25519 key.
Clients must confirm that the `sender_key` property in the cleartext
`m.room.encrypted` event body, and the `keys.ed25519` property in the
decrypted plaintext, match the keys returned by
[`/keys/query`](#post_matrixclientv3keysquery) for
the given user. Clients must also verify the signature of the keys from the
`/keys/query` response. Without this check, a client cannot be sure that
the sender device owns the private part of the ed25519 key it claims to
have in the Olm payload. This is crucial when the ed25519 key corresponds
to a verified device.
If a client has multiple sessions established with another device, it
should use the session from which it last received and successfully
decrypted a message. For these purposes, a session that has not received
@ -1555,6 +1526,68 @@ maximum number of olm sessions that it will maintain for each device,
and expiring sessions on a Least Recently Used basis. The maximum number
of olm sessions maintained per device should be at least 4.
###### Validation of incoming decrypted events
{{% changed-in v="1.15" %}} Existing checks made more explicit, and checks for `sender_device_keys` added.
After decrypting an incoming encrypted event, clients MUST apply the
following checks:
1. The `sender` property in the decrypted content must match the
`sender` of the event.
2. The `keys.ed25519` property in the decrypted content must match
the `sender_key` property in the cleartext `m.room.encrypted`
event body.
3. The `recipient` property in the decrypted content must match
the user ID of the local user.
4. The `recipient_keys.ed25519` property in the decrypted content
must match the client device's [Ed25519 signing key](#device-keys).
5. Where `sender_device_keys` is present in the decrypted content:
1. `sender_device_keys.user_id` must also match the `sender`
of the event.
2. `sender_device_keys.keys.ed25519:<device_id>` must also match
the `sender_key` property in the cleartext `m.room.encrypted`
event body.
3. `sender_device_keys.keys.curve25519:<device_id>` must match
the Curve25519 key used to establish the Olm session.
4. The `sender_device_keys` structure must have a valid signature
from the key with ID `ed25519:<device_id>` (i.e., the sending
device's Ed25519 key).
Any event that does not comply with these checks MUST be discarded.
###### Verification of the sending user for incoming events
{{% added-in v="1.15" %}}
In addition, for each Olm session, clients MUST verify that the
Curve25519 key used to establish the Olm session does indeed belong
to the claimed `sender`. This requires a signed "device keys" structure
for that Curve25519 key, which can be obtained in one of two ways:
1. An Olm message may be received with a `sender_device_keys` property
in the decrypted content.
2. The keys are returned via a [`/keys/query`](#post_matrixclientv3keysquery)
request. Note that both the Curve25519 key **and** the Ed25519 key in
the returned device keys structure must match those used in an
Olm-encrypted event as above. (In particular, the Ed25519 key must
be present in the **encrypted** content of an Olm-encrypted event
to prevent an attacker from claiming another user's Curve25519 key
as their own.)
Ownership of the Curve25519 key is then established in one of two ways:
1. Via [cross-signing](#cross-signing). For this to be sufficient, the
device keys structure must be signed by the sender's self-signing key,
and that self-signing key must itself have been validated (either via
[explicit verification](#device-verification) or a "trust on first use" (TOFU) mechanism).
2. Via explicit verification of the device's Ed25519 signing key, as
contained in the device keys structure. This is no longer recommended.
A failure to complete these verifications does not necessarily mean that
the session is bogus; however it is the case that there is no proof that
the claimed sender is accurate, and the user should be warned accordingly.
###### Recovering from undecryptable messages
Occasionally messages may be undecryptable by clients due to a variety

View file

@ -195,7 +195,7 @@ given event (for example, if an event is edited multiple times). These should
be [aggregated](#aggregations-of-child-events) by the homeserver.
The aggregation format of `m.replace` relationships gives the **most recent**
replacement event, formatted [as normal](#room-event-format).
valid replacement event, formatted [as normal](#room-event-format).
The most recent event is determined by comparing `origin_server_ts`; if two or
more replacement events have identical `origin_server_ts`, the event with the
@ -268,6 +268,11 @@ Client authors are reminded to take note of the requirements for [Validity of
replacement events](#validity-of-replacement-events), and to ignore any
invalid replacement events that are received.
Clients should render the content of the **most recent** valid replacement event. The
most recent event is determined by comparing `origin_server_ts`; if two or more
replacement events have identical `origin_server_ts`, the event with the
lexicographically largest `event_id` is treated as more recent.
##### Permalinks
When creating [links](/appendices/#uris) to events (also known as permalinks),
@ -364,7 +369,7 @@ property under `m.new_content`.
A particular constraint applies to events which replace a [reply](#rich-replies):
in contrast to the original reply, there should be no `m.in_reply_to` property
in the the `m.relates_to` object, since it would be redundant (see
in the `m.relates_to` object, since it would be redundant (see
[Applying `m.new_content`](#applying-mnew_content) above, which notes that the
original event's `m.relates_to` is preserved), as well as being contrary to the
spirit of the event relationships mechanism which expects only one "parent" per

View file

@ -18,8 +18,9 @@ the entity making the decisions on filtering is best positioned to
interpret the rules how it sees fit.
Moderation policy lists are stored as room state events. There are no
restrictions on how the rooms can be configured (they could be public,
private, encrypted, etc).
restrictions on how the rooms can be configured in terms of
[join rules](#mroomjoin_rules), [history visibility](#room-history-visibility),
encryption, etc.
There are currently 3 kinds of entities which can be affected by rules:
`user`, `server`, and `room`. All 3 are described with

View file

@ -68,5 +68,7 @@ will cause the server to automatically set their presence to `online`.
#### Security considerations
Presence information is shared with all users who share a room with the
target user. In large public rooms this could be undesirable.
Presence information is published to all users who share a room with the
target user. If the target user is a member of a room with a `public`
[join rule](#mroomjoin_rules), any other user in the federation is
able to gain access to the target user's presence. This could be undesirable.

View file

@ -26,9 +26,10 @@ on certain keys of certain event types.
The supported keys to search over are:
- `content.body` in `m.room.message`
- `content.name` in `m.room.name`
- `content.topic` in `m.room.topic`
- `content.body` in [`m.room.message`](/client-server-api/#mroommessage)
- `content.name` in [`m.room.name`](/client-server-api/#mroomname)
- In [`m.room.topic`](/client-server-api/#mroomtopic), `content.topic`
as well as the `body` of the `text/plain` representation in `content['m.topic']`.
The search will *not* include rooms that are end to end encrypted.

View file

@ -2,8 +2,8 @@
{{% added-in v="1.2" %}}
Often used to group rooms of similar subject matter (such as a public "Official
matrix.org rooms" space or personal "Work stuff" space), spaces are a way to
Often used to group rooms of similar subject matter (such as an "Official
matrix.org rooms" space or a "Work stuff" space), spaces are a way to
organise rooms while being represented as rooms themselves.
A space is defined by the [`m.space` room type](#types), making it known as a
@ -18,11 +18,11 @@ In the default power level structure, this would be `100`. Clients might wish to
go a step further and explicitly ignore notification counts on space-rooms.
Membership of a space is defined and controlled by the existing mechanisms which
govern a room: [`m.room.member`](#mroommember), [`m.room.history_visibility`](#mroomhistory_visibility),
and [`m.room.join_rules`](#mroomjoin_rules). Public spaces are encouraged to have
a similar setup to public rooms: `world_readable` history visibility, published
canonical alias, and suitably public `join_rule`. Invites, including third-party
invites, still work just as they do in normal rooms as well.
govern a room: [`m.room.member`](/client-server-api#mroommember), [`m.room.history_visibility`](/client-server-api#mroomhistory_visibility),
and [`m.room.join_rules`](/client-server-api#mroomjoin_rules). Canonical aliases and invites, including
third-party invites, still work just as they do in normal rooms as well. Furthermore,
spaces can also be published in the [room directory](/client-server-api#published-room-directory) to make them
discoverable.
All other aspects of regular rooms are additionally carried over, such as the
ability to set arbitrary state events, hold room account data, etc. Spaces are
@ -87,10 +87,9 @@ the state of `#space:example.org` would consist of:
}
```
No state events in the child rooms themselves would be required (though they
can also be present). This allows for users
to define personal/private spaces to organise their own rooms without needing explicit
permission from the room moderators/admins.
No state events in the child rooms themselves would be required (though they can also
be present). This allows for users to define spaces without needing explicit permission
from the room moderators/admins.
Child rooms can be removed from a space by omitting the `via` key of `content` on the
relevant state event, such as through redaction or otherwise clearing the `content`.

View file

@ -6,9 +6,10 @@ allow users to log into applications via a single web-based
authentication portal. Examples include OpenID Connect, "Central
Authentication Service" (CAS) and SAML.
This module allows a Matrix homeserver to delegate user authentication
to an external authentication server supporting one of these protocols.
In this process, there are three systems involved:
This module allows a Matrix homeserver that supports the [legacy authentication
API](#legacy-api) to delegate user authentication to an external authentication
server supporting one of these protocols. In this process, there are three
systems involved:
- A Matrix client, using the APIs defined in this specification, which
is seeking to authenticate a user to a Matrix homeserver.
@ -24,7 +25,7 @@ used to communicate with the authentication server. Different Matrix
homeserver implementations might support different SSO protocols.
Clients and homeservers implementing the SSO flow will need to consider
both [login](#login) and [user-interactive authentication](#user-interactive-authentication-api). The flow is
both [login](#legacy-login) and [user-interactive authentication](#user-interactive-authentication-api). The flow is
similar in both cases, but there are slight differences.
Typically, SSO systems require a single "callback" URI to be configured

View file

@ -5,8 +5,8 @@ This module adds in support for inviting new members to a room where
their Matrix user ID is not known, instead addressing them by a third-party
identifier such as an email address. There are two flows here; one
if a Matrix user ID is known for the third-party identifier, and one if
not. Either way, the client calls [`/invite`](#post_matrixclientv3roomsroomidinvite) with the details of the
third-party identifier.
not. Either way, the client calls [`/invite`](#thirdparty_post_matrixclientv3roomsroomidinvite)
with the details of the third-party identifier.
The homeserver asks the identity server whether a Matrix user ID is
known for that identifier:
@ -37,10 +37,12 @@ A client asks a server to invite a user by their third-party identifier.
#### Server behaviour
Upon receipt of an [`/invite`](#post_matrixclientv3roomsroomidinvite), the server is expected to look up the
third-party identifier with the provided identity server. If the lookup
yields a result for a Matrix User ID then the normal invite process can
be initiated. This process ends up looking like this:
Upon receipt of an [`/invite`](#thirdparty_post_matrixclientv3roomsroomidinvite),
the server is expected to look up the third-party identifier with the provided
identity server by making a call to [`/_matrix/identity/v2/lookup`](/identity-service-api/#post_matrixidentityv2lookup).
If the lookup yields a result for a Matrix User ID then the normal [invite
process](/server-server-api/#inviting-to-a-room) can be initiated. This process
ends up looking like this:
```
+---------+ +-------------+ +-----------------+
@ -66,10 +68,11 @@ be initiated. This process ends up looking like this:
| | |
```
However, if the lookup does not yield a bound User ID, the homeserver
must store the invite on the identity server and emit a valid
`m.room.third_party_invite` event to the room. This process ends up
looking like this:
However, if the lookup does not yield a bound User ID, the homeserver must store
the invite on the identity server with a call to
[`/_matrix/identity/v2/store-invite`](/identity-service-api/#post_matrixidentityv2store-invite)
and emit a valid [`m.room.third_party_invite`](#mroomthird_party_invite) event
to the room. This process ends up looking like this:
```
+---------+ +-------------+ +-----------------+
@ -101,15 +104,18 @@ looking like this:
| | |
```
All homeservers MUST verify the signature in the event's
`content.third_party_invite.signed` object.
The third-party user will then need to verify their identity, which results in a
request to [`/_matrix/federation/v1/3pid/onbind`](/server-server-api/#put_matrixfederationv13pidonbind)
from the identity server to the homeserver that bound the third-party identifier
to a user. The homeserver then exchanges the `m.room.third_party_invite` event
in the room for a complete [`m.room.member`](#mroommember) event with
`content.membership: invite` and a `content.third_party_invite` property for the
user that has bound the third-party identifier. If the invitee is on a different
homeserver than the inviting user, the invitee's homeserver makes a request to
[`/_matrix/federation/v1/exchange_third_party_invite/{roomId}`](/server-server-api/#put_matrixfederationv1exchange_third_party_inviteroomid).
The third-party user will then need to verify their identity, which
results in a call from the identity server to the homeserver that bound
the third-party identifier to a user. The homeserver then exchanges the
`m.room.third_party_invite` event in the room for a complete
`m.room.member` event for `membership: invite` for the user that has
bound the third-party identifier.
All homeservers MUST verify the signature in the `m.room.member` event's
`content.third_party_invite.signed` object.
If a homeserver is joining a room for the first time because of an
`m.room.third_party_invite`, the server which is already participating
@ -193,8 +199,8 @@ at any time - the completion is not shown in the diagram.
H1 MUST verify the request from H3 to ensure the `signed` property is
correct as well as the `key_validity_url` as still being valid. This is
done by making a request to the [identity server
/isvalid](/identity-service-api/#get_matrixidentityv2pubkeyisvalid)
done by making a request to the identity server's
[`/pubkey/isvalid`](/identity-service-api/#get_matrixidentityv2pubkeyisvalid)
endpoint, using the provided URL rather than constructing a new one. The
query string and response for the provided URL must match the Identity
Service Specification.

View file

@ -185,7 +185,7 @@ included under the `m.relations` property in `unsigned` for the thread root. For
```
`latest_event` is the most recent event (topologically to the server) in the thread sent by an
un-[ignored user](#ignoring-users).
un-[ignored user](#ignoring-users). It should be serialized in the same form as the event itself.
Note that, as in the example above, child events of the `latest_event` should
themselves be aggregated and included under `m.relations` for that event. The

View file

@ -202,11 +202,13 @@ specific user, and should be set to the Matrix user ID of that user. Invites
without an `invitee` field are defined to be intended for any member of the
room other than the sender of the event.
Clients should consider an incoming call if they see a non-expired invite event where the `invitee` field is either
absent or equal to their user's Matrix ID, however they should evaluate whether or not to ring based on their
user's trust relationship with the callers and/or where the call was placed. As a starting point, it is
suggested that clients ignore call invites from users in public rooms. It is strongly recommended that
when clients do not ring for an incoming call invite, they still display the call invite in the room and
Clients should consider an incoming call if they see a non-expired invite event
where the `invitee` field is either absent or equal to their user's Matrix ID.
They should, however, evaluate whether or not to ring based on their user's trust
relationship with the callers and/or where the call was placed. As a starting
point, it is RECOMMENDED that clients ignore call invites in rooms with a
[join rule](#mroomjoin_rules) of `public`. When clients suppress ringing for an
incoming call invite, they SHOULD still display the call invite in the room and
annotate that it was ignored.
##### Glare

View file

@ -185,6 +185,10 @@ is as follows:
- Take care in creating your proposal. Specify your intended
changes, and give reasoning to back them up. Changes without
justification will likely be poorly received by the community.
- At the time of creating your draft you will not yet know the PR number, so you
should use a placeholder number to name your file and edit that
after PR submission. The suggested steps are described in
detail [in the proposals guide](https://github.com/matrix-org/matrix-spec-proposals#1-writing-the-proposal).
- Fork and make a PR to the
[matrix-spec-proposals](https://github.com/matrix-org/matrix-spec-proposals) repository.
The ID of your PR will become the MSC ID for the lifetime of your
@ -493,6 +497,42 @@ In summary:
a small table at the bottom mapping the various values from stable
to unstable.
### Placeholder MSCs
Some proposals may contain security-sensitive or private context which can't be
publicly disclosed until a later stage in the idea or solution process. Typically,
the initial idea is validated using some amount of implementation or experimentation
and may require an MSC number to make that implementation easier.
Placeholder MSCs are used to represent proposals in a state where implementation
is ongoing, but the MSC details can't yet be disclosed. Authors which feel as
though their MSC could be highly sensitive MUST get in contact with the Spec Core
Team or [Security Team](https://matrix.org/security-disclosure-policy/) prior to
opening their MSC. If either team determines that a placeholder MSC is required,
it may be opened as such.
There are a few expectations attached to placeholder MSCs:
* They have a title which marks them WIP, and are in the "draft" state.
* They have the following labels: `[proposal-placeholder, action-required, needs-implementation]`.
* Notably, *not* `proposal`.
* They are relatively short-lived (ideally less than 6-12 months in placeholder).
* They propose solutions which are reasonably likely to be accepted. If a placeholder
needs to be closed because the idea won't work, isn't needed, etc, then the MSC's
content MUST be published ahead of that closure.
* Note: the MSC's publication (and therefore closure) may be delayed until an
appropriate point in the security disclosure cycle. For example, an alternative
MSC being published, or a stream of work being completed.
* When they are updated to receive real content, the following happens:
1. The Spec Core Team or the author leaves a comment to cause a notification
that the MSC has been replaced with real content.
2. The `proposal` label (or its equivalent) is added to trigger chat notifications
in the public Matrix rooms. The `proposal-placeholder` and `action-required`
labels should be removed at this stage as well. Other labels are removed/applied
per normal process.
* The Spec Core Team is aware of the intended MSC's title and purpose. This is
especially important if the Security Team approved the use of a placeholder MSC.
## Proposal Tracking
This is a living document generated from the list of proposals on the

View file

@ -119,7 +119,8 @@ to send. The process overall is as follows:
server must present a valid certificate for the hostname.
3. If the hostname is not an IP literal, a regular HTTPS request is
made to `https://<hostname>/.well-known/matrix/server`, expecting
made to `https://<hostname>/.well-known/matrix/server` (according to
[RFC 8615](https://datatracker.ietf.org/doc/html/rfc8615)), expecting
the schema defined later in this section. 30x redirects should be
followed, however redirection loops should be avoided. Responses
(successful or otherwise) to the `/.well-known` endpoint should be
@ -543,8 +544,8 @@ the following subset of the room state:
`third_party_invite` property, the current
`m.room.third_party_invite` event with `state_key` matching
`content.third_party_invite.signed.token`, if any.
- If `content.join_authorised_via_users_server` is present,
and the [room version supports restricted rooms](/rooms/#feature-matrix),
- If `membership` is `join`, `content.join_authorised_via_users_server`
is present, and the [room version supports restricted rooms](/rooms/#feature-matrix),
then the `m.room.member` event with `state_key` matching
`content.join_authorised_via_users_server`.
@ -970,9 +971,8 @@ the event to other servers in the room.
## Third-party invites
{{% boxes/note %}}
More information about third-party invites is available in the
[Client-Server API](/client-server-api) under
the Third-party Invites module.
More information about third-party invites is available in the Client-Server API
under the [Third-party invites](/client-server-api/#third-party-invites) module.
{{% /boxes/note %}}
When a user wants to invite another user in a room but doesn't know the
@ -985,38 +985,41 @@ API](/identity-service-api).
### Cases where an association exists for a third-party identifier
If the third-party identifier is already bound to a Matrix ID, a lookup
request on the identity server will return it. The invite is then
processed by the inviting homeserver as a standard `m.room.member`
invite event. This is the simplest case.
If the third-party identifier is already bound to a Matrix ID, a [lookup
request](/identity-service-api/#post_matrixidentityv2lookup) on the identity
server will return it. The invite is then processed by the inviting homeserver
as a [standard `m.room.member` invite event](#inviting-to-a-room). This is the
simplest case.
### Cases where an association doesn't exist for a third-party identifier
If the third-party identifier isn't bound to any Matrix ID, the inviting
homeserver will request the identity server to store an invite for this
identifier and to deliver it to whoever binds it to its Matrix ID. It
will also send an `m.room.third_party_invite` event in the room to
specify a display name, a token and public keys the identity server
provided as a response to the invite storage request.
homeserver will request the identity server to [store an invite](/identity-service-api/#invitation-storage)
for this identifier and to deliver it to whoever binds it to its Matrix ID. It
will also send an [`m.room.third_party_invite`](/client-server-api/#mroomthird_party_invite)
event in the room to specify a display name, a token and public keys the
identity server provided as a response to the invite storage request.
When a third-party identifier with pending invites gets bound to a
Matrix ID, the identity server will send a POST request to the ID's
homeserver as described in the [Invitation
Storage](/identity-service-api#invitation-storage)
section of the Identity Service API.
When a third-party identifier with pending invites gets bound to a Matrix ID,
the identity server will send a request to the [`/3pid/onbind`](#put_matrixfederationv13pidonbind)
endpoint of the the ID's homeserver as described in the [Invitation
Storage](/identity-service-api#invitation-storage) section of the Identity
Service API.
The following process applies for each invite sent by the identity
server:
The invited homeserver will create an `m.room.member` invite event
containing a special `third_party_invite` section containing the token
and a signed object, both provided by the identity server.
The invited homeserver will create an [`m.room.member`](/client-server-api/#mroommember)
invite event containing a special `third_party_invite` section containing the
token and a `signed` object, both provided by the identity server.
If the invited homeserver is in the room the invite came from, it can
auth the event and send it.
However, if the invited homeserver isn't in the room the invite came
from, it will need to request the room's homeserver to auth the event.
from, it will need to request the inviting homeserver to auth the event
at the [`/exchange_third_party_invite`](#put_matrixfederationv1exchange_third_party_inviteroomid)
endpoint.
{{% http-api spec="server-server" api="third_party_invite" %}}
@ -1045,11 +1048,10 @@ user's Matrix ID and the token delivered when the invite was stored,
this verification will prove that the `m.room.member` invite event comes
from the user owning the invited third-party identifier.
## Public Room Directory
## Published Room Directory
To complement the [Client-Server
API](/client-server-api)'s room directory,
homeservers need a way to query the public rooms for another server.
To complement the [room directory in the Client-Server API](/client-server-api#published-room-directory),
homeservers need a way to query the published rooms of another server.
This can be done by making a request to the `/publicRooms` endpoint for
the server the room directory should be retrieved for.

View file

@ -23,3 +23,4 @@ allOf:
type: array
items:
$ref: protocol_instance.yaml
required: ['instances']

View file

@ -77,4 +77,4 @@ properties:
"placeholder": "#foobar"
}
}
required: ['user_fields', 'location_fields', 'icon', 'field_types', 'instances']
required: ['user_fields', 'location_fields', 'icon', 'field_types']

View file

@ -20,7 +20,7 @@ properties:
type: string
description: A unique, user-defined ID of the application service which will never change.
url:
type: string
type: ["null", "string"]
description: The URL for the application service. May include a path after the domain name. Optionally set to null if no traffic is required.
as_token:
type: string

View file

@ -0,0 +1,141 @@
# Copyright 2016 OpenMarket Ltd
# Copyright 2022 The Matrix.org Foundation C.I.C.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
openapi: 3.1.0
info:
title: Matrix Client-Server Account Deactivation API
version: 1.0.0
paths:
/account/deactivate:
post:
summary: Deactivate a user's account.
description: |-
Deactivate the user's account, removing all ability for the user to
login again.
This API endpoint uses the [User-Interactive Authentication API](/client-server-api/#user-interactive-authentication-api).
An access token should be submitted to this endpoint if the client has
an active session.
The homeserver may change the flows available depending on whether a
valid access token is provided.
Unlike other endpoints, this endpoint does not take an `id_access_token`
parameter because the homeserver is expected to sign the request to the
identity server instead.
security:
- {}
- accessTokenQuery: []
- accessTokenBearer: []
operationId: deactivateAccount
requestBody:
content:
application/json:
schema:
type: object
properties:
auth:
description: Additional authentication information for the user-interactive
authentication API.
allOf:
- $ref: definitions/auth_data.yaml
id_server:
type: string
description: |-
The identity server to unbind all of the user's 3PIDs from.
If not provided, the homeserver MUST use the `id_server`
that was originally use to bind each identifier. If the
homeserver does not know which `id_server` that was,
it must return an `id_server_unbind_result` of
`no-support`.
example: example.org
erase:
x-addedInMatrixVersion: "1.10"
type: boolean
description: |-
Whether the user would like their content to be erased as
much as possible from the server.
Erasure means that any users (or servers) which join the
room after the erasure request are served redacted copies of
the events sent by this account. Users which had visibility
on those events prior to the erasure are still able to see
unredacted copies. No redactions are sent and the erasure
request is not shared over federation, so other servers
might still serve unredacted copies.
The server should additionally erase any non-event data
associated with the user, such as [account data](/client-server-api/#client-config)
and [contact 3PIDs](/client-server-api/#adding-account-administrative-contact-information).
Defaults to `false` if not present.
required: true
responses:
"200":
description: The account has been deactivated.
content:
application/json:
schema:
type: object
properties:
id_server_unbind_result:
type: string
enum:
- success
- no-support
description: |-
An indicator as to whether or not the homeserver was able to unbind
the user's 3PIDs from the identity server(s). `success` indicates
that all identifiers have been unbound from the identity server while
`no-support` indicates that one or more identifiers failed to unbind
due to the identity server refusing the request or the homeserver
being unable to determine an identity server to unbind from. This
must be `success` if the homeserver has no identifiers to unbind
for the user.
example: success
required:
- id_server_unbind_result
"401":
description: The homeserver requires additional authentication information.
content:
application/json:
schema:
$ref: definitions/auth_response.yaml
"429":
description: This request was rate-limited.
content:
application/json:
schema:
$ref: definitions/errors/rate_limited.yaml
tags:
- Account management
servers:
- url: "{protocol}://{hostname}{basePath}"
variables:
protocol:
enum:
- http
- https
default: https
hostname:
default: localhost:8008
basePath:
default: /_matrix/client/v3
components:
securitySchemes:
accessTokenQuery:
$ref: definitions/security.yaml#/accessTokenQuery
accessTokenBearer:
$ref: definitions/security.yaml#/accessTokenBearer

View file

@ -201,6 +201,11 @@ paths:
Homeservers should prevent the caller from adding a 3PID to their account if it has
already been added to another user's account on the homeserver.
{{% boxes/warning %}}
Since this endpoint uses User-Interactive Authentication, it cannot be used when the access token was obtained
via the [OAuth 2.0 API](/client-server-api/#oauth-20-api).
{{% /boxes/warning %}}
operationId: add3PID
security:
- accessTokenQuery: []

View file

@ -13,18 +13,21 @@
# limitations under the License.
openapi: 3.1.0
info:
title: Matrix Client-Server Application Service Room Directory API
title: Matrix Client-Server Application Service Published Room Directory API
version: 1.0.0
paths:
"/directory/list/appservice/{networkId}/{roomId}":
put:
summary: Updates a room's visibility in the application service's room directory.
description: |-
Updates the visibility of a given room on the application service's room
summary: |-
Updates a room's visibility in the application service's published room
directory.
description: |-
Updates the visibility of a given room in the application service's
published room directory.
This API is similar to the room directory visibility API used by clients
to update the homeserver's more general room directory.
This API is similar to the
[visibility API](/client-server-api#put_matrixclientv3directorylistroomroomid)
used by clients to update the homeserver's more general published room directory.
This API requires the use of an application service access token (`as_token`)
instead of a typical client's access_token. This API cannot be invoked by

View file

@ -87,12 +87,9 @@ paths:
- public
- private
description: |-
A `public` visibility indicates that the room will be shown
in the published room list. A `private` visibility will hide
the room from the published room list. Rooms default to
`private` visibility if this key is not included. NB: This
should not be confused with `join_rules` which also uses the
word `public`.
The room's visibility in the server's
[published room directory](/client-server-api#published-room-directory).
Defaults to `private`.
room_alias_name:
type: string
description: |-
@ -109,15 +106,17 @@ paths:
name:
type: string
description: |-
If this is included, an `m.room.name` event will be sent
into the room to indicate the name of the room. See Room
Events for more information on `m.room.name`.
If this is included, an [`m.room.name`](/client-server-api/#mroomname) event
will be sent into the room to indicate the name for the room.
This overwrites any [`m.room.name`](/client-server-api/#mroomname)
event in `initial_state`.
topic:
type: string
description: |-
If this is included, an `m.room.topic` event will be sent
into the room to indicate the topic for the room. See Room
Events for more information on `m.room.topic`.
If this is included, an [`m.room.topic`](/client-server-api/#mroomtopic)
event with a `text/plain` mimetype will be sent into the room
to indicate the topic for the room. This overwrites any
[`m.room.topic`](/client-server-api/#mroomtopic) event in `initial_state`.
invite:
type: array
description: |-

View file

@ -26,7 +26,7 @@ paths:
Publishes cross-signing keys for the user.
This API endpoint uses the [User-Interactive Authentication API](/client-server-api/#user-interactive-authentication-api).
User-Interactive Authentication MUST be performed, except in these cases:
- there is no existing cross-signing master key uploaded to the homeserver, OR
- there is an existing cross-signing master key and it exactly matches the
@ -34,11 +34,16 @@ paths:
keys provided in the request (self-signing key, user-signing key) they MUST also
match the existing keys stored on the server. In other words, the request contains
no new keys.
This allows clients to freely upload one set of keys, but not modify/overwrite keys if
they already exist. Allowing clients to upload the same set of keys more than once
they already exist. Allowing clients to upload the same set of keys more than once
makes this endpoint idempotent in the case where the response is lost over the network,
which would otherwise cause a UIA challenge upon retry.
{{% boxes/warning %}}
When this endpoint requires User-Interactive Authentication, it cannot be used when the access token was obtained
via the [OAuth 2.0 API](/client-server-api/#oauth-20-api).
{{% /boxes/warning %}}
operationId: uploadCrossSigningKeys
security:
- accessTokenQuery: []

View file

@ -23,6 +23,7 @@ properties:
type: string
description: |-
The end-to-end message encryption algorithm that the key is for. Must be `m.megolm.v1.aes-sha2`.
example: "m.megolm.v1.aes-sha2"
forwarding_curve25519_key_chain:
type: array
items:
@ -30,31 +31,24 @@ properties:
description: |-
Chain of Curve25519 keys through which this session was forwarded, via [m.forwarded_room_key](/client-server-api/#mforwarded_room_key)
events.
example: [ "hPQNcabIABgGnx3/ACv/jmMmiQHoeFfuLB17tzWp6Hw" ]
sender_key:
type: string
description: |-
Unpadded base64-encoded device Curve25519 key.
example: "RF3s+E7RkTQTGF2d8Deol0FkQvgII2aJDf3/Jp5mxVU"
sender_claimed_keys:
type: object
additionalProperties:
type: string
description: |-
A map from algorithm name (`ed25519`) to the Ed25519 signing key of the sending device.
example: { "ed25519": "aj40p+aw64yPIdsxoog8jhPu9i7l7NcFRecuOQblE3Y" }
session_key:
type: string
description: |-
Unpadded base64-encoded session key in [session-export format](https://gitlab.matrix.org/matrix-org/olm/blob/master/docs/megolm.md#session-export-format).
example: {
"algorithm": "m.megolm.v1.aes-sha2",
"forwarding_curve25519_key_chain": [
"hPQNcabIABgGnx3/ACv/jmMmiQHoeFfuLB17tzWp6Hw"
],
"sender_key": "RF3s+E7RkTQTGF2d8Deol0FkQvgII2aJDf3/Jp5mxVU",
"sender_claimed_keys": {
"ed25519": "aj40p+aw64yPIdsxoog8jhPu9i7l7NcFRecuOQblE3Y",
},
"session_key": "AgAAAADxKHa9uFxcXzwYoNueL5Xqi69IkD4sni8Llf..."
}
example: "AgAAAADxKHa9uFxcXzwYoNueL5Xqi69IkD4sni8Llf..."
required:
- algorithm
- forwarding_curve25519_key_chain

View file

@ -0,0 +1,88 @@
# Copyright 2025 The Matrix.org Foundation C.I.C
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
type: object
title: OlmPayload
description: |-
The plaintext payload of Olm message events.
properties:
type:
type: string
description: The type of the event.
content:
type: object
description: The event content.
sender:
type: string
description: The user ID of the event sender.
recipient:
type: string
description: The user ID of the intended event recipient.
recipient_keys:
description: The recipient's signing keys of the encrypted event.
$ref: "#/components/schemas/SigningKeys"
keys:
$ref: "#/components/schemas/SigningKeys"
description: The sender's signing keys of the encrypted event.
sender_device_keys:
$ref: device_keys.yaml
description: The sender's device keys.
x-addedInMatrixVersion: "1.15"
required:
- type
- content
- sender
- recipient
- recipient_keys
- keys
components:
schemas:
SigningKeys:
type: object
title: SigningKeys
description: Public keys used for an `m.olm.v1.curve25519-aes-sha2` event.
properties:
ed25519:
type: string
description: The Ed25519 public key encoded using unpadded base64.
required:
- ed25519
example: {
"type": "<type of the plaintext event>",
"content": "<content for the plaintext event>",
"sender": "<sender_user_id>",
"recipient": "<recipient_user_id>",
"recipient_keys": {
"ed25519": "<our_ed25519_key>"
},
"keys": {
"ed25519": "<sender_ed25519_key>"
},
"sender_device_keys": {
"algorithms": ["<supported>", "<algorithms>"],
"user_id": "<user_id>",
"device_id": "<device_id>",
"keys": {
"ed25519:<device_id>": "<sender_ed25519_key>",
"curve25519:<device_id>": "<sender_curve25519_key>"
},
"signatures": {
"<user_id>": {
"ed25519:<device_id>": "<device_signature>",
"ed25519:<ssk_id>": "<ssk_signature>",
}
}
}
}

View file

@ -37,7 +37,8 @@ allOf:
A unique identifier for this instance on the homeserver. This field is added
to the response of [`GET /_matrix/app/v1/thirdparty/protocol/{protocol}`](/application-service-api/#get_matrixappv1thirdpartyprotocolprotocol)
by the homeserver.
This is the identifier to use as the `third_party_instance_id` in a request to
[`POST /_matrix/client/v3/publicRooms`](/client-server-api/#post_matrixclientv3publicrooms).
example: "irc-freenode"
required: ['instances']

View file

@ -13,10 +13,12 @@
# limitations under the License.
type: object
title: "PublicRoomsChunk"
title: "PublishedRoomsChunk"
properties:
canonical_alias:
type: string
format: mx-room-alias
pattern: "^#"
description: The canonical alias of the room, if any.
example: "#general:example.org"
name:
@ -29,11 +31,15 @@ properties:
example: 42
room_id:
type: string
format: mx-room-id
pattern: "^!"
description: The ID of the room.
example: "!abcdefg:example.org"
topic:
type: string
description: The topic of the room, if any.
description: |-
The plain text topic of the room. Omitted if no `text/plain` mimetype
exists in [`m.room.topic`](/client-server-api/#mroomtopic).
example: "All things general"
world_readable:
type: boolean
@ -59,7 +65,6 @@ properties:
example: "public"
room_type:
type: string
x-addedInMatrixVersion: "1.4"
description: |-
The `type` of room (from [`m.room.create`](/client-server-api/#mroomcreate)), if any.
required:

View file

@ -13,28 +13,15 @@
# limitations under the License.
type: object
description: A list of the rooms on the server.
description: A list of the published rooms on the server.
required: ["chunk"]
properties:
chunk:
type: array
description: |-
A paginated chunk of public rooms.
A paginated chunk of published rooms.
items:
allOf:
- $ref: "public_rooms_chunk.yaml"
- type: object
title: PublicRoomsChunk
properties:
# Override description of join_rule
join_rule:
type: string
description: |-
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.
example: "public"
$ref: "public_rooms_chunk.yaml"
next_batch:
type: string
description: |-
@ -50,7 +37,7 @@ properties:
total_room_count_estimate:
type: integer
description: |-
An estimate on the total number of public rooms, if the
An estimate on the total number of published rooms, if the
server has an estimate.
example: {
"chunk": [

View file

@ -0,0 +1,44 @@
# Copyright 2025 The Matrix.org Foundation C.I.C.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
type: object
title: RoomSummary
allOf:
- $ref: public_rooms_chunk.yaml
- type: object
properties:
room_type:
type: string
description: The `type` of room (from
[`m.room.create`](/client-server-api/#mroomcreate)),
if any.
allowed_room_ids:
type: array
items:
type: string
format: mx-room-id
pattern: "^!"
description: |-
If the room is a [restricted room](/server-server-api/#restricted-rooms), these are the room IDs which
are specified by the join rules. Empty or omitted otherwise.
encryption:
type: string
enum:
- "m.megolm.v1.aes-sha2"
description: |-
The encryption algorithm to be used to encrypt messages sent in the
room.
room_version:
description: The version of the room.
type: string

View file

@ -14,8 +14,8 @@
accessTokenQuery:
type: apiKey
description: |-
**Deprecated.** The `access_token` returned by a call to `/login` or `/register`, as a query
parameter.
**Deprecated.** The `access_token` obtained during [account registration](/client-server-api/#account-registration)
or [login](/client-server-api/#login), as a query parameter.
It can also be the `as_token` of an application service.
name: access_token
@ -23,11 +23,11 @@ accessTokenQuery:
accessTokenBearer:
type: http
description: |-
The `access_token` returned by a call to `/login` or `/register`, using the
`Authorization: Bearer` header.
The `access_token` obtained during [account registration](/client-server-api/#account-registration)
or [login](/client-server-api/#login), using the `Authorization: Bearer` header.
It can also be the `as_token` of an application service.
This is the preferred method.
scheme: bearer
appserviceAccessTokenQuery:
@ -42,6 +42,6 @@ appserviceAccessTokenBearer:
description: |-
The `as_token` of an application service, using the `Authorization: Bearer`
header.
This is the preferred method.
scheme: bearer

View file

@ -137,6 +137,11 @@ paths:
This API endpoint uses the [User-Interactive Authentication API](/client-server-api/#user-interactive-authentication-api).
Deletes the given device, and invalidates any access token associated with it.
{{% boxes/warning %}}
Since this endpoint uses User-Interactive Authentication, it cannot be used when the access token was obtained
via the [OAuth 2.0 API](/client-server-api/#oauth-20-api).
{{% /boxes/warning %}}
operationId: deleteDevice
security:
- accessTokenQuery: []
@ -189,6 +194,11 @@ paths:
This API endpoint uses the [User-Interactive Authentication API](/client-server-api/#user-interactive-authentication-api).
Deletes the given devices, and invalidates any access token associated with them.
{{% boxes/warning %}}
Since this endpoint uses User-Interactive Authentication, it cannot be used when the access token was obtained
via the [OAuth 2.0 API](/client-server-api/#oauth-20-api).
{{% /boxes/warning %}}
operationId: deleteDevices
security:
- accessTokenQuery: []

View file

@ -13,14 +13,15 @@
# limitations under the License.
openapi: 3.1.0
info:
title: Matrix Client-Server Room Directory API
title: Matrix Client-Server Published Room Directory API
version: 1.0.0
paths:
"/directory/list/room/{roomId}":
get:
summary: Gets the visibility of a room in the directory
description: Gets the visibility of a given room on the server's public room
directory.
description: |-
Gets the visibility of a given room in the server's
published room directory.
operationId: getRoomVisibilityOnDirectory
parameters:
- in: path
@ -32,7 +33,7 @@ paths:
type: string
responses:
"200":
description: The visibility of the room in the directory
description: The visibility of the room in the directory.
content:
application/json:
schema:
@ -50,7 +51,7 @@ paths:
"visibility": "public"
}
"404":
description: The room is not known to the server
description: The room is not known to the server.
content:
application/json:
schema:
@ -64,14 +65,13 @@ paths:
tags:
- Room discovery
put:
summary: Sets the visibility of a room in the room directory
summary: Sets the visibility of a room in the directory
description: |-
Sets the visibility of a given room in the server's public room
directory.
Sets the visibility of a given room in the server's published room directory.
Servers may choose to implement additional access control checks
here, for instance that room visibility can only be changed by
the room creator or a server administrator.
Servers MAY implement additional access control checks, for instance,
to ensure that a room's visibility can only be changed by the room creator
or a server administrator.
operationId: setRoomVisibilityOnDirectory
security:
- accessTokenQuery: []
@ -97,11 +97,11 @@ paths:
- public
description: |-
The new visibility setting for the room.
Defaults to 'public'.
Defaults to `public`.
example: {
"visibility": "public"
}
description: The new visibility for the room on the room directory.
description: The new visibility for the room in the published room directory.
required: true
responses:
"200":
@ -114,7 +114,7 @@ paths:
response:
value: {}
"404":
description: The room is not known to the server
description: The room is not known to the server.
content:
application/json:
schema:
@ -129,9 +129,9 @@ paths:
- Room discovery
/publicRooms:
get:
summary: Lists the public rooms on the server.
summary: Lists a server's published room directory
description: |-
Lists the public rooms on the server.
Lists a server's published room directory.
This API returns paginated responses. The rooms are ordered by the number
of joined members, with the largest rooms first.
@ -154,13 +154,13 @@ paths:
- in: query
name: server
description: |-
The server to fetch the public room lists from. Defaults to the
local server. Case sensitive.
The server to fetch the published room directory from. Defaults
to the local server. Case sensitive.
schema:
type: string
responses:
"200":
description: A list of the rooms on the server.
description: A list of the published rooms on the server.
content:
application/json:
schema:
@ -168,9 +168,9 @@ paths:
tags:
- Room discovery
post:
summary: Lists the public rooms on the server with optional filter.
summary: Lists a server's published room directory with an optional filter
description: |-
Lists the public rooms on the server, with optional filter.
Lists a server's published room directory with an optional filter.
This API returns paginated responses. The rooms are ordered by the number
of joined members, with the largest rooms first.
@ -182,8 +182,8 @@ paths:
- in: query
name: server
description: |-
The server to fetch the public room lists from. Defaults to the
local server. Case sensitive.
The server to fetch the published room directory from. Defaults
to the local server. Case sensitive.
schema:
type: string
requestBody:
@ -253,7 +253,7 @@ paths:
required: true
responses:
"200":
description: A list of the rooms on the server.
description: A filtered list of the published rooms on the server.
content:
application/json:
schema:

View file

@ -47,7 +47,7 @@ paths:
deleted alongside the device.
This endpoint does not use the [User-Interactive Authentication API](/client-server-api/#user-interactive-authentication-api) because
User-Interactive Authentication is designed to protect against attacks where the
User-Interactive Authentication is designed to protect against attacks where
someone gets hold of a single access token then takes over the account. This
endpoint invalidates all access tokens for the user, including the token used in
the request, and therefore the attacker is unable to take over the account in

View file

@ -0,0 +1,176 @@
# Copyright 2025 The Matrix.org Foundation C.I.C.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
openapi: 3.1.0
info:
title: Matrix Client-Server OAuth 2.0 Server Metadata Discovery API
version: 1.0.0
paths:
"/auth_metadata":
get:
summary: Get the OAuth 2.0 authorization server metadata.
description: |-
Gets the OAuth 2.0 authorization server metadata, as defined in
[RFC 8414](https://datatracker.ietf.org/doc/html/rfc8414), including the
endpoint URLs and the supported parameters that can be used by the
clients.
This endpoint definition includes only the fields that are meaningful in
the context of the Matrix specification. The full list of possible
fields is available in the [OAuth Authorization Server Metadata
registry](https://www.iana.org/assignments/oauth-parameters/oauth-parameters.xhtml#authorization-server-metadata),
and normative definitions of them are available in their respective
RFCs.
{{% boxes/note %}}
The authorization server metadata is relatively large and may change
over time. Clients should:
- Cache the metadata appropriately based on HTTP caching headers
- Refetch the metadata if it is stale
{{% /boxes/note %}}
operationId: getAuthMetadata
responses:
"200":
description: The OAuth 2.0 authorization server metadata.
content:
application/json:
schema:
type: object
properties:
issuer:
type: string
format: uri
description: |-
The authorization server's issuer identifier, which is a URL that uses the
`https` scheme and has no query or fragment components.
This is not used in the context of the Matrix specification, but is required
by [RFC 8414](https://datatracker.ietf.org/doc/html/rfc8414).
authorization_endpoint:
type: string
format: uri
description: |-
URL of the authorization endpoint, necessary to use the authorization code
grant.
token_endpoint:
type: string
format: uri
description: |-
URL of the token endpoint, necessary to use the authorization code grant and
the refresh token grant.
revocation_endpoint:
type: string
format: uri
description: |-
URL of the revocation endpoint, necessary to log out a client by invalidating
its access and refresh tokens.
registration_endpoint:
type: string
format: uri
description: |-
URL of the client registration endpoint, necessary to perform dynamic
registration of a client.
response_types_supported:
type: array
description: |-
List of OAuth 2.0 response type strings that the server supports at the
authorization endpoint.
This array MUST contain at least the `code` value, for clients to be able to
use the authorization code grant.
items:
type: string
description: A response type that the server supports.
grant_types_supported:
type: array
description: |-
List of OAuth 2.0 grant type strings that the server supports at the token
endpoint.
This array MUST contain at least the `authorization_code` and `refresh_token`
values, for clients to be able to use the authorization code grant and refresh
token grant, respectively.
items:
type: string
description: A grant type that the server supports.
response_modes_supported:
type: array
description: |-
List of OAuth 2.0 response mode strings that the server supports at the
authorization endpoint.
This array MUST contain at least the `query` and `fragment` values, for
improved security in the authorization code grant.
items:
type: string
description: A response mode that the server supports.
code_challenge_methods_supported:
type: array
description: |-
List of OAuth 2.0 Proof Key for Code Exchange (PKCE) code challenge methods
that the server supports at the authorization endpoint.
This array MUST contain at least the `S256` value, for improved security in
the authorization code grant.
items:
type: string
description: A PKCE code challenge method that the server supports.
prompt_values_supported:
type: array
description: |-
List of OpenID Connect prompt values that the server supports at the
authorization endpoint.
Only the `create` value defined in [Initiating User Registration via OpenID
Connect](https://openid.net/specs/openid-connect-prompt-create-1_0.html) is
supported, for a client to signal to the server that the user desires to
register a new account.
items:
type: string
description: A prompt value that the server supports.
required:
- issuer
- authorization_endpoint
- token_endpoint
- revocation_endpoint
- registration_endpoint
- response_types_supported
- grant_types_supported
- response_modes_supported
- code_challenge_methods_supported
example: {
"issuer": "https://account.example.com/",
"authorization_endpoint": "https://account.example.com/oauth2/auth",
"token_endpoint": "https://account.example.com/oauth2/token",
"registration_endpoint": "https://account.example.com/oauth2/clients/register",
"revocation_endpoint": "https://account.example.com/oauth2/revoke",
"response_types_supported": ["code"],
"grant_types_supported": ["authorization_code", "refresh_token"],
"response_modes_supported": ["query", "fragment"],
"code_challenge_methods_supported": ["S256"],
}
tags:
- Session management
servers:
- url: "{protocol}://{hostname}{basePath}"
variables:
protocol:
enum:
- http
- https
default: https
hostname:
default: localhost:8008
basePath:
default: /_matrix/client/v1

View file

@ -0,0 +1,242 @@
# Copyright 2016 OpenMarket Ltd
# Copyright 2022 The Matrix.org Foundation C.I.C.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
openapi: 3.1.0
info:
title: Matrix Client-Server Password Management API
version: 1.0.0
paths:
/account/password:
post:
summary: Changes a user's password.
description: |-
Changes the password for an account on this homeserver.
This API endpoint uses the [User-Interactive Authentication API](/client-server-api/#user-interactive-authentication-api) to
ensure the user changing the password is actually the owner of the
account.
An access token should be submitted to this endpoint if the client has
an active session.
The homeserver may change the flows available depending on whether a
valid access token is provided. The homeserver SHOULD NOT revoke the
access token provided in the request. Whether other access tokens for
the user are revoked depends on the request parameters.
security:
- {}
- accessTokenQuery: []
- accessTokenBearer: []
operationId: changePassword
requestBody:
content:
application/json:
schema:
type: object
properties:
new_password:
type: string
description: The new password for the account.
example: ihatebananas
logout_devices:
type: boolean
description: |-
Whether the user's other access tokens, and their associated devices, should be
revoked if the request succeeds. Defaults to true.
When `false`, the server can still take advantage of the [soft logout method](/client-server-api/#soft-logout)
for the user's remaining devices.
example: true
auth:
description: Additional authentication information for the user-interactive
authentication API.
allOf:
- $ref: definitions/auth_data.yaml
required:
- new_password
required: true
responses:
"200":
description: The password has been changed.
content:
application/json:
schema:
type: object
examples:
response:
value: {}
"401":
description: The homeserver requires additional authentication information.
content:
application/json:
schema:
$ref: definitions/auth_response.yaml
"429":
description: This request was rate-limited.
content:
application/json:
schema:
$ref: definitions/errors/rate_limited.yaml
tags:
- Account management
/account/password/email/requestToken:
post:
summary: Requests a validation token be sent to the given email address for the
purpose of resetting a user's password
description: |-
The homeserver must check that the given email address **is
associated** with an account on this homeserver. This API should be
used to request validation tokens when authenticating for the
`/account/password` endpoint.
This API's parameters and response are identical to that of the
[`/register/email/requestToken`](/client-server-api/#post_matrixclientv3registeremailrequesttoken)
endpoint, except that
`M_THREEPID_NOT_FOUND` may be returned if no account matching the
given email address could be found. The server may instead send an
email to the given address prompting the user to create an account.
`M_THREEPID_IN_USE` may not be returned.
The homeserver should validate the email itself, either by sending a
validation email itself or by using a service it has control over.
operationId: requestTokenToResetPasswordEmail
requestBody:
content:
application/json:
schema:
$ref: definitions/request_email_validation.yaml
required: true
responses:
"200":
description: An email was sent to the given address.
content:
application/json:
schema:
$ref: definitions/request_token_response.yaml
"400":
description: |-
The referenced third-party identifier is not recognised by the
homeserver, or the request was invalid. The error code `M_SERVER_NOT_TRUSTED`
can be returned if the server does not trust/support the identity server
provided in the request.
content:
application/json:
schema:
$ref: definitions/errors/error.yaml
examples:
response:
value: {
"errcode": "M_THREEPID_NOT_FOUND",
"error": "Email not found"
}
"403":
description: |-
The homeserver does not allow the third-party identifier as a
contact option.
content:
application/json:
schema:
$ref: definitions/errors/error.yaml
examples:
response:
value: {
"errcode": "M_THREEPID_DENIED",
"error": "Third-party identifier is not allowed"
}
tags:
- Account management
/account/password/msisdn/requestToken:
post:
summary: Requests a validation token be sent to the given phone number for the
purpose of resetting a user's password.
description: |-
The homeserver must check that the given phone number **is
associated** with an account on this homeserver. This API should be
used to request validation tokens when authenticating for the
`/account/password` endpoint.
This API's parameters and response are identical to that of the
[`/register/msisdn/requestToken`](/client-server-api/#post_matrixclientv3registermsisdnrequesttoken)
endpoint, except that
`M_THREEPID_NOT_FOUND` may be returned if no account matching the
given phone number could be found. The server may instead send the SMS
to the given phone number prompting the user to create an account.
`M_THREEPID_IN_USE` may not be returned.
The homeserver should validate the phone number itself, either by sending a
validation message itself or by using a service it has control over.
operationId: requestTokenToResetPasswordMSISDN
requestBody:
content:
application/json:
schema:
$ref: definitions/request_msisdn_validation.yaml
required: true
responses:
"200":
description: An SMS message was sent to the given phone number.
content:
application/json:
schema:
$ref: definitions/request_token_response.yaml
"400":
description: |-
The referenced third-party identifier is not recognised by the
homeserver, or the request was invalid. The error code `M_SERVER_NOT_TRUSTED`
can be returned if the server does not trust/support the identity server
provided in the request.
content:
application/json:
schema:
$ref: definitions/errors/error.yaml
examples:
response:
value: {
"errcode": "M_THREEPID_NOT_FOUND",
"error": "Phone number not found"
}
"403":
description: |-
The homeserver does not allow the third-party identifier as a
contact option.
content:
application/json:
schema:
$ref: definitions/errors/error.yaml
examples:
response:
value: {
"errcode": "M_THREEPID_DENIED",
"error": "Third-party identifier is not allowed"
}
tags:
- Account management
servers:
- url: "{protocol}://{hostname}{basePath}"
variables:
protocol:
enum:
- http
- https
default: https
hostname:
default: localhost:8008
basePath:
default: /_matrix/client/v3
components:
securitySchemes:
accessTokenQuery:
$ref: definitions/security.yaml#/accessTokenQuery
accessTokenBearer:
$ref: definitions/security.yaml#/accessTokenBearer

View file

@ -373,315 +373,6 @@ paths:
}
tags:
- Account management
/account/password:
post:
summary: Changes a user's password.
description: |-
Changes the password for an account on this homeserver.
This API endpoint uses the [User-Interactive Authentication API](/client-server-api/#user-interactive-authentication-api) to
ensure the user changing the password is actually the owner of the
account.
An access token should be submitted to this endpoint if the client has
an active session.
The homeserver may change the flows available depending on whether a
valid access token is provided. The homeserver SHOULD NOT revoke the
access token provided in the request. Whether other access tokens for
the user are revoked depends on the request parameters.
security:
- {}
- accessTokenQuery: []
- accessTokenBearer: []
operationId: changePassword
requestBody:
content:
application/json:
schema:
type: object
properties:
new_password:
type: string
description: The new password for the account.
example: ihatebananas
logout_devices:
type: boolean
description: |-
Whether the user's other access tokens, and their associated devices, should be
revoked if the request succeeds. Defaults to true.
When `false`, the server can still take advantage of the [soft logout method](/client-server-api/#soft-logout)
for the user's remaining devices.
example: true
auth:
description: Additional authentication information for the user-interactive
authentication API.
allOf:
- $ref: definitions/auth_data.yaml
required:
- new_password
required: true
responses:
"200":
description: The password has been changed.
content:
application/json:
schema:
type: object
examples:
response:
value: {}
"401":
description: The homeserver requires additional authentication information.
content:
application/json:
schema:
$ref: definitions/auth_response.yaml
"429":
description: This request was rate-limited.
content:
application/json:
schema:
$ref: definitions/errors/rate_limited.yaml
tags:
- Account management
/account/password/email/requestToken:
post:
summary: Requests a validation token be sent to the given email address for the
purpose of resetting a user's password
description: |-
The homeserver must check that the given email address **is
associated** with an account on this homeserver. This API should be
used to request validation tokens when authenticating for the
`/account/password` endpoint.
This API's parameters and response are identical to that of the
[`/register/email/requestToken`](/client-server-api/#post_matrixclientv3registeremailrequesttoken)
endpoint, except that
`M_THREEPID_NOT_FOUND` may be returned if no account matching the
given email address could be found. The server may instead send an
email to the given address prompting the user to create an account.
`M_THREEPID_IN_USE` may not be returned.
The homeserver should validate the email itself, either by sending a
validation email itself or by using a service it has control over.
operationId: requestTokenToResetPasswordEmail
requestBody:
content:
application/json:
schema:
$ref: definitions/request_email_validation.yaml
required: true
responses:
"200":
description: An email was sent to the given address.
content:
application/json:
schema:
$ref: definitions/request_token_response.yaml
"400":
description: |-
The referenced third-party identifier is not recognised by the
homeserver, or the request was invalid. The error code `M_SERVER_NOT_TRUSTED`
can be returned if the server does not trust/support the identity server
provided in the request.
content:
application/json:
schema:
$ref: definitions/errors/error.yaml
examples:
response:
value: {
"errcode": "M_THREEPID_NOT_FOUND",
"error": "Email not found"
}
"403":
description: |-
The homeserver does not allow the third-party identifier as a
contact option.
content:
application/json:
schema:
$ref: definitions/errors/error.yaml
examples:
response:
value: {
"errcode": "M_THREEPID_DENIED",
"error": "Third-party identifier is not allowed"
}
tags:
- Account management
/account/password/msisdn/requestToken:
post:
summary: Requests a validation token be sent to the given phone number for the
purpose of resetting a user's password.
description: |-
The homeserver must check that the given phone number **is
associated** with an account on this homeserver. This API should be
used to request validation tokens when authenticating for the
`/account/password` endpoint.
This API's parameters and response are identical to that of the
[`/register/msisdn/requestToken`](/client-server-api/#post_matrixclientv3registermsisdnrequesttoken)
endpoint, except that
`M_THREEPID_NOT_FOUND` may be returned if no account matching the
given phone number could be found. The server may instead send the SMS
to the given phone number prompting the user to create an account.
`M_THREEPID_IN_USE` may not be returned.
The homeserver should validate the phone number itself, either by sending a
validation message itself or by using a service it has control over.
operationId: requestTokenToResetPasswordMSISDN
requestBody:
content:
application/json:
schema:
$ref: definitions/request_msisdn_validation.yaml
required: true
responses:
"200":
description: An SMS message was sent to the given phone number.
content:
application/json:
schema:
$ref: definitions/request_token_response.yaml
"400":
description: |-
The referenced third-party identifier is not recognised by the
homeserver, or the request was invalid. The error code `M_SERVER_NOT_TRUSTED`
can be returned if the server does not trust/support the identity server
provided in the request.
content:
application/json:
schema:
$ref: definitions/errors/error.yaml
examples:
response:
value: {
"errcode": "M_THREEPID_NOT_FOUND",
"error": "Phone number not found"
}
"403":
description: |-
The homeserver does not allow the third-party identifier as a
contact option.
content:
application/json:
schema:
$ref: definitions/errors/error.yaml
examples:
response:
value: {
"errcode": "M_THREEPID_DENIED",
"error": "Third-party identifier is not allowed"
}
tags:
- Account management
/account/deactivate:
post:
summary: Deactivate a user's account.
description: |-
Deactivate the user's account, removing all ability for the user to
login again.
This API endpoint uses the [User-Interactive Authentication API](/client-server-api/#user-interactive-authentication-api).
An access token should be submitted to this endpoint if the client has
an active session.
The homeserver may change the flows available depending on whether a
valid access token is provided.
Unlike other endpoints, this endpoint does not take an `id_access_token`
parameter because the homeserver is expected to sign the request to the
identity server instead.
security:
- {}
- accessTokenQuery: []
- accessTokenBearer: []
operationId: deactivateAccount
requestBody:
content:
application/json:
schema:
type: object
properties:
auth:
description: Additional authentication information for the user-interactive
authentication API.
allOf:
- $ref: definitions/auth_data.yaml
id_server:
type: string
description: |-
The identity server to unbind all of the user's 3PIDs from.
If not provided, the homeserver MUST use the `id_server`
that was originally use to bind each identifier. If the
homeserver does not know which `id_server` that was,
it must return an `id_server_unbind_result` of
`no-support`.
example: example.org
erase:
x-addedInMatrixVersion: "1.10"
type: boolean
description: |-
Whether the user would like their content to be erased as
much as possible from the server.
Erasure means that any users (or servers) which join the
room after the erasure request are served redacted copies of
the events sent by this account. Users which had visibility
on those events prior to the erasure are still able to see
unredacted copies. No redactions are sent and the erasure
request is not shared over federation, so other servers
might still serve unredacted copies.
The server should additionally erase any non-event data
associated with the user, such as [account data](/client-server-api/#client-config)
and [contact 3PIDs](/client-server-api/#adding-account-administrative-contact-information).
Defaults to `false` if not present.
required: true
responses:
"200":
description: The account has been deactivated.
content:
application/json:
schema:
type: object
properties:
id_server_unbind_result:
type: string
enum:
- success
- no-support
description: |-
An indicator as to whether or not the homeserver was able to unbind
the user's 3PIDs from the identity server(s). `success` indicates
that all identifiers have been unbound from the identity server while
`no-support` indicates that one or more identifiers failed to unbind
due to the identity server refusing the request or the homeserver
being unable to determine an identity server to unbind from. This
must be `success` if the homeserver has no identifiers to unbind
for the user.
example: success
required:
- id_server_unbind_result
"401":
description: The homeserver requires additional authentication information.
content:
application/json:
schema:
$ref: definitions/auth_response.yaml
"429":
description: This request was rate-limited.
content:
application/json:
schema:
$ref: definitions/errors/rate_limited.yaml
tags:
- Account management
/register/available:
get:
summary: Checks to see if a username is available on the server.

View file

@ -0,0 +1,138 @@
# Copyright 2025 The Matrix.org Foundation C.I.C.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
openapi: 3.1.0
info:
title: Matrix Client-Server Room Summary API
version: 1.0.0
paths:
"/room_summary/{roomIdOrAlias}":
get:
x-addedInMatrixVersion: "1.15"
summary: Retrieves a summary for a room.
description: |-
Retrieves a summary for a room.
Clients should note that requests for rooms where the user's membership
is `invite` or `knock` might yield outdated, partial or even no data
since the server may not have access to the current state of the room.
Servers MAY allow unauthenticated access to this API if at least one of
the following conditions holds true:
- The room has a [join rule](#mroomjoin_rules) of `public`, `knock` or
`knock_restricted`.
- The room has a `world_readable` [history visibility](#room-history-visibility).
Servers should consider rate limiting requests that require a federation
request more heavily if the client is unauthenticated.
operationId: getRoomSummary
security:
- signedRequest: []
parameters:
- in: path
name: roomIdOrAlias
description: The room identifier or alias to summarise.
required: true
example: "#monkeys:matrix.org"
schema:
oneOf:
- type: string
format: mx-room-id
pattern: "^!"
- type: string
format: mx-room-alias
pattern: "^#"
- in: query
name: via
description: |-
The servers to attempt to request the summary from when
the local server cannot generate it (for instance, because
it has no local user in the room).
example:
- matrix.org
- elsewhere.ca
schema:
type: array
items:
type: string
format: mx-server-name
responses:
"200":
description: A summary of the room.
content:
application/json:
schema:
description: A summary of the room.
allOf:
- $ref: ../client-server/definitions/room_summary.yaml
- type: object
properties:
membership:
description: |-
The membership state of the user if the user is joined to the room. Absent
if the API was called unauthenticated.
enum:
- invite
- join
- knock
- leave
- ban
type: string
examples:
response:
value: {
room_id: "!ol19s:bleecker.street",
avatar_url: "mxc://bleecker.street/CHEDDARandBRIE",
guest_can_join: false,
name: "CHEESE",
num_joined_members: 37,
topic: "Tasty tasty cheese",
world_readable: true,
join_rule: "public",
room_type: "m.space",
membership: "invite",
encryption: "m.megolm.v1.aes-sha2",
room_version: "9001",
}
"404":
description: |-
The room could not be found.
content:
application/json:
schema:
$ref: ../client-server/definitions/errors/error.yaml
examples:
response:
value: {
"errcode": "M_NOT_FOUND",
"error": "Room not found."
}
servers:
- url: "{protocol}://{hostname}{basePath}"
variables:
protocol:
enum:
- http
- https
default: https
hostname:
default: localhost:8008
basePath:
default: /_matrix/client/v1
components:
securitySchemes:
accessTokenQuery:
$ref: definitions/security.yaml#/accessTokenQuery
accessTokenBearer:
$ref: definitions/security.yaml#/accessTokenBearer

View file

@ -105,13 +105,31 @@ paths:
example: ""
schema:
type: string
- in: query
name: format
x-addedInMatrixVersion: "1.16"
description: |-
The format to use for the returned data. `content` (the default) will
return only the content of the state event. `event` will return the entire
event in the usual format suitable for clients, including fields like event
ID, sender and timestamp.
example: event
schema:
type: string
enum:
- content
- event
responses:
"200":
description: The content of the state event.
description: |-
The content of the state event, or the entire client-formatted event
if `?format=event` was used.
content:
application/json:
schema:
type: object
oneOf:
- type: object
- $ref: "../../event-schemas/schema/core-event-schema/state_event.yaml"
examples:
response:
value: {

View file

@ -102,15 +102,10 @@ paths:
* The room's [`m.room.history_visibility`](#room-history-visibility) is set to `world_readable`.
items:
allOf:
- $ref: definitions/public_rooms_chunk.yaml
- $ref: definitions/room_summary.yaml
- type: object
title: SpaceHierarchyRoomsChunk
properties:
room_type:
type: string
description: The `type` of room (from
[`m.room.create`](/client-server-api/#mroomcreate)),
if any.
children_state:
type: array
description: |-
@ -130,6 +125,14 @@ paths:
description: The `origin_server_ts` for the event.
required:
- origin_server_ts
room_type:
x-addedInMatrixVersion: "1.4" # Extends room_summary.yaml
allowed_room_ids:
x-addedInMatrixVersion: "1.15" # Extends room_summary.yaml
encryption:
x-addedInMatrixVersion: "1.15" # Extends room_summary.yaml
room_version:
x-addedInMatrixVersion: "1.15" # Extends room_summary.yaml
required:
- children_state
next_batch:

View file

@ -22,9 +22,12 @@ paths:
description: |-
Gets server admin contact and support page of the domain.
Like the [well-known discovery URI](/client-server-api/#well-known-uri),
this should be accessed with the hostname of the homeserver by making a
{{% boxes/note %}}
Like the [well-known discovery URI](/client-server-api/#well-known-uris),
this endpoint should be accessed with the hostname of the homeserver's
[server name](/appendices/#server-name) by making a
GET request to `https://hostname/.well-known/matrix/support`.
{{% /boxes/note %}}
Note that this endpoint is not necessarily handled by the homeserver.
It may be served by another webserver, used for discovering support

View file

@ -117,6 +117,31 @@ paths:
example: 30000
schema:
type: integer
- in: query
name: use_state_after
x-addedInMatrixVersion: "1.16"
description: |-
Controls whether to receive state changes between the previous sync
and the **start** of the timeline, or between the previous sync and
the **end** of the timeline.
If this is set to `true`, servers MUST respond with the state
between the previous sync and the **end** of the timeline in
`state_after` and MUST omit `state`.
If `false`, servers MUST respond with the state between the previous
sync and the **start** of the timeline in `state` and MUST omit
`state_after`.
Even if this is set to `true`, clients MUST update their local state
with events in `state` and `timeline` if `state_after` is missing in
the response, for compatibility with servers that don't support this
parameter.
By default, this is `false`.
example: false
schema:
type: boolean
responses:
"200":
description: The initial snapshot or delta for the client to use to update their
@ -197,16 +222,50 @@ paths:
type: object
description: |-
Updates to the state, between the time indicated by
the `since` parameter, and the start of the
`timeline` (or all state up to the start of the
the `since` parameter, and the **start** of the
`timeline` (or all state up to the **start** of the
`timeline`, if `since` is not given, or
`full_state` is true).
N.B. state updates for `m.room.member` events will
{{% boxes/note %}}
State updates for `m.room.member` events will
be incomplete if `lazy_load_members` is enabled in
the `/sync` filter, and only return the member events
required to display the senders of the timeline events
in this response.
{{% /boxes/note %}}
MUST be omitted if `use_state_after` was set to `true`
in the request.
allOf:
- $ref: definitions/state_event_batch.yaml
state_after:
title: State
type: object
x-addedInMatrixVersion: "1.16"
description: |-
Updates to the state, between the time indicated by
the `since` parameter, and the **end** of the
`timeline` (or all state up to the **end** of the
`timeline`, if `since` is not given, or
`full_state` is true).
{{% boxes/note %}}
State updates for `m.room.member` events will
be incomplete if `lazy_load_members` is enabled in
the `/sync` filter, and only return the member events
required to display the senders of the timeline events
in this response.
{{% /boxes/note %}}
If this field is set, even if it is empty, clients MUST
only update their local state with events in this list,
and MUST NOT update their local state with events in
`timeline`. If this field is not set, clients MUST update
their local state with events in `state` and `timeline`.
**Required** if `use_state_after` was set to `true` in the
request, even if it is empty.
allOf:
- $ref: definitions/state_event_batch.yaml
timeline:
@ -353,7 +412,28 @@ paths:
state:
title: State
type: object
description: The state updates for the room up to the start of the timeline.
description: |-
The state updates for the room up to the **start** of the timeline.
MUST be omitted if `use_state_after` was set to `true` in the
request.
allOf:
- $ref: definitions/state_event_batch.yaml
state_after:
title: State
type: object
x-addedInMatrixVersion: "1.16"
description: |-
The state updates for the room up to the **end** of the timeline.
If this field is set, even if it is empty, clients MUST only
update their local state with events in this list, and MUST NOT
update their local state with events in `timeline`. If this field
is not set, clients MUST update their local state with events in
`state` and `timeline`.
**Required** if `use_state_after` was set to `true` in the
request, even if it is empty.
allOf:
- $ref: definitions/state_event_batch.yaml
timeline:
@ -441,17 +521,57 @@ paths:
"state": {
"events": [
{
"$ref": "../../event-schemas/examples/m.room.member.yaml"
"content": {
"avatar_url": "mxc://example.org/SFHyPlCeYUSFFxlgbQYZmoEoe",
"displayname": "Example user",
"membership": "join"
},
"event_id": "$143273976499sgjks:example.org",
"origin_server_ts": 1432735824653,
"sender": "@example:example.org",
"state_key": "@example:example.org",
"type": "m.room.member",
"unsigned": {
"age": 45603,
"membership": "join"
}
}
]
},
"timeline": {
"events": [
{
"$ref": "../../event-schemas/examples/m.room.member.yaml"
"content": {
"avatar_url": "mxc://example.org/SEsfnsuifSDFSSEF",
"displayname": "Alice Margatroid",
"membership": "join",
"reason": "Looking for support"
},
"event_id": "$143273582443PhrSn:example.org",
"origin_server_ts": 1432735824653,
"sender": "@alice:example.org",
"state_key": "@alice:example.org",
"type": "m.room.member",
"unsigned": {
"age": 1234,
"membership": "join"
}
},
{
"$ref": "../../event-schemas/examples/m.room.message$m.text.yaml"
"content": {
"body": "This is an example text message",
"format": "org.matrix.custom.html",
"formatted_body": "<b>This is an example text message</b>",
"msgtype": "m.text"
},
"event_id": "$143273582443PhrSn:example.org",
"origin_server_ts": 1432735824653,
"sender": "@example:example.org",
"type": "m.room.message",
"unsigned": {
"age": 1234,
"membership": "join"
}
}
],
"limited": true,

View file

@ -57,9 +57,6 @@ paths:
- A signature of the token, signed with the identity server's private key
- The matrix user ID who invited them to the room
If a token is requested from the identity server, the homeserver will
append a `m.room.third_party_invite` event to the room.
operationId: inviteBy3PID
security:
- accessTokenQuery: []
@ -72,6 +69,8 @@ paths:
example: "!d41d8cd:matrix.org"
schema:
type: string
format: mx-room-id
pattern: "^!"
requestBody:
content:
application/json:
@ -90,7 +89,9 @@ paths:
value: {}
"403":
description: |-
You do not have permission to invite the user to the room. A meaningful `errcode` and description error text will be returned. Example reasons for rejections are:
You do not have permission to invite the user to the room. A
meaningful `errcode` and description error text will be returned.
Example reasons for rejections are:
- The invitee has been banned from the room.
- The invitee is already a member of the room.

View file

@ -20,10 +20,17 @@ paths:
post:
summary: Searches the user directory.
description: |-
Performs a search for users. The homeserver may
determine which subset of users are searched, however the homeserver
MUST at a minimum consider the users the requesting user shares a
room with and those who reside in public rooms (known to the homeserver).
Performs a search for users. The homeserver may determine which
subset of users are searched. However, the homeserver MUST at a
minimum consider users who are visible to the requester based
on their membership in rooms known to the homeserver. This means:
- users that share a room with the requesting user
- users who are joined to rooms known to the homeserver that have a
`public` [join rule](#mroomjoin_rules)
- users who are joined to rooms known to the homeserver that have a
`world_readable` [history visibility](#room-history-visibility)
The search MUST consider local users to the homeserver, and SHOULD
query remote users as part of the search.

View file

@ -26,6 +26,12 @@ paths:
suitably namespaced for each application and reduces the risk of
clashes.
{{% boxes/note %}}
This endpoint should be accessed with the hostname of the homeserver's
[server name](/appendices/#server-name) by making a
GET request to `https://hostname/.well-known/matrix/client`.
{{% /boxes/note %}}
Note that this endpoint is not necessarily handled by the homeserver,
but by another webserver, to be used for discovering the homeserver URL.
operationId: getWellknown

View file

@ -43,7 +43,8 @@ paths:
properties:
public_key:
type: string
description: Unpadded Base64 encoded public key.
description: |-
[Unpadded Base64](/appendices/#unpadded-base64)-encoded public key.
required:
- public_key
examples:
@ -74,7 +75,8 @@ paths:
- in: query
name: public_key
required: true
description: The unpadded base64-encoded public key to check.
description: |-
The [unpadded Base64](/appendices/#unpadded-base64)-encoded public key to check.
example: VXuGitF39UH5iRfvbIknlvlAVKgD1BsLDMvBf0pmp7c
schema:
type: string
@ -105,7 +107,14 @@ paths:
- in: query
name: public_key
required: true
description: The unpadded base64-encoded public key to check.
description: |-
The [unpadded Base64](/appendices/#unpadded-base64)-encoded public
key to check.
This MUST be the exact same encoded string returned in the response
of the [`/store-invite`](/identity-service-api/#post_matrixidentityv2store-invite)
endpoint, or found in the corresponding [`m.room.third_party_invite`](/client-server-api/#mroomthird_party_invite)
event, so it may use the standard or URL-safe alphabets.
example: VXuGitF39UH5iRfvbIknlvlAVKgD1BsLDMvBf0pmp7c
schema:
type: string

View file

@ -42,7 +42,7 @@ paths:
(if present) from the request here.
Also, the generated ephemeral public key will be listed as valid on
requests to `/_matrix/identity/v2/pubkey/ephemeral/isvalid`.
requests to [`/_matrix/identity/v2/pubkey/ephemeral/isvalid`](/identity-service-api/#get_matrixidentityv2pubkeyephemeralisvalid).
Currently, invites may only be issued for 3pids of the `email` medium.
@ -70,10 +70,14 @@ paths:
room_id:
type: string
description: The Matrix room ID to which the user is invited
format: mx-room-id
pattern: "^!"
example: "!something:example.org"
sender:
type: string
description: The Matrix user ID of the inviting user
format: mx-user-id
pattern: "^@"
example: "@bob:example.com"
room_alias:
type: string
@ -81,12 +85,16 @@ paths:
The Matrix room alias for the room to which the user is
invited. This should be retrieved from the `m.room.canonical_alias`
state event.
format: mx-room-alias
pattern: "^#"
example: "#somewhere:example.org"
room_avatar_url:
type: string
description: |-
The Content URI for the room to which the user is invited. This should
be retrieved from the `m.room.avatar` state event.
format: mx-mxc-uri
pattern: "^mxc:\\/\\/"
example: mxc://example.org/s0meM3dia
room_join_rules:
type: string
@ -108,6 +116,8 @@ paths:
type: string
description: The Content URI for the avatar of the user ID initiating the
invite.
format: mx-mxc-uri
pattern: "^mxc:\\/\\/"
example: mxc://example.org/an0th3rM3dia
room_type:
type: string
@ -146,7 +156,7 @@ paths:
public_key:
type: string
description: |
The public key, encoded using [unpadded Base64](/appendices/#unpadded-base64).
The public key, encoded using standard or URL-safe [unpadded Base64](/appendices/#unpadded-base64).
key_validity_url:
type: string
description: |

View file

@ -20,7 +20,7 @@ paths:
put:
summary: Invites a remote user to a room
description: |-
Invites a remote user to a room. Once the event has been signed by both the inviting
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.
@ -32,6 +32,10 @@ paths:
[room version specification](/rooms) 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.**
Also note that if the remote homeserver is already in the room, it will receive the
invite event twice; once through this endpoint, and again through a [federation
transaction](/server-server-api/#transactions).
operationId: sendInviteV1
security:
- signedRequest: []

View file

@ -24,7 +24,7 @@ paths:
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
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.
@ -36,6 +36,10 @@ paths:
[room version specification](/rooms) 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.**
Also note that if the remote homeserver is already in the room, it will receive the
invite event twice; once through this endpoint, and again through a [federation
transaction](/server-server-api/#transactions).
operationId: sendInviteV2
security:
- signedRequest: []

View file

@ -13,16 +13,20 @@
# limitations under the License.
openapi: 3.1.0
info:
title: Matrix Federation Public Rooms API
title: Matrix Federation Published Room Directory API
version: 1.0.0
paths:
/publicRooms:
get:
summary: Get all the public rooms for a homeserver
summary: Lists the server's published room directory
description: |-
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.
Lists the server's published room directory.
This API returns paginated responses. The rooms are ordered by the number
of joined members, with the largest rooms first.
This SHOULD not return rooms that are listed on another homeserver's directory,
just those listed on the receiving homeserver's directory.
operationId: getPublicRooms
security:
- signedRequest: []
@ -62,21 +66,18 @@ paths:
type: string
responses:
"200":
description: The public room list for the homeserver.
description: A list of the published rooms on the server.
content:
application/json:
schema:
$ref: ../client-server/definitions/public_rooms_response.yaml
post:
summary: Gets the public rooms on the server with optional filter.
summary: Lists the server's published room directory with an optional filter
description: |-
Lists the public rooms on the server, with optional filter.
Lists the server's published room directory with an 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.
operationId: queryPublicRooms
security:
- signedRequest: []
@ -147,69 +148,11 @@ paths:
required: true
responses:
"200":
description: A list of the rooms on the server.
description: A filtered list of the published rooms on the server.
content:
application/json:
schema:
type: object
description: A list of the rooms on the server.
required:
- chunk
properties:
chunk:
title: PublicRoomsChunks
type: array
description: A paginated chunk of public rooms.
items:
allOf:
- $ref: ../client-server/definitions/public_rooms_chunk.yaml
- type: object
properties:
# Override description of join_rule
join_rule:
type: string
description: |-
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.
next_batch:
type: string
description: |-
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:
type: string
description: |-
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:
type: integer
description: |-
An estimate on the total number of public rooms, if the
server has an estimate.
examples:
response:
value: {
"chunk": [
{
"avatar_url": "mxc://bleecker.street/CHEDDARandBRIE",
"guest_can_join": false,
"name": "CHEESE",
"num_joined_members": 37,
"room_id": "!ol19s:bleecker.street",
"topic": "Tasty tasty cheese",
"world_readable": true,
"join_rule": "public",
"room_type": "m.space"
}
],
"next_batch": "p190q",
"prev_batch": "p1902",
"total_room_count_estimate": 115
}
$ref: ../client-server/definitions/public_rooms_response.yaml
servers:
- url: "{protocol}://{hostname}{basePath}"
variables:

View file

@ -61,22 +61,10 @@ paths:
room:
description: A summary of the room requested.
allOf:
- $ref: ../client-server/definitions/public_rooms_chunk.yaml
- $ref: ../client-server/definitions/room_summary.yaml
- type: object
title: SpaceHierarchyParentRoom
properties:
room_type:
type: string
description: The `type` of room (from
[`m.room.create`](/client-server-api/#mroomcreate)),
if any.
allowed_room_ids:
type: array
items:
type: string
description: |-
If the room is a [restricted room](/server-server-api/#restricted-rooms), these are the room IDs which
are specified by the join rules. Empty or omitted otherwise.
children_state:
type: array
description: |-
@ -96,6 +84,12 @@ paths:
description: The `origin_server_ts` for the event.
required:
- origin_server_ts
room_type:
x-addedInMatrixVersion: "1.4" # Extends room_summary.yaml
encryption:
x-addedInMatrixVersion: "1.15" # Extends room_summary.yaml
room_version:
x-addedInMatrixVersion: "1.15" # Extends room_summary.yaml
required:
- children_state
children:
@ -105,22 +99,16 @@ paths:
be excluded.
items:
allOf:
- $ref: ../client-server/definitions/public_rooms_chunk.yaml
- $ref: ../client-server/definitions/room_summary.yaml
- type: object
title: SpaceHierarchyChildRoomsChunk
properties:
room_type:
type: string
description: The `type` of room (from
[`m.room.create`](/client-server-api/#mroomcreate)),
if any.
allowed_room_ids:
type: array
items:
type: string
description: |-
If the room is a [restricted room](/server-server-api/#restricted-rooms), these are the room IDs which
are specified by the join rules. Empty or omitted otherwise.
x-addedInMatrixVersion: "1.4" # Extends room_summary.yaml
encryption:
x-addedInMatrixVersion: "1.15" # Extends room_summary.yaml
room_version:
x-addedInMatrixVersion: "1.15" # Extends room_summary.yaml
inaccessible_children:
type: array
items:

View file

@ -35,6 +35,8 @@ paths:
example: "!abc123:matrix.org"
schema:
type: string
format: mx-room-id
pattern: "^!"
requestBody:
content:
application/json:
@ -50,16 +52,22 @@ paths:
description: |-
The room ID the event is for. Must match the ID given in
the path.
format: mx-room-id
pattern: "^!"
example: "!abc123:matrix.org"
sender:
type: string
description: |-
The user ID of the user who sent the original `m.room.third_party_invite`
event.
format: mx-user-id
pattern: "^@"
example: "@joe:matrix.org"
state_key:
type: string
description: The user ID of the invited user
format: mx-user-id
pattern: "^@"
example: "@someone:example.org"
content:
type: object
@ -82,45 +90,7 @@ paths:
third-party identifier.
example: alice
signed:
type: object
description: |-
A block of content which has been signed, which servers can use to
verify the event.
title: Invite Signatures
properties:
signatures:
type: object
title: Signatures
additionalProperties:
type: object
additionalProperties:
type: string
description: |-
The server signatures for this event.
The signature is calculated using the process
described at [Signing JSON](/appendices/#signing-json).
example:
magic.forest:
ed25519:3: fQpGIW1Snz+pwLZu6sTy2aHy/DYWWTspTJRPyNp0PKkymfIsNffysMl6ObMMFdIJhk6g6pwlIqZ54rxo8SLmAg
mxid:
type: string
description: The invited matrix user ID
example: "@alice:localhost"
token:
type: string
description: The token used to verify the event
example: abc123
required:
- signatures
- mxid
- token
example:
mxid: "@alice:localhost"
token: abc123
signatures:
magic.forest:
ed25519:3: fQpGIW1Snz+pwLZu6sTy2aHy/DYWWTspTJRPyNp0PKkymfIsNffysMl6ObMMFdIJhk6g6pwlIqZ54rxo8SLmAg
$ref: ../../event-schemas/schema/components/signed_third_party_invite.yaml
required:
- display_name
- signed
@ -215,6 +185,8 @@ paths:
mxid:
type: string
description: The user that is now bound to the third-party identifier.
format: mx-user-id
pattern: "^@"
example: "@alice:matrix.org"
invites:
type: array
@ -237,59 +209,23 @@ paths:
mxid:
type: string
description: The now-bound user ID that received the invite.
format: mx-user-id
pattern: "^@"
example: "@alice:matrix.org"
room_id:
type: string
description: The room ID the invite is valid for.
format: mx-room-id
pattern: "^!"
example: "!somewhere:example.org"
sender:
type: string
description: The user ID that sent the invite.
format: mx-user-id
pattern: "^@"
example: "@bob:matrix.org"
# TODO (TravisR): Make this reusable when doing IS spec changes
# also make sure it isn't lying about anything, like the key version
signed:
type: object
title: Identity Server Signatures
description: |-
Signature from the identity server using a long-term private
key.
properties:
mxid:
type: string
description: |-
The user ID that has been bound to the third-party
identifier.
example: "@alice:matrix.org"
token:
type: string
# TODO: What is this actually?
description: A token.
example: Hello World
signatures:
type: object
title: Identity Server Signature
description: |-
The signature from the identity server. The `string` key
is the identity server's domain name, such as vector.im
additionalProperties:
type: object
title: Identity Server Domain Signature
description: The signature for the identity server.
properties:
ed25519:0:
type: string
description: The signature.
example: SomeSignatureGoesHere
required:
- ed25519:0
example:
vector.im:
ed25519:0: SomeSignatureGoesHere
required:
- mxid
- token
- signatures
$ref: ../../event-schemas/schema/components/signed_third_party_invite.yaml
required:
- medium
- address

View file

@ -24,6 +24,12 @@ paths:
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.
{{% boxes/note %}}
This endpoint should be accessed with the hostname of the homeserver's
[server name](/appendices/#server-name) by making a
GET request to `https://hostname/.well-known/matrix/server`.
{{% /boxes/note %}}
operationId: getWellKnown
responses:
"200":

View file

@ -1,6 +1,7 @@
{
"$ref": "core/state_event.json",
"state_key": "@alice:example.org",
"sender": "@alice:example.org",
"type": "m.room.member",
"content": {
"membership": "join",

View file

@ -3,6 +3,14 @@
"type": "m.room.topic",
"state_key": "",
"content": {
"topic": "A room topic"
"m.topic": {
"m.text": [ {
"mimetype": "text/html",
"body": "An <em>interesting</em> room topic"
}, {
"body": "An interesting room topic"
}]
},
"topic": "An interesting room topic"
}
}

View file

@ -0,0 +1,28 @@
type: array
description: |-
An ordered array of textual representations in different mimetypes.
Senders SHOULD specify at least one representation and SHOULD always
include a plaintext representation.
Receivers SHOULD use the first representation in the array that
they understand.
title: TextContentBlock
items:
type: object
title: TextualRepresentation
properties:
mimetype:
type: string
description: The mimetype. Defaults to `text/plain` if omitted.
example: "text/html"
body:
type: string
description: |-
The string content.
Clients SHOULD validate and sanitize the content as they do
for rich content associated with [`msgtype`](/client-server-api/#mroommessage-msgtypes)
of [`m.room.message`](/client-server-api/#mroommessage).
required:
- body

View file

@ -0,0 +1,45 @@
title: SignedThirdPartyInvite
description: |-
A block of content which has been signed by the identity server, which
homeservers can use to verify the event. Clients should ignore this.
type: object
properties:
mxid:
description: |-
The user ID that has been bound to the third-party identifier.
type: string
format: mx-user-id
pattern: "^@"
example: "@alice:example.org"
signatures:
title: IdentityServerSignatures
description: |-
The identity server signatures for this block. This is a map of identity
server name to signing key identifier to base64-encoded signature.
The signatures are calculated using the process described at
[Signing JSON](/appendices/#signing-json).
type: object
additionalProperties:
type: object
additionalProperties:
type: string
example: {
"magic.forest": {
"ed25519:3": "fQpGIW1Snz+pwLZu6sTy2aHy/DYWWTspTJRPyNp0PKkymfIsNffysMl6ObMMFdIJhk6g6pwlIqZ54rxo8SLmAg"
}
}
token:
description: |-
The token generated by the identity server at the
[`/store_invite`](/identity-service-api/#post_matrixidentityv2store-invite)
endpoint.
It matches the `state_key` of the corresponding [`m.room.third_party_invite`](/client-server-api/#mroomthird_party_invite)
event.
type: string
example: "abc123"
required:
- mxid
- signatures
- token

View file

@ -1,15 +1,15 @@
$schema: https://json-schema.org/draft/2020-12/schema
title: RoomEvent
description: Room Events have the following fields.
allOf:
- $ref: sync_room_event.yaml
description: Room Events have the following fields.
properties:
room_id:
description: |-
The ID of the room associated with this event. Will not be present on events
that arrive through `/sync`, despite being required everywhere else.
type: string
required:
- room_id
title: RoomEvent
type: object
- type: object
properties:
room_id:
description: |-
The ID of the room associated with this event. Will not be present on events
that arrive through `/sync`, despite being required everywhere else.
type: string
required:
- room_id

View file

@ -19,27 +19,27 @@
$schema: https://json-schema.org/draft/2020-12/schema
allOf:
- $ref: event.yaml
title: SyncRoomEvent
description: In addition to the Event fields, Room Events have the following additional
fields.
properties:
event_id:
description: The globally unique event identifier.
type: string
sender:
description: Contains the fully-qualified ID of the user who sent this event.
type: string
origin_server_ts:
description: Timestamp in milliseconds on originating homeserver
when this event was sent.
type: integer
format: int64
unsigned:
$ref: unsigned_prop.yaml
required:
- event_id
- sender
- origin_server_ts
title: SyncRoomEvent
type: object
allOf:
- $ref: event.yaml
- type: object
properties:
event_id:
description: The globally unique event identifier.
type: string
sender:
description: Contains the fully-qualified ID of the user who sent this event.
type: string
origin_server_ts:
description: Timestamp in milliseconds on originating homeserver
when this event was sent.
type: integer
format: int64
unsigned:
$ref: unsigned_prop.yaml
required:
- event_id
- sender
- origin_server_ts

View file

@ -16,21 +16,21 @@
$schema: https://json-schema.org/draft/2020-12/schema
allOf:
- $ref: sync_room_event.yaml
title: SyncStateEvent
description: In addition to the Room Event fields, State Events have the following
additional fields.
properties:
state_key:
description: A unique key which defines the overwriting semantics for this piece
of room state. This value is often a zero-length string. The presence of this
key makes this event a State Event.
allOf:
- $ref: sync_room_event.yaml
- type: object
properties:
state_key:
description: A unique key which defines the overwriting semantics for this piece
of room state. This value is often a zero-length string. The presence of this
key makes this event a State Event.
State keys starting with an `@` are reserved for referencing user IDs, such
as room members. With the exception of a few events, state events set with a
given user's ID as the state key MUST only be set by that user.
type: string
required:
- state_key
title: SyncStateEvent
type: object
State keys starting with an `@` are reserved for referencing user IDs, such
as room members. With the exception of a few events, state events set with a
given user's ID as the state key MUST only be set by that user.
type: string
required:
- state_key

View file

@ -4,17 +4,27 @@ $schema: https://json-schema.org/draft/2020-12/schema
allOf:
- $ref: core-event-schema/state_event.yaml
description: |-
Adjusts the membership state for a user in a room. It is preferable to use the membership APIs (`/rooms/<room id>/invite` etc) when performing membership actions rather than adjusting the state directly as there are a restricted set of valid transformations. For example, user A cannot force user B to join a room, and trying to force this state change directly will fail.
Adjusts the membership state for a user in a room. It is preferable to use the membership APIs
(`/rooms/<room id>/invite` etc) when performing membership actions rather than adjusting the
state directly as there are a restricted set of valid transformations. For example, user A cannot
force user B to join a room, and trying to force this state change directly will fail.
The following membership states are specified:
- `invite` - The user has been invited to join a room, but has not yet joined it. They may not participate in the room until they join.
- `join` - The user has joined the room (possibly after accepting an invite), and may participate in it.
- `leave` - The user was once joined to the room, but has since left (possibly by choice, or possibly by being kicked).
- `ban` - The user has been banned from the room, and is no longer allowed to join it until they are un-banned from the room (by having their membership state set to a value other than `ban`).
- `knock` - The user has knocked on the room, requesting permission to participate. They may not participate in the room until they join.
- `invite` - The user has been invited to join a room, but has not yet joined it. They may not
participate in the room until they join.
- `join` - The user has joined the room (possibly after accepting an invite), and may participate
in it.
- `leave` - The user was once joined to the room, but has since left (possibly by choice, or
possibly by being kicked).
- `ban` - The user has been banned from the room, and is no longer allowed to join it until they
are un-banned from the room (by having their membership state set to a value other than `ban`).
- `knock` - The user has knocked on the room, requesting permission to participate. They may not
participate in the room until they join.
The `third_party_invite` property will be set if this invite is an `invite` event and is the successor of an `m.room.third_party_invite` event, and absent otherwise.
The `third_party_invite` property will be set if this invite is an `invite` event and is the
successor of an [`m.room.third_party_invite`](/client-server-api/#mroomthird_party_invite) event,
and absent otherwise.
This event may also include an `invite_room_state` key inside the event's `unsigned` data.
If present, this contains an array of [stripped state events](/client-server-api/#stripped-state)
@ -59,63 +69,54 @@ properties:
- ban
type: string
is_direct:
description: Flag indicating if the room containing this event was created with the intention of being a direct chat. See [Direct Messaging](/client-server-api/#direct-messaging).
description: |-
Flag indicating if the room containing this event was created with the intention of being
a direct chat. See [Direct Messaging](/client-server-api/#direct-messaging).
type: boolean
join_authorised_via_users_server:
x-addedInMatrixVersion: "1.2"
type: string
description: |-
Usually found on `join` events, this field is used to denote which homeserver (through representation of a user with sufficient power level)
authorised the user's join. More information about this field can be found in the [Restricted Rooms Specification](/client-server-api/#restricted-rooms).
Usually found on `join` events, this field is used to denote which homeserver (through
representation of a user with sufficient power level) authorised the user's join. More
information about this field can be found in the [Restricted Rooms Specification](/client-server-api/#restricted-rooms).
Client and server implementations should be aware of the [signing implications](/rooms/v8/#authorization-rules) of including this
field in further events: in particular, the event must be signed by the server which
owns the user ID in the field. When copying the membership event's `content`
(for profile updates and similar) it is therefore encouraged to exclude this
field in the copy, as otherwise the event might fail event authorization.
Client and server implementations should be aware of the [signing implications](/rooms/v8/#authorization-rules)
of including this field in further events: in particular, the event must be signed by the
server which owns the user ID in the field. When copying the membership event's `content`
(for profile updates and similar) it is therefore encouraged to exclude this field in the
copy, as otherwise the event might fail event authorization.
reason:
x-addedInMatrixVersion: "1.1"
type: string
description: |-
Optional user-supplied text for why their membership has changed. For kicks and bans, this is typically the reason for the kick or ban.
For other membership changes, this is a way for the user to communicate their intent without having to send a message to the room, such
as in a case where Bob rejects an invite from Alice about an upcoming concert, but can't make it that day.
Optional user-supplied text for why their membership has changed. For kicks and bans,
this is typically the reason for the kick or ban. For other membership changes, this is a
way for the user to communicate their intent without having to send a message to the
room, such as in a case where Bob rejects an invite from Alice about an upcoming concert,
but can't make it that day.
Clients are not recommended to show this reason to users when receiving an invite due to the potential for spam and abuse. Hiding the
reason behind a button or other component is recommended.
Clients are not recommended to show this reason to users when receiving an invite due to
the potential for spam and abuse. Hiding the reason behind a button or other component is
recommended.
third_party_invite:
title: ThirdPartyInvite
description: |-
A third-party invite, if this `m.room.member` is the successor to an
[`m.room.third_party_invite`](/client-server-api/#mroomthird_party_invite)
event.
type: object
properties:
display_name:
description: A name which can be displayed to represent the user instead of their third-party identifier
description: |-
A name which can be displayed to represent the user instead of their
third-party identifier
type: string
signed:
description: 'A block of content which has been signed, which servers can use to verify the event. Clients should ignore this.'
properties:
mxid:
description: The invited matrix user ID. Must be equal to the user_id property of the event.
type: string
signatures:
description: 'A single signature from the verifying server, in the format specified by the Signing Events section of the server-server API.'
title: Signatures
type: object
additionalProperties:
type: object
additionalProperties:
type: string
token:
description: The token property of the containing third_party_invite object.
type: string
required:
- mxid
- signatures
- token
title: signed
type: object
$ref: components/signed_third_party_invite.yaml
required:
- display_name
- signed
title: Invite
type: object
required:
- membership
title: EventContent

View file

@ -17,8 +17,8 @@ properties:
"1.10": This property can act as a caption for the audio.
format:
description: |-
The format used in the `formatted_body`. Currently only
`org.matrix.custom.html` is supported.
The format used in the `formatted_body`. This is required if `formatted_body`
is specified. Currently only `org.matrix.custom.html` is supported.
type: string
x-addedInMatrixVersion: "1.10"
formatted_body:

View file

@ -16,8 +16,8 @@ properties:
type: string
format:
description: |-
The format used in the `formatted_body`. Currently only
`org.matrix.custom.html` is supported.
The format used in the `formatted_body`. This is required if `formatted_body`
is specified. Currently only `org.matrix.custom.html` is supported.
type: string
formatted_body:
description: |-

View file

@ -17,8 +17,8 @@ properties:
"1.10": This property can act as a caption for the file.
format:
description: |-
The format used in the `formatted_body`. Currently only
`org.matrix.custom.html` is supported.
The format used in the `formatted_body`. This is required if `formatted_body`
is specified. Currently only `org.matrix.custom.html` is supported.
type: string
x-addedInMatrixVersion: "1.10"
formatted_body:

View file

@ -17,8 +17,8 @@ properties:
"1.10": This property can act as a caption for the image.
format:
description: |-
The format used in the `formatted_body`. Currently only
`org.matrix.custom.html` is supported.
The format used in the `formatted_body`. This is required if `formatted_body`
is specified. Currently only `org.matrix.custom.html` is supported.
type: string
x-addedInMatrixVersion: "1.10"
formatted_body:

View file

@ -24,8 +24,8 @@ properties:
verification.
format:
description: |-
The format used in the `formatted_body`. Currently only
`org.matrix.custom.html` is supported.
The format used in the `formatted_body`. This is required if `formatted_body`
is specified. Currently only `org.matrix.custom.html` is supported.
type: string
formatted_body:
description: |-

View file

@ -16,8 +16,8 @@ properties:
type: string
format:
description: |-
The format used in the `formatted_body`. Currently only
`org.matrix.custom.html` is supported.
The format used in the `formatted_body`. This is required if `formatted_body`
is specified. Currently only `org.matrix.custom.html` is supported.
type: string
formatted_body:
description: |-

View file

@ -16,8 +16,8 @@ properties:
type: string
format:
description: |-
The format used in the `formatted_body`. Currently only
`org.matrix.custom.html` is supported.
The format used in the `formatted_body`. This is required if `formatted_body`
is specified. Currently only `org.matrix.custom.html` is supported.
type: string
formatted_body:
description: |-

View file

@ -17,8 +17,8 @@ properties:
"1.10": This property can act as a caption for the video.
format:
description: |-
The format used in the `formatted_body`. Currently only
`org.matrix.custom.html` is supported.
The format used in the `formatted_body`. This is required if `formatted_body`
is specified. Currently only `org.matrix.custom.html` is supported.
type: string
x-addedInMatrixVersion: "1.10"
formatted_body:

View file

@ -3,28 +3,56 @@ $schema: https://json-schema.org/draft/2020-12/schema
allOf:
- $ref: core-event-schema/state_event.yaml
description: "Acts as an `m.room.member` invite event, where there isn't a target user_id to invite. This event contains a token and a public key whose private key must be used to sign the token. Any user who can present that signature may use this invitation to join the target room."
description: |-
Acts as an `m.room.member` invite event, where there isn't a target user_id to
invite. This event contains a token and a public key whose private key must be
used to sign the token. Any user who can present that signature may use this
invitation to join the target room.
properties:
content:
properties:
display_name:
description: "A user-readable string which represents the user who has been invited. This should not contain the user's third-party ID, as otherwise when the invite is accepted it would leak the association between the matrix ID and the third-party ID."
description: |-
A user-readable string which represents the user who has been invited.
This should not contain the user's third-party ID, as otherwise when
the invite is accepted it would leak the association between the
matrix ID and the third-party ID.
type: string
key_validity_url:
description: "A URL which can be fetched, with querystring public_key=public_key, to validate whether the key has been revoked. The URL must return a JSON object containing a boolean property named 'valid'."
description: |-
A URL which can be fetched, with querystring public_key=public_key, to
validate whether the key has been revoked. The URL must return a JSON
object containing a boolean property named 'valid'.
type: string
format: uri
public_key:
description: A base64-encoded ed25519 key with which token must be signed (though a signature from any entry in public_keys is also sufficient). This exists for backwards compatibility.
description: |-
An Ed25519 key with which the token must be signed (though a signature
from any entry in `public_keys` is also sufficient).
The key is encoded using [Unpadded Base64](/appendices/#unpadded-base64),
using the standard or URL-safe alphabets.
This exists for backwards compatibility.
type: string
public_keys:
description: Keys with which the token may be signed.
items:
properties:
key_validity_url:
description: "An optional URL which can be fetched, with querystring public_key=public_key, to validate whether the key has been revoked. The URL must return a JSON object containing a boolean property named 'valid'. If this URL is absent, the key must be considered valid indefinitely."
description: |-
An optional URL which can be fetched, with querystring
`public_key=<public_key>`, to validate whether the key has been
revoked. The URL must return a JSON object containing a boolean
property named `valid`. If this URL is absent, the key must be
considered valid indefinitely.
type: string
public_key:
description: A base-64 encoded ed25519 key with which token may be signed.
description: |-
An Ed25519 key with which the token may be signed.
The key is encoded using [Unpadded Base64](/appendices/#unpadded-base64),
using the standard or URL-safe alphabets.
type: string
required:
- public_key
@ -37,11 +65,15 @@ properties:
- public_key
type: object
state_key:
description: 'The token, of which a signature must be produced in order to join the room.'
description: |-
The token, of which a signature must be produced in order to join the
room.
type: string
type:
enum:
- m.room.third_party_invite
type: string
title: 'An invitation to a room issued to a third-party identifier, rather than a matrix user ID.'
title: |-
An invitation to a room issued to a third-party identifier, rather than a
matrix user ID.
type: object

View file

@ -3,13 +3,41 @@ $schema: https://json-schema.org/draft/2020-12/schema
allOf:
- $ref: core-event-schema/state_event.yaml
description: 'A topic is a short message detailing what is currently being discussed in the room. It can also be used as a way to display extra information about the room, which may not be suitable for the room name. The room topic can also be set when creating a room using `/createRoom` with the `topic` key.'
description: |-
A topic is a short message detailing what is currently being discussed
in the room. It can also be used as a way to display extra information
about the room, which may not be suitable for the room name. The room
topic can also be set when creating a room using
[`/createRoom`](client-server-api/#post_matrixclientv3createroom), either
with the `topic` key or by specifying a full event in `initial_state`.
If the `topic` property is absent, null, or empty then the topic is unset. In other words,
an empty `topic` property effectively resets the room to having no topic.
In order to prevent formatting abuse in room topics, clients SHOULD
limit the length of topics during both entry and display, for instance,
by capping the number of displayed lines. Additionally, clients SHOULD
ignore things like headings and enumerations (or format them as regular
text).
properties:
content:
properties:
topic:
description: The topic text.
description: |-
The topic in plain text.
This SHOULD duplicate the content of the `text/plain`
representation in `m.topic` if any exists.
type: string
m.topic:
type: object
title: TopicContentBlock
x-addedInMatrixVersion: "1.15"
description: |-
Textual representation of the room topic in different mimetypes.
properties:
m.text:
$ref: components/m_text_content_block.yaml
required:
- topic
type: object

View file

@ -0,0 +1,140 @@
# Copyright 2025 The Matrix.org Foundation C.I.C.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
title: OAuthClientMetadata
type: object
description: |-
This definition of the metadata specifies only the fields that are meaningful
in the context of the Matrix specification. All the possible values are
registered in the [OAuth Dynamic Client Registration Metadata registry](https://www.iana.org/assignments/oauth-parameters/oauth-parameters.xhtml#client-metadata),
and normative definitions of them are available in their respective RFCs.
properties:
client_uri:
type: string
format: uri
description: |-
A URL to a valid web page that SHOULD give the user more information about
the client.
This URL MUST use the `https` scheme and SHOULD NOT require authentication
to access. It MUST NOT use a user or password in the authority component
of the URI.
The server MAY reject client registrations if this field is invalid or
missing.
This URI is a common base for all the other URIs in the metadata: those
MUST be either on the same host or on a subdomain of the host of the
`client_uri`. The port number, path and query components MAY be different.
For example, if the `client_uri` is `https://example.com/`, then one of
the `redirect_uris` can be `https://example.com/callback` or
`https://app.example.com/callback`, but not `https://app.com/callback`.
client_name:
type: string
description: |-
Human-readable name of the client to be presented to the user.
This field can be [localized](/client-server-api/#metadata-localization).
logo_uri:
type: string
format: uri
description: |-
URL that references a logo for the client.
This URL MUST use the `https` scheme.
This field can be [localized](/client-server-api/#metadata-localization).
tos_uri:
type: string
format: uri
description: |-
URL that points to a human-readable terms of service document for the
client.
This URL MUST use the `https` scheme and SHOULD NOT require authentication
to access. It MUST NOT use a user or password in the authority component
of the URI.
If this field is set, the server SHOULD show or link to this URL.
This field can be [localized](/client-server-api/#metadata-localization).
policy_uri:
type: string
format: uri
description: |-
URL that points to a human-readable policy document for the client.
This URL MUST use the `https` scheme and SHOULD NOT require authentication
to access. It MUST NOT use a user or password in the authority component
of the URI.
If this field is set, the server SHOULD show or link to this URL.
This field can be [localized](/client-server-api/#metadata-localization).
redirect_uris:
type: array
description: |-
Array of redirection URIs for use in redirect-based flows.
At least one URI is required to use the authorization code grant.
The server MUST perform [validation on redirect URIs](/client-server-api/#redirect-uri-validation).
items:
type: string
format: uri
description: A redirection URI.
response_types:
type: array
description: |-
Array of the OAuth 2.0 response types that the client may use.
This MUST include the `code` value to use the authorization code grant.
The server MUST ignore values that it does not understand.
items:
type: string
description: A response type that the client may use.
grant_types:
type: array
description: |-
Array of the OAuth 2.0 grant types that the client may use.
This MUST include:
- the `authorization_code` value to use the authorization code grant,
- the `refresh_token` value to use the refresh token grant.
The server MUST ignore values that it does not understand.
items:
type: string
description: A grant type that the client may use.
token_endpoint_auth_method:
type: string
description: |-
String indicator of the requested authentication method for the token
endpoint.
The homeserver MUST support the `none` value, as most Matrix clients are
client-side only, do not have a server component, and therefore are public
clients.
application_type:
type: string
description: |-
Kind of the application.
The homeserver MUST support the `web` and `native` values to be able to
perform [redirect URI validation](/client-server-api/#redirect-uri-validation).
Defaults to `web` if omitted.
required:
- client_uri

View file

@ -51,6 +51,11 @@ mx-room-id:
url: appendices#room-ids
# regex: "^!"
mx-room-alias:
title: Room Alias
url: appendices#room-aliases
# regex: "^#"
mx-server-name:
title: Server Name
url: appendices#server-name

View file

@ -60,6 +60,11 @@ General
you have at home. "identity server" is clear, whereas "identityserver" is
horrible.
* When talking about a user's "display name", it is spelt as two words. In
identifiers such as within the content of an ``m.room.member`` event, it is
spelt as a single word, ``displayname``. (There are some historical exceptions
to this where the identifier is spelt ``display_name``.)
* Lists should:
* Be introduced with a colon.
@ -84,12 +89,12 @@ Changes between spec versions
Sections should reference the Matrix spec version they were added/changed in. This
is often a guess at what the next version will be - please use the currently released
version with a minor version bump as the referenced version. For example, if the
current version is `v1.1` then annotate your changes with `v1.2`.
current version is ``v1.1`` then annotate your changes with ``v1.2``.
"Added/changed in" tags can be documented as the following:
* `{{% added-in v="1.2" %}}` or `{{% changed-in v="1.2" %}}` within Markdown documents.
* `x-addedInMatrixVersion` and `x-changedInMatrixVersion` within OpenAPI.
* ``{{% added-in v="1.2" %}}`` or ``{{% changed-in v="1.2" %}}`` within Markdown documents.
* ``x-addedInMatrixVersion`` and ``x-changedInMatrixVersion`` within OpenAPI.
OpenAPI
~~~~~~~
@ -185,4 +190,4 @@ Describing grammar
Use `RFC5234-style ABNF <https://datatracker.ietf.org/doc/html/rfc5234>`_ when describing
the grammar for something in the spec, such as user IDs or server names. Use lowercase
and underscore-delimited element names (`user_id`, not `UserID` or `user-id`).
and underscore-delimited element names (``user_id``, not ``UserID`` or ``user-id``).

View file

@ -32,6 +32,35 @@ import yaml
scripts_dir = os.path.dirname(os.path.abspath(__file__))
api_dir = os.path.join(os.path.dirname(scripts_dir), "data", "api")
# Finds a Hugo shortcode in a string.
#
# A shortcode is defined as (newlines and whitespaces for presentation purpose):
#
# {{%
# <zero or more whitespaces>
# <name of shortcode>
# (optional <one or more whitespaces><list of parameters>)
# <zero or more whitespaces>
# %}}
#
# With:
#
# * <name of shortcode>: any word character and `-` and `/`. `re.ASCII` is used to only match
# ASCII characters in the name.
# * <list of parameters>: any character except `}`, must not start or end with a
# whitespace.
shortcode_regex = re.compile(r"""\{\{\% # {{%
\s* # zero or more whitespaces
(?P<name>[\w/-]+) # name of shortcode
(?:\s+(?P<params>[^\s\}][^\}]+[^\s\}]))? # optional list of parameters
\s* # zero or more whitespaces
\%\}\} # %}}""", re.ASCII | re.VERBOSE)
# Parses the parameters of a Hugo shortcode.
#
# For simplicity, this currently only supports the `key="value"` format.
shortcode_params_regex = re.compile(r"(?P<key>\w+)=\"(?P<value>[^\"]+)\"", re.ASCII)
def prefix_absolute_path_references(text, base_url):
"""Adds base_url to absolute-path references.
@ -44,17 +73,90 @@ def prefix_absolute_path_references(text, base_url):
"""
return text.replace("](/", "]({}/".format(base_url))
def edit_links(node, base_url):
"""Finds description nodes and makes any links in them absolute."""
def replace_match(match, replacement):
"""Replaces the regex match by the replacement in the text."""
return match.string[:match.start()] + replacement + match.string[match.end():]
def replace_shortcode(shortcode):
"""Replaces the shortcode by a Markdown fallback in the text.
The supported shortcodes are:
* boxes/note, boxes/rationale, boxes/warning
* added-in, changed-in
All closing tags (`{{ /shortcode }}`) are replaced with the empty string.
"""
if shortcode['name'].startswith("/"):
# This is the end of the shortcode, just remove it.
return replace_match(shortcode, "")
# Parse the parameters of the shortcode
params = {}
if shortcode['params']:
for param in shortcode_params_regex.finditer(shortcode['params']):
if param['key']:
params[param['key']] = param['value']
match shortcode['name']:
case "boxes/note":
return replace_match(shortcode, "**NOTE:** ")
case "boxes/rationale":
return replace_match(shortcode, "**RATIONALE:** ")
case "boxes/warning":
return replace_match(shortcode, "**WARNING:** ")
case "added-in":
version = params['v']
if not version:
raise ValueError("Missing parameter `v` for `added-in` shortcode")
return replace_match(shortcode, f"**[Added in `v{version}`]** ")
case "changed-in":
version = params['v']
if not version:
raise ValueError("Missing parameter `v` for `changed-in` shortcode")
return replace_match(shortcode, f"**[Changed in `v{version}`]** ")
case _:
raise ValueError("Unknown shortcode", shortcode['name'])
def find_and_replace_shortcodes(text):
"""Finds Hugo shortcodes and replaces them by a Markdown fallback.
The supported shortcodes are:
* boxes/note, boxes/rationale, boxes/warning
* added-in, changed-in
"""
# We use a `while` loop with `search` instead of a `for` loop with
# `finditer`, because as soon as we start replacing text, the
# indices of the match are invalid.
while shortcode := shortcode_regex.search(text):
text = replace_shortcode(shortcode)
return text
def edit_descriptions(node, base_url):
"""Finds description nodes and apply fixes to them.
The fixes that are applied are:
* Make links absolute
* Replace Hugo shortcodes
"""
if isinstance(node, dict):
for key in node:
if isinstance(node[key], str):
node[key] = prefix_absolute_path_references(node[key], base_url)
node[key] = find_and_replace_shortcodes(node[key])
else:
edit_links(node[key], base_url)
edit_descriptions(node[key], base_url)
elif isinstance(node, list):
for item in node:
edit_links(item, base_url)
edit_descriptions(item, base_url)
parser = argparse.ArgumentParser(
"dump-openapi.py - assemble the OpenAPI specs into a single JSON file"
@ -164,7 +266,7 @@ for filename in os.listdir(selected_api_dir):
if untagged != 0:
print("{} untagged operations, you may want to look into fixing that.".format(untagged))
edit_links(output, base_url)
edit_descriptions(output, base_url)
print("Generating %s" % output_file)