Client-Server API

Warning

You are viewing an outdated version of this specification. To view the current specification, please click here.

The client-server API provides a simple lightweight API to let clients send messages, control rooms and synchronise conversation history. It is designed to support both lightweight clients which store no state and lazy-load data from the server as required - as well as heavyweight clients which maintain a full local persistent copy of server state.

Table of Contents

1   Changelog

Version: r0.3.0

  • Breaking changes:
    • Change the rule kind of .m.rule.contains_display_name from underride to override. This works with all known clients which support push rules, but any other clients implementing the push rules API should be aware of this change. This makes it simple to mute rooms correctly in the API (#373).
    • Remove /tokenrefresh from the API (#395).
    • Remove requirement that tokens used in token-based login be macaroons (#395).
    • Move thumbnail_url and thumbnail_info members of json objects for m.room.message events with msgtypes m.image, m.file and m.location, inside the info member, to match m.video events (#723).
  • Changes to the API which will be backwards-compatible for clients:
    • Add filename parameter to POST /_matrix/media/r0/upload (#364).
    • Document CAS-based client login and the use of m.login.token in /login (#367).
    • Make origin_server_ts a mandatory field of room events (#379).
    • Add top-level account_data key to the responses to GET /sync and GET /initialSync (#380).
    • Add is_direct flag to POST /createRoom and invite member event. Add 'Direct Messaging' module (#389).
    • Add contains_url option to RoomEventFilter (#390).
    • Add filter optional query param to /messages (#390).
    • Add 'Send-to-Device messaging' module (#386).
    • Add 'Device management' module (#402).
    • Require that User-Interactive auth fallback pages call window.postMessage to notify apps of completion (#398).
    • Add pagination and filter support to /publicRooms. Change response to omit fields rather than return null. Add estimate of total number of rooms in list. (#388).
    • Allow guest accounts to use a number of endpoints which are required for end-to-end encryption. (#751).
    • Add key distribution APIs, for use with end-to-end encryption. (#894).
    • Add m.room.pinned_events state event for rooms. (#1007).
    • Add mention of ability to send Access Token via an Authorization Header.
    • New endpoints:
      • GET /joined_rooms (#999).
      • GET /rooms/{roomId}/joined_members (#999).
      • GET /account/whoami (#1063).
      • GET /media/{version}/preview_url (#1064).
  • Spec clarifications:
    • Add endpoints and logic for invites and third-party invites to the federation spec and update the JSON of the request sent by the identity server upon 3PID binding (#997)
    • Fix "membership" property on third-party invite upgrade example (#995)
    • Fix response format and 404 example for room alias lookup (#960)
    • Fix examples of m.room.member event and room state change, and added a clarification on the membership event sent upon profile update (#950).
    • Spell out the way that state is handled by POST /createRoom (#362).
    • Clarify the fields which are applicable to different types of push rule (#365).
    • A number of clarifications to authentication (#371).
    • Correct references to user_id which should have been sender (#376).
    • Correct inconsistent specification of redacted_because fields and their values (#378).
    • Mark required fields in response objects as such (#394).
    • Make m.notice description a bit harder in its phrasing to try to dissuade the same issues that occurred with IRC (#750).
    • GET /user/{userId}/filter/{filterId} requires authentication (#1003).
    • Add some clarifying notes on the behaviour of rooms with no m.room.power_levels event (#1026).
    • Clarify the relationship between username and user_id in the /register API (#1032).
    • Clarify rate limiting and security for content repository. (#1064).

This version of the specification is generated from matrix-doc as of Git commit client_server/r0.3.0_updates,20ebae4.

For the full historical changelog, see https://github.com/matrix-org/matrix-doc/blob/main/changelogs/legacy/client_server.rst

If this is an unstable snapshot, any changes since the last release may be viewed using git log.

1.1   Other versions of this specification

The following other versions are also available, in reverse chronological order:

  • HEAD: Includes all changes since the latest versioned release.
  • r0.2.0
  • r0.1.0
  • r0.0.1
  • r0.0.0
  • Legacy: The last draft before the spec was formally released in version r0.0.0.

2   API Standards

The mandatory baseline for client-server communication in Matrix is exchanging JSON objects over HTTP APIs. HTTPS is recommended for communication, although HTTP may be supported as a fallback to support basic HTTP clients. More efficient optional transports will in future be supported as optional extensions - e.g. a packed binary encoding over stream-cipher encrypted TCP socket for low-bandwidth/low-roundtrip mobile usage. For the default HTTP transport, all API calls use a Content-Type of application/json. In addition, all strings MUST be encoded as UTF-8. Clients are authenticated using opaque access_token strings (see Client Authentication for details), passed as a query string parameter on all requests.

The names of the API endponts for the HTTP transport follow a convention of using underscores to separate words (for example /delete_devices). The key names in JSON objects passed over the API also follow this convention.

Note

There are a few historical exceptions to this rule, such as /createRoom. A future version of this specification will address the inconsistency.

Any errors which occur at the Matrix API level MUST return a "standard error response". This is a JSON object which looks like:

{
  "errcode": "<error code>",
  "error": "<error message>"
}

The error string will be a human-readable error message, usually a sentence explaining what went wrong. The errcode string will be a unique string which can be used to handle an error message e.g. M_FORBIDDEN. These error codes should have their namespace first in ALL CAPS, followed by a single _ to ease separating the namespace from the error code. For example, if there was a custom namespace com.mydomain.here, and a FORBIDDEN code, the error code should look like COM.MYDOMAIN.HERE_FORBIDDEN. There may be additional keys depending on the error, but the keys error and errcode MUST always be present.

Some standard error codes are below:

M_FORBIDDEN:Forbidden access, e.g. joining a room without permission, failed login.
M_UNKNOWN_TOKEN:
 The access token specified was not recognised.
M_BAD_JSON:Request contained valid JSON, but it was malformed in some way, e.g. missing required keys, invalid values for keys.
M_NOT_JSON:Request did not contain valid JSON.
M_NOT_FOUND:No resource was found for this request.
M_LIMIT_EXCEEDED:
 Too many requests have been sent in a short period of time. Wait a while then try again.

Some requests have unique error codes:

M_USER_IN_USE:Encountered when trying to register a user ID which has been taken.
M_INVALID_USERNAME:
 Encountered when trying to register a user ID which is not valid.
M_ROOM_IN_USE:Sent when the room alias given to the createRoom API is already in use.
M_INVALID_ROOM_STATE:
 Sent when the intial state given to the createRoom API is invalid.
M_BAD_PAGINATION:
 Encountered when specifying bad pagination query parameters.
M_THREEPID_IN_USE:
 Sent when a threepid given to an API cannot be used because the same threepid is already in use.
M_THREEPID_NOT_FOUND:
 Sent when a threepid given to an API cannot be used because no record matching the threepid was found.
M_SERVER_NOT_TRUSTED:
 The client's request used a third party server, eg. ID server, that this server does not trust.

The client-server API typically uses HTTP PUT to submit requests with a client-generated transaction identifier. This means that these requests are idempotent. The scope of a transaction identifier is a particular access token. It only serves to identify new requests from retransmits. After the request has finished, the {txnId} value should be changed (how is not specified; a monotonically increasing integer is recommended).

Some API endpoints may allow or require the use of POST requests without a transaction ID. Where this is optional, the use of a PUT request is strongly recommended.

2.1   GET /_matrix/client/versions

Gets the versions of the specification supported by the server.

Values will take the form rX.Y.Z.

Only the latest Z value will be reported for each supported X.Y value. i.e. if the server implements r0.0.0, r0.0.1, and r1.2.0, it will report r0.0.1 and r1.2.0.

Request format:

No parameters

Response format:

Parameter Type Description
versions [string] The supported versions.

Example request:

GET /_matrix/client/versions HTTP/1.1

Response:

Status code 200:

The versions supported by the server.

Example

{
  "versions": [
    "r0.0.1"
  ]
}

3   Client Authentication

Most API endpoints require the user to identify themselves by presenting previously obtained credentials in the form of an access_token query parameter or through an Authorization Header of Bearer $access_token. An access token is typically obtained via the Login or Registration processes.

When credentials are required but missing or invalid, the HTTP call will return with a status of 401 and the error code, M_MISSING_TOKEN or M_UNKNOWN_TOKEN respectively.

Note

This specification does not mandate a particular format for the access token. Clients should treat it as an opaque byte sequence. Servers are free to choose an appropriate format. Server implementors may like to investigate macaroons.

3.1   Relationship between access tokens and devices

Client devices are closely related to access tokens. Matrix servers should record which device each access token is assigned to, so that subsequent requests can be handled correctly.

By default, the Login and Registration processes auto-generate a new device_id. A client is also free to generate its own device_id or, provided the user remains the same, reuse a device: in ether case the client should pass the device_id in the request body. If the client sets the device_id, the server will invalidate any access token previously assigned to that device. There is therefore at most one active access token assigned to each device at any one time.

3.2   User-Interactive Authentication API

3.2.1   Overview

Some API endpoints require authentication that interacts with the user. The homeserver may provide many different ways of authenticating, such as user/password auth, login via a social network (OAuth2), login by confirming a token sent to their email address, etc. This specification does not define how homeservers should authorise their users but instead defines the standard interface which implementations should follow so that ANY client can login to ANY homeserver.

The process takes the form of one or more 'stages'. At each stage the client submits a set of data for a given authentication type and awaits a response from the server, which will either be a final success or a request to perform an additional stage. This exchange continues until the final success.

For each endpoint, a server offers one or more 'flows' that the client can use to authenticate itself. Each flow comprises a series of stages, as described above. The client is free to choose which flow it follows. When all stages in a flow are complete, authentication is complete and the API call succeeds.

3.2.2   User-interactive API in the REST API

In the REST API described in this specification, authentication works by the client and server exchanging JSON dictionaries. The server indicates what authentication data it requires via the body of an HTTP 401 response, and the client submits that authentication data via the auth request parameter.

A client should first make a request with no auth parameter [1]. The homeserver returns an HTTP 401 response, with a JSON body, as follows:

HTTP/1.1 401 Unauthorized
Content-Type: application/json

{
  "flows": [
    {
      "stages": [ "example.type.foo", "example.type.bar" ]
    },
    {
      "stages": [ "example.type.foo", "example.type.baz" ]
    }
  ],
  "params": {
      "example.type.baz": {
          "example_key": "foobar"
      }
  },
  "session": "xxxxxx"
}

In addition to the flows, this object contains some extra information:

params
This section contains any information that the client will need to know in order to use a given type of authentication. For each authentication type presented, that type may be present as a key in this dictionary. For example, the public part of an OAuth client ID could be given here.
session
This is a session identifier that the client must pass back to the home server, if one is provided, in subsequent attempts to authenticate in the same API call.

The client then chooses a flow and attempts to complete one of the stages. It does this by resubmitting the same request with the addition of an auth key in the object that it submits. This dictionary contains a type key whose value is the name of the authentication type that the client is attempting to complete. It must also contain a session key with the value of the session key given by the homeserver, if one was given. It also contains other keys dependent on the auth type being attempted. For example, if the client is attempting to complete auth type example.type.foo, it might submit something like this:

POST /_matrix/client/r0/endpoint HTTP/1.1
Content-Type: application/json

{
  "a_request_parameter": "something",
  "another_request_parameter": "something else",
  "auth": {
      "type": "example.type.foo",
      "session": "xxxxxx",
      "example_credential": "verypoorsharedsecret"
  }
}

If the homeserver deems the authentication attempt to be successful but still requires more stages to be completed, it returns HTTP status 401 along with the same object as when no authentication was attempted, with the addition of the completed key which is an array of auth types the client has completed successfully:

HTTP/1.1 401 Unauthorized
Content-Type: application/json

{
  "completed": [ "example.type.foo" ],
  "flows": [
    {
      "stages": [ "example.type.foo", "example.type.bar" ]
    },
    {
      "stages": [ "example.type.foo", "example.type.baz" ]
    }
  ],
  "params": {
      "example.type.baz": {
          "example_key": "foobar"
      }
  },
  "session": "xxxxxx"
}

Individual stages may require more than one request to complete, in which case the response will be as if the request was unauthenticated with the addition of any other keys as defined by the auth type.

If the homeserver decides that an attempt on a stage was unsuccessful, but the client may make a second attempt, it returns the same HTTP status 401 response as above, with the addition of the standard errcode and error fields describing the error. For example:

HTTP/1.1 401 Unauthorized
Content-Type: application/json

{
  "errcode": "M_FORBIDDEN",
  "error": "Invalid password",
  "completed": [ "example.type.foo" ],
  "flows": [
    {
      "stages": [ "example.type.foo", "example.type.bar" ]
    },
    {
      "stages": [ "example.type.foo", "example.type.baz" ]
    }
  ],
  "params": {
      "example.type.baz": {
          "example_key": "foobar"
      }
  },
  "session": "xxxxxx"
}

If the request fails for a reason other than authentication, the server returns an error message in the standard format. For example:

HTTP/1.1 400 Bad request
Content-Type: application/json

{
  "errcode": "M_EXAMPLE_ERROR",
  "error": "Something was wrong"
}

If the client has completed all stages of a flow, the homeserver performs the API call and returns the result as normal.

Some authentication types may be completed by means other than through the Matrix client, for example, an email confirmation may be completed when the user clicks on the link in the email. In this case, the client retries the request with an auth dict containing only the session key. The response to this will be the same as if the client were attempting to complete an auth state normally, i.e. the request will either complete or request auth, with the presence or absence of that auth type in the 'completed' array indicating whether that stage is complete.

[1]A request to an endpoint that uses User-Interactive Authentication never succeeds without auth. Homeservers may allow requests that don't require auth by offering a stage with only the m.login.dummy auth type, but they must still give a 401 response to requests with no auth data.

3.2.3   Example

At a high level, the requests made for an API call completing an auth flow with three stages will resemble the following diagram:

 _______________________
|       Stage 0         |
| No auth               |
|  ___________________  |
| |_Request_1_________| | <-- Returns "session" key which is used throughout.
|_______________________|
          |
          |
 _________V_____________
|       Stage 1         |
| type: "<auth type1>"  |
|  ___________________  |
| |_Request_1_________| |
|_______________________|
          |
          |
 _________V_____________
|       Stage 2         |
| type: "<auth type2>"  |
|  ___________________  |
| |_Request_1_________| |
|  ___________________  |
| |_Request_2_________| |
|  ___________________  |
| |_Request_3_________| |
|_______________________|
          |
          |
 _________V_____________
|       Stage 3         |
| type: "<auth type3>"  |
|  ___________________  |
| |_Request_1_________| | <-- Returns API response
|_______________________|

3.2.4   Authentication types

This specification defines the following auth types:
  • m.login.password
  • m.login.recaptcha
  • m.login.oauth2
  • m.login.email.identity
  • m.login.token
  • m.login.dummy

3.2.4.1   Password-based

Type:m.login.password
Description:The client submits a username and secret password, both sent in plain-text.

To use this authentication type, clients should submit an auth dict as follows:

{
  "type": "m.login.password",
  "user": "<user_id or user localpart>",
  "password": "<password>",
  "session": "<session ID>"
}

Alternatively reply using a 3pid bound to the user's account on the homeserver using the /account/3pid API rather then giving the user explicitly as follows:

{
  "type": "m.login.password",
  "medium": "<The medium of the third party identifier. Must be 'email'>",
  "address": "<The third party address of the user>",
  "password": "<password>",
  "session": "<session ID>"
}

In the case that the homeserver does not know about the supplied 3pid, the homeserver must respond with 403 Forbidden.

3.2.4.2   Google ReCaptcha

Type:m.login.recaptcha
Description:The user completes a Google ReCaptcha 2.0 challenge

To use this authentication type, clients should submit an auth dict as follows:

{
  "type": "m.login.recaptcha",
  "response": "<captcha response>",
  "session": "<session ID>"
}

3.2.4.3   Token-based

Type:m.login.token
Description:The client submits a login token.

To use this authentication type, clients should submit an auth dict as follows:

{
  "type": "m.login.token",
  "token": "<token>",
  "txn_id": "<client generated nonce>",
  "session": "<session ID>"
}

The nonce should be a random string generated by the client for the request. The same nonce should be used if retrying the request.

There are many ways a client may receive a token, including via an email or from an existing logged in device.

The txn_id may be used by the server to disallow other devices from using the token, thus providing "single use" tokens while still allowing the device to retry the request. This would be done by tying the token to the txn_id server side, as well as potentially invalidating the token completely once the device has successfully logged in (e.g. when we receive a request from the newly provisioned access_token).

The server must encode the user id in the token. There is therefore no need for the client to submit a separate username.

3.2.4.4   OAuth2-based

Type:m.login.oauth2
Description:Authentication is supported via OAuth2 URLs. This login consists of multiple requests.
Parameters:uri: Authorization Request URI OR service selection URI. Both contain an encoded redirect URI.

The homeserver acts as a 'confidential' client for the purposes of OAuth2. If the uri is a service selection URI, it MUST point to a webpage which prompts the user to choose which service to authorize with. On selection of a service, this MUST link through to an Authorization Request URI. If there is only one service which the homeserver accepts when logging in, this indirection can be skipped and the "uri" key can be the Authorization Request URI.

The client then visits the Authorization Request URI, which then shows the OAuth2 Allow/Deny prompt. Hitting 'Allow' redirects to the redirect URI with the auth code. Homeservers can choose any path for the redirect URI. Once the OAuth flow has completed, the client retries the request with the session only, as above.

3.2.4.5   Email-based (identity server)

Type:m.login.email.identity
Description:Authentication is supported by authorising an email address with an identity server.

Prior to submitting this, the client should authenticate with an identity server. After authenticating, the session information should be submitted to the homeserver.

To use this authentication type, clients should submit an auth dict as follows:

{
  "type": "m.login.email.identity",
  "threepidCreds": [
    {
      "sid": "<identity server session id>",
      "client_secret": "<identity server client secret>",
      "id_server": "<url of identity server authed with, e.g. 'matrix.org:8090'>"
    }
  ],
  "session": "<session ID>"
}

3.2.4.6   Dummy Auth

Type:m.login.dummy
Description:Dummy authentication always succeeds and requires no extra parameters. Its purpose is to allow servers to not require any form of User-Interactive Authentication to perform a request.

To use this authentication type, clients should submit an auth dict with just the type and session, if provided:

{
  "type": "m.login.dummy",
  "session": "<session ID>"
}

3.2.5   Fallback

Clients cannot be expected to be able to know how to process every single login type. If a client does not know how to handle a given login type, it can direct the user to a web browser with the URL of a fallback page which will allow the user to complete that login step out-of-band in their web browser. The URL it should open is:

/_matrix/client/r0/auth/<auth type>/fallback/web?session=<session ID>

Where auth type is the type name of the stage it is attempting and session ID is the ID of the session given by the homeserver.

This MUST return an HTML page which can perform this authentication stage. This page must use the following JavaScript when the authentication has been completed:

if (window.onAuthDone) {
    window.onAuthDone();
} else if (window.opener && window.opener.postMessage) {
    window.opener.postMessage("authDone", "*");
}

This allows the client to either arrange for the global function onAuthDone to be defined in an embedded browser, or to use the HTML5 cross-document messaging API, to receive a notification that the authentication stage has been completed.

Once a client receives the notificaton that the authentication stage has been completed, it should resubmit the request with an auth dict with just the session ID:

{
  "session": "<session ID>"
}

3.2.5.1   Example

A client webapp might use the following javascript to open a popup window which will handle unknown login types:

/**
 * Arguments:
 *     homeserverUrl: the base url of the homeserver (eg "https://matrix.org")
 *
 *     apiEndpoint: the API endpoint being used (eg
 *        "/_matrix/client/r0/account/password")
 *
 *     loginType: the loginType being attempted (eg "m.login.recaptcha")
 *
 *     sessionID: the session ID given by the homeserver in earlier requests
 *
 *     onComplete: a callback which will be called with the results of the request
 */
function unknownLoginType(homeserverUrl, apiEndpoint, loginType, sessionID, onComplete) {
    var popupWindow;

    var eventListener = function(ev) {
        // check it's the right message from the right place.
        if (ev.data !== "authDone" || ev.origin !== homeserverUrl) {
            return;
        }

        // close the popup
        popupWindow.close();
        window.removeEventListener("message", eventListener);

        // repeat the request
        var requestBody = {
            auth: {
                session: sessionID,
            },
        };

        request({
            method:'POST', url:apiEndpint, json:requestBody,
        }, onComplete);
    };

    window.addEventListener("message", eventListener);

    var url = homeserverUrl +
        "/_matrix/client/r0/auth/" +
        encodeURIComponent(loginType) +
        "/fallback/web?session=" +
        encodeURIComponent(sessionID);


   popupWindow = window.open(url);
}

3.3   Login

A client can obtain access tokens using the /login API.

Note that this endpoint does not currently use the user-interactive authentication API.

For a simple username/password login, clients should submit a /login request as follows:

{
  "type": "m.login.password",
  "user": "<user_id or user localpart>",
  "password": "<password>"
}

Alternatively, a client can use a 3pid bound to the user's account on the homeserver using the /account/3pid API rather then giving the user explicitly, as follows:

{
  "type": "m.login.password",
  "medium": "<The medium of the third party identifier. Must be 'email'>",
  "address": "<The third party address of the user>",
  "password": "<password>"
}

In the case that the homeserver does not know about the supplied 3pid, the homeserver must respond with 403 Forbidden.

To log in using a login token, clients should submit a /login request as follows:

{
  "type": "m.login.token",
  "token": "<login token>"
}

As with token-based interactive login, the token must encode the user id. In the case that the token is not valid, the homeserver must respond with 403 Forbidden and an error code of M_FORBIDDEN.

3.3.1   POST /_matrix/client/r0/login

Authenticates the user, and issues an access token they can use to authorize themself in subsequent requests.

If the client does not supply a device_id, the server must auto-generate one.

The returned access token must be associated with the device_id supplied by the client or generated by the server. The server may invalidate any access token previously associated with that device. See Relationship between access tokens and devices.

Rate-limited:Yes.

Request format:

Parameter Type Description
JSON body parameters
type enum Required. The login type being used. One of: ["m.login.password", "m.login.token"]
user string The fully qualified user ID or just local part of the user ID, to log in.
medium string When logging in using a third party identifier, the medium of the identifier. Must be 'email'.
address string Third party identifier for the user.
password string Required when type is m.login.password. The user's password.
token string Required when type is m.login.token. The login token.
device_id string ID of the client device. If this does not correspond to a known client device, a new device will be created. The server will auto-generate a device_id if this is not specified.
initial_device_display_name string A display name to assign to the newly-created device. Ignored if device_id corresponds to a known device.

Response format:

Parameter Type Description
user_id string The fully-qualified Matrix ID that has been registered.
access_token string An access token for the account. This access token can then be used to authorize other requests.
home_server string The hostname of the homeserver on which the account has been registered.
device_id string ID of the logged-in device. Will be the same as the corresponding parameter in the request, if one was specified.

Example request:

POST /_matrix/client/r0/login HTTP/1.1
Content-Type: application/json

{
  "type": "m.login.password",
  "user": "cheeky_monkey",
  "password": "ilovebananas",
  "initial_device_display_name": "Jungle Phone"
}

Responses:

Status code 200:

The user has been authenticated.

Example

{
  "user_id": "@cheeky_monkey:matrix.org",
  "access_token": "abc123",
  "home_server": "matrix.org",
  "device_id": "GHTYAJCE"
}

Status code 400:

Part of the request was invalid. For example, the login type may not be recognised.

Example

{
  "errcode": "M_UNKNOWN",
  "error": "Bad login type."
}

Status code 403:

The login attempt failed. For example, the password may have been incorrect.

Example

{
  "errcode": "M_FORBIDDEN"
}

Status code 429:

This request was rate-limited.

Example

{
  "errcode": "string",
  "error": "string"
}

3.3.2   POST /_matrix/client/r0/logout

Invalidates an existing access token, so that it can no longer be used for authorization.

Requires auth:Yes.

Request format:

No parameters

Example request:

POST /_matrix/client/r0/logout HTTP/1.1

Response:

Status code 200:

The access token used in the request was succesfully invalidated.

Example

{}

3.3.3   Login Fallback

If a client does not recognize any or all login flows it can use the fallback login API:

GET /_matrix/static/client/login/

This returns an HTML and JavaScript page which can perform the entire login process. The page will attempt to call the JavaScript function window.onLogin when login has been successfully completed.

3.4   Account registration and management

3.4.1   POST /_matrix/client/r0/register

This API endpoint uses the User-Interactive Authentication API.

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.

If registration is successful, this endpoint will issue an access token the client can use to authorize itself in subsequent requests.

If the client does not supply a device_id, the server must auto-generate one.

The server SHOULD register an account with a User ID based on the username provided, if any. Note that the grammar of Matrix User ID localparts is restricted, so the server MUST either map the provided username onto a user_id in a logical manner, or reject usernames which do not comply to the grammar, with M_INVALID_USERNAME.

Matrix clients MUST NOT assume that localpart of the registered user_id matches the provided username.

The returned access token must be associated with the device_id supplied by the client or generated by the server. The server may invalidate any access token previously associated with that device. See Relationship between access tokens and devices.

Rate-limited:Yes.

Request format:

Parameter Type Description
query parameters
kind enum The kind of account to register. Defaults to user. One of: ["guest", "user"]
JSON body parameters
auth Authentication Data Additional authentication information for the user-interactive authentication API. Note that this information is not used to define how the registered user should be authenticated, but is instead used to authenticate the register call itself. It should be left empty, or omitted, unless an earlier call returned an response with status code 401.
bind_email boolean If true, the server binds the email used for authentication to the Matrix ID with the ID Server.
username string The basis for the localpart of the desired Matrix ID. If omitted, the homeserver MUST generate a Matrix ID local part.
password string The desired password for the account.
device_id string ID of the client device. If this does not correspond to a known client device, a new device will be created. The server will auto-generate a device_id if this is not specified.
initial_device_display_name string A display name to assign to the newly-created device. Ignored if device_id corresponds to a known device.

Authentication Data

Parameter Type Description
type string Required. The login type that the client is attempting to complete.
session string The value of the session key given by the homeserver.

Response format:

Parameter Type Description
user_id string

The fully-qualified Matrix user ID (MXID) that has been registered.

Any user ID returned by this API must conform to the grammar given in the Matrix specification.

access_token string An access token for the account. This access token can then be used to authorize other requests.
home_server string The hostname of the homeserver on which the account has been registered.
device_id string ID of the registered device. Will be the same as the corresponding parameter in the request, if one was specified.

Example request:

POST /_matrix/client/r0/register?kind=user HTTP/1.1
Content-Type: application/json

{
  "auth": {
    "type": "example.type.foo",
    "session": "xxxxx",
    "example_credential": "verypoorsharedsecret"
  },
  "bind_email": false,
  "username": "cheeky_monkey",
  "password": "ilovebananas",
  "device_id": "GHTYAJCE",
  "initial_device_display_name": "Jungle Phone"
}

Responses:

Status code 200:

The account has been registered.

Example

{
  "user_id": "@cheeky_monkey:matrix.org",
  "access_token": "abc123",
  "home_server": "matrix.org",
  "device_id": "GHTYAJCE"
}

Status code 400:

Part of the request was invalid. This may include one of the following error codes:

  • M_USER_IN_USE : The desired user ID is already taken.
  • M_INVALID_USERNAME : The desired user ID is not a valid user name.
  • M_EXCLUSIVE : The desired user ID is in the exclusive namespace claimed by an application service.

These errors may be returned at any stage of the registration process, including after authentication if the requested user ID was registered whilst the client was performing authentication.

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.

Example

{
  "errcode": "M_USER_IN_USE",
  "error": "Desired user ID is already taken."
}

Status code 401:

The homeserver requires additional authentication information.

Example

{
  "flows": [
    {
      "stages": [
        "example.type.foo"
      ]
    }
  ],
  "params": {
    "example.type.baz": {
      "example_key": "foobar"
    }
  },
  "session": "xxxxxxyz",
  "completed": [
    "example.type.foo"
  ]
}

Status code 429:

This request was rate-limited.

Example

{
  "errcode": "string",
  "error": "string"
}

3.4.2   POST /_matrix/client/r0/register/email/requestToken

Proxies the identity server API validate/email/requestToken, but first checks that the given email address is not already associated with an account on this Home Server. Note that, for consistency, this API takes JSON objects, though the Identity Server API takes x-www-form-urlencoded parameters. See the Identity Server API for further information.

Request format:

Parameter Type Description
JSON body parameters
id_server string The ID server to send the onward request to as a hostname with an appended colon and port number if the port is not the default.
client_secret string Required. Client-generated secret string used to protect this session
email string Required. The email address
send_attempt number Required. Used to distinguish protocol level retries from requests to re-send the email.

Example request:

POST /_matrix/client/r0/register/email/requestToken HTTP/1.1
Content-Type: application/json

{
  "id_server": "id.matrix.org",
  "client_secret": "this_is_my_secret_string",
  "email": "example@example.com",
  "send_attempt": "1"
}

Responses:

Status code 200:

An email has been sent to the specified address. Note that this may be an email containing the validation token or it may be informing the user of an error.

Example

{}

Status code 400:

Part of the request was invalid. This may include one of the following error codes:

  • M_THREEPID_IN_USE : The email address is already registered to an account on this server. However, if the home server has the ability to send email, it is recommended that the server instead send an email to the user with instructions on how to reset their password. This prevents malicious parties from being able to determine if a given email address has an account on the Home Server in question.
  • M_SERVER_NOT_TRUSTED : The id_server parameter refers to an ID server that is not trusted by this Home Server.

Example

{
  "errcode": "M_THREEPID_IN_USE",
  "error": "The specified address is already in use"
}

3.4.3   POST /_matrix/client/r0/account/password

Changes the password for an account on this homeserver.

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.

Rate-limited:Yes.
Requires auth:Yes.

Request format:

Parameter Type Description
JSON body parameters
new_password string Required. The new password for the account.
auth Authentication Data Additional authentication information for the user-interactive authentication API.

Authentication Data

Parameter Type Description
type string Required. The login type that the client is attempting to complete.
session string The value of the session key given by the homeserver.

Example request:

POST /_matrix/client/r0/account/password HTTP/1.1
Content-Type: application/json

{
  "new_password": "ihatebananas",
  "auth": {
    "type": "example.type.foo",
    "session": "xxxxx",
    "example_credential": "verypoorsharedsecret"
  }
}

Responses:

Status code 200:

The password has been changed.

Example

{}

Status code 401:

The homeserver requires additional authentication information.

Example

{
  "flows": [
    {
      "stages": [
        "example.type.foo"
      ]
    }
  ],
  "params": {
    "example.type.baz": {
      "example_key": "foobar"
    }
  },
  "session": "xxxxxxyz",
  "completed": [
    "example.type.foo"
  ]
}

Status code 429:

This request was rate-limited.

Example

{
  "errcode": "string",
  "error": "string"
}

3.4.4   POST /_matrix/client/r0/account/password/email/requestToken

Proxies the identity server API validate/email/requestToken, but first checks that the given email address is associated with an account on this Home Server. This API should be used to request validation tokens when authenticating for the account/password endpoint. This API's parameters and response are identical to that of the HS API /register/email/requestToken except that M_THREEPID_NOT_FOUND may be returned if no account matching the given email address could be found. The server may instead send an email to the given address prompting the user to create an account. M_THREEPID_IN_USE may not be returned.

Request format:

No parameters

Example request:

POST /_matrix/client/r0/account/password/email/requestToken HTTP/1.1

Response:

Status code 200:

An email was sent to the given address

3.4.5   POST /_matrix/client/r0/account/deactivate

Deactivate the user's account, removing all ability for the user to login again.

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.

Rate-limited:Yes.
Requires auth:Yes.

Request format:

Parameter Type Description
JSON body parameters
auth Authentication Data Additional authentication information for the user-interactive authentication API.

Authentication Data

Parameter Type Description
type string Required. The login type that the client is attempting to complete.
session string The value of the session key given by the homeserver.

Example request:

POST /_matrix/client/r0/account/deactivate HTTP/1.1
Content-Type: application/json

{
  "auth": {
    "type": "example.type.foo",
    "session": "xxxxx",
    "example_credential": "verypoorsharedsecret"
  }
}

Responses:

Status code 200:

The account has been deactivated.

Example

{}

Status code 401:

The homeserver requires additional authentication information.

Example

{
  "flows": [
    {
      "stages": [
        "example.type.foo"
      ]
    }
  ],
  "params": {
    "example.type.baz": {
      "example_key": "foobar"
    }
  },
  "session": "xxxxxxyz",
  "completed": [
    "example.type.foo"
  ]
}

Status code 429:

This request was rate-limited.

Example

{
  "errcode": "string",
  "error": "string"
}

3.4.6   Notes on password management

Warning

Clients SHOULD enforce that the password provided is suitably complex. The password SHOULD include a lower-case letter, an upper-case letter, a number and a symbol and be at a minimum 8 characters in length. Servers MAY reject weak passwords with an error code M_WEAK_PASSWORD.

3.5   Adding Account Administrative Contact Information

A homeserver may keep some contact information for administrative use. This is independent of any information kept by any Identity Servers.

3.5.1   GET /_matrix/client/r0/account/3pid

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.

Requires auth:Yes.

Request format:

No parameters

Response format:

Parameter Type Description
threepids [Third party identifier]  

Third party identifier

Parameter Type Description
medium string The medium of the third party identifier. Must be 'email'.
address string The third party identifier address.

Example request:

GET /_matrix/client/r0/account/3pid HTTP/1.1

Response:

Status code 200:

The lookup was successful.

Example

{
  "threepids": [
    {
      "medium": "email",
      "address": "monkey@banana.island"
    }
  ]
}

3.5.2   POST /_matrix/client/r0/account/3pid

Adds contact information to the user's account.

Requires auth:Yes.

Request format:

Parameter Type Description
JSON body parameters
three_pid_creds ThreePidCredentials Required. The third party credentials to associate with the account.
bind boolean Whether the homeserver should also bind this third party identifier to the account's Matrix ID with the passed identity server. Default: false.

ThreePidCredentials

Parameter Type Description
client_secret string Required. The client secret used in the session with the Identity Server.
id_server string Required. The Identity Server to use.
sid string Required. The session identifier given by the Identity Server.

Example request:

POST /_matrix/client/r0/account/3pid HTTP/1.1
Content-Type: application/json

{
  "three_pid_creds": {
    "id_server": "matrix.org",
    "sid": "abc123987",
    "client_secret": "d0n'tT3ll"
  },
  "bind": false
}

Responses:

Status code 200:

The addition was successful.

Example

{}

Status code 403:

The credentials could not be verified with the identity server.

Example

{
  "errcode": "M_THREEPID_AUTH_FAILED",
  "error": "The third party credentials could not be verified by the identity server."
}

3.5.3   POST /_matrix/client/r0/account/3pid/email/requestToken

Proxies the identity server API validate/email/requestToken, but first checks that the given email address is not already associated with an account on this Home Server. This API should be used to request validation tokens when adding an email address to an account. This API's parameters and response is identical to that of the HS API /register/email/requestToken endpoint.

Request format:

No parameters

Example request:

POST /_matrix/client/r0/account/3pid/email/requestToken HTTP/1.1

Response:

Status code 200:

An email was sent to the given address

3.6   Current account information

3.6.1   GET /_matrix/client/r0/account/whoami

Gets information about the owner of a given access token.

Requires auth:Yes.

Request format:

No parameters

Response format:

Parameter Type Description
user_id string Required. The user id that owns the access token.

Example request:

GET /_matrix/client/r0/account/whoami HTTP/1.1

Response:

Status code 200:

The token belongs to a known user.

Example

{
  "user_id": "@joe:example.org"
}

5   Filtering

Filters can be created on the server and can be passed as as a parameter to APIs which return events. These filters alter the data returned from those APIs. Not all APIs accept filters.

5.1   POST /_matrix/client/r0/user/{userId}/filter

Uploads a new filter definition to the homeserver. Returns a filter ID that may be used in future requests to restrict which events are returned to the client.

Requires auth:Yes.

Request format:

Parameter Type Description
path parameters
userId string Required. The id of the user uploading the filter. The access token must be authorized to make requests for this user id.
JSON body parameters
event_fields [string] 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.
event_format enum 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'. One of: ["client", "federation"]
presence Filter The presence updates to include.
account_data Filter The user account data that isn't associated with rooms to include.
room RoomFilter Filters to be applied to room data.

Filter

Parameter Type Description
limit integer The maximum number of events to return.
not_senders [string] 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.
not_types [string] 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.
senders [string] A list of senders IDs to include. If this list is absent then all senders are included.
types [string] 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.

RoomFilter

Parameter Type Description
not_rooms [string] 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. This filter is applied before the filters in ephemeral, state, timeline or account_data
rooms [string] A list of room IDs to include. If this list is absent then all rooms are included. This filter is applied before the filters in ephemeral, state, timeline or account_data
ephemeral RoomEventFilter The events that aren't recorded in the room history, e.g. typing and receipts, to include for rooms.
include_leave boolean Include rooms that the user has left in the sync, default false
state RoomEventFilter The state events to include for rooms.
timeline RoomEventFilter The message and state update events to include for rooms.
account_data RoomEventFilter The per user account data to include for rooms.

RoomEventFilter

Parameter Type Description
limit integer The maximum number of events to return.
not_senders [string] 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.
not_types [string] 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.
senders [string] A list of senders IDs to include. If this list is absent then all senders are included.
types [string] 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.
not_rooms [string] 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.
rooms [string] A list of room IDs to include. If this list is absent then all rooms are included.
contains_url boolean If true, includes only events with a url key in their content. If false, excludes those events.

Response format:

Parameter Type Description
filter_id string The ID of the filter that was created.

Example request:

POST /_matrix/client/r0/user/%40alice%3Aexample.com/filter HTTP/1.1
Content-Type: application/json

{
  "room": {
    "state": {
      "types": [
        "m.room.*"
      ],
      "not_rooms": [
        "!726s6s6q:example.com"
      ]
    },
    "timeline": {
      "limit": 10,
      "types": [
        "m.room.message"
      ],
      "not_rooms": [
        "!726s6s6q:example.com"
      ],
      "not_senders": [
        "@spam:example.com"
      ]
    },
    "ephemeral": {
      "types": [
        "m.receipt",
        "m.typing"
      ],
      "not_rooms": [
        "!726s6s6q:example.com"
      ],
      "not_senders": [
        "@spam:example.com"
      ]
    }
  },
  "presence": {
    "types": [
      "m.presence"
    ],
    "not_senders": [
      "@alice:example.com"
    ]
  },
  "event_format": "client",
  "event_fields": [
    "type",
    "content",
    "sender"
  ]
}

Response:

Status code 200:

The filter was created.

Example

{
  "filter_id": "66696p746572"
}

5.2   GET /_matrix/client/r0/user/{userId}/filter/{filterId}

Download a filter

Requires auth:Yes.

Request format:

Parameter Type Description
path parameters
userId string Required. The user ID to download a filter for.
filterId string Required. The filter ID to download.

Response format:

Parameter Type Description
event_fields [string] 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.
event_format enum 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'. One of: ["client", "federation"]
presence Filter The presence updates to include.
account_data Filter The user account data that isn't associated with rooms to include.
room RoomFilter Filters to be applied to room data.

Filter

Parameter Type Description
limit integer The maximum number of events to return.
not_senders [string] 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.
not_types [string] 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.
senders [string] A list of senders IDs to include. If this list is absent then all senders are included.
types [string] 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.

RoomFilter

Parameter Type Description
not_rooms [string] 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. This filter is applied before the filters in ephemeral, state, timeline or account_data
rooms [string] A list of room IDs to include. If this list is absent then all rooms are included. This filter is applied before the filters in ephemeral, state, timeline or account_data
ephemeral RoomEventFilter The events that aren't recorded in the room history, e.g. typing and receipts, to include for rooms.
include_leave boolean Include rooms that the user has left in the sync, default false
state RoomEventFilter The state events to include for rooms.
timeline RoomEventFilter The message and state update events to include for rooms.
account_data RoomEventFilter The per user account data to include for rooms.

RoomEventFilter

Parameter Type Description
limit integer The maximum number of events to return.
not_senders [string] 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.
not_types [string] 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.
senders [string] A list of senders IDs to include. If this list is absent then all senders are included.
types [string] 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.
not_rooms [string] 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.
rooms [string] A list of room IDs to include. If this list is absent then all rooms are included.
contains_url boolean If true, includes only events with a url key in their content. If false, excludes those events.

Example request:

GET /_matrix/client/r0/user/%40alice%3Aexample.com/filter/66696p746572 HTTP/1.1

Responses:

Status code 200:

"The filter defintion"

Example

{
  "room": {
    "state": {
      "types": [
        "m.room.*"
      ],
      "not_rooms": [
        "!726s6s6q:example.com"
      ]
    },
    "timeline": {
      "limit": 10,
      "types": [
        "m.room.message"
      ],
      "not_rooms": [
        "!726s6s6q:example.com"
      ],
      "not_senders": [
        "@spam:example.com"
      ]
    },
    "ephemeral": {
      "types": [
        "m.receipt",
        "m.typing"
      ],
      "not_rooms": [
        "!726s6s6q:example.com"
      ],
      "not_senders": [
        "@spam:example.com"
      ]
    }
  },
  "presence": {
    "types": [
      "m.presence"
    ],
    "not_senders": [
      "@alice:example.com"
    ]
  },
  "event_format": "client",
  "event_fields": [
    "type",
    "content",
    "sender"
  ]
}

Status code 404:

Unknown filter.

6   Events

The model of conversation history exposed by the client-server API can be considered as a list of events. The server 'linearises' the eventually-consistent event graph of events into an 'event stream' at any given point in time:

[E0]->[E1]->[E2]->[E3]->[E4]->[E5]

6.1   Types of room events

Room events are split into two categories:

State Events:These are events which update the metadata state of the room (e.g. room topic, room membership etc). State is keyed by a tuple of event type and a state_key. State in the room with the same key-tuple will be overwritten.
Message events:These are events which describe transient "once-off" activity in a room: typically communication such as sending an instant message or setting up a VoIP call.

This specification outlines several events, all with the event type prefix m.. (See Room Events for the m. event specification.) However, applications may wish to add their own type of event, and this can be achieved using the REST API detailed in the following sections. If new events are added, the event type key SHOULD follow the Java package naming convention, e.g. com.example.myapp.event. This ensures event types are suitably namespaced for each application and reduces the risk of clashes.

6.2   Syncing

To read events, the intended flow of operation is for clients to first call the /sync API without a since parameter. This returns the most recent message events for each room, as well as the state of the room at the start of the returned timeline. The response also includes a next_batch field, which should be used as the value of the since parameter in the next call to /sync. Finally, the response includes, for each room, a prev_batch field, which can be passed as a start parameter to the /rooms/<room_id>/messages API to retrieve earlier messages.

You can visualise the range of events being returned as:

[E0]->[E1]->[E2]->[E3]->[E4]->[E5]
           ^                      ^
           |                      |
     prev_batch: '1-2-3'        next_batch: 'a-b-c'

Clients then receive new events by "long-polling" the homeserver via the /sync API, passing the value of the next_batch field from the response to the previous call as the since parameter. The client should also pass a timeout parameter. The server will then hold open the HTTP connection for a short period of time waiting for new events, returning early if an event occurs. Only the /sync API (and the deprecated /events API) support long-polling in this way.

The response for such an incremental sync can be visualised as:

[E0]->[E1]->[E2]->[E3]->[E4]->[E5]->[E6]
                                  ^     ^
                                  |     |
                                  |  next_batch: 'x-y-z'
                                prev_batch: 'a-b-c'

Normally, all new events which are visible to the client will appear in the response to the /sync API. However, if a large number of events arrive between calls to /sync, a "limited" timeline is returned, containing only the most recent message events. A state "delta" is also returned, summarising any state changes in the omitted part of the timeline. The client may therefore end up with "gaps" in its knowledge of the message timeline. The client can fill these gaps using the /rooms/<room_id>/messages API. This situation looks like this:

                                  | gap |
                                  | <-> |
[E0]->[E1]->[E2]->[E3]->[E4]->[E5]->[E6]->[E7]->[E8]->[E9]->[E10]
                                        ^                        ^
                                        |                        |
                                   prev_batch: 'd-e-f'       next_batch: 'u-v-w'

Warning

Events are ordered in this API according to the arrival time of the event on the homeserver. This can conflict with other APIs which order events based on their partial ordering in the event graph. This can result in duplicate events being received (once per distinct API called). Clients SHOULD de-duplicate events based on the event ID when this happens.

Note

The /sync API returns a state list which is separate from the timeline. This state list allows clients to keep their model of the room state in sync with that on the server. In the case of an initial (since-less) sync, the state list represents the complete state of the room at the start of the returned timeline (so in the case of a recently-created room whose state fits entirely in the timeline, the state list will be empty).

In the case of an incremental sync, the state list gives a delta between the state of the room at the since parameter and that at the start of the returned timeline. (It will therefore be empty unless the timeline was limited.)

In both cases, it should be noted that the events returned in the state list did not necessarily take place just before the returned timeline, so clients should not display them to the user in the timeline.

Rationale

An early design of this specification made the state list represent the room state at the end of the returned timeline, instead of the start. This was unsatisfactory because it led to duplication of events between the state list and the timeline, but more importantly, it made it difficult for clients to show the timeline correctly.

In particular, consider a returned timeline [M0, S1, M2], where M0 and M2 are both messages sent by the same user, and S1 is a state event where that user changes their displayname. If the state list represents the room state at the end of the timeline, the client must take a copy of the state dictionary, and rewind S1, in order to correctly calculate the display name for M0.

6.2.1   GET /_matrix/client/r0/sync

Synchronise the client's state with the latest state on the server. Clients use this API when they first log in to get an initial snapshot of the state on the server, and then continue to call this API to get incremental deltas to the state, and to receive new messages.

Requires auth:Yes.

Request format:

Parameter Type Description
query parameters
filter string The ID of a filter created using the filter API or a filter JSON object encoded as a string. The server will detect whether it is an ID or a JSON object by whether the first character is a "{" open brace. Passing the JSON inline is best suited to one off requests. Creating a filter using the filter API is recommended for clients that reuse the same filter multiple times, for example in long poll requests.
since string A point in time to continue a sync from.
full_state boolean

Controls whether to include the full state for all rooms the user is a member of.

If this is set to true, then all state events will be returned, even if since is non-empty. The timeline will still be limited by the since parameter. In this case, the timeout parameter will be ignored and the query will return immediately, possibly with an empty timeline.

If false, and since is non-empty, only state which has changed since the point indicated by since will be returned.

By default, this is false.

set_presence enum Controls whether the client is automatically marked as online by polling this API. If this parameter is omitted then the client is automatically marked as online when it uses this API. Otherwise if the parameter is set to "offline" then the client is not marked as being online when it uses this API. One of: ["offline"]
timeout integer

The maximum time to wait, in milliseconds, before returning this request. If no events (or other data) become available before this time elapses, the server will return a response with empty fields.

By default, this is 0, so the server will return immediately even if the response is empty.

Response format:

Parameter Type Description
next_batch string The batch token to supply in the since param of the next /sync request.
rooms Rooms Updates to rooms.
presence Presence The updates to the presence status of other users.
account_data Account Data The global private data created by this user.
to_device ToDevice Information on the send-to-device messages for the client device, as defined in Send-to-Device messaging.
device_lists DeviceLists Information on end-to-end device updates, as specified in End-to-end encryption.

Rooms

Parameter Type Description
join {string: Joined Room} The rooms that the user has joined.
invite {string: Invited Room} The rooms that the user has been invited to.
leave {string: Left Room} The rooms that the user has left or been banned from.

Joined Room

Parameter Type Description
state State 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).
timeline Timeline The timeline of messages and state changes in the room.
ephemeral Ephemeral The ephemeral events in the room that aren't recorded in the timeline or state of the room. e.g. typing.
account_data Account Data The private data that this user has attached to this room.
unread_notifications Unread Notification Counts Counts of unread notifications for this room

Ephemeral

Parameter Type Description
events [Event] List of events

Unread Notification Counts

Parameter Type Description
highlight_count integer The number of unread notifications for this room with the highlight flag set
notification_count integer The total number of unread notifications for this room

Invited Room

Parameter Type Description
invite_state InviteState The state of a room that the user has been invited to. These state events may only have the sender, type, state_key and content keys present. These events do not replace any state that the client already has for the room, for example if the client has archived the room. Instead the client should keep two separate copies of the state: the one from the invite_state and one from the archived state. If the client joins the room then the current state will be given as a delta against the archived state not the invite_state.

InviteState

Parameter Type Description
events [Event] List of events

Left Room

Parameter Type Description
state State The state updates for the room up to the start of the timeline.
timeline Timeline The timeline of messages and state changes in the room up to the point when the user left.

State

Parameter Type Description
events [Event] List of events

Timeline

Parameter Type Description
events [Event] List of events
limited boolean True if the number of events returned was limited by the limit on the filter
prev_batch string A token that can be supplied to to the from parameter of the rooms/{roomId}/messages endpoint

Presence

Parameter Type Description
events [Event] List of events

Account Data

Parameter Type Description
events [Event] List of events

Event

Parameter Type Description
event_id string The ID of this event, if applicable.
content EventContent The content of this event. The fields in this object will vary depending on the type of event.
origin_server_ts integer Timestamp in milliseconds on originating homeserver when this event was sent.
sender string The MXID of the user who sent this event.
state_key string 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 The type of event.
unsigned Unsigned Information about this event which was not sent by the originating homeserver

Unsigned

Parameter Type Description
age integer Time in milliseconds since the event was sent.
prev_content EventContent 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.
transaction_id string 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.
redacted_because Event Optional. The event that redacted this event, if any.

Example request:

GET /_matrix/client/r0/sync?filter=66696p746572&since=s72594_4483_1934&full_state=false&set_presence=offline&timeout=30000 HTTP/1.1

Response:

Status code 200:

The initial snapshot or delta for the client to use to update their state.

Example

{
  "next_batch": "s72595_4483_1934",
  "presence": {
    "events": [
      {
        "sender": "@alice:example.com",
        "type": "m.presence",
        "content": {
          "presence": "online"
        }
      }
    ]
  },
  "account_data": {
    "events": [
      {
        "type": "org.example.custom.config",
        "content": {
          "custom_config_key": "custom_config_value"
        }
      }
    ]
  },
  "rooms": {
    "join": {
      "!726s6s6q:example.com": {
        "state": {
          "events": [
            {
              "sender": "@alice:example.com",
              "type": "m.room.member",
              "state_key": "@alice:example.com",
              "content": {
                "membership": "join"
              },
              "origin_server_ts": 1417731086795,
              "event_id": "$66697273743031:example.com"
            }
          ]
        },
        "timeline": {
          "events": [
            {
              "sender": "@bob:example.com",
              "type": "m.room.member",
              "state_key": "@bob:example.com",
              "content": {
                "membership": "join"
              },
              "prev_content": {
                "membership": "invite"
              },
              "origin_server_ts": 1417731086795,
              "event_id": "$7365636s6r6432:example.com"
            },
            {
              "sender": "@alice:example.com",
              "type": "m.room.message",
              "age": 124524,
              "txn_id": "1234",
              "content": {
                "body": "I am a fish",
                "msgtype": "m.text"
              },
              "origin_server_ts": 1417731086797,
              "event_id": "$74686972643033:example.com"
            }
          ],
          "limited": true,
          "prev_batch": "t34-23535_0_0"
        },
        "ephemeral": {
          "events": [
            {
              "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"
              }
            }
          ]
        }
      }
    },
    "invite": {
      "!696r7674:example.com": {
        "invite_state": {
          "events": [
            {
              "sender": "@alice:example.com",
              "type": "m.room.name",
              "state_key": "",
              "content": {
                "name": "My Room Name"
              }
            },
            {
              "sender": "@alice:example.com",
              "type": "m.room.member",
              "state_key": "@bob:example.com",
              "content": {
                "membership": "invite"
              }
            }
          ]
        }
      }
    },
    "leave": {}
  }
}

6.2.2   GET /_matrix/client/r0/events

Warning

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

This will listen for new events and return them to the caller. This will block until an event is received, or until the timeout is reached.

This endpoint was deprecated in r0 of this specification. Clients should instead call the /sync API with a since parameter. See the migration guide.

Requires auth:Yes.

Request format:

Parameter Type Description
query parameters
from string The token to stream from. This token is either from a previous request to this API or from the initial sync API.
timeout integer The maximum time in milliseconds to wait for an event.

Response format:

Parameter Type Description
start string A token which correlates to the first value in chunk. This is usually the same token supplied to from=.
end string A token which correlates to the last value in chunk. This token should be used in the next request to /events.
chunk [Event] An array of events.

Event

Parameter Type Description
content object The fields in this object will vary depending on the type of event. When interacting with the REST API, this is the HTTP body.
type string Required. The type of event. This SHOULD be namespaced similar to Java package naming conventions e.g. 'com.example.subdomain.event.type'
event_id string Required. The globally unique event identifier.
room_id string Required. The ID of the room associated with this event.
sender string Required. Contains the fully-qualified ID of the user who sent this event.
origin_server_ts number Required. Timestamp in milliseconds on originating homeserver when this event was sent.
unsigned UnsignedData Contains optional extra information about the event.

UnsignedData

Parameter Type Description
age integer The time in milliseconds that has elapsed since the event was sent. This field is generated by the local homeserver, and may be incorrect if the local time on at least one of the two servers is out of sync, which can cause the age to either be negative or greater than it actually is.
redacted_because Event Optional. The event that redacted this event, if any.
transaction_id string The client-supplied transaction ID, if the client being given the event is the same one which sent it.

Example request:

GET /_matrix/client/r0/events?from=s3456_9_0&timeout=35000 HTTP/1.1

Responses:

Status code 200:

The events received, which may be none.

Example

{
  "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"
    }
  ]
}

Status code 400:

Bad pagination from parameter.

6.2.3   GET /_matrix/client/r0/initialSync

Warning

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

This returns the full state for this user, with an optional limit on the number of messages per room to return.

This endpoint was deprecated in r0 of this specification. Clients should instead call the /sync API with no since parameter. See the migration guide.

Requires auth:Yes.

Request format:

Parameter Type Description
query parameters
limit integer The maximum number of messages to return for each room.
archived boolean Whether to include rooms that the user has left. If false then only rooms that the user has been invited to or has joined are included. If set to true then rooms that the user has left are included as well. By default this is false.

Response format:

Parameter Type Description
end string Required. A token which correlates to the last value in chunk. This token should be used with the /events API to listen for new events.
presence [Event] Required. A list of presence events.
rooms [RoomInfo] Required.
account_data [Event] The global private data created by this user.

RoomInfo

Parameter Type Description
room_id string Required. The ID of this room.
membership enum Required. The user's membership state in this room. One of: ["invite", "join", "leave", "ban"]
invite InviteEvent The invite event if membership is invite
messages PaginationChunk The pagination chunk for this room.
state [StateEvent] If the user is a member of the room this will be the current state of the room as a list of events. If the user has left the room this will be the state of the room when they left it.
visibility enum Whether this room is visible to the /publicRooms API or not." One of: ["private", "public"]
account_data [Event] The private data that this user has attached to this room.

InviteEvent

Parameter Type Description
content EventContent  
type string Required. Must be 'm.room.member'.
event_id string Required. The globally unique event identifier.
room_id string Required. The ID of the room associated with this event.
sender string Required. Contains the fully-qualified ID of the user who sent this event.
origin_server_ts number Required. Timestamp in milliseconds on originating homeserver when this event was sent.
unsigned UnsignedData Contains optional extra information about the event.
prev_content EventContent Optional. The previous content for this event. If there is no previous content, this key will be missing.
state_key string Required. The user_id this membership event relates to.
invite_room_state [StrippedState] A subset of the state of the room at the time of the invite, if membership is invite. Note that this state is informational, and SHOULD NOT be trusted; once the client has joined the room, it SHOULD fetch the live state from the server and discard the invite_room_state. Also, clients must not rely on any particular state being present here; they SHOULD behave properly (with possibly a degraded but not a broken experience) in the absence of any particular events here. If they are set on the room, at least the state for m.room.avatar, m.room.canonical_alias, m.room.join_rules, and m.room.name SHOULD be included.

EventContent

Parameter Type Description
avatar_url string The avatar URL for this user, if any. This is added by the homeserver.
displayname string or null The display name for this user, if any. This is added by the homeserver.
membership enum Required. The membership state of the user. One of: ["invite", "join", "knock", "leave", "ban"]
is_direct boolean Flag indicating if the room containing this event was created with the intention of being a direct chat. See Direct Messaging.
third_party_invite Invite  

Invite

Parameter Type Description
display_name string Required. A name which can be displayed to represent the user instead of their third party identifier
signed signed Required. A block of content which has been signed, which servers can use to verify the event. Clients should ignore this.

signed

Parameter Type Description
mxid string Required. The invited matrix user ID. Must be equal to the user_id property of the event.
signatures Signatures Required. A single signature from the verifying server, in the format specified by the Signing Events section of the server-server API.
token string Required. The token property of the containing third_party_invite object.

StrippedState

Parameter Type Description
content EventContent Required. The content for the event.
state_key string Required. The state_key for the event.
type string Required. The type for the event.

PaginationChunk

Parameter Type Description
start string Required. A token which correlates to the first value in chunk. Used for pagination.
end string Required. A token which correlates to the last value in chunk. Used for pagination.
chunk [RoomEvent] Required. If the user is a member of the room this will be a list of the most recent messages for this room. If the user has left the room this will be the messages that preceeded them leaving. This array will consist of at most limit elements.

RoomEvent

Parameter Type Description
content object The fields in this object will vary depending on the type of event. When interacting with the REST API, this is the HTTP body.
type string Required. The type of event. This SHOULD be namespaced similar to Java package naming conventions e.g. 'com.example.subdomain.event.type'
event_id string Required. The globally unique event identifier.
room_id string Required. The ID of the room associated with this event.
sender string Required. Contains the fully-qualified ID of the user who sent this event.
origin_server_ts number Required. Timestamp in milliseconds on originating homeserver when this event was sent.
unsigned UnsignedData Contains optional extra information about the event.

StateEvent

Parameter Type Description
content object The fields in this object will vary depending on the type of event. When interacting with the REST API, this is the HTTP body.
type string Required. The type of event. This SHOULD be namespaced similar to Java package naming conventions e.g. 'com.example.subdomain.event.type'
event_id string Required. The globally unique event identifier.
room_id string Required. The ID of the room associated with this event.
sender string Required. Contains the fully-qualified ID of the user who sent this event.
origin_server_ts number Required. Timestamp in milliseconds on originating homeserver when this event was sent.
unsigned UnsignedData Contains optional extra information about the event.
prev_content EventContent Optional. The previous content for this event. If there is no previous content, this key will be missing.
state_key string Required. A unique key which defines the overwriting semantics for this piece of room state. This value is often a zero-length string. The presence of this key makes this event a State Event. The key MUST NOT start with '_'.

UnsignedData

Parameter Type Description
age integer The time in milliseconds that has elapsed since the event was sent. This field is generated by the local homeserver, and may be incorrect if the local time on at least one of the two servers is out of sync, which can cause the age to either be negative or greater than it actually is.
redacted_because Event Optional. The event that redacted this event, if any.
transaction_id string The client-supplied transaction ID, if the client being given the event is the same one which sent it.

Event

Parameter Type Description
content object The fields in this object will vary depending on the type of event. When interacting with the REST API, this is the HTTP body.
type string Required. The type of event. This SHOULD be namespaced similar to Java package naming conventions e.g. 'com.example.subdomain.event.type'

Example request:

GET /_matrix/client/r0/initialSync?limit=2&archived=true HTTP/1.1

Responses:

Status code 200:

The user's current state.

Example

{
  "end": "s3456_9_0",
  "presence": [
    {
      "content": {
        "avatar_url": "mxc://localhost/GCmhgzMPRjqgpODLsNQzVuHZ#auto",
        "displayname": "Bob",
        "last_active_ago": 31053,
        "presence": "online",
        "user_id": "@bob:localhost"
      },
      "type": "m.presence"
    }
  ],
  "account_data": [
    {
      "type": "org.example.custom.config",
      "content": {
        "custom_config_key": "custom_config_value"
      }
    }
  ],
  "rooms": [
    {
      "membership": "join",
      "messages": {
        "chunk": [
          {
            "age": 343513403,
            "content": {
              "body": "foo",
              "msgtype": "m.text"
            },
            "event_id": "$14328044851tzTJS:localhost",
            "origin_server_ts": 1432804485886,
            "room_id": "!TmaZBKYIFrIPVGoUYp:localhost",
            "type": "m.room.message",
            "sender": "@alice:localhost"
          },
          {
            "age": 343511809,
            "content": {
              "body": "bar",
              "msgtype": "m.text"
            },
            "event_id": "$14328044872spjFg:localhost",
            "origin_server_ts": 1432804487480,
            "room_id": "!TmaZBKYIFrIPVGoUYp:localhost",
            "type": "m.room.message",
            "sender": "@bob:localhost"
          }
        ],
        "end": "s3456_9_0",
        "start": "t44-3453_9_0"
      },
      "room_id": "!TmaZBKYIFrIPVGoUYp:localhost",
      "state": [
        {
          "age": 7148266897,
          "content": {
            "join_rule": "public"
          },
          "event_id": "$14259997323TLwtb:localhost",
          "origin_server_ts": 1425999732392,
          "room_id": "!TmaZBKYIFrIPVGoUYp:localhost",
          "state_key": "",
          "type": "m.room.join_rules",
          "sender": "@alice:localhost"
        },
        {
          "age": 6547561012,
          "content": {
            "avatar_url": "mxc://localhost/fzysBrHpPEeTGANCVLXWXNMI#auto",
            "membership": "join"
          },
          "event_id": "$1426600438280zExKY:localhost",
          "membership": "join",
          "origin_server_ts": 1426600438277,
          "room_id": "!TmaZBKYIFrIPVGoUYp:localhost",
          "state_key": "@alice:localhost",
          "type": "m.room.member",
          "sender": "@alice:localhost"
        },
        {
          "age": 7148267200,
          "content": {
            "creator": "@alice:localhost"
          },
          "event_id": "$14259997320KhbwJ:localhost",
          "origin_server_ts": 1425999732089,
          "room_id": "!TmaZBKYIFrIPVGoUYp:localhost",
          "state_key": "",
          "type": "m.room.create",
          "sender": "@alice:localhost"
        },
        {
          "age": 1622568720,
          "content": {
            "avatar_url": "mxc://localhost/GCmhgzMPRjqgpODLsNQzVuHZ#auto",
            "displayname": "Bob",
            "membership": "join"
          },
          "event_id": "$1431525430134MxlLX:localhost",
          "origin_server_ts": 1431525430569,
          "replaces_state": "$142652023736BSXcM:localhost",
          "room_id": "!TmaZBKYIFrIPVGoUYp:localhost",
          "state_key": "@bob:localhost",
          "type": "m.room.member",
          "sender": "@bob:localhost"
        },
        {
          "age": 7148267004,
          "content": {
            "ban": 50,
            "events": {
              "m.room.name": 100,
              "m.room.power_levels": 100
            },
            "events_default": 0,
            "kick": 50,
            "redact": 50,
            "state_default": 50,
            "users": {
              "@alice:localhost": 100
            },
            "users_default": 0
          },
          "event_id": "$14259997322mqfaq:localhost",
          "origin_server_ts": 1425999732285,
          "room_id": "!TmaZBKYIFrIPVGoUYp:localhost",
          "state_key": "",
          "type": "m.room.power_levels",
          "sender": "@alice:localhost"
        }
      ],
      "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"
          }
        }
      ]
    }
  ]
}

Status code 404:

There is no avatar URL for this user or this user does not exist.

6.2.4   GET /_matrix/client/r0/events/{eventId}

Warning

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

Get a single event based on event_id. You must have permission to retrieve this event e.g. by being a member in the room for this event.

This endpoint was deprecated in r0 of this specification. Clients should instead call the /rooms/{roomId}/context/{eventId} API.

Requires auth:Yes.

Request format:

Parameter Type Description
path parameters
eventId string Required. The event ID to get.

Response format:

Event

Parameter Type Description
content object The fields in this object will vary depending on the type of event. When interacting with the REST API, this is the HTTP body.
type string Required. The type of event. This SHOULD be namespaced similar to Java package naming conventions e.g. 'com.example.subdomain.event.type'

Example request:

GET /_matrix/client/r0/events/%24asfDuShaf7Gafaw%3Amatrix.org HTTP/1.1

Responses:

Status code 200:

The full event.

Example

{
  "content": {
    "body": "Hello world!",
    "msgtype": "m.text"
  },
  "room_id": "!wfgy43Sg4a:matrix.org",
  "sender": "@bob:matrix.org",
  "event_id": "$asfDuShaf7Gafaw:matrix.org",
  "type": "m.room.message"
}

Status code 404:

The event was not found or you do not have permission to read this event.

6.3   Getting events for a room

There are several APIs provided to GET events for a room:

6.3.1   GET /_matrix/client/r0/rooms/{roomId}/state/{eventType}/{stateKey}

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.

Requires auth:Yes.

Request format:

Parameter Type Description
path parameters
roomId string Required. The room to look up the state in.
eventType string Required. The type of state to look up.
stateKey string Required. The key of the state to look up.

Example request:

GET /_matrix/client/r0/rooms/%21636q39766251%3Aexample.com/state/m.room.name/ HTTP/1.1

Responses:

Status code 200:

The content of the state event.

Example

{
  "name": "Example room name"
}

Status code 403:

You aren't a member of the room and weren't previously a member of the room.

Status code 404:

The room has no state with the given type or key.

6.3.2   GET /_matrix/client/r0/rooms/{roomId}/state/{eventType}

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.

Requires auth:Yes.

Request format:

Parameter Type Description
path parameters
roomId string Required. The room to look up the state in.
eventType string Required. The type of state to look up.

Example request:

GET /_matrix/client/r0/rooms/%21636q39766251%3Aexample.com/state/m.room.name HTTP/1.1

Responses:

Status code 200:

The content of the state event.

Example

{
  "name": "Example room name"
}

Status code 403:

You aren't a member of the room and weren't previously a member of the room.

Status code 404:

The room has no state with the given type or key.

6.3.3   GET /_matrix/client/r0/rooms/{roomId}/state

Get the state events for the current state of a room.

Requires auth:Yes.

Request format:

Parameter Type Description
path parameters
roomId string Required. The room to look up the state for.

Response format:

Parameter Type Description
<body> [StateEvent] If the user is a member of the room this will be the current state of the room as a list of events. If the user has left the room then this will be the state of the room when they left as a list of events.

StateEvent

Parameter Type Description
content object The fields in this object will vary depending on the type of event. When interacting with the REST API, this is the HTTP body.
type string Required. The type of event. This SHOULD be namespaced similar to Java package naming conventions e.g. 'com.example.subdomain.event.type'
event_id string Required. The globally unique event identifier.
room_id string Required. The ID of the room associated with this event.
sender string Required. Contains the fully-qualified ID of the user who sent this event.
origin_server_ts number Required. Timestamp in milliseconds on originating homeserver when this event was sent.
unsigned UnsignedData Contains optional extra information about the event.
prev_content EventContent Optional. The previous content for this event. If there is no previous content, this key will be missing.
state_key string Required. A unique key which defines the overwriting semantics for this piece of room state. This value is often a zero-length string. The presence of this key makes this event a State Event. The key MUST NOT start with '_'.

UnsignedData

Parameter Type Description
age integer The time in milliseconds that has elapsed since the event was sent. This field is generated by the local homeserver, and may be incorrect if the local time on at least one of the two servers is out of sync, which can cause the age to either be negative or greater than it actually is.
redacted_because Event Optional. The event that redacted this event, if any.
transaction_id string The client-supplied transaction ID, if the client being given the event is the same one which sent it.

Example request:

GET /_matrix/client/r0/rooms/%21636q39766251%3Aexample.com/state HTTP/1.1

Responses:

Status code 200:

The current state of the room

Example

[
  {
    "age": 7148266897,
    "content": {
      "join_rule": "public"
    },
    "event_id": "$14259997323TLwtb:example.com",
    "origin_server_ts": 1425999732392,
    "room_id": "!636q39766251:example.com",
    "state_key": "",
    "type": "m.room.join_rules",
    "sender": "@alice:example.com"
  },
  {
    "age": 6547561012,
    "content": {
      "avatar_url": "mxc://example.com/fzysBrHpPEeTGANCVLXWXNMI#auto",
      "membership": "join"
    },
    "event_id": "$1426600438280zExKY:example.com",
    "membership": "join",
    "origin_server_ts": 1426600438277,
    "room_id": "!636q39766251:example.com",
    "state_key": "@alice:example.com",
    "type": "m.room.member",
    "sender": "@alice:example.com"
  },
  {
    "age": 7148267200,
    "content": {
      "creator": "@alice:example.com"
    },
    "event_id": "$14259997320KhbwJ:example.com",
    "origin_server_ts": 1425999732089,
    "room_id": "!636q39766251:example.com",
    "state_key": "",
    "type": "m.room.create",
    "sender": "@alice:example.com"
  },
  {
    "age": 1622568720,
    "content": {
      "avatar_url": "mxc://example.com/GCmhgzMPRjqgpODLsNQzVuHZ#auto",
      "displayname": "Bob",
      "membership": "join"
    },
    "event_id": "$1431525430134MxlLX:example.com",
    "origin_server_ts": 1431525430569,
    "replaces_state": "$142652023736BSXcM:example.com",
    "room_id": "!636q39766251:example.com",
    "state_key": "@bob:example.com",
    "type": "m.room.member",
    "sender": "@bob:example.com"
  },
  {
    "age": 7148267004,
    "content": {
      "ban": 50,
      "events": {
        "m.room.name": 100,
        "m.room.power_levels": 100
      },
      "events_default": 0,
      "kick": 50,
      "redact": 50,
      "state_default": 50,
      "users": {
        "@alice:example.com": 100
      },
      "users_default": 0
    },
    "event_id": "$14259997322mqfaq:example.com",
    "origin_server_ts": 1425999732285,
    "room_id": "!636q39766251:example.com",
    "state_key": "",
    "type": "m.room.power_levels",
    "sender": "@alice:example.com"
  }
]

Status code 403:

You aren't a member of the room and weren't previously a member of the room.

6.3.4   GET /_matrix/client/r0/rooms/{roomId}/members

Get the list of members for this room.

Request format:

Parameter Type Description
path parameters
roomId string Required. The room to get the member events for.

Response format:

Parameter Type Description
chunk [MemberEvent]  

MemberEvent

Parameter Type Description
content EventContent  
type string Required. Must be 'm.room.member'.
event_id string Required. The globally unique event identifier.
room_id string Required. The ID of the room associated with this event.
sender string Required. Contains the fully-qualified ID of the user who sent this event.
origin_server_ts number Required. Timestamp in milliseconds on originating homeserver when this event was sent.
unsigned UnsignedData Contains optional extra information about the event.
prev_content EventContent Optional. The previous content for this event. If there is no previous content, this key will be missing.
state_key string Required. The user_id this membership event relates to.
invite_room_state [StrippedState] A subset of the state of the room at the time of the invite, if membership is invite. Note that this state is informational, and SHOULD NOT be trusted; once the client has joined the room, it SHOULD fetch the live state from the server and discard the invite_room_state. Also, clients must not rely on any particular state being present here; they SHOULD behave properly (with possibly a degraded but not a broken experience) in the absence of any particular events here. If they are set on the room, at least the state for m.room.avatar, m.room.canonical_alias, m.room.join_rules, and m.room.name SHOULD be included.

EventContent

Parameter Type Description
avatar_url string The avatar URL for this user, if any. This is added by the homeserver.
displayname string or null The display name for this user, if any. This is added by the homeserver.
membership enum Required. The membership state of the user. One of: ["invite", "join", "knock", "leave", "ban"]
is_direct boolean Flag indicating if the room containing this event was created with the intention of being a direct chat. See Direct Messaging.
third_party_invite Invite  

Invite

Parameter Type Description
display_name string Required. A name which can be displayed to represent the user instead of their third party identifier
signed signed Required. A block of content which has been signed, which servers can use to verify the event. Clients should ignore this.

signed

Parameter Type Description
mxid string Required. The invited matrix user ID. Must be equal to the user_id property of the event.
signatures Signatures Required. A single signature from the verifying server, in the format specified by the Signing Events section of the server-server API.
token string Required. The token property of the containing third_party_invite object.

UnsignedData

Parameter Type Description
age integer The time in milliseconds that has elapsed since the event was sent. This field is generated by the local homeserver, and may be incorrect if the local time on at least one of the two servers is out of sync, which can cause the age to either be negative or greater than it actually is.
redacted_because Event Optional. The event that redacted this event, if any.
transaction_id string The client-supplied transaction ID, if the client being given the event is the same one which sent it.

StrippedState

Parameter Type Description
content EventContent Required. The content for the event.
state_key string Required. The state_key for the event.
type string Required. The type for the event.

Example request:

GET /_matrix/client/r0/rooms/%21636q39766251%3Aexample.com/members HTTP/1.1

Responses:

Status code 200:

A list of members of the room. If you are joined to the room then this will be the current members of the room. If you have left the room then this will be the members of the room when you left.

Example

{
  "chunk": [
    {
      "age": 6547561012,
      "content": {
        "avatar_url": "mxc://example.com/fzysBrHpPEeTGANCVLXWXNMI#auto",
        "membership": "join"
      },
      "event_id": "$1426600438280zExKY:example.com",
      "membership": "join",
      "origin_server_ts": 1426600438277,
      "room_id": "!636q39766251:example.com",
      "state_key": "@alice:example.com",
      "type": "m.room.member",
      "sender": "@alice:example.com"
    },
    {
      "age": 1622568720,
      "content": {
        "avatar_url": "mxc://example.com/GCmhgzMPRjqgpODLsNQzVuHZ#auto",
        "displayname": "Bob",
        "membership": "join"
      },
      "event_id": "$1431525430134MxlLX:example.com",
      "origin_server_ts": 1431525430569,
      "replaces_state": "$142652023736BSXcM:example.com",
      "room_id": "!636q39766251:example.com",
      "state_key": "@bob:example.com",
      "type": "m.room.member",
      "sender": "@bob:example.com"
    }
  ]
}

Status code 403:

You aren't a member of the room and weren't previously a member of the room.

6.3.5   GET /_matrix/client/r0/rooms/{roomId}/joined_members

This API returns a map of MXIDs to member info objects for members of the room. The current user must be in the room for it to work, unless it is an Application Service in which case any of the AS's users must be in the room. This API is primarily for Application Services and should be faster to respond than /members as it can be implemented more efficiently on the server.

Requires auth:Yes.

Request format:

Parameter Type Description
path parameters
roomId string Required. The room to get the members of.

Response format:

Parameter Type Description
joined {string: RoomMember} A map from user ID to a RoomMember object.

RoomMember

Parameter Type Description
display_name string The display name of the user this object is representing.
avatar_url string The mxc avatar url of the user this object is representing.

Example request:

GET /_matrix/client/r0/rooms/%21636q39766251%3Aexample.com/joined_members HTTP/1.1

Responses:

Status code 200:

A map of MXID to room member objects.

Example

{
  "joined": {
    "@bar:example.com": {
      "display_name": "Bar",
      "avatar_url": "mxc://riot.ovh/printErCATzZijQsSDWorRaK"
    }
  }
}

Status code 403:

You aren't a member of the room.

6.3.6   GET /_matrix/client/r0/rooms/{roomId}/messages

This API returns a list of message and state events for a room. It uses pagination query parameters to paginate history in the room.

Requires auth:Yes.

Request format:

Parameter Type Description
path parameters
roomId string Required. The room to get events from.
query parameters
from string Required. The token to start returning events from. This token can be obtained from a prev_batch token returned for each room by the sync API, or from a start or end token returned by a previous request to this endpoint.
to string The token to stop returning events at. This token can be obtained from a prev_batch token returned for each room by the sync endpoint, or from a start or end token returned by a previous request to this endpoint.
dir enum Required. The direction to return events from. One of: ["b", "f"]
limit integer The maximum number of events to return. Default: 10.
filter string A JSON RoomEventFilter to filter returned events with.

Response format:

Parameter Type Description
start string The token the pagination starts from. If dir=b this will be the token supplied in from.
end string The token the pagination ends at. If dir=b this token should be used again to request even earlier events.
chunk [RoomEvent] A list of room events.

Example request:

GET /_matrix/client/r0/rooms/%21636q39766251%3Aexample.com/messages?from=s345_678_333&dir=b&limit=3&filter=%7B%22contains_url%22%3Atrue%7D HTTP/1.1

Responses:

Status code 200:

A list of messages with a new token to request more.

Example

{
  "start": "t47429-4392820_219380_26003_2265",
  "end": "t47409-4357353_219380_26003_2265",
  "chunk": [
    {
      "origin_server_ts": 1444812213737,
      "sender": "@alice:example.com",
      "event_id": "$1444812213350496Caaaa:example.com",
      "content": {
        "body": "hello world",
        "msgtype": "m.text"
      },
      "room_id": "!Xq3620DUiqCaoxq:example.com",
      "type": "m.room.message",
      "age": 1042
    },
    {
      "origin_server_ts": 1444812194656,
      "sender": "@bob:example.com",
      "event_id": "$1444812213350496Cbbbb:example.com",
      "content": {
        "body": "the world is big",
        "msgtype": "m.text"
      },
      "room_id": "!Xq3620DUiqCaoxq:example.com",
      "type": "m.room.message",
      "age": 20123
    },
    {
      "origin_server_ts": 1444812163990,
      "sender": "@bob:example.com",
      "event_id": "$1444812213350496Ccccc:example.com",
      "content": {
        "name": "New room name"
      },
      "prev_content": {
        "name": "Old room name"
      },
      "state_key": "",
      "room_id": "!Xq3620DUiqCaoxq:example.com",
      "type": "m.room.name",
      "age": 50789
    }
  ]
}

Status code 403:

You aren't a member of the room.

6.3.7   GET /_matrix/client/r0/rooms/{roomId}/initialSync

Warning

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

Get a copy of the current state and the most recent messages in a room.

This endpoint was deprecated in r0 of this specification. There is no direct replacement; the relevant information is returned by the /sync API. See the migration guide.

Requires auth:Yes.

Request format:

Parameter Type Description
path parameters
roomId string Required. The room to get the data.

Response format:

RoomInfo

Parameter Type Description
room_id string Required. The ID of this room.
membership enum The user's membership state in this room. One of: ["invite", "join", "leave", "ban"]
messages PaginationChunk The pagination chunk for this room.
state [StateEvent] If the user is a member of the room this will be the current state of the room as a list of events. If the user has left the room this will be the state of the room when they left it.
visibility enum Whether this room is visible to the /publicRooms API or not." One of: ["private", "public"]
account_data [Event] The private data that this user has attached to this room.

PaginationChunk

Parameter Type Description
start string Required. A token which correlates to the first value in chunk. Used for pagination.
end string Required. A token which correlates to the last value in chunk. Used for pagination.
chunk [RoomEvent] Required. If the user is a member of the room this will be a list of the most recent messages for this room. If the user has left the room this will be the messages that preceeded them leaving. This array will consist of at most limit elements.

RoomEvent

Parameter Type Description
content object The fields in this object will vary depending on the type of event. When interacting with the REST API, this is the HTTP body.
type string Required. The type of event. This SHOULD be namespaced similar to Java package naming conventions e.g. 'com.example.subdomain.event.type'
event_id string Required. The globally unique event identifier.
room_id string Required. The ID of the room associated with this event.
sender string Required. Contains the fully-qualified ID of the user who sent this event.
origin_server_ts number Required. Timestamp in milliseconds on originating homeserver when this event was sent.
unsigned UnsignedData Contains optional extra information about the event.

StateEvent

Parameter Type Description
content object The fields in this object will vary depending on the type of event. When interacting with the REST API, this is the HTTP body.
type string Required. The type of event. This SHOULD be namespaced similar to Java package naming conventions e.g. 'com.example.subdomain.event.type'
event_id string Required. The globally unique event identifier.
room_id string Required. The ID of the room associated with this event.
sender string Required. Contains the fully-qualified ID of the user who sent this event.
origin_server_ts number Required. Timestamp in milliseconds on originating homeserver when this event was sent.
unsigned UnsignedData Contains optional extra information about the event.
prev_content EventContent Optional. The previous content for this event. If there is no previous content, this key will be missing.
state_key string Required. A unique key which defines the overwriting semantics for this piece of room state. This value is often a zero-length string. The presence of this key makes this event a State Event. The key MUST NOT start with '_'.

UnsignedData

Parameter Type Description
age integer The time in milliseconds that has elapsed since the event was sent. This field is generated by the local homeserver, and may be incorrect if the local time on at least one of the two servers is out of sync, which can cause the age to either be negative or greater than it actually is.
redacted_because Event Optional. The event that redacted this event, if any.
transaction_id string The client-supplied transaction ID, if the client being given the event is the same one which sent it.

Event

Parameter Type Description
content object The fields in this object will vary depending on the type of event. When interacting with the REST API, this is the HTTP body.
type string Required. The type of event. This SHOULD be namespaced similar to Java package naming conventions e.g. 'com.example.subdomain.event.type'

Example request:

GET /_matrix/client/r0/rooms/%21636q39766251%3Aexample.com/initialSync HTTP/1.1

Responses:

Status code 200:

The current state of the room

Example

{
  "membership": "join",
  "messages": {
    "chunk": [
      {
        "age": 343513403,
        "content": {
          "body": "foo",
          "msgtype": "m.text"
        },
        "event_id": "$14328044851tzTJS:example.com",
        "origin_server_ts": 1432804485886,
        "room_id": "!636q39766251:example.com",
        "type": "m.room.message",
        "sender": "@alice:example.com"
      },
      {
        "age": 343511809,
        "content": {
          "body": "bar",
          "msgtype": "m.text"
        },
        "event_id": "$14328044872spjFg:example.com",
        "origin_server_ts": 1432804487480,
        "room_id": "!636q39766251:example.com",
        "type": "m.room.message",
        "sender": "@bob:example.com"
      }
    ],
    "end": "s3456_9_0",
    "start": "t44-3453_9_0"
  },
  "room_id": "!636q39766251:example.com",
  "state": [
    {
      "age": 7148266897,
      "content": {
        "join_rule": "public"
      },
      "event_id": "$14259997323TLwtb:example.com",
      "origin_server_ts": 1425999732392,
      "room_id": "!636q39766251:example.com",
      "state_key": "",
      "type": "m.room.join_rules",
      "sender": "@alice:example.com"
    },
    {
      "age": 6547561012,
      "content": {
        "avatar_url": "mxc://example.com/fzysBrHpPEeTGANCVLXWXNMI#auto",
        "membership": "join"
      },
      "event_id": "$1426600438280zExKY:example.com",
      "membership": "join",
      "origin_server_ts": 1426600438277,
      "room_id": "!636q39766251:example.com",
      "state_key": "@alice:example.com",
      "type": "m.room.member",
      "sender": "@alice:example.com"
    },
    {
      "age": 7148267200,
      "content": {
        "creator": "@alice:example.com"
      },
      "event_id": "$14259997320KhbwJ:example.com",
      "origin_server_ts": 1425999732089,
      "room_id": "!636q39766251:example.com",
      "state_key": "",
      "type": "m.room.create",
      "sender": "@alice:example.com"
    },
    {
      "age": 1622568720,
      "content": {
        "avatar_url": "mxc://example.com/GCmhgzMPRjqgpODLsNQzVuHZ#auto",
        "displayname": "Bob",
        "membership": "join"
      },
      "event_id": "$1431525430134MxlLX:example.com",
      "origin_server_ts": 1431525430569,
      "replaces_state": "$142652023736BSXcM:example.com",
      "room_id": "!636q39766251:example.com",
      "state_key": "@bob:example.com",
      "type": "m.room.member",
      "sender": "@bob:example.com"
    },
    {
      "age": 7148267004,
      "content": {
        "ban": 50,
        "events": {
          "m.room.name": 100,
          "m.room.power_levels": 100
        },
        "events_default": 0,
        "kick": 50,
        "redact": 50,
        "state_default": 50,
        "users": {
          "@alice:example.com": 100
        },
        "users_default": 0
      },
      "event_id": "$14259997322mqfaq:example.com",
      "origin_server_ts": 1425999732285,
      "room_id": "!636q39766251:example.com",
      "state_key": "",
      "type": "m.room.power_levels",
      "sender": "@alice:example.com"
    }
  ],
  "visibility": "private",
  "account_data": [
    {
      "type": "m.tag",
      "content": {
        "tags": {
          "work": {
            "order": "1"
          }
        }
      }
    }
  ]
}

Status code 403:

You aren't a member of the room and weren't previously a member of the room.

6.4   Sending events to a room

6.4.1   PUT /_matrix/client/r0/rooms/{roomId}/state/{eventType}/{stateKey}

State events can be sent using this endpoint. These events will be overwritten if <room id>, <event type> and <state key> all match.

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.

Requires auth:Yes.

Request format:

Parameter Type Description
path parameters
roomId string Required. The room to set the state in
eventType string Required. The type of event to send.
stateKey string Required. The state_key for the state to send. Defaults to the empty string.

Response format:

Parameter Type Description
event_id string A unique identifier for the event.

Example request:

PUT /_matrix/client/r0/rooms/%21636q39766251%3Aexample.com/state/m.room.member/%40alice%3Aexample.com HTTP/1.1
Content-Type: application/json

{
  "membership": "join",
  "avatar_url": "mxc://localhost/SEsfnsuifSDFSSEF#auto",
  "displayname": "Alice Margatroid"
}

Response:

Status code 200:

An ID for the sent event.

Example

{
  "event_id": "YUwRidLecu"
}

6.4.2   PUT /_matrix/client/r0/rooms/{roomId}/state/{eventType}

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.

Requires auth:Yes.

Request format:

Parameter Type Description
path parameters
roomId string Required. The room to set the state in
eventType string Required. The type of event to send.

Response format:

Parameter Type Description
event_id string A unique identifier for the event.

Example request:

PUT /_matrix/client/r0/rooms/%21636q39766251%3Aexample.com/state/m.room.name HTTP/1.1
Content-Type: application/json

{
  "name": "New name for the room"
}

Response:

Status code 200:

An ID for the sent event.

Example

{
  "event_id": "YUwRidLecu"
}

Examples

Valid requests look like:

PUT /rooms/!roomid:domain/state/m.example.event
{ "key" : "without a state key" }

PUT /rooms/!roomid:domain/state/m.another.example.event/foo
{ "key" : "with 'foo' as the state key" }

In contrast, these requests are invalid:

POST /rooms/!roomid:domain/state/m.example.event/
{ "key" : "cannot use POST here" }

PUT /rooms/!roomid:domain/state/m.another.example.event/foo/11
{ "key" : "txnIds are not supported" }

Care should be taken to avoid setting the wrong state key:

PUT /rooms/!roomid:domain/state/m.another.example.event/11
{ "key" : "with '11' as the state key, but was probably intended to be a txnId" }

The state_key is often used to store state about individual users, by using the user ID as the state_key value. For example:

PUT /rooms/!roomid:domain/state/m.favorite.animal.event/%40my_user%3Adomain.com
{ "animal" : "cat", "reason": "fluffy" }

In some cases, there may be no need for a state_key, so it can be omitted:

PUT /rooms/!roomid:domain/state/m.room.bgd.color
{ "color": "red", "hex": "#ff0000" }

6.4.3   PUT /_matrix/client/r0/rooms/{roomId}/send/{eventType}/{txnId}

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.

Requires auth:Yes.

Request format:

Parameter Type Description
path parameters
roomId string Required. The room to send the event to.
eventType string Required. The type of event to send.
txnId string Required. The transaction ID for this event. Clients should generate an ID unique across requests with the same access token; it will be used by the server to ensure idempotency of requests.

Response format:

Parameter Type Description
event_id string A unique identifier for the event.

Example request:

PUT /_matrix/client/r0/rooms/%21636q39766251%3Aexample.com/send/m.room.message/35 HTTP/1.1
Content-Type: application/json

{
  "msgtype": "m.text",
  "body": "hello"
}

Response:

Status code 200:

An ID for the sent event.

Example

{
  "event_id": "YUwRidLecu"
}

6.5   Redactions

Since events are extensible it is possible for malicious users and/or servers to add keys that are, for example offensive or illegal. Since some events cannot be simply deleted, e.g. membership events, we instead 'redact' events. This involves removing all keys from an event that are not required by the protocol. This stripped down event is thereafter returned anytime a client or remote server requests it. Redacting an event cannot be undone, allowing server owners to delete the offending content from the databases. Events that have been redacted include a redacted_because key whose value is the event that caused it to be redacted, which may include a reason.

Upon receipt of a redaction event, the server should strip off any keys not in the following list:

  • event_id
  • type
  • room_id
  • sender
  • state_key
  • prev_content
  • content

The content object should also be stripped of all keys, unless it is one of one of the following event types:

  • m.room.member allows key membership
  • m.room.create allows key creator
  • m.room.join_rules allows key join_rule
  • m.room.power_levels allows keys ban, events, events_default, kick, redact, state_default, users, users_default.
  • m.room.aliases allows key aliases

The server should add the event causing the redaction to the unsigned property of the redacted event, under the redacted_because key. When a client receives a redaction event it should change the redacted event in the same way a server does.

6.5.1   Events

6.5.1.1   m.room.redaction

Message Event

Events can be redacted by either room or server admins. Redacting an event means that all keys not required by the protocol are stripped off, allowing admins to remove offensive or illegal content that may have been attached to any event. This cannot be undone, allowing server owners to physically delete the offending data. There is also a concept of a moderator hiding a message event, which can be undone, but cannot be applied to state events. The event that has been redacted is specified in the redacts event level key.

Content Key Type Description
reason string The reason for the redaction, if any.

Example:

{
    "content": {
        "reason": "Spamming"
    },
    "event_id": "$WLGTSEFSEF:localhost",
    "origin_server_ts": 1431961217939,
    "redacts": "$fukweghifu23:localhost",
    "room_id": "!Cuyf34gef24t:localhost",
    "sender": "@example:localhost",
    "type": "m.room.redaction",
    "unsigned": {
        "age": 242352
    }
}

6.5.2   Client behaviour

6.5.2.1   PUT /_matrix/client/r0/rooms/{roomId}/redact/{eventId}/{txnId}

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.

Requires auth:Yes.

Request format:

Parameter Type Description
path parameters
roomId string Required. The room from which to redact the event.
eventId string Required. The ID of the event to redact
txnId string Required. The transaction ID for this event. Clients should generate a unique ID; it will be used by the server to ensure idempotency of requests.
JSON body parameters
reason string The reason for the event being redacted.

Response format:

Parameter Type Description
event_id string A unique identifier for the event.

Example request:

PUT /_matrix/client/r0/rooms/%21637q39766251%3Aexample.com/redact/bai2b1i9%3Amatrix.org/37 HTTP/1.1
Content-Type: application/json

{
  "reason": "Indecent material"
}

Response:

Status code 200:

An ID for the redaction event.

Example

{
  "event_id": "YUwQidLecu"
}

7   Rooms

7.1   Creation

The homeserver will create an m.room.create event when a room is created, which serves as the root of the event graph for this room. This event also has a creator key which contains the user ID of the room creator. It will also generate several other events in order to manage permissions in this room. This includes:

  • m.room.power_levels : Sets the power levels of users and required power
    levels for various actions within the room such as sending events.
  • m.room.join_rules : Whether the room is "invite-only" or not.

See Room Events for more information on these events. To create a room, a client has to use the following API.

7.1.1   POST /_matrix/client/r0/createRoom

Create a new room with various configuration options.

The server MUST apply the normal state resolution rules when creating the new room, including checking power levels for each event. It MUST apply the events implied by the request in the following order:

  1. A default m.room.power_levels event, giving the room creator (and not other members) permission to send state events.
  2. Events set by presets.
  3. Events listed in initial_state, in the order that they are listed.
  4. Events implied by name and topic.
  5. Invite events implied by invite and invite_3pid.
Requires auth:Yes.

Request format:

Parameter Type Description
JSON body parameters
visibility enum A public visibility indicates that the room will be shown in the published room list. A private visibility will hide the room from the published room list. Rooms default to private visibility if this key is not included. NB: This should not be confused with join_rules which also uses the word public. One of: ["public", "private"]
room_alias_name string The desired room alias local part. If this is included, a room alias will be created and mapped to the newly created room. The alias will belong on the same homeserver which created the room. For example, if this was set to "foo" and sent to the homeserver "example.com" the complete room alias would be #foo:example.com.
name string If this is included, an m.room.name event will be sent into the room to indicate the name of the room. See Room Events for more information on m.room.name.
topic string If this is included, an m.room.topic event will be sent into the room to indicate the topic for the room. See Room Events for more information on m.room.topic.
invite [string] A list of user IDs to invite to the room. This will tell the server to invite everyone in the list to the newly created room.
invite_3pid [Invite3pid] A list of objects representing third party IDs to invite into the room.
creation_content CreationContent Extra keys to be added to the content of the m.room.create. The server will clobber the following keys: creator. Future versions of the specification may allow the server to clobber other keys.
initial_state [StateEvent]

A list of state events to set in the new room. This allows the user to override the default state events set in the new room. The expected format of the state events are an object with type, state_key and content keys set.

Takes precedence over events set by presets, but gets overriden by name and topic keys.

preset enum

Convenience parameter for setting various default state events based on a preset. Must be either:

private_chat => join_rules is set to invite. history_visibility is set to shared.

trusted_private_chat => join_rules is set to invite. history_visibility is set to shared. All invitees are given the same power level as the room creator.

public_chat: => join_rules is set to public. history_visibility is set to shared. One of: ["private_chat", "public_chat", "trusted_private_chat"]

is_direct boolean This flag makes the server set the is_direct flag on the m.room.member events sent to the users in invite and invite_3pid. See Direct Messaging for more information.

Invite3pid

Parameter Type Description
id_server string Required. The hostname+port of the identity server which should be used for third party identifier lookups.
medium string Required. The kind of address being passed in the address field, for example email.
address string Required. The invitee's third party identifier.

StateEvent

Parameter Type Description
type string  
state_key string  
content string  

Response format:

Parameter Type Description
room_id string The created room's ID.

Example request:

POST /_matrix/client/r0/createRoom HTTP/1.1
Content-Type: application/json

{
  "preset": "public_chat",
  "room_alias_name": "thepub",
  "name": "The Grand Duke Pub",
  "topic": "All about happy hour",
  "creation_content": {
    "m.federate": false
  }
}

Responses:

Status code 200:

Information about the newly created room.

Example

{
  "room_id": "!sefiuhWgwghwWgh:example.com"
}

Status code 400:

The request is invalid. A meaningful errcode and description error text will be returned. Example reasons for rejection include:

  • The request body is malformed (errcode set to M_BAD_JSON or M_NOT_JSON).
  • The room alias specified is already taken (errcode set to M_ROOM_IN_USE).
  • The initial state implied by the parameters to the request is invalid: for example, the user's power_level is set below that necessary to set the room name (errcode set to M_INVALID_ROOM_STATE).

7.2   Room aliases

Servers may host aliases for rooms with human-friendly names. Aliases take the form #friendlyname:server.name.

As room aliases are scoped to a particular homeserver domain name, it is likely that a homeserver will reject attempts to maintain aliases on other domain names. This specification does not provide a way for homeservers to send update requests to other servers. However, homeservers MUST handle GET requests to resolve aliases on other servers; they should do this using the federation API if necessary.

Rooms store a partial list of room aliases via the m.room.aliases state event. This alias list is partial because it cannot guarantee that the alias list is in any way accurate or up-to-date, as room aliases can point to different room IDs over time. Crucially, the aliases in this event are purely informational and SHOULD NOT be treated as accurate. They SHOULD be checked before they are used or shared with another user. If a room appears to have a room alias of #alias:example.com, this SHOULD be checked to make sure that the room's ID matches the room_id returned from the request.

7.2.1   PUT /_matrix/client/r0/directory/room/{roomAlias}

Create a new mapping from room alias to room ID.

Requires auth:Yes.

Request format:

Parameter Type Description
path parameters
roomAlias string Required. The room alias to set.
JSON body parameters
room_id string The room ID to set.

Example request:

PUT /_matrix/client/r0/directory/room/%23monkeys%3Amatrix.org HTTP/1.1
Content-Type: application/json

{
  "room_id": "!abnjk1jdasj98:capuchins.com"
}

Responses:

Status code 200:

The mapping was created.

Example

{}

Status code 409:

A room alias with that name already exists.

Example

{
  "errcode": "M_UNKNOWN",
  "error": "Room alias #monkeys:matrix.org already exists."
}

7.2.2   GET /_matrix/client/r0/directory/room/{roomAlias}

Requests that the server resolve a room alias to a room ID.

The server will use the federation API to resolve the alias if the domain part of the alias does not correspond to the server's own domain.

Request format:

Parameter Type Description
path parameters
roomAlias string Required. The room alias.

Response format:

Parameter Type Description
room_id string The room ID for this room alias.
servers [string] A list of servers that are aware of this room alias.

Example request:

GET /_matrix/client/r0/directory/room/%23monkeys%3Amatrix.org HTTP/1.1

Responses:

Status code 200:

The room ID and other information for this alias.

Example

{
  "room_id": "!abnjk1jdasj98:capuchins.com",
  "servers": [
    "capuchins.com",
    "matrix.org",
    "another.com"
  ]
}

Status code 404:

There is no mapped room ID for this room alias.

Example

{
  "errcode": "M_NOT_FOUND",
  "error": "Room alias #monkeys:matrix.org not found."
}

7.2.3   DELETE /_matrix/client/r0/directory/room/{roomAlias}

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.

Requires auth:Yes.

Request format:

Parameter Type Description
path parameters
roomAlias string Required. The room alias to remove.

Example request:

DELETE /_matrix/client/r0/directory/room/%23monkeys%3Amatrix.org HTTP/1.1

Response:

Status code 200:

The mapping was deleted.

Example

{}

7.3   Permissions

Note

This section is a work in progress.

Permissions for rooms are done via the concept of power levels - to do any action in a room a user must have a suitable power level. Power levels are stored as state events in a given room. The power levels required for operations and the power levels for users are defined in m.room.power_levels, where both a default and specific users' power levels can be set. By default all users have a power level of 0, other than the room creator whose power level defaults to 100. Users can grant other users increased power levels up to their own power level. For example, user A with a power level of 50 could increase the power level of user B to a maximum of level 50. Power levels for users are tracked per-room even if the user is not present in the room. The keys contained in m.room.power_levels determine the levels required for certain operations such as kicking, banning and sending state events. See m.room.power_levels for more information.

Clients may wish to assign names to particular power levels. A suggested mapping is as follows: - 0 User - 50 Moderator - 100 Admin

7.4   Room membership

Users need to be a member of a room in order to send and receive events in that room. There are several states in which a user may be, in relation to a room:

  • Unrelated (the user cannot send or receive events in the room)
  • Invited (the user has been invited to participate in the room, but is not yet participating)
  • Joined (the user can send and receive events in the room)
  • Banned (the user is not allowed to join the room)

There is an exception to the requirement that a user join a room before sending events to it: users may send an m.room.member event to a room with content.membership set to leave to reject an invitation if they have currently been invited to a room but have not joined it.

Some rooms require that users be invited to it before they can join; others allow anyone to join. Whether a given room is an "invite-only" room is determined by the room config key m.room.join_rules. It can have one of the following values:

public
This room is free for anyone to join without an invite.
invite
This room can only be joined if you were invited.

The allowable state transitions of membership are:

                                     /ban
                +------------------------------------------------------+
                |                                                      |
                |  +----------------+  +----------------+              |
                |  |    /leave      |  |                |              |
                |  |                v  v                |              |
  /invite    +--------+           +-------+             |              |
------------>| invite |<----------| leave |----+        |              |
             +--------+  /invite  +-------+    |        |              |
               |                   |    ^      |        |              |
               |                   |    |      |        |              |
         /join |   +---------------+    |      |        |              |
               |   | /join if           |      |        |              |
               |   | join_rules         |      | /ban   | /unban       |
               |   | public      /leave |      |        |              |
               v   v               or   |      |        |              |
             +------+            /kick  |      |        |              |
------------>| join |-------------------+      |        |              |
 /join       +------+                          v        |              |
 if             |                           +-----+     |              |
 join_rules     +-------------------------->| ban |-----+              |
 public                   /ban              +-----+                    |
                                              ^ ^                      |
                                              | |                      |
----------------------------------------------+ +----------------------+
                /ban

7.4.1   GET /_matrix/client/r0/joined_rooms

This API returns a list of the user's current rooms.

Requires auth:Yes.

Request format:

No parameters

Response format:

Parameter Type Description
joined_rooms [string] Required. The ID of each room in which the user has joined membership.

Example request:

GET /_matrix/client/r0/joined_rooms HTTP/1.1

Response:

Status code 200:

A list of the rooms the user is in.

Example

{
  "joined_rooms": [
    "!foo:example.com"
  ]
}

7.4.2   Joining rooms

7.4.2.1   POST /_matrix/client/r0/rooms/{roomId}/invite

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.

Rate-limited:Yes.
Requires auth:Yes.

Request format:

Parameter Type Description
path parameters
roomId string Required. The room identifier (not alias) to which to invite the user.
JSON body parameters
user_id string Required. The fully qualified user ID of the invitee.

Example request:

POST /_matrix/client/r0/rooms/%21d41d8cd%3Amatrix.org/invite  HTTP/1.1
Content-Type: application/json

{
  "user_id": "@cheeky_monkey:matrix.org"
}

Responses:

Status code 200:

The user has been invited to join the room.

Example

{}

Status code 403:

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.

Example

{
  "errcode": "M_FORBIDDEN",
  "error": "@cheeky_monkey:matrix.org is banned from the room"
}

Status code 429:

This request was rate-limited.

Example

{
  "errcode": "string",
  "error": "string"
}

7.4.2.2   POST /_matrix/client/r0/rooms/{roomId}/join

Note that this API requires a room ID, not alias. /join/{roomIdOrAlias} exists if you have a room alias.

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 and /sync APIs.

If a third_party_signed was supplied, the homeserver must verify that it matches a pending m.room.third_party_invite event in the room, and perform key validity checking if required by the event.

Rate-limited:Yes.
Requires auth:Yes.

Request format:

Parameter Type Description
path parameters
roomId string Required. The room identifier (not alias) to join.
JSON body parameters
third_party_signed ThirdPartySigned A signature of an m.third_party_invite token to prove that this user owns a third party identity which has been invited to the room.

ThirdPartySigned

Parameter Type Description
sender string Required. The Matrix ID of the user who issued the invite.
mxid string Required. The Matrix ID of the invitee.
token string Required. The state key of the m.third_party_invite event.
signatures Signatures Required. A signatures object containing a signature of the entire signed object.

Example request:

POST /_matrix/client/r0/rooms/%21d41d8cd%3Amatrix.org/join HTTP/1.1
Content-Type: application/json

{
  "third_party_signed": {
    "sender": "@cat:the.hat",
    "mxid": "@green:eggs.ham",
    "token": "random8nonce",
    "signatures": {
      "horton.hears": {
        "ed25519:0": "some9signature"
      }
    }
  }
}

Responses:

Status code 200:

The room has been joined.

The joined room ID must be returned in the room_id field.

Example

{
  "room_id": "!d41d8cd:matrix.org"
}

Status code 403:

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.

Example

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

Status code 429:

This request was rate-limited.

Example

{
  "errcode": "string",
  "error": "string"
}

7.4.2.3   POST /_matrix/client/r0/join/{roomIdOrAlias}

Note that this API takes either a room ID or alias, unlike /room/{roomId}/join.

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 and /sync APIs.

If a third_party_signed was supplied, the homeserver must verify that it matches a pending m.room.third_party_invite event in the room, and perform key validity checking if required by the event.

Rate-limited:Yes.
Requires auth:Yes.

Request format:

Parameter Type Description
path parameters
roomIdOrAlias string Required. The room identifier or alias to join.
JSON body parameters
third_party_signed ThirdPartySigned A signature of an m.third_party_invite token to prove that this user owns a third party identity which has been invited to the room.

ThirdPartySigned

Parameter Type Description
signed Signed Required.

Signed

Parameter Type Description
sender string Required. The Matrix ID of the user who issued the invite.
mxid string Required. The Matrix ID of the invitee.
token string Required. The state key of the m.third_party_invite event.
signatures Signatures Required. A signatures object containing a signature of the entire signed object.

Example request:

POST /_matrix/client/r0/join/%23monkeys%3Amatrix.org HTTP/1.1
Content-Type: application/json

{
  "third_party_signed": {
    "signed": {
      "sender": "@cat:the.hat",
      "mxid": "@green:eggs.ham",
      "token": "random8nonce",
      "signatures": {
        "horton.hears": {
          "ed25519:0": "some9signature"
        }
      }
    }
  }
}

Responses:

Status code 200:

The room has been joined.

The joined room ID must be returned in the room_id field.

Example

{
  "room_id": "!d41d8cd:matrix.org"
}

Status code 403:

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.

Example

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

Status code 429:

This request was rate-limited.

Example

{
  "errcode": "string",
  "error": "string"
}

7.4.3   Leaving rooms

A user can leave a room to stop receiving events for that room. A user must have been invited to or have joined the room before they are eligible to leave the room. Leaving a room to which the user has been invited rejects the invite. Once a user leaves a room, it will no longer appear in the response to the /sync API unless it is explicitly requested via a filter with the include_leave field set to true.

Whether or not they actually joined the room, if the room is an "invite-only" room the user will need to be re-invited before they can re-join the room.

A user can also forget a room which they have left. Rooms which have been forgotten will never appear the response to the /sync API, until the user re-joins or is re-invited.

A user may wish to force another user to leave a room. This can be done by 'kicking' the other user. To do so, the user performing the kick MUST have the required power level. Once a user has been kicked, the behaviour is the same as if they had left of their own accord. In particular, the user is free to re-join if the room is not "invite-only".

7.4.3.1   POST /_matrix/client/r0/rooms/{roomId}/leave

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.

Rate-limited:Yes.
Requires auth:Yes.

Request format:

Parameter Type Description
path parameters
roomId string Required. The room identifier to leave.

Example request:

POST /_matrix/client/r0/rooms/%21nkl290a%3Amatrix.org/leave HTTP/1.1

Responses:

Status code 200:

The room has been left.

Example

{}

Status code 429:

This request was rate-limited.

Example

{
  "errcode": "string",
  "error": "string"
}

7.4.3.2   POST /_matrix/client/r0/rooms/{roomId}/forget

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.

Rate-limited:Yes.
Requires auth:Yes.

Request format:

Parameter Type Description
path parameters
roomId string Required. The room identifier to forget.

Example request:

POST /_matrix/client/r0/rooms/%21au1ba7o%3Amatrix.org/forget HTTP/1.1

Responses:

Status code 200:

The room has been forgotten.

Example

{}

Status code 429:

This request was rate-limited.

Example

{
  "errcode": "string",
  "error": "string"
}

7.4.3.3   POST /_matrix/client/r0/rooms/{roomId}/kick

Kick a user from the room.

The caller must have the required power level in order to perform this operation.

Requires auth:Yes.

Request format:

Parameter Type Description
path parameters
roomId string Required. The room identifier (not alias) from which the user should be kicked.
JSON body parameters
user_id string Required. The fully qualified user ID of the user being kicked.
reason string The reason the user has been kicked.

Example request:

POST /_matrix/client/r0/rooms/%21e42d8c%3Amatrix.org/kick HTTP/1.1
Content-Type: application/json

{
  "reason": "Telling unfunny jokes",
  "user_id": "@cheeky_monkey:matrix.org"
}

Responses:

Status code 200:

The user has been kicked from the room.

Example

{}

Status code 403:

You do not have permission to kick the user from the room. A meaningful errcode and description error text will be returned. Example reasons for rejections are:

  • The kicker is not currently in the room.
  • The kickee is not currently in the room.
  • The kicker's power level is insufficient to kick users from the room.

Example

{
  "errcode": "M_FORBIDDEN",
  "error": "You do not have a high enough power level to kick from this room."
}

7.4.4   Banning users in a room

A user may decide to ban another user in a room. 'Banning' forces the target user to leave the room and prevents them from re-joining the room. A banned user will not be treated as a joined user, and so will not be able to send or receive events in the room. In order to ban someone, the user performing the ban MUST have the required power level. To ban a user, a request should be made to /rooms/<room_id>/ban with:

{
  "user_id": "<user id to ban>"
  "reason": "string: <reason for the ban>"
}

Banning a user adjusts the banned member's membership state to ban. Like with other membership changes, a user can directly adjust the target member's state, by making a request to /rooms/<room id>/state/m.room.member/<user id>:

{
  "membership": "ban"
}

A user must be explicitly unbanned with a request to /rooms/<room_id>/unban before they can re-join the room or be re-invited.

7.4.4.1   POST /_matrix/client/r0/rooms/{roomId}/ban

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 or be invited to it until they are unbanned.

The caller must have the required power level in order to perform this operation.

Requires auth:Yes.

Request format:

Parameter Type Description
path parameters
roomId string Required. The room identifier (not alias) from which the user should be banned.
JSON body parameters
user_id string Required. The fully qualified user ID of the user being banned.
reason string The reason the user has been banned.

Example request:

POST /_matrix/client/r0/rooms/%21e42d8c%3Amatrix.org/ban HTTP/1.1
Content-Type: application/json

{
  "reason": "Telling unfunny jokes",
  "user_id": "@cheeky_monkey:matrix.org"
}

Responses:

Status code 200:

The user has been kicked and banned from the room.

Example

{}

Status code 403:

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.

Example

{
  "errcode": "M_FORBIDDEN",
  "error": "You do not have a high enough power level to ban from this room."
}

7.4.4.2   POST /_matrix/client/r0/rooms/{roomId}/unban

Unban a user from the room. This allows them to be invited to the room, and join if they would otherwise be allowed to join according to its join rules.

The caller must have the required power level in order to perform this operation.

Requires auth:Yes.

Request format:

Parameter Type Description
path parameters
roomId string Required. The room identifier (not alias) from which the user should be unbanned.
JSON body parameters
user_id string Required. The fully qualified user ID of the user being unbanned.

Example request:

POST /_matrix/client/r0/rooms/%21e42d8c%3Amatrix.org/unban HTTP/1.1
Content-Type: application/json

{
  "user_id": "@cheeky_monkey:matrix.org"
}

Responses:

Status code 200:

The user has been unbanned from the room.

Example

{}

Status code 403:

You do not have permission to unban the user from the room. A meaningful errcode and description error text will be returned. Example reasons for rejections are:

  • The unbanner's power level is insufficient to unban users from the room.

Example

{
  "errcode": "M_FORBIDDEN",
  "error": "You do not have a high enough power level to unban from this room."
}

7.5   Listing rooms

7.5.1   GET /_matrix/client/r0/publicRooms

Lists the public rooms on the server.

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

Request format:

Parameter Type Description
query parameters
limit number Limit the number of results returned.
since string A pagination token from a previous request, allowing clients to get the next (or previous) batch of rooms. The direction of pagination is specified solely by which token is supplied, rather than via an explicit flag.
server string The server to fetch the public room lists from. Defaults to the local server.

Response format:

Parameter Type Description
chunk [PublicRoomsChunk] Required. A paginated chunk of public rooms.
next_batch string A pagination token for the response. The absence of this token means there are no more results to fetch and the client should stop paginating.
prev_batch string A pagination token that allows fetching previous results. The absence of this token means there are no results before this batch, i.e. this is the first batch.
total_room_count_estimate number An estimate on the total number of public rooms, if the server has an estimate.

PublicRoomsChunk

Parameter Type Description
aliases [string] Aliases of the room. May be empty.
canonical_alias string The canonical alias of the room, if any.
name string The name of the room, if any.
num_joined_members number Required. The number of members joined to the room.
room_id string Required. The ID of the room.
topic string The topic of the room, if any.
world_readable boolean Required. Whether the room may be viewed by guest users without joining.
guest_can_join boolean Required. Whether guest users may join the room and participate in it. If they can, they will be subject to ordinary power level rules like any other user.
avatar_url string The URL for the room's avatar, if one is set.

Example request:

GET /_matrix/client/r0/publicRooms HTTP/1.1

Response:

Status code 200:

A list of the rooms on the server.

Example

{
  "chunk": [
    {
      "aliases": [
        "#murrays:cheese.bar"
      ],
      "avatar_url": "mxc://bleeker.street/CHEDDARandBRIE",
      "guest_can_join": false,
      "name": "CHEESE",
      "num_joined_members": 37,
      "room_id": "!ol19s:bleecker.street",
      "topic": "Tasty tasty cheese",
      "world_readable": true
    }
  ],
  "next_batch": "p190q",
  "prev_batch": "p1902",
  "total_room_count_estimate": 115
}

7.5.2   POST /_matrix/client/r0/publicRooms

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

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

Requires auth:Yes.

Request format:

Parameter Type Description
query parameters
server string The server to fetch the public room lists from. Defaults to the local server.
JSON body parameters
limit number Limit the number of results returned.
since string A pagination token from a previous request, allowing clients to get the next (or previous) batch of rooms. The direction of pagination is specified solely by which token is supplied, rather than via an explicit flag.
filter Filter Filter to apply to the results.

Filter

Parameter Type Description
generic_search_term string A string to search for in the room metadata, e.g. name, topic, canonical alias etc. (Optional).

Response format:

Parameter Type Description
chunk [PublicRoomsChunk] Required. A paginated chunk of public rooms.
next_batch string A pagination token for the response. The absence of this token means there are no more results to fetch and the client should stop paginating.
prev_batch string A pagination token that allows fetching previous results. The absence of this token means there are no results before this batch, i.e. this is the first batch.
total_room_count_estimate number An estimate on the total number of public rooms, if the server has an estimate.

PublicRoomsChunk

Parameter Type Description
aliases [string] Aliases of the room. May be empty.
canonical_alias string The canonical alias of the room, if any.
name string The name of the room, if any.
num_joined_members number Required. The number of members joined to the room.
room_id string Required. The ID of the room.
topic string The topic of the room, if any.
world_readable boolean Required. Whether the room may be viewed by guest users without joining.
guest_can_join boolean Required. Whether guest users may join the room and participate in it. If they can, they will be subject to ordinary power level rules like any other user.
avatar_url string The URL for the room's avatar, if one is set.

Example request:

POST /_matrix/client/r0/publicRooms HTTP/1.1
Content-Type: application/json

{
  "limit": 10,
  "filter": {
    "generic_search_term": "foo"
  }
}

Response:

Status code 200:

A list of the rooms on the server.

Example

{
  "chunk": [
    {
      "aliases": [
        "#murrays:cheese.bar"
      ],
      "avatar_url": "mxc://bleeker.street/CHEDDARandBRIE",
      "guest_can_join": false,
      "name": "CHEESE",
      "num_joined_members": 37,
      "room_id": "!ol19s:bleecker.street",
      "topic": "Tasty tasty cheese",
      "world_readable": true
    }
  ],
  "next_batch": "p190q",
  "prev_batch": "p1902",
  "total_room_count_estimate": 115
}

8   Profiles

8.1   PUT /_matrix/client/r0/profile/{userId}/displayname

This API sets the given user's display name. You must have permission to set this user's display name, e.g. you need to have their access_token.

Rate-limited:Yes.
Requires auth:Yes.

Request format:

Parameter Type Description
path parameters
userId string Required. The user whose display name to set.
JSON body parameters
displayname string The new display name for this user.

Example request:

PUT /_matrix/client/r0/profile/%40alice%3Aexample.com/displayname HTTP/1.1
Content-Type: application/json

{
  "displayname": "Alice Margatroid"
}

Responses:

Status code 200:

The display name was set.

Example

{}

Status code 429:

This request was rate-limited.

Example

{
  "errcode": "string",
  "error": "string"
}

8.2   GET /_matrix/client/r0/profile/{userId}/displayname

Get the user's display name. This API may be used to fetch the user's own displayname or to query the name of other users; either locally or on remote homeservers.

Request format:

Parameter Type Description
path parameters
userId string Required. The user whose display name to get.

Response format:

Parameter Type Description
displayname string The user's display name if they have set one, otherwise not present.

Example request:

GET /_matrix/client/r0/profile/%40alice%3Aexample.com/displayname HTTP/1.1

Responses:

Status code 200:

The display name for this user.

Example

{
  "displayname": "Alice Margatroid"
}

Status code 404:

There is no display name for this user or this user does not exist.

8.3   PUT /_matrix/client/r0/profile/{userId}/avatar_url

This API sets the given user's avatar URL. You must have permission to set this user's avatar URL, e.g. you need to have their access_token.

Rate-limited:Yes.
Requires auth:Yes.

Request format:

Parameter Type Description
path parameters
userId string Required. The user whose avatar URL to set.
JSON body parameters
avatar_url string The new avatar URL for this user.

Example request:

PUT /_matrix/client/r0/profile/%40alice%3Aexample.com/avatar_url HTTP/1.1
Content-Type: application/json

{
  "avatar_url": "mxc://matrix.org/wefh34uihSDRGhw34"
}

Responses:

Status code 200:

The avatar URL was set.

Example

{}

Status code 429:

This request was rate-limited.

Example

{
  "errcode": "string",
  "error": "string"
}

8.4   GET /_matrix/client/r0/profile/{userId}/avatar_url

Get the user's avatar URL. This API may be used to fetch the user's own avatar URL or to query the URL of other users; either locally or on remote homeservers.

Request format:

Parameter Type Description
path parameters
userId string Required. The user whose avatar URL to get.

Response format:

Parameter Type Description
avatar_url string The user's avatar URL if they have set one, otherwise not present.

Example request:

GET /_matrix/client/r0/profile/%40alice%3Aexample.com/avatar_url HTTP/1.1

Responses:

Status code 200:

The avatar URL for this user.

Example

{
  "avatar_url": "mxc://matrix.org/SDGdghriugerRg"
}

Status code 404:

There is no avatar URL for this user or this user does not exist.

8.5   GET /_matrix/client/r0/profile/{userId}

Get the combined profile information for this user. This API may be used to fetch the user's own profile information or other users; either locally or on remote homeservers. This API may return keys which are not limited to displayname or avatar_url.

Request format:

Parameter Type Description
path parameters
userId string Required. The user whose profile information to get.

Response format:

Parameter Type Description
avatar_url string The user's avatar URL if they have set one, otherwise not present.
displayname string The user's display name if they have set one, otherwise not present.

Example request:

GET /_matrix/client/r0/profile/%40alice%3Aexample.com HTTP/1.1

Responses:

Status code 200:

The avatar URL for this user.

Example

{
  "avatar_url": "mxc://matrix.org/SDGdghriugerRg",
  "displayname": "Alice Margatroid"
}

Status code 404:

There is no profile information for this user or this user does not exist.

8.6   Events on Change of Profile Information

Because the profile display name and avatar information are likely to be used in many places of a client's display, changes to these fields cause an automatic propagation event to occur, informing likely-interested parties of the new values. This change is conveyed using two separate mechanisms:

  • a m.room.member event (with a join membership) is sent to every room the user is a member of, to update the displayname and avatar_url.
  • a m.presence presence status update is sent, again containing the new values of the displayname and avatar_url keys, in addition to the required presence key containing the current presence state of the user.

Both of these should be done automatically by the homeserver when a user successfully changes their display name or avatar URL fields.

Additionally, when homeservers emit room membership events for their own users, they should include the display name and avatar URL fields in these events so that clients already have these details to hand, and do not have to perform extra round trips to query it.

9   Security

9.1   Rate limiting

Homeservers SHOULD implement rate limiting to reduce the risk of being overloaded. If a request is refused due to rate limiting, it should return a standard error response of the form:

{
  "errcode": "M_LIMIT_EXCEEDED",
  "error": "string",
  "retry_after_ms": integer (optional)
}

The retry_after_ms key SHOULD be included to tell the client how long they have to wait in milliseconds before they can try again.

10   Event Structure

All communication in Matrix is expressed in the form of data objects called Events. These are the fundamental building blocks common to the client-server, server-server and application-service APIs, and are described below.

Note that the structure of these events may be different than those in the server-server API.

10.1   Event Fields

The basic set of fields all events must have.

Event

Key Type Description
content object The fields in this object will vary depending on the type of event. When interacting with the REST API, this is the HTTP body.
type string Required. The type of event. This SHOULD be namespaced similar to Java package naming conventions e.g. 'com.example.subdomain.event.type'

10.2   Room Event Fields

In addition to the Event fields, Room Events have the following additional fields.

Room Event

Key Type Description
event_id string Required. The globally unique event identifier.
room_id string Required. The ID of the room associated with this event.
sender string Required. Contains the fully-qualified ID of the user who sent this event.
origin_server_ts number Required. Timestamp in milliseconds on originating homeserver when this event was sent.
unsigned UnsignedData Contains optional extra information about the event.

UnsignedData

Key Type Description
age integer The time in milliseconds that has elapsed since the event was sent. This field is generated by the local homeserver, and may be incorrect if the local time on at least one of the two servers is out of sync, which can cause the age to either be negative or greater than it actually is.
redacted_because Event Optional. The event that redacted this event, if any.
transaction_id string The client-supplied transaction ID, if the client being given the event is the same one which sent it.

10.3   State Event Fields

In addition to the Room Event fields, State Events have the following additional fields.

State Event

Key Type Description
prev_content EventContent Optional. The previous content for this event. If there is no previous content, this key will be missing.
state_key string Required. A unique key which defines the overwriting semantics for this piece of room state. This value is often a zero-length string. The presence of this key makes this event a State Event. The key MUST NOT start with '_'.

10.4   Size limits

The complete event MUST NOT be larger than 65535 bytes, when formatted as a PDU for the Server-Server protocol, including any signatures, and encoded as Canonical JSON.

There are additional restrictions on sizes per key:

  • sender MUST NOT exceed 255 bytes (including domain).
  • room_id MUST NOT exceed 255 bytes.
  • state_key MUST NOT exceed 255 bytes.
  • type MUST NOT exceed 255 bytes.
  • event_id MUST NOT exceed 255 bytes.

Some event types have additional size restrictions which are specified in the description of the event. Additional keys have no limit other than that implied by the total 65 KB limit on events.

10.5   Room Events

Note

This section is a work in progress.

This specification outlines several standard event types, all of which are prefixed with m.

10.5.1   m.room.aliases

State Event
state_key: The homeserver domain which owns these room aliases.

This event is sent by a homeserver directly to inform of changes to the list of aliases it knows about for that room. The state_key for this event is set to the homeserver which owns the room alias. The entire set of known aliases for the room is the union of all the m.room.aliases events, one for each homeserver. Clients should check the validity of any room alias given in this list before presenting it to the user as trusted fact. The lists given by this event should be considered simply as advice on which aliases might exist, for which the client can perform the lookup to confirm whether it receives the correct room ID.

Content Key Type Description
aliases [string] Required. A list of room aliases.

Example:

{
    "age": 242352,
    "content": {
        "aliases": [
            "#somewhere:localhost",
            "#another:localhost"
        ]
    },
    "event_id": "$WLGTSEFSEF:localhost",
    "origin_server_ts": 1431961217939,
    "room_id": "!Cuyf34gef24t:localhost",
    "sender": "@example:localhost",
    "state_key": "localhost",
    "type": "m.room.aliases"
}

10.5.2   m.room.canonical_alias

State Event
state_key: A zero-length string.

This event is used to inform the room about which alias should be considered the canonical one. This could be for display purposes or as suggestion to users which alias to use to advertise the room.

A room with an m.room.canonical_alias event with an absent, null, or empty alias field should be treated the same as a room with no m.room.canonical_alias event.

Content Key Type Description
alias string Required. The canonical alias.

Example:

{
    "age": 242352,
    "content": {
        "alias": "#somewhere:localhost"
    },
    "event_id": "$WLGTSEFSEF:localhost",
    "origin_server_ts": 1431961217939,
    "room_id": "!Cuyf34gef24t:localhost",
    "sender": "@example:localhost",
    "state_key": "",
    "type": "m.room.canonical_alias"
}

10.5.3   m.room.create

State Event
state_key: A zero-length string.

This is the first event in a room and cannot be changed. It acts as the root of all other events.

Content Key Type Description
creator string Required. The user_id of the room creator. This is set by the homeserver.
m.federate boolean Whether users on other servers can join this room. Defaults to true if key does not exist.

Example:

{
    "age": 242352,
    "content": {
        "creator": "@example:localhost"
    },
    "event_id": "$WLGTSEFSEF:localhost",
    "origin_server_ts": 1431961217939,
    "room_id": "!Cuyf34gef24t:localhost",
    "sender": "@example:localhost",
    "state_key": "",
    "type": "m.room.create"
}

10.5.4   m.room.join_rules

State Event
state_key: A zero-length string.

A room may be public meaning anyone can join the room without any prior action. Alternatively, it can be invite meaning that a user who wishes to join the room must first receive an invite to the room from someone already inside of the room. Currently, knock and private are reserved keywords which are not implemented.

Content Key Type Description
join_rule enum Required. The type of rules used for users wishing to join this room. One of: ["public", "knock", "invite", "private"]

Example:

{
    "age": 242352,
    "content": {
        "join_rule": "public"
    },
    "event_id": "$WLGTSEFSEF:localhost",
    "origin_server_ts": 1431961217939,
    "room_id": "!Cuyf34gef24t:localhost",
    "sender": "@example:localhost",
    "state_key": "",
    "type": "m.room.join_rules"
}

10.5.5   m.room.member

State Event
state_key: The user_id this membership event relates to.

Adjusts the membership state for a user in a room. It is preferable to use the membership APIs (/rooms/<room id>/invite etc) when performing membership actions rather than adjusting the state directly as there are a restricted set of valid transformations. For example, user A cannot force user B to join a room, and trying to force this state change directly will fail.

The following membership states are specified:

  • invite - The user has been invited to join a room, but has not yet joined it. They may not participate in the room until they join.
  • join - The user has joined the room (possibly after accepting an invite), and may participate in it.
  • leave - The user was once joined to the room, but has since left (possibly by choice, or possibly by being kicked).
  • ban - The user has been banned from the room, and is no longer allowed to join it until they are un-banned from the room (by having their membership state set to a value other than ban).
  • knock - This is a reserved word, which currently has no meaning.

The third_party_invite property will be set if this invite is an invite event and is the successor of an m.room.third_party_invite event, and absent otherwise.

This event may also include an invite_room_state key outside the content key. If present, this contains an array of StrippedState Events. These events provide information on a subset of state events such as the room name.

EventContent

EventContent Key Type Description
avatar_url string The avatar URL for this user, if any. This is added by the homeserver.
displayname string or null The display name for this user, if any. This is added by the homeserver.
membership enum Required. The membership state of the user. One of: ["invite", "join", "knock", "leave", "ban"]
is_direct boolean Flag indicating if the room containing this event was created with the intention of being a direct chat. See Direct Messaging.
third_party_invite Invite  

Invite

Invite Key Type Description
display_name string Required. A name which can be displayed to represent the user instead of their third party identifier
signed signed Required. A block of content which has been signed, which servers can use to verify the event. Clients should ignore this.

signed

signed Key Type Description
mxid string Required. The invited matrix user ID. Must be equal to the user_id property of the event.
signatures Signatures Required. A single signature from the verifying server, in the format specified by the Signing Events section of the server-server API.
token string Required. The token property of the containing third_party_invite object.

StrippedState

StrippedState Key Type Description
content EventContent Required. The content for the event.
state_key string Required. The state_key for the event.
type string Required. The type for the event.

Examples:

{
    "age": 242352,
    "content": {
        "avatar_url": "mxc://localhost/SEsfnsuifSDFSSEF#auto",
        "displayname": "Alice Margatroid",
        "membership": "join"
    },
    "event_id": "$WLGTSEFSEF:localhost",
    "origin_server_ts": 1431961217939,
    "room_id": "!Cuyf34gef24t:localhost",
    "sender": "@example:localhost",
    "state_key": "@alice:localhost",
    "type": "m.room.member"
}
{
    "age": 242352,
    "content": {
        "avatar_url": "mxc://localhost/SEsfnsuifSDFSSEF#auto",
        "displayname": "Alice Margatroid",
        "membership": "invite"
    },
    "event_id": "$WLGTSEFSEF:localhost",
    "invite_room_state": [
        {
            "content": {
                "name": "Forest of Magic"
            },
            "state_key": "",
            "type": "m.room.name"
        },
        {
            "content": {
                "join_rule": "invite"
            },
            "state_key": "",
            "type": "m.room.join_rules"
        }
    ],
    "origin_server_ts": 1431961217939,
    "room_id": "!Cuyf34gef24t:localhost",
    "sender": "@example:localhost",
    "state_key": "@alice:localhost",
    "type": "m.room.member"
}
{
    "age": 242352,
    "content": {
        "avatar_url": "mxc://localhost/SEsfnsuifSDFSSEF#auto",
        "displayname": "Alice Margatroid",
        "membership": "invite",
        "third_party_invite": {
            "display_name": "alice",
            "signed": {
                "mxid": "@alice:localhost",
                "signatures": {
                    "magic.forest": {
                        "ed25519:3": "fQpGIW1Snz+pwLZu6sTy2aHy/DYWWTspTJRPyNp0PKkymfIsNffysMl6ObMMFdIJhk6g6pwlIqZ54rxo8SLmAg"
                    }
                },
                "token": "abc123"
            }
        }
    },
    "event_id": "$WLGTSEFSEF:localhost",
    "origin_server_ts": 1431961217939,
    "room_id": "!Cuyf34gef24t:localhost",
    "sender": "@example:localhost",
    "state_key": "@alice:localhost",
    "type": "m.room.member"
}

10.5.6   m.room.power_levels

State Event
state_key: A zero-length string.

This event specifies the minimum level a user must have in order to perform a certain action. It also specifies the levels of each user in the room.

If a user_id is in the users list, then that user_id has the associated power level. Otherwise they have the default level users_default. If users_default is not supplied, it is assumed to be 0.

The level required to send a certain event is governed by events, state_default and events_default. If an event type is specified in events, then the user must have at least the level specified in order to send that event. If the event type is not supplied, it defaults to events_default for Message Events and state_default for State Events.

If there is no state_default in the m.room.power_levels event, the state_default is 50. If there is no events_default in the m.room.power_levels event, the events_default is 0. If the room contains no m.room.power_levels event, both the state_default and events_default are 0.

The power level required to invite a user to the room, kick a user from the room, ban a user from the room, or redact an event, is defined by invite, kick, ban, and redact, respectively. Each of these levels defaults to 50 if they are not specified in the m.room.power_levels event, or if the room contains no m.room.power_levels event.

Note

As noted above, in the absence of an m.room.power_levels event, the state_default is 0, and all users are considered to have power level 0. That means that any member of the room can send an m.room.power_levels event, changing the permissions in the room.

Server implementations should therefore ensure that each room has an m.room.power_levels event as soon as it is created. See also the documentation of the /createRoom API.

Content Key Type Description
ban number The level required to ban a user. Defaults to 50 if unspecified.
events {string: number} The level required to send specific event types. This is a mapping from event type to power level required.
events_default number The default level required to send message events. Can be overridden by the events key. Defaults to 0 if unspecified.
invite number The level required to invite a user. Defaults to 50 if unspecified.
kick number The level required to kick a user. Defaults to 50 if unspecified.
redact number The level required to redact an event. Defaults to 50 if unspecified.
state_default number The default level required to send state events. Can be overridden by the events key. Defaults to 50 if unspecified, but 0 if there is no m.room.power_levels event at all.
users {string: number} The power levels for specific users. This is a mapping from user_id to power level for that user.
users_default number The default power level for every user in the room, unless their user_id is mentioned in the users key. Defaults to 0 if unspecified.

Example:

{
    "age": 242352,
    "content": {
        "ban": 50,
        "events": {
            "m.room.name": 100,
            "m.room.power_levels": 100
        },
        "events_default": 0,
        "invite": 50,
        "kick": 50,
        "redact": 50,
        "state_default": 50,
        "users": {
            "@example:localhost": 100
        },
        "users_default": 0
    },
    "event_id": "$WLGTSEFSEF:localhost",
    "origin_server_ts": 1431961217939,
    "room_id": "!Cuyf34gef24t:localhost",
    "sender": "@example:localhost",
    "state_key": "",
    "type": "m.room.power_levels"
}

10.5.7   m.room.redaction

Message Event

Events can be redacted by either room or server admins. Redacting an event means that all keys not required by the protocol are stripped off, allowing admins to remove offensive or illegal content that may have been attached to any event. This cannot be undone, allowing server owners to physically delete the offending data. There is also a concept of a moderator hiding a message event, which can be undone, but cannot be applied to state events. The event that has been redacted is specified in the redacts event level key.

Content Key Type Description
reason string The reason for the redaction, if any.

Example:

{
    "content": {
        "reason": "Spamming"
    },
    "event_id": "$WLGTSEFSEF:localhost",
    "origin_server_ts": 1431961217939,
    "redacts": "$fukweghifu23:localhost",
    "room_id": "!Cuyf34gef24t:localhost",
    "sender": "@example:localhost",
    "type": "m.room.redaction",
    "unsigned": {
        "age": 242352
    }
}

11   Modules

11.1   Feature Profiles

Matrix supports many different kinds of clients: from embedded IoT devices to desktop clients. Not all clients can provide the same feature sets as other clients e.g. due to lack of physical hardware such as not having a screen. Clients can fall into one of several profiles and each profile contains a set of features that the client MUST support. This section details a set of "feature profiles". Clients are expected to implement a profile in its entirety in order for it to be classified as that profile.

11.1.1   Summary

Module / Profile Web Mobile Desktop CLI Embedded
Instant Messaging Required Required Required Required Optional
Presence Required Required Required Required Optional
Push Notifications Optional Required Optional Optional Optional
Receipts Required Required Required Required Optional
Typing Notifications Required Required Required Required Optional
VoIP Required Required Required Optional Optional
Content Repository Required Required Required Optional Optional
Managing History Visibility Required Required Required Required Optional
Server Side Search Optional Optional Optional Optional Optional
Server Administration Optional Optional Optional Optional Optional
Event Context Optional Optional Optional Optional Optional

Please see each module for more details on what clients need to implement.

11.1.2   Clients

11.1.2.1   Stand-alone web (Web)

This is a web page which heavily uses Matrix for communication. Single-page web apps would be classified as a stand-alone web client, as would multi-page web apps which use Matrix on nearly every page.

11.1.2.2   Mobile (Mobile)

This is a Matrix client specifically designed for consumption on mobile devices. This is typically a mobile app but need not be so provided the feature set can be reached (e.g. if a mobile site could display push notifications it could be classified as a mobile client).

11.1.2.3   Desktop (Desktop)

This is a native GUI application which can run in its own environment outside a browser.

11.1.2.4   Command Line Interface (CLI)

This is a client which is used via a text-based terminal.

11.1.2.5   Embedded (Embedded)

This is a client which is embedded into another application or an embedded device.

11.1.2.5.1   Application

This is a Matrix client which is embedded in another website, e.g. using iframes. These embedded clients are typically for a single purpose related to the website in question, and are not intended to be fully-fledged communication apps.

11.1.2.5.2   Device

This is a client which is typically running on an embedded device such as a kettle, fridge or car. These clients tend to perform a few operations and run in a resource constrained environment. Like embedded applications, they are not intended to be fully-fledged communication systems.

11.2   Instant Messaging

This module adds support for sending human-readable messages to a room. It also adds support for associating human-readable information with the room itself such as a room name and topic.

11.2.1   Events

11.2.1.1   m.room.message

Message Event

This event is used when sending messages in a room. Messages are not limited to be text. The msgtype key outlines the type of message, e.g. text, audio, image, video, etc. The body key is text and MUST be used with every kind of msgtype as a fallback mechanism for when a client cannot render a message. This allows clients to display something even if it is just plain text. For more information on msgtypes, see m.room.message msgtypes.

Content Key Type Description
body string Required. The textual representation of this message.
msgtype string Required. The type of message, e.g. m.image, m.text

Examples:

{
    "age": 242352,
    "content": {
        "body": "This is an example text message",
        "msgtype": "m.text"
    },
    "event_id": "$WLGTSEFSEF:localhost",
    "origin_server_ts": 1431961217939,
    "room_id": "!Cuyf34gef24t:localhost",
    "sender": "@example:localhost",
    "type": "m.room.message"
}
{
    "age": 242352,
    "content": {
        "body": "This is an example notice",
        "msgtype": "m.notice"
    },
    "event_id": "$WLGTSEFSEF:localhost",
    "origin_server_ts": 1431961217939,
    "room_id": "!Cuyf34gef24t:localhost",
    "sender": "@example:localhost",
    "type": "m.room.message"
}
{
    "age": 146,
    "content": {
        "body": "Gangnam Style",
        "info": {
            "duration": 2140786,
            "h": 320,
            "mimetype": "video/mp4",
            "size": 1563685,
            "thumbnail_info": {
                "h": 300,
                "mimetype": "image/jpeg",
                "size": 46144,
                "w": 300
            },
            "thumbnail_url": "mxc://localhost/FHyPlCeYUSFFxlgbQYZmoEoe",
            "w": 480
        },
        "msgtype": "m.video",
        "url": "mxc://localhost/a526eYUSFFxlgbQYZmo442"
    },
    "event_id": "$143273582443PhrSn:localhost",
    "origin_server_ts": 1432735824653,
    "room_id": "!jEsUZKDJdhlrceRyVU:localhost",
    "sender": "@example:localhost",
    "type": "m.room.message"
}
{
    "age": 242352,
    "content": {
        "body": "filename.jpg",
        "info": {
            "h": 398,
            "mimetype": "image/jpeg",
            "size": 31037,
            "w": 394
        },
        "msgtype": "m.image",
        "url": "mxc://localhost/JWEIFJgwEIhweiWJE"
    },
    "event_id": "$WLGTSEFSEF:localhost",
    "origin_server_ts": 1431961217939,
    "room_id": "!Cuyf34gef24t:localhost",
    "sender": "@example:localhost",
    "type": "m.room.message"
}
{
    "age": 146,
    "content": {
        "body": "Big Ben, London, UK",
        "geo_uri": "geo:51.5008,0.1247",
        "info": {
            "thumbnail_info": {
                "h": 300,
                "mimetype": "image/jpeg",
                "size": 46144,
                "w": 300
            },
            "thumbnail_url": "mxc://localhost/FHyPlCeYUSFFxlgbQYZmoEoe"
        },
        "msgtype": "m.location"
    },
    "event_id": "$143273582443PhrSn:localhost",
    "origin_server_ts": 1432735824653,
    "room_id": "!jEsUZKDJdhlrceRyVU:localhost",
    "sender": "@example:localhost",
    "type": "m.room.message"
}
{
    "age": 146,
    "content": {
        "body": "something-important.doc",
        "filename": "something-important.doc",
        "info": {
            "mimetype": "application/msword",
            "size": 46144
        },
        "msgtype": "m.file",
        "url": "mxc://localhost/FHyPlCeYUSFFxlgbQYZmoEoe"
    },
    "event_id": "$143273582443PhrSn:localhost",
    "origin_server_ts": 1432735824653,
    "room_id": "!jEsUZKDJdhlrceRyVU:localhost",
    "sender": "@example:localhost",
    "type": "m.room.message"
}
{
    "age": 242352,
    "content": {
        "body": "thinks this is an example emote",
        "msgtype": "m.emote"
    },
    "event_id": "$WLGTSEFSEF:localhost",
    "origin_server_ts": 1431961217939,
    "room_id": "!Cuyf34gef24t:localhost",
    "sender": "@example:localhost",
    "type": "m.room.message"
}
{
    "age": 146,
    "content": {
        "body": "Bee Gees - Stayin' Alive",
        "info": {
            "duration": 2140786,
            "mimetype": "audio/mpeg",
            "size": 1563685
        },
        "msgtype": "m.audio",
        "url": "mxc://localhost/ffed755USFFxlgbQYZGtryd"
    },
    "event_id": "$143273582443PhrSn:localhost",
    "origin_server_ts": 1432735824653,
    "room_id": "!jEsUZKDJdhlrceRyVU:localhost",
    "sender": "@example:localhost",
    "type": "m.room.message"
}

11.2.1.2   m.room.message.feedback

Message Event

NB: Usage of this event is discouraged in favour of the receipts module. Most clients will not recognise this event. Feedback events are events sent to acknowledge a message in some way. There are two supported acknowledgements: delivered (sent when the event has been received) and read (sent when the event has been observed by the end-user). The target_event_id should reference the m.room.message event being acknowledged.

Content Key Type Description
target_event_id string Required. The event that this feedback is related to.
type enum Required. The type of feedback. One of: ["delivered", "read"]

Example:

{
    "age": 242352,
    "content": {
        "target_event_id": "$WEIGFHFW:localhost",
        "type": "delivered"
    },
    "event_id": "$WLGTSEFSEF:localhost",
    "origin_server_ts": 1431961217939,
    "room_id": "!Cuyf34gef24t:localhost",
    "sender": "@example:localhost",
    "type": "m.room.message.feedback"
}
Usage of this event is discouraged for several reasons:
  • The number of feedback events will grow very quickly with the number of users in the room. This event provides no way to "batch" feedback, unlike the receipts module.
  • Pairing feedback to messages gets complicated when paginating as feedback arrives before the message it is acknowledging.
  • There are no guarantees that the client has seen the event ID being acknowledged.

11.2.1.3   m.room.name

State Event
state_key: A zero-length string.

A room has an opaque room ID which is not human-friendly to read. A room alias is human-friendly, but not all rooms have room aliases. The room name is a human-friendly string designed to be displayed to the end-user. The room name is not unique, as multiple rooms can have the same room name set.

A room with an m.room.name event with an absent, null, or empty name field should be treated the same as a room with no m.room.name event.

An event of this type is automatically created when creating a room using /createRoom with the name key.

Content Key Type Description
name string Required. The name of the room. This MUST NOT exceed 255 bytes.

Example:

{
    "age": 242352,
    "content": {
        "name": "The room name"
    },
    "event_id": "$WLGTSEFSEF:localhost",
    "origin_server_ts": 1431961217939,
    "room_id": "!Cuyf34gef24t:localhost",
    "sender": "@example:localhost",
    "state_key": "",
    "type": "m.room.name"
}

11.2.1.4   m.room.topic

State Event
state_key: A zero-length string.

A topic is a short message detailing what is currently being discussed in the room. It can also be used as a way to display extra information about the room, which may not be suitable for the room name. The room topic can also be set when creating a room using /createRoom with the topic key.

Content Key Type Description
topic string Required. The topic text.

Example:

{
    "age": 242352,
    "content": {
        "topic": "A room topic"
    },
    "event_id": "$WLGTSEFSEF:localhost",
    "origin_server_ts": 1431961217939,
    "room_id": "!Cuyf34gef24t:localhost",
    "sender": "@example:localhost",
    "state_key": "",
    "type": "m.room.topic"
}

11.2.1.5   m.room.avatar

State Event
state_key: A zero-length string.

A picture that is associated with the room. This can be displayed alongside the room information.

Content Key Type Description
info ImageInfo Metadata about the image referred to in url.
url string Required. The URL to the image.

ImageInfo

ImageInfo Key Type Description
h integer The height of the image in pixels.
w integer The width of the image in pixels.
mimetype string The mimetype of the image, e.g. image/jpeg.
size integer Size of the image in bytes.
thumbnail_url string The URL to a thumbnail of the image.
thumbnail_info ThumbnailInfo Metadata about the image referred to in thumbnail_url.

ThumbnailInfo

ThumbnailInfo Key Type Description
h integer The height of the image in pixels.
w integer The width of the image in pixels.
mimetype string The mimetype of the image, e.g. image/jpeg.
size integer Size of the image in bytes.

Example:

{
    "age": 242352,
    "content": {
        "info": {
            "h": 398,
            "mimetype": "image/jpeg",
            "size": 31037,
            "w": 394
        },
        "url": "mxc://localhost/JWEIFJgwEIhweiWJE"
    },
    "event_id": "$WLGTSEFSEF:localhost",
    "origin_server_ts": 1431961217939,
    "room_id": "!Cuyf34gef24t:localhost",
    "sender": "@example:localhost",
    "state_key": "",
    "type": "m.room.avatar"
}

11.2.1.6   m.room.pinned_events

State Event
state_key: A zero-length string.

This event is used to "pin" particular events in a room for other participants to review later. The order of the pinned events is guaranteed and based upon the order supplied in the event. Clients should be aware that the current user may not be able to see some of the events pinned due to visibility settings in the room. Clients are responsible for determining if a particular event in the pinned list is displayable, and have the option to not display it if it cannot be pinned in the client.

Content Key Type Description
pinned [string] Required. An ordered list of event IDs to pin.

Example:

{
    "age": 242352,
    "content": {
        "pinned": [
            "$someevent:localhost"
        ]
    },
    "event_id": "$WLGTSEFSEF:localhost",
    "origin_server_ts": 1431961217939,
    "room_id": "!Cuyf34gef24t:localhost",
    "sender": "@example:localhost",
    "state_key": "",
    "type": "m.room.pinned_events"
}

11.2.1.7   m.room.message msgtypes

Each m.room.message MUST have a msgtype key which identifies the type of message being sent. Each type has their own required and optional keys, as outlined below. If a client cannot display the given msgtype then it SHOULD display the fallback plain text body key instead.

11.2.1.7.1   m.text

This message is the most basic message and is used to represent text.

Content Key Type Description
body string Required. The body of the message.
msgtype string Required. Must be 'm.text'.

Example:

{
    "age": 242352,
    "content": {
        "body": "This is an example text message",
        "msgtype": "m.text"
    },
    "event_id": "$WLGTSEFSEF:localhost",
    "origin_server_ts": 1431961217939,
    "room_id": "!Cuyf34gef24t:localhost",
    "sender": "@example:localhost",
    "type": "m.room.message"
}

11.2.1.7.2   m.emote

This message is similar to m.text except that the sender is 'performing' the action contained in the body key, similar to /me in IRC. This message should be prefixed by the name of the sender. This message could also be represented in a different colour to distinguish it from regular m.text messages.

Content Key Type Description
body string Required. The emote action to perform.
msgtype string Required. Must be 'm.emote'.

Example:

{
    "age": 242352,
    "content": {
        "body": "thinks this is an example emote",
        "msgtype": "m.emote"
    },
    "event_id": "$WLGTSEFSEF:localhost",
    "origin_server_ts": 1431961217939,
    "room_id": "!Cuyf34gef24t:localhost",
    "sender": "@example:localhost",
    "type": "m.room.message"
}

11.2.1.7.3   m.notice

The m.notice type is primarily intended for responses from automated clients. An m.notice message must be treated the same way as a regular m.text message with two exceptions. Firstly, clients should present m.notice messages to users in a distinct manner, and secondly, m.notice messages must never be automatically responded to. This helps to prevent infinite-loop situations where two automated clients continuously exchange messages.

Content Key Type Description
body string Required. The notice text to send.
msgtype string Required. Must be 'm.notice'.

Example:

{
    "age": 242352,
    "content": {
        "body": "This is an example notice",
        "msgtype": "m.notice"
    },
    "event_id": "$WLGTSEFSEF:localhost",
    "origin_server_ts": 1431961217939,
    "room_id": "!Cuyf34gef24t:localhost",
    "sender": "@example:localhost",
    "type": "m.room.message"
}

11.2.1.7.4   m.image

This message represents a single image and an optional thumbnail.

Content Key Type Description
body string Required. A textual representation of the image. This could be the alt text of the image, the filename of the image, or some kind of content description for accessibility e.g. 'image attachment'.
info ImageInfo Metadata about the image referred to in url.
msgtype string Required. Must be 'm.image'.
url string Required. The URL to the image.

ImageInfo

ImageInfo Key Type Description
h integer The height of the image in pixels.
w integer The width of the image in pixels.
mimetype string The mimetype of the image, e.g. image/jpeg.
size integer Size of the image in bytes.
thumbnail_url string The URL to a thumbnail of the image.
thumbnail_info ThumbnailInfo Metadata about the image referred to in thumbnail_url.

ThumbnailInfo

ThumbnailInfo Key Type Description
h integer The height of the image in pixels.
w integer The width of the image in pixels.
mimetype string The mimetype of the image, e.g. image/jpeg.
size integer Size of the image in bytes.

Example:

{
    "age": 242352,
    "content": {
        "body": "filename.jpg",
        "info": {
            "h": 398,
            "mimetype": "image/jpeg",
            "size": 31037,
            "w": 394
        },
        "msgtype": "m.image",
        "url": "mxc://localhost/JWEIFJgwEIhweiWJE"
    },
    "event_id": "$WLGTSEFSEF:localhost",
    "origin_server_ts": 1431961217939,
    "room_id": "!Cuyf34gef24t:localhost",
    "sender": "@example:localhost",
    "type": "m.room.message"
}

11.2.1.7.5   m.file

This message represents a generic file.

Content Key Type Description
body string Required. A human-readable description of the file. This is recommended to be the filename of the original upload.
filename string Required. The original filename of the uploaded file.
info FileInfo Information about the file referred to in url.
msgtype string Required. Must be 'm.file'.
url string Required. The URL to the file.

FileInfo

FileInfo Key Type Description
mimetype string The mimetype of the file e.g. application/msword.
size integer The size of the file in bytes.
thumbnail_url string The URL to the thumbnail of the file.
thumbnail_info ThumbnailInfo Metadata about the image referred to in thumbnail_url.

ThumbnailInfo

ThumbnailInfo Key Type Description
h integer The height of the image in pixels.
w integer The width of the image in pixels.
mimetype string The mimetype of the image, e.g. image/jpeg.
size integer Size of the image in bytes.

Example:

{
    "age": 146,
    "content": {
        "body": "something-important.doc",
        "filename": "something-important.doc",
        "info": {
            "mimetype": "application/msword",
            "size": 46144
        },
        "msgtype": "m.file",
        "url": "mxc://localhost/FHyPlCeYUSFFxlgbQYZmoEoe"
    },
    "event_id": "$143273582443PhrSn:localhost",
    "origin_server_ts": 1432735824653,
    "room_id": "!jEsUZKDJdhlrceRyVU:localhost",
    "sender": "@example:localhost",
    "type": "m.room.message"
}

11.2.1.7.6   m.location

This message represents a real-world location.

Content Key Type Description
body string Required. A description of the location e.g. 'Big Ben, London, UK', or some kind of content description for accessibility e.g. 'location attachment'.
geo_uri string Required. A geo URI representing this location.
msgtype string Required. Must be 'm.location'.
info LocationInfo  

LocationInfo

LocationInfo Key Type Description
thumbnail_url string The URL to a thumbnail of the location being represented.
thumbnail_info ThumbnailInfo Metadata about the image referred to in thumbnail_url.

ThumbnailInfo

ThumbnailInfo Key Type Description
h integer The height of the image in pixels.
w integer The width of the image in pixels.
mimetype string The mimetype of the image, e.g. image/jpeg.
size integer Size of the image in bytes.

Example:

{
    "age": 146,
    "content": {
        "body": "Big Ben, London, UK",
        "geo_uri": "geo:51.5008,0.1247",
        "info": {
            "thumbnail_info": {
                "h": 300,
                "mimetype": "image/jpeg",
                "size": 46144,
                "w": 300
            },
            "thumbnail_url": "mxc://localhost/FHyPlCeYUSFFxlgbQYZmoEoe"
        },
        "msgtype": "m.location"
    },
    "event_id": "$143273582443PhrSn:localhost",
    "origin_server_ts": 1432735824653,
    "room_id": "!jEsUZKDJdhlrceRyVU:localhost",
    "sender": "@example:localhost",
    "type": "m.room.message"
}

11.2.1.7.7   m.video

This message represents a single video clip.

Content Key Type Description
body string Required. A description of the video e.g. 'Gangnam style', or some kind of content description for accessibility e.g. 'video attachment'.
info VideoInfo Metadata about the video clip referred to in url.
msgtype string Required. Must be 'm.video'.
url string Required. The URL to the video clip.

VideoInfo

VideoInfo Key Type Description
duration integer The duration of the video in milliseconds.
h integer The height of the video in pixels.
w integer The width of the video in pixels.
mimetype string The mimetype of the video e.g. video/mp4.
size integer The size of the video in bytes.
thumbnail_url string The URL to an image thumbnail of the video clip.
thumbnail_info ThumbnailInfo Metadata about the image referred to in thumbnail_url.

ThumbnailInfo

ThumbnailInfo Key Type Description
h integer The height of the image in pixels.
w integer The width of the image in pixels.
mimetype string The mimetype of the image, e.g. image/jpeg.
size integer Size of the image in bytes.

Example:

{
    "age": 146,
    "content": {
        "body": "Gangnam Style",
        "info": {
            "duration": 2140786,
            "h": 320,
            "mimetype": "video/mp4",
            "size": 1563685,
            "thumbnail_info": {
                "h": 300,
                "mimetype": "image/jpeg",
                "size": 46144,
                "w": 300
            },
            "thumbnail_url": "mxc://localhost/FHyPlCeYUSFFxlgbQYZmoEoe",
            "w": 480
        },
        "msgtype": "m.video",
        "url": "mxc://localhost/a526eYUSFFxlgbQYZmo442"
    },
    "event_id": "$143273582443PhrSn:localhost",
    "origin_server_ts": 1432735824653,
    "room_id": "!jEsUZKDJdhlrceRyVU:localhost",
    "sender": "@example:localhost",
    "type": "m.room.message"
}

11.2.1.7.8   m.audio

This message represents a single audio clip.

Content Key Type Description
body string Required. A description of the audio e.g. 'Bee Gees - Stayin' Alive', or some kind of content description for accessibility e.g. 'audio attachment'.
info AudioInfo Metadata for the audio clip referred to in url.
msgtype string Required. Must be 'm.audio'.
url string Required. The URL to the audio clip.

AudioInfo

AudioInfo Key Type Description
duration integer The duration of the audio in milliseconds.
mimetype string The mimetype of the audio e.g. audio/aac.
size integer The size of the audio clip in bytes.

Example:

{
    "age": 146,
    "content": {
        "body": "Bee Gees - Stayin' Alive",
        "info": {
            "duration": 2140786,
            "mimetype": "audio/mpeg",
            "size": 1563685
        },
        "msgtype": "m.audio",
        "url": "mxc://localhost/ffed755USFFxlgbQYZGtryd"
    },
    "event_id": "$143273582443PhrSn:localhost",
    "origin_server_ts": 1432735824653,
    "room_id": "!jEsUZKDJdhlrceRyVU:localhost",
    "sender": "@example:localhost",
    "type": "m.room.message"
}

11.2.2   Client behaviour

Clients SHOULD verify the structure of incoming events to ensure that the expected keys exist and that they are of the right type. Clients can discard malformed events or display a placeholder message to the user. Redacted m.room.message events MUST be removed from the client. This can either be replaced with placeholder text (e.g. "[REDACTED]") or the redacted message can be removed entirely from the messages view.

Events which have attachments (e.g. m.image, m.file) SHOULD be uploaded using the content repository module where available. The resulting mxc:// URI can then be used in the url key.

Clients MAY include a client generated thumbnail image for an attachment under a info.thumbnail_url key. The thumbnail SHOULD also be a mxc:// URI. Clients displaying events with attachments can either use the client generated thumbnail or ask its homeserver to generate a thumbnail from the original attachment using the content repository module.

11.2.2.1   Recommendations when sending messages

In the event of send failure, clients SHOULD retry requests using an exponential-backoff algorithm for a certain amount of time T. It is recommended that T is no longer than 5 minutes. After this time, the client should stop retrying and mark the message as "unsent". Users should be able to manually resend unsent messages.

Users may type several messages at once and send them all in quick succession. Clients SHOULD preserve the order in which they were sent by the user. This means that clients should wait for the response to the previous request before sending the next request. This can lead to head-of-line blocking. In order to reduce the impact of head-of-line blocking, clients should use a queue per room rather than a global queue, as ordering is only relevant within a single room rather than between rooms.

11.2.2.2   Local echo

Messages SHOULD appear immediately in the message view when a user presses the "send" button. This should occur even if the message is still sending. This is referred to as "local echo". Clients SHOULD implement "local echo" of messages. Clients MAY display messages in a different format to indicate that the server has not processed the message. This format should be removed when the server responds.

Clients need to be able to match the message they are sending with the same message which they receive from the event stream. The echo of the same message from the event stream is referred to as "remote echo". Both echoes need to be identified as the same message in order to prevent duplicate messages being displayed. Ideally this pairing would occur transparently to the user: the UI would not flicker as it transitions from local to remote. Flickering cannot be fully avoided in the current client-server API. Two scenarios need to be considered:

  • The client sends a message and the remote echo arrives on the event stream after the request to send the message completes.
  • The client sends a message and the remote echo arrives on the event stream before the request to send the message completes.

In the first scenario, the client will receive an event ID when the request to send the message completes. This ID can be used to identify the duplicate event when it arrives on the event stream. However, in the second scenario, the event arrives before the client has obtained an event ID. This makes it impossible to identify it as a duplicate event. This results in the client displaying the message twice for a fraction of a second before the the original request to send the message completes. Once it completes, the client can take remedial actions to remove the duplicate event by looking for duplicate event IDs. A future version of the client-server API will resolve this by attaching the transaction ID of the sending request to the event itself.

11.2.2.3   Calculating the display name for a user

Clients may wish to show the human-readable display name of a room member as part of a membership list, or when they send a message. However, different members may have conflicting display names. Display names MUST be disambiguated before showing them to the user, in order to prevent spoofing of other users.

To ensure this is done consistently across clients, clients SHOULD use the following algorithm to calculate a disambiguated display name for a given user:

  1. Inspect the m.room.member state event for the relevant user id.
  2. If the m.room.member state event has no displayname field, or if that field has a null value, use the raw user id as the display name. Otherwise:
  3. If the m.room.member event has a displayname which is unique among members of the room with membership: join or membership: invite, use the given displayname as the user-visible display name. Otherwise:
  4. The m.room.member event has a non-unique displayname. This should be disambiguated using the user id, for example "display name (@id:homeserver.org)".

Developers should take note of the following when implementing the above algorithm:

  • The user-visible display name of one member can be affected by changes in the state of another member. For example, if @user1:matrix.org is present in a room, with displayname: Alice, then when @user2:example.com joins the room, also with displayname: Alice, both users must be given disambiguated display names. Similarly, when one of the users then changes their display name, there is no longer a clash, and both users can be given their chosen display name. Clients should be alert to this possibility and ensure that all affected users are correctly renamed.
  • The display name of a room may also be affected by changes in the membership list. This is due to the room name sometimes being based on user display names (see Calculating the display name for a room).
  • If the entire membership list is searched for clashing display names, this leads to an O(N^2) implementation for building the list of room members. This will be very inefficient for rooms with large numbers of members. It is recommended that client implementations maintain a hash table mapping from displayname to a list of room members using that name. Such a table can then be used for efficient calculation of whether disambiguation is needed.

11.2.2.4   Displaying membership information with messages

Clients may wish to show the display name and avatar URL of the room member who sent a message. This can be achieved by inspecting the m.room.member state event for that user ID (see Calculating the display name for a user).

When a user paginates the message history, clients may wish to show the historical display name and avatar URL for a room member. This is possible because older m.room.member events are returned when paginating. This can be implemented efficiently by keeping two sets of room state: old and current. As new events arrive and/or the user paginates back in time, these two sets of state diverge from each other. New events update the current state and paginated events update the old state. When paginated events are processed sequentially, the old state represents the state of the room at the time the event was sent. This can then be used to set the historical display name and avatar URL.

11.2.2.5   Calculating the display name for a room

Clients may wish to show a human-readable name for a room. There are a number of possibilities for choosing a useful name. To ensure that rooms are named consistently across clients, clients SHOULD use the following algorithm to choose a name:

  1. If the room has an m.room.name state event with a non-empty name field, use the name given by that field.

  2. If the room has an m.room.canonical_alias state event with a non-empty alias field, use the alias given by that field as the name.

  3. If neither of the above conditions are met, a name should be composed based on the members of the room. Clients should consider m.room.member events for users other than the logged-in user, with membership: join or membership: invite.

    1. If there is only one such event, the display name for the room should be the disambiguated display name of the corresponding user.

    2. If there are two such events, they should be lexicographically sorted by their state_key (i.e. the corresponding user IDs), and the display name for the room should be the disambiguated display name of both users: "<user1> and <user2>", or a localised variant thereof.

    3. If there are three or more such events, the display name for the room should be based on the disambiguated display name of the user corresponding to the first such event, under a lexicographical sorting according to their state_key. The display name should be in the format "<user1> and <N> others" (or a localised variant thereof), where N is the number of m.room.member events with membership: join or membership: invite, excluding the logged-in user and "user1".

      For example, if Alice joins a room, where Bob (whose user id is @superuser:example.com), Carol (user id @carol:example.com) and Dan (user id @dan:matrix.org) are in conversation, Alice's client should show the room name as "Carol and 2 others".

  4. If the room has no valid m.room.name or m.room.canonical_alias event, and no active members other than the current user, clients should consider m.room.member events with membership: leave. If such events exist, a display name such as "Empty room (was <user1> and <N> others)" (or a localised variant thereof) should be used, following similar rules as for active members (see above).

  5. A complete absence of room name, canonical alias, and room members is likely to indicate a problem with creating the room or synchronising the state table; however clients should still handle this situation. A display name such as "Empty room" (or a localised variant thereof) should be used in this situation.

Clients SHOULD NOT use m.room.aliases events as a source for room names, as it is difficult for clients to agree on the best alias to use, and aliases can change unexpectedly.

11.2.3   Server behaviour

Homeservers SHOULD reject m.room.message events which don't have a msgtype key, or which don't have a textual body key, with an HTTP status code of 400.

11.2.4   Security considerations

Messages sent using this module are not encrypted, although end to end encryption is in development (see E2E module).

Clients should sanitise all displayed keys for unsafe HTML to prevent Cross-Site Scripting (XSS) attacks. This includes room names and topics.

11.3   Voice over IP

This module outlines how two users in a room can set up a Voice over IP (VoIP) call to each other. Voice and video calls are built upon the WebRTC 1.0 standard. Call signalling is achieved by sending message events to the room. In this version of the spec, only two-party communication is supported (e.g. between two peers, or between a peer and a multi-point conferencing unit). This means that clients MUST only send call events to rooms with exactly two participants.

11.3.1   Events

11.3.1.1   m.call.invite

Message Event

This event is sent by the caller when they wish to establish a call.

Content Key Type Description
call_id string Required. A unique identifer for the call.
offer Offer Required. The session description object
version integer Required. The version of the VoIP specification this message adheres to. This specification is version 0.
lifetime integer Required. The time in milliseconds that the invite is valid for. Once the invite age exceeds this value, clients should discard it. They should also no longer show the call as awaiting an answer in the UI.

Offer

Offer Key Type Description
type string Required. The type of session description. Must be 'offer'.
sdp string Required. The SDP text of the session description.

Example:

{
    "age": 242352,
    "content": {
        "call_id": "12345",
        "lifetime": 60000,
        "offer": {
            "sdp": "v=0\r\no=- 6584580628695956864 2 IN IP4 127.0.0.1[...]",
            "type": "offer"
        },
        "version": 0
    },
    "event_id": "$WLGTSEFSEF:localhost",
    "origin_server_ts": 1431961217939,
    "room_id": "!Cuyf34gef24t:localhost",
    "sender": "@example:localhost",
    "type": "m.call.invite"
}

11.3.1.2   m.call.candidates

Message Event

This event is sent by callers after sending an invite and by the callee after answering. Its purpose is to give the other party additional ICE candidates to try using to communicate.

Content Key Type Description
call_id string Required. The ID of the call this event relates to.
candidates [Candidate] Required. Array of objects describing the candidates.
version integer Required. The version of the VoIP specification this messages adheres to. This specification is version 0.

Candidate

Candidate Key Type Description
sdpMid string Required. The SDP media type this candidate is intended for.
sdpMLineIndex number Required. The index of the SDP 'm' line this candidate is intended for.
candidate string Required. The SDP 'a' line of the candidate.

Example:

{
    "age": 242352,
    "content": {
        "call_id": "12345",
        "candidates": [
            {
                "candidate": "candidate:863018703 1 udp 2122260223 10.9.64.156 43670 typ host generation 0",
                "sdpMLineIndex": 0,
                "sdpMid": "audio"
            }
        ],
        "version": 0
    },
    "event_id": "$WLGTSEFSEF:localhost",
    "origin_server_ts": 1431961217939,
    "room_id": "!Cuyf34gef24t:localhost",
    "sender": "@example:localhost",
    "type": "m.call.candidates"
}

11.3.1.3   m.call.answer

Message Event

This event is sent by the callee when they wish to answer the call.

Content Key Type Description
call_id string Required. The ID of the call this event relates to.
answer Answer Required. The session description object
version number Required.

Answer

Answer Key Type Description
type string Required. The type of session description. Must be 'answer'.
sdp string Required. The SDP text of the session description.

Example:

{
    "age": 242352,
    "content": {
        "answer": {
            "sdp": "v=0\r\no=- 6584580628695956864 2 IN IP4 127.0.0.1[...]",
            "type": "answer"
        },
        "call_id": "12345",
        "lifetime": 60000,
        "version": 0
    },
    "event_id": "$WLGTSEFSEF:localhost",
    "origin_server_ts": 1431961217939,
    "room_id": "!Cuyf34gef24t:localhost",
    "sender": "@example:localhost",
    "type": "m.call.answer"
}

11.3.1.4   m.call.hangup

Message Event

Sent by either party to signal their termination of the call. This can be sent either once the call has has been established or before to abort the call.

Content Key Type Description
call_id string Required. The ID of the call this event relates to.
version integer Required. The version of the VoIP specification this message adheres to. This specification is version 0.

Example:

{
    "age": 242352,
    "content": {
        "call_id": "12345",
        "version": 0
    },
    "event_id": "$WLGTSEFSEF:localhost",
    "origin_server_ts": 1431961217939,
    "room_id": "!Cuyf34gef24t:localhost",
    "sender": "@example:localhost",
    "type": "m.call.hangup"
}

11.3.2   Client behaviour

A call is set up with message events exchanged as follows:

  Caller                    Callee
[Place Call]
m.call.invite ----------->
m.call.candidate -------->
[..candidates..] -------->
                          [Answers call]
         <--------------- m.call.answer
   [Call is active and ongoing]
         <--------------- m.call.hangup

Or a rejected call:

  Caller                      Callee
m.call.invite ------------>
m.call.candidate --------->
[..candidates..] --------->
                           [Rejects call]
           <-------------- m.call.hangup

Calls are negotiated according to the WebRTC specification.

11.3.2.1   Glare

"Glare" is a problem which occurs when two users call each other at roughly the same time. This results in the call failing to set up as there already is an incoming/outgoing call. A glare resolution algorithm can be used to determine which call to hangup and which call to answer. If both clients implement the same algorithm then they will both select the same call and the call will be successfully connected.

As calls are "placed" to rooms rather than users, the glare resolution algorithm outlined below is only considered for calls which are to the same room. The algorithm is as follows:

  • If an m.call.invite to a room is received whilst the client is preparing to send an m.call.invite to the same room:
    • the client should cancel its outgoing call and instead automatically accept the incoming call on behalf of the user.
  • If an m.call.invite to a room is received after the client has sent an m.call.invite to the same room and is waiting for a response:
    • the client should perform a lexicographical comparison of the call IDs of the two calls and use the lesser of the two calls, aborting the greater. If the incoming call is the lesser, the client should accept this call on behalf of the user.

The call setup should appear seamless to the user as if they had simply placed a call and the other party had accepted. This means any media stream that had been setup for use on a call should be transferred and used for the call that replaces it.

11.3.3   Server behaviour

The homeserver MAY provide a TURN server which clients can use to contact the remote party. The following HTTP API endpoints will be used by clients in order to get information about the TURN server.

11.3.3.1   GET /_matrix/client/r0/voip/turnServer

This API provides credentials for the client to use when initiating calls.

Rate-limited:Yes.
Requires auth:Yes.

Request format:

No parameters

Response format:

Parameter Type Description
username string Required. The username to use.
password string Required. The password to use.
uris [string] Required. A list of TURN URIs
ttl integer Required. The time-to-live in seconds

Example request:

GET /_matrix/client/r0/voip/turnServer HTTP/1.1

Responses:

Status code 200:

The TURN server credentials.

Example

{
  "username": "1443779631:@user:example.com",
  "password": "JlKfBy1QwLrO20385QyAtEyIv0=",
  "uris": [
    "turn:turn.example.com:3478?transport=udp",
    "turn:10.20.30.40:3478?transport=tcp",
    "turns:10.20.30.40:443?transport=tcp"
  ],
  "ttl": 86400
}

Status code 429:

This request was rate-limited.

Example

{
  "errcode": "string",
  "error": "string"
}

11.3.4   Security considerations

Calls should only be placed to rooms with one other user in them. If they are placed to group chat rooms it is possible that another user will intercept and answer the call.

11.4   Typing Notifications

Users may wish to be informed when another user is typing in a room. This can be achieved using typing notifications. These are ephemeral events scoped to a room_id. This means they do not form part of the Event Graph but still have a room_id key.

11.4.1   Events

11.4.1.1   m.typing

Informs the client of the list of users currently typing.

Content Key Type Description
user_ids [string] Required. The list of user IDs typing in this room, if any.

Example:

{
    "content": {
        "user_ids": [
            "@alice:matrix.org",
            "@bob:example.com"
        ]
    },
    "room_id": "!z0mnsuiwhifuhwwfw:matrix.org",
    "type": "m.typing"
}

11.4.2   Client behaviour

When a client receives an m.typing event, it MUST use the user ID list to REPLACE its knowledge of every user who is currently typing. The reason for this is that the server does not remember users who are not currently typing as that list gets big quickly. The client should mark as not typing any user ID who is not in that list.

It is recommended that clients store a boolean indicating whether the user is typing or not. Whilst this value is true a timer should fire periodically every N seconds to send a typing HTTP request. The value of N is recommended to be no more than 20-30 seconds. This request should be re-sent by the client to continue informing the server the user is still typing. As subsequent requests will replace older requests, a safety margin of 5 seconds before the expected timeout runs out is recommended. When the user stops typing, the state change of the boolean to false should trigger another HTTP request to inform the server that the user has stopped typing.

11.4.2.1   PUT /_matrix/client/r0/rooms/{roomId}/typing/{userId}

This tells the server that the user is typing for the next N milliseconds where N is the value specified in the timeout key. Alternatively, if typing is false, it tells the server that the user has stopped typing.

Rate-limited:Yes.
Requires auth:Yes.

Request format:

Parameter Type Description
path parameters
userId string Required. The user who has started to type.
roomId string Required. The room in which the user is typing.
JSON body parameters
typing boolean Required. Whether the user is typing or not. If false, the timeout key can be omitted.
timeout integer The length of time in milliseconds to mark this user as typing.

Example request:

PUT /_matrix/client/r0/rooms/%21wefh3sfukhs%3Aexample.com/typing/%40alice%3Aexample.com HTTP/1.1
Content-Type: application/json

{
  "typing": true,
  "timeout": 30000
}

Responses:

Status code 200:

The new typing state was set.

Example

{}

Status code 429:

This request was rate-limited.

Example

{
  "errcode": "string",
  "error": "string"
}

11.4.3   Security considerations

Clients may not wish to inform everyone in a room that they are typing and instead only specific users in the room.

11.5   Receipts

This module adds in support for receipts. These receipts are a form of acknowledgement of an event. This module defines a single acknowledgement: m.read which indicates that the user has read up to a given event.

Sending a receipt for each event can result in sending large amounts of traffic to a homeserver. To prevent this from becoming a problem, receipts are implemented using "up to" markers. This marker indicates that the acknowledgement applies to all events "up to and including" the event specified. For example, marking an event as "read" would indicate that the user had read all events up to the referenced event.

11.5.1   Events

Each user_id, receipt_type pair must be associated with only a single event_id.

11.5.1.1   m.receipt

Informs the client of new receipts.

Content Key Type Description
$EVENT_ID Receipts The mapping of event ID to a collection of receipts for this event ID. The event ID is the ID of the event being acknowledged and not an ID for the receipt itself.

Receipts

Receipts Key Type Description
m.read Users A collection of users who have sent m.read receipts for this event.

Users

Users Key Type Description
$USER_ID Receipt The mapping of user ID to receipt. The user ID is the entity who sent this receipt.

Receipt

Receipt Key Type Description
ts number The timestamp the receipt was sent at.

Example:

{
    "content": {
        "$1435641916114394fHBLK:matrix.org": {
            "m.read": {
                "@rikj:jki.re": {
                    "ts": 1436451550453
                }
            }
        }
    },
    "room_id": "!KpjVgQyZpzBwvMBsnT:matrix.org",
    "type": "m.receipt"
}

11.5.2   Client behaviour

In /initialSync, receipts are listed in a separate top level receipts key. In /sync, receipts are contained in the ephemeral block for a room. New receipts that come down the event streams are deltas which update existing mappings. Clients should replace older receipt acknowledgements based on user_id and receipt_type pairs. For example:

Client receives m.receipt:
  user = @alice:example.com
  receipt_type = m.read
  event_id = $aaa:example.com

Client receives another m.receipt:
  user = @alice:example.com
  receipt_type = m.read
  event_id = $bbb:example.com

The client should replace the older acknowledgement for $aaa:example.com with
this one for $bbb:example.com

Clients should send read receipts when there is some certainty that the event in question has been displayed to the user. Simply receiving an event does not provide enough certainty that the user has seen the event. The user SHOULD need to take some action such as viewing the room that the event was sent to or dismissing a notification in order for the event to count as "read".

A client can update the markers for its user by interacting with the following HTTP APIs.

11.5.2.1   POST /_matrix/client/r0/rooms/{roomId}/receipt/{receiptType}/{eventId}

This API updates the marker for the given receipt type to the event ID specified.

Rate-limited:Yes.
Requires auth:Yes.

Request format:

Parameter Type Description
path parameters
roomId string Required. The room in which to send the event.
receiptType enum Required. The type of receipt to send. One of: ["m.read"]
eventId string Required. The event ID to acknowledge up to.

Example request:

POST /_matrix/client/r0/rooms/%21wefuh21ffskfuh345%3Aexample.com/receipt/m.read/%241924376522eioj%3Aexample.com HTTP/1.1
Content-Type: application/json

{}

Responses:

Status code 200:

The receipt was sent.

Example

{}

Status code 429:

This request was rate-limited.

Example

{
  "errcode": "string",
  "error": "string"
}

11.5.3   Server behaviour

For efficiency, receipts SHOULD be batched into one event per room before delivering them to clients.

Receipts are sent across federation as EDUs with type m.receipt. The format of the EDUs are:

{
    <room_id>: {
        <receipt_type>: {
            <user_id>: { <content> }
        },
        ...
    },
    ...
}

These are always sent as deltas to previously sent receipts. Currently only a single <receipt_type> should be used: m.read.

11.5.4   Security considerations

As receipts are sent outside the context of the event graph, there are no integrity checks performed on the contents of m.receipt events.

11.6   Presence

Each user has the concept of presence information. This encodes:

  • Whether the user is currently online
  • How recently the user was last active (as seen by the server)
  • Whether a given client considers the user to be currently idle
  • Arbitrary information about the user's current status (e.g. "in a meeting").

This information is collated from both per-device (online, idle, last_active) and per-user (status) data, aggregated by the user's homeserver and transmitted as an m.presence event. This is one of the few events which are sent outside the context of a room. Presence events are sent to all users who subscribe to this user's presence through a presence list or by sharing membership of a room.

A presence list is a list of user IDs whose presence the user wants to follow. To be added to this list, the user being added must be invited by the list owner who must accept the invitation.

User's presence state is represented by the presence key, which is an enum of one of the following:

  • online : The default state when the user is connected to an event stream.
  • unavailable : The user is not reachable at this time e.g. they are idle.
  • offline : The user is not connected to an event stream or is explicitly suppressing their profile information from being sent.

11.6.1   Events

11.6.1.1   m.presence

Informs the client of a user's presence state change.

Content Key Type Description
avatar_url string The current avatar URL for this user, if any.
displayname string The current display name for this user, if any.
last_active_ago number The last time since this used performed some action, in milliseconds.
presence enum Required. The presence state for this user. One of: ["online", "offline", "unavailable"]
currently_active boolean Whether the user is currently active
user_id string Required. The user's ID.

Example:

{
    "content": {
        "avatar_url": "mxc://localhost:wefuiwegh8742w",
        "currently_active": false,
        "last_active_ago": 2478593,
        "presence": "online",
        "user_id": "@example:localhost"
    },
    "event_id": "$WLGTSEFSEF:localhost",
    "type": "m.presence"
}

11.6.2   Client behaviour

Clients can manually set/get their presence/presence list using the HTTP APIs listed below.

11.6.2.1   PUT /_matrix/client/r0/presence/{userId}/status

This API sets the given user's presence state. When setting the status, the activity time is updated to reflect that activity; the client does not need to specify the last_active_ago field. You cannot set the presence state of another user.

Rate-limited:Yes.
Requires auth:Yes.

Request format:

Parameter Type Description
path parameters
userId string Required. The user whose presence state to update.
JSON body parameters
presence enum Required. The new presence state. One of: ["online", "offline", "unavailable"]
status_msg string The status message to attach to this state.

Example request:

PUT /_matrix/client/r0/presence/%40alice%3Aexample.com/status HTTP/1.1
Content-Type: application/json

{
  "presence": "online",
  "status_msg": "I am here."
}

Responses:

Status code 200:

The new presence state was set.

Example

{}

Status code 429:

This request was rate-limited.

Example

{
  "errcode": "string",
  "error": "string"
}

11.6.2.2   GET /_matrix/client/r0/presence/{userId}/status

Get the given user's presence state.

Request format:

Parameter Type Description
path parameters
userId string Required. The user whose presence state to get.

Response format:

Parameter Type Description
presence enum Required. This user's presence. One of: ["online", "offline", "unavailable"]
last_active_ago integer The length of time in milliseconds since an action was performed by this user.
status_msg string or null The state message for this user if one was set.
currently_active boolean Whether the user is currently active

Example request:

GET /_matrix/client/r0/presence/%40alice%3Aexample.com/status HTTP/1.1

Responses:

Status code 200:

The presence state for this user.

Example

{
  "presence": "unavailable",
  "last_active_ago": 420845
}

Status code 404:

There is no presence state for this user. This user may not exist or isn't exposing presence information to you.

11.6.2.3   POST /_matrix/client/r0/presence/list/{userId}

Adds or removes users from this presence list.

Rate-limited:Yes.
Requires auth:Yes.

Request format:

Parameter Type Description
path parameters
userId string Required. The user whose presence list is being modified.
JSON body parameters
invite [string] A list of user IDs to add to the list.
drop [string] A list of user IDs to remove from the list.

Example request:

POST /_matrix/client/r0/presence/list/%40alice%3Aexample.com HTTP/1.1
Content-Type: application/json

{
  "invite": [
    "@bob:matrix.org"
  ],
  "drop": [
    "@alice:matrix.org"
  ]
}

Responses:

Status code 200:

The list was updated.

Example

{}

Status code 429:

This request was rate-limited.

Example

{
  "errcode": "string",
  "error": "string"
}

11.6.2.4   GET /_matrix/client/r0/presence/list/{userId}

Retrieve a list of presence events for every user on this list.

Request format:

Parameter Type Description
path parameters
userId string Required. The user whose presence list should be retrieved.

Response format:

Parameter Type Description
<body> [PresenceEvent]  

PresenceEvent

Parameter Type Description
content object The fields in this object will vary depending on the type of event. When interacting with the REST API, this is the HTTP body.
type string Required. The type of event. This SHOULD be namespaced similar to Java package naming conventions e.g. 'com.example.subdomain.event.type'

Example request:

GET /_matrix/client/r0/presence/list/%40alice%3Aexample.com HTTP/1.1

Response:

Status code 200:

A list of presence events for this list.

Example

[
  {
    "content": {
      "last_active_ago": 395,
      "presence": "offline",
      "user_id": "@alice:matrix.org"
    },
    "type": "m.presence"
  },
  {
    "content": {
      "last_active_ago": 16874,
      "presence": "online",
      "user_id": "@marisa:matrix.org",
      "currently_active": true
    },
    "type": "m.presence"
  }
]

11.6.3   Server behaviour

Each user's homeserver stores a "presence list" per user. Once a user accepts a presence list, both user's HSes must track the subscription.

11.6.3.1   Last active ago

The server maintains a timestamp of the last time it saw a pro-active event from the user. A pro-active event may be sending a message to a room or changing presence state to online. This timestamp is presented via a key called last_active_ago which gives the relative number of milliseconds since the pro-active event.

To reduce the number of presence updates sent to clients the server may include a currently_active boolean field when the presence state is online. When true, the server will not send further updates to the last active time until an update is sent to the client with either a) currently_active set to false or b) a presence state other than online. During this period clients must consider the user to be currently active, irrespective of the last active time.

The last active time must be up to date whenever the server gives a presence event to the client. The currently_active mechanism should purely be used by servers to stop sending continuous presence updates, as opposed to disabling last active tracking entirely. Thus clients can fetch up to date last active times by explicitly requesting the presence for a given user.

11.6.3.2   Idle timeout

The server will automatically set a user's presence to unavailable if their last active time was over a threshold value (e.g. 5 minutes). Clients can manually set a user's presence to unavailable. Any activity that bumps the last active time on any of the user's clients will cause the server to automatically set their presence to online.

11.6.4   Security considerations

Presence information is shared with all users who share a room with the target user. In large public rooms this could be undesirable.

11.7   Content repository

This module allows users to upload content to their homeserver which is retrievable from other homeservers. Its' purpose is to allow users to share attachments in a room. Content locations are represented as Matrix Content (MXC) URIs. They look like:

mxc://<server-name>/<media-id>

<server-name> : The name of the homeserver where this content originated, e.g. matrix.org
<media-id> : An opaque ID which identifies the content.

Uploads are POSTed to a resource on the user's local homeserver which returns a token which is used to GET the download. Content is downloaded from the recipient's local homeserver, which must first transfer the content from the origin homeserver using the same API (unless the origin and destination homeservers are the same).

11.7.1   Client behaviour

Clients can upload and download content using the following HTTP APIs.

11.7.1.1   POST /_matrix/media/r0/upload

Upload some content to the content repository.

Rate-limited:Yes.
Requires auth:Yes.

Request format:

Parameter Type Description
header parameters
Content-Type string The content type of the file being uploaded
query parameters
filename string The name of the file being uploaded

Response format:

Parameter Type Description
content_uri string Required. The MXC URI to the uploaded content.

Example request:

POST /_matrix/media/r0/upload?filename=War+and+Peace.pdf HTTP/1.1
Content-Type: application/json

"<bytes>"

Responses:

Status code 200:

The MXC URI for the uploaded content.

Example

{
  "content_uri": "mxc://example.com/AQwafuaFswefuhsfAFAgsw"
}

Status code 429:

This request was rate-limited.

Example

{
  "errcode": "string",
  "error": "string"
}

11.7.1.2   GET /_matrix/media/r0/download/{serverName}/{mediaId}

Download content from the content repository.

Rate-limited:Yes.

Request format:

Parameter Type Description
path parameters
serverName string Required. The server name from the mxc:// URI (the authoritory component)
mediaId string Required. The media ID from the mxc:// URI (the path component)

Response headers:

Parameter Type Description
Content-Type string The content type of the file that was previously uploaded.
Content-Disposition string The name of the file that was previously uploaded, if set.

Response format:

Parameter Type Description
<body> file  

Example request:

GET /_matrix/media/r0/download/matrix.org/ascERGshawAWawugaAcauga HTTP/1.1

Responses:

Status code 200:

The content that was previously uploaded.

Status code 429:

This request was rate-limited.

Example

{
  "errcode": "string",
  "error": "string"
}

11.7.1.3   GET /_matrix/media/r0/download/{serverName}/{mediaId}/{fileName}

Download content from the content repository as a given filename.

Rate-limited:Yes.

Request format:

Parameter Type Description
path parameters
serverName string Required. The server name from the mxc:// URI (the authoritory component)
mediaId string Required. The media ID from the mxc:// URI (the path component)
fileName string Required. The filename to give in the Content- Disposition

Response headers:

Parameter Type Description
Content-Type string The content type of the file that was previously uploaded.
Content-Disposition string The name of file given in the request

Response format:

Parameter Type Description
<body> file  

Example request:

GET /_matrix/media/r0/download/matrix.org/ascERGshawAWawugaAcauga/filename.jpg HTTP/1.1

Responses:

Status code 200:

The content that was previously uploaded.

Status code 429:

This request was rate-limited.

Example

{
  "errcode": "string",
  "error": "string"
}

11.7.1.4   GET /_matrix/media/r0/thumbnail/{serverName}/{mediaId}

Download a thumbnail of the content from the content repository.

Rate-limited:Yes.

Request format:

Parameter Type Description
path parameters
serverName string Required. The server name from the mxc:// URI (the authoritory component)
mediaId string Required. The media ID from the mxc:// URI (the path component)
query parameters
width integer The desired width of the thumbnail. The actual thumbnail may not match the size specified.
height integer The desired height of the thumbnail. The actual thumbnail may not match the size specified.
method enum The desired resizing method. One of: ["crop", "scale"]

Response headers:

Parameter Type Description
Content-Type string The content type of the thumbnail.

Response format:

Parameter Type Description
<body> file  

Example request:

GET /_matrix/media/r0/thumbnail/matrix.org/ascERGshawAWawugaAcauga?width=64&height=64&method=scale HTTP/1.1

Responses:

Status code 200:

A thumbnail of the requested content.

Status code 429:

This request was rate-limited.

Example

{
  "errcode": "string",
  "error": "string"
}

11.7.1.5   GET /_matrix/media/r0/preview_url

Get information about a URL for a client

Rate-limited:Yes.
Requires auth:Yes.

Request format:

Parameter Type Description
query parameters
url string Required. The URL to get a preview of
ts number The preferred point in time to return a preview for. The server may return a newer version if it does not have the requested version available.

Response format:

Parameter Type Description
matrix:image:size number The byte-size of the image. Omitted if there is no image attached.
og:image string An MXC URI to the image. Ommitted if there is no image.

Example request:

GET /_matrix/media/r0/preview_url?url=https%3A%2F%2Fmatrix.org&ts=1510610716656 HTTP/1.1

Responses:

Status code 200:

The OpenGraph data for the URL, which may be empty. Some values are replaced with matrix equivalents if they are provided in the response. The differences from the OpenGraph protocol are described here.

Example

{
  "og:title": "Matrix Blog Post",
  "og:description": "This is a really cool blog post from matrix.org",
  "og:image": "mxc://example.com/ascERGshawAWawugaAcauga",
  "og:image:type": "image/png",
  "og:image:height": 48,
  "og:image:width": 48,
  "matrix:image:size": 102400
}

Status code 429:

This request was rate-limited.

Example

{
  "errcode": "string",
  "error": "string"
}

11.7.1.6   Thumbnails

The thumbnail methods are "crop" and "scale". "scale" tries to return an image where either the width or the height is smaller than the requested size. The client should then scale and letterbox the image if it needs to fit within a given rectangle. "crop" tries to return an image where the width and height are close to the requested size and the aspect matches the requested size. The client should scale the image if it needs to fit within a given rectangle.

In summary:
  • "scale" maintains the original aspect ratio of the image
  • "crop" provides an image in the aspect ratio of the sizes given in the request

11.7.2   Server behaviour

Homeservers may generate thumbnails for content uploaded to remote homeservers themselves or may rely on the remote homeserver to thumbnail the content. Homeservers may return thumbnails of a different size to that requested. However homeservers should provide exact matches where reasonable. Homeservers must never upscale images.

11.7.3   Security considerations

The HTTP GET endpoint does not require any authentication. Knowing the URL of the content is sufficient to retrieve the content, even if the entity isn't in the room.

MXC URIs are vulnerable to directory traversal attacks such as mxc://127.0.0.1/../../../some_service/etc/passwd. This would cause the target homeserver to try to access and return this file. As such, homeservers MUST sanitise MXC URIs by allowing only alphanumeric (A-Za-z0-9), _ and - characters in the server-name and media-id values. This set of whitelisted characters allows URL-safe base64 encodings specified in RFC 4648. Applying this character whitelist is preferable to blacklisting . and / as there are techniques around blacklisted characters (percent-encoded characters, UTF-8 encoded traversals, etc).

Homeservers have additional content-specific concerns:

  • Clients may try to upload very large files. Homeservers should not store files that are too large and should not serve them to clients.
  • Clients may try to upload very large images. Homeservers should not attempt to generate thumbnails for images that are too large.
  • Remote homeservers may host very large files or images. Homeservers should not proxy or thumbnail large files or images from remote homeservers.
  • Clients may try to upload a large number of files. Homeservers should limit the number and total size of media that can be uploaded by clients.
  • Clients may try to access a large number of remote files through a homeserver. Homeservers should restrict the number and size of remote files that it caches.
  • Clients or remote homeservers may try to upload malicious files targeting vulnerabilities in either the homeserver thumbnailing or the client decoders.

11.8   Send-to-Device messaging

This module provides a means by which clients can exchange signalling messages without them being stored permanently as part of a shared communication history. A message is delivered exactly once to each client device.

The primary motivation for this API is exchanging data that is meaningless or undesirable to persist in the room DAG - for example, one-time authentication tokens or key data. It is not intended for conversational data, which should be sent using the normal /rooms/<room_id>/send API for consistency throughout Matrix.

11.8.1   Client behaviour

To send a message to other devices, a client should call /sendToDevice. Only one message can be sent to each device per transaction, and they must all have the same event type. The device ID in the request body can be set to * to request that the message be sent to all known devices.

If there are send-to-device messages waiting for a client, they will be returned by /sync, as detailed in Extensions to /sync. Clients should inspect the type of each returned event, and ignore any they do not understand.

11.8.2   Server behaviour

Servers should store pending messages for local users until they are successfully delivered to the destination device. When a client calls /sync with an access token which corresponds to a device with pending messages, the server should list the pending messages, in order of arrival, in the response body.

When the client calls /sync again with the next_batch token from the first response, the server should infer that any send-to-device messages in that response have been delivered successfully, and delete them from the store.

If there is a large queue of send-to-device messages, the server should limit the number sent in each /sync response. 100 messages is recommended as a reasonable limit.

If the client sends messages to users on remote domains, those messages should be sent on to the remote servers via federation.

11.8.3   Protocol definitions

11.8.3.1   PUT /_matrix/client/r0/sendToDevice/{eventType}/{txnId}

This endpoint is used to send send-to-device events to a set of client devices.

Requires auth:Yes.

Request format:

Parameter Type Description
path parameters
eventType string Required. The type of event to send.
txnId string Required. The transaction ID for this event. Clients should generate an ID unique across requests with the same access token; it will be used by the server to ensure idempotency of requests.
JSON body parameters
messages {string: {string: EventContent}} The messages to send. A map from user ID, to a map from device ID to message body. The device ID may also be *, meaning all known devices for the user.

Example request:

PUT /_matrix/client/r0/sendToDevice/m.new_device/35 HTTP/1.1
Content-Type: application/json

{
  "messages": {
    "@alice:example.com": {
      "TLLBEANAAG": {
        "example_content_key": "value"
      }
    }
  }
}

Response:

Status code 200:

The message was successfully sent.

Example

{}

11.8.3.2   Extensions to /sync

This module adds the following properties to the /sync response:

Parameter Type Description
to_device ToDevice Optional. Information on the send-to-device messages for the client device.

ToDevice

Parameter Type Description
events [Event] List of send-to-device messages

Event

Parameter Type Description
content EventContent The content of this event. The fields in this object will vary depending on the type of event.
sender string The Matrix user ID of the user who sent this event.
type string The type of event.

Example response:

{
  "next_batch": "s72595_4483_1934",
  "rooms": {"leave": {}, "join": {}, "invite": {}},
  "to_device": {
    "events": [
      {
        "sender": "@alice:example.com",
        "type": "m.new_device",
        "content": {
          "device_id": "XYZABCDE",
          "rooms": ["!726s6s6q:example.com"]
        }
      }
    ]
  }
}

11.9   Device Management

This module provides a means for a user to manage their devices.

11.9.1   Client behaviour

Clients that implement this module should offer the user a list of registered devices, as well as the means to update their display names. Clients should also allow users to delete disused devices.

11.9.1.1   GET /_matrix/client/r0/devices

Gets information about all devices for the current user.

Requires auth:Yes.

Request format:

No parameters

Response format:

Parameter Type Description
devices [Device] A list of all registered devices for this user.

Device

Parameter Type Description
device_id string Required. Identifier of this device.
display_name string Display name set by the user for this device. Absent if no name has been set.
last_seen_ip string The IP address where this device was last seen. (May be a few minutes out of date, for efficiency reasons).
last_seen_ts integer The timestamp (in milliseconds since the unix epoch) when this devices was last seen. (May be a few minutes out of date, for efficiency reasons).

Example request:

GET /_matrix/client/r0/devices HTTP/1.1

Response:

Status code 200:

Device information

Example

{
  "devices": [
    {
      "device_id": "QBUAZIFURK",
      "display_name": "android",
      "last_seen_ip": "1.2.3.4",
      "last_seen_ts": 1474491775024
    }
  ]
}

11.9.1.2   GET /_matrix/client/r0/devices/{deviceId}

Gets information on a single device, by device id.

Requires auth:Yes.

Request format:

Parameter Type Description
path parameters
deviceId string Required. The device to retrieve.

Response format:

Device

Parameter Type Description
device_id string Required. Identifier of this device.
display_name string Display name set by the user for this device. Absent if no name has been set.
last_seen_ip string The IP address where this device was last seen. (May be a few minutes out of date, for efficiency reasons).
last_seen_ts integer The timestamp (in milliseconds since the unix epoch) when this devices was last seen. (May be a few minutes out of date, for efficiency reasons).

Example request:

GET /_matrix/client/r0/devices/QBUAZIFURK HTTP/1.1

Responses:

Status code 200:

Device information

Example

{
  "device_id": "QBUAZIFURK",
  "display_name": "android",
  "last_seen_ip": "1.2.3.4",
  "last_seen_ts": 1474491775024
}

Status code 404:

The current user has no device with the given ID.

11.9.1.3   PUT /_matrix/client/r0/devices/{deviceId}

Updates the metadata on the given device.

Requires auth:Yes.

Request format:

Parameter Type Description
path parameters
deviceId string Required. The device to update.
JSON body parameters
display_name string The new display name for this device. If not given, the display name is unchanged.

Example request:

PUT /_matrix/client/r0/devices/QBUAZIFURK HTTP/1.1
Content-Type: application/json

{
  "display_name": "My other phone"
}

Responses:

Status code 200:

The device was successfully updated.

Example

{}

Status code 404:

The current user has no device with the given ID.

11.9.1.4   DELETE /_matrix/client/r0/devices/{deviceId}

This API endpoint uses the User-Interactive Authentication API.

Deletes the given device, and invalidates any access token assoicated with it.

Requires auth:Yes.

Request format:

Parameter Type Description
path parameters
deviceId string Required. The device to delete.
JSON body parameters
auth Authentication Data Additional authentication information for the user-interactive authentication API.

Authentication Data

Parameter Type Description
type string Required. The login type that the client is attempting to complete.
session string The value of the session key given by the homeserver.

Example request:

DELETE /_matrix/client/r0/devices/QBUAZIFURK HTTP/1.1
Content-Type: application/json

{
  "auth": {
    "type": "example.type.foo",
    "session": "xxxxx",
    "example_credential": "verypoorsharedsecret"
  }
}

Responses:

Status code 200:

The device was successfully removed, or had been removed previously.

Example

{}

Status code 401:

The homeserver requires additional authentication information.

Example

{
  "flows": [
    {
      "stages": [
        "example.type.foo"
      ]
    }
  ],
  "params": {
    "example.type.baz": {
      "example_key": "foobar"
    }
  },
  "session": "xxxxxxyz",
  "completed": [
    "example.type.foo"
  ]
}

11.9.2   Security considerations

Deleting devices has security implications: it invalidates the access_token assigned to the device, so an attacker could use it to log out the real user (and do it repeatedly every time the real user tries to log in to block the attacker). Servers should require additional authentication beyond the access token when deleting devices (for example, requiring that the user resubmit their password).

The display names of devices are publicly visible. Clients should consider advising the user of this.

11.10   End-to-End Encryption

Matrix optionally supports end-to-end encryption, allowing rooms to be created whose conversation contents is not decryptable or interceptable on any of the participating homeservers.

Warning

End to end encryption is being worked on and will be coming soon. This section is incomplete. You can read more about what's underway at http://matrix.org/speculator/spec/drafts%2Fe2e/client_server/unstable.html#end-to-end-encryption.

11.10.1   Key Distribution

Encryption and Authentication in Matrix is based around public-key cryptography. The Matrix protocol provides a basic mechanism for exchange of public keys, though an out-of-band channel is required to exchange fingerprints between users to build a web of trust.

11.10.1.1   Overview

1) Bob publishes the public keys and supported algorithms for his
   device. This may include long-term identity keys, and/or one-time
   keys.

                                      +----------+  +--------------+
                                      | Bob's HS |  | Bob's Device |
                                      +----------+  +--------------+
                                            |              |
                                            |<=============|
                                              /keys/upload

2) Alice requests Bob's public identity keys and supported algorithms.

  +----------------+  +------------+  +----------+
  | Alice's Device |  | Alice's HS |  | Bob's HS |
  +----------------+  +------------+  +----------+
         |                  |               |
         |=================>|==============>|
           /keys/query        <federation>

3) Alice selects an algorithm and claims any one-time keys needed.

  +----------------+  +------------+  +----------+
  | Alice's Device |  | Alice's HS |  | Bob's HS |
  +----------------+  +------------+  +----------+
         |                  |               |
         |=================>|==============>|
           /keys/claim         <federation>

11.10.1.2   Key algorithms

The name ed25519 corresponds to the Ed25519 signature algorithm. The key is a 32-byte Ed25519 public key, encoded using unpadded Base64. Example:

"SogYyrkTldLz0BXP+GYWs0qaYacUI0RleEqNT8J3riQ"

The name curve25519 corresponds to the Curve25519 ECDH algorithm. The key is a 32-byte Curve25519 public key, encoded using unpadded Base64. Example:

"JGLn/yafz74HB2AbPLYJWIVGnKAtqECOBf11yyXac2Y"

The name signed_curve25519 also corresponds to the Curve25519 algorithm, but keys using this algorithm are objects with the properties key (giving the Base64-encoded 32-byte Curve25519 public key), and signatures (giving a signature for the key object, as described in Signing JSON). Example:

{
  "key":"06UzBknVHFMwgi7AVloY7ylC+xhOhEX4PkNge14Grl8",
  "signatures": {
    "@user:example.com": {
      "ed25519:EGURVBUNJP": "YbJva03ihSj5mPk+CHMJKUKlCXCPFXjXOK6VqBnN9nA2evksQcTGn6hwQfrgRHIDDXO2le49x7jnWJHMJrJoBQ"
    }
  }
}

11.10.1.3   Device keys

Each device should have one Ed25519 signing key. This key should be generated on the device from a cryptographically secure source, and the private part of the key should never be exported from the device. This key is used as the fingerprint for a device by other clients.

A device will generally need to generate a number of additional keys. Details of these will vary depending on the messaging algorithm in use.

Algorithms generally require device identity keys as well as signing keys. Some algorithms also require one-time keys to improve their secrecy and deniability. These keys are used once during session establishment, and are then thrown away.

For Olm version 1, each device requires a single Curve25519 identity key, and a number of signed Curve25519 one-time keys.

11.10.1.4   Uploading keys

A device uploads the public parts of identity keys to their homeserver as a signed JSON object, using the /keys/upload API. The JSON object must include the public part of the device's Ed25519 key, and must be signed by that key, as described in Signing JSON.

One-time keys are also uploaded to the homeserver using the /keys/upload API.

Devices must store the private part of each key they upload. They can discard the private part of a one-time key when they receive a message using that key. However it's possible that a one-time key given out by a homeserver will never be used, so the device that generates the key will never know that it can discard the key. Therefore a device could end up trying to store too many private keys. A device that is trying to store too many private keys may discard keys starting with the oldest.

11.10.1.5   Tracking the device list for a user

Before Alice can send an encrypted message to Bob, she needs a list of each of his devices and the associated identity keys, so that she can establish an encryption session with each device. This list can be obtained by calling /keys/query, passing Bob's user ID in the device_keys parameter.

From time to time, Bob may add new devices, and Alice will need to know this so that she can include his new devices for later encrypted messages. A naive solution to this would be to call /keys/query before sending each message - however, the number of users and devices may be large and this would be inefficient.

It is therefore expected that each client will maintain a list of devices for a number of users (in practice, typically each user with whom we share an encrypted room). Furthermore, it is likely that this list will need to be persisted between invocations of the client application (to preserve device verification data and to alert Alice if Bob suddently gets a new device).

Alice's client can maintain a list of Bob's devices via the following process:

  1. It first sets a flag to record that it is now tracking Bob's device list, and a separate flag to indicate that its list of Bob's devices is outdated. Both flags should be in storage which persists over client restarts.
  2. It then makes a request to /keys/query, passing Bob's user ID in the device_keys parameter. When the request completes, it stores the resulting list of devices in persistent storage, and clears the 'outdated' flag.
  3. During its normal processing of responses to /sync, Alice's client inspects the device_lists field. If it is tracking the device lists of any of the listed users, then it marks the device lists for those users outdated, and initiates another request to /keys/query for them.
  4. Periodically, Alice's client stores the next_batch field of the result from /sync in persistent storage. If Alice later restarts her client, it can obtain a list of the users who have updated their device list while it was offline by calling /keys/changes, passing the recorded next_batch field as the from parameter. If the client is tracking the device list of any of the users listed in the response, it marks them as outdated. It combines this list with those already flagged as outdated, and initiates a /keys/query requests for all of them.

Warning

Bob may update one of his devices while Alice has a request to /keys/query in flight. Alice's client may therefore see Bob's user ID in the device_lists field of the /sync response while the first request is in flight, and initiate a second request to /keys/query. This may lead to either of two related problems.

The first problem is that, when the first request completes, the client will clear the 'outdated' flag for Bob's devices. If the second request fails, or the client is shut down before it completes, this could lead to Alice using an outdated list of Bob's devices.

The second possibility is that, under certain conditions, the second request may complete before the first one. When the first request completes, the client could overwrite the later results from the second request with those from the first request.

Clients MUST guard against these situations. For example, a client could ensure that only one request to /keys/query is in flight at a time for each user, by queuing additional requests until the first completes. Alternatively, the client could make a new request immediately, but ensure that the first request's results are ignored (possibly by cancelling the request).

11.10.1.6   Claiming one-time keys

A client wanting to set up a session with another device can claim a one-time key for that device. This is done by making a request to the /keys/claim API.

A homeserver should rate-limit the number of one-time keys that a given user or remote server can claim. A homeserver should discard the public part of a one time key once it has given that key to another user.

11.10.2   Protocol definitions

11.10.2.1   POST /_matrix/client/r0/keys/upload

Publishes end-to-end encryption keys for the device.

Requires auth:Yes.

Request format:

Parameter Type Description
JSON body parameters
device_keys DeviceKeys Identity keys for the device. May be absent if no new identity keys are required.
one_time_keys {string: string or object}

One-time public keys for "pre-key" messages. The names of the properties should be in the format <algorithm>:<key_id>. The format of the key is determined by the key algorithm.

May be absent if no new one-time keys are required.

DeviceKeys

Parameter Type Description
user_id string Required. The ID of the user the device belongs to. Must match the user ID used when logging in.
device_id string Required. The ID of the device these keys belong to. Must match the device ID used when logging in.
algorithms [string] Required. The encryption algorithms supported by this device.
keys {string: string} Required. Public identity keys. The names of the properties should be in the format <algorithm>:<device_id>. The keys themselves should be encoded as specified by the key algorithm.
signatures {string: {string: string}}

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

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

Response format:

Parameter Type Description
one_time_key_counts {string: integer} Required. For each key algorithm, the number of unclaimed one-time keys of that type currently held on the server for this device.

Example request:

POST /_matrix/client/r0/keys/upload HTTP/1.1
Content-Type: application/json

{
  "device_keys": {
    "user_id": "@alice:example.com",
    "device_id": "JLAFKJWSCS",
    "algorithms": [
      "m.olm.curve25519-aes-sha256",
      "m.megolm.v1.aes-sha"
    ],
    "keys": {
      "curve25519:JLAFKJWSCS": "3C5BFWi2Y8MaVvjM8M22DBmh24PmgR0nPvJOIArzgyI",
      "ed25519:JLAFKJWSCS": "lEuiRJBit0IG6nUf5pUzWTUEsRVVe/HJkoKuEww9ULI"
    },
    "signatures": {
      "@alice:example.com": {
        "ed25519:JLAFKJWSCS": "dSO80A01XiigH3uBiDVx/EjzaoycHcjq9lfQX0uWsqxl2giMIiSPR8a4d291W1ihKJL/a+myXS367WT6NAIcBA"
      }
    }
  },
  "one_time_keys": {
    "curve25519:AAAAAQ": "/qyvZvwjiTxGdGU0RCguDCLeR+nmsb3FfNG3/Ve4vU8",
    "signed_curve25519:AAAAHg": {
      "key": "zKbLg+NrIjpnagy+pIY6uPL4ZwEG2v+8F9lmgsnlZzs",
      "signatures": {
        "@alice:example.com": {
          "ed25519:JLAFKJWSCS": "FLWxXqGbwrb8SM3Y795eB6OA8bwBcoMZFXBqnTn58AYWZSqiD45tlBVcDa2L7RwdKXebW/VzDlnfVJ+9jok1Bw"
        }
      }
    },
    "signed_curve25519:AAAAHQ": {
      "key": "j3fR3HemM16M7CWhoI4Sk5ZsdmdfQHsKL1xuSft6MSw",
      "signatures": {
        "@alice:example.com": {
          "ed25519:JLAFKJWSCS": "IQeCEPb9HFk217cU9kw9EOiusC6kMIkoIRnbnfOh5Oc63S1ghgyjShBGpu34blQomoalCyXWyhaaT3MrLZYQAA"
        }
      }
    }
  }
}

Response:

Status code 200:

The provided keys were sucessfully uploaded.

Example

{
  "one_time_key_counts": {
    "curve25519": 10,
    "signed_curve25519": 20
  }
}

11.10.2.2   POST /_matrix/client/r0/keys/query

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

Requires auth:Yes.

Request format:

Parameter Type Description
JSON body parameters
timeout integer The time (in milliseconds) to wait when downloading keys from remote servers. 10 seconds is the recommended default.
device_keys {string: [string]} Required. The keys to be downloaded. A map from user ID, to a list of device IDs, or to an empty list to indicate all devices for the corresponding user.

Response format:

Parameter Type Description
failures {string: object}

If any remote homeservers could not be reached, they are recorded here. The names of the properties are the names of the unreachable servers.

If the homeserver could be reached, but the user or device was unknown, no failure is recorded. Instead, the corresponding user or device is missing from the device_keys result.

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

DeviceKeys

Parameter Type Description
user_id string Required. The ID of the user the device belongs to. Must match the user ID used when logging in.
device_id string Required. The ID of the device these keys belong to. Must match the device ID used when logging in.
algorithms [string] Required. The encryption algorithms supported by this device.
keys {string: string} Required. Public identity keys. The names of the properties should be in the format <algorithm>:<device_id>. The keys themselves should be encoded as specified by the key algorithm.
signatures {string: {string: string}}

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

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

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

UnsignedDeviceInfo

Parameter Type Description
device_display_name string The display name which the user set on the device.

Example request:

POST /_matrix/client/r0/keys/query HTTP/1.1
Content-Type: application/json

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

Response:

Status code 200:

The device information

Example

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

11.10.2.3   POST /_matrix/client/r0/keys/claim

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

Requires auth:Yes.

Request format:

Parameter Type Description
JSON body parameters
timeout integer The time (in milliseconds) to wait when downloading keys from remote servers. 10 seconds is the recommended default.
one_time_keys {string: {string: string}} Required. The keys to be claimed. A map from user ID, to a map from device ID to algorithm name.

Response format:

Parameter Type Description
failures {string: object}

If any remote homeservers could not be reached, they are recorded here. The names of the properties are the names of the unreachable servers.

If the homeserver could be reached, but the user or device was unknown, no failure is recorded. Instead, the corresponding user or device is missing from the one_time_keys result.

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

Example request:

POST /_matrix/client/r0/keys/claim HTTP/1.1
Content-Type: application/json

{
  "timeout": 10000,
  "one_time_keys": {
    "@alice:example.com": {
      "JLAFKJWSCS": "curve25519"
    }
  }
}

Response:

Status code 200:

The claimed keys

Example

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

11.10.2.4   GET /_matrix/client/r0/keys/changes

Gets a list of users who have updated their device identity keys since a previous sync token.

The server should include in the results any users who:

  • currently share a room with the calling user (ie, both users have membership state join); and
  • added new device identity keys or removed an existing device with identity keys, between from and to.
Requires auth:Yes.

Request format:

Parameter Type Description
query parameters
from string Required. The desired start point of the list. Should be the next_batch field from a response to an earlier call to /sync. Users who have not uploaded new device identity keys since this point, nor deleted existing devices with identity keys since then, will be excluded from the results.
to string Required. The desired end point of the list. Should be the next_batch field from a recent call to /sync - typically the most recent such call. This may be used by the server as a hint to check its caches are up to date.

Response format:

Parameter Type Description
changes [string] The Matrix User IDs of all users who updated their device identity keys.

Example request:

GET /_matrix/client/r0/keys/changes?from=s72594_4483_1934&to=s75689_5632_2435 HTTP/1.1

Response:

Status code 200:

The list of users who updated their devices.

Example

{
  "changes": [
    "@alice:example.com",
    "@bob:example.org"
  ]
}

11.10.2.5   Extensions to /sync

This module adds an optional device_lists property to the /sync response, as specified below. The server need only populate this property for an incremental /sync (ie, one where the since parameter was specified). The client is expected to use /keys/query or /keys/changes for the equivalent functionality after an initial sync, as documented in Tracking the device list for a user.

Parameter Type Description
device_lists DeviceLists Optional. Information on e2e device updates. Note: only present on an incremental sync.

DeviceLists

Parameter Type Description
changed [string] List of users who have updated their device identity keys since the previous sync response.

Example response:

{
  "next_batch": "s72595_4483_1934",
  "rooms": {"leave": {}, "join": {}, "invite": {}},
  "device_lists": {
    "changed": [
       "@alice:example.com",
    ],
  },
}

11.11   Room History Visibility

This module adds support for controlling the visibility of previous events in a room.

In all cases except world_readable, a user needs to join a room to view events in that room. Once they have joined a room, they will gain access to a subset of events in the room. How this subset is chosen is controlled by the m.room.history_visibility event outlined below. After a user has left a room, they may see any events which they were allowed to see before they left the room, but no events received after they left.

The four options for the m.room.history_visibility event are:

  • world_readable - All events while this is the m.room.history_visibility value may be shared by any participating homeserver with anyone, regardless of whether they have ever joined the room.
  • shared - Previous events are always accessible to newly joined members. All events in the room are accessible, even those sent when the member was not a part of the room.
  • invited - Events are accessible to newly joined members from the point they were invited onwards. Events stop being accessible when the member's state changes to something other than invite or join.
  • joined - Events are accessible to newly joined members from the point they joined the room onwards. Events stop being accessible when the member's state changes to something other than join.

Warning

These options are applied at the point an event is sent. Checks are performed with the state of the m.room.history_visibility event when the event in question is added to the DAG. This means clients cannot retrospectively choose to show or hide history to new users if the setting at that time was more restrictive.

11.11.1   Events

11.11.1.1   m.room.history_visibility

State Event
state_key: A zero-length string.

This event controls whether a user can see the events that happened in a room from before they joined.

Content Key Type Description
history_visibility enum Required. Who can see the room history. One of: ["invited", "joined", "shared", "world_readable"]

Example:

{
    "age": 242352,
    "content": {
        "history_visibility": "shared"
    },
    "event_id": "$WLGTSEFSEF:localhost",
    "origin_server_ts": 1431961217939,
    "room_id": "!Cuyf34gef24t:localhost",
    "sender": "@example:localhost",
    "state_key": "",
    "type": "m.room.history_visibility"
}

11.11.2   Client behaviour

Clients that implement this module MUST present to the user the possible options for setting history visibility when creating a room.

Clients may want to display a notice that their events may be read by non-joined people if the value is set to world_readable.

11.11.3   Server behaviour

By default if no history_visibility is set, or if the value is not understood, the visibility is assumed to be shared. The rules governing whether a user is allowed to see an event depend on the state of the room at that event.

  1. If the history_visibility was set to world_readable, allow.
  2. If the user's membership was join, allow.
  3. If history_visibility was set to shared, and the user joined the room at any point after the event was sent, allow.
  4. If the user's membership was invite, and the history_visibility was set to invited, allow.
  5. Otherwise, deny.

For m.room.history_visibility events themselves, the user should be allowed to see the event if the history_visibility before or after the event would allow them to see it. (For example, a user should be able to see m.room.history_visibility events which change the history_visibility from world_readable to joined or from joineded to world_readable, even if that user was not a member of the room.)

Likewise, for the user's own m.room.member events, the user should be allowed to see the event if their membership before or after the event would allow them to see it. (For example, a user can always see m.room.member events which set their membership to join, or which change their membership from join to any other value, even if history_visibility is joined.)

11.11.4   Security considerations

The default value for history_visibility is shared for backwards-compatibility reasons. Clients need to be aware that by not setting this event they are exposing all of their room history to anyone in the room.

11.12   Push Notifications

                                  +--------------------+  +-------------------+
                 Matrix HTTP      |                    |  |                   |
            Notification Protocol |   App Developer    |  |   Device Vendor   |
                                  |                    |  |                   |
          +-------------------+   | +----------------+ |  | +---------------+ |
          |                   |   | |                | |  | |               | |
          | Matrix homeserver +----->  Push Gateway  +------> Push Provider | |
          |                   |   | |                | |  | |               | |
          +-^-----------------+   | +----------------+ |  | +----+----------+ |
            |                     |                    |  |      |            |
   Matrix   |                     |                    |  |      |            |
Client/Server API  +              |                    |  |      |            |
            |      |              +--------------------+  +-------------------+
            |   +--+-+                                           |
            |   |    <-------------------------------------------+
            +---+    |
                |    |          Provider Push Protocol
                +----+

        Mobile Device or Client

This module adds support for push notifications. Homeservers send notifications of events to user-configured HTTP endpoints. Users may also configure a number of rules that determine which events generate notifications. These are all stored and managed by the user's homeserver. This allows user-specific push settings to be reused between client applications.

The above diagram shows the flow of push notifications being sent to a handset where push notifications are submitted via the handset vendor, such as Apple's APNS or Google's GCM. This happens as follows:

  1. The client app signs in to a homeserver.
  2. The client app registers with its vendor's Push Provider and obtains a routing token of some kind.
  3. The mobile app uses the Client/Server API to add a 'pusher', providing the URL of a specific Push Gateway which is configured for that application. It also provides the routing token it has acquired from the Push Provider.
  4. The homeserver starts sending HTTP requests to the Push Gateway using the supplied URL. The Push Gateway relays this notification to the Push Provider, passing the routing token along with any necessary private credentials the provider requires to send push notifications.
  5. The Push Provider sends the notification to the device.

Definitions for terms used in this section are below:

Push Provider
A push provider is a service managed by the device vendor which can send notifications directly to the device. Google Cloud Messaging (GCM) and Apple Push Notification Service (APNS) are two examples of push providers.
Push Gateway
A push gateway is a server that receives HTTP event notifications from homeservers and passes them on to a different protocol such as APNS for iOS devices or GCM for Android devices. Clients inform the homeserver which Push Gateway to send notifications to when it sets up a Pusher.
Pusher
A pusher is a worker on the homeserver that manages the sending of HTTP notifications for a user. A user can have multiple pushers: one per device.
Push Rule
A push rule is a single rule that states under what conditions an event should be passed onto a push gateway and how the notification should be presented. These rules are stored on the user's homeserver. They are manually configured by the user, who can create and view them via the Client/Server API.
Push Ruleset
A push ruleset scopes a set of rules according to some criteria. For example, some rules may only be applied for messages from a particular sender, a particular room, or by default. The push ruleset contains the entire set of scopes and rules.

11.12.1   Client behaviour

Clients MUST configure a Pusher before they will receive push notifications. There is a single API endpoint for this, as described below.

11.12.1.1   GET /_matrix/client/r0/pushers

Gets all currently active pushers for the authenticated user

Requires auth:Yes.

Request format:

No parameters

Response format:

Parameter Type Description
pushers [Pusher] An array containing the current pushers for the user

Pusher

Parameter Type Description
pushkey string This is a unique identifier for this pusher. See /set for more detail. Max length, 512 bytes.
kind string The kind of pusher. "http" is a pusher that sends HTTP pokes.
app_id string This is a reverse-DNS style identifier for the application. Max length, 64 chars.
app_display_name string A string that will allow the user to identify what application owns this pusher.
device_display_name string A string that will allow the user to identify what device owns this pusher.
profile_tag string This string determines which set of device specific rules this pusher executes.
lang string The preferred language for receiving notifications (e.g. 'en' or 'en-US')
data PusherData A dictionary of information for the pusher implementation itself.

PusherData

Parameter Type Description
url string Required if kind is http. The URL to use to send notifications to.

Example request:

GET /_matrix/client/r0/pushers HTTP/1.1

Response:

Status code 200:

The pushers for this user

Example

{
  "pushers": [
    {
      "pushkey": "Xp/MzCt8/9DcSNE9cuiaoT5Ac55job3TdLSSmtmYl4A=",
      "kind": "http",
      "app_id": "face.mcapp.appy.prod",
      "app_display_name": "Appy McAppface",
      "device_display_name": "Alice's Phone",
      "profile_tag": "xyz",
      "lang": "en-US",
      "data": {
        "url": "https://example.com/_matrix/push/v1/notify"
      }
    }
  ]
}

11.12.1.2   POST /_matrix/client/r0/pushers/set

This endpoint allows the creation, modification and deletion of pushers for this user ID. The behaviour of this endpoint varies depending on the values in the JSON body.

Rate-limited:Yes.
Requires auth:Yes.

Request format:

Parameter Type Description
JSON body parameters
pushkey string Required. This is a unique identifier for this pusher. The value you should use for this is the routing or destination address information for the notification, for example, the APNS token for APNS or the Registration ID for GCM. If your notification client has no such concept, use any unique identifier. Max length, 512 bytes.
kind string Required. The kind of pusher to configure. "http" makes a pusher that sends HTTP pokes. null deletes the pusher.
app_id string Required. This is a reverse-DNS style identifier for the application. It is recommended that this end with the platform, such that different platform versions get different app identifiers. Max length, 64 chars.
app_display_name string Required. A string that will allow the user to identify what application owns this pusher.
device_display_name string Required. A string that will allow the user to identify what device owns this pusher.
profile_tag string This string determines which set of device specific rules this pusher executes.
lang string Required. The preferred language for receiving notifications (e.g. 'en' or 'en-US')
data PusherData Required. A dictionary of information for the pusher implementation itself. If kind is http, this should contain url which is the URL to use to send notifications to.
append boolean 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 homeserver must remove any other pushers with the same App ID and pushkey for different users. The default is false.

PusherData

Parameter Type Description
url string Required if kind is http. The URL to use to send notifications to.

Example request:

POST /_matrix/client/r0/pushers/set HTTP/1.1
Content-Type: application/json

{
  "lang": "en",
  "kind": "http",
  "app_display_name": "Mat Rix",
  "device_display_name": "iPhone 9",
  "profile_tag": "xxyyzz",
  "app_id": "com.example.app.ios",
  "pushkey": "APA91bHPRgkF3JUikC4ENAHEeMrd41Zxv3hVZjC9KtT8OvPVGJ-hQMRKRrZuJAEcl7B338qju59zJMjw2DELjzEvxwYv7hH5Ynpc1ODQ0aT4U4OFEeco8ohsN5PjL1iC2dNtk2BAokeMCg2ZXKqpc8FXKmhX94kIxQ",
  "data": {
    "url": "https://push-gateway.location.here"
  },
  "append": false
}

Responses:

Status code 200:

The pusher was set.

Example

{}

Status code 400:

One or more of the pusher values were invalid.

Example

{
  "error": "Missing parameters: lang, data",
  "errcode": "M_MISSING_PARAM"
}

Status code 429:

This request was rate-limited.

Example

{
  "errcode": "string",
  "error": "string"
}

11.12.1.3   Listing Notifications

A client can retrieve a list of events that it has been notified about. This may be useful so that users can see a summary of what important messages they have received.

11.12.1.3.1   GET /_matrix/client/r0/notifications

This API is used to paginate through the list of events that the user has been, or would have been notified about.

Requires auth:Yes.

Request format:

Parameter Type Description
query parameters
from string Pagination token given to retrieve the next set of events.
limit number Limit on the number of events to return in this request.
only string Allows basic filtering of events returned. Supply highlight to return only events where the notification had the highlight tweak set.

Response format:

Parameter Type Description
next_token string The token to supply in the from param of the next /notifications request in order to request more events. If this is absent, there are no more results.
notifications [Notification] Required. The list of events that triggered notifications.

Notification

Parameter Type Description
actions [object or string] Required. The action(s) to perform when the conditions for this rule are met. See Push Rules: API.
event Event Required. The Event object for the event that triggered the notification.
profile_tag string The profile tag of the rule that matched this event.
read boolean Required. Indicates whether the user has sent a read receipt indicating that they have read this message.
room_id string Required. The ID of the room in which the event was posted.
ts integer Required. The unix timestamp at which the event notification was sent, in milliseconds.

Event

Parameter Type Description
event_id string The ID of this event, if applicable.
content EventContent The content of this event. The fields in this object will vary depending on the type of event.
origin_server_ts integer Timestamp in milliseconds on originating homeserver when this event was sent.
sender string The MXID of the user who sent this event.
state_key string 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 The type of event.
unsigned Unsigned Information about this event which was not sent by the originating homeserver

Unsigned

Parameter Type Description
age integer Time in milliseconds since the event was sent.
prev_content EventContent 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.
transaction_id string 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.
redacted_because Event Optional. The event that redacted this event, if any.

Example request:

GET /_matrix/client/r0/notifications?from=xxxxx&limit=20&only=highlight HTTP/1.1

Response:

Status code 200:

A batch of events is being returned

Example

{
  "next_token": "abcdef",
  "notifications": [
    {
      "actions": [
        "notify"
      ],
      "profile_tag": "hcbvkzxhcvb",
      "read": true,
      "room_id": "!abcdefg:example.com",
      "ts": 1475508881945,
      "event": {
        "sender": "@alice:example.com",
        "type": "m.room.message",
        "age": 124524,
        "txn_id": "1234",
        "content": {
          "body": "I am a fish",
          "msgtype": "m.text"
        },
        "origin_server_ts": 1417731086797,
        "event_id": "$74686972643033:example.com"
      }
    }
  ]
}

11.12.1.4   Push Rules

A push rule is a single rule that states under what conditions an event should be passed onto a push gateway and how the notification should be presented. There are different "kinds" of push rules and each rule has an associated priority. Every push rule MUST have a kind and rule_id. The rule_id is a unique string within the kind of rule and its' scope: rule_ids do not need to be unique between rules of the same kind on different devices. Rules may have extra keys depending on the value of kind.The different kinds of rule in descending order of priority are:

Override Rules override
The highest priority rules are user-configured overrides.
Content-specific Rules content
These configure behaviour for (unencrypted) messages that match certain patterns. Content rules take one parameter: pattern, that gives the glob pattern to match against. This is treated in the same way as pattern for event_match.
Room-specific Rules room
These rules change the behaviour of all messages for a given room. The rule_id of a room rule is always the ID of the room that it affects.
Sender-specific rules sender
These rules configure notification behaviour for messages from a specific Matrix user ID. The rule_id of Sender rules is always the Matrix user ID of the user whose messages they'd apply to.
Underride rules underride
These are identical to override rules, but have a lower priority than content, room and sender rules.

This means that the full list of rule kinds, in descending priority order, is as follows:

  • Global Override
  • Global Content
  • Global Room
  • Global Sender
  • Global Underride

Rules with the same kind can specify an ordering priority. This determines which rule is selected in the event of multiple matches. For example, a rule matching "tea" and a separate rule matching "time" would both match the sentence "It's time for tea". The ordering of the rules would then resolve the tiebreak to determine which rule is executed. Only actions for highest priority rule will be sent to the Push Gateway.

Each rule can be enabled or disabled. Disabled rules never match. If no rules match an event, the homeserver MUST NOT notify the Push Gateway for that event. Homeservers MUST NOT notify the Push Gateway for events that the user has sent themselves.

11.12.1.4.1   Actions

All rules have an associated list of actions. An action affects if and how a notification is delivered for a matching event. The following actions are defined:

notify
This causes each matching event to generate a notification.
dont_notify
This prevents each matching event from generating a notification
coalesce
This enables notifications for matching events but activates homeserver specific behaviour to intelligently coalesce multiple events into a single notification. Not all homeservers may support this. Those that do not support it should treat it as the notify action.
set_tweak
Sets an entry in the tweaks dictionary key that is sent in the notification request to the Push Gateway. This takes the form of a dictionary with a set_tweak key whose value is the name of the tweak to set. It may also have a value key which is the value to which it should be set.

Actions that have no parameters are represented as a string. Otherwise, they are represented as a dictionary with a key equal to their name and other keys as their parameters, e.g. { "set_tweak": "sound", "value": "default" }

11.12.1.4.1.1   Tweaks

The set_tweak action is used to add an entry to the 'tweaks' dictionary that is sent in the notification request to the Push Gateway. The following tweaks are defined:

sound
A string representing the sound to be played when this notification arrives. A value of default means to play a default sound. A device may choose to alert the user by some other means if appropriate, eg. vibration.
highlight
A boolean representing whether or not this message should be highlighted in the UI. This will normally take the form of presenting the message in a different colour and/or style. The UI might also be adjusted to draw particular attention to the room in which the event occurred. If a highlight tweak is given with no value, its value is defined to be true. If no highlight tweak is given at all then the value of highlight is defined to be false.

Tweaks are passed transparently through the homeserver so client applications and Push Gateways may agree on additional tweaks. For example, a tweak may be added to specify how to flash the notification light on a mobile device.

11.12.1.4.2   Predefined Rules

Homeservers can specify "server-default rules" which operate at a lower priority than "user-defined rules". The rule_id for all server-default rules MUST start with a dot (".") to identify them as "server-default". The following server-default rules are specified:

11.12.1.4.2.1   Default Override Rules

11.12.1.4.2.1.1   .m.rule.master

Matches all events, this can be enabled to turn off all push notifications other than those generated by override rules set by the user. By default this rule is disabled.

Definition

{
    "rule_id": ".m.rule.master",
    "default": true,
    "enabled": false,
    "conditions": [],
    "actions": [
        "dont_notify"
    ]
}

11.12.1.4.2.1.2   .m.rule.suppress_notices

Matches messages with a msgtype of notice. This should be an override rule so that it takes priority over content / sender / room rules.

Definition:

{
    "rule_id": ".m.rule.suppress_notices",
    "default": true,
    "enabled": true,
    "conditions": [
        {
            "kind": "event_match",
            "key": "content.msgtype",
            "pattern": "m.notice",
        }
    ],
    "actions": [
        "dont_notify",
    ]
}

11.12.1.4.2.1.3   .m.rule.invite_for_me

Matches any invites to a new room for this user.

Definition:

{
    "rule_id": ".m.rule.invite_for_me",
    "default": true,
    "enabled": true,
    "conditions": [
        {
            "key": "type",
            "kind": "event_match",
            "pattern": "m.room.member"
        },
        {
            "key": "content.membership",
            "kind": "event_match",
            "pattern": "invite"
        },
        {
            "key": "state_key",
            "kind": "event_match",
            "pattern": "[the user's Matrix ID]"
        }
    ],
    "actions": [
       "notify",
        {
            "set_tweak": "sound",
            "value": "default"
        },
        {
            "set_tweak": "highlight",
            "value": false
        }
    ]
}

11.12.1.4.2.1.4   .m.rule.member_event

Matches any m.room.member_event.

Definition:

{
    "rule_id": ".m.rule.member_event",
    "default": true,
    "enabled": true,
    "conditions": [
        {
            "key": "type",
            "kind": "event_match",
            "pattern": "m.room.member"
        }
    ],
    "actions": [
        "dont_notify"
    ]
}

11.12.1.4.2.1.5   .m.rule.contains_display_name

Matches any message whose content is unencrypted and contains the user's current display name in the room in which it was sent.

Definition:

{
    "rule_id": ".m.rule.contains_display_name",
    "default": true,
    "enabled": true,
    "conditions": [
        {
            "kind": "contains_display_name"
        }
    ],
    "actions": [
        "notify",
        {
            "set_tweak": "sound",
            "value": "default"
        },
        {
            "set_tweak": "highlight"
        }
    ]
}

11.12.1.4.2.2   Default Content Rules

11.12.1.4.2.2.1   .m.rule.contains_user_name

Matches any message whose content is unencrypted and contains the local part of the user's Matrix ID, separated by word boundaries.

Definition (as a content rule):

{
    "rule_id": ".m.rule.contains_user_name",
    "default": true,
    "enabled": true,
    "pattern": "[the local part of the user's Matrix ID]",
    "actions": [
        "notify",
        {
            "set_tweak": "sound",
            "value": "default"
        }
    ]
}

11.12.1.4.2.3   Default Underride Rules

11.12.1.4.2.3.1   .m.rule.call

Matches any incoming VOIP call.

Definition:

{
    "rule_id": ".m.rule.call",
    "default": true,
    "enabled": true,
    "conditions": [
        {
            "key": "type",
            "kind": "event_match",
            "pattern": "m.call.invite"
        }
    ],
    "actions": [
        "notify",
        {
            "set_tweak": "sound",
            "value": "ring"
        },
        {
            "set_tweak": "highlight",
            "value": false
        }
    ]
},

11.12.1.4.2.3.2   .m.rule.room_one_to_one

Matches any message sent in a room with exactly two members.

Definition:

{
    "rule_id": ".m.rule.room_one_to_one",
    "default": true,
    "enabled": true,
    "conditions": [
        {
            "kind": "room_member_count",
            "is": "2"
        }
    ],
    "actions": [
        "notify",
        {
            "set_tweak": "sound",
            "value": "default"
        },
        {
            "set_tweak": "highlight",
            "value": false
        }
    ]
}

11.12.1.4.2.3.3   .m.rule.message

Matches all chat messages.

Definition:

{
     "rule_id": ".m.rule.message",
     "default": true,
     "enabled": true,
     "conditions": [
         {
             "kind": "event_match",
             "key": "type",
             "pattern": "m.room.message"
         }
     ],
     "actions": [
         "notify",
         {
             "set_tweak": "highlight",
             "value": false
         }
     ]
}

11.12.1.4.3   Conditions

Override, Underride and Default Rules MAY have a list of 'conditions'. All conditions must hold true for an event in order to apply the action for the event. A rule with no conditions always matches. Room, Sender, User and Content rules do not have conditions in the same way, but instead have predefined conditions. These conditions can be configured using the parameters outlined below. In the cases of room and sender rules, the rule_id of the rule determines its behaviour. The following conditions are defined:

event_match

This is a glob pattern match on a field of the event. Parameters:

  • key: The dot-separated field of the event to match, e.g. content.body
  • pattern: The glob-style pattern to match against. Patterns with no special glob characters should be treated as having asterisks prepended and appended when testing the condition.
contains_display_name
This matches unencrypted messages where content.body contains the owner's display name in that room. This is a separate rule because display names may change and as such it would be hard to maintain a rule that matched the user's display name. This condition has no parameters.
room_member_count

This matches the current number of members in the room. Parameters:

  • is: A decimal integer optionally prefixed by one of, ==, <, >, >= or <=. A prefix of < matches rooms where the member count is strictly less than the given number and so forth. If no prefix is present, this parameter defaults to ==.

11.12.1.5   Push Rules: API

Clients can retrieve, add, modify and remove push rules globally or per-device using the APIs below.

11.12.1.5.1   GET /_matrix/client/r0/pushrules/

Retrieve all push rulesets for this user. Clients can "drill-down" on the rulesets by suffixing a scope to this path e.g. /pushrules/global/. This will return a subset of this data under the specified key e.g. the global key.

Requires auth:Yes.

Request format:

No parameters

Response format:

Parameter Type Description
global Ruleset Required. The global ruleset.

Ruleset

Parameter Type Description
content [PushRule]  
override [PushRule]  
room [PushRule]  
sender [PushRule]  
underride [PushRule]  

PushRule

Parameter Type Description
actions [object or string] Required. The actions to perform when this rule is matched.
default boolean Required. Whether this is a default rule, or has been set explicitly.
enabled boolean Required. Whether the push rule is enabled or not.
rule_id string Required. The ID of this rule.
conditions [PushCondition] The conditions that must hold true for an event in order for a rule to be applied to an event. A rule with no conditions always matches. Only applicable to underride and override rules.
pattern string The glob-style pattern to match against. Only applicable to content rules.

PushCondition

Parameter Type Description
kind enum Required. One of: ["event_match", "contains_display_name", "room_member_count"]
key string Required for event_match conditions. The dot- separated field of the event to match.
pattern string Required for event_match conditions. The glob- style pattern to match against. Patterns with no special glob characters should be treated as having asterisks prepended and appended when testing the condition.
is string Required for room_member_count conditions. A decimal integer optionally prefixed by one of, ==, <, >, >= or <=. A prefix of < matches rooms where the member count is strictly less than the given number and so forth. If no prefix is present, this parameter defaults to ==.

Example request:

GET /_matrix/client/r0/pushrules/ HTTP/1.1

Response:

Status code 200:

All the push rulesets for this user.

Example

{
  "global": {
    "content": [
      {
        "actions": [
          "notify",
          {
            "set_tweak": "sound",
            "value": "default"
          },
          {
            "set_tweak": "highlight"
          }
        ],
        "default": true,
        "enabled": true,
        "pattern": "alice",
        "rule_id": ".m.rule.contains_user_name"
      }
    ],
    "override": [
      {
        "actions": [
          "dont_notify"
        ],
        "conditions": [],
        "default": true,
        "enabled": false,
        "rule_id": ".m.rule.master"
      },
      {
        "actions": [
          "dont_notify"
        ],
        "conditions": [
          {
            "key": "content.msgtype",
            "kind": "event_match",
            "pattern": "m.notice"
          }
        ],
        "default": true,
        "enabled": true,
        "rule_id": ".m.rule.suppress_notices"
      }
    ],
    "room": [],
    "sender": [],
    "underride": [
      {
        "actions": [
          "notify",
          {
            "set_tweak": "sound",
            "value": "ring"
          },
          {
            "set_tweak": "highlight",
            "value": false
          }
        ],
        "conditions": [
          {
            "key": "type",
            "kind": "event_match",
            "pattern": "m.call.invite"
          }
        ],
        "default": true,
        "enabled": true,
        "rule_id": ".m.rule.call"
      },
      {
        "actions": [
          "notify",
          {
            "set_tweak": "sound",
            "value": "default"
          },
          {
            "set_tweak": "highlight"
          }
        ],
        "conditions": [
          {
            "kind": "contains_display_name"
          }
        ],
        "default": true,
        "enabled": true,
        "rule_id": ".m.rule.contains_display_name"
      },
      {
        "actions": [
          "notify",
          {
            "set_tweak": "sound",
            "value": "default"
          },
          {
            "set_tweak": "highlight",
            "value": false
          }
        ],
        "conditions": [
          {
            "is": "2",
            "kind": "room_member_count"
          }
        ],
        "default": true,
        "enabled": true,
        "rule_id": ".m.rule.room_one_to_one"
      },
      {
        "actions": [
          "notify",
          {
            "set_tweak": "sound",
            "value": "default"
          },
          {
            "set_tweak": "highlight",
            "value": false
          }
        ],
        "conditions": [
          {
            "key": "type",
            "kind": "event_match",
            "pattern": "m.room.member"
          },
          {
            "key": "content.membership",
            "kind": "event_match",
            "pattern": "invite"
          },
          {
            "key": "state_key",
            "kind": "event_match",
            "pattern": "@alice:example.com"
          }
        ],
        "default": true,
        "enabled": true,
        "rule_id": ".m.rule.invite_for_me"
      },
      {
        "actions": [
          "notify",
          {
            "set_tweak": "highlight",
            "value": false
          }
        ],
        "conditions": [
          {
            "key": "type",
            "kind": "event_match",
            "pattern": "m.room.member"
          }
        ],
        "default": true,
        "enabled": true,
        "rule_id": ".m.rule.member_event"
      },
      {
        "actions": [
          "notify",
          {
            "set_tweak": "highlight",
            "value": false
          }
        ],
        "conditions": [
          {
            "key": "type",
            "kind": "event_match",
            "pattern": "m.room.message"
          }
        ],
        "default": true,
        "enabled": true,
        "rule_id": ".m.rule.message"
      }
    ]
  }
}

11.12.1.5.2   GET /_matrix/client/r0/pushrules/{scope}/{kind}/{ruleId}

Retrieve a single specified push rule.

Requires auth:Yes.

Request format:

Parameter Type Description
path parameters
scope string Required. global to specify global rules.
kind enum Required. The kind of rule One of: ["override", "underride", "sender", "room", "content"]
ruleId string Required. The identifier for the rule.

Response format:

PushRule

Parameter Type Description
actions [object or string] Required. The actions to perform when this rule is matched.
default boolean Required. Whether this is a default rule, or has been set explicitly.
enabled boolean Required. Whether the push rule is enabled or not.
rule_id string Required. The ID of this rule.
conditions [PushCondition] The conditions that must hold true for an event in order for a rule to be applied to an event. A rule with no conditions always matches. Only applicable to underride and override rules.
pattern string The glob-style pattern to match against. Only applicable to content rules.

PushCondition

Parameter Type Description
kind enum Required. One of: ["event_match", "contains_display_name", "room_member_count"]
key string Required for event_match conditions. The dot- separated field of the event to match.
pattern string Required for event_match conditions. The glob- style pattern to match against. Patterns with no special glob characters should be treated as having asterisks prepended and appended when testing the condition.
is string Required for room_member_count conditions. A decimal integer optionally prefixed by one of, ==, <, >, >= or <=. A prefix of < matches rooms where the member count is strictly less than the given number and so forth. If no prefix is present, this parameter defaults to ==.

Example request:

GET /_matrix/client/r0/pushrules/global/content/nocake HTTP/1.1

Response:

Status code 200:

The specific push rule. This will also include keys specific to the rule itself such as the rule's actions and conditions if set.

Example

{
  "actions": [
    "dont_notify"
  ],
  "pattern": "cake*lie",
  "rule_id": "nocake",
  "enabled": true,
  "default": false
}

11.12.1.5.3   DELETE /_matrix/client/r0/pushrules/{scope}/{kind}/{ruleId}

This endpoint removes the push rule defined in the path.

Requires auth:Yes.

Request format:

Parameter Type Description
path parameters
scope string Required. global to specify global rules.
kind enum Required. The kind of rule One of: ["override", "underride", "sender", "room", "content"]
ruleId string Required. The identifier for the rule.

Example request:

DELETE /_matrix/client/r0/pushrules/global/content/nocake HTTP/1.1

Response:

Status code 200:

The push rule was deleted.

Example

{}

11.12.1.5.4   PUT /_matrix/client/r0/pushrules/{scope}/{kind}/{ruleId}

This endpoint allows the creation, modification and deletion of pushers for this user ID. The behaviour of this endpoint varies depending on the values in the JSON body.

Rate-limited:Yes.
Requires auth:Yes.

Request format:

Parameter Type Description
path parameters
scope string Required. global to specify global rules.
kind enum Required. The kind of rule One of: ["override", "underride", "sender", "room", "content"]
ruleId string Required. The identifier for the rule.
JSON body parameters
actions [enum] Required. The action(s) to perform when the conditions for this rule are met. One of: ["notify", "dont_notify", "coalesce", "set_tweak"]
conditions [PushCondition] The conditions that must hold true for an event in order for a rule to be applied to an event. A rule with no conditions always matches. Only applicable to underride and override rules.
pattern string Only applicable to content rules. The glob- style pattern to match against.
query parameters
before string Use 'before' with a rule_id as its value to make the new rule the next-most important rule with respect to the given user defined rule. It is not possible to add a rule relative to a predefined server rule.
after string This makes the new rule the next-less important rule relative to the given user defined rule. It is not possible to add a rule relative to a predefined server rule.

PushCondition

Parameter Type Description
kind enum Required. One of: ["event_match", "contains_display_name", "room_member_count"]
key string Required for event_match conditions. The dot- separated field of the event to match.
pattern string Required for event_match conditions. The glob- style pattern to match against. Patterns with no special glob characters should be treated as having asterisks prepended and appended when testing the condition.
is string Required for room_member_count conditions. A decimal integer optionally prefixed by one of, ==, <, >, >= or <=. A prefix of < matches rooms where the member count is strictly less than the given number and so forth. If no prefix is present, this parameter defaults to ==.

Example request:

PUT /_matrix/client/r0/pushrules/global/content/nocake?before=someRuleId&after=anotherRuleId HTTP/1.1
Content-Type: application/json

{
  "pattern": "cake*lie",
  "actions": [
    "notify"
  ]
}

Responses:

Status code 200:

The pusher was set.

Example

{}

Status code 400:

There was a problem configuring this push rule.

Example

{
  "error": "before/after rule not found: someRuleId",
  "errcode": "M_UNKNOWN"
}

Status code 429:

This request was rate-limited.

Example

{
  "errcode": "string",
  "error": "string"
}

11.12.1.5.5   GET /_matrix/client/r0/pushrules/{scope}/{kind}/{ruleId}/enabled

This endpoint gets whether the specified push rule is enabled.

Requires auth:Yes.

Request format:

Parameter Type Description
path parameters
scope string Required. Either global or device/<profile_tag> to specify global rules or device rules for the given profile_tag.
kind enum Required. The kind of rule One of: ["override", "underride", "sender", "room", "content"]
ruleId string Required. The identifier for the rule.

Response format:

Parameter Type Description
enabled boolean Required. Whether the push rule is enabled or not.

Example request:

GET /_matrix/client/r0/pushrules/global/cake/nocake/enabled HTTP/1.1

Response:

Status code 200:

Whether the push rule is enabled.

Example

{
  "enabled": true
}

11.12.1.5.6   PUT /_matrix/client/r0/pushrules/{scope}/{kind}/{ruleId}/enabled

This endpoint allows clients to enable or disable the specified push rule.

Requires auth:Yes.

Request format:

Parameter Type Description
path parameters
scope string Required. global to specify global rules.
kind enum Required. The kind of rule One of: ["override", "underride", "sender", "room", "content"]
ruleId string Required. The identifier for the rule.
JSON body parameters
enabled boolean Required. Whether the push rule is enabled or not.

Example request:

PUT /_matrix/client/r0/pushrules/global/content/nocake/enabled HTTP/1.1
Content-Type: application/json

{
  "enabled": true
}

Response:

Status code 200:

The push rule was enabled or disabled.

Example

{}

11.12.1.5.7   GET /_matrix/client/r0/pushrules/{scope}/{kind}/{ruleId}/actions

This endpoint get the actions for the specified push rule.

Requires auth:Yes.

Request format:

Parameter Type Description
path parameters
scope string Required. Either global or device/<profile_tag> to specify global rules or device rules for the given profile_tag.
kind enum Required. The kind of rule One of: ["override", "underride", "sender", "room", "content"]
ruleId string Required. The identifier for the rule.

Response format:

Parameter Type Description
actions [string] Required. The action(s) to perform for this rule.

Example request:

GET /_matrix/client/r0/pushrules/global/content/nocake/actions HTTP/1.1

Response:

Status code 200:

The actions for this push rule.

Example

{
  "actions": [
    "notify"
  ]
}

11.12.1.5.8   PUT /_matrix/client/r0/pushrules/{scope}/{kind}/{ruleId}/actions

This endpoint allows clients to change the actions of a push rule. This can be used to change the actions of builtin rules.

Requires auth:Yes.

Request format:

Parameter Type Description
path parameters
scope string Required. global to specify global rules.
kind enum Required. The kind of rule One of: ["override", "underride", "sender", "room", "content"]
ruleId string Required. The identifier for the rule.
JSON body parameters
actions [enum] Required. The action(s) to perform for this rule. One of: ["notify", "dont_notify", "coalesce", "set_tweak"]

Example request:

PUT /_matrix/client/r0/pushrules/global/room/%23spam%3Aexample.com/actions HTTP/1.1
Content-Type: application/json

{
  "actions": [
    "notify"
  ]
}

Response:

Status code 200:

The actions for the push rule were set.

Example

{}

11.12.1.6   Push Rules: Events

When a user changes their push rules a m.push_rules event is sent to all clients in the account_data section of their next /sync request. The content of the event is the current push rules for the user.

11.12.1.6.1   Examples

To create a rule that suppresses notifications for the room with ID !dj234r78wl45Gh4D:matrix.org:

curl -X PUT -H "Content-Type: application/json" "https://example.com/_matrix/client/r0/pushrules/global/room/%21dj234r78wl45Gh4D%3Amatrix.org?access_token=123456" -d \
'{
   "actions" : ["dont_notify"]
 }'

To suppress notifications for the user @spambot:matrix.org:

curl -X PUT -H "Content-Type: application/json" "https://example.com/_matrix/client/r0/pushrules/global/sender/%40spambot%3Amatrix.org?access_token=123456" -d \
'{
   "actions" : ["dont_notify"]
 }'

To always notify for messages that contain the work 'cake' and set a specific sound (with a rule_id of SSByZWFsbHkgbGlrZSBjYWtl):

curl -X PUT -H "Content-Type: application/json" "https://example.com/_matrix/client/r0/pushrules/global/content/SSByZWFsbHkgbGlrZSBjYWtl?access_token=123456" -d \
'{
   "pattern": "cake",
   "actions" : ["notify", {"set_sound":"cakealarm.wav"}]
 }'

To add a rule suppressing notifications for messages starting with 'cake' but ending with 'lie', superseding the previous rule:

curl -X PUT -H "Content-Type: application/json" "https://example.com/_matrix/client/r0/pushrules/global/content/U3BvbmdlIGNha2UgaXMgYmVzdA?access_token=123456&before=SSByZWFsbHkgbGlrZSBjYWtl" -d \
'{
   "pattern": "cake*lie",
   "actions" : ["notify"]
 }'

To add a custom sound for notifications messages containing the word 'beer' in any rooms with 10 members or fewer (with greater importance than the room, sender and content rules):

curl -X PUT -H "Content-Type: application/json" "https://example.com/_matrix/client/r0/pushrules/global/override/U2VlIHlvdSBpbiBUaGUgRHVrZQ?access_token=123456" -d \
'{
   "conditions": [
     {"kind": "event_match", "key": "content.body", "pattern": "beer" },
     {"kind": "room_member_count", "is": "<=10"}
   ],
   "actions" : [
     "notify",
     {"set_sound":"beeroclock.wav"}
   ]
 }'

11.12.3   Push Gateway behaviour

11.12.3.1   Recommendations for APNS

The exact format for sending APNS notifications is flexible and up to the client app and its' push gateway to agree on. As APNS requires that the sender has a private key owned by the app developer, each app must have its own push gateway. It is recommended that:

  • The APNS token be base64 encoded and used as the pushkey.
  • A different app_id be used for apps on the production and sandbox APS environments.
  • APNS push gateways do not attempt to wait for errors from the APNS gateway before returning and instead to store failures and return 'rejected' responses next time that pushkey is used.

11.12.4   Security considerations

Clients specify the Push Gateway URL to use to send event notifications to. This URL should be over HTTPS and never over HTTP.

As push notifications will pass through a Push Provider, message content shouldn't be sent in the push itself where possible. Instead, Push Gateways should send a "sync" command to instruct the client to get new events from the homeserver directly.

11.13   Third party invites

This module adds in support for inviting new members to a room where their Matrix user ID is not known, instead addressing them by a third party identifier such as an email address. There are two flows here; one if a Matrix user ID is known for the third party identifier, and one if not. Either way, the client calls /invite with the details of the third party identifier.

The homeserver asks the identity server whether a Matrix user ID is known for that identifier:

  • If it is, an invite is simply issued for that user.
  • If it is not, the homeserver asks the identity server to record the details of the invitation, and to notify the invitee's homeserver of this pending invitation if it gets a binding for this identifier in the future. The identity server returns a token and public key to the inviting homeserver.

When the invitee's homeserver receives the notification of the binding, it should insert an m.room.member event into the room's graph for that user, with content.membership = invite, as well as a content.third_party_invite property which contains proof that the invitee does indeed own that third party identifier.

11.13.1   Events

11.13.1.1   m.room.third_party_invite

State Event
state_key: The token, of which a signature must be produced in order to join the room.

Acts as an m.room.member invite event, where there isn't a target user_id to invite. This event contains a token and a public key whose private key must be used to sign the token. Any user who can present that signature may use this invitation to join the target room.

Content Key Type Description
display_name string Required. A user-readable string which represents the user who has been invited. This should not contain the user's third party ID, as otherwise when the invite is accepted it would leak the association between the matrix ID and the third party ID.
key_validity_url string Required. A URL which can be fetched, with querystring public_key=public_key, to validate whether the key has been revoked. The URL must return a JSON object containing a boolean property named 'valid'.
public_key string Required. A base64-encoded ed25519 key with which token must be signed (though a signature from any entry in public_keys is also sufficient). This exists for backwards compatibility.
public_keys [PublicKeys] Keys with which the token may be signed.

PublicKeys

PublicKeys Key Type Description
key_validity_url string An optional URL which can be fetched, with querystring public_key=public_key, to validate whether the key has been revoked. The URL must return a JSON object containing a boolean property named 'valid'. If this URL is absent, the key must be considered valid indefinitely.
public_key string Required. A base-64 encoded ed25519 key with which token may be signed.

Example:

{
    "age": 242352,
    "content": {
        "display_name": "Alice Margatroid",
        "key_validity_url": "https://magic.forest/verifykey",
        "public_key": "abc123",
        "public_keys": [
            {
                "key_validity_url": "https://magic.forest/verifykey",
                "public_key": "def456"
            }
        ]
    },
    "event_id": "$WLGTSEFSEF:localhost",
    "origin_server_ts": 1431961217939,
    "room_id": "!Cuyf34gef24t:localhost",
    "sender": "@example:localhost",
    "state_key": "pc98",
    "type": "m.room.third_party_invite"
}

11.13.2   Client behaviour

A client asks a server to invite a user by their third party identifier.

11.13.2.1   POST /_matrix/client/r0/rooms/{roomId}/invite

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.

Rate-limited:Yes.
Requires auth:Yes.

Request format:

Parameter Type Description
path parameters
roomId string Required. The room identifier (not alias) to which to invite the user.
JSON body parameters
id_server string Required. The hostname+port of the identity server which should be used for third party identifier lookups.
medium string Required. The kind of address being passed in the address field, for example email.
address string Required. The invitee's third party identifier.

Example request:

POST /_matrix/client/r0/rooms/%21d41d8cd%3Amatrix.org/invite HTTP/1.1
Content-Type: application/json

{
  "id_server": "matrix.org",
  "medium": "email",
  "address": "cheeky@monkey.com"
}

Responses:

Status code 200:

The user has been invited to join the room.

Example

{}

Status code 403:

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.

Example

{
  "errcode": "M_FORBIDDEN",
  "error": "@cheeky_monkey:matrix.org is banned from the room"
}

Status code 429:

This request was rate-limited.

Example

{
  "errcode": "string",
  "error": "string"
}

11.13.3   Server behaviour

All homeservers MUST verify the signature in the event's content.third_party_invite.signed object.

When a homeserver inserts an m.room.member invite event into the graph because of an m.room.third_party_invite event, that homesever MUST validate that the public key used for signing is still valid, by checking key_validity_url from the m.room.third_party_invite. It does this by making an HTTP GET request to key_validity_url:

Schema:

=> GET $key_validity_url?public_key=$public_key
<= HTTP/1.1 200 OK
{
    "valid": true|false
}

Example:

key_validity_url = https://identity.server/is_valid
public_key = ALJWLAFQfqffQHFqFfeqFUOEHf4AIHfefh4
=> GET https://identity.server/is_valid?public_key=ALJWLAFQfqffQHFqFfeqFUOEHf4AIHfefh4
<= HTTP/1.1 200 OK
{
    "valid": true
}

with the querystring ?public_key=``public_key``. A JSON object will be returned. The invitation is valid if the object contains a key named valid which is true. Otherwise, the invitation MUST be rejected. This request is idempotent and may be retried by the homeserver.

If a homeserver is joining a room for the first time because of an m.room.third_party_invite, the server which is already participating in the room (which is chosen as per the standard server-server specification) MUST validate that the public key used for signing is still valid, by checking key_validity_url in the above described way.

No other homeservers may reject the joining of the room on the basis of key_validity_url, this is so that all homeservers have a consistent view of the room. They may, however, indicate to their clients that a member's' membership is questionable.

For example:

  1. Room R has two participating homeservers, H1, H2
  2. User A on H1 invites a third party identifier to room R
  3. H1 asks the identity server for a binding to a Matrix user ID, and has none, so issues an m.room.third_party_invite event to the room.
  4. When the third party user validates their identity, their homeserver H3 is notified and attempts to issue an m.room.member event to participate in the room.
  5. H3 validates the signature given to it by the identity server.
  6. H3 then asks H1 to join it to the room. H1 must validate the signed property and check key_validity_url.
  7. Having validated these things, H1 writes the invite event to the room, and H3 begins participating in the room. H2 must accept this event.

The reason that no other homeserver may reject the event based on checking key_validity_url is that we must ensure event acceptance is deterministic. If some other participating server doesn't have a network path to the keyserver, or if the keyserver were to go offline, or revoke its keys, that other server would reject the event and cause the participating servers' graphs to diverge. This relies on participating servers trusting each other, but that trust is already implied by the server-server protocol. Also, the public key signature verification must still be performed, so the attack surface here is minimized.

11.13.4   Security considerations

There are a number of privary and trust implications to this module.

It is important for user privacy that leaking the mapping between a matrix user ID and a third party identifier is hard. In particular, being able to look up all third party identifiers from a matrix user ID (and accordingly, being able to link each third party identifier) should be avoided wherever possible. To this end, the third party identifier is not put in any event, rather an opaque display name provided by the identity server is put into the events. Clients should not remember or display third party identifiers from invites, other than for the use of the inviter themself.

Homeservers are not required to trust any particular identity server(s). It is generally a client's responsibility to decide which identity servers it trusts, not a homeserver's. Accordingly, this API takes identity servers as input from end users, and doesn't have any specific trusted set. It is possible some homeservers may want to supply defaults, or reject some identity servers for its users, but no homeserver is allowed to dictate which identity servers other homeservers' users trust.

There is some risk of denial of service attacks by flooding homeservers or identity servers with many requests, or much state to store. Defending against these is left to the implementer's discretion.

11.14   Server Side Search

11.14.1   Client behaviour

There is a single HTTP API for performing server-side search, documented below.

11.14.1.1   POST /_matrix/client/r0/search

Performs a full text search across different categories.

Rate-limited:Yes.
Requires auth:Yes.

Request format:

Parameter Type Description
query parameters
next_batch string The point to return events from. If given, this should be a next_batch result from a previous call to this endpoint.
JSON body parameters
search_categories Categories Required. Describes which categories to search in and their criteria.

Categories

Parameter Type Description
room_events Room Events Mapping of category name to search criteria.

Room Events

Parameter Type Description
search_term string Required. The string to search events for
keys [enum] The keys to search. Defaults to all. One of: ["content.body", "content.name", "content.topic"]
filter Filter This takes a filter.
order_by enum The order in which to search for results. One of: ["recent", "rank"]
event_context Event Context Configures whether any context for the events returned are included in the response.
include_state boolean Requests the server return the current state for each room returned.
groupings Groupings Requests that the server partitions the result set based on the provided list of keys.

Event Context

Parameter Type Description
before_limit integer How many events before the result are returned.
after_limit integer How many events after the result are returned.
include_profile boolean Requests that the server returns the historic profile information for the users that sent the events that were returned.

Groupings

Parameter Type Description
group_by [Group] List of groups to request.

Group

Parameter Type Description
key enum Key that defines the group. One of: ["room_id", "sender"]

Response format:

Results

Parameter Type Description
search_categories Categories Required. Describes which categories to search in and their criteria.

Categories

Parameter Type Description
room_events Room Event Results Mapping of category name to search criteria.

Room Event Results

Parameter Type Description
count number An approximate count of the total number of results found.
results [Result] List of results in the requested order.
state {string: [State Event]} The current state for every room in the results. This is included if the request had the include_state key set with a value of true.
groups {string: {string: Group Value}} Any groups that were requested.
next_batch string Token that can be used to get the next batch of results, by passing as the next_batch parameter to the next call. If this field is absent, there are no more results.

Result

Parameter Type Description
rank number A number that describes how closely this result matches the search. Higher is closer.
result Event The event that matched.
context Event Context Context for result, if requested.

Event Context

Parameter Type Description
start string Pagination token for the start of the chunk
end string Pagination token for the end of the chunk
profile_info {string: User Profile} The historic profile information of the users that sent the events returned.
events_before [Event] Events just before the result.
events_after [Event] Events just after the result.

User Profile

Parameter Type Description
displayname string  
avatar_url string  

Event

Parameter Type Description
content object The fields in this object will vary depending on the type of event. When interacting with the REST API, this is the HTTP body.
type string Required. The type of event. This SHOULD be namespaced similar to Java package naming conventions e.g. 'com.example.subdomain.event.type'
event_id string Required. The globally unique event identifier.
room_id string Required. The ID of the room associated with this event.
sender string Required. Contains the fully-qualified ID of the user who sent this event.
origin_server_ts number Required. Timestamp in milliseconds on originating homeserver when this event was sent.
unsigned UnsignedData Contains optional extra information about the event.

State Event

Parameter Type Description
content object The fields in this object will vary depending on the type of event. When interacting with the REST API, this is the HTTP body.
type string Required. The type of event. This SHOULD be namespaced similar to Java package naming conventions e.g. 'com.example.subdomain.event.type'
event_id string Required. The globally unique event identifier.
room_id string Required. The ID of the room associated with this event.
sender string Required. Contains the fully-qualified ID of the user who sent this event.
origin_server_ts number Required. Timestamp in milliseconds on originating homeserver when this event was sent.
unsigned UnsignedData Contains optional extra information about the event.
prev_content EventContent Optional. The previous content for this event. If there is no previous content, this key will be missing.
state_key string Required. A unique key which defines the overwriting semantics for this piece of room state. This value is often a zero-length string. The presence of this key makes this event a State Event. The key MUST NOT start with '_'.

UnsignedData

Parameter Type Description
age integer The time in milliseconds that has elapsed since the event was sent. This field is generated by the local homeserver, and may be incorrect if the local time on at least one of the two servers is out of sync, which can cause the age to either be negative or greater than it actually is.
redacted_because Event Optional. The event that redacted this event, if any.
transaction_id string The client-supplied transaction ID, if the client being given the event is the same one which sent it.

Group Value

Parameter Type Description
next_batch string Token that can be used to get the next batch of results in the group, by passing as the next_batch parameter to the next call. If this field is absent, there are no more results in this group.
order integer Key that can be used to order different groups.
results [string] Which results are in this group.

Example request:

POST /_matrix/client/r0/search?next_batch=YWxsCgpOb25lLDM1ODcwOA HTTP/1.1
Content-Type: application/json

{
  "search_categories": {
    "room_events": {
      "keys": [
        "content.body"
      ],
      "search_term": "martians and men"
    }
  },
  "order_by": "recent",
  "groupings": {
    "group_by": [
      {
        "key": "room_id"
      }
    ]
  }
}

Responses:

Status code 200:

Results of the search.

Example

{
  "search_categories": {
    "room_events": {
      "groups": {
        "room_id": {
          "!qPewotXpIctQySfjSy:localhost": {
            "order": 1,
            "next_batch": "BdgFsdfHSf-dsFD",
            "results": [
              "$144429830826TWwbB:localhost"
            ]
          }
        }
      },
      "next_batch": "5FdgFsd234dfgsdfFD",
      "count": 1224,
      "results": [
        {
          "rank": 0.00424866,
          "result": {
            "age": 526228296,
            "content": {
              "body": "Test content martians and men",
              "msgtype": "m.text"
            },
            "event_id": "$144429830826TWwbB:localhost",
            "origin_server_ts": 1444298308034,
            "room_id": "!qPewotXpIctQySfjSy:localhost",
            "type": "m.room.message",
            "sender": "@test:localhost"
          }
        }
      ]
    }
  }
}

Status code 400:

Part of the request was invalid.

Status code 429:

This request was rate-limited.

Example

{
  "errcode": "string",
  "error": "string"
}

11.14.2   Search Categories

The search API allows clients to search in different categories of items. Currently the only specified category is room_events.

11.14.2.1   room_events

This category covers all events that the user is allowed to see, including events in rooms that they have left. The search is performed on certain keys of certain event types.

The supported keys to search over are:

  • content.body in m.room.message
  • content.name in m.room.name
  • content.topic in m.room.topic

The search will not include rooms that are end to end encrypted.

The results include a rank key that can be used to sort the results by relevancy. The higher the rank the more relevant the result is.

The value of count gives an approximation of the total number of results. Homeservers may give an estimate rather than an exact value for this field.

11.14.3   Ordering

The client can specify the ordering that the server returns results in. The two allowed orderings are:

  • rank, which returns the most relevant results first.
  • recent, which returns the most recent results first.

The default ordering is rank.

11.14.4   Groups

The client can request that the results are returned along with grouping information, e.g. grouped by room_id. In this case the response will contain a group entry for each distinct value of room_id. Each group entry contains at least a list of the event_ids that are in that group, as well as potentially other metadata about the group.

The current required supported groupings are:

  • room_id
  • sender

11.14.5   Pagination

The server may return a next_batch key at various places in the response. These are used to paginate the results. To fetch more results, the client should send the same request to the server with a next_batch query parameter set to that of the token.

The scope of the pagination is defined depending on where the next_batch token was returned. For example, using a token inside a group will return more results from within that group.

The currently supported locations for the next_batch token are:

  • search_categories.<category>.next_batch
  • search_categories.<category>.groups.<group_key>.<group_id>.next_batch

A server need not support pagination, even if there are more matching results. In that case, they must not return a next_batch token in the response.

11.14.6   Security considerations

The server must only return results that the user has permission to see.

11.15   Guest Access

There are times when it is desirable for clients to be able to interact with rooms without having to fully register for an account on a homeserver or join the room. This module specifies how these clients should interact with servers in order to participate in rooms as guests.

Guest users retrieve access tokens from a homeserver using the ordinary register endpoint, specifying the kind parameter as guest. They may then interact with the client-server API as any other user would, but will only have access to a subset of the API as described the Client behaviour subsection below. Homeservers may choose not to allow this access at all to their local users, but have no information about whether users on other homeservers are guests or not.

Guest users can also upgrade their account by going through the ordinary register flow, but specifying the additional POST parameter guest_access_token containing the guest's access token. They are also required to specify the username parameter to the value of the local part of their username, which is otherwise optional.

This module does not fully factor in federation; it relies on individual homeservers properly adhering to the rules set out in this module, rather than allowing all homeservers to enforce the rules on each other.

11.15.1   Events

11.15.1.1   m.room.guest_access

State Event
state_key: A zero-length string.

This event controls whether guest users are allowed to join rooms. If this event is absent, servers should act as if it is present and has the guest_access value "forbidden".

Content Key Type Description
guest_access enum Required. Whether guests can join the room. One of: ["can_join", "forbidden"]

Example:

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

11.15.2   Client behaviour

The following API endpoints are allowed to be accessed by guest accounts for retrieving events:

The following API endpoints are allowed to be accessed by guest accounts for sending events:

The following API endpoints are allowed to be accessed by guest accounts for their own account maintenance:

The following API endpoints are allowed to be accessed by guest accounts for end-to-end encryption:

11.15.3   Server behaviour

Servers MUST only allow guest users to join rooms if the m.room.guest_access state event is present on the room, and has the guest_access value can_join. If the m.room.guest_access event is changed to stop this from being the case, the server MUST set those users' m.room.member state to leave.

11.15.4   Security considerations

Each homeserver manages its own guest accounts itself, and whether an account is a guest account or not is not information passed from server to server. Accordingly, any server participating in a room is trusted to properly enforce the permissions outlined in this section.

Homeservers may want to enable protections such as captchas for guest registration to prevent spam, denial of service, and similar attacks.

11.16   Room Previews

It is sometimes desirable to offer a preview of a room, where a user can "lurk" and read messages posted to the room, without joining the room. This can be particularly effective when combined with Guest Access.

Previews are implemented via the world_readable Room History Visibility. setting, along with a special version of the GET /events endpoint.

11.16.1   Client behaviour

A client wishing to view a room without joining it should call GET /rooms/:room_id/initialSync, followed by GET /events. Clients will need to do this in parallel for each room they wish to view.

Clients can of course also call other endpoints such as GET /rooms/:room_id/messages and GET /search to access events outside the /events stream.

11.16.1.1   GET /_matrix/client/r0/events

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 normal /events endpoint, but can be called by users who have not joined the room.

Note that the normal /events endpoint has been deprecated. This API will also be deprecated at some point, but its replacement is not yet known.

Requires auth:Yes.

Request format:

Parameter Type Description
query parameters
from string The token to stream from. This token is either from a previous request to this API or from the initial sync API.
timeout integer The maximum time in milliseconds to wait for an event.
room_id string The room ID for which events should be returned.

Response format:

Parameter Type Description
start string A token which correlates to the first value in chunk. This is usually the same token supplied to from=.
end string A token which correlates to the last value in chunk. This token should be used in the next request to /events.
chunk [Event] An array of events.

Event

Parameter Type Description
content object The fields in this object will vary depending on the type of event. When interacting with the REST API, this is the HTTP body.
type string Required. The type of event. This SHOULD be namespaced similar to Java package naming conventions e.g. 'com.example.subdomain.event.type'
event_id string Required. The globally unique event identifier.
room_id string Required. The ID of the room associated with this event.
sender string Required. Contains the fully-qualified ID of the user who sent this event.
origin_server_ts number Required. Timestamp in milliseconds on originating homeserver when this event was sent.
unsigned UnsignedData Contains optional extra information about the event.

UnsignedData

Parameter Type Description
age integer The time in milliseconds that has elapsed since the event was sent. This field is generated by the local homeserver, and may be incorrect if the local time on at least one of the two servers is out of sync, which can cause the age to either be negative or greater than it actually is.
redacted_because Event Optional. The event that redacted this event, if any.
transaction_id string The client-supplied transaction ID, if the client being given the event is the same one which sent it.

Example request:

GET /_matrix/client/r0/events?from=s3456_9_0&timeout=35000&room_id=%21somewhere%3Aover.the.rainbow HTTP/1.1

Responses:

Status code 200:

The events received, which may be none.

Example

{
  "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"
    }
  ]
}

Status code 400:

Bad pagination from parameter.

11.16.2   Server behaviour

For clients which have not joined a room, servers are required to only return events where the room state at the event had the m.room.history_visibility state event present with history_visibility value world_readable.

11.16.3   Security considerations

Clients may wish to display to their users that rooms which are world_readable may be showing messages to non-joined users. There is no way using this module to find out whether any non-joined guest users do see events in the room, or to list or count any lurking users.

11.17   Room Tagging

Users can add tags to rooms. Tags are short strings used to label rooms, e.g. "work", "family". A room may have multiple tags. Tags are only visible to the user that set them but are shared across all their devices.

11.17.1   Events

The tags on a room are received as single m.tag event in the account_data section of a room in a /sync.

The m.tag can also be received in a /events response or in the account_data section of a room in /initialSync. m.tag events appearing in /events will have a room_id with the room the tags are for.

Each tag has an associated JSON object with information about the tag, e.g how to order the rooms with a given tag.

Ordering information is given under the order key as a string. The string are compared lexicographically by unicode codepoint to determine which should displayed first. So a room with a tag with an order key of "apples" would appear before a room with a tag with an order key of "oranges". If a room has a tag without an order key then it should appear after the rooms with that tag that have an order key.

The name of a tag MUST not exceed 255 bytes.

The name of a tag should be human readable. When displaying tags for a room a client should display this human readable name. When adding a tag for a room a client may offer a list to choose from that includes all the tags that the user has previously set on any of their rooms.

Two special names are listed in the specification:

  • m.favourite
  • m.lowpriority

11.17.1.1   m.tag

Informs the client of tags on a room.

Content Key Type Description
tags {string: Tag} The tags on the room and their contents.

Example:

{
    "content": {
        "tags": {
            "work": {
                "order": 1
            }
        }
    },
    "type": "m.tag"
}

Tags namespaces are defined in the following way, depending on how the client are expected to interpret them:

  • The namespace m.* is reserved for tags defined in the current specification
  • The namespace u.* is reserved for user-defined tags, and the client should not try to interpret as anything other than an utf8 string
  • A client or app willing to use special tags for advanced functionnality should namespace them similarly to state keys: tld.name.*
  • Any tag in the tld.name.* form but not matching the namespace of the current client should be ignored
  • Any tag not matching the previous rules should be interpreted as an user tag from the u.* namespace

11.17.2   Client Behaviour

11.17.2.1   GET /_matrix/client/r0/user/{userId}/rooms/{roomId}/tags

List the tags set by a user on a room.

Requires auth:Yes.

Request format:

Parameter Type Description
path parameters
userId string Required. The id of the user to get tags for. The access token must be authorized to make requests for this user id.
roomId string Required. The id of the room to get tags for.

Response format:

Parameter Type Description
tags Tags  

Example request:

GET /_matrix/client/r0/user/%40alice%3Aexample.com/rooms/%21726s6s6q%3Aexample.com/tags HTTP/1.1

Response:

Status code 200:

The list of tags for the user for the room.

Example

{
  "tags": {
    "work": {
      "order": "1"
    },
    "pinned": {}
  }
}

11.17.2.2   PUT /_matrix/client/r0/user/{userId}/rooms/{roomId}/tags/{tag}

Add a tag to the room.

Requires auth:Yes.

Request format:

Parameter Type Description
path parameters
userId string Required. The id of the user to add a tag for. The access token must be authorized to make requests for this user id.
roomId string Required. The id of the room to add a tag to.
tag string Required. The tag to add.

Example request:

PUT /_matrix/client/r0/user/%40alice%3Aexample.com/rooms/%21726s6s6q%3Aexample.com/tags/work HTTP/1.1
Content-Type: application/json

{
  "order": "1"
}

Response:

Status code 200:

The tag was successfully added.

Example

{}

11.17.2.3   DELETE /_matrix/client/r0/user/{userId}/rooms/{roomId}/tags/{tag}

Remove a tag from the room.

Requires auth:Yes.

Request format:

Parameter Type Description
path parameters
userId string Required. The id of the user to remove a tag for. The access token must be authorized to make requests for this user id.
roomId string Required. The id of the room to remove a tag from.
tag string Required. The tag to remove.

Example request:

DELETE /_matrix/client/r0/user/%40alice%3Aexample.com/rooms/%21726s6s6q%3Aexample.com/tags/work HTTP/1.1

Response:

Status code 200:

The tag was successfully removed

Example

{}

11.18   Client Config

Clients can store custom config data for their account on their homeserver. This account data will be synced between different devices and can persist across installations on a particular device. Users may only view the account data for their own account

The account_data may be either global or scoped to a particular rooms.

11.18.1   Events

The client recieves the account data as events in the account_data sections of a /sync.

These events can also be received in a /events response or in the account_data section of a room in /initialSync. m.tag events appearing in /events will have a room_id with the room the tags are for.

11.18.2   Client Behaviour

11.18.2.1   PUT /_matrix/client/r0/user/{userId}/account_data/{type}

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.

Requires auth:Yes.

Request format:

Parameter Type Description
path parameters
userId string Required. The id of the user to set account_data for. The access token must be authorized to make requests for this user id.
type string Required. The event type of the account_data to set. Custom types should be namespaced to avoid clashes.

Example request:

PUT /_matrix/client/r0/user/%40alice%3Aexample.com/account_data/org.example.custom.config HTTP/1.1
Content-Type: application/json

{
  "custom_account_data_key": "custom_config_value"
}

Response:

Status code 200:

The account_data was successfully added.

11.18.2.2   PUT /_matrix/client/r0/user/{userId}/rooms/{roomId}/account_data/{type}

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.

Requires auth:Yes.

Request format:

Parameter Type Description
path parameters
userId string Required. The id of the user to set account_data for. The access token must be authorized to make requests for this user id.
roomId string Required. The id of the room to set account_data on.
type string Required. The event type of the account_data to set. Custom types should be namespaced to avoid clashes.

Example request:

PUT /_matrix/client/r0/user/%40alice%3Aexample.com/rooms/%21726s6s6q%3Aexample.com/account_data/org.example.custom.room.config HTTP/1.1
Content-Type: application/json

{
  "custom_account_data_key": "custom_account_data_value"
}

Response:

Status code 200:

The account_data was successfully added.

11.19   Server Administration

This module adds capabilities for server administrators to inspect server state and data.

11.19.1   Client Behaviour

11.19.1.1   GET /_matrix/client/r0/admin/whois/{userId}

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.

Requires auth:Yes.

Request format:

Parameter Type Description
path parameters
userId string Required. The user to look up.

Response format:

Parameter Type Description
user_id string The Matrix user ID of the user.
devices {string: DeviceInfo} Each key is an identitfier for one of the user's devices.

DeviceInfo

Parameter Type Description
sessions [SessionInfo] A user's sessions (i.e. what they did with an access token from one login).

SessionInfo

Parameter Type Description
connections [ConnectionInfo] Information particular connections in the session.

ConnectionInfo

Parameter Type Description
ip string Most recently seen IP address of the session.
last_seen number Unix timestamp that the session was last active.
user_agent string User agent string last seen in the session.

Example request:

GET /_matrix/client/r0/admin/whois/%40peter%3Arabbit.rocks HTTP/1.1

Response:

Status code 200:

The lookup was successful.

Example

{
  "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"
            }
          ]
        }
      ]
    }
  }
}

11.20   Event Context

This API returns a number of events that happened just before and after the specified event. This allows clients to get the context surrounding an event.

11.20.1   Client behaviour

There is a single HTTP API for retrieving event context, documented below.

11.20.1.1   GET /_matrix/client/r0/rooms/{roomId}/context/{eventId}

This API returns a number of events that happened just before and after the specified event. This allows clients to get the context surrounding an event.

Requires auth:Yes.

Request format:

Parameter Type Description
path parameters
roomId string Required. The room to get events from.
eventId string Required. The event to get context around.
query parameters
limit integer The maximum number of events to return. Default: 10.

Response format:

Parameter Type Description
start string A token that can be used to paginate backwards with.
end string A token that can be used to paginate forwards with.
events_before [Room Event] A list of room events that happened just before the requested event, in reverse-chronological order.
event Room Event Details of the requested event.
events_after [Room Event] A list of room events that happened just after the requested event, in chronological order.
state [State Event] The state of the room at the last event returned.

Room Event

Parameter Type Description
content object The fields in this object will vary depending on the type of event. When interacting with the REST API, this is the HTTP body.
type string Required. The type of event. This SHOULD be namespaced similar to Java package naming conventions e.g. 'com.example.subdomain.event.type'
event_id string Required. The globally unique event identifier.
room_id string Required. The ID of the room associated with this event.
sender string Required. Contains the fully-qualified ID of the user who sent this event.
origin_server_ts number Required. Timestamp in milliseconds on originating homeserver when this event was sent.
unsigned UnsignedData Contains optional extra information about the event.

State Event

Parameter Type Description
content object The fields in this object will vary depending on the type of event. When interacting with the REST API, this is the HTTP body.
type string Required. The type of event. This SHOULD be namespaced similar to Java package naming conventions e.g. 'com.example.subdomain.event.type'
event_id string Required. The globally unique event identifier.
room_id string Required. The ID of the room associated with this event.
sender string Required. Contains the fully-qualified ID of the user who sent this event.
origin_server_ts number Required. Timestamp in milliseconds on originating homeserver when this event was sent.
unsigned UnsignedData Contains optional extra information about the event.
prev_content EventContent Optional. The previous content for this event. If there is no previous content, this key will be missing.
state_key string Required. A unique key which defines the overwriting semantics for this piece of room state. This value is often a zero-length string. The presence of this key makes this event a State Event. The key MUST NOT start with '_'.

UnsignedData

Parameter Type Description
age integer The time in milliseconds that has elapsed since the event was sent. This field is generated by the local homeserver, and may be incorrect if the local time on at least one of the two servers is out of sync, which can cause the age to either be negative or greater than it actually is.
redacted_because Event Optional. The event that redacted this event, if any.
transaction_id string The client-supplied transaction ID, if the client being given the event is the same one which sent it.

Example request:

GET /_matrix/client/r0/rooms/%21636q39766251%3Aexample.com/context/%24f3h4d129462ha%3Aexample.com?limit=3 HTTP/1.1

Response:

Status code 200:

The events and state surrounding the requested event.

Example

{
  "end": "t29-57_2_0_2",
  "events_after": [
    {
      "age": 91911336,
      "content": {
        "body": "7",
        "msgtype": "m.text"
      },
      "event_id": "$14460306086CiUaL:localhost:8480",
      "origin_server_ts": 1446030608551,
      "room_id": "!sCDvXTtzjpiPxaqkkt:localhost:8480",
      "type": "m.room.message",
      "sender": "@test:localhost:8480"
    }
  ],
  "events_before": [
    {
      "age": 91911903,
      "content": {
        "body": "5",
        "msgtype": "m.text"
      },
      "event_id": "$14460306074UYTlh:localhost:8480",
      "origin_server_ts": 1446030607984,
      "room_id": "!sCDvXTtzjpiPxaqkkt:localhost:8480",
      "type": "m.room.message",
      "sender": "@test:localhost:8480"
    }
  ],
  "start": "t27-54_2_0_2",
  "state": [
    {
      "age": 3123715284,
      "content": {
        "creator": "@test:localhost:8480"
      },
      "event_id": "$14429988040dgQAE:localhost:8480",
      "origin_server_ts": 1442998804603,
      "room_id": "!sCDvXTtzjpiPxaqkkt:localhost:8480",
      "state_key": "",
      "type": "m.room.create",
      "sender": "@test:localhost:8480"
    },
    {
      "age": 2067105053,
      "content": {
        "avatar_url": "mxc://localhost:8480/tVWZTAIIfqtXMZZtmGCkVjTD#auto",
        "displayname": "Bob2",
        "membership": "join"
      },
      "event_id": "$14440554144URDbf:localhost:8480",
      "origin_server_ts": 1444055414834,
      "replaces_state": "$14440552472PgiGk:localhost:8480",
      "room_id": "!sCDvXTtzjpiPxaqkkt:localhost:8480",
      "state_key": "@test:localhost:8480",
      "type": "m.room.member",
      "sender": "@test:localhost:8480"
    }
  ]
}

11.20.2   Security considerations

The server must only return results that the user has permission to see.

11.21   CAS-based client login

Central Authentication Service (CAS) is a web-based single sign-on protocol.

An overview of the process, as used in Matrix, is as follows:

  1. The Matrix client instructs the user's browser to navigate to the /login/cas/redirect endpoint on the user's homeserver.
  2. The homeserver responds with an HTTP redirect to the CAS user interface, which the browser follows.
  3. The CAS system authenticates the user.
  4. The CAS server responds to the user's browser with a redirect back to the /login/cas/ticket endpoint on the homeserver, which the browser follows. A 'ticket' identifier is passed as a query parameter in the redirect.
  5. The homeserver receives the ticket ID from the user's browser, and makes a request to the CAS server to validate the ticket.
  6. Having validated the ticket, the homeserver responds to the browser with a third HTTP redirect, back to the Matrix client application. A login token is passed as a query parameter in the redirect.
  7. The Matrix client receives the login token and passes it to the /login API.

11.21.1   Client behaviour

The client starts the process by instructing the browser to navigate to /login/cas/redirect with an appropriate redirectUrl. Once authentication is successful, the browser will be redirected to that redirectUrl.

11.21.1.1   GET /_matrix/client/r0/login/cas/redirect

A web-based Matrix client should instruct the user's browser to navigate to this endpoint in order to log in via CAS.

The server MUST respond with an HTTP redirect to the CAS interface. The URI MUST include a service parameter giving the path of the /login/cas/ticket endpoint (including the redirectUrl query parameter).

For example, if the endpoint is called with redirectUrl=https://client.example.com/?q=p, it might redirect to https://cas.example.com/?service=https%3A%2F%2Fserver.example.com%2F_matrix%2Fclient%2Fr0%2Flogin%2Fcas%2Fticket%3FredirectUrl%3Dhttps%253A%252F%252Fclient.example.com%252F%253Fq%253Dp.

Request format:

Parameter Type Description
query parameters
redirectUrl string Required. URI to which the user will be redirected after the homeserver has authenticated the user with CAS.

Example request:

GET /_matrix/client/r0/login/cas/redirect HTTP/1.1

Response:

Status code 302:

A redirect to the CAS interface.

11.21.1.2   GET /_matrix/client/r0/login/cas/ticket

Once the CAS server has authenticated the user, it will redirect the browser to this endpoint (assuming /login/cas/redirect gave it the correct service parameter).

The server MUST call /proxyValidate on the CAS server, to validate the ticket supplied by the browser.

If validation is successful, the server must generate a Matrix login token. It must then respond with an HTTP redirect to the URI given in the redirectUrl parameter, adding a loginToken query parameter giving the generated token.

If validation is unsuccessful, the server should respond with a 401 Unauthorized error, the body of which will be displayed to the user.

Request format:

Parameter Type Description
query parameters
redirectUrl string Required. The redirectUrl originally provided by the client to /login/cas/redirect.
ticket string Required. CAS authentication ticket.

Example request:

GET /_matrix/client/r0/login/cas/ticket HTTP/1.1

Responses:

Status code 302:

A redirect to the Matrix client.

Status code 401:

The server was unable to validate the CAS ticket.

11.21.2   Server behaviour

The URI for the CAS system to be used should be configured on the server by the server administrator.

11.21.2.1   Handling the redirect endpoint

When responding to the /login/cas/redirect endpoint, the server must generate a URI for the CAS login page. The server should take the base CAS URI described above, and add a service query parameter. This parameter MUST be the URI of the /login/cas/ticket endpoint, including the redirectUrl query parameter. Because the homeserver may not know its base URI, this may also require manual configuration.

11.21.2.2   Handling the authentication endpoint

When responding to the /login/cas/ticket endpoint, the server MUST make a request to the CAS server to validate the provided ticket. The server MAY also check for certain user attributes in the response. Any required attributes should be configured by the server administrator.

Once the ticket has been validated, the server MUST map the CAS user_id to a valid Matrix user identifier. The guidance in Mapping from other character sets may be useful.

If the generated user identifier represents a new user, it should be registered as a new user.

Finally, the server should generate a short-term login token. The generated token should be a macaroon, suitable for use with the m.login.token type of the /login API, and token-based interactive login. The lifetime of this token SHOULD be limited to around five seconds.

11.22   Direct Messaging

All communication over Matrix happens within a room. It is sometimes desirable to offer users the concept of speaking directly to one particular person. This module defines a way of marking certain rooms as 'direct chats' with a given person. This does not restrict the chat to being between exactly two people since this would preclude the presence of automated 'bot' users or even a 'personal assistant' who is able to answer direct messages on behalf of the user in their absence.

A room may not necessarily be considered 'direct' by all members of the room, but a signalling mechanism exists to propagate the information of whether a chat is 'direct' to an invitee.

11.22.1   Events

11.22.1.1   m.direct

A map of which rooms are considered 'direct' rooms for specific users is kept in account_data in an event of type m.direct. The content of this event is an object where the keys are the user IDs and values are lists of room ID strings of the 'direct' rooms for that user ID.

Example:

{
    "content": {
        "@bob:example.com": [
            "!abcdefgh:example.com",
            "!hgfedcba:example.com"
        ]
    },
    "type": "m.direct"
}

11.22.2   Client behaviour

To start a direct chat with another user, the inviting user's client should set the is_direct flag to /createRoom. The client should do this whenever the flow the user has followed is one where their intention is to speak directly with another person, as opposed to bringing that person in to a shared room. For example, clicking on 'Start Chat' beside a person's profile picture would imply the is_direct flag should be set.

The invitee's client may use the is_direct flag in the m.room.member event to automatically mark the room as a direct chat but this is not required: it may for example, prompt the user, or ignore the flag altogether.

Both the inviting client and the invitee's client should record the fact that the room is a direct chat by storing an m.direct event in the account data using /user/<user_id>/account_data/<type>.

11.22.3   Server behaviour

When the is_direct flag is given to /createRoom, the home server must set the is_direct flag in the invite member event for any users invited in the /createRoom call.