Compare commits

...

37 commits

Author SHA1 Message Date
Tom Foster 63e2928dbf
Merge 6183f2410f into ca9c376076 2025-05-09 12:22:07 -04:00
Kim Brose ca9c376076
Clarify Well-Known URIs (#2140)
Some checks failed
Spec / 🔎 Validate OpenAPI specifications (push) Has been cancelled
Spec / 🔎 Check Event schema examples (push) Has been cancelled
Spec / 🔎 Check OpenAPI definitions examples (push) Has been cancelled
Spec / 🔎 Check JSON Schemas inline examples (push) Has been cancelled
Spec / ⚙️ Calculate baseURL for later jobs (push) Has been cancelled
Spec / 📢 Run towncrier for changelog (push) Has been cancelled
Spell Check / Spell Check with Typos (push) Has been cancelled
Spec / 🐍 Build OpenAPI definitions (push) Has been cancelled
Spec / 📖 Build the spec (push) Has been cancelled
Spec / 🔎 Validate generated HTML (push) Has been cancelled
Spec / 📖 Build the historical backup spec (push) Has been cancelled
* Clarify Well-Known URIs

Signed-off-by: HarHarLinks <2803622+HarHarLinks@users.noreply.github.com>

* Fix section link

---------

Signed-off-by: HarHarLinks <2803622+HarHarLinks@users.noreply.github.com>
2025-05-08 13:55:51 +02:00
Kévin Commaille fe46e0c363
Replace Hugo shortcodes in OpenAPI output (#2088)
Signed-off-by: Kévin Commaille <zecakeh@tedomum.fr>
2025-05-08 09:29:32 +00:00
Andrew Morgan a8c326962a
Add a note to the federation invite endpoints that invites can be sent twice (#2067)
... as this may be non-obvious when implementing behaviour that is triggered by an incoming invite
event.

See https://github.com/matrix-org/matrix-spec/issues/2062 for more context.

Co-authored-by: Kévin Commaille <76261501+zecakeh@users.noreply.github.com>
2025-05-08 10:09:45 +01:00
Tom Foster 6183f2410f Clarify value validation requirements 2025-02-21 10:32:28 +00:00
Tom Foster dd4ea948b6 Clarify why avatar_url and displayname can't be returned as null 2025-02-21 09:53:43 +00:00
Tom Foster 50eab3501e Standardise line-wrapping and update avatar_url format to mx-mxc-uri 2025-02-21 09:28:46 +00:00
Tom Foster 37b1362bc1 Attempt to describe variable payload content 2025-02-20 18:08:10 +00:00
Tom Foster d8cc250d20 Tag x-addedInMatrixVersion on additionalProperties in entire profile GET 2025-02-20 17:02:23 +00:00
Tom Foster b5e2edf2e5 Add x-addedInMatrixVersion 2025-02-20 16:59:44 +00:00
Tom Foster 7ef1d9d0ec Add x-changedInMatrixVersion 2025-02-20 16:56:53 +00:00
Tom Foster 3a5e5555fa Correct PUT/GET payload definitions 2025-02-20 16:48:20 +00:00
Tom Foster 9889fe3584 Use more accessible terminology than "glob" 2025-02-20 16:40:07 +00:00
Tom Foster 013502b0c0 Mention replacement for m.set_displayname and m.set_avatar_url capability deprecation 2025-02-20 16:35:26 +00:00
Tom Foster 9859e20927 Don't use reference for capability. 2025-02-20 16:31:27 +00:00
Tom Foster 7a3b0c0804 Clarify in change log that m.set_avatar_url and m.set_displayname capabilities are now deprecated 2025-02-14 15:03:17 +00:00
Tom Foster 0b0942d192 Clarify capability lists should support wildcards 2025-02-14 15:00:53 +00:00
Tom Foster 1cc93ec951 Attempt to make descriptions look better in HTML rendered spec 2025-02-14 14:53:29 +00:00
Tom Foster 79af78022e Camel case for endpoint variables 2025-02-14 13:47:49 +00:00
Tom Foster 17af55ddce Fix broken link 2025-02-14 13:30:33 +00:00
Tom Foster 79a1cded02 Remove reference to spec version in m.profile_field capability 2025-02-14 12:57:51 +00:00
Tom Foster 76b48e25d0 Specify CNIG pattern for custom fields 2025-02-14 12:56:16 +00:00
Tom Foster 5d5b561140 Deprecate m.set_displayname and m.set_avatar_url capabilities 2025-02-14 12:47:14 +00:00
Tom Foster 9327793007 Inline information from MSC4133, remove links 2025-02-14 12:39:19 +00:00
Tom Foster f3c269d951 Added capability 2025-02-14 12:20:25 +00:00
Tom Foster 3311b084bf Alphabetise avatar_url and displayname and remove redundant descriptions on displayname 2025-02-14 12:03:49 +00:00
Tom Foster 992cf9dc35 Clarify null behaviour for PUT and DELETE 2025-02-14 11:53:19 +00:00
Tom Foster 4f8999be0a Tweak wording on full profile GET 2025-02-14 11:32:39 +00:00
Tom Foster 82adcec491 Clarify avatar_url should be MXC 2025-02-14 11:21:45 +00:00
Tom Foster 41c64c877b Linkify MSC4133 in change log 2025-02-14 11:16:40 +00:00
Tom Foster 8e9874ad22 Simplify change log 2025-02-14 11:15:00 +00:00
Tom Foster ee9b5ddcca Correct types and errors 2025-02-14 11:02:11 +00:00
Tom Foster 59d2c62d2d Link to MSC4133 in endpoint descriptions 2025-02-14 10:40:09 +00:00
Tom Foster b2e122f308 Update changelog from clarification to feature 2025-02-14 10:12:29 +00:00
Tom Foster 1fc01189f3 2071 change log 2025-02-14 09:59:22 +00:00
Tom Foster 212377e393
Merge branch 'matrix-org:main' into MSC4133 2025-02-14 09:50:59 +00:00
Tom Foster fdc012ac01 Describe MSC4133 profile endpoint changes 2025-02-13 17:54:21 +00:00
17 changed files with 394 additions and 162 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"
@ -172,7 +173,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"

View file

@ -0,0 +1 @@
Feature: Update profile endpoints to become generic to support [MSC4133](https://github.com/matrix-org/matrix-spec-proposals/pull/4133) extended fields. Extended profile fields are now supported via the new `m.profile_fields` capability, which deprecates the previous `m.set_avatar_url` and `m.set_displayname` capabilities. Stabilised keys are explicitly enumerated, and custom keys must conform to the Common Namespaced Identifier Grammar.

View file

@ -0,0 +1 @@
Clarify that Well-Known URIs are available on the server name's hostname. Contributed by @HarHarLinks.

View file

@ -0,0 +1 @@
Replace Hugo shortcodes in OpenAPI output.

View file

@ -0,0 +1 @@
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.

View file

@ -0,0 +1 @@
Clarify that Well-Known URIs are available on the server name's hostname. Contributed by @HarHarLinks.

View file

@ -371,15 +371,23 @@ valid data was obtained, but no server is available to serve the client.
No further guess should be attempted and the user should make a
conscientious decision what to do next.
### Well-known URI
### Well-known URIs
Matrix facilitates automatic discovery for the Client-Server API base URL and more via the
[RFC 8615](https://datatracker.ietf.org/doc/html/rfc8615) "Well-Known URI" method.
This method uses JSON files at a predetermined location on the root path `/.well-known/` to
specify parameter values.
{{% boxes/note %}}
Diverging from the rest of the endpoints in the Client-Server spec, these files can not be provided
on the base URL that the Client-Server API is reachable on, as it is yet to be discovered.
Instead, they can be reached via HTTPS on the [server name](/appendices/#server-name)'s hostname as domain.
Servers hosting the `.well-known` JSON file SHOULD offer CORS headers,
as per the [CORS](#web-browser-clients) section in this specification.
{{% /boxes/note %}}
The `.well-known` method uses a JSON file at a predetermined location to
specify parameter values. The flow for this method is as follows:
The flow for auto-discovery is as follows:
1. Extract the [server name](/appendices/#server-name) from the user's Matrix ID by splitting the
Matrix ID at the first colon.
@ -415,10 +423,17 @@ specify parameter values. The flow for this method is as follows:
{{% http-api spec="client-server" api="wellknown" %}}
{{% http-api spec="client-server" api="versions" %}}
{{% http-api spec="client-server" api="support" %}}
### API Versions
Upon connecting, the Matrix client and server need to negotiate which version of the specification
they commonly support, as the API evolves over time. The server advertises its supported versions
and optionally unstable features to the client, which can then go on to make requests to the
endpoints it supports.
{{% http-api spec="client-server" api="versions" %}}
## Client Authentication
Most API endpoints require the user to identify themselves by presenting

View file

@ -63,7 +63,7 @@ for sending events:
The following API endpoints are allowed to be accessed by guest accounts
for their own account maintenance:
* [PUT /profile/{userId}/displayname](#put_matrixclientv3profileuseriddisplayname)
* [PUT /profile/{userId}/{key_name}](#put_matrixclientv3profileuseridkeyname)
* [GET /devices](#get_matrixclientv3devices)
* [GET /devices/{deviceId}](#get_matrixclientv3devicesdeviceid)
* [PUT /devices/{deviceId}](#put_matrixclientv3devicesdeviceid)

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

View file

@ -73,11 +73,17 @@ paths:
- default
- available
m.set_displayname:
deprecated: true
$ref: '#/components/schemas/booleanCapability'
description: Capability to indicate if the user can change their display name.
description: |
**Deprecated:** Capability to indicate if the user can change their display name.
Please refer to `m.profile_fields` for extended profile management.
m.set_avatar_url:
deprecated: true
$ref: '#/components/schemas/booleanCapability'
description: Capability to indicate if the user can change their avatar.
description: |
**Deprecated:** Capability to indicate if the user can change their avatar.
Please refer to `m.profile_fields` for extended profile management.
m.3pid_changes:
$ref: '#/components/schemas/booleanCapability'
description: Capability to indicate if the user can change 3PID associations
@ -86,6 +92,37 @@ paths:
$ref: '#/components/schemas/booleanCapability'
description: Capability to indicate if the user can generate tokens to log further
clients into their account.
m.profile_fields:
x-addedInMatrixVersion: "1.14"
type: object
title: ProfileFieldsCapability
description: Capability to indicate if the user can set or modify extended profile fields.
If absent, clients should assume custom profile fields are supported.
properties:
allowed:
type: array
description: List of allowed additional custom profile field keys. A `*` can be used as a
wildcard to match any sequence of characters. This list takes precedence over the
disallowed list if both are provided.
items:
type: string
example:
- "m.example_field"
- "org.example/job_title"
disallowed:
type: array
description: List of disallowed additional custom profile field keys. A `*` can be used as
a wildcard to match any sequence of characters. Ignored if an allowed list is provided.
items:
type: string
example:
- "org.example.secret_field"
enabled:
type: boolean
description: True if the user can set or modify any extended profile fields, false otherwise.
example: true
required:
- enabled
examples:
response:
value: {

View file

@ -16,48 +16,105 @@ info:
title: Matrix Client-Server Profile API
version: 1.0.0
paths:
"/profile/{userId}/displayname":
"/profile/{userId}/{keyName}":
put:
summary: Set the user's display name.
x-changedInMatrixVersion:
"1.14": Endpoint now accepts variable `keyName` parameter.
summary: Set a profile field for a user.
description: |-
This API sets the given user's display name. You must have permission to
set this user's display name, e.g. you need to have their `access_token`.
operationId: setDisplayName
Set or update a profile field for a user. Must be authenticated with an
access token authorised to make changes. Servers may impose size limits
on individual fields, and the total profile must be under 64 KiB.
**Note**: Setting a field to `null` keeps the key but with a `null` value,
which some servers may reject. To remove a field completely, use the
`DELETE` endpoint instead.
operationId: setProfileField
security:
- accessTokenQuery: []
- accessTokenBearer: []
parameters:
- in: path
name: userId
description: The user whose display name to set.
description: The user whose profile field to set.
required: true
example: "@alice:example.com"
schema:
type: string
- in: path
name: keyName
description: The profile field key name to set. It must be either
`avatar_url`, `displayname`, or a custom field following the
[Common Namespaced Identifier Grammar](/appendices/#common-namespaced-identifier-grammar).
required: true
example: "displayname"
schema:
type: string
pattern: '^(avatar_url|displayname|[a-z][a-z0-9_]*(\.[a-z][a-z0-9_]*)+)$'
requestBody:
description: A JSON object containing the property whose name matches
the `keyName` specified in the URL. See `additionalProperties` for
further details.
required: true
content:
application/json:
schema:
type: object
example: {
"displayname": "Alice Margatroid"
}
properties:
displayname:
type: string
description: The new display name for this user.
description: The new display name information.
required: true
minProperties: 1
additionalProperties:
description: The JSON object must include a property whose key
matches the `keyName` specified in the URL. For `avatar_url`,
the value must be an MXC URI string. For `displayname`, the value
must be a string. For custom keys, any JSON type is allowed -
servers may not validate these values, but clients should follow
the format defined for that key.
example: { "displayname": "Alice Wonderland" }
responses:
"200":
description: The display name was set.
description: The profile field was set.
content:
application/json:
schema:
type: object # empty json object
type: object # empty JSON object
examples:
response:
value: {}
"400":
description: The request is malformed, contains invalid JSON, missing
a required parameter, specifies an invalid key, or exceeds allowed
size limits.
content:
application/json:
schema:
$ref: definitions/errors/error.yaml
examples:
bad_json:
value:
{
"errcode": "M_BAD_JSON",
"error": "Malformed JSON payload.",
}
invalid_key:
value:
{
"errcode": "M_INVALID_PARAM",
"error": "Invalid profile key.",
}
"403":
description: The server is unwilling to perform the operation, either
due to insufficient permissions or because profile modifications
are disabled.
content:
application/json:
schema:
$ref: definitions/errors/error.yaml
examples:
forbidden:
value:
{
"errcode": "M_FORBIDDEN",
"error": "Profile modification is not permitted.",
}
"429":
description: This request was rate-limited.
content:
@ -67,98 +124,133 @@ paths:
tags:
- User data
get:
summary: Get the user's display name.
description: |-
Get the user's display name. This API may be used to fetch the user's
own displayname or to query the name of other users; either locally or
on remote homeservers.
operationId: getDisplayName
x-changedInMatrixVersion:
"1.14": Endpoint now accepts variable `keyName` parameter.
summary: Get a profile field for a user.
description: Get the value of a profile field for a user. Any individual
field must be within the total profile limit of 64 KiB.
operationId: getProfileField
parameters:
- in: path
name: userId
description: The user whose display name to get.
description: The user whose profile field to get.
required: true
example: "@alice:example.com"
schema:
type: string
- in: path
name: keyName
description: The profile field key name to retrieve. It must be either
`avatar_url`, `displayname`, or a custom field following the
[Common Namespaced Identifier Grammar](/appendices/#common-namespaced-identifier-grammar).
required: true
example: "displayname"
schema:
type: string
pattern: '^(avatar_url|displayname|[a-z][a-z0-9_]*(\.[a-z][a-z0-9_]*)+)$'
responses:
"200":
description: The display name for this user.
description: The profile field value was retrieved.
content:
application/json:
schema:
type: object
properties:
displayname:
type: string
description: The user's display name if they have set one, otherwise not
present.
minProperties: 1
additionalProperties:
description: The JSON response includes a property whose key
matches the `keyName` specified in the URL. For `avatar_url`,
the value will be an MXC URI string. For `displayname`, the
value will be a string. For custom keys, any JSON type is
possible - clients should expect the format defined for that key.
examples:
response:
value: {
"displayname": "Alice Margatroid"
}
value: { "displayname": "Alice" }
"403":
x-addedInMatrixVersion: "1.12"
description: The server is unwilling to disclose whether the user exists and/or
has a display name.
description: The server is unwilling to disclose whether the user
exists and/or has the specified profile field.
content:
application/json:
schema:
$ref: definitions/errors/error.yaml
examples:
response:
value: {
"errcode": "M_FORBIDDEN",
"error": "Profile lookup is disabled on this homeserver"
}
value:
{
"errcode": "M_FORBIDDEN",
"error": "Profile lookup is disabled on this homeserver",
}
"404":
description: There is no display name for this user or this user does not exist.
description: There is no profile field with this key for this user, or
the user does not exist.
tags:
- User data
"/profile/{userId}/avatar_url":
put:
summary: Set the user's avatar URL.
description: |-
This API sets the given user's avatar URL. You must have permission to
set this user's avatar URL, e.g. you need to have their `access_token`.
operationId: setAvatarUrl
delete:
x-addedInMatrixVersion: "1.14"
summary: Remove a profile field from a user.
description: Remove a specific field from a user's profile.
operationId: deleteProfileField
security:
- accessTokenQuery: []
- accessTokenBearer: []
parameters:
- in: path
name: userId
description: The user whose avatar URL to set.
description: The user whose profile field to delete.
required: true
example: "@alice:example.com"
schema:
type: string
requestBody:
content:
application/json:
schema:
type: object
example: {
"avatar_url": "mxc://matrix.org/wefh34uihSDRGhw34"
}
properties:
avatar_url:
type: string
format: uri
description: The new avatar URL for this user.
description: The new avatar information.
required: true
- in: path
name: keyName
description: The profile field key name to delete. It must be either
`avatar_url`, `displayname`, or a custom field following the
[Common Namespaced Identifier Grammar](/appendices/#common-namespaced-identifier-grammar).
required: true
example: "displayname"
schema:
type: string
pattern: '^(avatar_url|displayname|[a-z][a-z0-9_]*(\.[a-z][a-z0-9_]*)+)$'
responses:
"200":
description: The avatar URL was set.
description: The profile field was deleted.
content:
application/json:
schema:
type: object # empty json object
type: object
examples:
response:
value: {}
"400":
description: The request is malformed, contains invalid JSON, or
specifies an invalid key.
content:
application/json:
schema:
$ref: definitions/errors/error.yaml
examples:
bad_json:
value:
{ "errcode": "M_BAD_JSON", "error": "Malformed request." }
invalid_key:
value:
{
"errcode": "M_INVALID_PARAM",
"error": "Invalid profile key.",
}
"403":
description: The user is not authorised to delete this profile field.
content:
application/json:
schema:
$ref: definitions/errors/error.yaml
examples:
forbidden:
value:
{
"errcode": "M_FORBIDDEN",
"error": "Profile deletion is not permitted.",
}
"429":
description: This request was rate-limited.
content:
@ -167,63 +259,15 @@ paths:
$ref: definitions/errors/rate_limited.yaml
tags:
- User data
get:
summary: Get the user's avatar URL.
description: |-
Get the user's avatar URL. This API may be used to fetch the user's
own avatar URL or to query the URL of other users; either locally or
on remote homeservers.
operationId: getAvatarUrl
parameters:
- in: path
name: userId
description: The user whose avatar URL to get.
required: true
example: "@alice:example.com"
schema:
type: string
responses:
"200":
description: The avatar URL for this user.
content:
application/json:
schema:
type: object
properties:
avatar_url:
type: string
format: uri
description: The user's avatar URL if they have set one, otherwise not present.
examples:
response:
value: {
"avatar_url": "mxc://matrix.org/SDGdghriugerRg"
}
"403":
x-addedInMatrixVersion: "1.12"
description: The server is unwilling to disclose whether the user exists and/or
has an avatar URL.
content:
application/json:
schema:
$ref: definitions/errors/error.yaml
examples:
response:
value: {
"errcode": "M_FORBIDDEN",
"error": "Profile lookup is disabled on this homeserver"
}
"404":
description: There is no avatar URL for this user or this user does not exist.
tags:
- User data
"/profile/{userId}":
get:
summary: Get this user's profile information.
summary: Get all profile information for a user.
description: |-
Get the combined profile information for this user. This API may be used
to fetch the user's own profile information or other users; either
locally or on remote homeservers.
Get the complete profile for a user. The response includes `avatar_url`
and `displayname` (unless set to `null`, as they can only be strings)
plus any custom profile fields.
**Note**: The complete profile must be under 64 KiB.
operationId: getUserProfile
parameters:
- in: path
@ -243,45 +287,49 @@ paths:
properties:
avatar_url:
type: string
format: uri
description: The user's avatar URL if they have set one, otherwise not present.
format: mx-mxc-uri
description: "Avatar URL value (MXC URI format)."
displayname:
type: string
description: The user's display name if they have set one, otherwise not
present.
additionalProperties:
x-addedInMatrixVersion: "1.14"
description: Any additional profile field value; may be any
valid JSON type, with keys following the
[Common Namespaced Identifier Grammar](/appendices/#common-namespaced-identifier-grammar).
examples:
response:
value: {
"avatar_url": "mxc://matrix.org/SDGdghriugerRg",
"displayname": "Alice Margatroid"
}
value:
{
"avatar_url": "mxc://matrix.org/SDGdghriugerRg",
"displayname": "Alice Margatroid",
"m.example_field": "custom_value",
}
"403":
x-addedInMatrixVersion: "1.2"
description: The server is unwilling to disclose whether the user exists and/or
has profile information.
description: The server is unwilling to disclose whether the user
exists and/or has profile information.
content:
application/json:
schema:
$ref: definitions/errors/error.yaml
examples:
response:
value: {
"errcode": "M_FORBIDDEN",
"error": "Profile lookup is disabled on this homeserver"
}
value:
{
"errcode": "M_FORBIDDEN",
"error": "Profile lookup is disabled on this homeserver",
}
"404":
description: There is no profile information for this user or this user does not
exist.
description: There is no profile information for this user or this
user does not exist.
content:
application/json:
schema:
$ref: definitions/errors/error.yaml
examples:
response:
value: {
"errcode": "M_NOT_FOUND",
"error": "Profile not found"
}
value:
{ "errcode": "M_NOT_FOUND", "error": "Profile not found" }
tags:
- User data
servers:

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

@ -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

@ -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

@ -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

@ -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)