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.

List of Endpoints
Required

API Standards

These standards only apply to the APIs defined in the Matrix specification. APIs used by this specification but defined in other specifications, like the OAuth 2.0 API, use their own rules.

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 those listed below, 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.

The exceptions are:

Similarly, all endpoints require the server to return a JSON object, with the exception of 200 responses to the media download endpoints in the Content Repository module. 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 with 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_BAD_JSON
Request contained valid JSON, but it was malformed in some way, e.g. missing required keys, invalid values for keys.
M_FORBIDDEN
Forbidden access, e.g. joining a room without permission, failed login.
M_LIMIT_EXCEEDED
Too many requests have been sent in a short period of time. Wait a while then try again. See Rate limiting.
M_MISSING_TOKEN
No access token was specified for the request.
M_NOT_FOUND
No resource was found for this request.
M_NOT_JSON
Request did not contain valid JSON.
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, /user/{userId}/account_data/{type}, etc).
M_UNKNOWN
An unknown error has occurred.
M_UNKNOWN_DEVICE
[Added in v1.17] The device ID supplied by the application service does not belong to the user ID during identity assertion.
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_UNRECOGNIZED
The server did not understand the request. This is expected to be returned with a 404 HTTP status code if the endpoint is not implemented or a 405 HTTP status code if the endpoint is implemented, but the incorrect HTTP method is used.
M_USER_LIMIT_EXCEEDED
[Added in v1.18] The request cannot be completed because the user has exceeded (or the request would cause them to exceed) a limit associated with their account. For example, a user may have reached their allocated storage quota, reached a maximum number of allowed rooms, devices, or other account-scoped resources, or exceeded usage limits for specific features.

The error response MUST have an info_uri field (string), which is a URI that the client can present to the user to provide more context on the encountered limit and, if applicable, guidance on how to increase the limit. The homeserver MAY return different values for info_uri depending on the type of limit reached.

The error response MAY include a can_upgrade field (boolean, default false). If true, it indicates that the specific limit encountered can be increased, for example by upgrading the user’s account tier. If absent or false, the limit is a hard limit that cannot be increased.

The HTTP status code will depend on depend on the particular endpoint.

Example response:

{
  "errcode": "M_USER_LIMIT_EXCEEDED",
  "error": "You have exceeded your storage quota of 10GB",
  "info_uri": "https://example.com/homeserver/about?limit_type=quota",
  "can_upgrade": true
}
M_USER_LOCKED
The account has been locked and cannot be used at this time.
M_USER_SUSPENDED
The account has been suspended and can only be used for limited actions at this time.

Other error codes

The following error codes are specific to certain endpoints.

M_BAD_STATE
The state change requested cannot be performed, such as attempting to unban a user who is not banned.
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.
M_CAPTCHA_INVALID
The Captcha provided did not match what was expected.
M_CAPTCHA_NEEDED
A Captcha is required to complete the request.
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_GUEST_ACCESS_FORBIDDEN
The room or resource does not permit guests to access it.
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_INVALID_PARAM
A parameter that was specified has the wrong value. For example, the server expected an integer and instead received a string.
M_INVALID_ROOM_STATE
Sent when the initial state given to the createRoom API is invalid.
M_INVALID_USERNAME
Encountered when trying to register a user ID which is not valid.
M_MISSING_PARAM
A required parameter was missing from the request.
M_ROOM_IN_USE
Sent when the room alias given to the createRoom API is already in use.
M_SERVER_NOT_TRUSTED
The client’s request used a third-party server, e.g. identity server, that this server does not trust.
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_THREEPID_IN_USE
The third party identifier specified by the client is not acceptable because it is already in use in some way.
M_THREEPID_MEDIUM_NOT_SUPPORTED
The homeserver does not support adding a third party identifier of the given medium.
M_THREEPID_NOT_FOUND
Sent when a threepid given to an API cannot be used because no record matching the threepid was found.
M_TOO_LARGE
The request or entity was too large.
M_UNAUTHORIZED
The request was not correctly authorized. Usually due to login failures.
M_UNSUPPORTED_ROOM_VERSION
The client’s request to create a room used a room version that the server does not support.
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.

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, deprecated)
}

Homeservers SHOULD include a Retry-After header for any response with a 429 status code.

The retry_after_ms property MAY be included to tell the client how long they have to wait in milliseconds before they can try again. This property is deprecated, in favour of the Retry-After header.

[Changed in v1.10]: retry_after_ms property deprecated in favour of Retry-After header.

Transaction identifiers

The client-server API typically uses HTTP PUT to submit requests with a client-generated transaction identifier in the HTTP path.

The purpose of the transaction ID is to allow the homeserver to distinguish a new request from a retransmission of a previous request so that it can make the request idempotent.

The transaction ID should only be used for this purpose.

After the request has finished, clients should change the {txnId} value for the next request. How this is achieved, is left as an implementation detail. It is recommended that clients use either version 4 UUIDs or a concatenation of the current timestamp and a monotonically increasing integer.

The homeserver should identify a request as a retransmission if the transaction ID is the same as a previous request, and the path of the HTTP request is the same.

Where a retransmission has been identified, the homeserver should return the same HTTP response code and content as the original request. For example, PUT /_matrix/client/v3/rooms/{roomId}/send/{eventType}/{txnId} would return a 200 OK with the event_id of the original request in the response body.

The scope of a transaction ID is for a single device, and a single HTTP endpoint. In other words: a single device could use the same transaction ID for a request to PUT /_matrix/client/v3/rooms/{roomId}/send/{eventType}/{txnId} and PUT /_matrix/client/v3/sendToDevice/{eventType}/{txnId}, and the two requests would be considered distinct because the two are considered separate endpoints. Similarly, if a client logs out and back in between two requests using the same transaction ID, the requests are distinct because the act of logging in and out creates a new device (unless an existing device_id is given during the login process). On the other hand, if a client re-uses a transaction ID for the same endpoint after refreshing an access token, it will be assumed to be a duplicate request and ignored. See also Relationship between access tokens and devices.

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.

Prior to v1.7, transaction IDs were scoped to “client sessions” rather than devices.

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

[Added in v1.13] The recommended value of the Access-Control-Allow-Methods header only covers the existing endpoints in the specification. Servers which support additional endpoints or methods should add those methods as well.

This section will be updated whenever a new method is supported by an endpoint. Examples of possible future-use methods include PATCH and HEAD.

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 URIs

Matrix facilitates automatic discovery for the Client-Server API base URL and more via the RFC 8615 “Well-Known URI” method. This method uses JSON files at a predetermined location on the root path /.well-known/ to specify parameter values.

Diverging from the rest of the endpoints in the Client-Server spec, these files can not be provided on the base URL that the Client-Server API is reachable on, as it is yet to be discovered. Instead, they can be reached via HTTPS on the server name’s hostname as domain.

Servers hosting the .well-known JSON file SHOULD offer CORS headers, as per the CORS section in this specification.

The flow for auto-discovery 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 as described by the grammar.
  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.

This endpoint should be accessed with the hostname of the homeserver’s server name by making a GET request to https://hostname/.well-known/matrix/client.

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.

<Other properties>

Application-dependent keys using Java package naming convention.

Homeserver Information
Name Type Description
base_url URI

Required: The base URL for the homeserver for client-server connections.

Identity Server Information
Name Type Description
base_url URI

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 /.well-known/matrix/support


Added in v1.10

Gets server admin contact and support page of the domain.

Like the well-known discovery URI, this endpoint should be accessed with the hostname of the homeserver’s server name by making a GET request to https://hostname/.well-known/matrix/support.

Note that this endpoint is not necessarily handled by the homeserver. It may be served by another webserver, used for discovering support information for the homeserver.

Rate-limited: No
Requires authentication: No

Request

No request parameters or request body.


Responses

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

200 response

Name Type Description
contacts [Contact]

Ways to contact the server administrator.

At least one of contacts or support_page is required. If only contacts is set, it must contain at least one item.

support_page URI

The URL of a page to give users help specific to the homeserver, like extra login/registration steps.

At least one of contacts or support_page is required.

Contact
Name Type Description
email_address Email Address

An email address to reach the administrator.

At least one of matrix_id or email_address is required.

matrix_id User ID

A Matrix User ID representing the administrator.

It could be an account registered on a different homeserver so the administrator can be contacted when the homeserver is down.

At least one of matrix_id or email_address is required.

role string

Required: An informal description of what the contact methods are used for.

m.role.admin is a catch-all role for any queries and m.role.security is intended for sensitive requests.

Unspecified roles are permitted through the use of Namespaced Identifiers.

One of: [m.role.admin, m.role.security].

{
  "contacts": [
    {
      "email_address": "[email protected]",
      "matrix_id": "@admin:example.org",
      "role": "m.role.admin"
    },
    {
      "email_address": "[email protected]",
      "role": "m.role.security"
    }
  ],
  "support_page": "https://example.org/support.html"
}

GET /.well-known/matrix/policy_server


Added in v1.18

Gets public key information for a Policy Server.

Like the well-known discovery URI, this endpoint should be accessed with the hostname of the Policy Server’s server name by making a GET request to https://hostname/.well-known/matrix/policy_server.

Note that this endpoint is not necessarily handled by the homeserver or Policy Server. It may be served by another webserver.

Rate-limited: No
Requires authentication: No

Request

No request parameters or request body.


Responses

Status Description
200 Public keys for the Policy Server. Can be supplied to the m.room.policy state event.
404 No policy server information available.

200 response

Name Type Description
public_keys object

Required: The unpadded base64-encoded public keys for the Policy Server. MUST contain at least ed25519.

Name Type Description
ed25519 string

Required: The unpadded base64-encoded ed25519 public key for the Policy Server.

<Other properties> string

The unpadded base64-encoded public key for the key algorithm.

{
  "public_keys": {
    "ed25519": "6yhHGKhCiXTSEN2ksjV7kX_N6rBQZ3Xb-M7LlC6NS-s"
  }
}

API Versions

Upon connecting, the Matrix client and server need to negotiate which version of the specification they commonly support, as the API evolves over time. The server advertises its supported versions and optionally unstable features to the client, which can then go on to make requests to the endpoints it supports.

GET /_matrix/client/versions


Changed in v1.10: This endpoint can behave differently when authentication is provided.

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 can choose to enable some features only for some users, so clients should include authentication in the request to get all the features available for the logged-in user. If no authentication is provided, the server should only return the features available to all users. 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: Optional

Request

No request parameters or request body.


Responses

Status Description
200 The versions supported by the server.

200 response

Name Type Description
unstable_features {string: boolean}

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

[Changed in v1.15] OAuth 2.0 API added to the specification.

Most API endpoints require the user to identify themselves by presenting previously obtained credentials in the form of an 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.

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

Since Matrix 1.15, the Client-Server specification supports two authentication APIs:

The legacy API has existed since the first version of the Matrix specification, while the OAuth 2.0 API has been introduced to rely on a industry standard and its experience rather than implementing a custom protocol that might not follow the best practices.

A homeserver may support one of those two APIs, or both. The two APIs are mutually incompatible, which means that after logging in, clients MUST only use the API that was used to obtain their current access token.

Currently the OAuth 2.0 API doesn’t cover all the use cases of the legacy API, such as automated applications that cannot use a web browser.

[Added in v1.18] A compatibility feature, called OAuth 2.0 aware clients, is available to ease the transition to the OAuth 2.0 API for clients that only support the legacy API.

Authentication API discovery

To discover if a homeserver supports the legacy API, the GET /login endpoint can be used.

To discover if a homeserver supports the OAuth 2.0 API, the GET /auth_metadata endpoint can be used.

In both cases, the server SHOULD respond with 404 and an M_UNRECOGNIZED error code if the corresponding API is not supported.

Account registration

With the legacy API, a client can register a new account with the /register endpoint.

With the OAuth 2.0 API, a client can’t register a new account directly. The end user must do that directly in the homeserver’s web UI. However, the client can signal to the homeserver that the user wishes to create a new account with the prompt=create parameter during authorization.

[Added in v1.17] Application services can use the /register endpoint to create users regardless of the authentication API supported by the homeserver.

Login

With the legacy API, a client can obtain an access token by using one of the login methods supported by the homeserver at the POST /login endpoint. To invalidate the access token the client must call the /logout endpoint.

With the OAuth 2.0 API, a client can obtain an access token by using one of the grant types supported by the homeserver and authorizing the proper scope, as demonstrated in the login flows. To invalidate the access token the client must use token revocation.

Using access tokens

Access tokens may be provided via a request header, using the Authentication Bearer scheme: Authorization: Bearer TheTokenHere.

Clients may alternatively provide the access token via a query string parameter: access_token=TheTokenHere. This method is deprecated to prevent the access token being leaked in access/HTTP logs and SHOULD NOT be used by clients.

Homeservers MUST support both methods.

[Changed in v1.11] Sending the access token as a query string parameter is now deprecated.

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.

During login or registration, the generated access token should be associated with a device_id. The legacy Login and Registration processes auto-generate a new device_id, but a client is also free to provide its own device_id. With the OAuth 2.0 API, the device_id is always provided by the client. The client can generate a new device_id or, provided the user remains the same, reuse an existing device. 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. 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.

With the legacy API, refreshing access tokens is done by calling /refresh. 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.

With the OAuth 2.0 API, refreshing access tokens is done with the refresh token grant type, as demonstrated in the token refresh flow. Support for refreshing access tokens is mandatory with this API.

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.

[Changed in v1.12] A client that receives such a response together with an M_USER_LOCKED error code, cannot obtain a new access token until the account has been unlocked.

Account management

With the legacy API, a client can use several endpoints to allow the user to manage their account like changing their password, managing their devices or deactivating their account.

With the OAuth 2.0 API, all account management is done via the homeserver’s web UI that can be accessed by users via the account management URL.

Legacy API

This is the original authentication API that was introduced in the first version of the Client-Server specification and uses custom APIs. Contrary to the OAuth 2.0 API, account management is primarily done in the client’s interface and as such it does not usually require the end user to be redirected to a web UI in their browser.

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.

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

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
  • [Added in v1.11] m.login.terms
  • [Added in v1.17] m.oauth
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

The m.login.registration_token authentication type is only valid on the /register endpoint.

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 using the Opaque Identifier Grammar, with maximum length of 64 characters. 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
}
Terms of service at registration

[Added in v1.11]

Type Description
m.login.terms Authentication requires the user to accept a set of policy documents.

The m.login.terms authentication type is only valid on the /register endpoint.

This authentication type is used when the homeserver requires new users to accept a given set of policy documents, such as a terms of service and a privacy policy. There may be many different types of documents, all of which are versioned and presented in (potentially) multiple languages.

When the server requires the user to accept some terms, it does so by returning a 401 response to the /register request, where the response body includes m.login.terms in the flows list, and the m.login.terms property in the params object has the structure shown below.

If a client encounters an invalid parameter, registration should stop with an error presented to the user.

The client should present the user with a checkbox to accept each policy, including a link to the provided URL. Once the user has done so, the client submits an auth dict with just the type and session, as follows, to indicate that all of the policies have been accepted:

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

The server is expected to track which document versions it presented to the user during registration, if applicable.

Example

  1. A client might submit a registration request as follows:

    POST /_matrix/client/v3/register
    
    {
      "username": "cheeky_monkey",
      "password": "ilovebananas"
    }
    
  2. The server requires the user to accept some terms of service before registration, so returns the following response:

    HTTP/1.1 401 Unauthorized
    Content-Type: application/json
    
    {
      "flows": [
        { "stages": [ "m.login.terms" ] }
      ],
      "params": {
        "m.login.terms": {
          "policies": {
            "terms_of_service": {
              "version": "1.2",
              "en": {
                  "name": "Terms of Service",
                  "url": "https://example.org/somewhere/terms-1.2-en.html"
              },
              "fr": {
                  "name": "Conditions d'utilisation",
                  "url": "https://example.org/somewhere/terms-1.2-fr.html"
              }
            }
          }
        }
      },
      "session": "kasgjaelkgj"
    }
    
  3. The client presents the list of documents to the user, inviting them to accept the polices.

  4. The client repeats the registration request, confirming that the user has accepted the documents:

    POST /_matrix/client/v3/register
    
    {
      "username": "cheeky_monkey",
      "password": "ilovebananas",
      "auth": {
        "type": "m.login.terms",
        "session": "kasgjaelkgj"
      }
    }
    
  5. All authentication steps have now completed, so the request is successful:

    HTTP/1.1 200 OK
    Content-Type: application/json
    
    {
      "access_token": "abc123",
      "device_id": "GHTYAJCE",
      "user_id": "@cheeky_monkey:matrix.org"
    }
    

m.login.terms params


Schema for m.login.terms entry in the params object in a User-Interactive Authentication response.

m.login.terms params
Name Type Description
policies {string: Policy Definition}

Required: A map from “Policy ID” to the current definition of this policy document. The Policy ID is a unique identifier for a given policy document, using the Opaque Identifier Grammar.

Policy Definition
Name Type Description
version string

Required: The version of this policy document. This is provided as a convenience for the client, and uses the Opaque Identifier Grammar.

<Other properties> Policy Translation

Map from language codes to details of the document in that language. Language codes SHOULD be formatted as per Section 2.2 of RFC 5646, though some implementations may use an underscore instead of dash (for example, en_US instead of en-US).

Policy Translation
Name Type Description
name string

Required: The name of this document, in the appropriate language. An arbitrary string with no specified maximum length.

url URI

Required: A link to the text of this document, in the appropriate language. MUST be a valid URI with scheme https:// or http://. Insecure HTTP is discouraged.

Examples

{
  "policies": {
    "privacy_policy": {
      "en": {
        "name": "Privacy Policy",
        "url": "https://example.org/somewhere/privacy-1.2-en.html"
      },
      "fr": {
        "name": "Politique de confidentialité",
        "url": "https://example.org/somewhere/privacy-1.2-fr.html"
      },
      "version": "1.2"
    },
    "terms_of_service": {
      "en": {
        "name": "Terms of Service",
        "url": "https://example.org/somewhere/terms-1.2-en.html"
      },
      "fr": {
        "name": "Conditions d'utilisation",
        "url": "https://example.org/somewhere/terms-1.2-fr.html"
      },
      "version": "1.2"
    }
  }
}
OAuth authentication

[Added in v1.17]

Type Description
m.oauth Authentication is supported by authorising via the homeserver’s OAuth account management web UI.

The m.oauth authentication type is currently only valid on the /keys/device_signing/upload endpoint.

This authentication type provides homeservers the ability to guard access to sensitive actions when the client has authenticated via the OAuth 2.0 API, which is otherwise not compatible with User-Interactive Authentication (UIA). To do so, the server returns a 401 response on the respective request, where the response body includes m.oauth in the flows list, and the m.oauth property in the params object has the structure shown below.

The client is expected to open the contained URL to let the user confirm the action in the homeserver’s account management web UI. Once the user has done so, the client submits an auth dict with just the session, as follows, to complete the stage:

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

m.oauth params


Schema for m.oauth entry in the params object in a User-Interactive Authentication response.

m.oauth params
Name Type Description
url URI

Required: A URL pointing to the homeserver’s OAuth account management web UI where the user can approve the action. MUST be a valid URI with scheme http:// or https://, the latter being RECOMMENDED.

Examples

{
  "url": "https://example.org/account/reset-cross-signing"
}
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.

[Added in v1.7] Already-authenticated clients can additionally generate a token for their user ID if supported by the homeserver using POST /login/get_token.

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
404 With M_UNRECOGNIZED: the homeserver does not support the legacy authentication API. (See Authentication API discovery.)
429 This request was rate-limited.

200 response

Name Type Description
flows [LoginFlow]

The homeserver’s supported login types

LoginFlow
Name Type Description
get_login_token boolean

If type is m.login.token, an optional field to indicate to the unauthenticated client that the homeserver supports the POST /login/get_token endpoint. Note that supporting the endpoint does not necessarily indicate that the user attempting to log in will be able to generate such a token.

Added in v1.7

type string

Required: The login type. This is supplied as the type when logging in.

{
  "flows": [
    {
      "type": "m.login.password"
    },
    {
      "get_login_token": true,
      "type": "m.login.token"
    }
  ]
}

404 response

Error
Name Type Description
errcode string

Required: An error code.

error string

A human-readable error message.

{
  "errcode": "M_UNRECOGNIZED",
  "error": "OAuth 2.0 authentication is in use 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
}

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 string

Required: The login type being used.

This must be a type returned in one of the flows of the response of the GET /login endpoint, like m.login.password or 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.

<Other properties>

Keys dependent on the identification type.

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.

Specific error codes used with this status code include:

  • [Added in v1.17] M_APPSERVICE_LOGIN_UNSUPPORTED: an application service used the m.login.application_service type, but the server doesn’t support logging in via the Legacy authentication API.
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. Servers MAY instead use M_FORBIDDEN when they can no longer authenticate the deactivated user (e.g. their password has been wiped).
429 This request was rate-limited.

200 response

Name Type Description
access_token string

Required: An access token for the account. This access token can then be used to authorize other requests.

device_id string

Required: 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 Server Name

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 User ID

Required: 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.

<Other properties>

Application-dependent keys using Java package naming convention.

Homeserver Information
Name Type Description
base_url URI

Required: The base URL for the homeserver for client-server connections.

Identity Server Information
Name Type Description
base_url URI

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/v1/login/get_token


Added in v1.7

Optional endpoint - the server is not required to implement this endpoint if it does not intend to use or support this functionality.

This API endpoint uses the User-Interactive Authentication API.

An already-authenticated client can call this endpoint to generate a single-use, time-limited, token for an unauthenticated client to log in with, becoming logged in as the same user which called this endpoint. The unauthenticated client uses the generated token in a m.login.token login flow with the homeserver.

Clients, both authenticated and unauthenticated, might wish to hide user interface which exposes this feature if the server is not offering it. Authenticated clients can check for support on a per-user basis with the m.get_login_token capability, while unauthenticated clients can detect server support by looking for an m.login.token login flow with get_login_token: true on GET /login.

In v1.7 of the specification, transmission of the generated token to an unauthenticated client is left as an implementation detail. Future MSCs such as MSC3906 might standardise a way to transmit the token between clients.

The generated token MUST only be valid for a single login, enforced by the server. Clients which intend to log in multiple devices must generate a token for each.

With other User-Interactive Authentication (UIA)-supporting endpoints, servers sometimes do not re-prompt for verification if the session recently passed UIA. For this endpoint, servers MUST always re-prompt the user for verification to ensure explicit consent is gained for each additional client.

Servers are encouraged to apply stricter than normal rate limiting to this endpoint, such as maximum of 1 request per minute.

Rate-limited: Yes
Requires authentication: Yes

Request

Request body

Name Type Description
auth Authentication Data

Additional authentication information for the user-interactive authentication API.

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

<Other properties>

Keys dependent on the login type

Request body example

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

Responses

Status Description
200 The login token an unauthenticated client can use to log in as the requesting user.
400

The request was malformed, or the user does not have an ability to generate tokens for their devices, as implied by the User-Interactive Authentication API.

Clients should verify whether the user has an ability to call this endpoint with the m.get_login_token capability.

401 The homeserver requires additional authentication information.
429 This request was rate-limited.

200 response

Name Type Description
expires_in_ms integer

Required: The time remaining in milliseconds until the homeserver will no longer accept the token. 120000 (2 minutes) is recommended as a default.

login_token string

Required: The login token for the m.login.token login flow.

{
  "expires_in_ms": 120000,
  "login_token": "<opaque string>"
}

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

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 {string: 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/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

Required: 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 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

{}
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.

Appservices do not need to log in as individual users in all cases, as they can perform Identity Assertion using the appservice token. However, if the appservice needs a scoped token for a single user then they can use this API instead.

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.

[Added in v1.17] If this login type is used and the server doesn’t support logging in via the Legacy authentication API, it MUST return a 400 HTTP status code with an M_APPSERVICE_LOGIN_UNSUPPORTED error code.

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.matrixLogin.onLogin(response) when login has been successfully completed. The argument, response, is the JSON response body of POST /_matrix/client/v3/login parsed into a JavaScript object.

[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

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 any username which does 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.

[Added in v1.17] Even if the server doesn’t support the Legacy authentication API, it MUST support this endpoint for application services to be able to create users.

In that case application services MUST set the "inhibit_login": true parameter as they cannot use it to log in as users. If the inhibit_login parameter is not set to true, the server MUST return a 400 HTTP status code with an M_APPSERVICE_LOGIN_UNSUPPORTED error code.

[Added in v1.18] OAuth 2.0 aware clients MUST NOT use this endpoint when the server offers the m.login.sso authentication flow with oauth_aware_preferred set to true. Instead they MUST use the /login/sso/redirect endpoint, adding the action=register parameter.

Rate-limited: Yes
Requires authentication: No

Request

Request parameters

query parameters
Name Type Description
kind string

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

<Other properties>

Keys dependent on the login type

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.
  • [Added in v1.17] M_APPSERVICE_LOGIN_UNSUPPORTED: an application service used the m.login.application_service type without setting inhibit_login to true, but the server doesn’t support logging in via the Legacy authentication API.

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 Server Name

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 User ID

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 {string: 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 Email Address

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 URI

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 URI

An optional field containing a URL where the client must submit the validation token, with identical request and response parameters and error codes to the Identity Service API’s POST /validate/email/submitToken and POST /validate/msisdn/submitToken endpoints (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 a sufficiently recent version in the GET /versions response (ie: r0.5.0).

Changed in v1.18: The URL has the same request and response parameters and error codes as the Identity Service API’s endpoint.

{
  "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 URI

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 URI

An optional field containing a URL where the client must submit the validation token, with identical request and response parameters and error codes to the Identity Service API’s POST /validate/email/submitToken and POST /validate/msisdn/submitToken endpoints (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 a sufficiently recent version in the GET /versions response (ie: r0.5.0).

Changed in v1.18: The URL has the same request and response parameters and error codes as the Identity Service API’s endpoint.

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

Account management

Password management

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

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.

This endpoint uses capabilities negotiation. Clients SHOULD check the value of the m.change_password capability to determine if this endpoint is available.

Rate-limited: Yes
Requires authentication: Optional

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

<Other properties>

Keys dependent on the login type

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 {string: 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 Email Address

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 URI

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 URI

An optional field containing a URL where the client must submit the validation token, with identical request and response parameters and error codes to the Identity Service API’s POST /validate/email/submitToken and POST /validate/msisdn/submitToken endpoints (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 a sufficiently recent version in the GET /versions response (ie: r0.5.0).

Changed in v1.18: The URL has the same request and response parameters and error codes as the Identity Service API’s endpoint.

{
  "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 URI

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 URI

An optional field containing a URL where the client must submit the validation token, with identical request and response parameters and error codes to the Identity Service API’s POST /validate/email/submitToken and POST /validate/msisdn/submitToken endpoints (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 a sufficiently recent version in the GET /versions response (ie: r0.5.0).

Changed in v1.18: The URL has the same request and response parameters and error codes as the Identity Service API’s endpoint.

{
  "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"
}
Account deactivation

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.

[Added in v1.18] OAuth 2.0 aware clients MUST NOT use this endpoint when the server supports the OAuth 2.0 API. Instead they MUST refer the user to the account management URL, if available, and MAY use the action=org.matrix.account_deactivate parameter.

Rate-limited: Yes
Requires authentication: Optional

Request

Request body

Name Type Description
auth Authentication Data

Additional authentication information for the user-interactive authentication API.

erase boolean

Whether the user would like their content to be erased as much as possible from the server.

Erasure means that any users (or servers) which join the room after the erasure request are served redacted copies of the events sent by this account. Users which had visibility on those events prior to the erasure are still able to see unredacted copies. No redactions are sent and the erasure request is not shared over federation, so other servers might still serve unredacted copies.

The server should additionally erase any non-event data associated with the user, such as account data and contact 3PIDs.

Defaults to false if not present.

Added in v1.10

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

<Other properties>

Keys dependent on the login type

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 string

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 {string: 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
}

OAuth 2.0 aware clients

[Added in v1.18]

This is a compatibility feature to aide clients in the transition to the OAuth 2.0 API. It allows clients that only support the legacy API to make some less-invasive changes to improve the user experience when talking to a homeserver that is using the OAuth 2.0 API without actually having to implement the full OAuth 2.0 API.

Client behaviour

For a client to be considered fully OAuth 2.0 aware it MUST:

  • Support the m.login.sso authentication flow.

  • Where a oauth_aware_preferred value of true is present on an m.login.sso flow, only offer that auth flow to the user.

  • Append action=login or action=register parameters to the SSO redirect endpoints. The client might determine the value to use based on whether the user clicked a “Login” or “Register” button.

  • Check and honour the m.3pid_changes capability so that the user is not offered the ability to add or remove 3PIDs if the homeserver says the capability is not available.

  • Determine if the homeserver is using the OAuth 2.0 API by using server metadata discovery from the OAuth 2.0 API.

  • If a homeserver is using the OAuth 2.0 API as discovered in the previous step then the client MUST redirect users to manage their account at the account management URL, if available, instead of providing a native UI using the legacy API endpoints.

    • If the user wishes to deactivate their account then the client MUST refer them to the account management URL.
    • If the user wishes to sign out a device other than its own then the client MUST deep link the user to the account management URL by adding the action=org.matrix.device_delete and device_id=<device_id> parameters so that the web UI knows that the user wishes to sign out a device and which one it is.

Optionally, an OAuth 2.0 aware client MAY:

  • Label the SSO button as “Continue” rather than “SSO” when oauth_aware_preferred is true. This is because after redirect the server may then offer a password and/or further upstream IdPs.
  • Pass other account management URL parameters for context when linking to the account web UI.
Server behaviour

For a homeserver to provide support for OAuth 2.0 aware clients it MUST:

Additionally, the homeserver SHOULD:

OAuth 2.0 API

[Added in v1.15]

Contrary to the legacy API that uses custom endpoints and UIA, this authentication API is based on the OAuth 2.0 industry standard introduced in RFC 6749 and extended by other RFCs, with a few features from OpenID Connect. This allows us to benefit from its experience and from any further enhancements or best practice recommendations.

The main change for end users with this API is that all the account management occurs in their browser on the homeserver’s web UI. This is where they will register a new account or log into an existing account and authorize a client to access their Matrix account. This means that the homeserver has complete control over the requirements to create a new account and is not limited by the steps defined in this specification. It also means that less trust is given to clients because they don’t have access to the user’s credentials anymore.

The User-Interactive Authentication API is not compatible with the OAuth 2.0 API, so the endpoints that depend on it for authentication can’t be used when an access token is obtained with this API.

The only exception to this is the /keys/device_signing/upload endpoint which uses the m.oauth authentication type.

Sample flow

  1. Discover the OAuth 2.0 server metadata.
  2. Register the client with the homeserver.
  3. Obtain an access token by authorizing a scope for the client with the authorization code grant or device authorization grant.
  4. Refresh the access token with the refresh token grant when it expires.
  5. Revoke the tokens when the users wants to log out of the client.

Login flows

Logging in and obtaining an access token with the OAuth 2.0 API should be done using either the authorization code grant or device authorization grant. In the context of the Matrix specification, this means requesting a scope including full client-server API read/write access and allocating a device ID.

Authorization code flow

This login flow uses the authorization code grant and is suitable for clients where the following criteria are met:

  • There is a web browser available for the user to complete authentication and authorization.
  • The client can receive the callback via a redirect from the web browser.

Once the client has retrieved the server metadata the client needs to generate the following values:

  • device_id: a unique identifier for this device; see the urn:matrix:client:device:<device_id> scope token.

  • state: a unique opaque identifier, like a transaction ID, that will allow the client to maintain state between the authorization request and the callback.

  • code_verifier: a cryptographically random value that will allow to make sure that the client that makes the token request for a given code is the same one that made the authorization request.

    It is defined in RFC 7636 as a high-entropy cryptographic random string using the characters [A-Z], [a-z], [0-9], -, ., _ and ~ with a minimum length of 43 characters and a maximum length of 128 characters.

Authorization request

The client then constructs the authorization request URL using the authorization_endpoint value, with the following query parameters:

Parameter Value
response_type code
client_id The client ID returned from client registration.
redirect_uri The redirect URI that MUST match one of the values registered in the client metadata
scope urn:matrix:client:api:* urn:matrix:client:device:<device_id> with the device_id generated previously.
state The state value generated previously.
response_mode fragment or query (see “Callback” below).
code_challenge Computed from the code_verifier value generated previously using the SHA-256 algorithm, as described in RFC 7636.
code_challenge_method S256

This authorization request URL must be opened in the user’s browser:

  • For web-based clients, this can be done through a redirection or by opening the URL in a new tab.
  • For native clients, this can be done by opening the URL using the system browser, or, when available, through platform-specific APIs such as ASWebAuthenticationSession on iOS or Android Custom Tabs.

Sample authorization request, with extra whitespaces for readability:

https://account.example.com/oauth2/auth?
    client_id     = s6BhdRkqt3 &
    response_type = code &
    response_mode = fragment &
    redirect_uri  = https://app.example.com/oauth2-callback &
    scope         = urn:matrix:client:api:* urn:matrix:client:device:AAABBBCCCDDD &
    state         = ewubooN9weezeewah9fol4oothohroh3 &
    code_challenge        = 72xySjpngTcCxgbPfFmkPHjMvVDl2jW1aWP7-J6rmwU &
    code_challenge_method = S256

Callback

Once completed, the user is redirected to the redirect_uri, with either a successful or failed authorization in the URL fragment or query parameters. Whether the parameters are in the URL fragment or query parameters is determined by the response_mode value:

  • If set to fragment, the parameters will be placed in the URL fragment, like https://example.com/callback#param1=value1&param2=value2.
  • If set to query, the parameters will be in placed the query string, like com.example.app:/callback?param1=value1&param2=value2.

To avoid disclosing the parameters to the web server hosting the redirect_uri, clients SHOULD use the fragment response mode if the redirect_uri is an HTTPS URI with a remote host.

In both success and failure cases, the parameters will include the state value used in the authorization request.

A successful authorization will have a code value, for example:

https://app.example.com/oauth2-callback#state=ewubooN9weezeewah9fol4oothohroh3&code=iuB7Eiz9heengah1joh2ioy9ahChuP6R

A failed authorization will have the following values:

  • error: the error code
  • error_description: the error description (optional)
  • error_uri: the URI where the user can find more information about the error (optional)

For example:

https://app.example.com/oauth2-callback#state=ewubooN9weezeewah9fol4oothohroh3&error=access_denied&error_description=The+resource+owner+or+authorization+server+denied+the+request.&error_uri=https%3A%2F%2Ferrors.example.com%2F

Token request

The client then exchanges the authorization code to obtain an access token using the token endpoint.

This is done by making a POST request to the token_endpoint with the following parameters, encoded as application/x-www-form-urlencoded in the body:

Parameter Value
grant_type authorization_code
code The value of code obtained from the callback.
redirect_uri The same redirect_uri used in the authorization request.
client_id The client ID returned from client registration.
code_verifier The value generated at the start of the authorization flow.

The server replies with a JSON object containing the access token, the token type, the expiration time, and the refresh token.

Sample token request:

POST /oauth2/token HTTP/1.1
Host: account.example.com
Content-Type: application/x-www-form-urlencoded
Accept: application/json

grant_type=authorization_code
  &code=iuB7Eiz9heengah1joh2ioy9ahChuP6R
  &redirect_uri=https://app.example.com/oauth2-callback
  &client_id=s6BhdRkqt3
  &code_verifier=ogie4iVaeteeKeeLaid0aizuimairaCh

Sample response:

{
  "access_token": "2YotnFZFEjr1zCsicMWpAA",
  "token_type": "Bearer",
  "expires_in": 299,
  "refresh_token": "tGz3JOkF0XG5Qx2TlKWIA",
  "scope": "urn:matrix:client:api:* urn:matrix:client:device:AAABBBCCCDDD"
}

Finally, the client can call the /whoami endpoint to get the user ID that owns the access token.

Device authorization flow

[Added in v1.18]

This flow uses the device authorization grant to allow clients to obtain an access token without needing to directly interact with a web browser. Instead, the user completes authorization on a web browser that can be a separate device.

This is useful for devices with limited input capabilities (such as CLI applications or embedded devices) or where the redirect handling may be unreliable (such as a desktop applications).

Once the client has retrieved the server metadata the client needs to generate following value:

Device authorization request

The client sends a application/x-www-form-urlencoded encoded POST request to the device_authorization_endpoint as defined in RFC 8628 section 3.1:

Parameter Value
client_id The client ID returned from client registration.
scope urn:matrix:client:api:* urn:matrix:client:device:<device_id> with the device_id generated previously.

Sample device authorization request:

POST /oauth2/device HTTP/1.1
Host: account.example.com
Content-Type: application/x-www-form-urlencoded

client_id=s6BhdRkqt3&scope=urn%3Amatrix%3Aclient%3Aapi%3A%2A%20urn%3Amatrix%3Aclient%3Adevice%3AAABBBCCCDDD

Device authorization response

The server responds with a JSON object as defined in RFC 8628 section 3.2, containing:

Parameter
device_code The device verification code.
user_code An end-user verification code.
verification_uri The end-user verification URI on the authorization server.
verification_uri_complete Optionally, the URI which doesn’t require the user to manually type the user_code, designed for non-textual transmission.
expires_in The lifetime in seconds of the device_code and user_code.
interval The minimum number of seconds the client should wait between polling requests to the token endpoint. If omitted, clients should default to 5.

It is RECOMMENDED that the server provides a verification_uri_complete such that the user does not need to type in the user_code.

Sample response:

{
  "device_code": "GmRhmhcxhwAzkoEqiMEg_DnyEysNkuNhszIySk9eS",
  "user_code": "WDJB-MJHT",
  "verification_uri": "https://account.example.com/link",
  "verification_uri_complete": "https://account.example.com/link?user_code=WDJB-MJHT",
  "expires_in": 1800,
  "interval": 5
}

User interaction

The client conveys the verification_uri_complete (and/or verification_uri and user_code) to the user. How the client does this depends on the specific device characteristics and use case. For example:

  • A CLI application could display the verification_uri and user_code as text for the user to type into their browser on another device.
  • An embedded device with a screen could encode the verification_uri_complete (with fallback to verification_uri) as a QR code for the user to scan with their phone.
  • A desktop application running on a platform that does not support callbacks could launch the verification_uri_complete (with fallback to verification_uri) in the system browser.

The user opens the verification URI in a web browser, which may be on another device, and completes authentication and authorization.

Token polling

While the user is completing authorization, the client polls the token_endpoint for the outcome, at intervals no shorter than the interval value from the device authorization response.

The poll request is a POST to the token_endpoint with the following parameters, encoded as application/x-www-form-urlencoded in the body:

Parameter Value
grant_type urn:ietf:params:oauth:grant-type:device_code
device_code The device_code from the device authorization response.
client_id The client ID returned from client registration.

Sample token polling request:

POST /oauth2/token HTTP/1.1
Host: account.example.com
Content-Type: application/x-www-form-urlencoded

grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Adevice_code&device_code=GmRhmhcxhwAzkoEqiMEg_DnyEysNkuNhszIySk9eS&client_id=s6BhdRkqt3

The server responds as defined in RFC 8628 section 3.5:

  • While authorization is pending, the server returns an authorization_pending error (or slow_down if the client is polling too frequently).
  • If authorization is denied, the server returns an access_denied error.
  • If the device code expires, the server returns an expired_token error.
  • On successful authorization, the server returns a JSON object containing the access token, token type, expiration time, refresh token, and scope:
{
  "access_token": "2YotnFZFEjr1zCsicMWpAA",
  "token_type": "Bearer",
  "expires_in": 299,
  "refresh_token": "tGz3JOkF0XG5Qx2TlKWIA",
  "scope": "urn:matrix:client:api:* urn:matrix:client:device:AAABBBCCCDDD"
}

Finally, the client can call the /whoami endpoint to get the user ID that owns the access token.

Token refresh flow

Refreshing a token with the OAuth 2.0 API should be done with the refresh token grant.

When the access token expires, the client must refresh it by making a POST request to the token_endpoint with the following parameters, encoded as application/x-www-form-urlencoded in the body:

Parameter Value
grant_type refresh_token
refresh_token The refresh_token obtained from the token response during the last token request.
client_id The client ID returned from client registration.

The server replies with a JSON object containing the new access token, the token type, the expiration time, and a new refresh token, like in the authorization flow.

Server metadata discovery

GET /_matrix/client/v1/auth_metadata


Gets the OAuth 2.0 authorization server metadata, as defined in RFC 8414, including the endpoint URLs and the supported parameters that can be used by the clients.

This endpoint definition includes only the fields that are meaningful in the context of the Matrix specification. The full list of possible fields is available in the OAuth Authorization Server Metadata registry, and normative definitions of them are available in their respective RFCs.

The authorization server metadata is relatively large and may change over time. Clients should:

  • Cache the metadata appropriately based on HTTP caching headers
  • Refetch the metadata if it is stale
Rate-limited: No
Requires authentication: No

Request

No request parameters or request body.


Responses

Status Description
200 The OAuth 2.0 authorization server metadata.
404 With M_UNRECOGNIZED: the homeserver does not support the OAuth 2.0 API. (See Authentication API discovery.)

200 response

Name Type Description
account_management_actions_supported [string]

List of actions that the account management URL supports.

This is an extension defined in this specification.

Added in v1.18

account_management_uri URI

The URL where the user is able to access the account management capabilities of the homeserver.

This is an extension defined in this specification.

Added in v1.18

authorization_endpoint URI

Required: URL of the authorization endpoint, necessary to use the authorization code grant.

code_challenge_methods_supported [string]

Required: List of OAuth 2.0 Proof Key for Code Exchange (PKCE) code challenge methods that the server supports at the authorization endpoint.

This array MUST contain at least the S256 value, for improved security in the authorization code grant.

device_authorization_endpoint URI

URL of the device authorization endpoint, as defined in RFC 8628, necessary to use the device authorization grant.

Added in v1.18

grant_types_supported [string]

Required: List of OAuth 2.0 grant type strings that the server supports at the token endpoint.

This array MUST contain at least the authorization_code and refresh_token values, for clients to be able to use the authorization code grant and refresh token grant, respectively.

[Added in v1.18] It MAY also contain urn:ietf:params:oauth:grant-type:device_code to indicate support for the device authorization grant.

issuer URI

Required: The authorization server’s issuer identifier, which is a URL that uses the https scheme and has no query or fragment components.

This is not used in the context of the Matrix specification, but is required by RFC 8414.

prompt_values_supported [string]

List of OpenID Connect prompt values that the server supports at the authorization endpoint.

Only the create value defined in Initiating User Registration via OpenID Connect is supported, for a client to signal to the server that the user desires to register a new account.

registration_endpoint URI

Required: URL of the client registration endpoint, necessary to perform dynamic registration of a client.

response_modes_supported [string]

Required: List of OAuth 2.0 response mode strings that the server supports at the authorization endpoint.

This array MUST contain at least the query and fragment values, for improved security in the authorization code grant.

response_types_supported [string]

Required: List of OAuth 2.0 response type strings that the server supports at the authorization endpoint.

This array MUST contain at least the code value, for clients to be able to use the authorization code grant.

revocation_endpoint URI

Required: URL of the revocation endpoint, necessary to log out a client by invalidating its access and refresh tokens.

token_endpoint URI

Required: URL of the token endpoint, used by the grants.

{
  "account_management_actions_supported": [
    "org.matrix.profile",
    "org.matrix.devices_list",
    "org.matrix.device_view",
    "org.matrix.device_delete",
    "org.matrix.account_deactivate",
    "org.matrix.cross_signing_reset"
  ],
  "account_management_uri": "https://account.example.com/manage",
  "authorization_endpoint": "https://account.example.com/oauth2/auth",
  "code_challenge_methods_supported": [
    "S256"
  ],
  "device_authorization_endpoint": "https://account.example.com/oauth2/device",
  "grant_types_supported": [
    "authorization_code",
    "refresh_token",
    "urn:ietf:params:oauth:grant-type:device_code"
  ],
  "issuer": "https://account.example.com/",
  "registration_endpoint": "https://account.example.com/oauth2/clients/register",
  "response_modes_supported": [
    "query",
    "fragment"
  ],
  "response_types_supported": [
    "code"
  ],
  "revocation_endpoint": "https://account.example.com/oauth2/revoke",
  "token_endpoint": "https://account.example.com/oauth2/token"
}

404 response

Error
Name Type Description
errcode string

Required: An error code.

error string

A human-readable error message.

{
  "errcode": "M_UNRECOGNIZED",
  "error": "Legacy authentication is in use on this homeserver."
}

Client registration

Before being able to use the authorization flow to obtain an access token, a client needs to obtain a client_id by registering itself with the server.

This should be done via OAuth 2.0 Dynamic Client Registration as defined in RFC 7591.

Client metadata

In OAuth 2.0, clients register a set of metadata values with the authorization server, which associates it with a newly generated client_id. These values are used to describe the client to the user and define how the client interacts with the server.

OAuthClientMetadata


This definition of the metadata specifies only the fields that are meaningful in the context of the Matrix specification. All the possible values are registered in the OAuth Dynamic Client Registration Metadata registry, and normative definitions of them are available in their respective RFCs.

OAuthClientMetadata
Name Type Description
application_type string

Kind of the application.

The homeserver MUST support the web and native values to be able to perform redirect URI validation.

Defaults to web if omitted.

client_name string

Human-readable name of the client to be presented to the user.

This field can be localized.

client_uri URI

Required: A URL to a valid web page that SHOULD give the user more information about the client.

This URL MUST use the https scheme and SHOULD NOT require authentication to access. It MUST NOT use a user or password in the authority component of the URI.

The server MAY reject client registrations if this field is invalid or missing.

This URI is a common base for all the other URIs in the metadata: those MUST be either on the same host or on a subdomain of the host of the client_uri. The port number, path and query components MAY be different.

For example, if the client_uri is https://example.com/, then one of the redirect_uris can be https://example.com/callback or https://app.example.com/callback, but not https://app.com/callback.

grant_types [string]

Array of the OAuth 2.0 grant types that the client may use.

This MUST include:

  • the authorization_code value to use the authorization code grant,
  • the refresh_token value to use the refresh token grant.

The server MUST ignore values that it does not understand.

logo_uri URI

URL that references a logo for the client.

This URL MUST use the https scheme.

This field can be localized.

policy_uri URI

URL that points to a human-readable policy document for the client.

This URL MUST use the https scheme and SHOULD NOT require authentication to access. It MUST NOT use a user or password in the authority component of the URI.

If this field is set, the server SHOULD show or link to this URL.

This field can be localized.

redirect_uris [URI]

Array of redirection URIs for use in redirect-based flows.

At least one URI is required to use the authorization code grant.

The server MUST perform validation on redirect URIs.

response_types [string]

Array of the OAuth 2.0 response types that the client may use.

This MUST include the code value to use the authorization code grant.

The server MUST ignore values that it does not understand.

token_endpoint_auth_method string

String indicator of the requested authentication method for the token endpoint.

The homeserver MUST support the none value, as most Matrix clients are client-side only, do not have a server component, and therefore are public clients.

tos_uri URI

URL that points to a human-readable terms of service document for the client.

This URL MUST use the https scheme and SHOULD NOT require authentication to access. It MUST NOT use a user or password in the authority component of the URI.

If this field is set, the server SHOULD show or link to this URL.

This field can be localized.

Metadata localization

As per RFC 7591 section 2.2, all the human-readable metadata values MAY be localized.

The human-readable values include:

  • client_name
  • logo_uri
  • tos_uri
  • policy-uri

For example:

{
  "client_name": "Digital mailbox",
  "client_name#en-US": "Digital mailbox",
  "client_name#en-GB": "Digital postbox",
  "client_name#fr": "Boîte aux lettres numérique",
  "tos_uri": "https://example.com/tos.html",
  "tos_uri#fr": "https://example.com/fr/tos.html",
  "policy_uri": "https://example.com/policy.html",
  "policy_uri#fr": "https://example.com/fr/policy.html"
}
Redirect URI validation

The redirect URI plays a critical role in validating the authenticity of the client. The client “proves” its identity by demonstrating that it controls the redirect URI. This is why it is critical to have strict validation of the redirect URI.

The application_type metadata is used to determine the type of client.

In all cases, the redirect URI MUST NOT have a fragment component.

Web clients

web clients can use redirect URIs that:

  • MUST use the https scheme.
  • MUST NOT use a user or password in the authority component of the URI.
  • MUST use the client URI as a common base for the authority component, as defined previously.
  • MAY include an application/x-www-form-urlencoded formatted query component.

For example, with https://example.com/ as the client URI, the following are valid redirect URIs:

  • https://example.com/callback
  • https://app.example.com/callback
  • https://example.com:5173/?query=value

With the same client URI, the following are invalid redirect URIs:

  • https://example.com/callback#fragment
  • http://example.com/callback
  • http://localhost/

Native clients

native clients can use three types of redirect URIs:

  1. Private-Use URI Scheme

    • The scheme MUST be prefixed with the client URI hostname in reverse-DNS notation. For example, if the client URI is https://example.com/, then a valid custom URI scheme would be com.example.app:/.
    • There MUST NOT be an authority component. This means that the URI MUST have either a single slash or none immediately following the scheme, with no hostname, username, or port.
  2. http URI on the loopback interface

    • The scheme MUST be http.
    • The host part MUST be localhost, 127.0.0.1, or [::1].
    • There MUST NOT be a port. The homeserver MUST then accept any port number during the authorization flow.
  3. Claimed https Scheme URI

    Some operating systems allow apps to claim https scheme URIs in the domains they control. When the browser encounters a claimed URI, instead of the page being loaded in the browser, the native app is launched with the URI supplied as a launch parameter. The same rules as for web clients apply.

These restrictions are the same as defined by RFC 8252 section 7.

For example, with https://example.com/ as the client URI,

These are valid redirect URIs:

  • com.example.app:/callback
  • com.example:/
  • com.example:callback
  • http://localhost/callback
  • http://127.0.0.1/callback
  • http://[::1]/callback

These are invalid redirect URIs:

  • example:/callback
  • com.example.app://callback
  • https://localhost/callback
  • http://localhost:1234/callback
Dynamic client registration flow

To register, the client sends an HTTP POST request to the registration_endpoint, which can be found in the server metadata. The body of the request is the JSON-encoded OAuthClientMetadata.

For example, the client could send the following registration request:

POST /register HTTP/1.1
Content-Type: application/json
Accept: application/json
Server: auth.example.com
{
  "client_name": "My App",
  "client_name#fr": "Mon application",
  "client_uri": "https://example.com/",
  "logo_uri": "https://example.com/logo.png",
  "tos_uri": "https://example.com/tos.html",
  "tos_uri#fr": "https://example.com/fr/tos.html",
  "policy_uri": "https://example.com/policy.html",
  "policy_uri#fr": "https://example.com/fr/policy.html",
  "redirect_uris": ["https://app.example.com/callback"],
  "token_endpoint_auth_method": "none",
  "response_types": ["code"],
  "grant_types": [
    "authorization_code",
    "refresh_token",
    "urn:ietf:params:oauth:grant-type:token-exchange"
  ],
  "application_type": "web"
}

Upon successful registration, the server replies with an HTTP 201 Created response, with a JSON object containing the allocated client_id and all the registered metadata values.

With the registration request above, the server might reply with:

{
  "client_id": "s6BhdRkqt3",
  "client_name": "My App",
  "client_uri": "https://example.com/",
  "logo_uri": "https://example.com/logo.png",
  "tos_uri": "https://example.com/tos.html",
  "policy_uri": "https://example.com/policy.html",
  "redirect_uris": ["https://app.example.com/callback"],
  "token_endpoint_auth_method": "none",
  "response_types": ["code"],
  "grant_types": ["authorization_code", "refresh_token"],
  "application_type": "web"
}

In this example, the server has not registered the locale-specific values for client_name, tos_uri, and policy_uri, which is why they are not present in the response. The server also does not support the urn:ietf:params:oauth:grant-type:token-exchange grant type, which is why it is not present in the response.

The client MUST store the client_id for future use.

To avoid the number of client registrations growing over time, the server MAY choose to delete client registrations that don’t have an active session. The server MUST NOT delete client registrations that have an active session.

Clients MUST perform a new client registration at the start of each authorization flow.

Because each client on each user device will do its own registration, they may all have different client_ids. This means that the server may store the same client registration multiple times, which could lead to a large number of client registrations.

This can be mitigated by de-duplicating client registrations that have identical metadata. By doing so, different users on different devices using the same client can share a single client_id, reducing the overall number of registrations.

Scope

The client requests a scope in the OAuth 2.0 authorization flow, which is then associated to the generated access and refresh tokens. This provides a framework for obtaining user consent.

A scope is defined in RFC 6749 section 3.3 as a string containing a list of space-separated scope tokens.

The framework encourages the practice of obtaining additional user consent when a client asks for a new scope that was not granted previously. This could be used by future MSCs to replace the legacy User-Interactive Authentication API.

Scope token format

All scope tokens related to Matrix should start with urn:matrix: and use the : delimiter for further sub-division.

Scope tokens related to mapping of Client-Server API access levels should start with urn:matrix:client:.

For MSCs that build on this namespace, unstable subdivisions should be used whilst in development. For example, if MSCXXXX wants to introduce the urn:matrix:client:foo scope, it could use urn:matrix:client:com.example.mscXXXX.foo during development. If it needs to introduce multiple scopes, like urn:matrix:client:foo and urn:matrix:client:bar, it could use urn:matrix:client:com.example.mscXXXX:foo and urn:matrix:client:com.example.mscXXXX:bar.

Allocated scope tokens

This specification defines the following scope tokens:

Full client-server API read/write access
Scope Purpose
urn:matrix:client:api:* Grants full access to the Client-Server API.

This token matches the behavior of the legacy authentication API. Future MSCs could introduce more fine-grained scope tokens like urn:matrix:client:api:read:* for read-only access.

Device ID allocation
Scope Purpose
urn:matrix:client:device:<device_id> Allocates the given device_id and associates it to the generated access and refresh tokens.

Contrary to the legacy login and registration APIs where the homeserver is typically the one generating a device_id and providing it to the client, with the OAuth 2.0 API, the client is responsible for allocating the device_id.

There MUST be exactly one urn:matrix:client:device:<device_id> token in the requested scope in the login flow.

When generating a new device_id, the client SHOULD generate a random string with enough entropy. It SHOULD only use characters from the unreserved character list defined by RFC 3986 section 2.3:

unreserved = a-z / A-Z / 0-9 / "-" / "." / "_" / "~"

Using this alphabet, a 10 character string is enough to stand a sufficient chance of being unique per user. The homeserver MAY reject a request for a device_id that is not long enough or contains characters outside the unreserved list.

In any case it MUST only use characters allowed by the OAuth 2.0 scope definition in RFC 6749 section 3.3, which is defined as the following ASCII ranges:

%x21 / %x23-5B / %x5D-7E

This definition matches:

  • alphanumeric characters: A-Z, a-z, 0-9
  • the following characters: ! # $ % & ' ( ) * + , - . / : ; < = > ? @ [ ] ^ _ ` { | } ~

Grant types

RFC 6749 and other RFCs define several “grant types”: ways to obtain an “access token”.

All these grants types require the client to know the following authorization server metadata:

  • token_endpoint
  • grant_types_supported

The client must also have obtained a client_id by registering with the server.

This specification supports the following grant types:

Authorization code grant

As per RFC 6749 section 4.1, the authorization code grant lets the client obtain an access token through a browser redirect.

This grant requires the client to know the following authorization server metadata:

  • authorization_endpoint
  • response_types_supported
  • response_mode_supported

To use this grant, homeservers and clients MUST:

Device authorization grant

[Added in v1.18]

As per RFC 8628, the device authorization grant lets clients on devices with limited input capabilities obtain an access token by having the user complete authorization on a separate device with a web browser.

This grant requires the client to know the following authorization server metadata:

  • device_authorization_endpoint

To use this grant, homeservers and clients MUST:

As with the authorization code grant, when authorization is granted to a client, the homeserver MUST issue a refresh token to the client in addition to the access token. The access token and refresh token have the same lifetime constraints as described in the refresh token grant section.

The full flow for using this grant is described in the device authorization flow.

Refresh token grant

As per RFC 6749 section 6, the refresh token grant lets the client exchange a refresh token for an access token.

When authorization is granted to a client, the homeserver MUST issue a refresh token to the client in addition to the access token.

The access token MUST be short-lived and SHOULD be refreshed using the refresh_token when expired.

The homeserver SHOULD issue a new refresh token each time an old one is used, and invalidate the old one. However, it MUST ensure that the client is able to retry the refresh request in the case that the response to the request is lost.

The homeserver SHOULD consider that the session is compromised if an old, invalidated refresh token is used, and SHOULD revoke the session.

The client MUST handle access token refresh failures as follows:

  • If the refresh fails due to network issues or a 5xx HTTP status code from the server, the client should retry the request with the old refresh token later.
  • If the refresh fails due to a 4xx HTTP status code from the server, the client should consider the session logged out.

Token revocation

When a user wants to log out from a client, the client SHOULD use OAuth 2.0 token revocation as defined in RFC 7009.

The client makes a POST request to the revocation_endpoint that can be found in the authorization server metadata.

The body of the request includes the following parameters, encoded as application/x-www-form-urlencoded:

Parameter Value
token Required. MUST contain either the access token or the refresh token to be revoked.
token_type_hint Optional. If present, MUST have a value of either access_token or refresh_token. The server MAY use this value to optimize the token lookup process.
client_id

Optional. The client identifier obtained during client registration.

If the client_id is not provided, or does not match the client associated with the token, the server SHOULD still revoke the token. This behavior is meant to help good actors like secret scanning tools to proactively revoke leaked tokens. The server MAY also warn the user that one of their sessions may be compromised in this scenario.

For example, revoking using the access token:

POST /oauth2/revoke HTTP/1.1
Host: auth.example.com
Content-Type: application/x-www-form-urlencoded

token=mat_ooreiPhei2wequu9fohkai3AeBaec9oo&
token_type_hint=access_token&
client_id=s6BhdRkqt3

The server MUST revoke both the access token and refresh token associated with the token provided in the request.

The server SHOULD return one of the following responses:

  • If the token is already revoked or invalid, the server returns a 200 OK response
  • If the client is not authorized to revoke the token, the server returns a 401 Unauthorized response
  • For other errors, the server returns a 400 Bad Request response with error details

User registration

Clients can signal to the server that the user desires to register a new account by initiating the authorization code grant with the prompt=create parameter set in the authorization request as defined in Initiating User Registration via OpenID Connect 1.0.

Whether the homeserver supports this parameter is advertised by the prompt_values_supported authorization server metadata.

Servers that support this parameter SHOULD show the account registration UI in the browser.

The prompt=create parameter is not supported when using the device authorization grant.

Account management

[Added in v1.18]

All account management is done via the homeserver’s web UI.

This specification defines extensions to the OAuth Authorization Server Metadata registry to offer clients a way to deep-link to the account management capabilities of the homeserver to allow the user to complete the account management operations in a browser.

Account management URL discovery

The OAuth 2.0 authorization server metadata is extended to include the following optional fields.

OAuth 2.0 Server Metadata Account Management Extension


OAuth 2.0 Server Metadata Account Management Extension
Name Type Description
account_management_actions_supported [string]

List of actions that the account management URL supports.

account_management_uri URI

The URL where the user is able to access the account management capabilities of the server.

Account management URL parameters

The account management URL MAY accept the following minimum query parameters.

OAuth 2.0 Account Management URL Query Parameters


OAuth 2.0 Account Management URL Query Parameters
Name Type Description
action string

The action that the user wishes to take. Must match one of the actions advertised by the server in account_management_actions_supported.

device_id string

For Matrix-specific actions, the user’s device ID. Actions which don’t support the device ID will ignore it.

If the org.matrix.device_view or org.matrix.device_delete actions are advertised as supported by the server then the server SHOULD support the device_id parameter.

Account management URL actions

Account management actions are unique to the application. They SHOULD follow the Common Namespaced Identifier Grammar where feasible. The Matrix-specific actions are:

Action Description
org.matrix.profile The user wishes to view/edit their profile (name, avatar, contact details).
org.matrix.devices_list The user wishes to view a list of their devices.
org.matrix.device_view The user wishes to view the details of a specific device. A device_id SHOULD be provided.
org.matrix.device_delete The user wishes to delete/log out a specific device. A device_id SHOULD be provided.
org.matrix.account_deactivate The user wishes to deactivate their account.
org.matrix.cross_signing_reset The user wishes to reset their cross-signing identity. Servers SHOULD use this action in the URL of the m.oauth UIA type.

Account moderation

Account locking

[Added in v1.12]

Server administrators may apply locks to prevent users from usefully using their accounts, for instance, due to safety or security concerns. In contrast to account deactivation, locking is a non-destructive action that can be reversed.

[Added in v1.18] To lock or unlock an account, administrators SHOULD use the PUT /admin/lock/{userId} endpoint. They MAY also use GET /admin/lock/{userId} to check whether a user’s account is locked.

When an account is locked, servers MUST return a 401 Unauthorized error response with an M_USER_LOCKED error code and soft_logout set to true on all but the following Client-Server APIs:

Servers MAY additionally include details of why the lock was applied in the error field.

HTTP/1.1 401 Unauthorized
Content-Type: application/json
{
  "errcode": "M_USER_LOCKED",
  "error": "This account has been locked",
  "soft_logout": true
}

Servers SHOULD NOT invalidate access tokens on locked accounts unless the client requests a logout (using the above endpoints). This ensures that users can retain their sessions without having to log back in if the account becomes unlocked.

Upon receiving an M_USER_LOCKED error, clients SHOULD retain session information including encryption state and inform the user that their account has been locked. While the lock is applied, clients SHOULD hide the normal UI from the user, preventing general use of their account. Clients SHOULD, however, continue to make rate-limited requests to /sync and other APIs to detect when the lock has been lifted.

To enable users to appeal to a lock clients MAY use server contact discovery.

Account suspension

[Added in v1.13]

Server administrators MAY suspend a user’s account to prevent further activity from that account. The effect is similar to locking, though without risk of the client losing state from a logout. Suspensions are reversible, like locks and unlike deactivations.

[Added in v1.18] To suspend or unsuspend an account, administrators SHOULD use the PUT /admin/suspend/{userId} endpoint. They MAY also use GET /admin/suspend/{userId} to check whether a user’s account is suspended.

The actions a user can perform while suspended is deliberately left as an implementation detail. Servers SHOULD permit the user to perform at least the following, however:

General purpose endpoints like /send/{eventType} MAY return the error described below depending on the path parameters. For example, a user may be allowed to send m.room.redaction events but not m.room.message events through /send.

Where a room is used to maintain communication between server administration teams and the suspended user, servers are recommended to allow the user to send events to that room specifically. Server administrators which do not want the user to continue receiving messages may be interested in account locking instead.

Otherwise, the recommended set of explicitly forbidden actions is:

When a client attempts to perform an action while suspended, the server MUST respond with a 403 Forbidden error response with M_USER_SUSPENDED as the error code, as shown below:

HTTP/1.1 403 Forbidden
Content-Type: application/json
{
  "errcode": "M_USER_SUSPENDED",
  "error": "You cannot perform this action while suspended."
}

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.

This section deals with two terms: “add” and “bind”. Where “add” (or “remove”) is used, it is speaking about an identifier that was not bound to an identity server. As a result, “bind” (or “unbind”) references an identifier that is found in an identity server. Note that an identifier can be added and bound at the same time, depending on context.

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 string

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


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

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.

This endpoint uses capabilities negotiation. Clients SHOULD check the value of the m.3pid_changes capability to determine if this endpoint is available.

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 URI

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.

This endpoint uses capabilities negotiation. Clients SHOULD check the value of the m.3pid_changes capability to determine if this endpoint is available.

Since this endpoint uses User-Interactive Authentication, it cannot be used when the access token was obtained via the OAuth 2.0 API.

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

<Other properties>

Keys dependent on the login type

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 {string: 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.

This endpoint uses capabilities negotiation. Clients SHOULD check the value of the m.3pid_changes capability to determine if this endpoint is available.

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 string

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 string

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 Email Address

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 URI

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. Error codes that can be returned are:

  • M_THREEPID_IN_USE: The email supplied cannot be bound because is is already associated with a different Matrix ID.
  • M_SERVER_NOT_TRUSTED: The server does not trust/support the identity server provided in the request.
  • M_THREEPID_MEDIUM_NOT_SUPPORTED: The homeserver does not support adding email addresses.
  • M_INVALID_PARAM: The email address given was not valid.
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 URI

An optional field containing a URL where the client must submit the validation token, with identical request and response parameters and error codes to the Identity Service API’s POST /validate/email/submitToken and