Merge remote-tracking branch 'origin/master' into erikj/event_context_api

pull/977/head
Erik Johnston 9 years ago
commit fda07e0d41

@ -1,41 +0,0 @@
.. This file is automatically processed by the templating system. To make it
.. happy, you MUST use '=' as the title underline and you MUST stick the version
.. in the title. The version MUST follow the numbering format
.. "v<num>.<num>.<num>" - You cannot use a-z. If the templating system fails to
.. find the right info, it will be treated as a test failure and so will show up
.. in Jenkins. Comments like this are ignored by both RST and the templating
.. system. Add the newest release notes beneath this comment.
Specification changes in v0.2.0 (2015-10-02)
============================================
This update fundamentally restructures the specification. The specification has
been split into more digestible "modules" which each describe a particular
function (e.g. typing). This was done in order make the specification easier to
maintain and help define which modules are mandatory for certain types
of clients. Types of clients along with the mandatory modules can be found in a
new "Feature Profiles" section. This update also begins to aggressively
standardise on using Swagger and JSON Schema to document HTTP endpoints and
Events respectively. It also introduces a number of new concepts to Matrix.
Additions:
- New section: Feature Profiles.
- New section: Receipts.
- New section: Room history visibility.
- New event: ``m.receipt``.
- New event: ``m.room.canonical_alias``
- New event: ``m.room.history_visibility``
- New keys: ``/createRoom`` - allows room "presets" using ``preset`` and
``initial_state`` keys.
- New endpoint: ``/tokenrefresh`` - Related to refreshing access tokens.
Modifications:
- Convert most of the older HTTP APIs to Swagger documentation.
- Convert most of the older event formats to JSON Schema.
- Move selected client-server sections to be "Modules".
Specification changes in v0.1.0 (2015-06-01)
============================================
- First numbered release.
- Restructure the format of Event information. Add more information.
- Restructure the format of the Client-Server HTTP APIs.

@ -49,7 +49,8 @@ def check_parameter(filepath, request, parameter):
# Setting the 'id' tells jsonschema where the file is so that it
# can correctly resolve relative $ref references in the schema
schema['id'] = fileurl
jsonschema.validate(example, schema)
resolver = jsonschema.RefResolver(filepath, schema, handlers={"file": load_yaml})
jsonschema.validate(example, schema, resolver=resolver)
except Exception as e:
raise ValueError("Error validating JSON schema for %r" % (
request
@ -76,7 +77,8 @@ def check_response(filepath, request, code, response):
# Setting the 'id' tells jsonschema where the file is so that it
# can correctly resolve relative $ref references in the schema
schema['id'] = fileurl
jsonschema.validate(example, schema)
resolver = jsonschema.RefResolver(filepath, schema, handlers={"file": load_yaml})
jsonschema.validate(example, schema, resolver=resolver)
except Exception as e:
raise ValueError("Error validating JSON schema for %r %r" % (
request, code
@ -103,6 +105,14 @@ def check_swagger_file(filepath):
check_response(filepath, request, code, response)
def load_yaml(path):
if not path.startswith("file:///"):
raise Exception("Bad ref: %s" % (path,))
path = path[len("file://"):]
with open(path, "r") as f:
return yaml.load(f)
if __name__ == '__main__':
paths = sys.argv[1:]
if not paths:

@ -0,0 +1,109 @@
swagger: '2.0'
info:
title: "Matrix Client-Server Client Config API"
version: "1.0.0"
host: localhost:8008
schemes:
- https
- http
basePath: /_matrix/client/%CLIENT_MAJOR_VERSION%
consumes:
- application/json
produces:
- application/json
securityDefinitions:
accessToken:
type: apiKey
description: The user_id or application service access_token
name: access_token
in: query
paths:
"/user/{userId}/account_data/{type}":
put:
summary: Set some account_data for the user.
description: |-
Set some account_data for the client. This config is only visible to the user
that set the account_data. The config will be synced to clients in the
top-level ``account_data``.
security:
- accessToken: []
parameters:
- in: path
type: string
name: userId
required: true
description: |-
The id of the user to set account_data for. The access token must be
authorized to make requests for this user id.
x-example: "@alice:example.com"
- in: path
type: string
name: type
required: true
description: |-
The event type of the account_data to set. Custom types should be
namespaced to avoid clashes.
x-example: "org.example.custom.config"
- in: body
name: content
required: true
description: |-
The content of the account_data
schema:
type: object
example: |-
{"custom_account_data_key": "custom_config_value"}
responses:
200:
description:
The account_data was successfully added.
tags:
- User data
"/user/{userId}/rooms/{roomId}/account_data/{type}":
put:
summary: Set some account_data for the user.
description: |-
Set some account_data for the client on a given room. This config is only
visible to the user that set the account_data. The config will be synced to
clients in the per-room ``account_data``.
security:
- accessToken: []
parameters:
- in: path
type: string
name: userId
required: true
description: |-
The id of the user to set account_data for. The access token must be
authorized to make requests for this user id.
x-example: "@alice:example.com"
- in: path
type: string
name: roomId
required: true
description: |-
The id of the room to set account_data on.
x-example: "!726s6s6q:example.com"
- in: path
type: string
name: type
required: true
description: |-
The event type of the account_data to set. Custom types should be
namespaced to avoid clashes.
x-example: "org.example.custom.room.config"
- in: body
name: content
required: true
description: |-
The content of the account_data
schema:
type: object
example: |-
{"custom_account_data_key": "custom_account_data_value"}
responses:
200:
description:
The account_data was successfully added.
tags:
- User data

@ -0,0 +1,105 @@
swagger: '2.0'
info:
title: "Matrix Client-Server Administration API"
version: "1.0.0"
host: localhost:8008
schemes:
- https
- http
basePath: /_matrix/client/%CLIENT_MAJOR_VERSION%
consumes:
- application/json
produces:
- application/json
securityDefinitions:
accessToken:
type: apiKey
description: The user_id or application service access_token
name: access_token
in: query
paths:
"/admin/whois/{userId}":
get:
summary: Gets information about a particular user.
description: |-
Gets information about a particular user.
This API may be restricted to only be called by the user being looked
up, or by a server admin. Server-local administrator privileges are not
specified in this document.
security:
- accessToken: []
parameters:
- in: path
type: string
name: userId
description: The user to look up.
required: true
x-example: "@peter:rabbit.rocks"
responses:
200:
description: The lookup was successful.
examples:
application/json: |-
{
"user_id": "@peter:rabbit.rocks",
"devices": {
"teapot": {
"sessions": [
{
"connections": [
{
"ip": "127.0.0.1",
"last_seen": 1411996332123,
"user_agent": "curl/7.31.0-DEV"
},
{
"ip": "10.0.0.2",
"last_seen": 1411996332123,
"user_agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/37.0.2062.120 Safari/537.36"
}
]
}
]
}
}
}
schema:
type: object
properties:
user_id:
type: string
description: The Matrix user ID of the user.
devices:
type: object
description: |-
Each key is an identitfier for one of the user's devices.
additionalProperties:
type: object
title: DeviceInfo
properties:
sessions:
type: array
description: A user's sessions (i.e. what they did with an access token from one login).
items:
type: object
title: SessionInfo
properties:
connections:
type: array
description: Information particular connections in the session.
items:
type: object
title: ConnectionInfo
properties:
ip:
type: string
description: Most recently seen IP address of the session.
last_seen:
type: number
description: Unix timestamp that the session was last active.
user_agent:
type: string
description: User agent string last seen in the session.
tags:
- Server administration

@ -0,0 +1,163 @@
swagger: '2.0'
info:
title: "Matrix Client-Server Account Administrative Contact API"
version: "1.0.0"
host: localhost:8008
schemes:
- https
- http
basePath: /_matrix/client/%CLIENT_MAJOR_VERSION%
consumes:
- application/json
produces:
- application/json
securityDefinitions:
accessToken:
type: apiKey
description: The user_id or application service access_token
name: access_token
in: query
paths:
"/account/password":
post:
summary: Changes a user's password.
description: |-
This API endpoint uses the 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.
security:
- accessToken: []
parameters:
- in: body
name: body
schema:
type: object
example: |-
{
"new_password": "ihatebananas"
}
properties:
new_password:
type: string
description: The new password for the account.
required: ["new_password"]
responses:
200:
description: The password has been changed.
examples:
application/json: "{}"
schema:
type: object
429:
description: This request was rate-limited.
schema:
"$ref": "definitions/error.yaml"
tags:
- User data
"/account/3pid":
get:
summary: Gets a list of a user's third party identifiers.
description: |-
Gets a list of the third party identifiers that the homeserver has
associated with the user's account.
This is *not* the same as the list of third party identifiers bound to
the user's Matrix ID in Identity Servers.
Identifiers in this list may be used by the homeserver as, for example,
identifiers that it will accept to reset the user's account password.
security:
- accessToken: []
responses:
200:
description: The lookup was successful.
examples:
application/json: |-
{
"threepids": [
{
"medium": "email",
"address": "monkey@banana.island"
}
]
}
schema:
type: object
properties:
threepids:
type: array
items:
type: object
title: Third party identifier
properties:
medium:
type: string
description: The medium of the third party identifier.
enum: ["email"]
address:
type: string
description: The third party identifier address.
tags:
- User data
post:
summary: Adds contact information to the user's account.
description: Adds contact information to the user's account.
security:
- accessToken: []
parameters:
- in: body
name: body
schema:
type: object
properties:
threePidCreds:
title: "ThreePidCredentials"
type: object
description: The third party credentials to associate with the account.
properties:
client_secret:
type: string
description: The client secret used in the session with the Identity Server.
id_server:
type: string
description: The Identity Server to use.
sid:
type: string
description: The session identifier given by the Identity Server.
required: ["client_secret", "id_server", "sid"]
bind:
type: boolean
description: |-
Whether the homeserver should also bind this third party
identifier to the account's Matrix ID with the passed identity
server. Default: ``false``.
x-example: true
required: ["threePidCreds"]
example: |-
{
"threePidCreds": {
"id_server": "matrix.org",
"sid": "abc123987",
"client_secret": "d0n'tT3ll"
},
"bind": false
}
responses:
200:
description: The addition was successful.
examples:
application/json: "{}"
schema:
type: object
403:
description: The credentials could not be verified with the identity server.
examples:
application/json: |-
{
"errcode": "M_THREEPID_AUTH_FAILED",
"error": "The third party credentials could not be verified by the identity server."
}
tags:
- User data

@ -1,50 +0,0 @@
{
"apiVersion": "1.0.0",
"swaggerVersion": "1.2",
"apis": [
{
"path": "-login",
"description": "Login operations"
},
{
"path": "-registration",
"description": "Registration operations"
},
{
"path": "-rooms",
"description": "Room operations"
},
{
"path": "-profile",
"description": "Profile operations"
},
{
"path": "-presence",
"description": "Presence operations"
},
{
"path": "-events",
"description": "Event operations"
},
{
"path": "-directory",
"description": "Directory operations"
},
{
"path": "-content",
"description": "Content repository operations"
}
],
"authorizations": {
"token": {
"scopes": []
}
},
"info": {
"title": "Matrix Client-Server API Reference",
"description": "This contains the client-server API for the reference implementation of the home server",
"termsOfServiceUrl": "http://matrix.org",
"license": "Apache 2.0",
"licenseUrl": "http://www.apache.org/licenses/LICENSE-2.0.html"
}
}

@ -1,119 +0,0 @@
{
"apiVersion": "1.0.0",
"swaggerVersion": "1.2",
"basePath": "http://localhost:8008/_matrix",
"resourcePath": "/media/v1/",
"apis": [
{
"path": "/media/v1/upload",
"operations": [
{
"method": "POST",
"summary": "Upload some content to the content repository.",
"type": "ContentUploadResponse",
"nickname": "upload_content",
"parameters": [
{
"name": "body",
"description": "The file to upload.",
"required": true,
"type": "file",
"paramType": "body"
}
]
}
]
},
{
"path": "/media/v1/download/{serverName}/{mediaId}",
"operations": [
{
"method": "GET",
"summary": "Get the content stored at this address.",
"type": "file",
"nickname": "download_content",
"parameters": [
{
"name": "serverName",
"description": "The serverName from the mxc://<serverName>/<mediaId> URI (the authority component).",
"required": true,
"type": "string",
"paramType": "path"
},
{
"name": "mediaId",
"description": "The mediaId from the mxc://<serverName>/<mediaId> URI (the path component).",
"required": true,
"type": "string",
"paramType": "path"
}
]
}
]
},
{
"path": "/media/v1/thumbnail/{serverName}/{mediaId}",
"operations": [
{
"method": "GET",
"summary": "Get a thumbnail of the content stored at this address.",
"type": "file",
"nickname": "thumbnail_content",
"parameters": [
{
"name": "serverName",
"description": "The serverName from the mxc://<serverName>/<mediaId> URI (the authority component).",
"required": true,
"type": "string",
"paramType": "path"
},
{
"name": "mediaId",
"description": "The mediaId from the mxc://<serverName>/<mediaId> URI (the path component).",
"required": true,
"type": "string",
"paramType": "path"
},
{
"name": "width",
"description": "The desired width of the thumbnail.",
"required": false,
"type": "integer",
"paramType": "query"
},
{
"name": "height",
"description": "The desired height of the thumbnail.",
"required": false,
"type": "integer",
"paramType": "query"
},
{
"name": "method",
"description": "The desired resizing method.",
"enum": [
"crop",
"scale"
],
"required": false,
"type": "string",
"paramType": "query"
}
]
}
]
}
],
"models": {
"ContentUploadResponse": {
"id": "ContentUploadResponse",
"properties": {
"content_uri": {
"type": "string",
"description": "The mxc:// URI where this content is stored. This is of the form 'mxc://{serverName}/{mediaId}'",
"required": true
}
}
}
}
}

@ -1,101 +0,0 @@
{
"apiVersion": "1.0.0",
"swaggerVersion": "1.2",
"basePath": "http://localhost:8008/_matrix/client/api/v1",
"resourcePath": "/directory",
"produces": [
"application/json"
],
"apis": [
{
"path": "/directory/room/{roomAlias}",
"operations": [
{
"method": "GET",
"summary": "Get the room ID corresponding to this room alias.",
"notes": "Volatile: This API is likely to change.",
"type": "DirectoryResponse",
"nickname": "get_room_id_for_alias",
"parameters": [
{
"name": "roomAlias",
"description": "The room alias.",
"required": true,
"type": "string",
"paramType": "path"
}
]
},
{
"method": "PUT",
"summary": "Create a new mapping from room alias to room ID.",
"notes": "Volatile: This API is likely to change.",
"type": "void",
"nickname": "add_room_alias",
"parameters": [
{
"name": "roomAlias",
"description": "The room alias to set.",
"required": true,
"type": "string",
"paramType": "path"
},
{
"name": "body",
"description": "The room ID to set.",
"required": true,
"type": "RoomAliasRequest",
"paramType": "body"
}
]
},
{
"method": "DELETE",
"summary": "Removes a mapping of room alias to room ID.",
"notes": "Only privileged users can perform this action.",
"type": "void",
"nickname": "remove_room_alias",
"parameters": [
{
"name": "roomAlias",
"description": "The room alias to remove.",
"required": true,
"type": "string",
"paramType": "path"
}
]
}
]
}
],
"models": {
"DirectoryResponse": {
"id": "DirectoryResponse",
"properties": {
"room_id": {
"type": "string",
"description": "The fully-qualified room ID.",
"required": true
},
"servers": {
"type": "array",
"items": {
"$ref": "string"
},
"description": "A list of servers that know about this room.",
"required": true
}
}
},
"RoomAliasRequest": {
"id": "RoomAliasRequest",
"properties": {
"room_id": {
"type": "string",
"description": "The room ID to map the alias to.",
"required": true
}
}
}
}
}

@ -1,247 +0,0 @@
{
"apiVersion": "1.0.0",
"swaggerVersion": "1.2",
"basePath": "http://localhost:8008/_matrix/client/api/v1",
"resourcePath": "/events",
"produces": [
"application/json"
],
"apis": [
{
"path": "/events",
"operations": [
{
"method": "GET",
"summary": "Listen on the event stream",
"notes": "This can only be done by the logged in user. This will block until an event is received, or until the timeout is reached.",
"type": "PaginationChunk",
"nickname": "get_event_stream",
"parameters": [
{
"name": "from",
"description": "The token to stream from.",
"required": false,
"type": "string",
"paramType": "query"
},
{
"name": "timeout",
"description": "The maximum time in milliseconds to wait for an event.",
"required": false,
"type": "integer",
"paramType": "query"
}
]
}
],
"responseMessages": [
{
"code": 400,
"message": "Bad pagination token."
}
]
},
{
"path": "/events/{eventId}",
"operations": [
{
"method": "GET",
"summary": "Get information about a single event.",
"notes": "Get information about a single event.",
"type": "Event",
"nickname": "get_event",
"parameters": [
{
"name": "eventId",
"description": "The event ID to get.",
"required": true,
"type": "string",
"paramType": "path"
}
],
"responseMessages": [
{
"code": 404,
"message": "Event not found."
}
]
}
]
},
{
"path": "/initialSync",
"operations": [
{
"method": "GET",
"summary": "Get this user's current state.",
"notes": "Get this user's current state.",
"type": "InitialSyncResponse",
"nickname": "initial_sync",
"parameters": [
{
"name": "limit",
"description": "The maximum number of messages to return for each room.",
"type": "integer",
"paramType": "query",
"required": false
}
]
}
]
},
{
"path": "/publicRooms",
"operations": [
{
"method": "GET",
"summary": "Get a list of publicly visible rooms.",
"type": "PublicRoomsPaginationChunk",
"nickname": "get_public_room_list"
}
]
}
],
"models": {
"PaginationChunk": {
"id": "PaginationChunk",
"properties": {
"start": {
"type": "string",
"description": "A token which correlates to the first value in \"chunk\" for paginating.",
"required": true
},
"end": {
"type": "string",
"description": "A token which correlates to the last value in \"chunk\" for paginating.",
"required": true
},
"chunk": {
"type": "array",
"description": "An array of events.",
"required": true,
"items": {
"$ref": "Event"
}
}
}
},
"Event": {
"id": "Event",
"properties": {
"event_id": {
"type": "string",
"description": "An ID which uniquely identifies this event.",
"required": true
},
"room_id": {
"type": "string",
"description": "The room in which this event occurred.",
"required": true
}
}
},
"PublicRoomInfo": {
"id": "PublicRoomInfo",
"properties": {
"aliases": {
"type": "array",
"description": "A list of room aliases for this room.",
"items": {
"$ref": "string"
}
},
"name": {
"type": "string",
"description": "The name of the room, as given by the m.room.name state event."
},
"room_id": {
"type": "string",
"description": "The room ID for this public room.",
"required": true
},
"topic": {
"type": "string",
"description": "The topic of this room, as given by the m.room.topic state event."
}
}
},
"PublicRoomsPaginationChunk": {
"id": "PublicRoomsPaginationChunk",
"properties": {
"start": {
"type": "string",
"description": "A token which correlates to the first value in \"chunk\" for paginating.",
"required": true
},
"end": {
"type": "string",
"description": "A token which correlates to the last value in \"chunk\" for paginating.",
"required": true
},
"chunk": {
"type": "array",
"description": "A list of public room data.",
"required": true,
"items": {
"$ref": "PublicRoomInfo"
}
}
}
},
"InitialSyncResponse": {
"id": "InitialSyncResponse",
"properties": {
"end": {
"type": "string",
"description": "A streaming token which can be used with /events to continue from this snapshot of data.",
"required": true
},
"presence": {
"type": "array",
"description": "A list of presence events.",
"items": {
"$ref": "Event"
},
"required": false
},
"rooms": {
"type": "array",
"description": "A list of initial sync room data.",
"required": false,
"items": {
"$ref": "InitialSyncRoomData"
}
}
}
},
"InitialSyncRoomData": {
"id": "InitialSyncRoomData",
"properties": {
"membership": {
"type": "string",
"description": "This user's membership state in this room.",
"required": true
},
"room_id": {
"type": "string",
"description": "The ID of this room.",
"required": true
},
"messages": {
"type": "PaginationChunk",
"description": "The most recent messages for this room, governed by the limit parameter.",
"required": false
},
"state": {
"type": "array",
"description": "A list of state events representing the current state of the room.",
"required": false,
"items": {
"$ref": "Event"
}
}
}
}
}
}

@ -1,120 +0,0 @@
{
"apiVersion": "1.0.0",
"apis": [
{
"operations": [
{
"method": "GET",
"nickname": "get_login_info",
"notes": "All login stages MUST be mentioned if there is >1 login type.",
"summary": "Get the login mechanism to use when logging in.",
"type": "LoginFlows"
},
{
"method": "POST",
"nickname": "submit_login",
"notes": "If this is part of a multi-stage login, there MUST be a 'session' key.",
"parameters": [
{
"description": "A login submission",
"name": "body",
"paramType": "body",
"required": true,
"type": "LoginSubmission"
}
],
"responseMessages": [
{
"code": 400,
"message": "Bad login type"
},
{
"code": 400,
"message": "Missing JSON keys"
}
],
"summary": "Submit a login action.",
"type": "LoginResult"
}
],
"path": "/login"
}
],
"basePath": "http://localhost:8008/_matrix/client/api/v1",
"consumes": [
"application/json"
],
"models": {
"LoginFlows": {
"id": "LoginFlows",
"properties": {
"flows": {
"description": "A list of valid login flows.",
"type": "array",
"items": {
"$ref": "LoginInfo"
}
}
}
},
"LoginInfo": {
"id": "LoginInfo",
"properties": {
"stages": {
"description": "Multi-stage login only: An array of all the login types required to login.",
"items": {
"$ref": "string"
},
"type": "array"
},
"type": {
"description": "The login type that must be used when logging in.",
"type": "string"
}
}
},
"LoginResult": {
"id": "LoginResult",
"properties": {
"access_token": {
"description": "The access token for this user's login if this is the final stage of the login process.",
"type": "string"
},
"user_id": {
"description": "The user's fully-qualified user ID.",
"type": "string"
},
"next": {
"description": "Multi-stage login only: The next login type to submit.",
"type": "string"
},
"session": {
"description": "Multi-stage login only: The session token to send when submitting the next login type.",
"type": "string"
}
}
},
"LoginSubmission": {
"id": "LoginSubmission",
"properties": {
"type": {
"description": "The type of login being submitted.",
"type": "string"
},
"session": {
"description": "Multi-stage login only: The session token from an earlier login stage.",
"type": "string"
},
"_login_type_defined_keys_": {
"description": "Keys as defined by the specified login type, e.g. \"user\", \"password\""
}
}
}
},
"produces": [
"application/json"
],
"resourcePath": "/login",
"swaggerVersion": "1.2"
}

@ -1,164 +0,0 @@
{
"apiVersion": "1.0.0",
"swaggerVersion": "1.2",
"basePath": "http://localhost:8008/_matrix/client/api/v1",
"resourcePath": "/presence",
"produces": [
"application/json"
],
"consumes": [
"application/json"
],
"apis": [
{
"path": "/presence/{userId}/status",
"operations": [
{
"method": "PUT",
"summary": "Update this user's presence state.",
"notes": "This can only be done by the logged in user.",
"type": "void",
"nickname": "update_presence",
"parameters": [
{
"name": "body",
"description": "The new presence state",
"required": true,
"type": "PresenceUpdate",
"paramType": "body"
},
{
"name": "userId",
"description": "The user whose presence to set.",
"required": true,
"type": "string",
"paramType": "path"
}
]
},
{
"method": "GET",
"summary": "Get this user's presence state.",
"notes": "Get this user's presence state.",
"type": "PresenceUpdate",
"nickname": "get_presence",
"parameters": [
{
"name": "userId",
"description": "The user whose presence to get.",
"required": true,
"type": "string",
"paramType": "path"
}
]
}
]
},
{
"path": "/presence/list/{userId}",
"operations": [
{
"method": "GET",
"summary": "Retrieve a list of presences for all of this user's friends.",
"notes": "",
"type": "array",
"items": {
"$ref": "Presence"
},
"nickname": "get_presence_list",
"parameters": [
{
"name": "userId",
"description": "The user whose presence list to get.",
"required": true,
"type": "string",
"paramType": "path"
}
]
},
{
"method": "POST",
"summary": "Add or remove users from this presence list.",
"notes": "Add or remove users from this presence list.",
"type": "void",
"nickname": "modify_presence_list",
"parameters": [
{
"name": "userId",
"description": "The user whose presence list is being modified.",
"required": true,
"type": "string",
"paramType": "path"
},
{
"name": "body",
"description": "The modifications to make to this presence list.",
"required": true,
"type": "PresenceListModifications",
"paramType": "body"
}
]
}
]
}
],
"models": {
"PresenceUpdate": {
"id": "PresenceUpdate",
"properties": {
"presence": {
"type": "string",
"description": "Enum: The presence state.",
"enum": [
"offline",
"unavailable",
"online",
"free_for_chat"
]
},
"status_msg": {
"type": "string",
"description": "The user-defined message associated with this presence state."
}
},
"subTypes": [
"Presence"
]
},
"Presence": {
"id": "Presence",
"properties": {
"last_active_ago": {
"type": "integer",
"format": "int64",
"description": "The last time this user performed an action on their home server."
},
"user_id": {
"type": "string",
"description": "The fully qualified user ID"
}
}
},
"PresenceListModifications": {
"id": "PresenceListModifications",
"properties": {
"invite": {
"type": "array",
"description": "A list of user IDs to add to the list.",
"items": {
"type": "string",
"description": "A fully qualified user ID."
}
},
"drop": {
"type": "array",
"description": "A list of user IDs to remove from the list.",
"items": {
"type": "string",
"description": "A fully qualified user ID."
}
}
}
}
}
}

@ -1,122 +0,0 @@
{
"apiVersion": "1.0.0",
"swaggerVersion": "1.2",
"basePath": "http://localhost:8008/_matrix/client/api/v1",
"resourcePath": "/profile",
"produces": [
"application/json"
],
"consumes": [
"application/json"
],
"apis": [
{
"path": "/profile/{userId}/displayname",
"operations": [
{
"method": "PUT",
"summary": "Set a display name.",
"notes": "This can only be done by the logged in user.",
"type": "void",
"nickname": "set_display_name",
"parameters": [
{
"name": "body",
"description": "The new display name for this user.",
"required": true,
"type": "DisplayName",
"paramType": "body"
},
{
"name": "userId",
"description": "The user whose display name to set.",
"required": true,
"type": "string",
"paramType": "path"
}
]
},
{
"method": "GET",
"summary": "Get a display name.",
"notes": "This can be done by anyone.",
"type": "DisplayName",
"nickname": "get_display_name",
"parameters": [
{
"name": "userId",
"description": "The user whose display name to get.",
"required": true,
"type": "string",
"paramType": "path"
}
]
}
]
},
{
"path": "/profile/{userId}/avatar_url",
"operations": [
{
"method": "PUT",
"summary": "Set an avatar URL.",
"notes": "This can only be done by the logged in user.",
"type": "void",
"nickname": "set_avatar_url",
"parameters": [
{
"name": "body",
"description": "The new avatar url for this user.",
"required": true,
"type": "AvatarUrl",
"paramType": "body"
},
{
"name": "userId",
"description": "The user whose avatar url to set.",
"required": true,
"type": "string",
"paramType": "path"
}
]
},
{
"method": "GET",
"summary": "Get an avatar url.",
"notes": "This can be done by anyone.",
"type": "AvatarUrl",
"nickname": "get_avatar_url",
"parameters": [
{
"name": "userId",
"description": "The user whose avatar url to get.",
"required": true,
"type": "string",
"paramType": "path"
}
]
}
]
}
],
"models": {
"DisplayName": {
"id": "DisplayName",
"properties": {
"displayname": {
"type": "string",
"description": "The textual display name"
}
}
},
"AvatarUrl": {
"id": "AvatarUrl",
"properties": {
"avatar_url": {
"type": "string",
"description": "A url to an image representing an avatar."
}
}
}
}
}

@ -1,120 +0,0 @@
{
"apiVersion": "1.0.0",
"apis": [
{
"operations": [
{
"method": "GET",
"nickname": "get_registration_info",
"notes": "All login stages MUST be mentioned if there is >1 login type.",
"summary": "Get the login mechanism to use when registering.",
"type": "RegistrationFlows"
},
{
"method": "POST",
"nickname": "submit_registration",
"notes": "If this is part of a multi-stage registration, there MUST be a 'session' key.",
"parameters": [
{
"description": "A registration submission",
"name": "body",
"paramType": "body",
"required": true,
"type": "RegistrationSubmission"
}
],
"responseMessages": [
{
"code": 400,
"message": "Bad login type"
},
{
"code": 400,
"message": "Missing JSON keys"
}
],
"summary": "Submit a registration action.",
"type": "RegistrationResult"
}
],
"path": "/register"
}
],
"basePath": "http://localhost:8008/_matrix/client/api/v1",
"consumes": [
"application/json"
],
"models": {
"RegistrationFlows": {
"id": "RegistrationFlows",
"properties": {
"flows": {
"description": "A list of valid registration flows.",
"type": "array",
"items": {
"$ref": "RegistrationInfo"
}
}
}
},
"RegistrationInfo": {
"id": "RegistrationInfo",
"properties": {
"stages": {
"description": "Multi-stage registration only: An array of all the login types required to registration.",
"items": {
"$ref": "string"
},
"type": "array"
},
"type": {
"description": "The first login type that must be used when logging in.",
"type": "string"
}
}
},
"RegistrationResult": {
"id": "RegistrationResult",
"properties": {
"access_token": {
"description": "The access token for this user's registration if this is the final stage of the registration process.",
"type": "string"
},
"user_id": {
"description": "The user's fully-qualified user ID.",
"type": "string"
},
"next": {
"description": "Multi-stage registration only: The next registration type to submit.",
"type": "string"
},
"session": {
"description": "Multi-stage registration only: The session token to send when submitting the next registration type.",
"type": "string"
}
}
},
"RegistrationSubmission": {
"id": "RegistrationSubmission",
"properties": {
"type": {
"description": "The type of registration being submitted.",
"type": "string"
},
"session": {
"description": "Multi-stage registration only: The session token from an earlier registration stage.",
"type": "string"
},
"_registration_type_defined_keys_": {
"description": "Keys as defined by the specified registration type, e.g. \"user\", \"password\""
}
}
}
},
"produces": [
"application/json"
],
"resourcePath": "/register",
"swaggerVersion": "1.2"
}

File diff suppressed because it is too large Load Diff

@ -0,0 +1,78 @@
swagger: '2.0'
info:
title: "Matrix Client-Server Room Banning API"
version: "1.0.0"
host: localhost:8008
schemes:
- https
- http
basePath: /_matrix/client/%CLIENT_MAJOR_VERSION%
consumes:
- application/json
produces:
- application/json
securityDefinitions:
accessToken:
type: apiKey
description: The user_id or application service access_token
name: access_token
in: query
paths:
"/rooms/{roomId}/ban":
post:
summary: Ban a user in the room.
description: |-
Ban a user in the room. If the user is currently in the room, also kick them.
When a user is banned from a room, they may not join it until they are unbanned.
The caller must have the required power level in order to perform this operation.
security:
- accessToken: []
parameters:
- in: path
type: string
name: roomId
description: The room identifier (not alias) from which the user should be banned.
required: true
x-example: "!e42d8c:matrix.org"
- in: body
name: body
required: true
schema:
type: object
example: |-
{
"reason": "Telling unfunny jokes",
"user_id": "@cheeky_monkey:matrix.org"
}
properties:
user_id:
type: string
description: The fully qualified user ID of the user being banned.
reason:
type: string
description: The reason the user has been banned.
required: ["user_id"]
responses:
200:
description: The user has been kicked and banned from the room.
examples:
application/json: |-
{}
schema:
type: object
403:
description: |-
You do not have permission to ban the user from the room. A meaningful ``errcode`` and description error text will be returned. Example reasons for rejections are:
- The banner is not currently in the room.
- The banner's power level is insufficient to ban users from the room.
examples:
application/json: |-
{
"errcode": "M_FORBIDDEN",
"error": "You do not have a high enough power level to ban from this room."
}
tags:
- Room membership

@ -1,11 +1,11 @@
swagger: '2.0'
info:
title: "Matrix Client-Server v1 Content Repository API"
title: "Matrix Client-Server Content Repository API"
version: "1.0.0"
host: localhost:8008
schemes:
- https
basePath: /_matrix/media/v1
basePath: /_matrix/media/%CLIENT_MAJOR_VERSION%
produces:
- application/json
- "*/*"
@ -43,6 +43,8 @@ paths:
{
"content_uri": "mxc://example.com/AQwafuaFswefuhsfAFAgsw"
}
tags:
- Media
"/download/{serverName}/{mediaId}":
get:
summary: "Download content from the content repository."
@ -74,6 +76,8 @@ paths:
type: "string"
schema:
type: file
tags:
- Media
"/thumbnail/{serverName}/{mediaId}":
get:
summary: "Download a thumbnail of the content from the content repository."
@ -123,5 +127,5 @@ paths:
enum: ["image/jpeg", "image/png"]
schema:
type: file
tags:
- Media

@ -1,12 +1,12 @@
swagger: '2.0'
info:
title: "Matrix Client-Server v1 Room Creation API"
title: "Matrix Client-Server Room Creation API"
version: "1.0.0"
host: localhost:8008
schemes:
- https
- http
basePath: /_matrix/client/api/v1
basePath: /_matrix/client/%CLIENT_MAJOR_VERSION%
consumes:
- application/json
produces:
@ -146,3 +146,5 @@ paths:
400:
description: >
The request body is malformed or the room alias specified is already taken.
tags:
- Room creation

@ -0,0 +1,45 @@
properties:
content:
description: The content of this event. The fields in this object will vary depending
on the type of event.
title: EventContent
type: object
origin_server_ts:
description: Timestamp in milliseconds on originating homeserver when this event
was sent.
format: int64
type: integer
sender:
description: The MXID of the user who sent this event.
type: string
state_key:
description: Optional. This key will only be present for state events. A unique
key which defines the overwriting semantics for this piece of room state.
type: string
type:
description: The type of event.
type: string
unsigned:
description: Information about this event which was not sent by the originating
homeserver
properties:
age:
description: Time in milliseconds since the event was sent.
format: int64
type: integer
prev_content:
description: Optional. The previous ``content`` for this state. This will
be present only for state events appearing in the ``timeline``. If this
is not a state event, or there is no previous content, this key will be
missing.
title: EventContent
type: object
transaction_id:
description: Optional. The transaction ID set when this message was sent.
This key will only be present for message events sent by the device calling
this API.
type: string
title: Unsigned
type: object
title: Event
type: object

@ -0,0 +1,9 @@
properties:
events:
description: List of events
items:
allOf:
- $ref: event.yaml
type: object
type: array
type: object

@ -0,0 +1,34 @@
properties:
limit:
description: The maximum number of events to return.
type: integer
not_senders:
description: A list of sender IDs to exclude. If this list is absent then no senders
are excluded. A matching sender will be excluded even if it is listed in the
'senders' filter. A '*' can be used as a wildcard to match any sequence of characters.
items:
type: string
type: array
not_types:
description: A list of event types to exclude. If this list is absent then no
event types are excluded. A matching type will be excluded even if it is listed
in the 'types' filter. A '*' can be used as a wildcard to match any sequence
of characters.
items:
type: string
type: array
senders:
description: A list of senders IDs to include. If this list is absent then all
senders are included. A '*' can be used as a wildcard to match any sequence
of characters.
items:
type: string
type: array
types:
description: A list of event types to include. If this list is absent then all
event types are included. A '*' can be used as a wildcard to match any sequence
of characters.
items:
type: string
type: array
type: object

@ -0,0 +1,9 @@
properties:
kind:
enum:
- event_match
- profile_tag
- contains_display_name
- room_member_count
type: string
type: object

@ -0,0 +1,15 @@
properties:
actions:
items:
type:
- object
- string
type: array
default:
type: boolean
enabled:
type: boolean
rule_id:
type: string
title: PushRule
type: object

@ -0,0 +1,37 @@
properties:
content:
items:
allOf:
- $ref: push_rule.yaml
title: PushRule
type: object
type: array
override:
items:
allOf:
- $ref: push_rule.yaml
title: PushRule
type: object
type: array
room:
items:
allOf:
- $ref: push_rule.yaml
title: PushRule
type: object
type: array
sender:
items:
allOf:
- $ref: push_rule.yaml
title: PushRule
type: object
type: array
underride:
items:
allOf:
- $ref: push_rule.yaml
title: PushRule
type: object
type: array
type: object

@ -0,0 +1,17 @@
allOf:
- $ref: event_filter.yaml
properties:
not_rooms:
description: A list of room IDs to exclude. If this list is absent then no rooms
are excluded. A matching room will be excluded even if it is listed in the 'rooms'
filter. A '*' can be used as a wildcard to match any sequence of characters.
items:
type: string
type: array
rooms:
description: A list of room IDs to include. If this list is absent then all rooms
are included. A '*' can be used as a wildcard to match any sequence of characters.
items:
type: string
type: array
type: object

@ -0,0 +1,42 @@
properties:
event_fields:
description: List of event fields to include. If this list is absent then all
fields are included. The entries may include '.' charaters to indicate sub-fields.
So ['content.body'] will include the 'body' field of the 'content' object. A
literal '.' character in a field name may be escaped using a '\'. A server may
include more fields than were requested.
items:
type: string
type: array
event_format:
description: The format to use for events. 'client' will return the events in
a format suitable for clients. 'federation' will return the raw event as receieved
over federation. The default is 'client'.
enum:
- client
- federation
type: string
presence:
allOf:
- $ref: event_filter.yaml
description: The presence updates to include.
room:
properties:
ephemeral:
allOf:
- $ref: room_event_filter.yaml
description: The events that aren't recorded in the room history, e.g. typing
and receipts, to include for rooms.
include_leave:
description: Include rooms that the user has left in the sync, default false
type: boolean
state:
allOf:
- $ref: room_event_filter.yaml
description: The state events to include for rooms.
timeline:
allOf:
- $ref: room_event_filter.yaml
description: The message and state update events to include for rooms.
type: object
type: object

@ -0,0 +1,12 @@
allOf:
- $ref: event_batch.yaml
properties:
limited:
description: True if the number of events returned was limited by the ``limit``
on the filter
type: boolean
prev_batch:
description: If the batch was limited then this is a token that can be supplied
to the server to retrieve earlier events
type: string
type: object

@ -1,12 +1,12 @@
swagger: '2.0'
info:
title: "Matrix Client-Server v1 Directory API"
title: "Matrix Client-Server Directory API"
version: "1.0.0"
host: localhost:8008
schemes:
- https
- http
basePath: /_matrix/client/api/v1/directory
basePath: /_matrix/client/%CLIENT_MAJOR_VERSION%/directory
consumes:
- application/json
produces:
@ -29,6 +29,7 @@ paths:
name: roomAlias
description: The room alias to set.
required: true
x-example: "#monkeys:matrix.org"
- in: body
name: roomInfo
description: Information about this room alias.
@ -39,11 +40,20 @@ paths:
room_id:
type: string
description: The room ID to set.
example: |-
{
"room_id": "!abnjk1jdasj98:capuchins.com"
}
responses:
200:
description: The mapping was created.
examples:
application/json: |-
{}
schema:
type: object # empty json object
type: object
tags:
- Room directory
get:
summary: Get the room ID corresponding to this room alias.
parameters:
@ -52,6 +62,7 @@ paths:
name: roomAlias
description: The room alias.
required: true
x-example: "#monkeys:matrix.org"
responses:
200:
description: The room ID and other information for this alias.
@ -67,10 +78,40 @@ paths:
items:
type: string
description: A server which is aware of this room ID.
examples:
application/json: |-
{
"room_id": "!abnjk1jdasj98:capuchins.com",
"servers": [
"capuchins.com",
"matrix.org",
"another.com"
]
}
404:
description: There is no mapped room ID for this room alias.
examples:
application/json: |-
{
"errcode": "M_NOT_FOUND",
"error": "Room ID !abnjk1jdasj98:capuchins.com not found."
}
409:
description: A room alias with that name already exists.
examples:
application/json: |-
{
"errcode": "M_UNKNOWN",
"error": "Room alias #monkeys:matrix.org already exists."
}
tags:
- Room directory
delete:
summary: Remove a mapping of room alias to room ID.
description: |-
Remove a mapping of room alias to room ID.
Servers may choose to implement additional access control checks here, for instance that room aliases can only be deleted by their creator or a server administrator.
security:
- accessToken: []
parameters:
@ -79,9 +120,14 @@ paths:
name: roomAlias
description: The room alias to remove.
required: true
x-example: "#monkeys:matrix.org"
responses:
200:
description: The mapping was removed.
description: The mapping was deleted.
examples:
application/json: |-
{}
schema:
type: object # empty json object
type: object
tags:
- Room directory

@ -1,11 +1,11 @@
swagger: '2.0'
info:
title: "Matrix Client-Server v2 filter API"
title: "Matrix Client-Server filter API"
version: "1.0.0"
host: localhost:8008
schemes:
- https
basePath: /_matrix/client/v2_alpha
basePath: /_matrix/client/%CLIENT_MAJOR_VERSION%
consumes:
- application/json
produces:
@ -22,8 +22,8 @@ paths:
summary: Upload a new filter.
description: |-
Uploads a new filter definition to the homeserver.
Returns a filter ID that may be used in /sync requests to
retrict which events are returned to the client.
Returns a filter ID that may be used in future requests to
restrict which events are returned to the client.
security:
- accessToken: []
parameters:
@ -42,7 +42,7 @@ paths:
schema:
type: object
allOf:
- $ref: "definitions/sync_filter.json"
- $ref: "definitions/sync_filter.yaml"
example: |-
{
"room": {
@ -84,6 +84,8 @@ paths:
type: string
description: |-
The ID of the filter that was created.
tags:
- Room participation
"/user/{userId}/filter/{filterId}":
get:
summary: Download a filter
@ -136,4 +138,6 @@ paths:
schema:
type: object
allOf:
- $ref: "definitions/sync_filter.json"
- $ref: "definitions/sync_filter.yaml"
tags:
- Room participation

@ -0,0 +1,104 @@
swagger: '2.0'
info:
title: "Matrix Client-Server Sync Guest API"
version: "1.0.0"
host: localhost:8008
schemes:
- https
- http
basePath: /_matrix/client/%CLIENT_MAJOR_VERSION%
consumes:
- application/json
produces:
- application/json
securityDefinitions:
accessToken:
type: apiKey
description: The user_id or application service access_token
name: access_token
in: query
paths:
"/events":
get:
summary: Listen on the event stream.
description: |-
This will listen for new events related to a particular room and return
them to the caller. This will block until an event is received, or until
the ``timeout`` is reached.
This API is the same as the non-guest /events endpoint, but can be
called by guest users.
security:
- accessToken: []
parameters:
- in: query
type: string
name: from
description: |-
The token to stream from. This token is either from a previous
request to this API or from the initial sync API.
required: false
x-example: "s3456_9_0"
- in: query
type: integer
name: timeout
description: The maximum time in milliseconds to wait for an event.
required: false
x-example: "35000"
- in: query
type: array
items:
type: string
name: room_id
description: |-
The room IDs for which events should be returned.
x-example:
- "!somewhere:over"
- "!the:rainbow"
responses:
200:
description: "The events received, which may be none."
examples:
application/json: |-
{
"start": "s3456_9_0",
"end": "s3457_9_0",
"chunk": [
{
"age": 32,
"content": {
"body": "incoming message",
"msgtype": "m.text"
},
"event_id": "$14328055551tzaee:localhost",
"origin_server_ts": 1432804485886,
"room_id": "!TmaZBKYIFrIPVGoUYp:localhost",
"type": "m.room.message",
"sender": "@bob:localhost"
}
]
}
schema:
type: object
properties:
start:
type: string
description: |-
A token which correlates to the first value in ``chunk``. This
is usually the same token supplied to ``from=``.
end:
type: string
description: |-
A token which correlates to the last value in ``chunk``. This
token should be used in the next request to ``/events``.
chunk:
type: array
description: "An array of events."
items:
type: object
title: Event
allOf:
- "$ref": "../../event-schemas/schema/core-event-schema/room_event.yaml"
400:
description: "Bad pagination ``from`` parameter."
# No tags to exclude this from the swagger UI - use the non-guest version instead.

@ -0,0 +1,92 @@
swagger: '2.0'
info:
title: "Matrix Client-Server Room Joining API"
version: "1.0.0"
host: localhost:8008
schemes:
- https
- http
basePath: /_matrix/client/%CLIENT_MAJOR_VERSION%
consumes:
- application/json
produces:
- application/json
securityDefinitions:
accessToken:
type: apiKey
description: The user_id or application service access_token
name: access_token
in: query
paths:
# With an extra " " to disambiguate from the 3pid invite endpoint
# The extra space makes it sort first for what I'm sure is a good reason.
"/rooms/{roomId}/invite ":
post:
summary: Invite a user to participate in a particular room.
description: |-
.. _invite-by-user-id-endpoint:
*Note that there are two forms of this API, which are documented separately.
This version of the API requires that the inviter knows the Matrix
identifier of the invitee. The other is documented in the*
`third party invites section`_.
This API invites a user to participate in a particular room.
They do not start participating in the room until they actually join the
room.
Only users currently in a particular room can invite other users to
join that room.
If the user was invited to the room, the homeserver will append a
``m.room.member`` event to the room.
.. _third party invites section: `invite-by-third-party-id-endpoint`_
security:
- accessToken: []
parameters:
- in: path
type: string
name: roomId
description: The room identifier (not alias) to which to invite the user.
required: true
x-example: "!d41d8cd:matrix.org"
- in: body
name: body
required: true
schema:
type: object
example: |-
{
"user_id": "@cheeky_monkey:matrix.org"
}
properties:
user_id:
type: string
description: The fully qualified user ID of the invitee.
required: ["user_id"]
responses:
200:
description: The user has been invited to join the room.
examples:
application/json: |-
{}
schema:
type: object
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:
- The invitee has been banned from the room.
- The invitee is already a member of the room.
- The inviter is not currently in the room.
- The inviter's power level is insufficient to invite users to the room.
examples:
application/json: |-
{"errcode": "M_FORBIDDEN", "error": "@cheeky_monkey:matrix.org is banned from the room"}
429:
description: This request was rate-limited.
schema:
"$ref": "definitions/error.yaml"
tags:
- Room membership

@ -0,0 +1,70 @@
swagger: '2.0'
info:
title: "Matrix Client-Server Room Inviting API"
version: "1.0.0"
host: localhost:8008
schemes:
- https
- http
basePath: /_matrix/client/%CLIENT_MAJOR_VERSION%
consumes:
- application/json
produces:
- application/json
securityDefinitions:
accessToken:
type: apiKey
description: The user_id or application service access_token
name: access_token
in: query
paths:
"/rooms/{roomId}/join":
post:
summary: Start the requesting user participating in a particular room.
description: |-
This API starts a user participating in a particular room, if that user
is allowed to participate in that room. After this call, the client is
allowed to see all current state events in the room, and all subsequent
events associated with the room until the user leaves the room.
After a user has joined a room, the room will appear as an entry in the
response of the |initialSync| API.
security:
- accessToken: []
parameters:
- in: path
type: string
name: roomId
description: The room identifier or room alias to join.
required: true
x-example: "#monkeys:matrix.org"
responses:
200:
description: |-
The room has been joined.
The joined room ID must be returned in the ``room_id`` field.
examples:
application/json: |-
{"room_id": "!d41d8cd:matrix.org"}
schema:
type: object
403:
description: |-
You do not have permission to join the room. A meaningful ``errcode`` and description error text will be returned. Example reasons for rejection are:
- The room is invite-only and the user was not invited.
- The user has been banned from the room.
examples:
application/json: |-
{"errcode": "M_FORBIDDEN", "error": "You are not invited to this room."}
429:
description: This request was rate-limited.
schema:
"$ref": "definitions/error.yaml"
x-alias:
canonical-link: "post-matrix-client-%CLIENT_MAJOR_VERSION%-rooms-roomid-join"
aliases:
- /_matrix/client/%CLIENT_MAJOR_VERSION%/join/{roomId}
tags:
- Room membership

@ -0,0 +1,96 @@
swagger: '2.0'
info:
title: "Matrix Client-Server Room Leaving API"
version: "1.0.0"
host: localhost:8008
schemes:
- https
- http
basePath: /_matrix/client/%CLIENT_MAJOR_VERSION%
consumes:
- application/json
produces:
- application/json
securityDefinitions:
accessToken:
type: apiKey
description: The user_id or application service access_token
name: access_token
in: query
paths:
"/rooms/{roomId}/leave":
post:
summary: Stop the requesting user participating in a particular room.
description: |-
This API stops a user participating in a particular room.
If the user was already in the room, they will no longer be able to see
new events in the room. If the room requires an invite to join, they
will need to be re-invited before they can re-join.
If the user was invited to the room, but had not joined, this call
serves to reject the invite.
The user will still be allowed to retrieve history from the room which
they were previously allowed to see.
security:
- accessToken: []
parameters:
- in: path
type: string
name: roomId
description: The room identifier to leave.
required: true
x-example: "!nkl290a:matrix.org"
responses:
200:
description: |-
The room has been left.
examples:
application/json: |-
{}
schema:
type: object
429:
description: This request was rate-limited.
schema:
"$ref": "definitions/error.yaml"
tags:
- Room membership
"/rooms/{roomId}/forget":
post:
summary: Stop the requesting user remembering about a particular room.
description: |-
This API stops a user remembering about a particular room.
In general, history is a first class citizen in Matrix. After this API
is called, however, a user will no longer be able to retrieve history
for this room. If all users on a homeserver forget a room, the room is
eligible for deletion from that homeserver.
If the user is currently joined to the room, they will implicitly leave
the room as part of this API call.
security:
- accessToken: []
parameters:
- in: path
type: string
name: roomId
description: The room identifier to forget.
required: true
x-example: "!au1ba7o:matrix.org"
responses:
200:
description: |-
The room has been forgotten.
examples:
application/json: |-
{}
schema:
type: object
429:
description: This request was rate-limited.
schema:
"$ref": "definitions/error.yaml"
tags:
- Room membership

@ -0,0 +1,99 @@
swagger: '2.0'
info:
title: "Matrix Client-Server Room Creation API"
version: "1.0.0"
host: localhost:8008
schemes:
- https
- http
basePath: /_matrix/client/%CLIENT_MAJOR_VERSION%
consumes:
- application/json
produces:
- application/json
paths:
"/publicRooms":
get:
summary: Lists the public rooms on the server.
description: |-
Lists the public rooms on the server.
This API returns paginated responses.
responses:
200:
description: A list of the rooms on the server.
schema:
type: object
description: A list of the rooms on the server.
properties:
chunk:
title: "PublicRoomsChunks"
type: array
description: |-
A paginated chunk of public rooms.
items:
type: object
title: "PublicRoomsChunk"
properties:
aliases:
type: array
description: |-
Aliases of the room. May be empty.
items:
type: string
name:
type: string
description: |-
The name of the room, if any. May be null.
num_joined_members:
type: number
description: |-
The number of members joined to the room.
room_id:
type: string
description: |-
The ID of the room.
topic:
type: string
description: |-
The topic of the room, if any. May be null.
world_readable:
type: boolean
description: |-
Whether the room may be viewed by guest users without joining.
guest_can_join:
type: boolean
description: |-
Whether guest users may join the room and participate in it.
If they can, they will be subject to ordinary power level
rules like any other user.
start:
type: string
description: |-
A pagination token for the response.
end:
type: string
description: |-
A pagination token for the response.
examples:
application/json: |-
{
"chunk": [
{
"aliases": ["#murrays:cheese.bar"],
"guest_can_join": false,
"name": "CHEESE",
"num_joined_members": 37,
"room_id": "!ol19s:bleecker.street",
"topic": "Tasty tasty cheese",
"world_readable": true
}
],
"start": "p190q",
"end": "p1902"
}
400:
description: >
The request body is malformed or the room alias specified is already taken.
tags:
- Room discovery

@ -1,12 +1,12 @@
swagger: '2.0'
info:
title: "Matrix Client-Server v1 Registration and Login API"
title: "Matrix Client-Server Registration and Login API"
version: "1.0.0"
host: localhost:8008
schemes:
- https
- http
basePath: /_matrix/client/api/v1
basePath: /_matrix/client/%CLIENT_MAJOR_VERSION%
consumes:
- application/json
produces:
@ -81,7 +81,7 @@ paths:
(optional) A ``refresh_token`` may be exchanged for a new ``access_token`` using the /tokenrefresh API endpoint.
home_server:
type: string
description: The hostname of the Home Server on which the account has been registered.
description: The hostname of the homeserver on which the account has been registered.
400:
description: |-
Part of the request was invalid. For example, the login type may not be recognised.
@ -101,6 +101,8 @@ paths:
description: This request was rate-limited.
schema:
"$ref": "definitions/error.yaml"
tags:
- Session management
"/tokenrefresh":
post:
summary: Exchanges a refresh token for an access token.
@ -158,3 +160,5 @@ paths:
description: This request was rate-limited.
schema:
"$ref": "definitions/error.yaml"
tags:
- Session management

@ -1,12 +1,12 @@
swagger: '2.0'
info:
title: "Matrix Client-Server v1 Rooms API"
title: "Matrix Client-Server Rooms API"
version: "1.0.0"
host: localhost:8008
schemes:
- https
- http
basePath: /_matrix/client/api/v1
basePath: /_matrix/client/%CLIENT_MAJOR_VERSION%
consumes:
- application/json
produces:
@ -129,3 +129,5 @@ paths:
403:
description: >
You aren't a member of the room.
tags:
- Room participation

@ -1,12 +1,12 @@
swagger: '2.0'
info:
title: "Matrix Client-Server v1 Sync API"
title: "Matrix Client-Server Sync API"
version: "1.0.0"
host: localhost:8008
schemes:
- https
- http
basePath: /_matrix/client/api/v1
basePath: /_matrix/client/%CLIENT_MAJOR_VERSION%
consumes:
- application/json
produces:
@ -60,7 +60,7 @@ paths:
"origin_server_ts": 1432804485886,
"room_id": "!TmaZBKYIFrIPVGoUYp:localhost",
"type": "m.room.message",
"user_id": "@bob:localhost"
"sender": "@bob:localhost"
}
]
}
@ -84,9 +84,11 @@ paths:
type: object
title: Event
allOf:
- "$ref": "core-event-schema/room_event.json"
- "$ref": "../../event-schemas/schema/core-event-schema/room_event.yaml"
400:
description: "Bad pagination ``from`` parameter."
tags:
- Room participation
"/initialSync":
get:
summary: Get the user's current state.
@ -131,6 +133,14 @@ paths:
"type": "m.presence"
}
],
"account_data": [
{
"type": "org.example.custom.config",
"content": {
"custom_config_key": "custom_config_value"
}
}
],
"rooms": [
{
"membership": "join",
@ -146,7 +156,7 @@ paths:
"origin_server_ts": 1432804485886,
"room_id": "!TmaZBKYIFrIPVGoUYp:localhost",
"type": "m.room.message",
"user_id": "@alice:localhost"
"sender": "@alice:localhost"
},
{
"age": 343511809,
@ -158,7 +168,7 @@ paths:
"origin_server_ts": 1432804487480,
"room_id": "!TmaZBKYIFrIPVGoUYp:localhost",
"type": "m.room.message",
"user_id": "@bob:localhost"
"sender": "@bob:localhost"
}
],
"end": "s3456_9_0",
@ -176,13 +186,12 @@ paths:
"room_id": "!TmaZBKYIFrIPVGoUYp:localhost",
"state_key": "",
"type": "m.room.join_rules",
"user_id": "@alice:localhost"
"sender": "@alice:localhost"
},
{
"age": 6547561012,
"content": {
"avatar_url": "mxc://localhost/fzysBrHpPEeTGANCVLXWXNMI#auto",
"displayname": null,
"membership": "join"
},
"event_id": "$1426600438280zExKY:localhost",
@ -191,7 +200,7 @@ paths:
"room_id": "!TmaZBKYIFrIPVGoUYp:localhost",
"state_key": "@alice:localhost",
"type": "m.room.member",
"user_id": "@alice:localhost"
"sender": "@alice:localhost"
},
{
"age": 7148267200,
@ -203,7 +212,7 @@ paths:
"room_id": "!TmaZBKYIFrIPVGoUYp:localhost",
"state_key": "",
"type": "m.room.create",
"user_id": "@alice:localhost"
"sender": "@alice:localhost"
},
{
"age": 1622568720,
@ -218,7 +227,7 @@ paths:
"room_id": "!TmaZBKYIFrIPVGoUYp:localhost",
"state_key": "@bob:localhost",
"type": "m.room.member",
"user_id": "@bob:localhost"
"sender": "@bob:localhost"
},
{
"age": 7148267004,
@ -242,10 +251,22 @@ paths:
"room_id": "!TmaZBKYIFrIPVGoUYp:localhost",
"state_key": "",
"type": "m.room.power_levels",
"user_id": "@alice:localhost"
"sender": "@alice:localhost"
}
],
"visibility": "private"
"visibility": "private",
"account_data": [
{
"type": "m.tag",
"content": {"tags": {"work": {"order": 1}}}
},
{
"type": "org.example.custom.room.config",
"content": {
"custom_config_key": "custom_config_value"
}
}
]
}
]
}
@ -265,7 +286,7 @@ paths:
type: object
title: Event
allOf:
- "$ref": "core-event-schema/event.json"
- "$ref": "../../event-schemas/schema/core-event-schema/event.yaml"
rooms:
type: array
items:
@ -284,7 +305,7 @@ paths:
title: "InviteEvent"
description: "The invite event if ``membership`` is ``invite``"
allOf:
- "$ref": "v1-event-schema/m.room.member"
- "$ref": "../../event-schemas/schema/m.room.member"
messages:
type: object
title: PaginationChunk
@ -312,7 +333,7 @@ paths:
type: object
title: RoomEvent
allOf:
- "$ref": "core-event-schema/room_event.json"
- "$ref": "../../event-schemas/schema/core-event-schema/room_event.yaml"
required: ["start", "end", "chunk"]
state:
type: array
@ -325,17 +346,29 @@ paths:
title: StateEvent
type: object
allOf:
- "$ref": "core-event-schema/state_event.json"
- "$ref": "../../event-schemas/schema/core-event-schema/state_event.yaml"
visibility:
type: string
enum: ["private", "public"]
description: |-
Whether this room is visible to the ``/publicRooms`` API
or not."
account_data:
type: array
description: |-
The private data that this user has attached to
this room.
items:
title: Event
type: object
allOf:
- "$ref": "../../event-schemas/schema/core-event-schema/event.yaml"
required: ["room_id", "membership"]
required: ["end", "rooms", "presence"]
404:
description: There is no avatar URL for this user or this user does not exist.
tags:
- Room participation
"/events/{eventId}":
get:
summary: Get a single event by event ID.
@ -362,12 +395,14 @@ paths:
"msgtype": "m.text"
},
"room_id:": "!wfgy43Sg4a:matrix.org",
"user_id": "@bob:matrix.org",
"sender": "@bob:matrix.org",
"event_id": "$asfDuShaf7Gafaw:matrix.org",
"type": "m.room.message"
}
schema:
allOf:
- "$ref": "core-event-schema/event.json"
- "$ref": "../../event-schemas/schema/core-event-schema/event.yaml"
404:
description: The event was not found or you do not have permission to read this event.
tags:
- Room participation

@ -1,12 +1,12 @@
swagger: '2.0'
info:
title: "Matrix Client-Server v1 Presence API"
title: "Matrix Client-Server Presence API"
version: "1.0.0"
host: localhost:8008
schemes:
- https
- http
basePath: /_matrix/client/api/v1
basePath: /_matrix/client/%CLIENT_MAJOR_VERSION%
consumes:
- application/json
produces:
@ -67,6 +67,8 @@ paths:
description: This request was rate-limited.
schema:
"$ref": "definitions/error.yaml"
tags:
- Presence
get:
summary: Get this user's presence state.
description: |-
@ -85,8 +87,7 @@ paths:
application/json: |-
{
"presence": "unavailable",
"last_active_ago": 420845,
"status_msg": null
"last_active_ago": 420845
}
schema:
type: object
@ -107,6 +108,8 @@ paths:
description: |-
There is no presence state for this user. This user may not exist or
isn't exposing presence information to you.
tags:
- Presence
"/presence/list/{userId}":
post:
summary: Add or remove users from this presence list.
@ -161,6 +164,8 @@ paths:
description: This request was rate-limited.
schema:
"$ref": "definitions/error.yaml"
tags:
- Presence
get:
summary: Get presence events for this presence list.
description: |-
@ -205,4 +210,6 @@ paths:
type: object
title: PresenceEvent
allOf:
- "$ref": "core-event-schema/event.json"
- "$ref": "../../event-schemas/schema/core-event-schema/event.yaml"
tags:
- Presence

@ -1,12 +1,12 @@
swagger: '2.0'
info:
title: "Matrix Client-Server v1 Profile API"
title: "Matrix Client-Server Profile API"
version: "1.0.0"
host: localhost:8008
schemes:
- https
- http
basePath: /_matrix/client/api/v1
basePath: /_matrix/client/%CLIENT_MAJOR_VERSION%
consumes:
- application/json
produces:
@ -59,6 +59,8 @@ paths:
description: This request was rate-limited.
schema:
"$ref": "definitions/error.yaml"
tags:
- User data
get:
summary: Get the user's display name.
description: |-
@ -88,6 +90,8 @@ paths:
description: The user's display name if they have set one.
404:
description: There is no display name for this user or this user does not exist.
tags:
- User data
"/profile/{userId}/avatar_url":
put:
summary: Set the user's avatar URL.
@ -129,6 +133,8 @@ paths:
description: This request was rate-limited.
schema:
"$ref": "definitions/error.yaml"
tags:
- User data
get:
summary: Get the user's avatar URL.
description: |-
@ -158,6 +164,8 @@ paths:
description: The user's avatar URL if they have set one.
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.
@ -193,3 +201,5 @@ paths:
description: The user's display name if they have set one.
404:
description: There is no profile information for this user or this user does not exist.
tags:
- User data

@ -6,7 +6,7 @@ host: localhost:8008
schemes:
- https
- http
basePath: /_matrix/push/v1
basePath: /_matrix/push/%CLIENT_MAJOR_VERSION%
consumes:
- application/json
produces:
@ -189,4 +189,5 @@ paths:
items:
type: string
description: A pushkey
tags:
- Push notifications

@ -1,12 +1,12 @@
swagger: '2.0'
info:
title: "Matrix Client-Server v1 Push API"
title: "Matrix Client-Server Push API"
version: "1.0.0"
host: localhost:8008
schemes:
- https
- http
basePath: /_matrix/client/api/v1
basePath: /_matrix/client/%CLIENT_MAJOR_VERSION%
consumes:
- application/json
produces:
@ -60,7 +60,6 @@ paths:
Max length, 512 bytes.
kind:
type: string
enum: ["http", null]
description: |-
The kind of pusher to configure. ``"http"`` makes a pusher that
sends HTTP pokes. ``null`` deletes the pusher.
@ -114,7 +113,7 @@ paths:
description: |-
If true, the homeserver should add another pusher with the
given pushkey and App ID in addition to any others with
different user IDs. Otherwise, the Home Server must remove any
different user IDs. Otherwise, the homeserver must remove any
other pushers with the same App ID and pushkey for different
users. The default is ``false``.
required: ['profile_tag', 'kind', 'app_id', 'app_display_name',
@ -141,4 +140,5 @@ paths:
description: This request was rate-limited.
schema:
"$ref": "definitions/error.yaml"
tags:
- Push notifications

@ -1,12 +1,12 @@
swagger: '2.0'
info:
title: "Matrix Client-Server v1 Push Rules API"
title: "Matrix Client-Server Push Rules API"
version: "1.0.0"
host: localhost:8008
schemes:
- https
- http
basePath: /_matrix/client/api/v1
basePath: /_matrix/client/%CLIENT_MAJOR_VERSION%
consumes:
- application/json
produces:
@ -45,14 +45,14 @@ paths:
description: The ruleset for this profile tag.
title: Ruleset
allOf: [
"$ref": "definitions/push_ruleset.json"
"$ref": "definitions/push_ruleset.yaml"
]
global:
type: object
description: The global ruleset.
title: Ruleset
allOf: [
"$ref": "definitions/push_ruleset.json"
"$ref": "definitions/push_ruleset.yaml"
]
examples:
application/json: |-
@ -245,6 +245,8 @@ paths:
]
}
}
tags:
- Push notifications
"/pushrules/{scope}/{kind}/{ruleId}":
get:
summary: Retrieve a push rule.
@ -295,8 +297,10 @@ paths:
description: The push rule.
title: PushRule
allOf: [
"$ref": "definitions/push_rule.json"
"$ref": "definitions/push_rule.yaml"
]
tags:
- Push notifications
delete:
summary: Delete a push rule.
description: |-
@ -335,6 +339,8 @@ paths:
{}
schema:
type: object # empty json object
tags:
- Push notifications
put:
summary: Add or change a push rule.
description: |-
@ -414,7 +420,7 @@ paths:
items:
type: object
title: conditions
allOf: [ "$ref": "definitions/push_condition.json" ]
allOf: [ "$ref": "definitions/push_condition.yaml" ]
required: ["actions"]
responses:
200:
@ -438,6 +444,8 @@ paths:
description: This request was rate-limited.
schema:
"$ref": "definitions/error.yaml"
tags:
- Push notifications
"/pushrules/{scope}/{kind}/{ruleId}/enabled":
put:
summary: "Enable or disable a push rule."
@ -470,14 +478,21 @@ paths:
description: |
The identifier for the rule.
- in: body
name: <body>
name: body
description: |
Whether the push rule is enabled or not.
required: true
schema:
type: object
properties:
enabled:
type: boolean
description: Whether the push rule is enabled or not.
required: ["enabled"]
example: |-
true
{
"enabled": true
}
responses:
200:
description: The push rule was enabled or disabled.
@ -485,4 +500,6 @@ paths:
application/json: |-
{}
schema:
type: object # empty json object
type: object
tags:
- Push notifications

@ -1,12 +1,12 @@
swagger: '2.0'
info:
title: "Matrix Client-Server v2 Receipts API"
title: "Matrix Client-Server Receipts API"
version: "1.0.0"
host: localhost:8008
schemes:
- https
- http
basePath: /_matrix/client/v2_alpha
basePath: /_matrix/client/%CLIENT_MAJOR_VERSION%
consumes:
- application/json
produces:
@ -67,3 +67,5 @@ paths:
description: This request was rate-limited.
schema:
"$ref": "definitions/error.yaml"
tags:
- Room participation

@ -0,0 +1,84 @@
swagger: '2.0'
info:
title: "Matrix Client-Server message redaction API"
version: "1.0.0"
host: localhost:8008
schemes:
- https
- http
basePath: /_matrix/client/api/%CLIENT_MAJOR_VERSION%
consumes:
- application/json
produces:
- application/json
securityDefinitions:
accessToken:
type: apiKey
description: The user_id or application service access_token
name: access_token
in: query
paths:
"/rooms/{roomId}/redact/{eventId}/{txnId}":
put:
summary: Strips all non-integrity-critical information out of an event.
description: |-
Strips all information out of an event which isn't critical to the
integrity of the server-side representation of the room.
This cannot be undone.
Users may redact their own events, and any user with a power level
greater than or equal to the `redact` power level of the room may
redact events there.
security:
- accessToken: []
parameters:
- in: path
type: string
name: roomId
description: The room from which to redact the event.
required: true
x-example: "!637q39766251:example.com"
- in: path
type: string
name: eventId
description: The ID of the event to redact
required: true
x-example: "bai2b1i9:matrix.org"
- in: path
name: txnId
type: string
description: |-
The transaction ID for this event. Clients should generate a
unique ID; it will be used by the server to ensure idempotency of requests.
required: true
x-example: "37"
- in: body
name: body
schema:
type: object
example: |-
{
"reason": "Indecent material"
}
properties:
reason:
type: string
description: The reason for the event being redacted.
responses:
200:
description: "An ID for the redaction event."
examples:
application/json: |-
{
"event_id": "YUwQidLecu"
}
schema:
type: object
properties:
event_id:
type: string
description: |-
A unique identifier for the event.
tags:
- Room participation

@ -1,12 +1,12 @@
swagger: '2.0'
info:
title: "Matrix Client-Server v2 Registration API"
title: "Matrix Client-Server Registration API"
version: "1.0.0"
host: localhost:8008
schemes:
- https
- http
basePath: /_matrix/client/api/v2_alpha
basePath: /_matrix/client/%CLIENT_MAJOR_VERSION%
consumes:
- application/json
produces:
@ -17,7 +17,24 @@ paths:
summary: Register for an account on this homeserver.
description: |-
Register for an account on this homeserver.
There are two kinds of user account:
- `user` accounts. These accounts may use the full API described in this specification.
- `guest` accounts. These accounts may have limited permissions and may not be supported by all servers.
parameters:
- in: query
name: kind
type: string
x-example: guest
required: false
default: user
enum:
- guest
- user
description: The kind of account to register. Defaults to `user`.
- in: body
name: body
schema:
@ -77,7 +94,7 @@ paths:
(optional) A ``refresh_token`` may be exchanged for a new ``access_token`` using the /tokenrefresh API endpoint.
home_server:
type: string
description: The hostname of the Home Server on which the account has been registered.
description: The hostname of the homeserver on which the account has been registered.
400:
description: |-
Part of the request was invalid. This may include one of the following error codes:
@ -90,7 +107,7 @@ paths:
including after authentication if the requested user ID was registered
whilst the client was performing authentication.
Home Servers MUST perform the relevant checks and return these codes before
Homeservers MUST perform the relevant checks and return these codes before
performing `User-Interactive Authentication`_, although they may also return
them after authentication is completed if, for example, the requested user ID
was registered whilst the client was performing authentication.
@ -104,3 +121,5 @@ paths:
description: This request was rate-limited.
schema:
"$ref": "definitions/error.yaml"
tags:
- User data

@ -1,12 +1,12 @@
swagger: '2.0'
info:
title: "Matrix Client-Server v1 state event send API"
title: "Matrix Client-Server message event send API"
version: "1.0.0"
host: localhost:8008
schemes:
- https
- http
basePath: /_matrix/client/api/v1
basePath: /_matrix/client/%CLIENT_MAJOR_VERSION%
consumes:
- application/json
produces:
@ -18,29 +18,24 @@ securityDefinitions:
name: access_token
in: query
paths:
"/rooms/{roomId}/state/{eventType}/{stateKey}":
"/rooms/{roomId}/send/{eventType}/{txnId}":
put:
summary: Send a message event to the given room.
description: |
State events can be sent using this endpoint. These events will be
overwritten if ``<room id>``, ``<event type>`` and ``<state key>`` all
match. If the state event has an empty ``state_key``, it can be
omitted from the path.
Requests to this endpoint **cannot use transaction IDs**
like other ``PUT`` paths because they cannot be differentiated from the
``state_key``. Furthermore, ``POST`` is unsupported on state paths.
description: |-
This endpoint is used to send a message event to a room. Message events
allow access to historical events and pagination, making them suited
for "once-off" activity in a room.
The body of the request should be the content object of the event; the
fields in this object will vary depending on the type of event. See
`Room Events`_ for the ``m.`` event specification.
`Room Events`_ for the m. event specification.
security:
- accessToken: []
parameters:
- in: path
type: string
name: roomId
description: The room to set the state in
description: The room to send the event to.
required: true
x-example: "!636q39766251:example.com"
- in: path
@ -48,20 +43,23 @@ paths:
name: eventType
description: The type of event to send.
required: true
x-example: "m.room.name"
x-example: "m.room.message"
- in: path
name: txnId
type: string
name: stateKey
description: The state_key for the state to send. Defaults to the empty string.
description: |-
The transaction ID for this event. Clients should generate a
unique ID; it will be used by the server to ensure idempotency of requests.
required: true
x-example: ""
x-example: "35"
- in: body
name: body
schema:
type: object
example: |-
{
"name": "New name for the room"
"msgtype": "m.text",
"body": "hello"
}
responses:
200:
@ -78,3 +76,5 @@ paths:
type: string
description: |-
A unique identifier for the event.
tags:
- Room participation

@ -1,12 +1,12 @@
swagger: '2.0'
info:
title: "Matrix Client-Server v1 message event send API"
title: "Matrix Client-Server state event send API"
version: "1.0.0"
host: localhost:8008
schemes:
- https
- http
basePath: /_matrix/client/api/v1
basePath: /_matrix/client/%CLIENT_MAJOR_VERSION%
consumes:
- application/json
produces:
@ -18,24 +18,29 @@ securityDefinitions:
name: access_token
in: query
paths:
"/rooms/{roomId}/send/{eventType}/{txnId}":
"/rooms/{roomId}/state/{eventType}/{stateKey}":
put:
summary: Send a message event to the given room.
description: |-
This endpoint is used to send a message event to a room. Message events
allow access to historical events and pagination, making them suited
for "once-off" activity in a room.
summary: Send a state event to the given room.
description: |
State events can be sent using this endpoint. This endpoint is
equivalent to calling `/rooms/{roomId}/state/{eventType}/{stateKey}`
with an empty `stateKey`. Previous state events with matching
`<roomId>` and `<eventType>`, and empty `<stateKey>`, will be overwritten.
Requests to this endpoint **cannot use transaction IDs**
like other ``PUT`` paths because they cannot be differentiated from the
``state_key``. Furthermore, ``POST`` is unsupported on state paths.
The body of the request should be the content object of the event; the
fields in this object will vary depending on the type of event. See
`Room Events`_ for the m. event specification.
`Room Events`_ for the ``m.`` event specification.
security:
- accessToken: []
parameters:
- in: path
type: string
name: roomId
description: The room to send the event to.
description: The room to set the state in
required: true
x-example: "!636q39766251:example.com"
- in: path
@ -43,23 +48,20 @@ paths:
name: eventType
description: The type of event to send.
required: true
x-example: "m.room.message"
x-example: "m.room.name"
- in: path
name: txnId
type: string
description: |-
The transaction ID for this event. Clients should generate a
unique ID; it will be used by the server to ensure idempotency of requests.
name: stateKey
description: The state_key for the state to send. Defaults to the empty string.
required: true
x-example: "35"
x-example: ""
- in: body
name: body
schema:
type: object
example: |-
{
"msgtype": "m.text",
"body": "hello"
"name": "New name for the room"
}
responses:
200:
@ -76,21 +78,30 @@ paths:
type: string
description: |-
A unique identifier for the event.
"/rooms/{roomId}/send/{eventType}":
post:
summary: Send a message event to the given room.
description: |-
This endpoint can be used to send a message event to a room; however
the lack of a transaction ID means that it is possible to cause message
duplication if events are resent on error, so it is preferable to use
`PUT /_matrix/client/api/v1/rooms/{roomId}/send/{eventType}/{txnId}`_.
tags:
- Room participation
"/rooms/{roomId}/state/{eventType}":
put:
summary: Send a state event to the given room.
description: |
State events can be sent using this endpoint. These events will be
overwritten if ``<room id>``, ``<event type>`` and ``<state key>`` all
match. This endpoint forces the state key to be the empty string.
Requests to this endpoint **cannot use transaction IDs**
like other ``PUT`` paths because they cannot be differentiated from the
``state_key``. Furthermore, ``POST`` is unsupported on state paths.
The body of the request should be the content object of the event; the
fields in this object will vary depending on the type of event. See
`Room Events`_ for the ``m.`` event specification.
security:
- accessToken: []
parameters:
- in: path
type: string
name: roomId
description: The room to send the event to.
description: The room to set the state in
required: true
x-example: "!636q39766251:example.com"
- in: path
@ -98,15 +109,14 @@ paths:
name: eventType
description: The type of event to send.
required: true
x-example: "m.room.message"
x-example: "m.room.name"
- in: body
name: body
schema:
type: object
example: |-
{
"msgtype": "m.text",
"body": "hello"
"name": "New name for the room"
}
responses:
200:
@ -123,3 +133,5 @@ paths:
type: string
description: |-
A unique identifier for the event.
tags:
- Room participation

@ -1,12 +1,12 @@
swagger: '2.0'
info:
title: "Matrix Client-Server v1 Rooms API"
title: "Matrix Client-Server Rooms API"
version: "1.0.0"
host: localhost:8008
schemes:
- https
- http
basePath: /_matrix/client/api/v1
basePath: /_matrix/client/%CLIENT_MAJOR_VERSION%
consumes:
- application/json
produces:
@ -44,7 +44,7 @@ paths:
- in: path
type: string
name: stateKey
description: The key of the state to look up. Defaults to the empty string.
description: The key of the state to look up.
required: true
x-example: ""
responses:
@ -61,7 +61,49 @@ paths:
description: >
You aren't a member of the room and weren't previously a
member of the room.
tags:
- Room participation
"/rooms/{roomId}/state/{eventType}":
get:
summary: Get the state identified by the type, with the empty state key.
description: |-
Looks up the contents of a state event in a room. If the user is
joined to the room then the state is taken from the current
state of the room. If the user has left the room then the state is
taken from the state of the room when they left.
This looks up the state event with the empty state key.
security:
- accessToken: []
parameters:
- in: path
type: string
name: roomId
description: The room to look up the state in.
required: true
x-example: "!636q39766251:example.com"
- in: path
type: string
name: eventType
description: The type of state to look up.
required: true
x-example: "m.room.name"
responses:
200:
description: The content of the state event.
examples:
application/json: |-
{"name": "Example room name"}
schema:
type: object
404:
description: The room has no state with the given type or key.
403:
description: >
You aren't a member of the room and weren't previously a
member of the room.
tags:
- Room participation
"/rooms/{roomId}/state":
get:
summary: Get all state events in the current state of a room.
@ -92,13 +134,12 @@ paths:
"room_id": "!636q39766251:example.com",
"state_key": "",
"type": "m.room.join_rules",
"user_id": "@alice:example.com"
"sender": "@alice:example.com"
},
{
"age": 6547561012,
"content": {
"avatar_url": "mxc://example.com/fzysBrHpPEeTGANCVLXWXNMI#auto",
"displayname": null,
"membership": "join"
},
"event_id": "$1426600438280zExKY:example.com",
@ -107,7 +148,7 @@ paths:
"room_id": "!636q39766251:example.com",
"state_key": "@alice:example.com",
"type": "m.room.member",
"user_id": "@alice:example.com"
"sender": "@alice:example.com"
},
{
"age": 7148267200,
@ -119,7 +160,7 @@ paths:
"room_id": "!636q39766251:example.com",
"state_key": "",
"type": "m.room.create",
"user_id": "@alice:example.com"
"sender": "@alice:example.com"
},
{
"age": 1622568720,
@ -134,7 +175,7 @@ paths:
"room_id": "!636q39766251:example.com",
"state_key": "@bob:example.com",
"type": "m.room.member",
"user_id": "@bob:example.com"
"sender": "@bob:example.com"
},
{
"age": 7148267004,
@ -158,7 +199,7 @@ paths:
"room_id": "!636q39766251:example.com",
"state_key": "",
"type": "m.room.power_levels",
"user_id": "@alice:example.com"
"sender": "@alice:example.com"
}
]
schema:
@ -173,12 +214,13 @@ paths:
title: StateEvent
type: object
allOf:
- "$ref": "core-event-schema/state_event.json"
- "$ref": "../../event-schemas/schema/core-event-schema/state_event.yaml"
403:
description: >
You aren't a member of the room and weren't previously a
member of the room.
tags:
- Room participation
"/rooms/{roomId}/initialSync":
get:
summary: Snapshot the current state of a room and its most recent messages.
@ -212,7 +254,7 @@ paths:
"origin_server_ts": 1432804485886,
"room_id": "!636q39766251:example.com",
"type": "m.room.message",
"user_id": "@alice:example.com"
"sender": "@alice:example.com"
},
{
"age": 343511809,
@ -224,7 +266,7 @@ paths:
"origin_server_ts": 1432804487480,
"room_id": "!636q39766251:example.com",
"type": "m.room.message",
"user_id": "@bob:example.com"
"sender": "@bob:example.com"
}
],
"end": "s3456_9_0",
@ -242,13 +284,12 @@ paths:
"room_id": "!636q39766251:example.com",
"state_key": "",
"type": "m.room.join_rules",
"user_id": "@alice:example.com"
"sender": "@alice:example.com"
},
{
"age": 6547561012,
"content": {
"avatar_url": "mxc://example.com/fzysBrHpPEeTGANCVLXWXNMI#auto",
"displayname": null,
"membership": "join"
},
"event_id": "$1426600438280zExKY:example.com",
@ -257,7 +298,7 @@ paths:
"room_id": "!636q39766251:example.com",
"state_key": "@alice:example.com",
"type": "m.room.member",
"user_id": "@alice:example.com"
"sender": "@alice:example.com"
},
{
"age": 7148267200,
@ -269,7 +310,7 @@ paths:
"room_id": "!636q39766251:example.com",
"state_key": "",
"type": "m.room.create",
"user_id": "@alice:example.com"
"sender": "@alice:example.com"
},
{
"age": 1622568720,
@ -284,7 +325,7 @@ paths:
"room_id": "!636q39766251:example.com",
"state_key": "@bob:example.com",
"type": "m.room.member",
"user_id": "@bob:example.com"
"sender": "@bob:example.com"
},
{
"age": 7148267004,
@ -308,10 +349,14 @@ paths:
"room_id": "!636q39766251:example.com",
"state_key": "",
"type": "m.room.power_levels",
"user_id": "@alice:example.com"
"sender": "@alice:example.com"
}
],
"visibility": "private"
"visibility": "private",
"account_data": [{
"type": "m.tag",
"content": {"tags": {"work": {"order": "1"}}}
}]
}
schema:
title: RoomInfo
@ -351,7 +396,7 @@ paths:
type: object
title: RoomEvent
allOf:
- "$ref": "core-event-schema/room_event.json"
- "$ref": "../../event-schemas/schema/core-event-schema/room_event.yaml"
required: ["start", "end", "chunk"]
state:
type: array
@ -364,19 +409,29 @@ paths:
title: StateEvent
type: object
allOf:
- "$ref": "core-event-schema/state_event.json"
- "$ref": "../../event-schemas/schema/core-event-schema/state_event.yaml"
visibility:
type: string
enum: ["private", "public"]
description: |-
Whether this room is visible to the ``/publicRooms`` API
or not."
required: ["room_id", "membership"]
account_data:
type: array
description: |-
The private data that this user has attached to this room.
items:
title: Event
type: object
allOf:
- "$ref": "../../event-schemas/schema/core-event-schema/event.yaml"
required: ["room_id"]
403:
description: >
You aren't a member of the room and weren't previously a
member of the room.
tags:
- Room participation
"/rooms/{roomId}/members":
get:
summary: Get the m.room.member events for the room.
@ -403,7 +458,6 @@ paths:
"age": 6547561012,
"content": {
"avatar_url": "mxc://example.com/fzysBrHpPEeTGANCVLXWXNMI#auto",
"displayname": null,
"membership": "join"
},
"event_id": "$1426600438280zExKY:example.com",
@ -412,7 +466,7 @@ paths:
"room_id": "!636q39766251:example.com",
"state_key": "@alice:example.com",
"type": "m.room.member",
"user_id": "@alice:example.com"
"sender": "@alice:example.com"
},
{
"age": 1622568720,
@ -427,7 +481,7 @@ paths:
"room_id": "!636q39766251:example.com",
"state_key": "@bob:example.com",
"type": "m.room.member",
"user_id": "@bob:example.com"
"sender": "@bob:example.com"
}
]
}
@ -440,9 +494,10 @@ paths:
title: MemberEvent
type: object
allOf:
- "$ref": "v1-event-schema/m.room.member"
- "$ref": "../../event-schemas/schema/m.room.member"
403:
description: >
You aren't a member of the room and weren't previously a
member of the room.
tags:
- Room participation

@ -1,12 +1,12 @@
swagger: '2.0'
info:
title: "Matrix Client-Server v1 Search API"
title: "Matrix Client-Server Search API"
version: "1.0.0"
host: localhost:8008
schemes:
- https
- http
basePath: /_matrix/client/api/v1
basePath: /_matrix/client/%CLIENT_MAJOR_VERSION%
consumes:
- application/json
produces:
@ -67,7 +67,7 @@ paths:
title: Filter
description: |-
The filter to apply to search results.
This has the same format as v2 filter API.
This has the same format as filter API.
required: ["search_term"]
required: ["search_categories"]
responses:
@ -111,7 +111,7 @@ paths:
title: Event
description: The event that matched.
allOf:
- "$ref": "core-event-schema/room_event.json"
- "$ref": "../../event-schemas/schema/core-event-schema/room_event.yaml"
examples:
application/json: |-
{
@ -131,7 +131,7 @@ paths:
"origin_server_ts": 1444298308034,
"room_id": "!qPewotXpIctQySfjSy:localhost",
"type": "m.room.message",
"user_id": "@test:localhost"
"sender": "@test:localhost"
}
}
}
@ -144,3 +144,5 @@ paths:
description: This request was rate-limited.
schema:
"$ref": "definitions/error.yaml"
tags:
- Search

@ -1,11 +1,11 @@
swagger: '2.0'
info:
title: "Matrix Client-Server v2 sync API"
title: "Matrix Client-Server sync API"
version: "1.0.0"
host: localhost:8008
schemes:
- https
basePath: /_matrix/client/v2_alpha
basePath: /_matrix/client/%CLIENT_MAJOR_VERSION%
consumes:
- application/json
produces:
@ -95,33 +95,26 @@ paths:
description: |-
Updates to rooms.
properties:
joined:
title: Joined
join:
title: Joined Rooms
type: object
description: |-
The rooms that the user has joined.
additionalProperties:
title: Joined Room
type: object
properties:
event_map:
title: EventMap
type: object
description: |-
A map from event ID to events for this room. The
events are referenced from the ``timeline`` and
``state`` keys for this room.
additionalProperties:
title: Event
description: An event object.
type: object
allOf:
- $ref: "core-event-schema/event.json"
state:
title: State
type: object
description: |-
The state updates for the room.
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
``timeline``, if ``since`` is not given, or
``full_state`` is true).
allOf:
- $ref: "definitions/room_event_batch.json"
- $ref: "definitions/event_batch.yaml"
timeline:
title: Timeline
type: object
@ -129,7 +122,7 @@ paths:
The timeline of messages and state changes in the
room.
allOf:
- $ref: "definitions/timeline_batch.json"
- $ref: "definitions/timeline_batch.yaml"
ephemeral:
title: Ephemeral
type: object
@ -138,9 +131,17 @@ paths:
recorded in the timeline or state of the room.
e.g. typing.
allOf:
- $ref: "definitions/event_batch.json"
invited:
title: Invited
- $ref: "definitions/event_batch.yaml"
account_data:
title: Account Data
type: object
description: |-
The private data that this user has attached to
this room.
allOf:
- $ref: "definitions/event_batch.yaml"
invite:
title: Invited Rooms
type: object
description: |-
The rooms that the user has been invited to.
@ -165,38 +166,23 @@ paths:
delta against the archived ``state`` not the
``invite_state``.
allOf:
- $ref: "definitions/event_batch.json"
archived:
title: Archived
- $ref: "definitions/event_batch.yaml"
leave:
title: Left rooms
type: object
description: |-
The rooms that the user has left or been banned from. The
entries in the room_map will lack an ``ephemeral`` key.
The rooms that the user has left or been banned from.
additionalProperties:
title: Archived Room
title: Left Room
type: object
properties:
event_map:
title: EventMap
type: object
description: |-
A map from event ID to events for this room. The
events are referenced from the ``timeline`` and
``state`` keys for this room.
additionalProperties:
title: Event
description: An event object.
type: object
allOf:
- $ref: "core-event-schema/event.json"
state:
title: State
type: object
description: |-
The state updates for the room up to the point when
the user left.
The state updates for the room up to the start of the timeline.
allOf:
- $ref: "definitions/room_event_batch.json"
- $ref: "definitions/event_batch.yaml"
timeline:
title: Timeline
type: object
@ -204,14 +190,14 @@ paths:
The timeline of messages and state changes in the
room up to the point when the user left.
allOf:
- $ref: "definitions/timeline_batch.json"
- $ref: "definitions/timeline_batch.yaml"
presence:
title: Presence
type: object
description: |-
The updates to the presence status of other users.
allOf:
- $ref: "definitions/event_batch.json"
- $ref: "definitions/event_batch.yaml"
examples:
application/json: |-
{
@ -225,45 +211,54 @@ paths:
}
]
},
"account_data": {
"events": [
{
"type": "org.example.custom.config",
"content": {
"custom_config_key": "custom_config_value"
}
}
]
},
"rooms": {
"joined": {
"join": {
"!726s6s6q:example.com": {
"event_map": {
"$66697273743031:example.com": {
"state": {
"events": [
{
"sender": "@alice:example.com",
"type": "m.room.member",
"state_key": "@alice:example.com",
"content": {"membership": "join"},
"origin_server_ts": 1417731086795
"origin_server_ts": 1417731086795,
"event_id": "$66697273743031:example.com"
}
]
},
"$7365636s6r6432:example.com": {
"timeline": {
"events": [
{
"sender": "@bob:example.com",
"type": "m.room.member",
"state_key": "@bob:example.com",
"content": {"membership": "join"},
"origin_server_ts": 1417731086795
"prev_content": {"membership": "invite"},
"origin_server_ts": 1417731086795,
"event_id": "$7365636s6r6432:example.com"
},
"$74686972643033:example.com": {
{
"sender": "@alice:example.com",
"type": "m.room.message",
"unsigned": {"age": "124524", "txn_id": "1234"},
"age": 124524,
"txn_id": "1234",
"content": {
"body": "I am a fish",
"msgtype": "m.text"
},
"origin_server_ts": 1417731086797
"origin_server_ts": 1417731086797,
"event_id": "$74686972643033:example.com"
}
},
"state": {
"events": [
"$66697273743031:example.com",
"$7365636s6r6432:example.com"
]
},
"timeline": {
"events": [
"$7365636s6r6432:example.com",
"$74686972643033:example.com"
],
"limited": true,
"prev_batch": "t34-23535_0_0"
@ -271,15 +266,28 @@ paths:
"ephemeral": {
"events": [
{
"room_id": "!726s6s6q:example.com",
"type": "m.typing",
"content": {"user_ids": ["@alice:example.com"]}
}
]
},
"account_data": {
"events": [
{
"type": "m.tag",
"content": {"tags": {"work": {"order": 1}}}
},
{
"type": "org.example.custom.room.config",
"content": {
"custom_config_key": "custom_config_value"
}
}
]
}
}
},
"invited": {
"invite": {
"!696r7674:example.com": {
"invite_state": {
"events": [
@ -299,6 +307,8 @@ paths:
}
}
},
"archived": {}
"leave": {}
}
}
tags:
- Room participation

@ -0,0 +1,153 @@
swagger: '2.0'
info:
title: "Matrix Client-Server tag API"
version: "1.0.0"
host: localhost:8008
schemes:
- https
- http
basePath: /_matrix/client/%CLIENT_MAJOR_VERSION%
consumes:
- application/json
produces:
- application/json
securityDefinitions:
accessToken:
type: apiKey
description: The user_id or application service access_token
name: access_token
in: query
paths:
"/user/{userId}/rooms/{roomId}/tags":
get:
summary: List the tags for a room.
description: |-
List the tags set by a user on a room.
security:
- accessToken: []
parameters:
- in: path
type: string
name: userId
required: true
description: |-
The id of the user to get tags for. The access token must be
authorized to make requests for this user id.
x-example: "@alice:example.com"
- in: path
type: string
name: roomId
required: true
description: |-
The id of the room to get tags for.
x-example: "!726s6s6q:example.com"
responses:
200:
description:
The list of tags for the user for the room.
schema:
type: object
properties:
tags:
title: Tags
type: object
examples:
application/json: |-
{
"tags": {
"work": {"order": "1"},
"pinned": {}
}
}
tags:
- User data
"/user/{userId}/rooms/{roomId}/tags/{tag}":
put:
summary: Add a tag to a room.
description: |-
Add a tag to the room.
security:
- accessToken: []
parameters:
- in: path
type: string
name: userId
required: true
description: |-
The id of the user to add a tag for. The access token must be
authorized to make requests for this user id.
x-example: "@alice:example.com"
- in: path
type: string
name: roomId
required: true
description: |-
The id of the room to add a tag to.
x-example: "!726s6s6q:example.com"
- in: path
type: string
name: tag
required: true
description: |-
The tag to add.
x-example: "work"
- in: body
name: body
required: true
description: |-
Extra data for the tag, e.g. ordering.
schema:
type: object
example: |-
{"order": "1"}
responses:
200:
description:
The tag was successfully added.
schema:
type: object
examples:
application/json: |-
{}
tags:
- User data
delete:
summary: Remove a tag from the room.
description: |-
Remove a tag from the room.
security:
- access_token: []
parameters:
- in: path
type: string
name: userId
required: true
description: |-
The id of the user to remove a tag for. The access token must be
authorized to make requests for this user id.
x-example: "@alice:example.com"
- in: path
type: string
name: roomId
required: true
description: |-
The id of the room to remove a tag from.
x-example: "!726s6s6q:example.com"
- in: path
type: string
name: tag
required: true
description: |-
The tag to remove.
x-example: "work"
responses:
200:
description:
The tag was successfully removed
schema:
type: object
examples:
application/json: |-
{}
tags:
- User data

@ -0,0 +1,125 @@
swagger: '2.0'
info:
title: "Matrix Client-Server Room Membership API for third party identifiers"
version: "1.0.0"
host: localhost:8008
schemes:
- https
- http
basePath: /_matrix/client/%CLIENT_MAJOR_VERSION%
consumes:
- application/json
produces:
- application/json
securityDefinitions:
accessToken:
type: apiKey
description: The user_id or application service access_token
name: access_token
in: query
paths:
"/rooms/{roomId}/invite":
post:
summary: Invite a user to participate in a particular room.
description: |-
.. _invite-by-third-party-id-endpoint:
*Note that there are two forms of this API, which are documented separately.
This version of the API does not require that the inviter know the Matrix
identifier of the invitee, and instead relies on third party identifiers.
The homeserver uses an identity server to perform the mapping from
third party identifier to a Matrix identifier. The other is documented in the*
`joining rooms section`_.
This API invites a user to participate in a particular room.
They do not start participating in the room until they actually join the
room.
Only users currently in a particular room can invite other users to
join that room.
If the identity server did know the Matrix user identifier for the
third party identifier, the homeserver will append a ``m.room.member``
event to the room.
If the identity server does not know a Matrix user identifier for the
passed third party identifier, the homeserver will issue an invitation
which can be accepted upon providing proof of ownership of the third
party identifier. This is achieved by the identity server generating a
token, which it gives to the inviting homeserver. The homeserver will
add an ``m.room.third_party_invite`` event into the graph for the room,
containing that token.
When the invitee binds the invited third party identifier to a Matrix
user ID, the identity server will give the user a list of pending
invitations, each containing:
- The room ID to which they were invited
- The token given to the homeserver
- 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.
.. _joining rooms section: `invite-by-user-id-endpoint`_
security:
- accessToken: []
parameters:
- in: path
type: string
name: roomId
description: The room identifier (not alias) to which to invite the user.
required: true
x-example: "!d41d8cd:matrix.org"
- in: body
name: body
required: true
schema:
type: object
example: |-
{
"id_server": "matrix.org",
"medium": "email",
"address": "cheeky@monkey.com"
}
properties:
id_server:
type: string
description: The hostname+port of the identity server which should be used for third party identifier lookups.
medium:
type: string
# TODO: Link to identity service spec when it eixsts
description: The kind of address being passed in the address field, for example ``email``.
address:
type: string
description: The invitee's third party identifier.
required: ["id_server", "medium", "address"]
responses:
200:
description: The user has been invited to join the room.
examples:
application/json: |-
{}
schema:
type: object
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:
- The invitee has been banned from the room.
- The invitee is already a member of the room.
- The inviter is not currently in the room.
- The inviter's power level is insufficient to invite users to the room.
examples:
application/json: |-
{"errcode": "M_FORBIDDEN", "error": "@cheeky_monkey:matrix.org is banned from the room"}
429:
description: This request was rate-limited.
schema:
"$ref": "definitions/error.yaml"
tags:
- Room membership

@ -1,12 +1,12 @@
swagger: '2.0'
info:
title: "Matrix Client-Server v1 Typing API"
title: "Matrix Client-Server Typing API"
version: "1.0.0"
host: localhost:8008
schemes:
- https
- http
basePath: /_matrix/client/api/v1
basePath: /_matrix/client/%CLIENT_MAJOR_VERSION%
consumes:
- application/json
produces:
@ -74,4 +74,5 @@ paths:
description: This request was rate-limited.
schema:
"$ref": "definitions/error.yaml"
tags:
- Room participation

@ -1 +0,0 @@
v1-event-schema/core-event-schema

@ -1,9 +0,0 @@
{
"type": "object",
"properties": {
"kind": {
"type": "string",
"enum": ["event_match", "profile_tag", "contains_display_name", "room_member_count"]
}
}
}

@ -1,20 +0,0 @@
{
"type": "object",
"properties": {
"default": {
"type": "boolean"
},
"enabled": {
"type": "boolean"
},
"rule_id": {
"type": "string"
},
"actions": {
"items": {
"type": ["object", "string"]
},
"type": "array"
}
}
}

@ -1,60 +0,0 @@
{
"type": "object",
"properties": {
"content": {
"items": {
"type": "object",
"allOf": [
{
"$ref": "push_rule.json"
}
]
},
"type": "array"
},
"override": {
"items": {
"type": "object",
"allOf": [
{
"$ref": "push_rule.json"
}
]
},
"type": "array"
},
"sender": {
"items": {
"type": "object",
"allOf": [
{
"$ref": "push_rule.json"
}
]
},
"type": "array"
},
"underride": {
"items": {
"type": "object",
"allOf": [
{
"$ref": "push_rule.json"
}
]
},
"type": "array"
},
"room": {
"items": {
"type": "object",
"allOf": [
{
"$ref": "push_rule.json"
}
]
},
"type": "array"
}
}
}

@ -1,237 +0,0 @@
swagger: '2.0'
info:
title: "Matrix Client-Server v1 Room Membership API"
version: "1.0.0"
host: localhost:8008
schemes:
- https
- http
basePath: /_matrix/client/api/v1
consumes:
- application/json
produces:
- application/json
securityDefinitions:
accessToken:
type: apiKey
description: The user_id or application service access_token
name: access_token
in: query
paths:
"/rooms/{roomId}/join":
post:
summary: Start the requesting user participating in a particular room.
description: |-
This API starts a user participating in a particular room, if that user
is allowed to participate in that room. After this call, the client is
allowed to see all current state events in the room, and all subsequent
events associated with the room until the user leaves the room.
After a user has joined a room, the room will appear as an entry in the
response of the |initialSync| API.
security:
- accessToken: []
parameters:
- in: path
type: string
name: roomId
description: The room identifier or room alias to join.
required: true
x-example: "#monkeys:matrix.org"
responses:
200:
description: |-
The room has been joined.
The joined room ID must be returned in the ``room_id`` field.
examples:
application/json: |-
{"room_id": "!d41d8cd:matrix.org"}
schema:
type: object
403:
description: |-
You do not have permission to join the room. A meaningful ``errcode`` and description error text will be returned. Example reasons for rejection are:
- The room is invite-only and the user was not invited.
- The user has been banned from the room.
examples:
application/json: |-
{"errcode": "M_FORBIDDEN", "error": "You are not invited to this room."}
429:
description: This request was rate-limited.
schema:
"$ref": "definitions/error.yaml"
x-alias:
canonical-link: "post-matrix-client-api-v1-rooms-roomid-join"
aliases:
- /join/{roomId}
# With an extra " " to disambiguate from the 3pid invite endpoint
# The extra space makes it sort first for what I'm sure is a good reason.
"/rooms/{roomId}/invite ":
post:
summary: Invite a user to participate in a particular room.
description: |-
*Note that there are two forms of this API, which are documented separately.
This version of the API requires that the inviter knows the Matrix
identifier of the invitee.*
This API invites a user to participate in a particular room.
They do not start participating in the room until they actually join the
room.
Only users currently in a particular room can invite other users to
join that room.
If the user was invited to the room, the home server will append a
``m.room.member`` event to the room.
security:
- accessToken: []
parameters:
- in: path
type: string
name: roomId
description: The room identifier (not alias) to which to invite the user.
required: true
x-example: "!d41d8cd:matrix.org"
- in: body
name: body
required: true
schema:
type: object
example: |-
{
"user_id": "@cheeky_monkey:matrix.org"
}
properties:
user_id:
type: string
description: The fully qualified user ID of the invitee.
required: ["user_id"]
responses:
200:
description: The user has been invited to join the room.
examples:
application/json: |-
{}
schema:
type: object
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:
- The invitee has been banned from the room.
- The invitee is already a member of the room.
- The inviter is not currently in the room.
- The inviter's power level is insufficient to invite users to the room.
examples:
application/json: |-
{"errcode": "M_FORBIDDEN", "error": "@cheeky_monkey:matrix.org is banned from the room"}
429:
description: This request was rate-limited.
schema:
"$ref": "definitions/error.yaml"
"/rooms/{roomId}/invite":
post:
summary: Invite a user to participate in a particular room.
description: |-
*Note that there are two forms of this API, which are documented separately.
This version of the API does not require that the inviter know the Matrix
identifier of the invitee, and instead relies on third party identifiers.
The homeserver uses an identity server to perform the mapping from
third party identifier to a Matrix identifier.*
This API invites a user to participate in a particular room.
They do not start participating in the room until they actually join the
room.
Only users currently in a particular room can invite other users to
join that room.
If the identity server did know the Matrix user identifier for the
third party identifier, the home server will append a ``m.room.member``
event to the room.
If the identity server does not know a Matrix user identifier for the
passed third party identifier, the homeserver will issue an invitation
which can be accepted upon providing proof of ownership of the third
party identifier. This is achieved by the identity server generating a
token, which it gives to the inviting homeserver. The homeserver will
add an ``m.room.third_party_invite`` event into the graph for the room,
containing that token.
When the invitee binds the invited third party identifier to a Matrix
user ID, the identity server will give the user a list of pending
invitations, each containing:
- The room ID to which they were invited
- The token given to the homeserver
- 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 home server will
append a ``m.room.third_party_invite`` event to the room.
security:
- accessToken: []
parameters:
- in: path
type: string
name: roomId
description: The room identifier (not alias) to which to invite the user.
required: true
x-example: "!d41d8cd:matrix.org"
- in: body
name: body
required: true
schema:
type: object
example: |-
{
"id_server": "matrix.org",
"medium": "email",
"address": "cheeky@monkey.com",
"display_name": "A very cheeky monkey"
}
properties:
id_server:
type: string
description: The hostname+port of the identity server which should be used for third party identifier lookups.
medium:
type: string
# TODO: Link to identity service spec when it eixsts
description: The kind of address being passed in the address field, for example ``email``.
address:
type: string
description: The invitee's third party identifier.
display_name:
type: string
description: A user-friendly string describing who has been invited. It should not contain the address of the invitee, to avoid leaking mappings between third party identities and matrix user IDs.
required: ["id_server", "medium", "address", "display_name"]
responses:
200:
description: The user has been invited to join the room.
examples:
application/json: |-
{}
schema:
type: object
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:
- The invitee has been banned from the room.
- The invitee is already a member of the room.
- The inviter is not currently in the room.
- The inviter's power level is insufficient to invite users to the room.
examples:
application/json: |-
{"errcode": "M_FORBIDDEN", "error": "@cheeky_monkey:matrix.org is banned from the room"}
429:
description: This request was rate-limited.
schema:
"$ref": "definitions/error.yaml"

@ -1 +0,0 @@
../../../event-schemas/schema/v1

@ -1 +0,0 @@
../../../event-schemas/schema/v1/core-event-schema

@ -1,10 +0,0 @@
type: object
description: A Matrix-level Error
properties:
errcode:
type: string
description: An error code.
error:
type: string
description: A human-readable error message.
required: ["errcode"]

@ -1,12 +0,0 @@
{
"type": "object",
"properties": {
"events": {
"type": "array",
"description": "List of events",
"items": {
"type": "object"
}
}
}
}

@ -1,42 +0,0 @@
{
"type": "object",
"properties": {
"limit": {
"type": "integer",
"description":
"The maximum number of events to return."
},
"types": {
"type": "array",
"description":
"A list of event types to include. If this list is absent then all event types are included. A '*' can be used as a wildcard to match any sequence of characters.",
"items": {
"type": "string"
}
},
"not_types": {
"type": "array",
"description":
"A list of event types to exclude. If this list is absent then no event types are excluded. A matching type will be excluded even if it is listed in the 'types' filter. A '*' can be used as a wildcard to match any sequence of characters.",
"items": {
"type": "string"
}
},
"senders": {
"type": "array",
"description":
"A list of senders IDs to include. If this list is absent then all senders are included. A '*' can be used as a wildcard to match any sequence of characters.",
"items": {
"type": "string"
}
},
"not_senders": {
"type": "array",
"description":
"A list of sender IDs to exclude. If this list is absent then no senders are excluded. A matching sender will be excluded even if it is listed in the 'senders' filter. A '*' can be used as a wildcard to match any sequence of characters.",
"items": {
"type": "string"
}
}
}
}

@ -1,12 +0,0 @@
{
"type": "object",
"properties": {
"events": {
"type": "array",
"description": "List of event ids",
"items": {
"type": "string"
}
}
}
}

@ -1,22 +0,0 @@
{
"type": "object",
"allOf": [{"$ref": "definitions/event_filter.json"}],
"properties": {
"rooms": {
"type": "array",
"description":
"A list of room IDs to include. If this list is absent then all rooms are included. A '*' can be used as a wildcard to match any sequence of characters.",
"items": {
"type": "string"
}
},
"not_rooms": {
"type": "array",
"description":
"A list of room IDs to exclude. If this list is absent then no rooms are excluded. A matching room will be excluded even if it is listed in the 'rooms' filter. A '*' can be used as a wildcard to match any sequence of characters.",
"items": {
"type": "string"
}
}
}
}

@ -1,44 +0,0 @@
{
"type": "object",
"properties": {
"room": {
"type": "object",
"properties": {
"state": {
"description":
"The state events to include for rooms.",
"allOf": [{"$ref": "definitions/room_event_filter.json"}]
},
"timeline": {
"description":
"The message and state update events to include for rooms.",
"allOf": [{"$ref": "definitions/room_event_filter.json"}]
},
"ephemeral": {
"description":
"The events that aren't recorded in the room history, e.g. typing and receipts, to include for rooms.",
"allOf": [{"$ref": "definitions/room_event_filter.json"}]
}
}
},
"presence": {
"description":
"The presence updates to include.",
"allOf": [{"$ref": "definitions/event_filter.json"}]
},
"event_format": {
"description":
"The format to use for events. 'client' will return the events in a format suitable for clients. 'federation' will return the raw event as receieved over federation. The default is 'client'.",
"type": "string",
"enum": ["client", "federation"]
},
"event_fields": {
"type": "array",
"description":
"List of event fields to include. If this list is absent then all fields are included. The entries may include '.' charaters to indicate sub-fields. So ['content.body'] will include the 'body' field of the 'content' object. A literal '.' character in a field name may be escaped using a '\\'. A server may include more fields than were requested.",
"items": {
"type": "string"
}
}
}
}

@ -1,14 +0,0 @@
{
"type": "object",
"allOf": [{"$ref":"definitions/room_event_batch.json"}],
"properties": {
"limited": {
"type": "boolean",
"description": "Whether there are more events on the server"
},
"prev_batch": {
"type": "string",
"description": "If the batch was limited then this is a token that can be supplied to the server to retrieve more events"
}
}
}

@ -1,12 +1,12 @@
swagger: '2.0'
info:
title: "Matrix Client-Server v1 Voice over IP API"
title: "Matrix Client-Server Voice over IP API"
version: "1.0.0"
host: localhost:8008
schemes:
- https
- http
basePath: /_matrix/client/api/v1
basePath: /_matrix/client/%CLIENT_MAJOR_VERSION%
consumes:
- application/json
produces:
@ -18,7 +18,7 @@ securityDefinitions:
name: access_token
in: query
paths:
"/turnServer":
"/voip/turnServer":
get:
summary: Obtain TURN server credentials.
description: |-
@ -65,4 +65,5 @@ paths:
description: This request was rate-limited.
schema:
"$ref": "definitions/error.yaml"
tags:
- VOIP

@ -0,0 +1,37 @@
r0
===
This is the first release of the client-server specification. It is largely a dump of what has currently been implemented, and there are several inconsistencies.
An upcoming minor release will deprecate many of these inconsistencies, and they will be removed in the next major release.
Since the draft stage, the following major changes have been made:
- /api/v1 and /v2_alpha path segments have been replaced with the major version of the release (i.e. 'r0').
- Some POST versions of APIs with both POST and PUT have been removed.
- The specification has been split into one specification per API. This is the client-server API. The server-server API can be found documented separately.
- All APIs are now documented using Swagger
- The following modules have been added:
- Content repository
- Instant messaging
- Push notification
- History visibility
- Search
- Invites based on third party identifiers
- Room tagging
- Guest access
- Client config
- The following APIs were added:
- ``/sync``
- ``/publicRooms``
- ``/rooms/{roomId}/forget``
- ``/admin/whois``
- ``/rooms/{roomId}/redact``
- ``/user/{userId}/filter``
- The following APIs have been significantly modified:
- Invitations now contain partial room state
- Invitations can now be rejected
- ``/directory``
- The following events have been added:
- ``m.room.avatar``
- Example signed json is included for reference
- Commentary on display name calculation was added

@ -1,4 +1,4 @@
Versioning is, like, hard for backfilling backwards because of the number of Home Servers involved.
Versioning is, like, hard for backfilling backwards because of the number of homeservers involved.
The way we solve this is by doing versioning as an acyclic directed graph of PDUs. For backfilling purposes, this is done on a per context basis.
When we send a PDU we include all PDUs that have been received for that context that hasn't been subsequently listed in a later PDU. The trivial case is a simple list of PDUs, e.g. A <- B <- C. However, if two servers send out a PDU at the same to, both B and C would point at A - a later PDU would then list both B and C.

@ -13,7 +13,7 @@ Application Services HTTP API
.. sectnum::
Application Service -> Home Server
Application Service -> Homeserver
----------------------------------
This contains homeserver APIs which are used by the application service.
@ -122,7 +122,7 @@ API called when:
}
Home Server -> Application Service
Homeserver -> Application Service
----------------------------------
This contains application service APIs which are used by the homeserver.

@ -9,26 +9,35 @@ Caveats can only be used for reducing the scope of a token, never for increasing
Some caveats are specified in this specification, and must be understood by all servers. The use of non-standard caveats is allowed.
All caveats must take the form:
All caveats must take the form::
key operator value
where:
- ``key`` is a non-empty string drawn from the character set [A-Za-z0-9_]
- ``operator`` is a non-empty string which does not contain whitespace
- ``value`` is a non-empty string
`key` `operator` `value`
where `key` is a non-empty string drawn from the character set [A-Za-z0-9_]
`operator` is a non-empty string which does not contain whitespace
`value` is a non-empty string
And these are joined by single space characters.
Specified caveats:
+-------------+--------------------------------------------------+------------------------------------------------------------------------------------------------+
| Caveat name | Description | Legal Values |
+-------------+--------------------------------------------------+------------------------------------------------------------------------------------------------+
+=============+==================================================+================================================================================================+
| gen | Generation of the macaroon caveat spec. | 1 |
+-------------+--------------------------------------------------+------------------------------------------------------------------------------------------------+
| user_id | ID of the user for which this macaroon is valid. | Pure equality check. Operator must be =. |
| type | The purpose of this macaroon. | access - used to authorize any action except token refresh |
| refresh - only used to authorize a token refresh |
+-------------+--------------------------------------------------+------------------------------------------------------------------------------------------------+
| type | The purpose of this macaroon. | - ``access``: used to authorize any action except token refresh |
| | | - ``refresh``: only used to authorize a token refresh |
| | | - ``login``: issued as a very short-lived token by third party login flows; proves that |
| | | authentication has happened but doesn't grant any privileges other than being able to be |
| | | exchanged for other tokens. |
+-------------+--------------------------------------------------+------------------------------------------------------------------------------------------------+
| time | Time before/after which this macaroon is valid. | A POSIX timestamp in milliseconds (in UTC). |
| Operator < means the macaroon is valid before the timestamp, as interpreted by the server. |
| Operator > means the macaroon is valid after the timestamp, as interpreted by the server. |
| Operator == means the macaroon is valid at exactly the timestamp, as interpreted by the server.|
| Note that exact equality of time is largely meaningless. |
| | | Operator < means the macaroon is valid before the timestamp, as interpreted by the server. |
| | | Operator > means the macaroon is valid after the timestamp, as interpreted by the server. |
| | | Operator == means the macaroon is valid at exactly the timestamp, as interpreted by the server.|
| | | Note that exact equality of time is largely meaningless. |
+-------------+--------------------------------------------------+------------------------------------------------------------------------------------------------+

@ -5,14 +5,14 @@ A simple implementation of presence messaging has the ability to cause a large
amount of Internet traffic relating to presence updates. In order to minimise
the impact of such a feature, the following observations can be made:
* There is no point in a Home Server polling status for peers in a user's
* There is no point in a homeserver polling status for peers in a user's
presence list if the user has no clients connected that care about it.
* It is highly likely that most presence subscriptions will be symmetric - a
given user watching another is likely to in turn be watched by that user.
* It is likely that most subscription pairings will be between users who share
at least one Room in common, and so their Home Servers are actively
at least one Room in common, and so their homeservers are actively
exchanging message PDUs or transactions relating to that Room.
* Presence update messages do not need realtime guarantees. It is acceptable to
@ -25,7 +25,7 @@ promise to send them when required. Rather than actively polling for the
current state all the time, HSes can rely on their relative stability to only
push updates when required.
A Home Server should not rely on the longterm validity of this presence
A homeserver should not rely on the longterm validity of this presence
information, however, as this would not cover such cases as a user's server
crashing and thus failing to inform their peers that users it used to host are
no longer available online. Therefore, each promise of future updates should
@ -98,7 +98,7 @@ The data model presented here puts the following requirements on the APIs:
Client-Server
-------------
Requests that a client can make to its Home Server
Requests that a client can make to its homeserver
* get/set current presence state
Basic enumeration + ability to set a custom piece of text
@ -128,7 +128,7 @@ Requests that a client can make to its Home Server
Server-Server
-------------
Requests that Home Servers make to others
Requests that homeservers make to others
* request permission to add a user to presence list

@ -182,7 +182,7 @@ The data model presented here puts the following requirements on the APIs:
Client-Server
-------------
Requests that a client can make to its Home Server
Requests that a client can make to its homeserver
* get/set my Display Name
This should return/take a simple "text/plain" field
@ -207,7 +207,7 @@ TODO(paul): At some later stage we should consider the API for:
Server-Server
-------------
Requests that Home Servers make to others
Requests that homeservers make to others
* get a user's Display Name / Avatar
@ -221,7 +221,7 @@ Requests that Home Servers make to others
Room Event PDU Types
--------------------
Events that are pushed from Home Servers to other Home Servers or clients.
Events that are pushed from homeservers to other homeservers or clients.
* user Display Name change

@ -226,7 +226,7 @@ clients should display these in a special way too as the room name is not
important; instead it should distinguish them on the Display Name of the other
party.
Home Servers will need a client-API option to request setting up a new user-user
Homeservers will need a client-API option to request setting up a new user-user
chat room, which will then need special handling within the server. It will
create a new room with the following
@ -260,7 +260,7 @@ history with each other simultaneously create a room and invite the other to it.
This is called a "glare" situation. There are two possible ideas for how to
resolve this:
* Each Home Server should persist the mapping of (user ID pair) to room ID, so
* Each homeserver should persist the mapping of (user ID pair) to room ID, so
that duplicate requests can be suppressed. On receipt of a room creation
request that the HS thinks there already exists a room for, the invitation to
join can be rejected if:

@ -66,7 +66,7 @@ Privacy
A User may publish the association between their phone number and Matrix User ID
on the Identity Server without publishing the number in their Profile hosted on
their Home Server.
their homeserver.
Identity Servers should refrain from publishing reverse mappings and should
take steps, such as rate limiting, to prevent attackers enumerating the space of

@ -0,0 +1,285 @@
WebSockets API
==============
Introduction
------------
This document is a proposal for a WebSockets-based client-server API. It is not
intended to replace the REST API, but rather to complement it and provide an
alternative interface for certain operations.
The primary goal is to offer a more efficient interface than the REST API: by
using a bidirectional protocol such as WebSockets we can avoid the overheads
involved in long-polling (SSL negotiation, HTTP headers, etc). In doing so we
will reduce the latency between server and client by allowing the server to
send events as soon as they arrive, rather than having to wait for a poll from
the client.
Handshake
---------
1. Instead of calling ``/sync``, the client makes a websocket request to
``/_matrix/client/rN/stream``, passing the query parameters ``access_token``
and ``since``, and optionally ``filter`` - all of which have the same
meaning as for ``/sync``.
* The client sets the ``Sec-WebSocket-Protocol`` to ``m.json``. (Servers may
offer alternative encodings; at present only the JSON encoding is
specified but in future we will specify alternative encodings.)
#. The server returns the websocket handshake; the socket is then connected.
If the server does not return a valid websocket handshake, this indicates that
the server or an intermediate proxy does not support WebSockets. In this case,
the client should fall back to polling the ``/sync`` REST endpoint.
Example
~~~~~~~
Client request:
.. code:: http
GET /_matrix/client/v2_alpha/stream?access_token=123456&since=s72594_4483_1934 HTTP/1.1
Host: matrix.org
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==
Sec-WebSocket-Protocol: m.json
Sec-WebSocket-Version: 13
Origin: https://matrix.org
Server response:
.. code:: http
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk=
Sec-WebSocket-Protocol: m.json
Update Notifications
--------------------
Once the socket is connected, the server begins streaming updates over the
websocket. The server sends Update notifications about new messages or state
changes. To make it easy for clients to parse, Update notifications have the
same structure as the response to ``/sync``: an object with the following
members:
============= ========== ===================================================
Key Type Description
============= ========== ===================================================
next_batch string The batch token to supply in the ``since`` param of
the next /sync request. This is not required for
streaming of events over the WebSocket, but is
provided so that clients can reconnect if the
socket is disconnected.
presence Presence The updates to the presence status of other users.
rooms Rooms Updates to rooms.
============= ========== ===================================================
Example
~~~~~~~
Message from the server:
.. code:: json
{
"next_batch": "s72595_4483_1934",
"presence": {
"events": []
},
"rooms": {
"join": {},
"invite": {},
"leave": {}
}
}
Client-initiated operations
---------------------------
The client can perform certain operations by sending a websocket message to
the server. Such a "Request" message should be a JSON-encoded object with
the following members:
============= ========== ===================================================
Key Type Description
============= ========== ===================================================
id string A unique identifier for this request
method string Specifies the name of the operation to be
performed; see below for available operations
param object The parameters for the requested operation.
============= ========== ===================================================
The server responds to a client Request with a Response message. This is a
JSON-encoded object with the following members:
============= ========== ===================================================
Key Type Description
============= ========== ===================================================
id string The same as the value in the corresponding Request
object. The presence of the ``id`` field
distinguishes a Response message from an Update
notification.
result object On success, the results of the request.
error object On error, an object giving the resons for the
error. This has the same structure as the "standard
error response" for the Matrix API: an object with
the fields ``errcode`` and ``error``.
============= ========== ===================================================
Request methods
~~~~~~~~~~~~~~~
It is not intended that all operations which are available via the REST API
will be available via the WebSockets API, but a few simple, common operations
will be exposed. The initial operations will be as follows.
``ping``
^^^^^^^^
This is a no-op which clients may use to keep their connection alive.
The request ``params`` and the response ``result`` should be empty.
``send``
^^^^^^^^
Send a message event to a room. The parameters are as follows:
============= ========== ===================================================
Parameter Type Description
============= ========== ===================================================
room_id string **Required.** The room to send the event to
event_type string **Required.** The type of event to send.
content object **Required.** The content of the event.
============= ========== ===================================================
The result is as follows:
============= ========== ===================================================
Key Type Description
============= ========== ===================================================
event_id string A unique identifier for the event.
============= ========== ===================================================
The ``id`` from the Request message is used as the transaction ID by the
server.
``state``
^^^^^^^^^
Update the state on a room.
============= ========== ===================================================
Parameter Type Description
============= ========== ===================================================
room_id string **Required.** The room to set the state in
event_type string **Required.** The type of event to send.
state_key string **Required.** The state_key for the state to send.
content object **Required.** The content of the event.
============= ========== ===================================================
The result is as follows:
============= ========== ===================================================
Key Type Description
============= ========== ===================================================
event_id string A unique identifier for the event.
============= ========== ===================================================
Example
~~~~~~~
Client request:
.. code:: json
{
"id": "12345",
"method": "send",
"params": {
"room_id": "!d41d8cd:matrix.org",
"event_type": "m.room.message",
"content": {
"msgtype": "m.text",
"body": "hello"
}
}
}
Server response:
.. code:: json
{
"id": "12345",
"result": {
"event_id": "$66697273743031:matrix.org"
}
}
Alternative server response, in case of error:
.. code:: json
{
"id": "12345",
"error": {
"errcode": "M_MISSING_PARAM",
"error": "Missing parameter: event_type"
}
}
Rationale
---------
Alternatives to WebSockets include HTTP/2, CoAP, and simply rolling our own
protocol over raw TCP sockets. However, the need to implement browser-based
clients essentially reduces our choice to WebSockets. HTTP/2 streams will
probably provide an interesting alternative in the future, but current browsers
do not appear to give javascript applications low-level access to the protocol.
Concerning the continued use of the JSON encoding: we prefer to focus on the
transition to WebSockets initially. Replacing JSON with a compact
representation such as CBOR, MessagePack, or even just compressed JSON will be
a likely extension for the future. The support for negotiation of subprotocols
within WebSockets should make this a simple transition once time permits.
The number of methods available for client requests is deliberately limited, as
each method requires code to be written to map it onto the equivalent REST
implementation. Some REST methods - for instance, user registration and login -
would be pointless to expose via WebSockets. It is likely, however, that we
will increate the number of methods available via the WebSockets API as it
becomes clear which would be most useful.
Open questions
--------------
Throttling
~~~~~~~~~~
At least in v2 sync, clients are inherently self-throttling - if they do not
poll quickly enough, events will be dropped from the next result. This proposal
raises the possibility that events will be produced more quickly than they can
be sent to the client; backlogs will build up on the server and/or in the
intermediate network, which will not only lead to high latency on events being
delivered, but will lead to responses to client requests also being delayed.
We may need to implement some sort of throttling mechanism by which the server
can start to drop events. The difficulty is in knowing when to start dropping
events. A few ideas:
* Use websocket pings to measure the RTT; if it starts to increase, start
dropping events. But this requires knowledge of the base RTT, and a useful
model of what constitutes an excessive increase.
* Have the client acknowledge each batch of events, and use a window to ensure
the number of outstanding batches is limited. This is annoying as it requires
the client to have to acknowledge batches - and it's not clear what the right
window size is: we want a big window for long fat networks (think of mobile
clients), but a small one for one with lower latency.
* Start dropping events if the server's TCP buffer starts filling up. This has
the advantage of delegating the congestion-detection to TCP (which already
has a number of algorithms to deal with it, to greater or lesser
effectiveness), but relies on homeservers being hosted on OSes which use
sensible TCP congestion-avoidance algorithms, and more critically, an ability
to read the fill level of the TCP send buffer.

@ -7,7 +7,7 @@ resolved correctly. For basic CLI testing, we recommend and have verified they
work with the Node.js package [z-schema](https://github.com/zaggino/z-schema):
```
$ npm install -g z-schema
$ z-schema schema/v1/m.room.message examples/v1/m.room.message_m.text
$ z-schema schema/m.room.message examples/m.room.message_m.text
schema validation passed
json #1 validation passed
```

@ -1,22 +0,0 @@
#!/bin/bash -e
# Runs z-schema over all of the schema files (looking for matching examples)
if ! which z-schema; then
echo >&2 "Need to install z-schema; run: sudo npm install -g z-schema"
exit 1
fi
find schema/v1/m.* | while read line
do
split_path=(${line///// })
event_type=(${split_path[2]})
echo "Checking $event_type"
echo "--------------------"
# match exact name or exact name with a #<something>
find examples/v1 -name $event_type -o -name "$event_type#*" | while read exline
do
echo " against $exline"
# run z-schema: because of bash -e if this fails we bail with exit code 1
z-schema schema/v1/$event_type $exline
done
done

@ -38,13 +38,12 @@ def check_example_file(examplepath, schemapath):
schema = yaml.load(f)
fileurl = "file://" + os.path.abspath(schemapath)
schema["id"] = fileurl
resolver = jsonschema.RefResolver(schemapath, schema, handlers={"file": load_yaml})
print ("Checking schema for: %r %r" % (examplepath, schemapath))
# Setting the 'id' tells jsonschema where the file is so that it
# can correctly resolve relative $ref references in the schema
schema['id'] = fileurl
try:
jsonschema.validate(example, schema)
jsonschema.validate(example, schema, resolver=resolver)
except Exception as e:
raise ValueError("Error validating JSON schema for %r %r" % (
examplepath, schemapath
@ -60,6 +59,8 @@ def check_example_dir(exampledir, schemadir):
continue
examplepath = os.path.join(root, filename)
schemapath = examplepath.replace(exampledir, schemadir)
if schemapath.find("#") >= 0:
schemapath = schemapath[:schemapath.find("#")]
try:
check_example_file(examplepath, schemapath)
except Exception as e:
@ -69,6 +70,15 @@ def check_example_dir(exampledir, schemadir):
if errors:
raise ValueError("Error validating examples")
def load_yaml(path):
if not path.startswith("file:///"):
raise Exception("Bad ref: %s" % (path,))
path = path[len("file://"):]
with open(path, "r") as f:
return yaml.load(f)
if __name__ == '__main__':
try:
check_example_dir("examples", "schema")

@ -13,5 +13,5 @@
"event_id": "$WLGTSEFSEF:localhost",
"type": "m.call.answer",
"room_id": "!Cuyf34gef24t:localhost",
"user_id": "@example:localhost"
"sender": "@example:localhost"
}

@ -15,5 +15,5 @@
"event_id": "$WLGTSEFSEF:localhost",
"type": "m.call.candidates",
"room_id": "!Cuyf34gef24t:localhost",
"user_id": "@example:localhost"
"sender": "@example:localhost"
}

@ -8,5 +8,5 @@
"event_id": "$WLGTSEFSEF:localhost",
"type": "m.call.hangup",
"room_id": "!Cuyf34gef24t:localhost",
"user_id": "@example:localhost"
"sender": "@example:localhost"
}

@ -13,5 +13,5 @@
"event_id": "$WLGTSEFSEF:localhost",
"type": "m.call.invite",
"room_id": "!Cuyf34gef24t:localhost",
"user_id": "@example:localhost"
"sender": "@example:localhost"
}

@ -8,5 +8,5 @@
"event_id": "$WLGTSEFSEF:localhost",
"type": "m.room.aliases",
"room_id": "!Cuyf34gef24t:localhost",
"user_id": "@example:localhost"
"sender": "@example:localhost"
}

@ -14,5 +14,5 @@
"type": "m.room.avatar",
"state_key": "",
"room_id": "!Cuyf34gef24t:localhost",
"user_id": "@example:localhost"
"sender": "@example:localhost"
}

@ -8,5 +8,5 @@
"event_id": "$WLGTSEFSEF:localhost",
"type": "m.room.canonical_alias",
"room_id": "!Cuyf34gef24t:localhost",
"user_id": "@example:localhost"
"sender": "@example:localhost"
}

@ -8,5 +8,5 @@
"event_id": "$WLGTSEFSEF:localhost",
"type": "m.room.create",
"room_id": "!Cuyf34gef24t:localhost",
"user_id": "@example:localhost"
"sender": "@example:localhost"
}

@ -0,0 +1,12 @@
{
"age": 242353,
"content": {
"guest_access": "can_join"
},
"state_key": "",
"origin_server_ts": 1431961217938,
"event_id": "$WLGTSEFSEG:localhost",
"type": "m.room.guest_access",
"room_id": "!Cuyf34gef24u:localhost",
"sender": "@example:localhost"
}

@ -8,5 +8,5 @@
"event_id": "$WLGTSEFSEF:localhost",
"type": "m.room.history_visibility",
"room_id": "!Cuyf34gef24t:localhost",
"user_id": "@example:localhost"
"sender": "@example:localhost"
}

@ -8,5 +8,5 @@
"event_id": "$WLGTSEFSEF:localhost",
"type": "m.room.join_rules",
"room_id": "!Cuyf34gef24t:localhost",
"user_id": "@example:localhost"
"sender": "@example:localhost"
}

@ -3,22 +3,7 @@
"content": {
"membership": "join",
"avatar_url": "mxc://localhost/SEsfnsuifSDFSSEF#auto",
"displayname": "Alice Margatroid",
"third_party_invite": {
"token": "pc98",
"public_key": "abc123",
"key_validity_url": "https://magic.forest/verifykey",
"signed": {
"mxid": "@alice:localhost",
"token": "pc98",
"signatures": {
"magic.forest": {
"ed25519:0": "poi098"
}
}
},
"sender": "@zun:zun.soft"
}
"displayname": "Alice Margatroid"
},
"invite_room_state": [
{
@ -41,5 +26,5 @@
"event_id": "$WLGTSEFSEF:localhost",
"type": "m.room.member",
"room_id": "!Cuyf34gef24t:localhost",
"user_id": "@example:localhost"
"sender": "@example:localhost"
}

@ -0,0 +1,30 @@
{
"age": 242352,
"content": {
"membership": "join",
"avatar_url": "mxc://localhost/SEsfnsuifSDFSSEF#auto",
"displayname": "Alice Margatroid"
},
"invite_room_state": [
{
"type": "m.room.name",
"state_key": "",
"content": {
"name": "Forest of Magic"
}
},
{
"type": "m.room.join_rules",
"state_key": "",
"content": {
"join_rules": "invite"
}
}
],
"state_key": "@alice:localhost",
"origin_server_ts": 1431961217939,
"event_id": "$WLGTSEFSEF:localhost",
"type": "m.room.member",
"room_id": "!Cuyf34gef24t:localhost",
"sender": "@example:localhost"
}

@ -0,0 +1,25 @@
{
"age": 242352,
"content": {
"membership": "join",
"avatar_url": "mxc://localhost/SEsfnsuifSDFSSEF#auto",
"displayname": "Alice Margatroid",
"third_party_invite": {
"signed": {
"mxid": "@alice:localhost",
"signatures": {
"magic.forest": {
"ed25519:3": "fQpGIW1Snz+pwLZu6sTy2aHy/DYWWTspTJRPyNp0PKkymfIsNffysMl6ObMMFdIJhk6g6pwlIqZ54rxo8SLmAg"
}
},
"token": "abc123"
}
}
},
"state_key": "@alice:localhost",
"origin_server_ts": 1431961217939,
"event_id": "$WLGTSEFSEF:localhost",
"type": "m.room.member",
"room_id": "!Cuyf34gef24t:localhost",
"sender": "@example:localhost"
}

@ -14,5 +14,5 @@
"origin_server_ts": 1432735824653,
"room_id": "!jEsUZKDJdhlrceRyVU:localhost",
"type": "m.room.message",
"user_id": "@example:localhost"
"sender": "@example:localhost"
}

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save