You're looking at an unstable version of this specification. Unstable specifications may change at any time without notice.

Switch to the current stable release.

Client-Server API

The client-server API allows clients to 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.

API Standards

The mandatory baseline for client-server communication in Matrix is exchanging JSON objects over HTTP APIs. More efficient transports may be specified in future as optional extensions.

HTTPS is recommended for communication. The use of plain HTTP is not recommended outside test environments.

Clients are authenticated using opaque access_token strings (see Client Authentication for details).

All POST and PUT endpoints, with the exception of POST /_matrix/media/v3/upload, require the client to supply a request body containing a (potentially empty) JSON object. Clients should supply a Content-Type header of application/json for all requests with JSON bodies, but this is not required.

Similarly, all endpoints require the server to return a JSON object, with the exception of 200 responses to GET /_matrix/media/v3/download/{serverName}/{mediaId} and GET /_matrix/media/v3/thumbnail/{serverName}/{mediaId}. Servers must include a Content-Type header of application/json for all JSON responses.

All JSON data, in requests or responses, must be encoded using UTF-8.

See also Conventions for Matrix APIs in the Appendices for conventions which all Matrix APIs are expected to follow, and Web Browser Clients below for additional requirements for server responses.

Standard error response

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. Error codes should have their namespace first in ALL CAPS, followed by a single _. 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. Error codes defined by this specification should start M_.

Some errcodes define additional keys which should be present in the error response object, but the keys error and errcode MUST always be present.

Errors are generally best expressed by their error code rather than the HTTP status code returned. When encountering the error code M_UNKNOWN, clients should prefer the HTTP status code as a more reliable reference for what the issue was. For example, if the client receives an error code of M_NOT_FOUND but the request gave a 400 Bad Request status code, the client should treat the error as if the resource was not found. However, if the client were to receive an error code of M_UNKNOWN with a 400 Bad Request, the client should assume that the request being made was invalid.

Common error codes

These error codes can be returned by any API endpoint:

M_FORBIDDEN Forbidden access, e.g. joining a room without permission, failed login.

M_UNKNOWN_TOKEN The access or refresh token specified was not recognised.

An additional response parameter, soft_logout, might be present on the response for 401 HTTP status codes. See the soft logout section for more information.

M_MISSING_TOKEN No access token was specified for the request.

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.

M_UNKNOWN An unknown error has occurred.

Other error codes

The following error codes are specific to certain endpoints.

M_UNRECOGNIZED The server did not understand the request.

M_UNAUTHORIZED The request was not correctly authorized. Usually due to login failures.

M_USER_DEACTIVATED The user ID associated with the request has been deactivated. Typically for endpoints that prove authentication, such as /login.

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 initial state given to the createRoom API is invalid.

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_THREEPID_AUTH_FAILED Authentication could not be performed on the third party identifier.

M_THREEPID_DENIED The server does not permit this third party identifier. This may happen if the server only permits, for example, email addresses from a particular domain.

M_SERVER_NOT_TRUSTED The client’s request used a third party server, e.g. identity server, that this server does not trust.

M_UNSUPPORTED_ROOM_VERSION The client’s request to create a room used a room version that the server does not support.

M_INCOMPATIBLE_ROOM_VERSION The client attempted to join a room that has a version the server does not support. Inspect the room_version property of the error response for the room’s version.

M_BAD_STATE The state change requested cannot be performed, such as attempting to unban a user who is not banned.

M_GUEST_ACCESS_FORBIDDEN The room or resource does not permit guests to access it.

M_CAPTCHA_NEEDED A Captcha is required to complete the request.

M_CAPTCHA_INVALID The Captcha provided did not match what was expected.

M_MISSING_PARAM A required parameter was missing from the request.

M_INVALID_PARAM A parameter that was specified has the wrong value. For example, the server expected an integer and instead received a string.

M_TOO_LARGE The request or entity was too large.

M_EXCLUSIVE The resource being requested is reserved by an application service, or the application service making the request has not created the resource.

M_RESOURCE_LIMIT_EXCEEDED The request cannot be completed because the homeserver has reached a resource limit imposed on it. For example, a homeserver held in a shared hosting environment may reach a resource limit if it starts using too much memory or disk space. The error MUST have an admin_contact field to provide the user receiving the error a place to reach out to. Typically, this error will appear on routes which attempt to modify state (e.g.: sending messages, account data, etc) and not routes which only read state (e.g.: /sync, get account data, etc).

M_CANNOT_LEAVE_SERVER_NOTICE_ROOM The user is unable to reject an invite to join the server notices room. See the Server Notices module for more information.

Transaction identifiers

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.

Web Browser Clients

It is realistic to expect that some clients will be written to be run within a web browser or similar environment. In these cases, the homeserver should respond to pre-flight requests and supply Cross-Origin Resource Sharing (CORS) headers on all requests.

Servers MUST expect that clients will approach them with OPTIONS requests, allowing clients to discover the CORS headers. All endpoints in this specification support the OPTIONS method, however the server MUST NOT perform any logic defined for the endpoints when approached with an OPTIONS request.

When a client approaches the server with a request, the server should respond with the CORS headers for that route. The recommended CORS headers to be returned by servers on all requests are:

Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS
Access-Control-Allow-Headers: X-Requested-With, Content-Type, Authorization

Server Discovery

In order to allow users to connect to a Matrix server without needing to explicitly specify the homeserver’s URL or other parameters, clients SHOULD use an auto-discovery mechanism to determine the server’s URL based on a user’s Matrix ID. Auto-discovery should only be done at login time.

In this section, the following terms are used with specific meanings:

PROMPT Retrieve the specific piece of information from the user in a way which fits within the existing client user experience, if the client is inclined to do so. Failure can take place instead if no good user experience for this is possible at this point.

IGNORE Stop the current auto-discovery mechanism. If no more auto-discovery mechanisms are available, then the client may use other methods of determining the required parameters, such as prompting the user, or using default values.

FAIL_PROMPT Inform the user that auto-discovery failed due to invalid/empty data and PROMPT for the parameter.

FAIL_ERROR Inform the user that auto-discovery did not return any usable URLs. Do not continue further with the current login process. At this point, valid data was obtained, but no server is available to serve the client. No further guess should be attempted and the user should make a conscientious decision what to do next.

Well-known URI

The .well-known method uses a JSON file at a predetermined location to specify parameter values. The flow for this method is as follows:

  1. Extract the server name from the user’s Matrix ID by splitting the Matrix ID at the first colon.
  2. Extract the hostname from the server name.
  3. Make a GET request to https://hostname/.well-known/matrix/client.
    1. If the returned status code is 404, then IGNORE.
    2. If the returned status code is not 200, or the response body is empty, then FAIL_PROMPT.
    3. Parse the response body as a JSON object
      1. If the content cannot be parsed, then FAIL_PROMPT.
    4. Extract the base_url value from the m.homeserver property. This value is to be used as the base URL of the homeserver.
      1. If this value is not provided, then FAIL_PROMPT.
    5. Validate the homeserver base URL:
      1. Parse it as a URL. If it is not a URL, then FAIL_ERROR.
      2. Clients SHOULD validate that the URL points to a valid homeserver before accepting it by connecting to the /_matrix/client/versions endpoint, ensuring that it does not return an error, and parsing and validating that the data conforms with the expected response format. If any step in the validation fails, then FAIL_ERROR. Validation is done as a simple check against configuration errors, in order to ensure that the discovered address points to a valid homeserver.
      3. It is important to note that the base_url value might include a trailing /. Consumers should be prepared to handle both cases.
    6. If the m.identity_server property is present, extract the base_url value for use as the base URL of the identity server. Validation for this URL is done as in the step above, but using /_matrix/identity/v2 as the endpoint to connect to. If the m.identity_server property is present, but does not have a base_url value, then FAIL_PROMPT.

GET /.well-known/matrix/client


Gets discovery information about the domain. The file may include additional keys, which MUST follow the Java package naming convention, e.g. com.example.myapp.property. This ensures property names are suitably namespaced for each application and reduces the risk of clashes.

Note that this endpoint is not necessarily handled by the homeserver, but by another webserver, to be used for discovering the homeserver URL.

Rate-limited: No
Requires authentication: No

Request

No request parameters or request body.


Responses

Status Description
200 Server discovery information.
404 No server discovery information available.

200 response

Discovery Information
Name Type Description
m.homeserver Homeserver Information Required: Used by clients to discover homeserver information.
m.identity_server Identity Server Information Used by clients to discover identity server information.
Homeserver Information
Name Type Description
base_url string Required: The base URL for the homeserver for client-server connections.
Identity Server Information
Name Type Description
base_url string Required: The base URL for the identity server for client-server connections.
{
  "m.homeserver": {
    "base_url": "https://matrix.example.com"
  },
  "m.identity_server": {
    "base_url": "https://identity.example.com"
  },
  "org.example.custom.property": {
    "app_url": "https://custom.app.example.org"
  }
}

GET /_matrix/client/versions


Gets the versions of the specification supported by the server.

Values will take the form vX.Y or rX.Y.Z in historical cases. See the Specification Versioning for more information.

The server may additionally advertise experimental features it supports through unstable_features. These features should be namespaced and may optionally include version information within their name if desired. Features listed here are not for optionally toggling parts of the Matrix specification and should only be used to advertise support for a feature which has not yet landed in the spec. For example, a feature currently undergoing the proposal process may appear here and eventually be taken off this list once the feature lands in the spec and the server deems it reasonable to do so. Servers may wish to keep advertising features here after they’ve been released into the spec to give clients a chance to upgrade appropriately. Additionally, clients should avoid using unstable features in their stable releases.

Rate-limited: No
Requires authentication: No

Request

No request parameters or request body.


Responses

Status Description
200 The versions supported by the server.

200 response

Name Type Description
unstable_features object Experimental features the server supports. Features not listed here, or the lack of this property all together, indicate that a feature is not supported.
versions [string] Required: The supported versions.
{
  "unstable_features": {
    "org.example.my_feature": true
  },
  "versions": [
    "r0.0.1",
    "v1.1"
  ]
}

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. Access tokens can expire; a new access token can be generated by using a refresh token.

Using access tokens

Access tokens may be provided in two ways, both of which the homeserver MUST support:

  1. Via a query string parameter, access_token=TheTokenHere.
  2. Via a request header, Authorization: Bearer TheTokenHere.

Clients are encouraged to use the Authorization header where possible to prevent the access token being leaked in access/HTTP logs. The query string should only be used in cases where the Authorization header is inaccessible for the client.

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 that an error code of M_UNKNOWN_TOKEN could mean one of four things:

  1. the access token was never valid.
  2. the access token has been logged out.
  3. the access token has been soft logged out.
  4. [Added in v1.3] the access token needs to be refreshed.

When a client receives an error code of M_UNKNOWN_TOKEN, it should:

  • attempt to refresh the token, if it has a refresh token;
  • if soft_logout is set to true, it can offer to re-log in the user, retaining any of the client’s persisted information;
  • otherwise, consider the user as having been logged out.

Relationship between access tokens and devices

Client devices are closely related to access tokens and refresh tokens. Matrix servers should record which device each access token and refresh token are assigned to, so that subsequent requests can be handled correctly. When a refresh token is used to generate a new access token and refresh token, the new access and refresh tokens are now bound to the device associated with the initial refresh token.

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 either 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 and refresh tokens previously assigned to that device.

Refreshing access tokens

[Added in v1.3]

Access tokens can expire after a certain amount of time. Any HTTP calls that use an expired access token will return with an error code M_UNKNOWN_TOKEN, preferably with soft_logout: true. When a client receives this error and it has a refresh token, it should attempt to refresh the access token by calling /refresh. Clients can also refresh their access token at any time, even if it has not yet expired. If the token refresh succeeds, the client should use the new token for future requests, and can re-try previously-failed requests with the new token. When an access token is refreshed, a new refresh token may be returned; if a new refresh token is given, the old refresh token will be invalidated, and the new refresh token should be used when the access token needs to be refreshed.

The old refresh token remains valid until the new access token or refresh token is used, at which point the old refresh token is revoked. This ensures that if a client fails to receive or persist the new tokens, it will be able to repeat the refresh operation.

If the token refresh fails and the error response included a soft_logout: true property, then the client can treat it as a soft logout and attempt to obtain a new access token by re-logging in. If the error response does not include a soft_logout: true property, the client should consider the user as being logged out.

Handling of clients that do not support refresh tokens is up to the homeserver; clients indicate their support for refresh tokens by including a refresh_token: true property in the request body of the /login and /register endpoints. For example, homeservers may allow the use of non-expiring access tokens, or may expire access tokens anyways and rely on soft logout behaviour on clients that don’t support refreshing.

Soft logout

A client can be in a “soft logout” state if the server requires re-authentication before continuing, but does not want to invalidate the client’s session. The server indicates that the client is in a soft logout state by including a soft_logout: true parameter in an M_UNKNOWN_TOKEN error response; the soft_logout parameter defaults to false. If the soft_logout parameter is omitted or is false, this means the server has destroyed the session and the client should not reuse it. That is, any persisted state held by the client, such as encryption keys and device information, must not be reused and must be discarded. If soft_logout is true the client can reuse any persisted state.

[Changed in v1.3]

A client that receives such a response can try to refresh its access token, if it has a refresh token available. If it does not have a refresh token available, or refreshing fails with soft_logout: true, the client can acquire a new access token by specifying the device ID it is already using to the login API.

User-Interactive Authentication API

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 single-sign-on server (SSO), 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 log in 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, however the flow’s stages must be completed in order. Failing to follow the flows in order must result in an HTTP 401 response, as defined below. When all stages in a flow are complete, authentication is complete and the API call succeeds.

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. 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 homeserver, if one is provided, in subsequent attempts to authenticate in the same API call.

The client then chooses a flow and attempts to complete the first stage. 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/v3/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. Completed stages cannot be retried by clients, therefore servers must return either a 401 response with the completed stages, or the result of the API call if all stages were completed when a client retries a stage.

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.

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

Authentication types

This specification defines the following auth types:

  • m.login.password
  • m.login.recaptcha
  • m.login.sso
  • m.login.email.identity
  • m.login.msisdn
  • m.login.dummy
  • m.login.registration_token
Password-based
Type Description
m.login.password The client submits an identifier 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",
  "identifier": {
    ...
  },
  "password": "<password>",
  "session": "<session ID>"
}

where the identifier property is a user identifier object, as described in Identifier types.

For example, to authenticate using the user’s Matrix ID, clients would submit:

{
  "type": "m.login.password",
  "identifier": {
    "type": "m.id.user",
    "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 than giving the user explicitly as follows:

{
  "type": "m.login.password",
  "identifier": {
    "type": "m.id.thirdparty",
    "medium": "<The medium of the third party identifier.>",
    "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.

Google ReCaptcha
Type Description
m.login.recaptcha 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>"
}
Single Sign-On
Type Description
m.login.sso Authentication is supported by authorising with an external single sign-on provider.

A client wanting to complete authentication using SSO should use the Fallback mechanism. See SSO during User-Interactive Authentication for more information.

Email-based (identity / homeserver)
Type Description
m.login.email.identity Authentication is supported by authorising an email address with an identity server, or homeserver if supported.

Prior to submitting this, the client should authenticate with an identity server (or homeserver). 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",
  "threepid_creds": {
    "sid": "<identity server session id>",
    "client_secret": "<identity server client secret>",
    "id_server": "<url of identity server authed with, e.g. 'matrix.org:8090'>",
    "id_access_token": "<access token previously registered with the identity server>"
  },
  "session": "<session ID>"
}

Note that id_server (and therefore id_access_token) is optional if the /requestToken request did not include them.

Phone number/MSISDN-based (identity / homeserver)
Type Description
m.login.msisdn Authentication is supported by authorising a phone number with an identity server, or homeserver if supported.

Prior to submitting this, the client should authenticate with an identity server (or homeserver). 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.msisdn",
  "threepid_creds": {
    "sid": "<identity server session id>",
    "client_secret": "<identity server client secret>",
    "id_server": "<url of identity server authed with, e.g. 'matrix.org:8090'>",
    "id_access_token": "<access token previously registered with the identity server>"
  },
  "session": "<session ID>"
}

Note that id_server (and therefore id_access_token) is optional if the /requestToken request did not include them.

Dummy Auth
Type Description
m.login.dummy Dummy authentication always succeeds and requires no extra parameters.

The purpose of dummy authentication is to allow servers to not require any form of User-Interactive Authentication to perform a request. It can also be used to differentiate flows where otherwise one flow would be a subset of another flow. e.g. if a server offers flows m.login.recaptcha and m.login.recaptcha, m.login.email.identity and the client completes the recaptcha stage first, the auth would succeed with the former flow, even if the client was intending to then complete the email auth stage. A server can instead send flows m.login.recaptcha, m.login.dummy and m.login.recaptcha, m.login.email.identity to fix the ambiguity.

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>"
}
Token-authenticated registration

[Added in v1.2]

Type Description
m.login.registration_token Registers an account with a pre-shared token for authentication

This authentication type provides homeservers the ability to allow registrations to a limited set of people instead of either offering completely open registrations or completely closed registration (where the homeserver administrators create and distribute accounts).

The token required for this authentication type is shared out of band from Matrix and is an opaque string with maximum length of 64 characters in the range [A-Za-z0-9._~-]. The server can keep any number of tokens for any length of time/validity. Such cases might be a token limited to 100 uses or for the next 2 hours - after the tokens expire, they can no longer be used to create accounts.

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

{
  "type": "m.login.registration_token",
  "token": "fBVFdqVE",
  "session": "<session ID>"
}

To determine if a token is valid before attempting to use it, the client can use the /validity API defined below. The API doesn’t guarantee that a token will be valid when used, but does avoid cases where the user finds out late in the registration process that their token has expired.

GET /_matrix/client/v1/register/m.login.registration_token/validity


Added in v1.2

Queries the server to determine if a given registration token is still valid at the time of request. This is a point-in-time check where the token might still expire by the time it is used.

Servers should be sure to rate limit this endpoint to avoid brute force attacks.

Rate-limited: Yes
Requires authentication: No

Request

Request parameters

query parameters
Name Type Description
token string Required: The token to check validity of.

Responses

Status Description
200 The check has a result.
403 The homeserver does not permit registration and thus all tokens are considered invalid.
429 This request was rate-limited.

200 response

Name Type Description
valid boolean Required: True if the token is still valid, false otherwise. This should additionally be false if the token is not a recognised token by the server.
{
  "valid": true
}

403 response

Error
Name Type Description
errcode string Required: An error code.
error string A human-readable error message.
{
  "errcode": "M_FORBIDDEN",
  "error": "Registration is not enabled on this homeserver."
}

429 response

RateLimitError
Name Type Description
errcode string Required: The M_LIMIT_EXCEEDED error code
error string A human-readable error message.
retry_after_ms integer The amount of time in milliseconds the client should wait before trying the request again.
{
  "errcode": "M_LIMIT_EXCEEDED",
  "error": "Too many requests",
  "retry_after_ms": 2000
}

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/v3/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 notification that the authentication stage has been completed, it should resubmit the request with an auth dict with just the session ID:

{
  "session": "<session ID>"
}
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 (e.g. "https://matrix.org")
 *
 *     apiEndpoint: the API endpoint being used (e.g.
 *        "/_matrix/client/v3/account/password")
 *
 *     loginType: the loginType being attempted (e.g. "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:apiEndpoint, json:requestBody,
        }, onComplete);
    };

    window.addEventListener("message", eventListener);

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

   popupWindow = window.open(url);
}

Identifier types

Some authentication mechanisms use a user identifier object to identify a user. The user identifier object has a type field to indicate the type of identifier being used, and depending on the type, has other fields giving the information required to identify the user as described below.

This specification defines the following identifier types:

  • m.id.user
  • m.id.thirdparty
  • m.id.phone
Matrix User ID
Type Description
m.id.user The user is identified by their Matrix ID.

A client can identify a user using their Matrix ID. This can either be the fully qualified Matrix user ID, or just the localpart of the user ID.

"identifier": {
  "type": "m.id.user",
  "user": "<user_id or user localpart>"
}
Third-party ID
Type Description
m.id.thirdparty The user is identified by a third-party identifier in canonicalised form.

A client can identify a user using a 3PID associated with the user’s account on the homeserver, where the 3PID was previously associated using the /account/3pid_ API. See the 3PID Types Appendix for a list of Third-party ID media.

"identifier": {
  "type": "m.id.thirdparty",
  "medium": "<The medium of the third party identifier>",
  "address": "<The canonicalised third party address of the user>"
}
Phone number
Type Description
m.id.phone The user is identified by a phone number.

A client can identify a user using a phone number associated with the user’s account, where the phone number was previously associated using the /account/3pid_ API. The phone number can be passed in as entered by the user; the homeserver will be responsible for canonicalising it. If the client wishes to canonicalise the phone number, then it can use the m.id.thirdparty identifier type with a medium of msisdn instead.

"identifier": {
  "type": "m.id.phone",
  "country": "<The country that the phone number is from>",
  "phone": "<The phone number>"
}

The country is the two-letter uppercase ISO-3166-1 alpha-2 country code that the number in phone should be parsed as if it were dialled from.

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",
  "identifier": {
    "type": "m.id.user",
    "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 than giving the user explicitly, as follows:

{
  "type": "m.login.password",
  "identifier": {
    "medium": "<The medium of the third party identifier>",
    "address": "<The canonicalised 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>"
}

The token must encode the user ID, since there is no other identifying data in the request. In the case that the token is not valid, the homeserver must respond with 403 Forbidden and an error code of M_FORBIDDEN.

If the homeserver advertises m.login.sso as a viable flow, and the client supports it, the client should redirect the user to the /redirect endpoint for client login via SSO. After authentication is complete, the client will need to submit a /login request matching m.login.token.

Appservice Login

[Added in v1.2]

An appservice can log in by providing a valid appservice token and a user within the appservice’s namespace.

This request must be authenticated by the appservice as_token (see Client Authentication on how to provide the token).

To use this login type, clients should submit a /login request as follows:

{
  "type": "m.login.application_service",
  "identifier": {
    "type": "m.id.user",
    "user": "<user_id or user localpart>"
  }
}

If the access token is not valid, does not correspond to an appservice or the user has not previously been registered then the homeserver will respond with an errcode of M_FORBIDDEN.

If the access token does correspond to an appservice, but the user id does not lie within its namespace then the homeserver will respond with an errcode of M_EXCLUSIVE.

GET /_matrix/client/v3/login


Gets the homeserver’s supported login types to authenticate users. Clients should pick one of these and supply it as the type when logging in.

Rate-limited: Yes
Requires authentication: No

Request

No request parameters or request body.


Responses

Status Description
200 The login types the homeserver supports
429 This request was rate-limited.

200 response

Name Type Description
flows [LoginFlow] The homeserver’s supported login types
LoginFlow
Name Type Description
type string The login type. This is supplied as the type when logging in.
{
  "flows": [
    {
      "type": "m.login.password"
    }
  ]
}

429 response

RateLimitError
Name Type Description
errcode string Required: The M_LIMIT_EXCEEDED error code
error string A human-readable error message.
retry_after_ms integer The amount of time in milliseconds the client should wait before trying the request again.
{
  "errcode": "M_LIMIT_EXCEEDED",
  "error": "Too many requests",
  "retry_after_ms": 2000
}

POST /_matrix/client/v3/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
Requires authentication: No

Request

Request body

Name Type Description
address string Third party identifier for the user. Deprecated in favour of identifier.
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 given device ID must not be the same as a cross-signing key ID. The server will auto-generate a device_id if this is not specified.
identifier User identifier Identification information for a user
initial_device_display_name string A display name to assign to the newly-created device. Ignored if device_id corresponds to a known device.
medium string When logging in using a third party identifier, the medium of the identifier. Must be ’email’. Deprecated in favour of identifier.
password string Required when type is m.login.password. The user’s password.
refresh_token boolean If true, the client supports refresh tokens.

Added in v1.3

token string Required when type is m.login.token. Part of Token-based login.
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. Deprecated in favour of identifier.
User identifier
Name Type Description
type string Required: The type of identification. See Identifier types for supported values and additional property descriptions.

Request body example

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

Responses

Status Description
200 The user has been authenticated.
400 Part of the request was invalid. For example, the login type may not be recognised.
403

The login attempt failed. This can include one of the following error codes:

  • M_FORBIDDEN: The provided authentication data was incorrect or the requested device ID is the same as a cross-signing key ID.
  • M_USER_DEACTIVATED: The user has been deactivated.
429 This request was rate-limited.

200 response

Name Type Description
access_token string An access token for the account. This access token can then be used to authorize other requests.
device_id string ID of the logged-in device. Will be the same as the corresponding parameter in the request, if one was specified.
expires_in_ms integer The lifetime of the access token, in milliseconds. Once the access token has expired a new access token can be obtained by using the provided refresh token. If no refresh token is provided, the client will need to re-log in to obtain a new access token. If not given, the client can assume that the access token will not expire.

Added in v1.3

home_server string

The server_name of the homeserver on which the account has been registered.

Deprecated. Clients should extract the server_name from user_id (by splitting at the first colon) if they require it. Note also that homeserver is not spelt this way.

refresh_token string A refresh token for the account. This token can be used to obtain a new access token when it expires by calling the /refresh endpoint.

Added in v1.3

user_id string The fully-qualified Matrix ID for the account.
well_known Discovery Information Optional client configuration provided by the server. If present, clients SHOULD use the provided object to reconfigure themselves, optionally validating the URLs within. This object takes the same form as the one returned from .well-known autodiscovery.
Discovery Information
Name Type Description
m.homeserver Homeserver Information Required: Used by clients to discover homeserver information.
m.identity_server Identity Server Information Used by clients to discover identity server information.
Homeserver Information
Name Type Description
base_url string Required: The base URL for the homeserver for client-server connections.
Identity Server Information
Name Type Description
base_url string Required: The base URL for the identity server for client-server connections.
{
  "access_token": "abc123",
  "device_id": "GHTYAJCE",
  "expires_in_ms": 60000,
  "refresh_token": "def456",
  "user_id": "@cheeky_monkey:matrix.org",
  "well_known": {
    "m.homeserver": {
      "base_url": "https://example.org"
    },
    "m.identity_server": {
      "base_url": "https://id.example.org"
    }
  }
}

400 response

Error
Name Type Description
errcode string Required: An error code.
error string A human-readable error message.
{
  "errcode": "M_UNKNOWN",
  "error": "Bad login type."
}

403 response

Error
Name Type Description
errcode string Required: An error code.
error string A human-readable error message.
{
  "errcode": "M_FORBIDDEN"
}

429 response

RateLimitError
Name Type Description
errcode string Required: The M_LIMIT_EXCEEDED error code
error string A human-readable error message.
retry_after_ms integer The amount of time in milliseconds the client should wait before trying the request again.
{
  "errcode": "M_LIMIT_EXCEEDED",
  "error": "Too many requests",
  "retry_after_ms": 2000
}

POST /_matrix/client/v3/refresh


Added in v1.3

Refresh an access token. Clients should use the returned access token when making subsequent API calls, and store the returned refresh token (if given) in order to refresh the new access token when necessary.

After an access token has been refreshed, a server can choose to invalidate the old access token immediately, or can choose not to, for example if the access token would expire soon anyways. Clients should not make any assumptions about the old access token still being valid, and should use the newly provided access token instead.

The old refresh token remains valid until the new access token or refresh token is used, at which point the old refresh token is revoked.

Note that this endpoint does not require authentication via an access token. Authentication is provided via the refresh token.

Application Service identity assertion is disabled for this endpoint.

Rate-limited: Yes
Requires authentication: No

Request

Request body

Name Type Description
refresh_token string The refresh token

Request body example

{
  "refresh_token": "some_token"
}

Responses

Status Description
200 A new access token and refresh token were generated.
401 The provided token was unknown, or has already been used.
429 This request was rate-limited.

200 response

Name Type Description
access_token string Required: The new access token to use.
expires_in_ms integer The lifetime of the access token, in milliseconds. If not given, the client can assume that the access token will not expire.
refresh_token string The new refresh token to use when the access token needs to be refreshed again. If not given, the old refresh token can be re-used.
{
  "access_token": "a_new_token",
  "expires_in_ms": 60000,
  "refresh_token": "another_new_token"
}

401 response

Error
Name Type Description
errcode string Required: An error code.
error string A human-readable error message.
{
  "errcode": "M_UNKNOWN_TOKEN",
  "error": "Soft logged out",
  "soft_logout": true
}

429 response

RateLimitError
Name Type Description
errcode string Required: The M_LIMIT_EXCEEDED error code
error string A human-readable error message.
retry_after_ms integer The amount of time in milliseconds the client should wait before trying the request again.
{
  "errcode": "M_LIMIT_EXCEEDED",
  "error": "Too many requests",
  "retry_after_ms": 2000
}

POST /_matrix/client/v3/logout


Invalidates an existing access token, so that it can no longer be used for authorization. The device associated with the access token is also deleted. Device keys for the device are deleted alongside the device.

Rate-limited: No
Requires authentication: Yes

Request

No request parameters or request body.


Responses

Status Description
200 The access token used in the request was successfully invalidated.

200 response

{}

POST /_matrix/client/v3/logout/all


Invalidates all access tokens for a user, so that they can no longer be used for authorization. This includes the access token that made this request. All devices for the user are also deleted. Device keys for the device are deleted alongside the device.

This endpoint does not use the User-Interactive Authentication API because User-Interactive Authentication is designed to protect against attacks where the someone gets hold of a single access token then takes over the account. This endpoint invalidates all access tokens for the user, including the token used in the request, and therefore the attacker is unable to take over the account in this way.

Rate-limited: No
Requires authentication: Yes

Request

No request parameters or request body.


Responses

Status Description
200 The user’s access tokens were successfully invalidated.

200 response

{}

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.

[Added in v1.1]

Non-credential parameters valid for the /login endpoint can be provided as query string parameters here. These are to be forwarded to the login endpoint during the login process. For example:

GET /_matrix/static/client/login/?device_id=GHTYAJCE

Account registration and management

POST /_matrix/client/v3/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.

Unlike other endpoints, this endpoint does not take an id_access_token parameter because the homeserver is expected to sign the request to the identity server instead.

Rate-limited: Yes
Requires authentication: Yes

Request

Request body

Name Type Description
auth Authentication Data Additional authentication information for the user-interactive authentication API.
id_server string The identity server to unbind all of the user’s 3PIDs from. If not provided, the homeserver MUST use the id_server that was originally use to bind each identifier. If the homeserver does not know which id_server that was, it must return an id_server_unbind_result of no-support.
Authentication Data
Name Type Description
session string The value of the session key given by the homeserver.
type string The authentication type that the client is attempting to complete. May be omitted if session is given, and the client is reissuing a request which it believes has been completed out-of-band (for example, via the fallback mechanism).

Request body example

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

Responses

Status Description
200 The account has been deactivated.
401 The homeserver requires additional authentication information.
429 This request was rate-limited.

200 response

Name Type Description
id_server_unbind_result enum Required: An indicator as to whether or not the homeserver was able to unbind the user’s 3PIDs from the identity server(s). success indicates that all identifiers have been unbound from the identity server while no-support indicates that one or more identifiers failed to unbind due to the identity server refusing the request or the homeserver being unable to determine an identity server to unbind from. This must be success if the homeserver has no identifiers to unbind for the user.

One of: [success no-support].

{
  "id_server_unbind_result": "success"
}

401 response

Authentication response
Name Type Description
completed [string] A list of the stages the client has completed successfully
flows [Flow information] Required: A list of the login flows supported by the server for this API.
params object Contains any information that the client will need to know in order to use a given type of authentication. For each login 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 string 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.
Flow information
Name Type Description
stages [string] Required: The login type of each of the stages required to complete this authentication flow
{
  "completed": [
    "example.type.foo"
  ],
  "flows": [
    {
      "stages": [
        "example.type.foo"
      ]
    }
  ],
  "params": {
    "example.type.baz": {
      "example_key": "foobar"
    }
  },
  "session": "xxxxxxyz"
}

429 response

RateLimitError
Name Type Description
errcode string Required: The M_LIMIT_EXCEEDED error code
error string A human-readable error message.
retry_after_ms integer The amount of time in milliseconds the client should wait before trying the request again.
{
  "errcode": "M_LIMIT_EXCEEDED",
  "error": "Too many requests",
  "retry_after_ms": 2000
}

POST /_matrix/client/v3/account/password


Changes the password for an account on this homeserver.

This API endpoint uses the User-Interactive Authentication API to ensure the user changing the password is actually the owner of the account.

An access token should be submitted to this endpoint if the client has an active session.

The homeserver may change the flows available depending on whether a valid access token is provided. The homeserver SHOULD NOT revoke the access token provided in the request. Whether other access tokens for the user are revoked depends on the request parameters.

Rate-limited: Yes
Requires authentication: Yes

Request

Request body

Name Type Description
auth Authentication Data Additional authentication information for the user-interactive authentication API.
logout_devices boolean

Whether the user’s other access tokens, and their associated devices, should be revoked if the request succeeds. Defaults to true.

When false, the server can still take advantage of the soft logout method for the user’s remaining devices.

new_password string Required: The new password for the account.
Authentication Data
Name Type Description
session string The value of the session key given by the homeserver.
type string The authentication type that the client is attempting to complete. May be omitted if session is given, and the client is reissuing a request which it believes has been completed out-of-band (for example, via the fallback mechanism).

Request body example

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

Responses

Status Description
200 The password has been changed.
401 The homeserver requires additional authentication information.
429 This request was rate-limited.

200 response

{}

401 response

Authentication response
Name Type Description
completed [string] A list of the stages the client has completed successfully
flows [Flow information] Required: A list of the login flows supported by the server for this API.
params object Contains any information that the client will need to know in order to use a given type of authentication. For each login 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 string 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.
Flow information
Name Type Description
stages [string] Required: The login type of each of the stages required to complete this authentication flow
{
  "completed": [
    "example.type.foo"
  ],
  "flows": [
    {
      "stages": [
        "example.type.foo"
      ]
    }
  ],
  "params": {
    "example.type.baz": {
      "example_key": "foobar"
    }
  },
  "session": "xxxxxxyz"
}

429 response

RateLimitError
Name Type Description
errcode string Required: The M_LIMIT_EXCEEDED error code
error string A human-readable error message.
retry_after_ms integer The amount of time in milliseconds the client should wait before trying the request again.
{
  "errcode": "M_LIMIT_EXCEEDED",
  "error": "Too many requests",
  "retry_after_ms": 2000
}

POST /_matrix/client/v3/account/password/email/requestToken


The homeserver must check that the given email address is associated with an account on this homeserver. This API should be used to request validation tokens when authenticating for the /account/password endpoint.

This API’s parameters and response are identical to that of the /register/email/requestToken endpoint, except that M_THREEPID_NOT_FOUND may be returned if no account matching the given email address could be found. The server may instead send an email to the given address prompting the user to create an account. M_THREEPID_IN_USE may not be returned.

The homeserver should validate the email itself, either by sending a validation email itself or by using a service it has control over.

Rate-limited: No
Requires authentication: No

Request

Request body

Name Type Description
client_secret string Required: A unique string generated by the client, and used to identify the validation attempt. It must be a string consisting of the characters [0-9a-zA-Z.=_-]. Its length must not exceed 255 characters and it must not be empty.
email string Required: The email address to validate.
id_access_token string

An access token previously registered with the identity server. Servers can treat this as optional to distinguish between r0.5-compatible clients and this specification version.

Required if an id_server is supplied.

id_server string

The hostname of the identity server to communicate with. May optionally include a port. This parameter is ignored when the homeserver handles 3PID verification.

This parameter is deprecated with a plan to be removed in a future specification version for /account/password and /register requests.

next_link string Optional. When the validation is completed, the identity server will redirect the user to this URL. This option is ignored when submitting 3PID validation information through a POST request.
send_attempt integer Required: The server will only send an email if the send_attempt is a number greater than the most recent one which it has seen, scoped to that email + client_secret pair. This is to avoid repeatedly sending the same email in the case of request retries between the POSTing user and the identity server. The client should increment this value if they desire a new email (e.g. a reminder) to be sent. If they do not, the server should respond with success but not resend the email.

Request body example

{
  "client_secret": "monkeys_are_GREAT",
  "email": "[email protected]",
  "id_server": "id.example.com",
  "next_link": "https://example.org/congratulations.html",
  "send_attempt": 1
}

Responses

Status Description
200 An email was sent to the given address.
400 The referenced third party identifier is not recognised by the homeserver, or the request was invalid. The error code M_SERVER_NOT_TRUSTED can be returned if the server does not trust/support the identity server provided in the request.
403 The homeserver does not allow the third party identifier as a contact option.

200 response

RequestTokenResponse
Name Type Description
sid string Required: The session ID. Session IDs are opaque strings that must consist entirely of the characters [0-9a-zA-Z.=_-]. Their length must not exceed 255 characters and they must not be empty.
submit_url string

An optional field containing a URL where the client must submit the validation token to, with identical parameters to the Identity Service API’s POST /validate/email/submitToken endpoint (without the requirement for an access token). The homeserver must send this token to the user (if applicable), who should then be prompted to provide it to the client.

If this field is not present, the client can assume that verification will happen without the client’s involvement provided the homeserver advertises this specification version in the /versions response (ie: r0.5.0).

{
  "sid": "123abc",
  "submit_url": "https://example.org/path/to/submitToken"
}

400 response

Error
Name Type Description
errcode string Required: An error code.
error string A human-readable error message.
{
  "errcode": "M_THREEPID_NOT_FOUND",
  "error": "Email not found"
}

403 response

Error
Name Type Description
errcode string Required: An error code.
error string A human-readable error message.
{
  "errcode": "M_THREEPID_DENIED",
  "error": "Third party identifier is not allowed"
}

POST /_matrix/client/v3/account/password/msisdn/requestToken


The homeserver must check that the given phone number is associated with an account on this homeserver. This API should be used to request validation tokens when authenticating for the /account/password endpoint.

This API’s parameters and response are identical to that of the /register/msisdn/requestToken endpoint, except that M_THREEPID_NOT_FOUND may be returned if no account matching the given phone number could be found. The server may instead send the SMS to the given phone number prompting the user to create an account. M_THREEPID_IN_USE may not be returned.

The homeserver should validate the phone number itself, either by sending a validation message itself or by using a service it has control over.

Rate-limited: No
Requires authentication: No

Request

Request body

Name Type Description
client_secret string Required: A unique string generated by the client, and used to identify the validation attempt. It must be a string consisting of the characters [0-9a-zA-Z.=_-]. Its length must not exceed 255 characters and it must not be empty.
country string Required: The two-letter uppercase ISO-3166-1 alpha-2 country code that the number in phone_number should be parsed as if it were dialled from.
id_access_token string

An access token previously registered with the identity server. Servers can treat this as optional to distinguish between r0.5-compatible clients and this specification version.

Required if an id_server is supplied.

id_server string

The hostname of the identity server to communicate with. May optionally include a port. This parameter is ignored when the homeserver handles 3PID verification.

This parameter is deprecated with a plan to be removed in a future specification version for /account/password and /register requests.

next_link string Optional. When the validation is completed, the identity server will redirect the user to this URL. This option is ignored when submitting 3PID validation information through a POST request.
phone_number string Required: The phone number to validate.
send_attempt integer Required: The server will only send an SMS if the send_attempt is a number greater than the most recent one which it has seen, scoped to that country + phone_number + client_secret triple. This is to avoid repeatedly sending the same SMS in the case of request retries between the POSTing user and the identity server. The client should increment this value if they desire a new SMS (e.g. a reminder) to be sent.

Request body example

{
  "client_secret": "monkeys_are_GREAT",
  "country": "GB",
  "id_server": "id.example.com",
  "next_link": "https://example.org/congratulations.html",
  "phone_number": "07700900001",
  "send_attempt": 1
}

Responses

Status Description
200 An SMS message was sent to the given phone number.
400 The referenced third party identifier is not recognised by the homeserver, or the request was invalid. The error code M_SERVER_NOT_TRUSTED can be returned if the server does not trust/support the identity server provided in the request.
403 The homeserver does not allow the third party identifier as a contact option.

200 response

RequestTokenResponse
Name Type Description
sid string Required: The session ID. Session IDs are opaque strings that must consist entirely of the characters [0-9a-zA-Z.=_-]. Their length must not exceed 255 characters and they must not be empty.
submit_url string

An optional field containing a URL where the client must submit the validation token to, with identical parameters to the Identity Service API’s POST /validate/email/submitToken endpoint (without the requirement for an access token). The homeserver must send this token to the user (if applicable), who should then be prompted to provide it to the client.

If this field is not present, the client can assume that verification will happen without the client’s involvement provided the homeserver advertises this specification version in the /versions response (ie: r0.5.0).

{
  "sid": "123abc",
  "submit_url": "https://example.org/path/to/submitToken"
}

400 response

Error
Name Type Description
errcode string Required: An error code.
error string A human-readable error message.
{
  "errcode": "M_THREEPID_NOT_FOUND",
  "error": "Phone number not found"
}

403 response

Error
Name Type Description
errcode string Required: An error code.
error string A human-readable error message.
{
  "errcode": "M_THREEPID_DENIED",
  "error": "Third party identifier is not allowed"
}

POST /_matrix/client/v3/register


This API endpoint uses the User-Interactive Authentication API, except in the cases where a guest account is being registered.

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 username\s 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.

When registering a guest account, all parameters in the request body with the exception of initial_device_display_name MUST BE ignored by the server. The server MUST pick a device_id for the account regardless of input.

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

Rate-limited: Yes
Requires authentication: No

Request

Request parameters

query parameters
Name Type Description
kind enum The kind of account to register. Defaults to user.

One of: [guest user].

Request body

Name Type Description
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.
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.
inhibit_login boolean If true, an access_token and device_id should not be returned from this call, therefore preventing an automatic login. Defaults to false.
initial_device_display_name string A display name to assign to the newly-created device. Ignored if device_id corresponds to a known device.
password string The desired password for the account.
refresh_token boolean If true, the client supports refresh tokens.

Added in v1.3

username string The basis for the localpart of the desired Matrix ID. If omitted, the homeserver MUST generate a Matrix ID local part.
Authentication Data
Name Type Description
session string The value of the session key given by the homeserver.
type string The authentication type that the client is attempting to complete. May be omitted if session is given, and the client is reissuing a request which it believes has been completed out-of-band (for example, via the fallback mechanism).

Request body example

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

Responses

Status Description
200 The account has been registered.
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.

401 The homeserver requires additional authentication information.
403 The homeserver does not permit registering the account. This response can be used to identify that a particular kind of account is not allowed, or that registration is generally not supported by the homeserver.
429 This request was rate-limited.

200 response

Name Type Description
access_token string An access token for the account. This access token can then be used to authorize other requests. Required if the inhibit_login option is false.
device_id string ID of the registered device. Will be the same as the corresponding parameter in the request, if one was specified. Required if the inhibit_login option is false.
expires_in_ms integer

The lifetime of the access token, in milliseconds. Once the access token has expired a new access token can be obtained by using the provided refresh token. If no refresh token is provided, the client will need to re-log in to obtain a new access token. If not given, the client can assume that the access token will not expire.

Omitted if the inhibit_login option is true.

Added in v1.3

home_server string

The server_name of the homeserver on which the account has been registered.

Deprecated. Clients should extract the server_name from user_id (by splitting at the first colon) if they require it. Note also that homeserver is not spelt this way.

refresh_token string

A refresh token for the account. This token can be used to obtain a new access token when it expires by calling the /refresh endpoint.

Omitted if the inhibit_login option is true.

Added in v1.3

user_id string Required:

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": "abc123",
  "device_id": "GHTYAJCE",
  "user_id": "@cheeky_monkey:matrix.org"
}

400 response

Error
Name Type Description
errcode string Required: An error code.
error string A human-readable error message.
{
  "errcode": "M_USER_IN_USE",
  "error": "Desired user ID is already taken."
}

401 response

Authentication response
Name Type Description
completed [string] A list of the stages the client has completed successfully
flows [Flow information] Required: A list of the login flows supported by the server for this API.
params object Contains any information that the client will need to know in order to use a given type of authentication. For each login 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 string 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.
Flow information
Name Type Description
stages [string] Required: The login type of each of the stages required to complete this authentication flow
{
  "completed": [
    "example.type.foo"
  ],
  "flows": [
    {
      "stages": [
        "example.type.foo"
      ]
    }
  ],
  "params": {
    "example.type.baz": {
      "example_key": "foobar"
    }
  },
  "session": "xxxxxxyz"
}

403 response

Error
Name Type Description
errcode string Required: An error code.
error string A human-readable error message.
{
  "errcode": "M_FORBIDDEN",
  "error": "Registration is disabled"
}

429 response

RateLimitError
Name Type Description
errcode string Required: The M_LIMIT_EXCEEDED error code
error string A human-readable error message.
retry_after_ms integer The amount of time in milliseconds the client should wait before trying the request again.
{
  "errcode": "M_LIMIT_EXCEEDED",
  "error": "Too many requests",
  "retry_after_ms": 2000
}

GET /_matrix/client/v3/register/available


Checks to see if a username is available, and valid, for the server.

The server should check to ensure that, at the time of the request, the username requested is available for use. This includes verifying that an application service has not claimed the username and that the username fits the server’s desired requirements (for example, a server could dictate that it does not permit usernames with underscores).

Matrix clients may wish to use this API prior to attempting registration, however the clients must also be aware that using this API does not normally reserve the username. This can mean that the username becomes unavailable between checking its availability and attempting to register it.

Rate-limited: Yes
Requires authentication: No

Request

Request parameters

query parameters
Name Type Description
username string Required: The username to check the availability of.

Responses

Status Description
200 The username is available
400

Part of the request was invalid or the username is not available. This may include one of the following error codes:

  • M_USER_IN_USE : The desired username is already taken.
  • M_INVALID_USERNAME : The desired username is not a valid user name.
  • M_EXCLUSIVE : The desired username is in the exclusive namespace claimed by an application service.
429 This request was rate-limited.

200 response

Name Type Description
available boolean A flag to indicate that the username is available. This should always be true when the server replies with 200 OK.
{
  "available": true
}

400 response

Error
Name Type Description
errcode string Required: An error code.
error string A human-readable error message.
{
  "errcode": "M_USER_IN_USE",
  "error": "Desired user ID is already taken."
}

429 response

RateLimitError
Name Type Description
errcode string Required: The M_LIMIT_EXCEEDED error code
error string A human-readable error message.
retry_after_ms integer The amount of time in milliseconds the client should wait before trying the request again.
{
  "errcode": "M_LIMIT_EXCEEDED",
  "error": "Too many requests",
  "retry_after_ms": 2000
}

POST /_matrix/client/v3/register/email/requestToken


The homeserver must check that the given email address is not already associated with an account on this homeserver. The homeserver should validate the email itself, either by sending a validation email itself or by using a service it has control over.

Rate-limited: No
Requires authentication: No

Request

Request body

Name Type Description
client_secret string Required: A unique string generated by the client, and used to identify the validation attempt. It must be a string consisting of the characters [0-9a-zA-Z.=_-]. Its length must not exceed 255 characters and it must not be empty.
email string Required: The email address to validate.
id_access_token string

An access token previously registered with the identity server. Servers can treat this as optional to distinguish between r0.5-compatible clients and this specification version.

Required if an id_server is supplied.

id_server string

The hostname of the identity server to communicate with. May optionally include a port. This parameter is ignored when the homeserver handles 3PID verification.

This parameter is deprecated with a plan to be removed in a future specification version for /account/password and /register requests.

next_link string Optional. When the validation is completed, the identity server will redirect the user to this URL. This option is ignored when submitting 3PID validation information through a POST request.
send_attempt integer Required: The server will only send an email if the send_attempt is a number greater than the most recent one which it has seen, scoped to that email + client_secret pair. This is to avoid repeatedly sending the same email in the case of request retries between the POSTing user and the identity server. The client should increment this value if they desire a new email (e.g. a reminder) to be sent. If they do not, the server should respond with success but not resend the email.

Request body example

{
  "client_secret": "monkeys_are_GREAT",
  "email": "[email protected]",
  "id_server": "id.example.com",
  "next_link": "https://example.org/congratulations.html",
  "send_attempt": 1
}

Responses

Status Description
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.
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 homeserver 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 homeserver in question.
  • M_SERVER_NOT_TRUSTED : The id_server parameter refers to an identity server that is not trusted by this homeserver.
403 The homeserver does not permit the address to be bound.

200 response

RequestTokenResponse
Name Type Description
sid string Required: The session ID. Session IDs are opaque strings that must consist entirely of the characters [0-9a-zA-Z.=_-]. Their length must not exceed 255 characters and they must not be empty.
submit_url string

An optional field containing a URL where the client must submit the validation token to, with identical parameters to the Identity Service API’s POST /validate/email/submitToken endpoint (without the requirement for an access token). The homeserver must send this token to the user (if applicable), who should then be prompted to provide it to the client.

If this field is not present, the client can assume that verification will happen without the client’s involvement provided the homeserver advertises this specification version in the /versions response (ie: r0.5.0).

{
  "sid": "123abc",
  "submit_url": "https://example.org/path/to/submitToken"
}

400 response

Error
Name Type Description
errcode string Required: An error code.
error string A human-readable error message.
{
  "errcode": "M_THREEPID_IN_USE",
  "error": "The specified address is already in use"
}

403 response

Error
Name Type Description
errcode string Required: An error code.
error string A human-readable error message.
{
  "errcode": "M_THREEPID_DENIED",
  "error": "Third party identifier is not allowed"
}

POST /_matrix/client/v3/register/msisdn/requestToken


The homeserver must check that the given phone number is not already associated with an account on this homeserver. The homeserver should validate the phone number itself, either by sending a validation message itself or by using a service it has control over.

Rate-limited: No
Requires authentication: No

Request

Request body

Name Type Description
client_secret string Required: A unique string generated by the client, and used to identify the validation attempt. It must be a string consisting of the characters [0-9a-zA-Z.=_-]. Its length must not exceed 255 characters and it must not be empty.
country string Required: The two-letter uppercase ISO-3166-1 alpha-2 country code that the number in phone_number should be parsed as if it were dialled from.
id_access_token string

An access token previously registered with the identity server. Servers can treat this as optional to distinguish between r0.5-compatible clients and this specification version.

Required if an id_server is supplied.

id_server string

The hostname of the identity server to communicate with. May optionally include a port. This parameter is ignored when the homeserver handles 3PID verification.

This parameter is deprecated with a plan to be removed in a future specification version for /account/password and /register requests.

next_link string Optional. When the validation is completed, the identity server will redirect the user to this URL. This option is ignored when submitting 3PID validation information through a POST request.
phone_number string Required: The phone number to validate.
send_attempt integer Required: The server will only send an SMS if the send_attempt is a number greater than the most recent one which it has seen, scoped to that country + phone_number + client_secret triple. This is to avoid repeatedly sending the same SMS in the case of request retries between the POSTing user and the identity server. The client should increment this value if they desire a new SMS (e.g. a reminder) to be sent.

Request body example

{
  "client_secret": "monkeys_are_GREAT",
  "country": "GB",
  "id_server": "id.example.com",
  "next_link": "https://example.org/congratulations.html",
  "phone_number": "07700900001",
  "send_attempt": 1
}

Responses

Status Description
200 An SMS message has been sent to the specified phone number. Note that this may be an SMS message containing the validation token or it may be informing the user of an error.
400

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

  • M_THREEPID_IN_USE : The phone number is already registered to an account on this server. However, if the homeserver has the ability to send SMS message, it is recommended that the server instead send an SMS message to the user with instructions on how to reset their password. This prevents malicious parties from being able to determine if a given phone number has an account on the homeserver in question.
  • M_SERVER_NOT_TRUSTED : The id_server parameter refers to an identity server that is not trusted by this homeserver.
403 The homeserver does not permit the address to be bound.

200 response

RequestTokenResponse
Name Type Description
sid string Required: The session ID. Session IDs are opaque strings that must consist entirely of the characters [0-9a-zA-Z.=_-]. Their length must not exceed 255 characters and they must not be empty.
submit_url string

An optional field containing a URL where the client must submit the validation token to, with identical parameters to the Identity Service API’s POST /validate/email/submitToken endpoint (without the requirement for an access token). The homeserver must send this token to the user (if applicable), who should then be prompted to provide it to the client.

If this field is not present, the client can assume that verification will happen without the client’s involvement provided the homeserver advertises this specification version in the /versions response (ie: r0.5.0).

{
  "sid": "123abc",
  "submit_url": "https://example.org/path/to/submitToken"
}

400 response

Error
Name Type Description
errcode string Required: An error code.
error string A human-readable error message.
{
  "errcode": "M_THREEPID_IN_USE",
  "error": "The specified address is already in use"
}

403 response

Error
Name Type Description
errcode string Required: An error code.
error string A human-readable error message.
{
  "errcode": "M_THREEPID_DENIED",
  "error": "Third party identifier is not allowed"
}

Notes on password management

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, though can be proxied (bound) to the identity server in many cases.

GET /_matrix/client/v3/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.

Rate-limited: No
Requires authentication: Yes

Request

No request parameters or request body.


Responses

Status Description
200 The lookup was successful.

200 response

Name Type Description
threepids [Third party identifier]
Third party identifier
Name Type Description
added_at integer Required: The timestamp, in milliseconds, when the homeserver associated the third party identifier with the user.
address string Required: The third party identifier address.
medium enum Required: The medium of the third party identifier.

One of: [email msisdn].

validated_at integer Required: The timestamp, in milliseconds, when the identifier was validated by the identity server.
{
  "threepids": [
    {
      "added_at": 1535336848756,
      "address": "[email protected]",
      "medium": "email",
      "validated_at": 1535176800000
    }
  ]
}

POST /_matrix/client/v3/account/3pid


Adds contact information to the user’s account.

This endpoint is deprecated in favour of the more specific /3pid/add and /3pid/bind endpoints.

Note: Previously this endpoint supported a bind parameter. This parameter has been removed, making this endpoint behave as though it was false. This results in this endpoint being an equivalent to /3pid/bind rather than dual-purpose.

Rate-limited: No
Requires authentication: Yes

Request

Request body

Name Type Description
three_pid_creds ThreePidCredentials Required: The third party credentials to associate with the account.
ThreePidCredentials
Name Type Description
client_secret string Required: The client secret used in the session with the identity server.
id_access_token string Required: An access token previously registered with the identity server. Servers can treat this as optional to distinguish between r0.5-compatible clients and this specification version.
id_server string Required: The identity server to use.
sid string Required: The session identifier given by the identity server.

Request body example

{
  "three_pid_creds": {
    "client_secret": "d0nt-T3ll",
    "id_access_token": "abc123_OpaqueString",
    "id_server": "matrix.org",
    "sid": "abc123987"
  }
}

Responses

Status Description
200 The addition was successful.
403 The credentials could not be verified with the identity server.

200 response

Name Type Description
submit_url string

An optional field containing a URL where the client must submit the validation token to, with identical parameters to the Identity Service API’s POST /validate/email/submitToken endpoint (without the requirement for an access token). The homeserver must send this token to the user (if applicable), who should then be prompted to provide it to the client.

If this field is not present, the client can assume that verification will happen without the client’s involvement provided the homeserver advertises this specification version in the /versions response (ie: r0.5.0).

{
  "submit_url": "https://example.org/path/to/submitToken"
}

403 response

Error
Name Type Description
errcode string Required: An error code.
error string A human-readable error message.
{
  "errcode": "M_THREEPID_AUTH_FAILED",
  "error": "The third party credentials could not be verified by the identity server."
}

POST /_matrix/client/v3/account/3pid/add


This API endpoint uses the User-Interactive Authentication API.

Adds contact information to the user’s account. Homeservers should use 3PIDs added through this endpoint for password resets instead of relying on the identity server.

Homeservers should prevent the caller from adding a 3PID to their account if it has already been added to another user’s account on the homeserver.

Rate-limited: Yes
Requires authentication: Yes

Request

Request body

Name Type Description
auth Authentication Data Additional authentication information for the user-interactive authentication API.
client_secret string Required: The client secret used in the session with the homeserver.
sid string Required: The session identifier given by the homeserver.
Authentication Data
Name Type Description
session string The value of the session key given by the homeserver.
type string The authentication type that the client is attempting to complete. May be omitted if session is given, and the client is reissuing a request which it believes has been completed out-of-band (for example, via the fallback mechanism).

Request body example

{
  "auth": {
    "example_credential": "verypoorsharedsecret",
    "session": "xxxxx",
    "type": "example.type.foo"
  },
  "client_secret": "d0nt-T3ll",
  "sid": "abc123987"
}

Responses

Status Description
200 The addition was successful.
401 The homeserver requires additional authentication information.
429 This request was rate-limited.

200 response

{}

401 response

Authentication response
Name Type Description
completed [string] A list of the stages the client has completed successfully
flows [Flow information] Required: A list of the login flows supported by the server for this API.
params object Contains any information that the client will need to know in order to use a given type of authentication. For each login 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 string 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.
Flow information
Name Type Description
stages [string] Required: The login type of each of the stages required to complete this authentication flow
{
  "completed": [
    "example.type.foo"
  ],
  "flows": [
    {
      "stages": [
        "example.type.foo"
      ]
    }
  ],
  "params": {
    "example.type.baz": {
      "example_key": "foobar"
    }
  },
  "session": "xxxxxxyz"
}

429 response

RateLimitError
Name Type Description
errcode string Required: The M_LIMIT_EXCEEDED error code
error string A human-readable error message.
retry_after_ms integer The amount of time in milliseconds the client should wait before trying the request again.
{
  "errcode": "M_LIMIT_EXCEEDED",
  "error": "Too many requests",
  "retry_after_ms": 2000
}

POST /_matrix/client/v3/account/3pid/bind


Binds a 3PID to the user’s account through the specified identity server.

Homeservers should not prevent this request from succeeding if another user has bound the 3PID. Homeservers should simply proxy any errors received by the identity server to the caller.

Homeservers should track successful binds so they can be unbound later.

Rate-limited: Yes
Requires authentication: Yes

Request

Request body

Name Type Description
client_secret string Required: The client secret used in the session with the identity server.
id_access_token string Required: An access token previously registered with the identity server.
id_server string Required: The identity server to use.
sid string Required: The session identifier given by the identity server.

Request body example

{
  "client_secret": "d0nt-T3ll",
  "id_access_token": "abc123_OpaqueString",
  "id_server": "example.org",
  "sid": "abc123987"
}

Responses

Status Description
200 The addition was successful.
429 This request was rate-limited.

200 response

{}

429 response

RateLimitError
Name Type Description
errcode string Required: The M_LIMIT_EXCEEDED error code
error string A human-readable error message.
retry_after_ms integer The amount of time in milliseconds the client should wait before trying the request again.
{
  "errcode": "M_LIMIT_EXCEEDED",
  "error": "Too many requests",
  "retry_after_ms": 2000
}

POST /_matrix/client/v3/account/3pid/delete


Removes a third party identifier from the user’s account. This might not cause an unbind of the identifier from the identity server.

Unlike other endpoints, this endpoint does not take an id_access_token parameter because the homeserver is expected to sign the request to the identity server instead.

Rate-limited: No
Requires authentication: Yes

Request

Request body

Name Type Description
address string Required: The third party address being removed.
id_server string The identity server to unbind from. If not provided, the homeserver MUST use the id_server the identifier was added through. If the homeserver does not know the original id_server, it MUST return a id_server_unbind_result of no-support.
medium enum Required: The medium of the third party identifier being removed.

One of: [email msisdn].

Request body example

{
  "address": "[email protected]",
  "id_server": "example.org",
  "medium": "email"
}

Responses

Status Description
200 The homeserver has disassociated the third party identifier from the user.

200 response

Name Type Description
id_server_unbind_result enum Required: An indicator as to whether or not the homeserver was able to unbind the 3PID from the identity server. success indicates that the identity server has unbound the identifier whereas no-support indicates that the identity server refuses to support the request or the homeserver was not able to determine an identity server to unbind from.

One of: [no-support success].

{
  "id_server_unbind_result": "success"
}

POST /_matrix/client/v3/account/3pid/email/requestToken


The homeserver must check that the given email address is not already associated with an account on this homeserver. This API should be used to request validation tokens when adding an email address to an account. This API’s parameters and response are identical to that of the /register/email/requestToken endpoint. The homeserver should validate the email itself, either by sending a validation email itself or by using a service it has control over.

Rate-limited: No
Requires authentication: No

Request

Request body

Name Type Description
client_secret string Required: A unique string generated by the client, and used to identify the validation attempt. It must be a string consisting of the characters [0-9a-zA-Z.=_-]. Its length must not exceed 255 characters and it must not be empty.
email string Required: The email address to validate.
id_access_token string

An access token previously registered with the identity server. Servers can treat this as optional to distinguish between r0.5-compatible clients and this specification version.

Required if an id_server is supplied.

id_server string

The hostname of the identity server to communicate with. May optionally include a port. This parameter is ignored when the homeserver handles 3PID verification.

This parameter is deprecated with a plan to be removed in a future specification version for /account/password and /register requests.

next_link string Optional. When the validation is completed, the identity server will redirect the user to this URL. This option is ignored when submitting 3PID validation information through a POST request.
send_attempt integer Required: The server will only send an email if the send_attempt is a number greater than the most recent one which it has seen, scoped to that email + client_secret pair. This is to avoid repeatedly sending the same email in the case of request retries between the POSTing user and the identity server. The client should increment this value if they desire a new email (e.g. a reminder) to be sent. If they do not, the server should respond with success but not resend the email.

Request body example

{
  "client_secret": "monkeys_are_GREAT",
  "email": "[email protected]",
  "id_server": "id.example.com",
  "next_link": "https://example.org/congratulations.html",
  "send_attempt": 1
}

Responses

Status Description
200 An email was sent to the given address. Note that this may be an email containing the validation token or it may be informing the user of an error.
400 The third party identifier is already in use on the homeserver, or the request was invalid. The error code M_SERVER_NOT_TRUSTED can be returned if the server does not trust/support the identity server provided in the request.
403 The homeserver does not allow the third party identifier as a contact option.

200 response

RequestTokenResponse
Name Type Description
sid string Required: The session ID. Session IDs are opaque strings that must consist entirely of the characters [0-9a-zA-Z.=_-]. Their length must not exceed 255 characters and they must not be empty.
submit_url string

An optional field containing a URL where the client must submit the validation token to, with identical parameters to the Identity Service API’s POST /validate/email/submitToken endpoint (without the requirement for an access token). The homeserver must send this token to the user (if applicable), who should then be prompted to provide it to the client.

If this field is not present, the client can assume that verification will happen without the client’s involvement provided the homeserver advertises this specification version in the /versions response (ie: r0.5.0).

{
  "sid": "123abc",
  "submit_url": "https://example.org/path/to/submitToken"
}

400 response

Error
Name Type Description
errcode string Required: An error code.
error string A human-readable error message.
{
  "errcode": "M_THREEPID_IN_USE",
  "error": "Third party identifier already in use"
}

403 response

Error
Name Type Description
errcode string Required: An error code.
error string A human-readable error message.
{
  "errcode": "M_THREEPID_DENIED",
  "error": "Third party identifier is not allowed"
}

POST /_matrix/client/v3/account/3pid/msisdn/requestToken


The homeserver must check that the given phone number is not already associated with an account on this homeserver. This API should be used to request validation tokens when adding a phone number to an account. This API’s parameters and response are identical to that of the /register/msisdn/requestToken endpoint. The homeserver should validate the phone number itself, either by sending a validation message itself or by using a service it has control over.

Rate-limited: No
Requires authentication: No

Request

Request body

Name Type Description
client_secret string Required: A unique string generated by the client, and used to identify the validation attempt. It must be a string consisting of the characters [0-9a-zA-Z.=_-]. Its length must not exceed 255 characters and it must not be empty.
country string Required: The two-letter uppercase ISO-3166-1 alpha-2 country code that the number in phone_number should be parsed as if it were dialled from.
id_access_token string

An access token previously registered with the identity server. Servers can treat this as optional to distinguish between r0.5-compatible clients and this specification version.

Required if an id_server is supplied.

id_server string

The hostname of the identity server to communicate with. May optionally include a port. This parameter is ignored when the homeserver handles 3PID verification.

This parameter is deprecated with a plan to be removed in a future specification version for /account/password and /register requests.

next_link string Optional. When the validation is completed, the identity server will redirect the user to this URL. This option is ignored when submitting 3PID validation information through a POST request.
phone_number string Required: The phone number to validate.
send_attempt integer Required: The server will only send an SMS if the send_attempt is a number greater than the most recent one which it has seen, scoped to that country + phone_number + client_secret triple. This is to avoid repeatedly sending the same SMS in the case of request retries between the POSTing user and the identity server. The client should increment this value if they desire a new SMS (e.g. a reminder) to be sent.

Request body example

{
  "client_secret": "monkeys_are_GREAT",
  "country": "GB",
  "id_server": "id.example.com",
  "next_link": "https://example.org/congratulations.html",
  "phone_number": "07700900001",
  "send_attempt": 1
}

Responses

Status Description
200 An SMS message was sent to the given phone number.
400 The third party identifier is already in use on the homeserver, or the request was invalid. The error code M_SERVER_NOT_TRUSTED can be returned if the server does not trust/support the identity server provided in the request.
403 The homeserver does not allow the third party identifier as a contact option.

200 response

RequestTokenResponse
Name Type Description
sid string Required: The session ID. Session IDs are opaque strings that must consist entirely of the characters [0-9a-zA-Z.=_-]. Their length must not exceed 255 characters and they must not be empty.
submit_url string

An optional field containing a URL where the client must submit the validation token to, with identical parameters to the Identity Service API’s POST /validate/email/submitToken endpoint (without the requirement for an access token). The homeserver must send this token to the user (if applicable), who should then be prompted to provide it to the client.

If this field is not present, the client can assume that verification will happen without the client’s involvement provided the homeserver advertises this specification version in the /versions response (ie: r0.5.0).

{
  "sid": "123abc",
  "submit_url": "https://example.org/path/to/submitToken"
}

400 response

Error
Name Type Description
errcode string Required: An error code.
error string A human-readable error message.
{
  "errcode": "M_THREEPID_IN_USE",
  "error": "Third party identifier already in use"
}

403 response

Error
Name Type Description
errcode string Required: An error code.
error string A human-readable error message.
{
  "errcode": "M_THREEPID_DENIED",
  "error": "Third party identifier is not allowed"
}

POST /_matrix/client/v3/account/3pid/unbind


Removes a user’s third party identifier from the provided identity server without removing it from the homeserver.

Unlike other endpoints, this endpoint does not take an id_access_token parameter because the homeserver is expected to sign the request to the identity server instead.

Rate-limited: No
Requires authentication: Yes

Request

Request body

Name Type Description
address string Required: The third party address being removed.
id_server string The identity server to unbind from. If not provided, the homeserver MUST use the id_server the identifier was added through. If the homeserver does not know the original id_server, it MUST return a id_server_unbind_result of no-support.
medium enum Required: The medium of the third party identifier being removed.

One of: [email msisdn].

Request body example

{
  "address": "[email protected]",
  "id_server": "example.org",
  "medium": "email"
}

Responses

Status Description
200 The identity server has disassociated the third party identifier from the user.

200 response

Name Type Description
id_server_unbind_result enum Required: An indicator as to whether or not the identity server was able to unbind the 3PID. success indicates that the identity server has unbound the identifier whereas no-support indicates that the identity server refuses to support the request or the homeserver was not able to determine an identity server to unbind from.

One of: [no-support success].

{
  "id_server_unbind_result": "success"
}

Current account information

GET /_matrix/client/v3/account/whoami


Gets information about the owner of a given access token.

Note that, as with the rest of the Client-Server API, Application Services may masquerade as users within their namespace by giving a user_id query parameter. In this situation, the server should verify that the given user_id is registered by the appservice, and return it in the response body.

Rate-limited: Yes
Requires authentication: Yes

Request

No request parameters or request body.


Responses

Status Description
200 The token belongs to a known user.
401 The token is not recognised
403 The appservice cannot masquerade as the user or has not registered them.
429 This request was rate-limited.

200 response

Name Type Description
device_id string Device ID associated with the access token. If no device is associated with the access token (such as in the case of application services) then this field can be omitted. Otherwise this is required.

Added in v1.1

is_guest boolean When true, the user is a Guest User. When not present or false, the user is presumed to be a non-guest user.

Added in v1.2

user_id string Required: The user ID that owns the access token.
{
  "device_id": "ABC1234",
  "user_id": "@joe:example.org"
}

401 response

Error
Name Type Description
errcode string Required: An error code.
error string A human-readable error message.
{
  "errcode": "M_UNKNOWN_TOKEN",
  "error": "Unrecognised access token."
}

403 response

Error
Name Type Description
errcode string Required: An error code.
error string A human-readable error message.
{
  "errcode": "M_FORBIDDEN",
  "error": "Application service has not registered this user."
}

429 response

RateLimitError
Name Type Description
errcode string Required: The M_LIMIT_EXCEEDED error code
error string A human-readable error message.
retry_after_ms integer The amount of time in milliseconds the client should wait before trying the request again.
{
  "errcode": "M_LIMIT_EXCEEDED",
  "error": "Too many requests",
  "retry_after_ms": 2000
}

Notes on identity servers

Identity servers in Matrix store bindings (relationships) between a user’s third party identifier, typically email or phone number, and their user ID. Once a user has chosen an identity server, that identity server should be used by all clients.

Clients can see which identity server the user has chosen through the m.identity_server account data event, as described below. Clients SHOULD refrain from making requests to any identity server until the presence of m.identity_server is confirmed as (not) present. If present, the client SHOULD check for the presence of the base_url property in the event’s content. If the base_url is present, the client SHOULD use the identity server in that property as the identity server for the user. If the base_url is missing, or the account data event is not present, the client SHOULD use whichever default value it normally would for an identity server, if applicable. Clients SHOULD NOT update the account data with the default identity server when the user is missing an identity server in their account data.

Clients SHOULD listen for changes to the m.identity_server account data event and update the identity server they are contacting as a result.

If the client offers a way to set the identity server to use, it MUST update the value of m.identity_server accordingly. A base_url of null MUST be treated as though the user does not want to use an identity server, disabling all related functionality as a result.

Clients SHOULD refrain from populating the account data as a migration step for users who are lacking the account data, unless the user sets the identity server within the client to a value. For example, a user which has no m.identity_server account data event should not end up with the client’s default identity server in their account data, unless the user first visits their account settings to set the identity server.

m.identity_server


Persists the user’s preferred identity server, or preference to not use an identity server at all, in the user’s account data.

Event type: Message event

Content

Name Type Description
base_url string The URL of the identity server the user prefers to use, or null if the user does not want to use an identity server. This value is similar in structure to the base_url for identity servers in the .well-known/matrix/client schema.

Examples

{
  "content": {
    "base_url": "https://example.org"
  },
  "type": "m.identity_server"
}

Capabilities negotiation

A homeserver may not support certain operations and clients must be able to query for what the homeserver can and can’t offer. For example, a homeserver may not support users changing their password as it is configured to perform authentication against an external system.

The capabilities advertised through this system are intended to advertise functionality which is optional in the API, or which depend in some way on the state of the user or server. This system should not be used to advertise unstable or experimental features - this is better done by the /versions endpoint.

Some examples of what a reasonable capability could be are:

  • Whether the server supports user presence.
  • Whether the server supports optional features, such as the user or room directories.
  • The rate limits or file type restrictions imposed on clients by the server.

Some examples of what should not be a capability are:

  • Whether the server supports a feature in the unstable specification.
  • Media size limits - these are handled by the /config API.
  • Optional encodings or alternative transports for communicating with the server.

Capabilities prefixed with m. are reserved for definition in the Matrix specification while other values may be used by servers using the Java package naming convention. The capabilities supported by the Matrix specification are defined later in this section.

GET /_matrix/client/v3/capabilities


Gets information about the server’s supported feature set and other relevant capabilities.

Rate-limited: Yes
Requires authentication: Yes

Request

No request parameters or request body.


Responses

Status Description
200 The capabilities of the server.
429 This request was rate-limited.

200 response

Name Type Description
capabilities Capabilities Required: The custom capabilities the server supports, using the Java package naming convention.
Capabilities
Name Type Description
m.change_password ChangePasswordCapability Capability to indicate if the user can change their password.
m.room_versions RoomVersionsCapability The room versions the server supports.
ChangePasswordCapability
Name Type Description
enabled boolean Required: True if the user can change their password, false otherwise.
RoomVersionsCapability
Name Type Description
available { string: RoomVersionStability} Required: A detailed description of the room versions the server supports.
default string Required: The default room version the server is using for new rooms.
{
  "capabilities": {
    "com.example.custom.ratelimit": {
      "max_requests_per_hour": 600
    },
    "m.change_password": {
      "enabled": false
    },
    "m.room_versions": {
      "available": {
        "1": "stable",
        "2": "stable",
        "3": "unstable",
        "test-version": "unstable"
      },
      "default": "1"
    }
  }
}

429 response

RateLimitError
Name Type Description
errcode string Required: The M_LIMIT_EXCEEDED error code
error string A human-readable error message.
retry_after_ms integer The amount of time in milliseconds the client should wait before trying the request again.
{
  "errcode": "M_LIMIT_EXCEEDED",
  "error": "Too many requests",
  "retry_after_ms": 2000
}

m.change_password capability

This capability has a single flag, enabled, which indicates whether or not the user can use the /account/password API to change their password. If not present, the client should assume that password changes are possible via the API. When present, clients SHOULD respect the capability’s enabled flag and indicate to the user if they are unable to change their password.

An example of the capability API’s response for this capability is:

{
  "capabilities": {
    "m.change_password": {
      "enabled": false
    }
  }
}

m.room_versions capability

This capability describes the default and available room versions a server supports, and at what level of stability. Clients should make use of this capability to determine if users need to be encouraged to upgrade their rooms.

An example of the capability API’s response for this capability is:

{
  "capabilities": {
    "m.room_versions": {
      "default": "1",
      "available": {
        "1": "stable",
        "2": "stable",
        "3": "unstable",
        "custom-version": "unstable"
      }
    }
  }
}

This capability mirrors the same restrictions of room versions to describe which versions are stable and unstable. Clients should assume that the default version is stable. Any version not explicitly labelled as stable in the available versions is to be treated as unstable. For example, a version listed as future-stable should be treated as unstable.

The default version is the version the server is using to create new rooms. Clients should encourage users with sufficient permissions in a room to upgrade their room to the default version when the room is using an unstable version.

When this capability is not listed, clients should use "1" as the default and only stable available room version.

m.set_displayname capability

This capability has a single flag, enabled, to denote whether the user is able to change their own display name via profile endpoints. Cases for disabling might include users mapped from external identity/directory services, such as LDAP.

Note that this is well paired with the m.set_avatar_url capability.

When not listed, clients should assume the user is able to change their display name.

An example of the capability API’s response for this capability is:

{
  "capabilities": {
    "m.set_displayname": {
      "enabled": false
    }
  }
}

m.set_avatar_url capability

This capability has a single flag, enabled, to denote whether the user is able to change their own avatar via profile endpoints. Cases for disabling might include users mapped from external identity/directory services, such as LDAP.

Note that this is well paired with the m.set_displayname capability.

When not listed, clients should assume the user is able to change their avatar.

An example of the capability API’s response for this capability is:

{
  "capabilities": {
    "m.set_avatar_url": {
      "enabled": false
    }
  }
}

m.3pid_changes capability

This capability has a single flag, enabled, to denote whether the user is able to add, remove, or change 3PID associations on their account. Note that this only affects a user’s ability to use the Admin Contact Information API, not endpoints exposed by an Identity Service. Cases for disabling might include users mapped from external identity/directory services, such as LDAP.

When not listed, clients should assume the user is able to modify their 3PID associations.

An example of the capability API’s response for this capability is:

{
  "capabilities": {
    "m.3pid_changes": {
      "enabled": false
    }
  }
}

Filtering

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

Lazy-loading room members

Membership events often take significant resources for clients to track. In an effort to reduce the number of resources used, clients can enable “lazy-loading” for room members. By doing this, servers will attempt to only send membership events which are relevant to the client.

It is important to understand that lazy-loading is not intended to be a perfect optimisation, and that it may not be practical for the server to calculate precisely which membership events are relevant to the client. As a result, it is valid for the server to send redundant membership events to the client to ease implementation, although such redundancy should be minimised where possible to conserve bandwidth.

In terms of filters, lazy-loading is enabled by enabling lazy_load_members on a RoomEventFilter (or a StateFilter in the case of /sync only). When enabled, lazy-loading aware endpoints (see below) will only include membership events for the sender of events being included in the response. For example, if a client makes a /sync request with lazy-loading enabled, the server will only return membership events for the sender of events in the timeline, not all members of a room.

When processing a sequence of events (e.g. by looping on /sync or paginating /messages), it is common for blocks of events in the sequence to share a similar set of senders. Rather than responses in the sequence sending duplicate membership events for these senders to the client, the server MAY assume that clients will remember membership events they have already been sent, and choose to skip sending membership events for members whose membership has not changed. These are called ‘redundant membership events’. Clients may request that redundant membership events are always included in responses by setting include_redundant_members to true in the filter.

The expected pattern for using lazy-loading is currently:

  • Client performs an initial /sync with lazy-loading enabled, and receives only the membership events which relate to the senders of the events it receives.
  • Clients which support display-name tab-completion or other operations which require rapid access to all members in a room should call /members for the currently selected room, with an ?at parameter set to the /sync response’s from token. The member list for the room is then maintained by the state in subsequent incremental /sync responses.
  • Clients which do not support tab-completion may instead pull in profiles for arbitrary users (e.g. read receipts, typing notifications) on demand by querying the room state or /profile.

The current endpoints which support lazy-loading room members are:

API endpoints

POST /_matrix/client/v3/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.

Rate-limited: No
Requires authentication: Yes

Request

Request parameters

path parameters
Name Type Description
userId string Required: The id of the user uploading the filter. The access token must be authorized to make requests for this user id.

Request body

Filter
Name Type Description
account_data EventFilter The user account data that isn’t associated with rooms to include.
event_fields [string] List of event fields to include. If this list is absent then all fields are included. The entries may include ‘.’ characters 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 received over federation. The default is ‘client’.

One of: [client federation].

presence EventFilter The presence updates to include.
room RoomFilter Filters to be applied to room data.
EventFilter
Name 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
Name Type Description
account_data RoomEventFilter The per user account data to include for rooms.
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
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
state StateFilter The state events to include for rooms.
timeline RoomEventFilter The message and state update events to include for rooms.
RoomEventFilter
Name Type Description
contains_url boolean If true, includes only events with a url key in their content. If false, excludes those events. If omitted, url key is not considered for filtering.
include_redundant_members boolean If true, sends all membership events for all events, even if they have already been sent to the client. Does not apply unless lazy_load_members is true. See Lazy-loading room members for more information. Defaults to false.
lazy_load_members boolean If true, enables lazy-loading of membership events. See Lazy-loading room members for more information. Defaults to false.
limit integer The maximum number of events to return.
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.
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.
rooms [string] A list of room IDs to include. If this list is absent then all rooms are included.
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.
StateFilter
Name Type Description
contains_url boolean If true, includes only events with a url key in their content. If false, excludes those events. If omitted, url key is not considered for filtering.
include_redundant_members boolean If true, sends all membership events for all events, even if they have already been sent to the client. Does not apply unless lazy_load_members is true. See Lazy-loading room members for more information. Defaults to false.
lazy_load_members boolean If true, enables lazy-loading of membership events. See Lazy-loading room members for more information. Defaults to false.
limit integer The maximum number of events to return.
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.
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.
rooms [string] A list of room IDs to include. If this list is absent then all rooms are included.
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.

Request body example

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

Responses

Status Description
200 The filter was created.

200 response

Name Type Description
filter_id string Required: The ID of the filter that was created. Cannot start with a { as this character is used to determine if the filter provided is inline JSON or a previously declared filter by homeservers on some APIs.
{
  "filter_id": "66696p746572"
}

GET /_matrix/client/v3/user/{userId}/filter/{filterId}


Rate-limited: No
Requires authentication: Yes

Request

Request parameters

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

Responses

Status Description
200 The filter definition.
404 Unknown filter.

200 response

Filter
Name Type Description
account_data EventFilter The user account data that isn’t associated with rooms to include.
event_fields [string] List of event fields to include. If this list is absent then all fields are included. The entries may include ‘.’ characters 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 received over federation. The default is ‘client’.

One of: [client federation].

presence EventFilter The presence updates to include.
room RoomFilter Filters to be applied to room data.
EventFilter
Name 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
Name Type Description
account_data RoomEventFilter The per user account data to include for rooms.
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
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
state StateFilter The state events to include for rooms.
timeline RoomEventFilter The message and state update events to include for rooms.
RoomEventFilter
Name Type Description
contains_url boolean If true, includes only events with a url key in their content. If false, excludes those events. If omitted, url key is not considered for filtering.
include_redundant_members boolean If true, sends all membership events for all events, even if they have already been sent to the client. Does not apply unless lazy_load_members is true. See Lazy-loading room members for more information. Defaults to false.
lazy_load_members boolean If true, enables lazy-loading of membership events. See Lazy-loading room members for more information. Defaults to false.
limit integer The maximum number of events to return.
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.
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.
rooms [string] A list of room IDs to include. If this list is absent then all rooms are included.
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.
StateFilter
Name Type Description
contains_url boolean If true, includes only events with a url key in their content. If false, excludes those events. If omitted, url key is not considered for filtering.
include_redundant_members boolean If true, sends all membership events for all events, even if they have already been sent to the client. Does not apply unless lazy_load_members is true. See Lazy-loading room members for more information. Defaults to false.
lazy_load_members boolean If true, enables lazy-loading of membership events. See Lazy-loading room members for more information. Defaults to false.
limit integer The maximum number of events to return.
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.
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.
rooms [string] A list of room IDs to include. If this list is absent then all rooms are included.
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.
{
  "event_fields": [
    "type",
    "content",
    "sender"
  ],
  "event_format": "client",
  "presence": {
    "not_senders": [
      "@alice:example.com"
    ],
    "types": [
      "m.presence"
    ]
  },
  "room": {
    "ephemeral": {
      "not_rooms": [
        "!726s6s6q:example.com"
      ],
      "not_senders": [
        "@spam:example.com"
      ],
      "types": [
        "m.receipt",
        "m.typing"
      ]
    },
    "state": {
      "not_rooms": [
        "!726s6s6q:example.com"
      ],
      "types": [
        "m.room.*"
      ]
    },
    "timeline": {
      "limit": 10,
      "not_rooms": [
        "!726s6s6q:example.com"
      ],
      "not_senders": [
        "@spam:example.com"
      ],
      "types": [
        "m.room.message"
      ]
    }
  }
}

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]

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.

Room event format

The “federation” format of a room event, which is used internally by homeservers and between homeservers via the Server-Server API, depends on the “room version” in use by the room. See, for example, the definitions in room version 1 and room version 3.

However, it is unusual that a Matrix client would encounter this event format. Instead, homeservers are responsible for converting events into the format shown below so that they can be easily parsed by clients.

ClientEvent


The format used for events when they are returned from a homeserver to a client via the Client-Server API, or sent to an Application Service via the Application Services API.

ClientEvent
Name Type Description
content object Required: The body of this event, as created by the client which sent it.
event_id string Required: The globally unique identifier for this event.
origin_server_ts integer Required: Timestamp (in milliseconds since the unix epoch) on originating homeserver when this event was sent.
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.
state_key string

Present if, and only if, this event is a state event. The key making this piece of state unique in the room. Note that it is often an empty string.

State keys starting with an @ are reserved for referencing user IDs, such as room members. With the exception of a few events, state events set with a given user’s ID as the state key MUST only be set by that user.

type string Required: The type of the event.
unsigned UnsignedData Contains optional extra information about the event.
UnsignedData
Name 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.
prev_content EventContent The previous content for this event. This field is generated by the local homeserver, and is only returned if the event is a state event, and the client has permission to see the previous content.

Changed in v1.2: Previously, this field was specified at the top level of returned events rather than in unsigned (with the exception of the GET .../notifications endpoint), though in practice no known server implementations honoured this.
redacted_because ClientEvent The event that redacted this event, if any.
transaction_id string The client-supplied transaction ID, for example, provided via PUT /_matrix/client/v3/rooms/{roomId}/send/{eventType}/{txnId}, if the client being given the event is the same one which sent it.

Examples

{
  "content": {
    "membership": "join"
  },
  "event_id": "$26RqwJMLw-yds1GAH_QxjHRC1Da9oasK0e5VLnck_45",
  "origin_server_ts": 1632489532305,
  "room_id": "!jEsUZKDJdhlrceRyVU:example.org",
  "sender": "@example:example.org",
  "state_key": "@user:example.org",
  "type": "m.room.member",
  "unsigned": {
    "age": 1567437,
    "redacted_because": {
      "content": {
        "reason": "spam"
      },
      "event_id": "$Nhl3rsgHMjk-DjMJANawr9HHAhLg4GcoTYrSiYYGqEE",
      "origin_server_ts": 1632491098485,
      "redacts": "$26RqwJMLw-yds1GAH_QxjHRC1Da9oasK0e5VLnck_45",
      "room_id": "!jEsUZKDJdhlrceRyVU:example.org",
      "sender": "@moderator:example.org",
      "type": "m.room.redaction",
      "unsigned": {
        "age": 1257
      }
    }
  }
}

Stripped state

Stripped state events are simplified state events to help a potential joiner identify the room. These state events can only have the sender, type, state_key and content keys present.

These stripped state events typically appear on invites, knocks, and in other places where a user could join the room under the conditions available (such as a restricted room).

Clients should only use stripped state events so long as they don’t have access to the proper state of the room. Once the state of the room is available, all stripped state should be discarded. In cases where the client has an archived state of the room (such as after being kicked) and the client is receiving stripped state for the room, such as from an invite or knock, then the stripped state should take precedence until fresh state can be acquired from a join.

The following state events should be represented as stripped state when possible:

Stripped state event


A stripped down state event, with only the type, state_key, sender, and content keys.

Name Type Description
content EventContent Required: The content for the event.
sender string Required: The sender for the event.
state_key string Required: The state_key for the event.
type string Required: The type for the event.

Size limits

The complete event MUST NOT be larger than 65536 bytes, when formatted with the federation event format, 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 64 KiB limit on events.

Room Events

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

m.room.canonical_alias


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

Event type: State event
State key A zero-length string.

Content

Name Type Description
alias string The canonical alias for the room. If not present, null, or empty the room should be considered to have no canonical alias.
alt_aliases [string] Alternative aliases the room advertises. This list can have aliases despite the alias field being null, empty, or otherwise not present.

Examples

{
  "content": {
    "alias": "#somewhere:localhost",
    "alt_aliases": [
      "#somewhere:example.org",
      "#myroom:example.com"
    ]
  },
  "event_id": "$143273582443PhrSn:example.org",
  "origin_server_ts": 1432735824653,
  "room_id": "!jEsUZKDJdhlrceRyVU:example.org",
  "sender": "@example:example.org",
  "state_key": "",
  "type": "m.room.canonical_alias",
  "unsigned": {
    "age": 1234
  }
}

m.room.create


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

Event type: State event
State key A zero-length string.

Content

Name 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.
predecessor Previous Room A reference to the room this room replaces, if the previous room was upgraded.
room_version string The version of the room. Defaults to "1" if the key does not exist.
type string

Optional room type to denote a room’s intended function outside of traditional conversation.

Unspecified room types are possible using Namespaced Identifiers.

Previous Room
Name Type Description
event_id string Required: The event ID of the last known event in the old room.
room_id string Required: The ID of the old room.

Examples

{
  "content": {
    "creator": "@example:example.org",
    "m.federate": true,
    "predecessor": {
      "event_id": "$something:example.org",
      "room_id": "!oldroom:example.org"
    },
    "room_version": "1"
  },
  "event_id": "$143273582443PhrSn:example.org",
  "origin_server_ts": 1432735824653,
  "room_id": "!jEsUZKDJdhlrceRyVU:example.org",
  "sender": "@example:example.org",
  "state_key": "",
  "type": "m.room.create",
  "unsigned": {
    "age": 1234
  }
}

m.room.join_rules


A room may have one of the following designations:

  • public - anyone can join the room without any prior action.
  • invite - a user must first receive an invite from someone already in the room in order to join.
  • knock - a user can request an invite to the room. They can be allowed (invited) or denied (kicked/banned) access. Otherwise, users need to be invited in. Only available in rooms which support knocking.
  • restricted - anyone able to satisfy at least one of the allow conditions is able to join the room without prior action. Otherwise, an invite is required. Only available in rooms which support the join rule.
  • knock_restricted - a user can request an invite using the same functions offered by the knock join rule, or can attempt to join having satisfied an allow condition per the restricted join rule. Only available in rooms which support the join rule.
  • private - reserved without implementation. No significant meaning.
Event type: State event
State key A zero-length string.

Content

Name Type Description
allow [AllowCondition] For restricted rooms, the conditions the user will be tested against. The user needs only to satisfy one of the conditions to join the restricted room. If the user fails to meet any condition, or the condition is unable to be confirmed as satisfied, then the user requires an invite to join the room. Improper or no allow conditions on a restricted join rule imply the room is effectively invite-only (no conditions can be satisfied).

Added in v1.2

join_rule enum Required: The type of rules used for users wishing to join this room.

One of: [public knock invite private restricted].

AllowCondition
Name Type Description
room_id string Required if type is m.room_membership. The room ID to check the user’s membership against. If the user is joined to this room, they satisfy the condition and thus are permitted to join the restricted room.
type enum Required:

The type of condition:

  • m.room_membership - the user satisfies the condition if they are joined to the referenced room.

One of: [m.room_membership].

Examples

{
  "content": {
    "join_rule": "public"
  },
  "event_id": "$143273582443PhrSn:example.org",
  "origin_server_ts": 1432735824653,
  "room_id": "!jEsUZKDJdhlrceRyVU:example.org",
  "sender": "@example:example.org",
  "state_key": "",
  "type": "m.room.join_rules",
  "unsigned": {
    "age": 1234
  }
}
{
  "content": {
    "allow": [
      {
        "room_id": "!other:example.org",
        "type": "m.room_membership"
      },
      {
        "room_id": "!elsewhere:example.org",
        "type": "m.room_membership"
      }
    ],
    "join_rule": "restricted"
  },
  "event_id": "$143273582443PhrSn:example.org",
  "origin_server_ts": 1432735824653,
  "room_id": "!jEsUZKDJdhlrceRyVU:example.org",
  "sender": "@example:example.org",
  "state_key": "",
  "type": "m.room.join_rules",
  "unsigned": {
    "age": 1234
  }
}

m.room.member


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

The following membership states are specified:

  • invite - The user has been invited to join a room, but has not yet joined it. They may not participate in the room until they join.

  • join - The user has joined the room (possibly after accepting an invite), and may participate in it.

  • leave - The user was once joined to the room, but has since left (possibly by choice, or possibly by being kicked).

  • ban - The user has been banned from the room, and is no longer allowed to join it until they are un-banned from the room (by having their membership state set to a value other than ban).

  • knock - The user has knocked on the room, requesting permission to participate. They may not participate in the room until they join.

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 inside the event’s unsigned data. If present, this contains an array of stripped state events to assist the receiver in identifying the room.

The user for which a membership applies is represented by the state_key. Under some conditions, the sender and state_key may not match - this may be interpreted as the sender affecting the membership state of the state_key user.

The membership for a given user can change over time. The table below represents the various changes over time and how clients and servers must interpret those changes. Previous membership can be retrieved from the prev_content object on an event. If not present, the user’s previous membership must be assumed as leave.

to invite to join to leave to ban to knock
from invite No change. User joined the room. If the state_key is the same as the sender, the user rejected the invite. Otherwise, the state_key user had their invite revoked. User was banned. User is re-knocking.
from join Must never happen. displayname or avatar_url changed. If the state_key is the same as the sender, the user left. Otherwise, the state_key user was kicked. User was kicked and banned. Must never happen.
from leave New invitation sent. User joined. No change. User was banned. User is knocking.
from ban Must never happen. Must never happen. User was unbanned. No change. Must never happen.
from knock Knock accepted. Must never happen. If the state_key is the same as the sender, the user retracted the knock. Otherwise, the state_key user had their knock denied. User was banned. No change.
Event type: State event
State key The user_id this membership event relates to. In all cases except for when membership is join, the user ID sending the event does not need to match the user ID in the state_key, unlike other events. Regular authorisation rules still apply.

Content

EventContent
Name Type Description
avatar_url string The avatar URL for this user, if any.
displayname [string null] The display name for this user, if any.
is_direct boolean Flag indicating if the room containing this event was created with the intention of being a direct chat. See Direct Messaging.
join_authorised_via_users_server string

Usually found on join events, this field is used to denote which homeserver (through representation of a user with sufficient power level) authorised the user’s join. More information about this field can be found in the Restricted Rooms Specification.

Client and server implementations should be aware of the signing implications of including this field in further events: in particular, the event must be signed by the server which owns the user ID in the field. When copying the membership event’s content (for profile updates and similar) it is therefore encouraged to exclude this field in the copy, as otherwise the event might fail event authorization.

Added in v1.2

membership enum Required: The membership state of the user.

One of: [invite join knock leave ban].

reason string

Optional user-supplied text for why their membership has changed. For kicks and bans, this is typically the reason for the kick or ban. For other membership changes, this is a way for the user to communicate their intent without having to send a message to the room, such as in a case where Bob rejects an invite from Alice about an upcoming concert, but can’t make it that day.

Clients are not recommended to show this reason to users when receiving an invite due to the potential for spam and abuse. Hiding the reason behind a button or other component is recommended.

Added in v1.1

third_party_invite Invite
Invite
Name Type Description
display_name string Required: A name which can be displayed to represent the user instead of their third party identifier
signed signed Required: A block of content which has been signed, which servers can use to verify the event. Clients should ignore this.
signed
Name 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.

Examples

{
  "content": {
    "avatar_url": "mxc://example.org/SEsfnsuifSDFSSEF",
    "displayname": "Alice Margatroid",
    "membership": "join",
    "reason": "Looking for support"
  },
  "event_id": "$143273582443PhrSn:example.org",
  "origin_server_ts": 1432735824653,
  "room_id": "!jEsUZKDJdhlrceRyVU:example.org",
  "sender": "@example:example.org",
  "state_key": "@alice:example.org",
  "type": "m.room.member",
  "unsigned": {
    "age": 1234
  }
}
{
  "content": {
    "avatar_url": "mxc://example.org/SEsfnsuifSDFSSEF",
    "displayname": "Alice Margatroid",
    "membership": "invite",
    "reason": "Looking for support"
  },
  "event_id": "$143273582443PhrSn:example.org",
  "origin_server_ts": 1432735824653,
  "room_id": "!jEsUZKDJdhlrceRyVU:example.org",
  "sender": "@example:example.org",
  "state_key": "@alice:example.org",
  "type": "m.room.member",
  "unsigned": {
    "age": 1234,
    "invite_room_state": [
      {
        "content": {
          "name": "Example Room"
        },
        "sender": "@bob:example.org",
        "state_key": "",
        "type": "m.room.name"
      },
      {
        "content": {
          "join_rule": "invite"
        },
        "sender": "@bob:example.org",
        "state_key": "",
        "type": "m.room.join_rules"
      }
    ]
  }
}
{
  "content": {
    "avatar_url": "mxc://example.org/SEsfnsuifSDFSSEF",
    "displayname": "Alice Margatroid",
    "join_authorised_via_users_server": "@bob:other.example.org",
    "membership": "join"
  },
  "event_id": "$143273582443PhrSn:example.org",
  "origin_server_ts": 1432735824653,
  "room_id": "!jEsUZKDJdhlrceRyVU:example.org",
  "sender": "@example:example.org",
  "state_key": "@alice:example.org",
  "type": "m.room.member",
  "unsigned": {
    "age": 1234
  }
}
{
  "content": {
    "avatar_url": "mxc://example.org/SEsfnsuifSDFSSEF",
    "displayname": "Alice Margatroid",
    "membership": "knock",
    "reason": "Looking for support"
  },
  "event_id": "$143273582443PhrSn:example.org",
  "origin_server_ts": 1432735824653,
  "room_id": "!jEsUZKDJdhlrceRyVU:example.org",
  "sender": "@example:example.org",
  "state_key": "@alice:example.org",
  "type": "m.room.member",
  "unsigned": {
    "age": 1234,
    "knock_room_state": [
      {
        "content": {
          "name": "Example Room"
        },
        "sender": "@bob:example.org",
        "state_key": "",
        "type": "m.room.name"
      },
      {
        "content": {
          "join_rule": "knock"
        },
        "sender": "@bob:example.org",
        "state_key": "",
        "type": "m.room.join_rules"
      }
    ]
  }
}
{
  "content": {
    "avatar_url": "mxc://example.org/SEsfnsuifSDFSSEF",
    "displayname": "Alice Margatroid",
    "membership": "invite",
    "third_party_invite": {
      "display_name": "alice",
      "signed": {
        "mxid": "@alice:example.org",
        "signatures": {
          "magic.forest": {
            "ed25519:3": "fQpGIW1Snz+pwLZu6sTy2aHy/DYWWTspTJRPyNp0PKkymfIsNffysMl6ObMMFdIJhk6g6pwlIqZ54rxo8SLmAg"
          }
        },
        "token": "abc123"
      }
    }
  },
  "event_id": "$143273582443PhrSn:example.org",
  "origin_server_ts": 1432735824653,
  "room_id": "!jEsUZKDJdhlrceRyVU:example.org",
  "sender": "@example:example.org",
  "state_key": "@alice:example.org",
  "type": "m.room.member",
  "unsigned": {
    "age": 1234
  }
}

m.room.power_levels


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. If the room contains no m.room.power_levels event, the room’s creator has a power level of 100, and all other users have a power level of 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 sent by another user, is defined by invite, kick, ban, and redact, respectively. The levels for kick, ban and redact default 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. invite defaults to 0 in either case.

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.

Event type: State event
State key A zero-length string.

Content

Name Type Description
ban integer The level required to ban a user. Defaults to 50 if unspecified.
events Event power levels The level required to send specific event types. This is a mapping from event type to power level required.
events_default integer The default level required to send message events. Can be overridden by the events key. Defaults to 0 if unspecified.
invite integer The level required to invite a user. Defaults to 0 if unspecified.
kick integer The level required to kick a user. Defaults to 50 if unspecified.
notifications Notifications The power level requirements for specific notification types. This is a mapping from key to power level for that notifications key.
redact integer The level required to redact an event sent by another user. Defaults to 50 if unspecified.
state_default integer The default level required to send state events. Can be overridden by the events key. Defaults to 50 if unspecified.
users User power levels The power levels for specific users. This is a mapping from user_id to power level for that user.
users_default integer 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.
Notifications
Name Type Description
room integer The level required to trigger an @room notification. Defaults to 50 if unspecified.

Examples

{
  "content": {
    "ban": 50,
    "events": {
      "m.room.name": 100,
      "m.room.power_levels": 100
    },
    "events_default": 0,
    "invite": 50,
    "kick": 50,
    "notifications": {
      "room": 20
    },
    "redact": 50,
    "state_default": 50,
    "users": {
      "@example:localhost": 100
    },
    "users_default": 0
  },
  "event_id": "$143273582443PhrSn:example.org",
  "origin_server_ts": 1432735824653,
  "room_id": "!jEsUZKDJdhlrceRyVU:example.org",
  "sender": "@example:example.org",
  "state_key": "",
  "type": "m.room.power_levels",
  "unsigned": {
    "age": 1234
  }
}

Historical events

Some events within the m. namespace might appear in rooms, however they serve no significant meaning in this version of the specification. They are:

  • m.room.aliases

Previous versions of the specification have more information on these events.

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.

For example, a /sync request might return a range of four events E2, E3, E4 and E5 within a given room, omitting two prior events E0 and E1. This can be visualised as follows:

    [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.

Continuing the example above, an incremental sync might report a single new event E6. The response 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.

Continuing our example, suppose we make a third /sync request asking for events since the last sync, by passing the next_batch token x-y-z as the since parameter. The server knows about four new events, E7, E8, E9 and E10, but decides this is too many to report at once. Instead, the server sends a limited response containing E8, E9 and E10but omitting E7. This forms a gap, which we can see in the visualisation:

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

The limited response includes a state delta which describes how the state of the room changes over the gap. This delta explains how to build the state prior to returned timeline (i.e. at E7) from the state the client knows (i.e. at E6). To close the gap, the client should make a request to /rooms/<room_id>/messages with the query parameters from=x-y-z and to=d-e-f.

GET /_matrix/client/v3/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.

Note: This endpoint supports lazy-loading. See Filtering for more information. Lazy-loading members is only supported on a StateFilter for this endpoint. When lazy-loading is enabled, servers MUST include the syncing user’s own membership event when they join a room, or when the full state of rooms is requested, to aid discovering the user’s avatar & displayname.

Further, like other members, the user’s own membership event is eligible for being considered redundant by the server. When a sync is limited, the server MUST return membership events for events in the gap (between since and the start of the returned timeline), regardless as to whether or not they are redundant. This ensures that joins/leaves and profile changes which occur during the gap are not lost.

Note that the default behaviour of state is to include all membership events, alongside other state, when lazy-loading is not enabled.

Rate-limited: No
Requires authentication: Yes

Request

Request parameters

query parameters
Name Type Description
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.

See Filtering for more information.

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. When set to “unavailable”, the client is marked as being idle.

One of: [offline online unavailable].

since string A point in time to continue a sync from. This should be the next_batch token returned by an earlier call to this endpoint.
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.


Responses

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

200 response

Name Type Description
account_data Account Data The global private data created by this user.
device_lists DeviceLists Information on end-to-end device updates, as specified in End-to-end encryption.
device_one_time_keys_count One-time keys count Information on end-to-end encryption keys, as specified in End-to-end encryption.
next_batch string Required: The batch token to supply in the since param of the next /sync request.
presence Presence The updates to the presence status of other users.
rooms Rooms Updates to rooms.
to_device ToDevice Information on the send-to-device messages for the client device, as defined in Send-to-Device messaging.
Account Data
Name Type Description
events [Event] List of events.
Event
Name Type Description
content object Required: 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’
Presence
Name Type Description
events [Event] List of events.
Rooms
Name Type Description
invite { string: Invited Room} The rooms that the user has been invited to, mapped as room ID to room information.
join { string: Joined Room} The rooms that the user has joined, mapped as room ID to room information.
knock { string: Knocked Room} The rooms that the user has knocked upon, mapped as room ID to room information.
leave { string: Left Room} The rooms that the user has left or been banned from, mapped as room ID to room information.
Invited Room
Name Type Description
invite_state InviteState The stripped state of a room that the user has been invited to.
InviteState
Name Type Description
events [StrippedStateEvent] The stripped state events that form the invite state.
StrippedStateEvent
Name Type Description
content EventContent Required: The content for the event.
sender string Required: The sender for the event.
state_key string Required: The state_key for the event.
type string Required: The type for the event.
Joined Room
Name Type Description
account_data Account Data The private data that this user has attached to this room.
ephemeral Ephemeral The ephemeral events in the room that aren’t recorded in the timeline or state of the room. e.g. typing.
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).

N.B. state updates for m.room.member events will be incomplete if lazy_load_members is enabled in the /sync filter, and only return the member events required to display the senders of the timeline events in this response.

summary RoomSummary Information about the room which clients may need to correctly render it to users.
timeline Timeline The timeline of messages and state changes in the room.
unread_notifications Unread Notification Counts Counts of unread notifications for this room. See the Receiving notifications section for more information on how these are calculated.
Ephemeral
Name Type Description
events [Event] List of events.
State
Name Type Description
events [ClientEventWithoutRoomID] List of events.
ClientEventWithoutRoomID
Name Type Description
content object Required: The body of this event, as created by the client which sent it.
event_id string Required: The globally unique identifier for this event.
origin_server_ts integer Required: Timestamp (in milliseconds since the unix epoch) on originating homeserver when this event was sent.
sender string Required: Contains the fully-qualified ID of the user who sent this event.
state_key string

Present if, and only if, this event is a state event. The key making this piece of state unique in the room. Note that it is often an empty string.

State keys starting with an @ are reserved for referencing user IDs, such as room members. With the exception of a few events, state events set with a given user’s ID as the state key MUST only be set by that user.

type string Required: The type of the event.
unsigned UnsignedData Contains optional extra information about the event.
UnsignedData
Name 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.
prev_content EventContent The previous content for this event. This field is generated by the local homeserver, and is only returned if the event is a state event, and the client has permission to see the previous content.

Changed in v1.2: Previously, this field was specified at the top level of returned events rather than in unsigned (with the exception of the GET .../notifications endpoint), though in practice no known server implementations honoured this.
redacted_because ClientEventWithoutRoomID The event that redacted this event, if any.
transaction_id string The client-supplied transaction ID, for example, provided via PUT /_matrix/client/v3/rooms/{roomId}/send/{eventType}/{txnId}, if the client being given the event is the same one which sent it.
RoomSummary
Name Type Description
m.heroes [string]

The users which can be used to generate a room name if the room does not have one. Required if the room’s m.room.name or m.room.canonical_alias state events are unset or empty.

This should be the first 5 members of the room, ordered by stream ordering, which are joined or invited. The list must never include the client’s own user ID. When no joined or invited members are available, this should consist of the banned and left users. More than 5 members may be provided, however less than 5 should only be provided when there are less than 5 members to represent.

When lazy-loading room members is enabled, the membership events for the heroes MUST be included in the state, unless they are redundant. When the list of users changes, the server notifies the client by sending a fresh list of heroes. If there are no changes since the last sync, this field may be omitted.

m.invited_member_count integer The number of users with membership of invite. If this field has not changed since the last sync, it may be omitted. Required otherwise.
m.joined_member_count integer The number of users with membership of join, including the client’s own user ID. If this field has not changed since the last sync, it may be omitted. Required otherwise.
Timeline
Name Type Description
events [ClientEventWithoutRoomID] Required: 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 the from parameter of the /rooms/<room_id>/messages endpoint in order to retrieve earlier events. If no earlier events are available, this property may be omitted from the response.
Unread Notification Counts
Name Type Description
highlight_count Highlighted notification count The number of unread notifications for this room with the highlight flag set
notification_count Total notification count The total number of unread notifications for this room
Knocked Room
Name Type Description
knock_state KnockState The stripped state of a room that the user has knocked upon.
KnockState
Name Type Description
events [StrippedStateEvent] The stripped state events that form the knock state.
Left Room
Name Type Description
account_data Account Data The private data that this user has attached to this room.
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.
{
  "account_data": {
    "events": [
      {
        "content": {
          "custom_config_key": "custom_config_value"
        },
        "type": "org.example.custom.config"
      }
    ]
  },
  "next_batch": "s72595_4483_1934",
  "presence": {
    "events": [
      {
        "content": {
          "avatar_url": "mxc://localhost/wefuiwegh8742w",
          "currently_active": false,
          "last_active_ago": 2478593,
          "presence": "online",
          "status_msg": "Making cupcakes"
        },
        "sender": "@example:localhost",
        "type": "m.presence"
      }
    ]
  },
  "rooms": {
    "invite": {
      "!696r7674:example.com": {
        "invite_state": {
          "events": [
            {
              "content": {
                "name": "My Room Name"
              },
              "sender": "@alice:example.com",
              "state_key": "",
              "type": "m.room.name"
            },
            {
              "content": {
                "membership": "invite"
              },
              "sender": "@alice:example.com",
              "state_key": "@bob:example.com",
              "type": "m.room.member"
            }
          ]
        }
      }
    },
    "join": {
      "!726s6s6q:example.com": {
        "account_data": {
          "events": [
            {
              "content": {
                "tags": {
                  "u.work": {
                    "order": 0.9
                  }
                }
              },
              "type": "m.tag"
            },
            {
              "content": {
                "custom_config_key": "custom_config_value"
              },
              "type": "org.example.custom.room.config"
            }
          ]
        },
        "ephemeral": {
          "events": [
            {
              "content": {
                "user_ids": [
                  "@alice:matrix.org",
                  "@bob:example.com"
                ]
              },
              "type": "m.typing"
            }
          ]
        },
        "state": {
          "events": [
            {
              "content": {
                "avatar_url": "mxc://example.org/SEsfnsuifSDFSSEF",
                "displayname": "Alice Margatroid",
                "membership": "join",
                "reason": "Looking for support"
              },
              "event_id": "$143273582443PhrSn:example.org",
              "origin_server_ts": 1432735824653,
              "room_id": "!jEsUZKDJdhlrceRyVU:example.org",
              "sender": "@example:example.org",
              "state_key": "@alice:example.org",
              "type": "m.room.member",
              "unsigned": {
                "age": 1234
              }
            }
          ]
        },
        "summary": {
          "m.heroes": [
            "@alice:example.com",
            "@bob:example.com"
          ],
          "m.invited_member_count": 0,
          "m.joined_member_count": 2
        },
        "timeline": {
          "events": [
            {
              "content": {
                "avatar_url": "mxc://example.org/SEsfnsuifSDFSSEF",
                "displayname": "Alice Margatroid",
                "membership": "join",
                "reason": "Looking for support"
              },
              "event_id": "$143273582443PhrSn:example.org",
              "origin_server_ts": 1432735824653,
              "room_id": "!jEsUZKDJdhlrceRyVU:example.org",
              "sender": "@example:example.org",
              "state_key": "@alice:example.org",
              "type": "m.room.member",
              "unsigned": {
                "age": 1234
              }
            },
            {
              "content": {
                "body": "This is an example text message",
                "format": "org.matrix.custom.html",
                "formatted_body": "<b>This is an example text message</b>",
                "msgtype": "m.text"
              },
              "event_id": "$143273582443PhrSn:example.org",
              "origin_server_ts": 1432735824653,
              "room_id": "!jEsUZKDJdhlrceRyVU:example.org",
              "sender": "@example:example.org",
              "type": "m.room.message",
              "unsigned": {
                "age": 1234
              }
            }
          ],
          "limited": true,
          "prev_batch": "t34-23535_0_0"
        }
      }
    },
    "knock": {
      "!223asd456:example.com": {
        "knock_state": {
          "events": [
            {
              "content": {
                "name": "My Room Name"
              },
              "sender": "@alice:example.com",
              "state_key": "",
              "type": "m.room.name"
            },
            {
              "content": {
                "membership": "knock"
              },
              "sender": "@bob:example.com",
              "state_key": "@bob:example.com",
              "type": "m.room.member"
            }
          ]
        }
      }
    },
    "leave": {}
  }
}

GET /_matrix/client/v3/events


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 endpoint with a since parameter. See the migration guide.

Rate-limited: No
Requires authentication: Yes

Request

Request parameters

query parameters
Name Type Description
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.

Responses

Status Description
200 The events received, which may be none.
400 Bad pagination from parameter.

200 response

Name Type Description
chunk [ClientEvent] An array of events.
end string A token which correlates to the end of chunk. This token should be used in the next request to /events.
start string A token which correlates to the start of chunk. This is usually the same token supplied to from=.
ClientEvent
Name Type Description
content object Required: The body of this event, as created by the client which sent it.
event_id string Required: The globally unique identifier for this event.
origin_server_ts integer Required: Timestamp (in milliseconds since the unix epoch) on originating homeserver when this event was sent.
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.
state_key string

Present if, and only if, this event is a state event. The key making this piece of state unique in the room. Note that it is often an empty string.

State keys starting with an @ are reserved for referencing user IDs, such as room members. With the exception of a few events, state events set with a given user’s ID as the state key MUST only be set by that user.

type string Required: The type of the event.
unsigned UnsignedData Contains optional extra information about the event.
UnsignedData
Name 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.
prev_content EventContent The previous content for this event. This field is generated by the local homeserver, and is only returned if the event is a state event, and the client has permission to see the previous content.

Changed in v1.2: Previously, this field was specified at the top level of returned events rather than in unsigned (with the exception of the GET .../notifications endpoint), though in practice no known server implementations honoured this.
redacted_because ClientEvent The event that redacted this event, if any.
transaction_id string The client-supplied transaction ID, for example, provided via PUT /_matrix/client/v3/rooms/{roomId}/send/{eventType}/{txnId}, if the client being given the event is the same one which sent it.
{
  "chunk": [
    {
      "content": {
        "body": "This is an example text message",
        "format": "org.matrix.custom.html",
        "formatted_body": "<b>This is an example text message</b>",
        "msgtype": "m.text"
      },
      "event_id": "$143273582443PhrSn:example.org",
      "origin_server_ts": 1432735824653,
      "room_id": "!jEsUZKDJdhlrceRyVU:example.org",
      "sender": "@example:example.org",
      "type": "m.room.message",
      "unsigned": {
        "age": 1234
      }
    }
  ],
  "end": "s3457_9_0",
  "start": "s3456_9_0"
}

GET /_matrix/client/v3/events/{eventId}


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}/event/{eventId} API or the /rooms/{roomId}/context/{eventId API.

Rate-limited: No
Requires authentication: Yes

Request

Request parameters

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

Responses

Status Description
200 The full event.
404 The event was not found or you do not have permission to read this event.

200 response

ClientEvent
Name Type Description
content object Required: The body of this event, as created by the client which sent it.
event_id string Required: The globally unique identifier for this event.
origin_server_ts integer Required: Timestamp (in milliseconds since the unix epoch) on originating homeserver when this event was sent.
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.
state_key string

Present if, and only if, this event is a state event. The key making this piece of state unique in the room. Note that it is often an empty string.

State keys starting with an @ are reserved for referencing user IDs, such as room members. With the exception of a few events, state events set with a given user’s ID as the state key MUST only be set by that user.

type string Required: The type of the event.
unsigned UnsignedData Contains optional extra information about the event.
UnsignedData
Name 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.
prev_content EventContent The previous content for this event. This field is generated by the local homeserver, and is only returned if the event is a state event, and the client has permission to see the previous content.

Changed in v1.2: Previously, this field was specified at the top level of returned events rather than in unsigned (with the exception of the GET .../notifications endpoint), though in practice no known server implementations honoured this.
redacted_because ClientEvent The event that redacted this event, if any.
transaction_id string The client-supplied transaction ID, for example, provided via PUT /_matrix/client/v3/rooms/{roomId}/send/{eventType}/{txnId}, if the client being given the event is the same one which sent it.
{
  "content": {
    "body": "This is an example text message",
    "format": "org.matrix.custom.html",
    "formatted_body": "<b>This is an example text message</b>",
    "msgtype": "m.text"
  },
  "event_id": "$143273582443PhrSn:example.org",
  "origin_server_ts": 1432735824653,
  "room_id": "!jEsUZKDJdhlrceRyVU:example.org",
  "sender": "@example:example.org",
  "type": "m.room.message",
  "unsigned": {
    "age": 1234
  }
}

GET /_matrix/client/v3/initialSync


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 endpoint with no since parameter. See the migration guide.

Rate-limited: No
Requires authentication: Yes

Request

Request parameters

query parameters
Name Type Description
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.
limit integer The maximum number of messages to return for each room.

Responses

Status Description
200 The user’s current state.
404 There is no avatar URL for this user or this user does not exist.

200 response

Name Type Description
account_data [Event] The global private data created by this user.
end string Required: A token which correlates to the end of the timelines returned. This token should be used with the /events endpoint to listen for new events.
presence [ClientEvent] Required: A list of presence events.
rooms [RoomInfo] Required:
Event
Name Type Description
content object Required: 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’
ClientEvent
Name Type Description
content object Required: The body of this event, as created by the client which sent it.
event_id string Required: The globally unique identifier for this event.
origin_server_ts integer Required: Timestamp (in milliseconds since the unix epoch) on originating homeserver when this event was sent.
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.
state_key string

Present if, and only if, this event is a state event. The key making this piece of state unique in the room. Note that it is often an empty string.

State keys starting with an @ are reserved for referencing user IDs, such as room members. With the exception of a few events, state events set with a given user’s ID as the state key MUST only be set by that user.

type string Required: The type of the event.
unsigned UnsignedData Contains optional extra information about the event.
UnsignedData
Name 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.
prev_content EventContent The previous content for this event. This field is generated by the local homeserver, and is only returned if the event is a state event, and the client has permission to see the previous content.

Changed in v1.2: Previously, this field was specified at the top level of returned events rather than in unsigned (with the exception of the GET .../notifications endpoint), though in practice no known server implementations honoured this.
redacted_because ClientEvent The event that redacted this event, if any.
transaction_id string The client-supplied transaction ID, for example, provided via PUT /_matrix/client/v3/rooms/{roomId}/send/{eventType}/{txnId}, if the client being given the event is the same one which sent it.
RoomInfo
Name Type Description
account_data [ClientEvent] The private data that this user has attached to this room.
invite InviteEvent The invite event if membership is invite
membership enum Required: The user’s membership state in this room.

One of: [invite join leave ban].

messages PaginationChunk The pagination chunk for this room.
room_id string Required: The ID of this room.
state [ClientEvent] 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].

InviteEvent
Name Type Description
content object Required: The body of this event, as created by the client which sent it.
event_id string Required: The globally unique identifier for this event.
origin_server_ts integer Required: Timestamp (in milliseconds since the unix epoch) on originating homeserver when this event was sent.
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.
state_key string

Present if, and only if, this event is a state event. The key making this piece of state unique in the room. Note that it is often an empty string.

State keys starting with an @ are reserved for referencing user IDs, such as room members. With the exception of a few events, state events set with a given user’s ID as the state key MUST only be set by that user.

type string Required: The type of the event.
unsigned UnsignedData Contains optional extra information about the event.
PaginationChunk
Name Type Description
chunk [ClientEvent] 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 preceded them leaving. This array will consist of at most limit elements.
end string Required: A token which correlates to the end of chunk. Can be passed to /rooms/<room_id>/messages to retrieve later events.
start string

A token which correlates to the start of chunk. Can be passed to /rooms/<room_id>/messages to retrieve earlier events.

If no earlier events are available, this property may be omitted from the response.

{
  "account_data": [
    {
      "content": {
        "custom_config_key": "custom_config_value"
      },
      "type": "org.example.custom.config"
    }
  ],
  "end": "s3456_9_0",
  "presence": [
    {
      "content": {
        "avatar_url": "mxc://localhost/wefuiwegh8742w",
        "currently_active": false,
        "last_active_ago": 2478593,
        "presence": "online",
        "status_msg": "Making cupcakes"
      },
      "sender": "@example:localhost",
      "type": "m.presence"
    }
  ],
  "rooms": [
    {
      "account_data": [
        {
          "content": {
            "tags": {
              "work": {
                "order": 1
              }
            }
          },
          "type": "m.tag"
        },
        {
          "content": {
            "custom_config_key": "custom_config_value"
          },
          "type": "org.example.custom.room.config"
        }
      ],
      "membership": "join",
      "messages": {
        "chunk": [
          {
            "content": {
              "body": "This is an example text message",
              "format": "org.matrix.custom.html",
              "formatted_body": "<b>This is an example text message</b>",
              "msgtype": "m.text"
            },
            "event_id": "$143273582443PhrSn:example.org",
            "origin_server_ts": 1432735824653,
            "room_id": "!TmaZBKYIFrIPVGoUYp:localhost",
            "sender": "@example:example.org",
            "type": "m.room.message",
            "unsigned": {
              "age": 1234
            }
          },
          {
            "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://example.org/FHyPlCeYUSFFxlgbQYZmoEoe",
                "w": 480
              },
              "msgtype": "m.video",
              "url": "mxc://example.org/a526eYUSFFxlgbQYZmo442"
            },
            "event_id": "$143273582443PhrSn:example.org",
            "origin_server_ts": 1432735824653,
            "room_id": "!TmaZBKYIFrIPVGoUYp:localhost",
            "sender": "@example:example.org",
            "type": "m.room.message",
            "unsigned": {
              "age": 1234
            }
          }
        ],
        "end": "s3456_9_0",
        "start": "t44-3453_9_0"
      },
      "room_id": "!TmaZBKYIFrIPVGoUYp:localhost",
      "state": [
        {
          "content": {
            "join_rule": "public"
          },
          "event_id": "$143273582443PhrSn:example.org",
          "origin_server_ts": 1432735824653,
          "room_id": "!TmaZBKYIFrIPVGoUYp:localhost",
          "sender": "@example:example.org",
          "state_key": "",
          "type": "m.room.join_rules",
          "unsigned": {
            "age": 1234
          }
        },
        {
          "content": {
            "avatar_url": "mxc://example.org/SEsfnsuifSDFSSEF",
            "displayname": "Alice Margatroid",
            "membership": "join",
            "reason": "Looking for support"
          },
          "event_id": "$143273582443PhrSn:example.org",
          "origin_server_ts": 1432735824653,
          "room_id": "!TmaZBKYIFrIPVGoUYp:localhost",
          "sender": "@example:example.org",
          "state_key": "@alice:example.org",
          "type": "m.room.member",
          "unsigned": {
            "age": 1234
          }
        },
        {
          "content": {
            "creator": "@example:example.org",
            "m.federate": true,
            "predecessor": {
              "event_id": "$something:example.org",
              "room_id": "!oldroom:example.org"
            },
            "room_version": "1"
          },
          "event_id": "$143273582443PhrSn:example.org",
          "origin_server_ts": 1432735824653,
          "room_id": "!TmaZBKYIFrIPVGoUYp:localhost",
          "sender": "@example:example.org",
          "state_key": "",
          "type": "m.room.create",
          "unsigned": {
            "age": 1234
          }
        },
        {
          "content": {
            "ban": 50,
            "events": {
              "m.room.name": 100,
              "m.room.power_levels": 100
            },
            "events_default": 0,
            "invite": 50,
            "kick": 50,
            "notifications": {
              "room": 20
            },
            "redact": 50,
            "state_default": 50,
            "users": {
              "@example:localhost": 100
            },
            "users_default": 0
          },
          "event_id": "$143273582443PhrSn:example.org",
          "origin_server_ts": 1432735824653,
          "room_id": "!TmaZBKYIFrIPVGoUYp:localhost",
          "sender": "@example:example.org",
          "state_key": "",
          "type": "m.room.power_levels",
          "unsigned": {
            "age": 1234
          }
        }
      ],
      "visibility": "private"
    }
  ]
}

Getting events for a room

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

GET /_matrix/client/v3/rooms/{roomId}/event/{eventId}


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

Rate-limited: No
Requires authentication: Yes

Request

Request parameters

path parameters
Name Type Description
eventId string Required: The event ID to get.
roomId string Required: The ID of the room the event is in.

Responses

Status Description
200 The full event.
404 The event was not found or you do not have permission to read this event.

200 response

ClientEvent
Name Type Description
content object Required: The body of this event, as created by the client which sent it.
event_id string Required: The globally unique identifier for this event.
origin_server_ts integer Required: Timestamp (in milliseconds since the unix epoch) on originating homeserver when this event was sent.
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.
state_key string

Present if, and only if, this event is a state event. The key making this piece of state unique in the room. Note that it is often an empty string.

State keys starting with an @ are reserved for referencing user IDs, such as room members. With the exception of a few events, state events set with a given user’s ID as the state key MUST only be set by that user.

type string Required: The type of the event.
unsigned UnsignedData Contains optional extra information about the event.
UnsignedData
Name 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.
prev_content EventContent The previous content for this event. This field is generated by the local homeserver, and is only returned if the event is a state event, and the client has permission to see the previous content.

Changed in v1.2: Previously, this field was specified at the top level of returned events rather than in unsigned (with the exception of the GET .../notifications endpoint), though in practice no known server implementations honoured this.
redacted_because ClientEvent The event that redacted this event, if any.
transaction_id string The client-supplied transaction ID, for example, provided via PUT /_matrix/client/v3/rooms/{roomId}/send/{eventType}/{txnId}, if the client being given the event is the same one which sent it.
{
  "content": {
    "body": "This is an example text message",
    "format": "org.matrix.custom.html",
    "formatted_body": "<b>This is an example text message</b>",
    "msgtype": "m.text"
  },
  "event_id": "$143273582443PhrSn:example.org",
  "origin_server_ts": 1432735824653,
  "room_id": "!636q39766251:matrix.org",
  "sender": "@example:example.org",
  "type": "m.room.message",
  "unsigned": {
    "age": 1234
  }
}

404 response

Error
Name Type Description
errcode string Required: An error code.
error string A human-readable error message.
{
  "errcode": "M_NOT_FOUND",
  "error": "Event not found."
}

GET /_matrix/client/v3/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.

Rate-limited: No
Requires authentication: Yes

Request

Request parameters

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

Responses

Status Description
200 A map of MXID to room member objects.
403 You aren’t a member of the room.

200 response

Name Type Description
joined { string: RoomMember} A map from user ID to a RoomMember object.
RoomMember
Name Type Description
avatar_url string The mxc avatar url of the user this object is representing.
display_name string The display name of the user this object is representing.
{
  "joined": {
    "@bar:example.com": {
      "avatar_url": "mxc://riot.ovh/printErCATzZijQsSDWorRaK",
      "display_name": "Bar"
    }
  }
}

GET /_matrix/client/v3/rooms/{roomId}/members


Get the list of members for this room.

Rate-limited: No
Requires authentication: Yes

Request

Request parameters

path parameters
Name Type Description
roomId string Required: The room to get the member events for.
query parameters
Name Type Description
at string The point in time (pagination token) to return members for in the room. This token can be obtained from a prev_batch token returned for each room by the sync API. Defaults to the current state of the room, as determined by the server.
membership enum The kind of membership to filter for. Defaults to no filtering if unspecified. When specified alongside not_membership, the two parameters create an ‘or’ condition: either the membership is the same as membership or is not the same as not_membership.

One of: [join invite knock leave ban].

not_membership enum The kind of membership to exclude from the results. Defaults to no filtering if unspecified.

One of: [join invite knock leave ban].


Responses

Status Description
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.
403 You aren’t a member of the room and weren’t previously a member of the room.

200 response

Name Type Description
chunk [ClientEvent]
ClientEvent
Name Type Description
content object Required: The body of this event, as created by the client which sent it.
event_id string Required: The globally unique identifier for this event.
origin_server_ts integer Required: Timestamp (in milliseconds since the unix epoch) on originating homeserver when this event was sent.
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.
state_key string

Present if, and only if, this event is a state event. The key making this piece of state unique in the room. Note that it is often an empty string.

State keys starting with an @ are reserved for referencing user IDs, such as room members. With the exception of a few events, state events set with a given user’s ID as the state key MUST only be set by that user.

type string Required: The type of the event.
unsigned UnsignedData Contains optional extra information about the event.
UnsignedData
Name 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.
prev_content EventContent The previous content for this event. This field is generated by the local homeserver, and is only returned if the event is a state event, and the client has permission to see the previous content.

Changed in v1.2: Previously, this field was specified at the top level of returned events rather than in unsigned (with the exception of the GET .../notifications endpoint), though in practice no known server implementations honoured this.
redacted_because ClientEvent The event that redacted this event, if any.
transaction_id string The client-supplied transaction ID, for example, provided via PUT /_matrix/client/v3/rooms/{roomId}/send/{eventType}/{txnId}, if the client being given the event is the same one which sent it.
{
  "chunk": [
    {
      "content": {
        "avatar_url": "mxc://example.org/SEsfnsuifSDFSSEF",
        "displayname": "Alice Margatroid",
        "membership": "join",
        "reason": "Looking for support"
      },
      "event_id": "$143273582443PhrSn:example.org",
      "origin_server_ts": 1432735824653,
      "room_id": "!636q39766251:example.com",
      "sender": "@example:example.org",
      "state_key": "@alice:example.org",
      "type": "m.room.member",
      "unsigned": {
        "age": 1234
      }
    }
  ]
}

GET /_matrix/client/v3/rooms/{roomId}/state


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

Rate-limited: No
Requires authentication: Yes

Request

Request parameters

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

Responses

Status Description
200 The current state of the room
403 You aren’t a member of the room and weren’t previously a member of the room.

200 response

Array of ClientEvent.

ClientEvent
Name Type Description
content object Required: The body of this event, as created by the client which sent it.
event_id string Required: The globally unique identifier for this event.
origin_server_ts integer Required: Timestamp (in milliseconds since the unix epoch) on originating homeserver when this event was sent.
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.
state_key string

Present if, and only if, this event is a state event. The key making this piece of state unique in the room. Note that it is often an empty string.

State keys starting with an @ are reserved for referencing user IDs, such as room members. With the exception of a few events, state events set with a given user’s ID as the state key MUST only be set by that user.

type string Required: The type of the event.
unsigned UnsignedData Contains optional extra information about the event.
UnsignedData
Name 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.
prev_content EventContent The previous content for this event. This field is generated by the local homeserver, and is only returned if the event is a state event, and the client has permission to see the previous content.

Changed in v1.2: Previously, this field was specified at the top level of returned events rather than in unsigned (with the exception of the GET .../notifications endpoint), though in practice no known server implementations honoured this.
redacted_because ClientEvent The event that redacted this event, if any.
transaction_id string The client-supplied transaction ID, for example, provided via PUT /_matrix/client/v3/rooms/{roomId}/send/{eventType}/{txnId}, if the client being given the event is the same one which sent it.
[
  {
    "content": {
      "join_rule": "public"
    },
    "event_id": "$143273582443PhrSn:example.org",
    "origin_server_ts": 1432735824653,
    "room_id": "!636q39766251:example.com",
    "sender": "@example:example.org",
    "state_key": "",
    "type": "m.room.join_rules",
    "unsigned": {
      "age": 1234
    }
  },
  {
    "content": {
      "avatar_url": "mxc://example.org/SEsfnsuifSDFSSEF",
      "displayname": "Alice Margatroid",
      "membership": "join",
      "reason": "Looking for support"
    },
    "event_id": "$143273582443PhrSn:example.org",
    "origin_server_ts": 1432735824653,
    "room_id": "!636q39766251:example.com",
    "sender": "@example:example.org",
    "state_key": "@alice:example.org",
    "type": "m.room.member",
    "unsigned": {
      "age": 1234
    }
  },
  {
    "content": {
      "creator": "@example:example.org",
      "m.federate": true,
      "predecessor": {
        "event_id": "$something:example.org",
        "room_id": "!oldroom:example.org"
      },
      "room_version": "1"
    },
    "event_id": "$143273582443PhrSn:example.org",
    "origin_server_ts": 1432735824653,
    "room_id": "!636q39766251:example.com",
    "sender": "@example:example.org",
    "state_key": "",
    "type": "m.room.create",
    "unsigned": {
      "age": 1234
    }
  },
  {
    "content": {
      "ban": 50,
      "events": {
        "m.room.name": 100,
        "m.room.power_levels": 100
      },
      "events_default": 0,
      "invite": 50,
      "kick": 50,
      "notifications": {
        "room": 20
      },
      "redact": 50,
      "state_default": 50,
      "users": {
        "@example:localhost": 100
      },
      "users_default": 0
    },
    "event_id": "$143273582443PhrSn:example.org",
    "origin_server_ts": 1432735824653,
    "room_id": "!636q39766251:example.com",
    "sender": "@example:example.org",
    "state_key": "",
    "type": "m.room.power_levels",
    "unsigned": {
      "age": 1234
    }
  }
]

GET /_matrix/client/v3/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.

Rate-limited: No
Requires authentication: Yes

Request

Request parameters

path parameters
Name Type Description
eventType string Required: The type of state to look up.
roomId string Required: The room to look up the state in.
stateKey string Required: The key of the state to look up. Defaults to an empty string. When an empty string, the trailing slash on this endpoint is optional.

Responses

Status Description
200 The content of the state event.
403 You aren’t a member of the room and weren’t previously a member of the room.
404 The room has no state with the given type or key.

200 response

{
  "name": "Example room name"
}

GET /_matrix/client/v3/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.

Note: This endpoint supports lazy-loading of room member events. See Lazy-loading room members for more information.

Rate-limited: No
Requires authentication: Yes

Request

Request parameters

path parameters
Name Type Description
roomId string Required: The room to get events from.
query parameters
Name Type Description
dir enum Required: The direction to return events from. If this is set to f, events will be returned in chronological order starting at from. If it is set to b, events will be returned in reverse chronological order, again starting at from.

One of: [b f].

filter string A JSON RoomEventFilter to filter returned events with.
from string

The token to start returning events from. This token can be obtained from a prev_batch or next_batch token returned by the /sync endpoint, or from an end token returned by a previous request to this endpoint.

This endpoint can also accept a value returned as a start token by a previous request to this endpoint, though servers are not required to support this. Clients should not rely on the behaviour.

If it is not provided, the homeserver shall return a list of messages from the first or last (per the value of the dir parameter) visible event in the room history for the requesting user.



Changed in v1.3: Previously, this field was required and paginating from the first or last visible event in the room history wasn’t supported.
limit integer The maximum number of events to return. Default: 10.
to string The token to stop returning events at. This token can be obtained from a prev_batch or next_batch token returned by the /sync endpoint, or from an end token returned by a previous request to this endpoint.

Responses

Status Description
200 A list of messages with a new token to request more.
403 You aren’t a member of the room.

200 response

Name Type Description
chunk [ClientEvent] Required:

A list of room events. The order depends on the dir parameter. For dir=b events will be in reverse-chronological order, for dir=f in chronological order. (The exact definition of chronological is dependent on the server implementation.)

Note that an empty chunk does not necessarily imply that no more events are available. Clients should continue to paginate until no end property is returned.

end string

A token corresponding to the end of chunk. This token can be passed back to this endpoint to request further events.

If no further events are available (either because we have reached the start of the timeline, or because the user does not have permission to see any more events), this property is omitted from the response.

start string Required: A token corresponding to the start of chunk. This will be the same as the value given in from.
state [ClientEvent]

A list of state events relevant to showing the chunk. For example, if lazy_load_members is enabled in the filter then this may contain the membership events for the senders of events in the chunk.

Unless include_redundant_members is true, the server may remove membership events which would have already been sent to the client in prior calls to this endpoint, assuming the membership of those members has not changed.

ClientEvent
Name Type Description
content object Required: The body of this event, as created by the client which sent it.
event_id string Required: The globally unique identifier for this event.
origin_server_ts integer Required: Timestamp (in milliseconds since the unix epoch) on originating homeserver when this event was sent.
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.
state_key string

Present if, and only if, this event is a state event. The key making this piece of state unique in the room. Note that it is often an empty string.

State keys starting with an @ are reserved for referencing user IDs, such as room members. With the exception of a few events, state events set with a given user’s ID as the state key MUST only be set by that user.

type string Required: The type of the event.
unsigned UnsignedData Contains optional extra information about the event.
UnsignedData
Name 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.
prev_content EventContent The previous content for this event. This field is generated by the local homeserver, and is only returned if the event is a state event, and the client has permission to see the previous content.

Changed in v1.2: Previously, this field was specified at the top level of returned events rather than in unsigned (with the exception of the GET .../notifications endpoint), though in practice no known server implementations honoured this.
redacted_because ClientEvent The event that redacted this event, if any.
transaction_id string The client-supplied transaction ID, for example, provided via PUT /_matrix/client/v3/rooms/{roomId}/send/{eventType}/{txnId}, if the client being given the event is the same one which sent it.
{
  "chunk": [
    {
      "content": {
        "body": "This is an example text message",
        "format": "org.matrix.custom.html",
        "formatted_body": "<b>This is an example text message</b>",
        "msgtype": "m.text"
      },
      "event_id": "$143273582443PhrSn:example.org",
      "origin_server_ts": 1432735824653,
      "room_id": "!636q39766251:example.com",
      "sender": "@example:example.org",
      "type": "m.room.message",
      "unsigned": {
        "age": 1234
      }
    },
    {
      "content": {
        "name": "The room name"
      },
      "event_id": "$143273582443PhrSn:example.org",
      "origin_server_ts": 1432735824653,
      "room_id": "!636q39766251:example.com",
      "sender": "@example:example.org",
      "state_key": "",
      "type": "m.room.name",
      "unsigned": {
        "age": 1234
      }
    },
    {
      "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://example.org/FHyPlCeYUSFFxlgbQYZmoEoe",
          "w": 480
        },
        "msgtype": "m.video",
        "url": "mxc://example.org/a526eYUSFFxlgbQYZmo442"
      },
      "event_id": "$143273582443PhrSn:example.org",
      "origin_server_ts": 1432735824653,
      "room_id": "!636q39766251:example.com",
      "sender": "@example:example.org",
      "type": "m.room.message",
      "unsigned": {
        "age": 1234
      }
    }
  ],
  "end": "t47409-4357353_219380_26003_2265",
  "start": "t47429-4392820_219380_26003_2265"
}

GET /_matrix/client/v3/rooms/{roomId}/initialSync


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.

Rate-limited: No
Requires authentication: Yes

Request

Request parameters

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

Responses

Status Description
200 The current state of the room
403 You aren’t a member of the room and weren’t previously a member of the room.

200 response

RoomInfo
Name Type Description
account_data [Event] The private data that this user has attached to 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.
room_id string Required: The ID of this room.
state [ClientEvent] 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].

Event
Name Type Description
content object Required: 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’
PaginationChunk
Name Type Description
chunk [ClientEvent] 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 preceded them leaving. This array will consist of at most limit elements.
end string Required: A token which correlates to the end of chunk. Can be passed to /rooms/<room_id>/messages to retrieve later events.
start string

A token which correlates to the start of chunk. Can be passed to /rooms/<room_id>/messages to retrieve earlier events.

If no earlier events are available, this property may be omitted from the response.

ClientEvent
Name Type Description
content object Required: The body of this event, as created by the client which sent it.
event_id string Required: The globally unique identifier for this event.
origin_server_ts integer Required: Timestamp (in milliseconds since the unix epoch) on originating homeserver when this event was sent.
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.
state_key string

Present if, and only if, this event is a state event. The key making this piece of state unique in the room. Note that it is often an empty string.

State keys starting with an @ are reserved for referencing user IDs, such as room members. With the exception of a few events, state events set with a given user’s ID as the state key MUST only be set by that user.

type string Required: The type of the event.
unsigned UnsignedData Contains optional extra information about the event.
UnsignedData
Name 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.
prev_content EventContent The previous content for this event. This field is generated by the local homeserver, and is only returned if the event is a state event, and the client has permission to see the previous content.

Changed in v1.2: Previously, this field was specified at the top level of returned events rather than in unsigned (with the exception of the GET .../notifications endpoint), though in practice no known server implementations honoured this.
redacted_because ClientEvent The event that redacted this event, if any.
transaction_id string The client-supplied transaction ID, for example, provided via PUT /_matrix/client/v3/rooms/{roomId}/send/{eventType}/{txnId}, if the client being given the event is the same one which sent it.
{
  "account_data": [
    {
      "content": {
        "tags": {
          "work": {
            "order": "1"
          }
        }
      },
      "type": "m.tag"
    }
  ],
  "membership": "join",
  "messages": {
    "chunk": [
      {
        "content": {
          "body": "This is an example text message",
          "format": "org.matrix.custom.html",
          "formatted_body": "<b>This is an example text message</b>",
          "msgtype": "m.text"
        },
        "event_id": "$143273582443PhrSn:example.org",
        "origin_server_ts": 1432735824653,
        "room_id": "!636q39766251:example.com",
        "sender": "@example:example.org",
        "type": "m.room.message",
        "unsigned": {
          "age": 1234
        }
      },
      {
        "content": {
          "body": "something-important.doc",
          "filename": "something-important.doc",
          "info": {
            "mimetype": "application/msword",
            "size": 46144
          },
          "msgtype": "m.file",
          "url": "mxc://example.org/FHyPlCeYUSFFxlgbQYZmoEoe"
        },
        "event_id": "$143273582443PhrSn:example.org",
        "origin_server_ts": 1432735824653,
        "room_id": "!636q39766251:example.com",
        "sender": "@example:example.org",
        "type": "m.room.message",
        "unsigned": {
          "age": 1234
        }
      }
    ],
    "end": "s3456_9_0",
    "start": "t44-3453_9_0"
  },
  "room_id": "!636q39766251:example.com",
  "state": [
    {
      "content": {
        "join_rule": "public"
      },
      "event_id": "$143273582443PhrSn:example.org",
      "origin_server_ts": 1432735824653,
      "room_id": "!636q39766251:example.com",
      "sender": "@example:example.org",
      "state_key": "",
      "type": "m.room.join_rules",
      "unsigned": {
        "age": 1234
      }
    },
    {
      "content": {
        "avatar_url": "mxc://example.org/SEsfnsuifSDFSSEF",
        "displayname": "Alice Margatroid",
        "membership": "join",
        "reason": "Looking for support"
      },
      "event_id": "$143273582443PhrSn:example.org",
      "origin_server_ts": 1432735824653,
      "room_id": "!636q39766251:example.com",
      "sender": "@example:example.org",
      "state_key": "@alice:example.org",
      "type": "m.room.member",
      "unsigned": {
        "age": 1234
      }
    },
    {
      "content": {
        "creator": "@example:example.org",
        "m.federate": true,
        "predecessor": {
          "event_id": "$something:example.org",
          "room_id": "!oldroom:example.org"
        },
        "room_version": "1"
      },
      "event_id": "$143273582443PhrSn:example.org",
      "origin_server_ts": 1432735824653,
      "room_id": "!636q39766251:example.com",
      "sender": "@example:example.org",
      "state_key": "",
      "type": "m.room.create",
      "unsigned": {
        "age": 1234
      }
    },
    {
      "content": {
        "ban": 50,
        "events": {
          "m.room.name": 100,
          "m.room.power_levels": 100
        },
        "events_default": 0,
        "invite": 50,
        "kick": 50,
        "notifications": {
          "room": 20
        },
        "redact": 50,
        "state_default": 50,
        "users": {
          "@example:localhost": 100
        },
        "users_default": 0
      },
      "event_id": "$143273582443PhrSn:example.org",
      "origin_server_ts": 1432735824653,
      "room_id": "!636q39766251:example.com",
      "sender": "@example:example.org",
      "state_key": "",
      "type": "m.room.power_levels",
      "unsigned": {
        "age": 1234
      }
    }
  ],
  "visibility": "private"
}

Sending events to a room

PUT /_matrix/client/v3/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.

If the event type being sent is m.room.canonical_alias servers SHOULD ensure that any new aliases being listed in the event are valid per their grammar/syntax and that they point to the room ID where the state event is to be sent. Servers do not validate aliases which are being removed or are already present in the state event.

Rate-limited: No
Requires authentication: Yes

Request

Request parameters

path parameters
Name Type Description
eventType string Required: The type of event to send.
roomId string Required: The room to set the state in
stateKey string Required: The state_key for the state to send. Defaults to the empty string. When an empty string, the trailing slash on this endpoint is optional.

Request body

Request body example

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

Responses

Status Description
200 An ID for the sent event.
400

The sender’s request is malformed.

Some example error codes include:

  • M_INVALID_PARAM: One or more aliases within the m.room.canonical_alias event have invalid syntax.

  • M_BAD_ALIAS: One or more aliases within the m.room.canonical_alias event do not point to the room ID for which the state event is to be sent to.

403 The sender doesn’t have permission to send the event into the room.

200 response

Name Type Description
event_id string Required: A unique identifier for the event.
{
  "event_id": "$YUwRidLecu:example.com"
}

400 response

Error
Name Type Description
errcode string Required: An error code.
error string A human-readable error message.
{
  "errcode": "M_BAD_ALIAS",
  "error": "The alias '#hello:example.org' does not point to this room."
}

403 response

Error
Name Type Description
errcode string Required: An error code.
error string A human-readable error message.
{
  "errcode": "M_FORBIDDEN",
  "error": "You do not have permission to send the event."
}

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%3Aexample.org
{ "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" }

PUT /_matrix/client/v3/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.

Rate-limited: No
Requires authentication: Yes

Request

Request parameters

path parameters
Name Type Description
eventType string Required: The type of event to send.
roomId string Required: The room to send the event to.
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.

Request body

Request body example

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

Responses

Status Description
200 An ID for the sent event.

200 response

Name Type Description
event_id string Required: A unique identifier for the event.
{
  "event_id": "$YUwRidLecu:example.com"
}

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. Servers should include a copy of the m.room.redaction event under unsigned as redacted_because when serving the redacted event to clients.

The exact algorithm to apply against an event is defined in the room version specification, as are the criteria homeservers should use when deciding whether to accept a redaction event from a remote homeserver.

When a client receives an m.room.redaction event, it should change the affected event in the same way a server does.

Events

m.room.redaction


This event is created by the server to describe which event has been redacted, by whom, and optionally why. The event that has been redacted is specified in the redacts event level key. Redacting an event means that all keys not required by the protocol are stripped off, allowing messages to be hidden or allowing admins to remove offensive or illegal content.

Event type: Message event

Content

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

Examples

{
  "content": {
    "reason": "Spamming"
  },
  "event_id": "$143273582443PhrSn:example.org",
  "origin_server_ts": 1432735824653,
  "redacts": "$fukweghifu23:localhost",
  "room_id": "!jEsUZKDJdhlrceRyVU:example.org",
  "sender": "@example:example.org",
  "type": "m.room.redaction",
  "unsigned": {
    "age": 1234
  }
}

Client behaviour

PUT /_matrix/client/v3/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.

Any user with a power level greater than or equal to the m.room.redaction event power level may send redaction events in the room. If the user’s power level greater is also greater than or equal to the redact power level of the room, the user may redact events sent by other users.

Server administrators may redact events sent by users on their server.

Rate-limited: No
Requires authentication: Yes

Request

Request parameters

path parameters
Name Type Description
eventId string Required: The ID of the event to redact
roomId string Required: The room from which to redact the event.
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.

Request body

Name Type Description
reason string The reason for the event being redacted.

Request body example

{
  "reason": "Indecent material"
}

Responses

Status Description
200 An ID for the redaction event.

200 response

Name Type Description
event_id string A unique identifier for the event.
{
  "event_id": "$YUwQidLecu:example.com"
}

Forming relationships between events

[Changed in v1.3]

In some cases it is desirable to logically associate one event’s contents with another event’s contents — for example, when replying to a message, editing an event, or simply looking to add context for an event’s purpose.

Events are related to each other in a parent/child structure, where any event can become a parent by simply having a child event point at it. Parent events do not define their children, instead relying on the children to describe their parent.

The relationship between a child and its parent event is described in the child event’s content as m.relates_to (defined below). A child event can point at any other event, including another child event, to build the relationship so long as both events are in the same room, however additional restrictions might be imposed by the type of the relationship (the rel_type).

To allow the server to aggregate and find child events for a parent, the m.relates_to key of an event MUST be included in the plaintext copy of the event. It cannot be exclusively recorded in the encrypted payload as the server cannot decrypt the event for processing.

Relationships which don’t match the schema, or which break the rules of a relationship, are simply ignored. An example might be the parent and child being in different rooms, or the relationship missing properties required by the schema below. Clients handling such invalid relationships should show the events independently of each other, optionally with an error message.

m.relates_to is defined as follows:

m.relates_to


Describes the relationship of an event to its parent. This is contained within the event’s content alongside other fields for the relevant event type.

m.relates_to
Name Type Description
event_id string Required: The event ID of the event that this event relates to.
rel_type string Required:

The namespaced relationship type. Values must use the Common Namespaced Identifier Grammar.

The relationship type determines how clients should perceive the event, and in what context. Some relationship types are processed server-side for “bundling”, though not all relationships require such behaviour. For example, an m.thread relationship type might denote that the event is part of a “thread” of messages and should be rendered as such.

Examples

{
  "m.relates_to": {
    "event_id": "$an_event",
    "rel_type": "org.example.relationship"
  }
}

Relationship types

This specification describes the following relationship types:

Aggregations

[Added in v1.3]

Some child events can be “aggregated” by the server, depending on their rel_type. This can allow a set of child events to be summarised to the client without the client needing the child events themselves.

An example of this might be that a rel_type requires an extra key field which, when appropriately specified, would mean that the client receives a total count for the number of times that key was used by child events.

The actual aggregation format depends on the rel_type.

Aggregations are sometimes automatically included by a server alongside the parent event. This is known as a “bundled aggregation” or “bundle” for simplicity. The act of doing this is “bundling”.

When an event is served to the client through the APIs listed below, a m.relations property is included under unsigned if the event has child events which can be aggregated and point at it. The m.relations property is an object keyed by rel_type and value being the type-specific aggregated format for that rel_type, also known as the bundle.

For example (unimportant fields not included):

{
  "event_id": "$my_event",
  "unsigned": {
    "m.relations": {
      "org.example.possible_annotations": [
        {
          "key": "👍",
          "origin_server_ts": 1562763768320,
          "count": 3
        },
        {
          "key": "👎",
          "origin_server_ts": 1562763768320,
          "count": 1
        }
      ],
      "org.example.possible_thread": {
        "current_server_participated": true,
        "count": 7,
        "latest_event": {
          "event_id": "$another_event",
          "content": {
            "body": "Hello world"
          }
        }
      }
    }
  }
}

Note how the org.example.possible_annotations bundle is an array compared to the org.example.possible_thread bundle where the server is summarising the state of the relationship in a single object. Both are valid ways to aggregate, and their exact types depend on the rel_type.

The endpoints where the server should include bundled aggregations are:

While this functionality allows the client to see what was known to the server at the time of handling, the client should continue to aggregate locally if it is aware of the relationship type’s behaviour. For example, a client might increment a count on a parent event’s bundle if it saw a new child event which referenced that parent.

The bundle provided by the server only includes child events which were known at the time the client would receive the bundle. For example, in a single /sync response with the parent and multiple child events the child events would have already been included on the parent’s m.relations field. Events received in future syncs would need to be aggregated manually by the client.

When a parent event is redacted, the child events which pointed to that parent remain, however when a child event is redacted then the relationship is broken. Therefore, the server needs to de-aggregate or disassociate the event once the relationship is lost. Clients with local aggregation or which handle redactions locally should do the same.

It is suggested that clients perform local echo on aggregations — for instance, aggregating a new child event into a bundle optimistically until the server returns a failure or the client gives up on sending the event, at which point the event should be de-aggregated and an error or similar shown. The client should be cautious to not aggregate an event twice if it has already optimistically aggregated the event. Clients are encouraged to take this a step further to additionally track child events which target unsent/pending events, likely using the transaction ID as a temporary event ID until a proper event ID is known.

Relationships API

[Added in v1.3]

To retrieve the child events for a parent from the server, the client can call the following endpoint.

This endpoint is particularly useful if the client has lost context on the aggregation for a parent event and needs to rebuild/verify it.

GET /_matrix/client/v1/rooms/{roomId}/relations/{eventId}


Retrieve all of the child events for a given parent event.

Note that when paginating the from token should be “after” the to token in terms of topological ordering, because it is only possible to paginate “backwards” through events, starting at from.

For example, passing a from token from page 2 of the results, and a to token from page 1, would return the empty set. The caller can use a from token from page 1 and a to token from page 2 to paginate over the same range, however.

Rate-limited: No
Requires authentication: Yes

Request

Request parameters

path parameters
Name Type Description
eventId string Required: The ID of the parent event whose child events are to be returned.
roomId string Required: The ID of the room containing the parent event.
query parameters
Name Type Description
from string

The pagination token to start returning results from. If not supplied, results start at the most recent topological event known to the server.

Can be a next_batch token from a previous call, or a returned start token from /messages, or a next_batch token from /sync.

limit integer

The maximum number of results to return in a single chunk. The server can and should apply a maximum value to this parameter to avoid large responses.

Similarly, the server should apply a default value when not supplied.

to string

The pagination token to stop returning results at. If not supplied, results continue up to limit or until there are no more events.

Like from, this can be a previous token from a prior call to this endpoint or from /messages or /sync.


Responses

Status Description
200 The paginated child events which point to the parent. If no events are pointing to the parent or the pagination yields no results, an empty chunk is returned.
404 The parent event was not found or the user does not have permission to read this event (it might be contained in history that is not accessible to the user).

200 response

Name Type Description
chunk ChildEventsChunk Required: The child events of the requested event, ordered topologically most-recent first.
next_batch string An opaque string representing a pagination token. The absence of this token means there are no more results to fetch and the client should stop paginating.
prev_batch string An opaque string representing a pagination token. The absence of this token means this is the start of the result set, i.e. this is the first batch/page.
ClientEvent
Name Type Description
content object Required: The body of this event, as created by the client which sent it.
event_id string Required: The globally unique identifier for this event.
origin_server_ts integer Required: Timestamp (in milliseconds since the unix epoch) on originating homeserver when this event was sent.
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.
state_key string

Present if, and only if, this event is a state event. The key making this piece of state unique in the room. Note that it is often an empty string.

State keys starting with an @ are reserved for referencing user IDs, such as room members. With the exception of a few events, state events set with a given user’s ID as the state key MUST only be set by that user.

type string Required: The type of the event.
unsigned UnsignedData Contains optional extra information about the event.
UnsignedData
Name 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.
prev_content EventContent The previous content for this event. This field is generated by the local homeserver, and is only returned if the event is a state event, and the client has permission to see the previous content.

Changed in v1.2: Previously, this field was specified at the top level of returned events rather than in unsigned (with the exception of the GET .../notifications endpoint), though in practice no known server implementations honoured this.
redacted_because ClientEvent The event that redacted this event, if any.
transaction_id string The client-supplied transaction ID, for example, provided via PUT /_matrix/client/v3/rooms/{roomId}/send/{eventType}/{txnId}, if the client being given the event is the same one which sent it.
{
  "chunk": [
    {
      "content": {
        "m.relates_to": {
          "event_id": "$asfDuShaf7Gafaw",
          "rel_type": "org.example.my_relation"
        }
      },
      "event_id": "$143273582443PhrSn:example.org",
      "origin_server_ts": 1432735824653,
      "room_id": "!636q39766251:matrix.org",
      "sender": "@example:example.org",
      "type": "m.room.message",
      "unsigned": {
        "age": 1234
      }
    }
  ],
  "next_batch": "page2_token",
  "prev_batch": "page1_token"
}

404 response

Error
Name Type Description
errcode string Required: An error code.
error string A human-readable error message.
{
  "errcode": "M_NOT_FOUND",
  "error": "Event not found."
}

GET /_matrix/client/v1/rooms/{roomId}/relations/{eventId}/{relType}


Retrieve all of the child events for a given parent event which relate to the parent using the given relType.

Note that when paginating the from token should be “after” the to token in terms of topological ordering, because it is only possible to paginate “backwards” through events, starting at from.

For example, passing a from token from page 2 of the results, and a to token from page 1, would return the empty set. The caller can use a from token from page 1 and a to token from page 2 to paginate over the same range, however.

Rate-limited: No
Requires authentication: Yes

Request

Request parameters

path parameters
Name Type Description
eventId string Required: The ID of the parent event whose child events are to be returned.
relType string Required: The relationship type to search for.
roomId string Required: The ID of the room containing the parent event.
query parameters
Name Type Description
from string

The pagination token to start returning results from. If not supplied, results start at the most recent topological event known to the server.

Can be a next_batch token from a previous call, or a returned start token from /messages, or a next_batch token from /sync.

limit integer

The maximum number of results to return in a single chunk. The server can and should apply a maximum value to this parameter to avoid large responses.

Similarly, the server should apply a default value when not supplied.

to string

The pagination token to stop returning results at. If not supplied, results continue up to limit or until there are no more events.

Like from, this can be a previous token from a prior call to this endpoint or from /messages or /sync.


Responses

Status Description
200 The paginated child events which point to the parent. If no events are pointing to the parent or the pagination yields no results, an empty chunk is returned.
404 The parent event was not found or the user does not have permission to read this event (it might be contained in history that is not accessible to the user).

200 response

Name Type Description
chunk ChildEventsChunk Required: The child events of the requested event, ordered topologically most-recent first. The events returned will match the relType supplied in the URL.
next_batch string An opaque string representing a pagination token. The absence of this token means there are no more results to fetch and the client should stop paginating.
prev_batch string An opaque string representing a pagination token. The absence of this token means this is the start of the result set, i.e. this is the first batch/page.
ClientEvent
Name Type Description
content object Required: The body of this event, as created by the client which sent it.
event_id string Required: The globally unique identifier for this event.
origin_server_ts integer Required: Timestamp (in milliseconds since the unix epoch) on originating homeserver when this event was sent.
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.
state_key string

Present if, and only if, this event is a state event. The key making this piece of state unique in the room. Note that it is often an empty string.

State keys starting with an @ are reserved for referencing user IDs, such as room members. With the exception of a few events, state events set with a given user’s ID as the state key MUST only be set by that user.

type string Required: The type of the event.
unsigned UnsignedData Contains optional extra information about the event.
UnsignedData
Name 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.
prev_content EventContent The previous content for this event. This field is generated by the local homeserver, and is only returned if the event is a state event, and the client has permission to see the previous content.

Changed in v1.2: Previously, this field was specified at the top level of returned events rather than in unsigned (with the exception of the GET .../notifications endpoint), though in practice no known server implementations honoured this.
redacted_because ClientEvent The event that redacted this event, if any.
transaction_id string The client-supplied transaction ID, for example, provided via PUT /_matrix/client/v3/rooms/{roomId}/send/{eventType}/{txnId}, if the client being given the event is the same one which sent it.
{
  "chunk": [
    {
      "content": {
        "m.relates_to": {
          "event_id": "$asfDuShaf7Gafaw",
          "rel_type": "org.example.my_relation"
        }
      },
      "event_id": "$143273582443PhrSn:example.org",
      "origin_server_ts": 1432735824653,
      "room_id": "!636q39766251:matrix.org",
      "sender": "@example:example.org",
      "type": "m.room.message",
      "unsigned": {
        "age": 1234
      }
    }
  ],
  "next_batch": "page2_token",
  "prev_batch": "page1_token"
}

404 response

Error
Name Type Description
errcode string Required: An error code.
error string A human-readable error message.
{
  "errcode": "M_NOT_FOUND",
  "error": "Event not found."
}

GET /_matrix/client/v1/rooms/{roomId}/relations/{eventId}/{relType}/{eventType}


Retrieve all of the child events for a given parent event which relate to the parent using the given relType and have the given eventType.

Note that when paginating the from token should be “after” the to token in terms of topological ordering, because it is only possible to paginate “backwards” through events, starting at from.

For example, passing a from token from page 2 of the results, and a to token from page 1, would return the empty set. The caller can use a from token from page 1 and a to token from page 2 to paginate over the same range, however.

Rate-limited: No
Requires authentication: Yes

Request

Request parameters

path parameters
Name Type Description
eventId string Required: The ID of the parent event whose child events are to be returned.
eventType string Required:

The event type of child events to search for.

Note that in encrypted rooms this will typically always be m.room.encrypted regardless of the event type contained within the encrypted payload.

relType string Required: The relationship type to search for.
roomId string Required: The ID of the room containing the parent event.
query parameters
Name Type Description
from string

The pagination token to start returning results from. If not supplied, results start at the most recent topological event known to the server.

Can be a next_batch token from a previous call, or a returned start token from /messages, or a next_batch token from /sync.

limit integer

The maximum number of results to return in a single chunk. The server can and should apply a maximum value to this parameter to avoid large responses.

Similarly, the server should apply a default value when not supplied.

to string

The pagination token to stop returning results at. If not supplied, results continue up to limit or until there are no more events.

Like from, this can be a previous token from a prior call to this endpoint or from /messages or /sync.


Responses

Status Description
200 The paginated child events which point to the parent. If no events are pointing to the parent or the pagination yields no results, an empty chunk is returned.
404 The parent event was not found or the user does not have permission to read this event (it might be contained in history that is not accessible to the user).

200 response

Name Type Description
chunk ChildEventsChunk Required: The child events of the requested event, ordered topologically most-recent first. The events returned will match the relType and eventType supplied in the URL.
next_batch string An opaque string representing a pagination token. The absence of this token means there are no more results to fetch and the client should stop paginating.
prev_batch string An opaque string representing a pagination token. The absence of this token means this is the start of the result set, i.e. this is the first batch/page.
ClientEvent
Name Type Description
content object Required: The body of this event, as created by the client which sent it.
event_id string Required: The globally unique identifier for this event.
origin_server_ts integer Required: Timestamp (in milliseconds since the unix epoch) on originating homeserver when this event was sent.
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.
state_key string

Present if, and only if, this event is a state event. The key making this piece of state unique in the room. Note that it is often an empty string.

State keys starting with an @ are reserved for referencing user IDs, such as room members. With the exception of a few events, state events set with a given user’s ID as the state key MUST only be set by that user.

type string Required: The type of the event.
unsigned UnsignedData Contains optional extra information about the event.
UnsignedData
Name 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.
prev_content EventContent The previous content for this event. This field is generated by the local homeserver, and is only returned if the event is a state event, and the client has permission to see the previous content.

Changed in v1.2: Previously, this field was specified at the top level of returned events rather than in unsigned (with the exception of the GET .../notifications endpoint), though in practice no known server implementations honoured this.
redacted_because ClientEvent The event that redacted this event, if any.
transaction_id string The client-supplied transaction ID, for example, provided via PUT /_matrix/client/v3/rooms/{roomId}/send/{eventType}/{txnId}, if the client being given the event is the same one which sent it.
{
  "chunk": [
    {
      "content": {
        "m.relates_to": {
          "event_id": "$asfDuShaf7Gafaw",
          "rel_type": "org.example.my_relation"
        }
      },
      "event_id": "$143273582443PhrSn:example.org",
      "origin_server_ts": 1432735824653,
      "room_id": "!636q39766251:matrix.org",
      "sender": "@example:example.org",
      "type": "m.room.message",
      "unsigned": {
        "age": 1234
      }
    }
  ],
  "next_batch": "page2_token",
  "prev_batch": "page1_token"
}

404 response

Error
Name Type Description
errcode string Required: An error code.
error string A human-readable error message.
{
  "errcode": "M_NOT_FOUND",
  "error": "Event not found."
}

Rooms

Types

[Added in v1.2]

Optionally, rooms can have types to denote their intended function. A room without a type does not necessarily mean it has a specific default function, though commonly these rooms will be for conversational purposes.

Room types are best applied when a client might need to differentiate between two different rooms, such as conversation-holding and data-holding. If a room has a type, it is specified in the type key of an m.room.create event. To specify a room’s type, provide it as part of creation_content on the create room request.

In this specification the following room types are specified:

Unspecified room types are permitted through the use of Namespaced Identifiers.

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.

POST /_matrix/client/v3/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. The m.room.create event itself. Must be the first event in the room.

  2. An m.room.member event for the creator to join the room. This is needed so the remaining events can be sent.

  3. A default m.room.power_levels event, giving the room creator (and not other members) permission to send state events. Overridden by the power_level_content_override parameter.

  4. An m.room.canonical_alias event if room_alias_name is given.

  5. Events set by the preset. Currently these are the m.room.join_rules, m.room.history_visibility, and m.room.guest_access state events.

  6. Events listed in initial_state, in the order that they are listed.

  7. Events implied by name and topic (m.room.name and m.room.topic state events).

  8. Invite events implied by invite and invite_3pid (m.room.member with membership: invite and m.room.third_party_invite).

The available presets do the following with respect to room state:

Preset join_rules history_visibility guest_access Other
private_chat invite shared can_join
trusted_private_chat invite shared can_join All invitees are given the same power level as the room creator.
public_chat public shared forbidden

The server will create a m.room.create event in the room with the requesting user as the creator, alongside other keys provided in the creation_content.

Rate-limited: No
Requires authentication: Yes

Request

Request body

Name Type Description
creation_content CreationContent Extra keys, such as m.federate, to be added to the content of the m.room.create event. The server will overwrite the following keys: creator, room_version. Future versions of the specification may allow the server to overwrite 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 preset, but gets overridden by name and topic keys.

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.
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.
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.
power_level_content_override Power Level Event Content The power level content to override in the default power level event. This object is applied on top of the generated m.room.power_levels event content prior to it being sent to the room. Defaults to overriding nothing.
preset enum

Convenience parameter for setting various default state events based on a preset.

If unspecified, the server should use the visibility to determine which preset to use. A visbility of public equates to a preset of public_chat and private visibility equates to a preset of private_chat.

One of: [private_chat public_chat trusted_private_chat].

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.

The complete room alias will become the canonical alias for the room and an m.room.canonical_alias event will be sent into the room.

room_version string The room version to set for the room. If not provided, the homeserver is to use its configured default. If provided, the homeserver will return a 400 error with the errcode M_UNSUPPORTED_ROOM_VERSION if it does not support the room version.
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.
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].

StateEvent
Name Type Description
content object Required: The content of the event.
state_key string The state_key of the state event. Defaults to an empty string.
type string Required: The type of event to send.
Invite3pid
Name Type Description
address string Required: The invitee’s third party identifier.
id_access_token string Required: An access token previously registered with the identity server. Servers can treat this as optional to distinguish between r0.5-compatible clients and this specification version.
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.

Request body example

{
  "creation_content": {
    "m.federate": false
  },
  "initial_state": [
    {}
  ],
  "invite": [
    null
  ],
  "invite_3pid": [
    {}
  ],
  "name": "The Grand Duke Pub",
  "preset": "public_chat",
  "room_alias_name": "thepub",
  "room_version": "1",
  "topic": "All about happy hour"
}

Responses

Status Description
200 Information about the newly created room.
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).

  • The homeserver doesn’t support the requested room version, or one or more users being invited to the new room are residents of a homeserver which does not support the requested room version. The errcode will be M_UNSUPPORTED_ROOM_VERSION in these cases.

200 response

Name Type Description
room_id string Required: The created room’s ID.
{
  "room_id": "!sefiuhWgwghwWgh:example.com"
}

400 response

Error
Name Type Description
errcode string Required: An error code.
error string A human-readable error message.
{
  "errcode": "M_UNKNOWN",
  "error": "An unknown error occurred"
}

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 do not store a list of all aliases present on a room, though members of the room with relevant permissions may publish preferred aliases through the m.room.canonical_alias state event. The aliases in the state event should point to the room ID they are published within, however room aliases can and do drift to other room IDs over time. Clients SHOULD NOT treat the aliases 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.

GET /_matrix/client/v3/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.

Rate-limited: No
Requires authentication: No

Request

Request parameters

path parameters
Name Type Description
roomAlias string Required: The room alias.

Responses

Status Description
200 The room ID and other information for this alias.
404 There is no mapped room ID for this room alias.

200 response

Name 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.
{
  "room_id": "!abnjk1jdasj98:capuchins.com",
  "servers": [
    "capuchins.com",
    "matrix.org",
    "another.com"
  ]
}

404 response

Error
Name Type Description
errcode string Required: An error code.
error string A human-readable error message.
{
  "errcode": "M_NOT_FOUND",
  "error": "Room alias #monkeys:matrix.org not found."
}

PUT /_matrix/client/v3/directory/room/{roomAlias}


Rate-limited: No
Requires authentication: Yes

Request

Request parameters

path parameters
Name Type Description
roomAlias string Required: The room alias to set.

Request body

Name Type Description
room_id string Required: The room ID to set.

Request body example

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

Responses

Status Description
200 The mapping was created.
409 A room alias with that name already exists.

200 response

{}

409 response

Error
Name Type Description
errcode string Required: An error code.
error string A human-readable error message.
{
  "errcode": "M_UNKNOWN",
  "error": "Room alias #monkeys:matrix.org already exists."
}

DELETE /_matrix/client/v3/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.

Note: Servers may choose to update the alt_aliases for the m.room.canonical_alias state event in the room when an alias is removed. Servers which choose to update the canonical alias event are recommended to, in addition to their other relevant permission checks, delete the alias and return a successful response even if the user does not have permission to update the m.room.canonical_alias event.

Rate-limited: No
Requires authentication: Yes

Request

Request parameters

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

Responses

Status Description
200 The mapping was deleted.
404 There is no mapped room ID for this room alias.

200 response

{}

404 response

Error
Name Type Description
errcode string Required: An error code.
error string A human-readable error message.
{
  "errcode": "M_NOT_FOUND",
  "error": "Room alias #monkeys:example.org not found."
}

GET /_matrix/client/v3/rooms/{roomId}/aliases


Get a list of aliases maintained by the local server for the given room.

This endpoint can be called by users who are in the room (external users receive an M_FORBIDDEN error response). If the room’s m.room.history_visibility maps to world_readable, any user can call this endpoint.

Servers may choose to implement additional access control checks here, such as allowing server administrators to view aliases regardless of membership.

Note: Clients are recommended not to display this list of aliases prominently as they are not curated, unlike those listed in the m.room.canonical_alias state event.

Rate-limited: Yes
Requires authentication: Yes

Request

Request parameters

path parameters
Name Type Description
roomId string Required: The room ID to find local aliases of.

Responses

Status Description
200 The list of local aliases for the room.
403 The user is not permitted to retrieve the list of local aliases for the room.
429 This request was rate-limited.

200 response

Name Type Description
aliases [string] Required: The server’s local aliases on the room. Can be empty.
{
  "aliases": [
    "#somewhere:example.com",
    "#another:example.com",
    "#hat_trick:example.com"
  ]
}

403 response

Error
Name Type Description
errcode string Required: An error code.
error string A human-readable error message.
{
  "errcode": "M_FORBIDDEN",
  "error": "You are not a member of the room."
}

429 response

RateLimitError
Name Type Description
errcode string Required: The M_LIMIT_EXCEEDED error code
error string A human-readable error message.
retry_after_ms integer The amount of time in milliseconds the client should wait before trying the request again.
{
  "errcode": "M_LIMIT_EXCEEDED",
  "error": "Too many requests",
  "retry_after_ms": 2000
}

Permissions

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

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)
  • Knocking (the user has requested to participate in the room, but has not yet been allowed to)
  • 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 are a few notable exceptions which allow non-joined members of the room to send events in the room:

  • Users wishing to reject an invite would send m.room.member events with content.membership of leave. They must have been invited first.

  • If the room allows, users can send m.room.member events with content.membership of knock to knock on the room. This is a request for an invite by the user.

  • To retract a previous knock, a user would send a leave event similar to rejecting an invite.

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.

knock This room can only be joined if you were invited, and allows anyone to request an invite to the room. Note that this join rule is only available in room versions which support knocking.

[Added in v1.2]

restricted This room can be joined if you were invited or if you are a member of another room listed in the join rules. If the server cannot verify membership for any of the listed rooms then you can only join with an invite. Note that this rule is only expected to work in room versions which support it.

[Added in v1.3]

knock_restricted This room can be joined as though it was restricted or knock. If you interact with the room using knocking, the knock rule takes effect whereas trying to join the room without an invite applies the restricted join rule. Note that this rule is only expected to work in room versions which support it.

The allowable state transitions of membership are:

membership-flow-diagram

GET /_matrix/client/v3/joined_rooms


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

Rate-limited: No
Requires authentication: Yes

Request

No request parameters or request body.


Responses

Status Description
200 A list of the rooms the user is in.

200 response

Name Type Description
joined_rooms [string] Required: The ID of each room in which the user has joined membership.
{
  "joined_rooms": [
    "!foo:example.com"
  ]
}

Joining rooms

POST /_matrix/client/v3/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 authentication: Yes

Request

Request parameters

path parameters
Name Type Description
roomId string Required: The room identifier (not alias) to which to invite the user.

Request body

Name Type Description
reason string Optional reason to be included as the reason on the subsequent membership event.

Added in v1.1

user_id string Required: The fully qualified user ID of the invitee.

Request body example

{
  "reason": "Welcome to the team!",
  "user_id": "@cheeky_monkey:matrix.org"
}

Responses

Status Description
200 The user has been invited to join the room, or was already invited to the room.
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).

  • One or more users being invited to the room are residents of a homeserver which does not support the requested room version. The errcode will be M_UNSUPPORTED_ROOM_VERSION in these cases.

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.
429 This request was rate-limited.

200 response

{}

400 response

Error
Name Type Description
errcode string Required: An error code.
error string A human-readable error message.
{
  "errcode": "M_UNKNOWN",
  "error": "An unknown error occurred"
}

403 response

Error
Name Type Description
errcode string Required: An error code.
error string A human-readable error message.
{
  "errcode": "M_FORBIDDEN",
  "error": "@cheeky_monkey:matrix.org is banned from the room"
}

429 response

RateLimitError
Name Type Description
errcode string Required: The M_LIMIT_EXCEEDED error code
error string A human-readable error message.
retry_after_ms integer The amount of time in milliseconds the client should wait before trying the request again.
{
  "errcode": "M_LIMIT_EXCEEDED",
  "error": "Too many requests",
  "retry_after_ms": 2000
}

POST /_matrix/client/v3/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.

Rate-limited: Yes
Requires authentication: Yes

Request

Request parameters

path parameters
Name Type Description
roomIdOrAlias string Required: The room identifier or alias to join.
query parameters
Name Type Description
server_name [string] The servers to attempt to join the room through. One of the servers must be participating in the room.

Request body

Name Type Description
reason string Optional reason to be included as the reason on the subsequent membership event.

Added in v1.1

third_party_signed Third Party Signed 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.
Third Party Signed
Name Type Description
mxid string Required: The Matrix ID of the invitee.
sender string Required: The Matrix ID of the user who issued the invite.
signatures Signatures Required: A signatures object containing a signature of the entire signed object.
token string Required: The state key of the m.third_party_invite event.

Request body example

{
  "reason": "Looking for support",
  "third_party_signed": {
    "mxid": "@bob:example.org",
    "sender": "@alice:example.org",
    "signatures": {
      "example.org": {
        "ed25519:0": "some9signature"
      }
    },
    "token": "random8nonce"
  }
}

Responses

Status Description
200

The room has been joined.

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

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.
  • The room is restricted and the user failed to satisfy any of the conditions.
429 This request was rate-limited.

200 response

Name Type Description
room_id string Required: The joined room ID.
{
  "room_id": "!d41d8cd:matrix.org"
}

403 response

Error
Name Type Description
errcode string Required: An error code.
error string A human-readable error message.
{
  "errcode": "M_FORBIDDEN",
  "error": "You are not invited to this room."
}

429 response

RateLimitError
Name Type Description
errcode string Required: The M_LIMIT_EXCEEDED error code
error string A human-readable error message.
retry_after_ms integer The amount of time in milliseconds the client should wait before trying the request again.
{
  "errcode": "M_LIMIT_EXCEEDED",
  "error": "Too many requests",
  "retry_after_ms": 2000
}

POST /_matrix/client/v3/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.

Rate-limited: Yes
Requires authentication: Yes

Request

Request parameters

path parameters
Name Type Description
roomId string Required: The room identifier (not alias) to join.

Request body

Name Type Description
reason string Optional reason to be included as the reason on the subsequent membership event.

Added in v1.1

third_party_signed Third Party Signed If 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.
Third Party Signed
Name Type Description
mxid string Required: The Matrix ID of the invitee.
sender string Required: The Matrix ID of the user who issued the invite.
signatures Signatures Required: A signatures object containing a signature of the entire signed object.
token string Required: The state key of the m.third_party_invite event.

Request body example

{
  "reason": "Looking for support",
  "third_party_signed": {
    "mxid": "@bob:example.org",
    "sender": "@alice:example.org",
    "signatures": {
      "example.org": {
        "ed25519:0": "some9signature"
      }
    },
    "token": "random8nonce"
  }
}

Responses

Status Description
200

The room has been joined.

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

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.
  • The room is restricted and the user failed to satisfy any of the conditions.
429 This request was rate-limited.

200 response

Name Type Description
room_id string Required: The joined room ID.
{
  "room_id": "!d41d8cd:matrix.org"
}

403 response

Error
Name Type Description
errcode string Required: An error code.
error string A human-readable error message.
{
  "errcode": "M_FORBIDDEN",
  "error": "You are not invited to this room."
}

429 response

RateLimitError
Name Type Description
errcode string Required: The M_LIMIT_EXCEEDED error code
error string A human-readable error message.
retry_after_ms integer The amount of time in milliseconds the client should wait before trying the request again.
{
  "errcode": "M_LIMIT_EXCEEDED",
  "error": "Too many requests",
  "retry_after_ms": 2000
}
Knocking on rooms

[Added in v1.1]

[Changed in v1.3]

If the join rules allow, external users to the room can /knock on it to request permission to join. Users with appropriate permissions within the room can then approve (/invite) or deny (/kick, /ban, or otherwise set membership to leave) the knock. Knocks can be retracted by calling /leave or otherwise setting membership to leave.

Users who are currently in the room, already invited, or banned cannot knock on the room.

To accept another user’s knock, the user must have permission to invite users to the room. To reject another user’s knock, the user must have permission to either kick or ban users (whichever is being performed). Note that setting another user’s membership to leave is kicking them.

The knocking homeserver should assume that an invite to the room means that the knock was accepted, even if the invite is not explicitly related to the knock.

Homeservers are permitted to automatically accept invites as a result of knocks as they should be aware of the user’s intent to join the room. If the homeserver is not auto-accepting invites (or there was an unrecoverable problem with accepting it), the invite is expected to be passed down normally to the client to handle. Clients can expect to see the join event if the server chose to auto-accept.

POST /_matrix/client/v3/knock/{roomIdOrAlias}


Added in v1.1

Note that this API takes either a room ID or alias, unlike other membership APIs.

This API “knocks” on the room to ask for permission to join, if the user is allowed to knock on the room. Acceptance of the knock happens out of band from this API, meaning that the client will have to watch for updates regarding the acceptance/rejection of the knock.

If the room history settings allow, the user will still be able to see history of the room while being in the “knock” state. The user will have to accept the invitation to join the room (acceptance of knock) to see messages reliably. See the /join endpoints for more information about history visibility to the user.

The knock will appear as an entry in the response of the /sync API.

Rate-limited: Yes
Requires authentication: Yes

Request

Request parameters

path parameters
Name Type Description
roomIdOrAlias string Required: The room identifier or alias to knock upon.
query parameters
Name Type Description
server_name [string] The servers to attempt to knock on the room through. One of the servers must be participating in the room.

Request body

Name Type Description
reason string Optional reason to be included as the reason on the subsequent membership event.

Request body example

{
  "reason": "Looking for support"
}

Responses

Status Description
200

The room has been knocked upon.

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

403

You do not have permission to knock on the room. A meaningful errcode and description error text will be returned. Example reasons for rejection are:

  • The room is not set up for knocking.
  • The user has been banned from the room.
404 The room could not be found or resolved to a room ID.
429 This request was rate-limited.

200 response

Name Type Description
room_id string Required: The knocked room ID.
{
  "room_id": "!d41d8cd:matrix.org"
}

403 response

Error
Name Type Description
errcode string Required: An error code.
error string A human-readable error message.
{
  "errcode": "M_FORBIDDEN",
  "error": "You are not allowed to knock on this room."
}

404 response

Error
Name Type Description
errcode string Required: An error code.
error string A human-readable error message.
{
  "errcode": "M_NOT_FOUND",
  "error": "That room does not appear to exist."
}

429 response

RateLimitError
Name Type Description
errcode string Required: The M_LIMIT_EXCEEDED error code
error string A human-readable error message.
retry_after_ms integer The amount of time in milliseconds the client should wait before trying the request again.
{
  "errcode": "M_LIMIT_EXCEEDED",
  "error": "Too many requests",
  "retry_after_ms": 2000
}
Restricted rooms

[Added in v1.2]

[Changed in v1.3]

Restricted rooms are rooms with a join_rule of restricted. These rooms are accompanied by “allow conditions” as described in the m.room.join_rules state event.

If the user has an invite to the room then the restrictions will not affect them. They should be able to join by simply accepting the invite.

When joining without an invite, the server MUST verify that the requesting user meets at least one of the conditions. If no conditions can be verified or no conditions are satisfied, the user will not be able to join. When the join is happening over federation, the remote server will check the conditions before accepting the join. See the Server-Server Spec for more information.

If the room is restricted but no valid conditions are presented then the room is effectively invite only.

The user does not need to maintain the conditions in order to stay a member of the room: the conditions are only checked/evaluated during the join process.

Conditions

Currently there is only one condition available: m.room_membership. This condition requires the user trying to join the room to be a joined member of another room (specifically, the room_id accompanying the condition). For example, if !restricted:example.org wanted to allow joined members of !other:example.org to join, !restricted:example.org would have the following content for m.room.join_rules:

{
  "join_rule": "restricted",
  "allow": [
    {
      "room_id": "!other:example.org",
      "type": "m.room_membership"
    }
  ]
}

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, and can retract a knock. 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, is re-invited, or knocks.

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”.

POST /_matrix/client/v3/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 must leave the room before calling this API.

Rate-limited: Yes
Requires authentication: Yes

Request

Request parameters

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

Responses

Status Description
200 The room has been forgotten.
400 The user has not left the room
429 This request was rate-limited.

200 response

{}

400 response

Error
Name Type Description
errcode string Required: An error code.
error string A human-readable error message.
{
  "errcode": "M_UNKNOWN",
  "error": "User @example:matrix.org is in room !au1ba7o:matrix.org"
}

429 response

RateLimitError
Name Type Description
errcode string Required: The M_LIMIT_EXCEEDED error code
error string A human-readable error message.
retry_after_ms integer The amount of time in milliseconds the client should wait before trying the request again.
{
  "errcode": "M_LIMIT_EXCEEDED",
  "error": "Too many requests",
  "retry_after_ms": 2000
}

POST /_matrix/client/v3/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 authentication: Yes

Request

Request parameters

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

Request body

Name Type Description
reason string Optional reason to be included as the reason on the subsequent membership event.

Added in v1.1

Request body example

{
  "reason": "Saying farewell - thanks for the support!"
}

Responses

Status Description
200 The room has been left.
429 This request was rate-limited.

200 response

{}

429 response

RateLimitError
Name Type Description
errcode string Required: The M_LIMIT_EXCEEDED error code
error string A human-readable error message.
retry_after_ms integer The amount of time in milliseconds the client should wait before trying the request again.
{
  "errcode": "M_LIMIT_EXCEEDED",
  "error": "Too many requests",
  "retry_after_ms": 2000
}

POST /_matrix/client/v3/rooms/{roomId}/kick


Kick a user from the room.

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

Kicking a user adjusts the target member’s membership state to be leave with an optional reason. 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>.

Rate-limited: No
Requires authentication: Yes

Request

Request parameters

path parameters
Name Type Description
roomId string Required: The room identifier (not alias) from which the user should be kicked.

Request body

Name Type Description
reason string The reason the user has been kicked. This will be supplied as the reason on the target’s updated m.room.member event.
user_id string Required: The fully qualified user ID of the user being kicked.

Request body example

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

Responses

Status Description
200 The user has been kicked from the room.
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.

200 response

{}

403 response

Error
Name Type Description
errcode string Required: An error code.
error string A human-readable error message.
{
  "errcode": "M_FORBIDDEN",
  "error": "You do not have a high enough power level to kick from this room."
}
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.

POST /_matrix/client/v3/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.

Rate-limited: No
Requires authentication: Yes

Request

Request parameters

path parameters
Name Type Description
roomId string Required: The room identifier (not alias) from which the user should be banned.

Request body

Name Type Description
reason string The reason the user has been banned. This will be supplied as the reason on the target’s updated m.room.member event.

Added in v1.1

user_id string Required: The fully qualified user ID of the user being banned.

Request body example

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

Responses

Status Description
200 The user has been kicked and banned from the room.
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.

200 response

{}

403 response

Error
Name Type Description
errcode string Required: An error code.
error string A human-readable error message.
{
  "errcode": "M_FORBIDDEN",
  "error": "You do not have a high enough power level to ban from this room."
}

POST /_matrix/client/v3/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.

Rate-limited: No
Requires authentication: Yes

Request

Request parameters

path parameters
Name Type Description
roomId string Required: The room identifier (not alias) from which the user should be unbanned.

Request body

Name Type Description
reason string Optional reason to be included as the reason on the subsequent membership event.

Added in v1.1

user_id string Required: The fully qualified user ID of the user being unbanned.

Request body example

{
  "reason": "They've been banned long enough",
  "user_id": "@cheeky_monkey:matrix.org"
}

Responses

Status Description
200 The user has been unbanned from the room.
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.

200 response

{}

403 response

Error
Name Type Description
errcode string Required: An error code.
error string A human-readable error message.
{
  "errcode": "M_FORBIDDEN",
  "error": "You do not have a high enough power level to unban from this room."
}

Listing rooms

GET /_matrix/client/v3/directory/list/room/{roomId}


Gets the visibility of a given room on the server’s public room directory.

Rate-limited: No
Requires authentication: No

Request

Request parameters

path parameters
Name Type Description
roomId string Required: The room ID.

Responses

Status Description
200 The visibility of the room in the directory
404 The room is not known to the server

200 response

Name Type Description
visibility enum The visibility of the room in the directory.

One of: [private public].

{
  "visibility": "public"
}

404 response

Error
Name Type Description
errcode string Required: An error code.
error string A human-readable error message.
{
  "errcode": "M_NOT_FOUND",
  "error": "Room not found"
}

PUT /_matrix/client/v3/directory/list/room/{roomId}


Sets the visibility of a given room in the server’s public room directory.

Servers may choose to implement additional access control checks here, for instance that room visibility can only be changed by the room creator or a server administrator.

Rate-limited: No
Requires authentication: Yes

Request

Request parameters

path parameters
Name Type Description
roomId string Required: The room ID.

Request body

Name Type Description
visibility enum The new visibility setting for the room. Defaults to ‘public’.

One of: [private public].

Request body example

{
  "visibility": "public"
}

Responses

Status Description
200 The visibility was updated, or no change was needed.
404 The room is not known to the server

200 response

{}

404 response

Error
Name Type Description
errcode string Required: An error code.
error string A human-readable error message.
{
  "errcode": "M_NOT_FOUND",
  "error": "Room not found"
}

GET /_matrix/client/v3/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.

Rate-limited: No
Requires authentication: No

Request

Request parameters

query parameters
Name Type Description
limit integer Limit the number of results returned.
server string The server to fetch the public room lists from. Defaults to the local server.
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.

Responses

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

200 response

Name Type Description
chunk [PublicRoomsChunk] Required: A paginated chunk of public rooms.
next_batch string A pagination token for the response. The absence of this token means there are no more results to fetch and the client should stop paginating.
prev_batch string A pagination token that allows fetching previous results. The absence of this token means there are no results before this batch, i.e. this is the first batch.
total_room_count_estimate integer An estimate on the total number of public rooms, if the server has an estimate.
PublicRoomsChunk
Name Type Description
avatar_url string The URL for the room’s avatar, if one is set.
canonical_alias string The canonical alias of the room, if any.
guest_can_join boolean Required: Whether guest users may join the room and participate in it. If they can, they will be subject to ordinary power level rules like any other user.
join_rule string The room’s join rule. When not present, the room is assumed to be public. Note that rooms with invite join rules are not expected here, but rooms with knock rules are given their near-public nature.
name string The name of the room, if any.
num_joined_members integer Required: The number of members joined to the room.
room_id string Required: The ID of the room.
room_type string The type of room (from m.room.create), if any.

Added in v1.4

topic string The topic of the room, if any.
world_readable boolean Required: Whether the room may be viewed by guest users without joining.
{
  "chunk": [
    {
      "avatar_url": "mxc://bleecker.street/CHEDDARandBRIE",
      "guest_can_join": false,
      "join_rule": "public",
      "name": "CHEESE",
      "num_joined_members": 37,
      "room_id": "!ol19s:bleecker.street",
      "room_type": "m.space",
      "topic": "Tasty tasty cheese",
      "world_readable": true
    }
  ],
  "next_batch": "p190q",
  "prev_batch": "p1902",
  "total_room_count_estimate": 115
}

POST /_matrix/client/v3/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.

Rate-limited: No
Requires authentication: Yes

Request

Request parameters

query parameters
Name Type Description
server string The server to fetch the public room lists from. Defaults to the local server.

Request body

Name Type Description
filter Filter Filter to apply to the results.
include_all_networks boolean Whether or not to include all known networks/protocols from application services on the homeserver. Defaults to false.
limit integer Limit the number of results returned.
since string A pagination token from a previous request, allowing 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.
third_party_instance_id string The specific third party network/protocol to request from the homeserver. Can only be used if include_all_networks is false.
Filter
Name Type Description
generic_search_term string An optional string to search for in the room metadata, e.g. name, topic, canonical alias, etc.
room_types [string] An optional list of room types to search for. To include rooms without a room type, specify null within this list. When not specified, all applicable rooms (regardless of type) are returned.

Added in v1.4

Request body example

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

Responses

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

200 response

Name Type Description
chunk [PublicRoomsChunk] Required: A paginated chunk of public rooms.
next_batch string A pagination token for the response. The absence of this token means there are no more results to fetch and the client should stop paginating.
prev_batch string A pagination token that allows fetching previous results. The absence of this token means there are no results before this batch, i.e. this is the first batch.
total_room_count_estimate integer An estimate on the total number of public rooms, if the server has an estimate.
PublicRoomsChunk
Name Type Description
avatar_url string The URL for the room’s avatar, if one is set.
canonical_alias string The canonical alias of the room, if any.
guest_can_join boolean Required: Whether guest users may join the room and participate in it. If they can, they will be subject to ordinary power level rules like any other user.
join_rule string The room’s join rule. When not present, the room is assumed to be public. Note that rooms with invite join rules are not expected here, but rooms with knock rules are given their near-public nature.
name string The name of the room, if any.
num_joined_members integer Required: The number of members joined to the room.
room_id string Required: The ID of the room.
room_type string The type of room (from m.room.create), if any.

Added in v1.4

topic string The topic of the room, if any.
world_readable boolean Required: Whether the room may be viewed by guest users without joining.
{
  "chunk": [
    {
      "avatar_url": "mxc://bleecker.street/CHEDDARandBRIE",
      "guest_can_join": false,
      "join_rule": "public",
      "name": "CHEESE",
      "num_joined_members": 37,
      "room_id": "!ol19s:bleecker.street",
      "room_type": "m.space",
      "topic": "Tasty tasty cheese",
      "world_readable": true
    }
  ],
  "next_batch": "p190q",
  "prev_batch": "p1902",
  "total_room_count_estimate": 115
}

User Data

User Directory

POST /_matrix/client/v3/user_directory/search


Performs a search for users. The homeserver may determine which subset of users are searched, however the homeserver MUST at a minimum consider the users the requesting user shares a room with and those who reside in public rooms (known to the homeserver). The search MUST consider local users to the homeserver, and SHOULD query remote users as part of the search.

The search is performed case-insensitively on user IDs and display names preferably using a collation determined based upon the Accept-Language header provided in the request, if present.

Rate-limited: Yes
Requires authentication: Yes

Request

Request body

Name Type Description
limit integer The maximum number of results to return. Defaults to 10.
search_term string Required: The term to search for

Request body example

{
  "limit": 10,
  "search_term": "foo"
}

Responses

Status Description
200 The results of the search.
429 This request was rate-limited.

200 response

Name Type Description
limited boolean Required: Indicates if the result list has been truncated by the limit.
results [User] Required: Ordered by rank and then whether or not profile info is available.
User
Name Type Description
avatar_url string The avatar url, as an MXC, if one exists.
display_name string The display name of the user, if one exists.
user_id string Required: The user’s matrix user ID.
{
  "limited": false,
  "results": [
    {
      "avatar_url": "mxc://bar.com/foo",
      "display_name": "Foo",
      "user_id": "@foo:bar.com"
    }
  ]
}

429 response

RateLimitError
Name Type Description
errcode string Required: The M_LIMIT_EXCEEDED error code
error string A human-readable error message.
retry_after_ms integer The amount of time in milliseconds the client should wait before trying the request again.
{
  "errcode": "M_LIMIT_EXCEEDED",
  "error": "Too many requests",
  "retry_after_ms": 2000
}

Profiles

GET /_matrix/client/v3/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.

Rate-limited: No
Requires authentication: No

Request

Request parameters

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

Responses

Status Description
200 The avatar URL for this user.
403 The server is unwilling to disclose whether the user exists and/or has profile information.
404 There is no profile information for this user or this user does not exist.

200 response

Name 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.
{
  "avatar_url": "mxc://matrix.org/SDGdghriugerRg",
  "displayname": "Alice Margatroid"
}

403 response

Error
Name Type Description
errcode string Required: An error code.
error string A human-readable error message.
{
  "errcode": "M_FORBIDDEN",
  "error": "Profile lookup over federation is disabled on this homeserver"
}

404 response

Error
Name Type Description
errcode string Required: An error code.
error string A human-readable error message.
{
  "errcode": "M_NOT_FOUND",
  "error": "Profile not found"
}

GET /_matrix/client/v3/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.

Rate-limited: No
Requires authentication: No

Request

Request parameters

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

Responses

Status Description
200 The avatar URL for this user.
404 There is no avatar URL for this user or this user does not exist.

200 response

Name Type Description
avatar_url string The user’s avatar URL if they have set one, otherwise not present.
{
  "avatar_url": "mxc://matrix.org/SDGdghriugerRg"
}

PUT /_matrix/client/v3/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 authentication: Yes

Request

Request parameters

path parameters
Name Type Description
userId string Required: The user whose avatar URL to set.

Request body

Name Type Description
avatar_url string The new avatar URL for this user.

Request body example

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

Responses

Status Description
200 The avatar URL was set.
429 This request was rate-limited.

200 response

{}

429 response

RateLimitError
Name Type Description
errcode string Required: The M_LIMIT_EXCEEDED error code
error string A human-readable error message.
retry_after_ms integer The amount of time in milliseconds the client should wait before trying the request again.
{
  "errcode": "M_LIMIT_EXCEEDED",
  "error": "Too many requests",
  "retry_after_ms": 2000
}

GET /_matrix/client/v3/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.

Rate-limited: No
Requires authentication: No

Request

Request parameters

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

Responses

Status Description
200 The display name for this user.
404 There is no display name for this user or this user does not exist.

200 response

Name Type Description
displayname string The user’s display name if they have set one, otherwise not present.
{
  "displayname": "Alice Margatroid"
}

PUT /_matrix/client/v3/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 authentication: Yes

Request

Request parameters

path parameters
Name Type Description
userId string Required: The user whose display name to set.

Request body

Name Type Description
displayname string The new display name for this user.

Request body example

{
  "displayname": "Alice Margatroid"
}

Responses

Status Description
200 The display name was set.
429 This request was rate-limited.

200 response

{}

429 response

RateLimitError
Name Type Description
errcode string Required: The M_LIMIT_EXCEEDED error code
error string A human-readable error message.
retry_after_ms integer The amount of time in milliseconds the client should wait before trying the request again.
{
  "errcode": "M_LIMIT_EXCEEDED",
  "error": "Too many requests",
  "retry_after_ms": 2000
}

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:

  • an 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.
  • an 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.

Security

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.

Modules

Modules are parts of the Client-Server API which are not universal to all endpoints. Modules are strictly defined within this specification and should not be mistaken for experimental extensions or optional features. A compliant server implementation MUST support all modules and supporting specification (unless the implementation only targets clients of certain profiles, in which case only the required modules for those feature profiles MUST be implemented). A compliant client implementation MUST support all the required modules and supporting specification for the Feature Profile it targets.

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.

Summary

Module / Profile Web Mobile Desktop CLI Embedded
Instant Messaging Required Required Required Required Optional
Rich replies Optional Optional Optional Optional Optional
Direct Messaging Required Required Required Required Optional
Mentions Required Required Required Optional Optional
Presence Required Required Required Required Optional
Push Notifications Optional Required Optional Optional Optional
Receipts Required Required Required Required Optional
Fully read markers Optional Optional Optional Optional Optional
Typing Notifications Required Required Required Required Optional
VoIP Required Required Required Optional Optional
Ignoring Users Required Required Required Optional Optional
Reporting Content Optional Optional Optional 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
Room Upgrades Required Required Required Required Optional
Server Administration Optional Optional Optional Optional Optional
Event Context Optional Optional Optional Optional Optional
Third Party Networks Optional Optional Optional Optional Optional
Send-to-Device Messaging Optional Optional Optional Optional Optional
Device Management Optional Optional Optional Optional Optional
End-to-End Encryption Optional Optional Optional Optional Optional
Guest Accounts Optional Optional Optional Optional Optional
Room Previews Optional Optional Optional Optional Optional
Client Config Optional Optional Optional Optional Optional
SSO Login Optional Optional Optional Optional Optional
OpenID Optional Optional Optional Optional Optional
Stickers Optional Optional Optional Optional Optional
Server ACLs Optional Optional Optional Optional Optional
Server Notices Optional Optional Optional Optional Optional
Moderation policies Optional Optional Optional Optional Optional
Spaces Optional Optional Optional Optional Optional

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

Clients

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.

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

Desktop (Desktop)

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

Command Line Interface (CLI)

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

Embedded (Embedded)

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

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.

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.

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.

Events

m.room.message


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.

Event type: Message event

Content

Name 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

{
  "content": {
    "body": "Bee Gees - Stayin' Alive",
    "info": {
      "duration": 2140786,
      "mimetype": "audio/mpeg",
      "size": 1563685
    },
    "msgtype": "m.audio",
    "url": "mxc://example.org/ffed755USFFxlgbQYZGtryd"
  },
  "event_id": "$143273582443PhrSn:example.org",
  "origin_server_ts": 1432735824653,
  "room_id": "!jEsUZKDJdhlrceRyVU:example.org",
  "sender": "@example:example.org",
  "type": "m.room.message",
  "unsigned": {
    "age": 1234
  }
}
{
  "content": {
    "body": "thinks this is an example emote",
    "format": "org.matrix.custom.html",
    "formatted_body": "thinks <b>this</b> is an example emote",
    "msgtype": "m.emote"
  },
  "event_id": "$143273582443PhrSn:example.org",
  "origin_server_ts": 1432735824653,
  "room_id": "!jEsUZKDJdhlrceRyVU:example.org",
  "sender": "@example:example.org",
  "type": "m.room.message",
  "unsigned": {
    "age": 1234
  }
}
{
  "content": {
    "body": "something-important.doc",
    "filename": "something-important.doc",
    "info": {
      "mimetype": "application/msword",
      "size": 46144
    },
    "msgtype": "m.file",
    "url": "mxc://example.org/FHyPlCeYUSFFxlgbQYZmoEoe"
  },
  "event_id": "$143273582443PhrSn:example.org",
  "origin_server_ts": 1432735824653,
  "room_id": "!jEsUZKDJdhlrceRyVU:example.org",
  "sender": "@example:example.org",
  "type": "m.room.message",
  "unsigned": {
    "age": 1234
  }
}
{
  "content": {
    "body": "filename.jpg",
    "info": {
      "h": 398,
      "mimetype": "image/jpeg",
      "size": 31037,
      "w": 394
    },
    "msgtype": "m.image",
    "url": "mxc://example.org/JWEIFJgwEIhweiWJE"
  },
  "event_id": "$143273582443PhrSn:example.org",
  "origin_server_ts": 1432735824653,
  "room_id": "!jEsUZKDJdhlrceRyVU:example.org",
  "sender": "@example:example.org",
  "type": "m.room.message",
  "unsigned": {
    "age": 1234
  }
}
{
  "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://example.org/FHyPlCeYUSFFxlgbQYZmoEoe"
    },
    "msgtype": "m.location"
  },
  "event_id": "$143273582443PhrSn:example.org",
  "origin_server_ts": 1432735824653,
  "room_id": "!jEsUZKDJdhlrceRyVU:example.org",
  "sender": "@example:example.org",
  "type": "m.room.message",
  "unsigned": {
    "age": 1234
  }
}
{
  "content": {
    "body": "This is an example notice",
    "format": "org.matrix.custom.html",
    "formatted_body": "This is an <strong>example</strong> notice",
    "msgtype": "m.notice"
  },
  "event_id": "$143273582443PhrSn:example.org",
  "origin_server_ts": 1432735824653,
  "room_id": "!jEsUZKDJdhlrceRyVU:example.org",
  "sender": "@example:example.org",
  "type": "m.room.message",
  "unsigned": {
    "age": 1234
  }
}
{
  "content": {
    "admin_contact": "mailto:[email protected]",
    "body": "Human-readable message to explain the notice",
    "limit_type": "monthly_active_user",
    "msgtype": "m.server_notice",
    "server_notice_type": "m.server_notice.usage_limit_reached"
  },
  "event_id": "$143273582443PhrSn:example.org",
  "origin_server_ts": 1432735824653,
  "room_id": "!jEsUZKDJdhlrceRyVU:example.org",
  "sender": "@example:example.org",
  "type": "m.room.message",
  "unsigned": {
    "age": 1234
  }
}
{
  "content": {
    "body": "This is an example text message",
    "format": "org.matrix.custom.html",
    "formatted_body": "<b>This is an example text message</b>",
    "msgtype": "m.text"
  },
  "event_id": "$143273582443PhrSn:example.org",
  "origin_server_ts": 1432735824653,
  "room_id": "!jEsUZKDJdhlrceRyVU:example.org",
  "sender": "@example:example.org",
  "type": "m.room.message",
  "unsigned": {
    "age": 1234
  }
}
{
  "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://example.org/FHyPlCeYUSFFxlgbQYZmoEoe",
      "w": 480
    },
    "msgtype": "m.video",
    "url": "mxc://example.org/a526eYUSFFxlgbQYZmo442"
  },
  "event_id": "$143273582443PhrSn:example.org",
  "origin_server_ts": 1432735824653,
  "room_id": "!jEsUZKDJdhlrceRyVU:example.org",
  "sender": "@example:example.org",
  "type": "m.room.message",
  "unsigned": {
    "age": 1234
  }
}

m.room.name


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.

Event type: State event
State key A zero-length string.

Content

Name Type Description
name string Required: The name of the room.

Examples

{
  "content": {
    "name": "The room name"
  },
  "event_id": "$143273582443PhrSn:example.org",
  "origin_server_ts": 1432735824653,
  "room_id": "!jEsUZKDJdhlrceRyVU:example.org",
  "sender": "@example:example.org",
  "state_key": "",
  "type": "m.room.name",
  "unsigned": {
    "age": 1234
  }
}

m.room.topic


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.

Event type: State event
State key A zero-length string.

Content

Name Type Description
topic string Required: The topic text.

Examples

{
  "content": {
    "topic": "A room topic"
  },
  "event_id": "$143273582443PhrSn:example.org",
  "origin_server_ts": 1432735824653,
  "room_id": "!jEsUZKDJdhlrceRyVU:example.org",
  "sender": "@example:example.org",
  "state_key": "",
  "type": "m.room.topic",
  "unsigned": {
    "age": 1234
  }
}

m.room.avatar


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

Event type: State event
State key A zero-length string.

Content

Name Type Description
info ImageInfo Metadata about the image referred to in url.
url string The URL to the image. If this property is not present, the room has no avatar. This can be useful to remove a previous room avatar.
ImageInfo
Name Type Description
h integer The intended display height of the image in pixels. This may differ from the intrinsic dimensions of the image file.
mimetype string The mimetype of the image, e.g. image/jpeg.
size integer Size of the image in bytes.
thumbnail_file EncryptedFile Information on the encrypted thumbnail file, as specified in End-to-end encryption. Only present if the thumbnail is encrypted.
thumbnail_info ThumbnailInfo Metadata about the image referred to in thumbnail_url.
thumbnail_url string The URL (typically MXC URI) to a thumbnail of the image. Only present if the thumbnail is unencrypted.
w integer The intended display width of the image in pixels. This may differ from the intrinsic dimensions of the image file.
ThumbnailInfo
Name Type Description
h integer The intended display height of the image in pixels. This may differ from the intrinsic dimensions of the image file.
mimetype string The mimetype of the image, e.g. image/jpeg.
size integer Size of the image in bytes.
w integer The intended display width of the image in pixels. This may differ from the intrinsic dimensions of the image file.

Examples

{
  "content": {
    "info": {
      "h": 398,
      "mimetype": "image/jpeg",
      "size": 31037,
      "w": 394
    },
    "url": "mxc://example.org/JWEIFJgwEIhweiWJE"
  },
  "event_id": "$143273582443PhrSn:example.org",
  "origin_server_ts": 1432735824653,
  "room_id": "!jEsUZKDJdhlrceRyVU:example.org",
  "sender": "@example:example.org",
  "state_key": "",
  "type": "m.room.avatar",
  "unsigned": {
    "age": 1234
  }
}

m.room.pinned_events


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.

Event type: State event
State key A zero-length string.

Content

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

Examples

{
  "content": {
    "pinned": [
      "$someevent:example.org"
    ]
  },
  "event_id": "$143273582443PhrSn:example.org",
  "origin_server_ts": 1432735824653,
  "room_id": "!jEsUZKDJdhlrceRyVU:example.org",
  "sender": "@example:example.org",
  "state_key": "",
  "type": "m.room.pinned_events",
  "unsigned": {
    "age": 1234
  }
}
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.

Some message types support HTML in the event content that clients should prefer to display if available. Currently m.text, m.emote, and m.notice support an additional format parameter of org.matrix.custom.html. When this field is present, a formatted_body with the HTML must be provided. The plain text version of the HTML should be provided in the body.

Clients should limit the HTML they render to avoid Cross-Site Scripting, HTML injection, and similar attacks. The strongly suggested set of HTML tags to permit, denying the use and rendering of anything else, is: font, del, h1, h2, h3, h4, h5, h6, blockquote, p, a, ul, ol, sup, sub, li, b, i, u, strong, em, strike, code, hr, br, div, table, thead, tbody, tr, th, td, caption, pre, span, img, details, summary.

Not all attributes on those tags should be permitted as they may be avenues for other disruption attempts, such as adding onclick handlers or excessively large text. Clients should only permit the attributes listed for the tags below. Where data-mx-bg-color and data-mx-color are listed, clients should translate the value (a 6-character hex color code) to the appropriate CSS/attributes for the tag.

font data-mx-bg-color, data-mx-color, color

span data-mx-bg-color, data-mx-color, data-mx-spoiler (see spoiler messages)

a name, target, href (provided the value is not relative and has a scheme matching one of: https, http, ftp, mailto, magnet)

img width, height, alt, title, src (provided it is a Matrix Content (MXC) URI)

ol start

code class (only classes which start with language- for syntax highlighting)

Additionally, web clients should ensure that all a tags get a rel="noopener" to prevent the target page from referencing the client’s tab/window.

Tags must not be nested more than 100 levels deep. Clients should only support the subset of tags they can render, falling back to other representations of the tags where possible. For example, a client may not be able to render tables correctly and instead could fall back to rendering tab-delimited text.

In addition to not rendering unsafe HTML, clients should not emit unsafe HTML in events. Likewise, clients should not generate HTML that is not needed, such as extra paragraph tags surrounding text due to Rich Text Editors. HTML included in events should otherwise be valid, such as having appropriate closing tags, appropriate attributes (considering the custom ones defined in this specification), and generally valid structure.

A special tag, mx-reply, may appear on rich replies (described below) and should be allowed if, and only if, the tag appears as the very first tag in the formatted_body. The tag cannot be nested and cannot be located after another tag in the tree. Because the tag contains HTML, an mx-reply is expected to have a partner closing tag and should be treated similar to a div. Clients that support rich replies will end up stripping the tag and its contents and therefore may wish to exclude the tag entirely.

m.text


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

Event type: Message event

Content

Name Type Description
body string Required: The body of the message.
format string The format used in the formatted_body. Currently only org.matrix.custom.html is supported.
formatted_body string The formatted version of the body. This is required if format is specified.
msgtype enum Required:

One of: [m.text].

Examples

{
  "content": {
    "body": "This is an example text message",
    "format": "org.matrix.custom.html",
    "formatted_body": "\u003cb\u003eThis is an example text message\u003c/b\u003e",
    "msgtype": "m.text"
  },
  "event_id": "$143273582443PhrSn:example.org",
  "origin_server_ts": 1432735824653,
  "room_id": "!jEsUZKDJdhlrceRyVU:example.org",
  "sender": "@example:example.org",
  "type": "m.room.message",
  "unsigned": {
    "age": 1234
  }
}

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.

Event type: Message event

Content

Name Type Description
body string Required: The emote action to perform.
format string The format used in the formatted_body. Currently only org.matrix.custom.html is supported.
formatted_body string The formatted version of the body. This is required if format is specified.
msgtype enum Required:

One of: [m.emote].

Examples

{
  "content": {
    "body": "thinks this is an example emote",
    "format": "org.matrix.custom.html",
    "formatted_body": "thinks \u003cb\u003ethis\u003c/b\u003e is an example emote",
    "msgtype": "m.emote"
  },
  "event_id": "$143273582443PhrSn:example.org",
  "origin_server_ts": 1432735824653,
  "room_id": "!jEsUZKDJdhlrceRyVU:example.org",
  "sender": "@example:example.org",
  "type": "m.room.message",
  "unsigned": {
    "age": 1234
  }
}

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.

Event type: Message event

Content

Name Type Description
body string Required: The notice text to send.
format string The format used in the formatted_body. Currently only org.matrix.custom.html is supported.
formatted_body string The formatted version of the body. This is required if format is specified.
msgtype enum Required:

One of: [m.notice].

Examples

{
  "content": {
    "body": "This is an example notice",
    "format": "org.matrix.custom.html",
    "formatted_body": "This is an \u003cstrong\u003eexample\u003c/strong\u003e notice",
    "msgtype": "m.notice"
  },
  "event_id": "$143273582443PhrSn:example.org",
  "origin_server_ts": 1432735824653,
  "room_id": "!jEsUZKDJdhlrceRyVU:example.org",
  "sender": "@example:example.org",
  "type": "m.room.message",
  "unsigned": {
    "age": 1234
  }
}

m.image


This message represents a single image and an optional thumbnail.

Event type: Message event

Content

Name 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’.
file EncryptedFile Required if the file is encrypted. Information on the encrypted file, as specified in End-to-end encryption.
info ImageInfo Metadata about the image referred to in url.
msgtype enum Required:

One of: [m.image].

url string Required if the file is unencrypted. The URL (typically MXC URI) to the image.
ImageInfo
Name Type Description
h integer The intended display height of the image in pixels. This may differ from the intrinsic dimensions of the image file.
mimetype string The mimetype of the image, e.g. image/jpeg.
size integer Size of the image in bytes.
thumbnail_file EncryptedFile Information on the encrypted thumbnail file, as specified in End-to-end encryption. Only present if the thumbnail is encrypted.
thumbnail_info ThumbnailInfo Metadata about the image referred to in thumbnail_url.
thumbnail_url string The URL (typically MXC URI) to a thumbnail of the image. Only present if the thumbnail is unencrypted.
w integer The intended display width of the image in pixels. This may differ from the intrinsic dimensions of the image file.
ThumbnailInfo
Name Type Description
h integer The intended display height of the image in pixels. This may differ from the intrinsic dimensions of the image file.
mimetype string The mimetype of the image, e.g. image/jpeg.
size integer Size of the image in bytes.
w integer The intended display width of the image in pixels. This may differ from the intrinsic dimensions of the image file.

Examples

{
  "content": {
    "body": "filename.jpg",
    "info": {
      "h": 398,
      "mimetype": "image/jpeg",
      "size": 31037,
      "w": 394
    },
    "msgtype": "m.image",
    "url": "mxc://example.org/JWEIFJgwEIhweiWJE"
  },
  "event_id": "$143273582443PhrSn:example.org",
  "origin_server_ts": 1432735824653,
  "room_id": "!jEsUZKDJdhlrceRyVU:example.org",
  "sender": "@example:example.org",
  "type": "m.room.message",
  "unsigned": {
    "age": 1234
  }
}

m.file


This message represents a generic file.

Event type: Message event

Content

Name Type Description
body string Required: A human-readable description of the file. This is recommended to be the filename of the original upload.
file EncryptedFile Required if the file is encrypted. Information on the encrypted file, as specified in End-to-end encryption.
filename string The original filename of the uploaded file.
info FileInfo Information about the file referred to in url.
msgtype enum Required:

One of: [m.file].

url string Required if the file is unencrypted. The URL (typically MXC URI) to the file.
FileInfo
Name Type Description
mimetype string The mimetype of the file e.g. application/msword.
size integer The size of the file in bytes.
thumbnail_file EncryptedFile Information on the encrypted thumbnail file, as specified in End-to-end encryption. Only present if the thumbnail is encrypted.
thumbnail_info ThumbnailInfo Metadata about the image referred to in thumbnail_url.
thumbnail_url string The URL to the thumbnail of the file. Only present if the thumbnail is unencrypted.
ThumbnailInfo
Name Type Description
h integer The intended display height of the image in pixels. This may differ from the intrinsic dimensions of the image file.
mimetype string The mimetype of the image, e.g. image/jpeg.
size integer Size of the image in bytes.
w integer The intended display width of the image in pixels. This may differ from the intrinsic dimensions of the image file.

Examples

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

m.audio


This message represents a single audio clip.

Event type: Message event

Content

Name 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’.
file EncryptedFile Required if the file is encrypted. Information on the encrypted file, as specified in End-to-end encryption.
info AudioInfo Metadata for the audio clip referred to in url.
msgtype enum Required:

One of: [m.audio].

url string Required if the file is unencrypted. The URL (typically MXC URI) to the audio clip.
AudioInfo
Name 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.

Examples

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

m.location


This message represents a real-world location.

Event type: Message event

Content

Name 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 (RFC5870) representing this location.
info LocationInfo
msgtype enum Required:

One of: [m.location].

LocationInfo
Name Type Description
thumbnail_file EncryptedFile Information on the encrypted thumbnail file, as specified in End-to-end encryption. Only present if the thumbnail is encrypted.
thumbnail_info ThumbnailInfo Metadata about the image referred to in thumbnail_url.
thumbnail_url string The URL to the thumbnail of the file. Only present if the thumbnail is unencrypted.
ThumbnailInfo
Name Type Description
h integer The intended display height of the image in pixels. This may differ from the intrinsic dimensions of the image file.
mimetype string The mimetype of the image, e.g. image/jpeg.
size integer Size of the image in bytes.
w integer The intended display width of the image in pixels. This may differ from the intrinsic dimensions of the image file.

Examples

{
  "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://example.org/FHyPlCeYUSFFxlgbQYZmoEoe"
    },
    "msgtype": "m.location"
  },
  "event_id": "$143273582443PhrSn:example.org",
  "origin_server_ts": 1432735824653,
  "room_id": "!jEsUZKDJdhlrceRyVU:example.org",
  "sender": "@example:example.org",
  "type": "m.room.message",
  "unsigned": {
    "age": 1234
  }
}

m.video


This message represents a single video clip.

Event type: Message event

Content

Name 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’.
file EncryptedFile Required if the file is encrypted. Information on the encrypted file, as specified in End-to-end encryption.
info VideoInfo Metadata about the video clip referred to in url.
msgtype enum Required:

One of: [m.video].

url string Required if the file is unencrypted. The URL (typically MXC URI) to the video clip.
VideoInfo
Name Type Description
duration integer The duration of the video in milliseconds.
h integer The height 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_file EncryptedFile Information on the encrypted thumbnail file, as specified in End-to-end encryption. Only present if the thumbnail is encrypted.
thumbnail_info ThumbnailInfo Metadata about the image referred to in thumbnail_url.
thumbnail_url string The URL (typically MXC URI) to an image thumbnail of the video clip. Only present if the thumbnail is unencrypted.
w integer The width of the video in pixels.
ThumbnailInfo
Name Type Description
h integer The intended display height of the image in pixels. This may differ from the intrinsic dimensions of the image file.
mimetype string The mimetype of the image, e.g. image/jpeg.
size integer Size of the image in bytes.
w integer The intended display width of the image in pixels. This may differ from the intrinsic dimensions of the image file.

Examples

{
  "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://example.org/FHyPlCeYUSFFxlgbQYZmoEoe",
      "w": 480
    },
    "msgtype": "m.video",
    "url": "mxc://example.org/a526eYUSFFxlgbQYZmo442"
  },
  "event_id": "$143273582443PhrSn:example.org",
  "origin_server_ts": 1432735824653,
  "room_id": "!jEsUZKDJdhlrceRyVU:example.org",
  "sender": "@example:example.org",
  "type": "m.room.message",
  "unsigned": {
    "age": 1234
  }
}

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.

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.

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 can be reduced through clients making use of the transaction ID they used to send a particular event. The transaction ID used will be included in the event’s unsigned data as transaction_id when it arrives through the event stream.

Clients unable to make use of the transaction ID are likely to experience flickering when the remote echo arrives on the event stream before the request to send the message completes. In that case the event arrives before the client has obtained an event ID, making it impossible to identify it as a remote echo. This results in the client displaying the message twice for some time (depending on the server responsiveness) before 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.

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

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 valid alias field, use the alias given by that field as the name. Note that clients should avoid using alt_aliases when calculating the room name.
  3. If none 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, as defined below.
    1. If the number of m.heroes for the room are greater or equal to m.joined_member_count + m.invited_member_count - 1, then use the membership events for the heroes to calculate display names for the users (disambiguating them if required) and concatenating them. For example, the client may choose to show “Alice, Bob, and Charlie (@charlie:example.org)” as the room name. The client may optionally limit the number of users it uses to generate a room name.
    2. If there are fewer heroes than m.joined_member_count + m.invited_member_count - 1, and m.joined_member_count + m.invited_member_count is greater than 1, the client should use the heroes to calculate display names for the users (disambiguating them if required) and concatenating them alongside a count of the remaining users. For example, “Alice, Bob, and 1234 others”.
    3. If m.joined_member_count + m.invited_member_count is less than or equal to 1 (indicating the member is alone), the client should use the rules above to indicate that the room was empty. For example, “Empty Room (was Alice)”, “Empty Room (was Alice and 1234 others)”, or “Empty Room” if there are no heroes.

Clients SHOULD internationalise the room name to the user’s language when using the m.heroes to calculate the name. Clients SHOULD use minimum 5 heroes to calculate room names where possible, but may use more or less to fit better with their user experience.

Spoiler messages

[Added in v1.1]

Parts of a message can be hidden visually from the user through use of spoilers. This does not affect the server’s representation of the event content - it is simply a visual cue to the user that the message may reveal important information about something, spoiling any relevant surprise.

To send spoilers clients MUST use the formatted_body and therefore the org.matrix.custom.html format, described above. This makes spoilers valid on any msgtype which can support this format appropriately.

Spoilers themselves are contained with span tags, with the reason (optionally) being in the data-mx-spoiler attribute. Spoilers without a reason must at least specify the attribute, though the value may be empty/undefined.

An example of a spoiler is:

{
  "msgtype": "m.text",
  "format": "org.matrix.custom.html",
  "body": "Alice [Spoiler](mxc://example.org/abc123) in the movie.",
  "formatted_body": "Alice <span data-mx-spoiler>lived happily ever after</span> in the movie."
}

If a reason were to be supplied, it would look like:

{
  "msgtype": "m.text",
  "format": "org.matrix.custom.html",
  "body": "Alice [Spoiler for health of Alice](mxc://example.org/abc123) in the movie.",
  "formatted_body": "Alice <span data-mx-spoiler='health of alice'>lived happily ever after</span> in the movie."
}

When sending a spoiler, clients SHOULD provide the plain text fallback in the body as shown above (including the reason). The fallback SHOULD omit the spoiler text verbatim since body might show up in text-only clients or in notifications. To prevent spoilers showing up in such situations, clients are strongly encouraged to first upload the plaintext to the media repository then reference the MXC URI in a markdown-style link, as shown above.

Clients SHOULD render spoilers differently with some sort of disclosure. For example, the client could blur the actual text and ask the user to click on it for it to be revealed.

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.

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.

Rich replies

[Changed in v1.3]

Rich replies are a special kind of relationship which effectively quotes the referenced event for the client to render/process how it wishes. They are normally used with m.room.message events.

When possible, events SHOULD include a fallback representation to allow clients which do not render rich replies to still see something which appears to be a quoted reply.

Though rich replies form a relationship to another event, they do not use rel_type to create this relationship. Instead, a subkey named m.in_reply_to is used to describe the reply’s relationship, leaving the other properties of m.relates_to to describe the primary relationship of the event. This means that if an event is simply in reply to another event, without further relationship, the rel_type and event_id properties of m.relates_to become optional.

An example reply would be:

{
  "content": {
    "m.relates_to": {
      "m.in_reply_to": {
        "event_id": "$another_event"
      }
    },
    "body": "That sounds like a great idea!"
  },
  // other fields as required by events
}

Note that the event_id of the m.in_reply_to object has the same requirements as if it were to be under m.relates_to directly instead.

Fallbacks for rich replies

Some clients may not have support for rich replies and therefore need a fallback to use instead. Clients that do not support rich replies should render the event as if rich replies were not special.

Clients that do support rich replies SHOULD provide the fallback format on replies, and MUST strip the fallback before rendering the reply. The specific fallback text is different for each msgtype, however the general format for the body is:

> <@alice:example.org> This is the original body

This is where the reply goes

The formatted_body, if present and using an associated format of org.matrix.custom.html, should use the following template:

<mx-reply>
  <blockquote>
    <a href="https://matrix.to/#/!somewhere:example.org/$event:example.org">In reply to</a>
    <a href="https://matrix.to/#/@alice:example.org">@alice:example.org</a>
    <br />
    <!-- This is where the related event's HTML would be. -->
  </blockquote>
</mx-reply>
This is where the reply goes.

If the related event does not have a formatted_body, the event’s body should be considered after encoding any HTML special characters. Note that the href in both of the anchors use a matrix.to URI.

Stripping the fallback

Clients which support rich replies MUST strip the fallback from the event before rendering the event. This is because the text provided in the fallback cannot be trusted to be an accurate representation of the event. After removing the fallback, clients are recommended to represent the event referenced by m.in_reply_to similar to the fallback’s representation, although clients do have creative freedom for their user interface. Clients should prefer the formatted_body over the body, just like with other m.room.message events.

To strip the fallback on the body, the client should iterate over each line of the string, removing any lines that start with the fallback prefix ("> “, including the space, without quotes) and stopping when a line is encountered without the prefix. This prefix is known as the “fallback prefix sequence”.

To strip the fallback on the formatted_body, the client should remove the entirety of the mx-reply tag.

Fallback for m.text, m.notice, and unrecognised message types

Using the prefix sequence, the first line of the related event’s body should be prefixed with the user’s ID, followed by each line being prefixed with the fallback prefix sequence. For example:

> <@alice:example.org> This is the first line
> This is the second line

This is the reply

The formatted_body uses the template defined earlier in this section.

Fallback for m.emote

Similar to the fallback for m.text, each line gets prefixed with the fallback prefix sequence. However an asterisk should be inserted before the user’s ID, like so:

> * <@alice:example.org> feels like today is going to be a great day

This is the reply

The formatted_body has a subtle difference for the template where the asterisk is also inserted ahead of the user’s ID:

<mx-reply>
  <blockquote>
    <a href="https://matrix.to/#/!somewhere:example.org/$event:example.org">In reply to</a>
    * <a href="https://matrix.to/#/@alice:example.org">@alice:example.org</a>
    <br />
    <!-- This is where the related event's HTML would be. -->
  </blockquote>
</mx-reply>
This is where the reply goes.
Fallback for m.image, m.video, m.audio, and m.file

The related event’s body would be a file name, which may not be very descriptive. The related event should additionally not have a format or formatted_body in the content - if the event does have a format and/or formatted_body, those fields should be ignored. Because the filename alone may not be descriptive, the related event’s body should be considered to be "sent a file." such that the output looks similar to the following:

> <@alice:example.org> sent a file.

This is the reply
<mx-reply>
  <blockquote>
    <a href="https://matrix.to/#/!somewhere:example.org/$event:example.org">In reply to</a>
    <a href="https://matrix.to/#/@alice:example.org">@alice:example.org</a>
    <br />
    sent a file.
  </blockquote>
</mx-reply>
This is where the reply goes.

For m.image, the text should be "sent an image.". For m.video, the text should be "sent a video.". For m.audio, the text should be "sent an audio file".

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.

Events

m.call.answer


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

Event type: Message event

Content

Name Type Description
answer Answer Required: The session description object
call_id string Required: The ID of the call this event relates to.
version number Required:
Answer
Name Type Description
sdp string Required: The SDP text of the session description.
type enum Required: The type of session description.

One of: [answer].

Examples

{
  "content": {
    "answer": {
      "sdp": "v=0\r\no=- 6584580628695956864 2 IN IP4 127.0.0.1[...]",
      "type": "answer"
    },
    "call_id": "12345",
    "version": 0
  },
  "event_id": "$143273582443PhrSn:example.org",
  "origin_server_ts": 1432735824653,
  "room_id": "!jEsUZKDJdhlrceRyVU:example.org",
  "sender": "@example:example.org",
  "type": "m.call.answer",
  "unsigned": {
    "age": 1234
  }
}

m.call.candidates


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.

Event type: Message event

Content

Name 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
Name Type Description
candidate string Required: The SDP ‘a’ line of the candidate.
sdpMLineIndex number Required: The index of the SDP ’m’ line this candidate is intended for.
sdpMid string Required: The SDP media type this candidate is intended for.

Examples

{
  "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": "$143273582443PhrSn:example.org",
  "origin_server_ts": 1432735824653,
  "room_id": "!jEsUZKDJdhlrceRyVU:example.org",
  "sender": "@example:example.org",
  "type": "m.call.candidates",
  "unsigned": {
    "age": 1234
  }
}

m.call.hangup


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.

Event type: Message event

Content

Name Type Description
call_id string Required: The ID of the call this event relates to.
reason enum Optional error reason for the hangup. This should not be provided when the user naturally ends or rejects the call. When there was an error in the call negotiation, this should be ice_failed for when ICE negotiation fails or invite_timeout for when the other party did not answer in time.

One of: [ice_failed invite_timeout].

version integer Required: The version of the VoIP specification this message adheres to. This specification is version 0.

Examples

{
  "content": {
    "call_id": "12345",
    "version": 0
  },
  "event_id": "$143273582443PhrSn:example.org",
  "origin_server_ts": 1432735824653,
  "room_id": "!jEsUZKDJdhlrceRyVU:example.org",
  "sender": "@example:example.org",
  "type": "m.call.hangup",
  "unsigned": {
    "age": 1234
  }
}

m.call.invite


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

Event type: Message event

Content

Name Type Description
call_id string Required: A unique identifier for the call.
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 Required: The session description object
version integer Required: The version of the VoIP specification this message adheres to. This specification is version 0.
Offer
Name Type Description
sdp string Required: The SDP text of the session description.
type enum Required: The type of session description.

One of: [offer].

Examples

{
  "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": "$143273582443PhrSn:example.org",
  "origin_server_ts": 1432735824653,
  "room_id": "!jEsUZKDJdhlrceRyVU:example.org",
  "sender": "@example:example.org",
  "type": "m.call.invite",
  "unsigned": {
    "age": 1234
  }
}

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.

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.

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.

GET /_matrix/client/v3/voip/turnServer


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

Rate-limited: Yes
Requires authentication: Yes

Request

No request parameters or request body.


Responses

Status Description
200 The TURN server credentials.
429 This request was rate-limited.

200 response

Name Type Description
password string Required: The password to use.
ttl integer Required: The time-to-live in seconds
uris [string] Required: A list of TURN URIs
username string Required: The username to use.
{
  "password": "JlKfBy1QwLrO20385QyAtEyIv0=",
  "ttl": 86400,
  "uris": [
    "turn:turn.example.com:3478?transport=udp",
    "turn:10.20.30.40:3478?transport=tcp",
    "turns:10.20.30.40:443?transport=tcp"
  ],
  "username": "1443779631:@user:example.com"
}

429 response

RateLimitError
Name Type Description
errcode string Required: The M_LIMIT_EXCEEDED error code
error string A human-readable error message.
retry_after_ms integer The amount of time in milliseconds the client should wait before trying the request again.
{
  "errcode": "M_LIMIT_EXCEEDED",
  "error": "Too many requests",
  "retry_after_ms": 2000
}

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.

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.

Events

m.typing


Informs the client of the list of users currently typing.

Event type: Message event

Content

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

Examples

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

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.

PUT /_matrix/client/v3/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 authentication: Yes

Request

Request parameters

<
path parameters
Name Type Description
roomId