Newer
Older
Matrix Specification
====================
The Matrix specification is still very much evolving: the API is not yet frozen
and this document is in places incomplete, stale, and may contain security
issues. Needless to say, we have made every effort to highlight the problem
areas that we're aware of.
We're publishing it at this point because it's complete enough to be more than
useful and provide a canonical reference to how Matrix is evolving. Our end
goal is to mirror WHATWG's `Living Standard <http://wiki.whatwg.org/wiki/FAQ#What_does_.22Living_Standard.22_mean.3F>`_
approach except right now Matrix is more in the process of being born than actually being
Matrix is a new set of open APIs for open-federated Instant Messaging and VoIP
functionality, designed to create and support a new global real-time
communication ecosystem on the internet. This specification is the ongoing
result of standardising the APIs used by the various components of the Matrix
ecosystem to communicate with one another.
The principles that Matrix attempts to follow are:
- Pragmatic Web-friendly APIs (i.e. JSON over REST)
- Keep It Simple & Stupid
+ provide a simple architecture with minimal third-party dependencies.
+ Fully open federation - anyone should be able to participate in the global
Matrix network
+ Fully open standard - publicly documented standard with no IP or patent
licensing encumbrances
+ Fully open source reference implementation - liberally-licensed example
implementations with no IP or patent licensing encumbrances
- Empowering the end-user
+ The user should be able to choose the server and clients they use
+ The user should be control how private their communication is
+ The user should know precisely where their data is stored
- Fully decentralised - no single points of control over conversations or the
network as a whole
- Learning from history to avoid repeating it
+ Trying to take the best aspects of XMPP, SIP, IRC, SMTP, IMAP and NNTP
whilst trying to avoid their failings
The functionality that Matrix provides includes:
- Creation and management of fully distributed chat rooms with no
single points of control or failure
- Eventually-consistent cryptographically secure synchronisation of room
state across a global open network of federated servers and services
- Sending and receiving extensible messages in a room with (optional)
end-to-end encryption
- Extensible user management (inviting, joining, leaving, kicking, banning)
mediated by a power-level based user privilege system.
- Extensible room state management (room naming, aliasing, topics, bans)
- Extensible user profile management (avatars, displaynames, etc)
- Managing user accounts (registration, login, logout)
- Use of 3rd Party IDs (3PIDs) such as email addresses, phone numbers,
Facebook accounts to authenticate, identify and discover users on Matrix.
- Trusted federation of Identity servers for:
+ Publishing user public keys for PKI
+ Mapping of 3PIDs to Matrix IDs
The end goal of Matrix is to be a ubiquitous messaging layer for synchronising
arbitrary data between sets of people, devices and services - be that for
instant messages, VoIP call setups, or any other objects that need to be
reliably and persistently pushed from A to B in an interoperable and federated
manner.
Architecture
Kegan Dougal
committed
Clients transmit data to other clients through home servers (HSes). Clients do
not communicate with each other directly.
Kegan Dougal
committed
How data flows between clients
==============================
{ Matrix client A } { Matrix client B }
^ | ^ |
| events | | events |
| V | V
+------------------+ +------------------+
| |---------( HTTP )---------->| |
| Home Server | | Home Server |
| |<--------( HTTP )-----------| |
Kegan Dougal
committed
+------------------+ Federation +------------------+
A "Client" typically represents a human using a web application or mobile app.
Clients use the "Client-to-Server" (C-S) API to communicate with their home
server, which stores their profile data and their record of the conversations
in which they participate. Each client is associated with a user account (and
may optionally support multiple user accounts). A user account is represented
by a unique "User ID". This ID is namespaced to the home server which allocated
the account and looks like::
Kegan Dougal
committed
@localpart:domain
The ``localpart`` of a user ID may be a user name, or an opaque ID identifying
this user. They are case-insensitive.
Kegan Dougal
committed
Paul "LeoNerd" Evans
committed
.. TODO-spec
- Need to specify precise grammar for Matrix IDs
A "Home Server" is a server which provides C-S APIs and has the ability to
federate with other HSes. It is typically responsible for multiple clients.
"Federation" is the term used to describe the sharing of data between two or
more home servers.
Data in Matrix is encapsulated in an "event". An event is an action within the
system. Typically each action (e.g. sending a message) correlates with exactly
one event. Each event has a ``type`` which is used to differentiate different
kinds of data. ``type`` values MUST be uniquely globally namespaced following
Java's `package naming conventions
<http://docs.oracle.com/javase/specs/jls/se5.0/html/packages.html#7.7>`, e.g.
``com.example.myapp.event``. The special top-level namespace ``m.`` is reserved
for events defined in the Matrix specification. Events are usually sent in the
context of a "Room".
Kegan Dougal
committed
Room structure
A room is a conceptual place where users can send and receive events. Rooms can
be created, joined and left. Events are sent to a room, and all participants in
that room with sufficient access will receive the event. Rooms are uniquely
identified internally via a "Room ID", which look like::
Kegan Dougal
committed
Kegan Dougal
committed
!opaque_id:domain
Kegan Dougal
committed
Kegan Dougal
committed
There is exactly one room ID for each room. Whilst the room ID does contain a
domain, it is simply for globally namespacing room IDs. The room does NOT
reside on the domain specified. Room IDs are not meant to be human readable.
They ARE case-sensitive.
Kegan Dougal
committed
Kegan Dougal
committed
The following diagram shows an ``m.room.message`` event being sent in the room
``!qporfwt:matrix.org``::
Kegan Dougal
committed
{ @alice:matrix.org } { @bob:domain.com }
| ^
| |
Room ID: !qporfwt:matrix.org Room ID: !qporfwt:matrix.org
Event type: m.room.message Event type: m.room.message
Content: { JSON object } Content: { JSON object }
| |
V |
Kegan Dougal
committed
+------------------+ +------------------+
| Home Server | | Home Server |
| matrix.org |<-------Federation------->| domain.com |
+------------------+ +------------------+
| ................................. |
Kegan Dougal
committed
| Room ID: !qporfwt:matrix.org |
Kegan Dougal
committed
| Servers: matrix.org, domain.com |
| Members: |
| - @alice:matrix.org |
| - @bob:domain.com |
|.................................|
Federation maintains shared state between multiple home servers, such that when
an event is sent to a room, the home server knows where to forward the event on
to, and how to process the event. State is scoped to a single room, and
federation ensures that all home servers have the information they need, even
if that means the home server has to request more information from another home
server before processing the event.
Kegan Dougal
committed
Room Aliases
Kegan Dougal
committed
Each room can also have multiple "Room Aliases", which looks like::
#room_alias:domain
- Need to specify precise grammar for Room Aliases
A room alias "points" to a room ID and is the human-readable label by which
rooms are publicised and discovered. The room ID the alias is pointing to can
be obtained by visiting the domain specified. They are case-insensitive. Note
that the mapping from a room alias to a room ID is not fixed, and may change
over time to point to a different room ID. For this reason, Clients SHOULD
resolve the room alias to a room ID once and then use that ID on subsequent
requests.
Kegan Dougal
committed
When resolving a room alias the server will also respond with a list of servers
that are in the room that can be used to join via.
Kegan Dougal
committed
::
GET
#matrix:domain.com !aaabaa:matrix.org
| ^
| |
_______V____________________|____
| domain.com |
| Mappings: |
| #matrix >> !aaabaa:matrix.org |
| #golf >> !wfeiofh:sport.com |
| #bike >> !4rguxf:matrix.org |
Kegan Dougal
committed
|________________________________|
Kegan Dougal
committed
Identity
Users in Matrix are identified via their user ID. However, existing ID
namespaces can also be used in order to identify Matrix users. A Matrix
"Identity" describes both the user ID and any other existing IDs from third
party namespaces *linked* to their account.
Matrix users can *link* third-party IDs (3PIDs) such as email addresses, social
network accounts and phone numbers to their user ID. Linking 3PIDs creates a
mapping from a 3PID to a user ID. This mapping can then be used by other Matrix
users in order to discover other users, according to a strict set of privacy
permissions.
In order to ensure that the mapping from 3PID to user ID is genuine, a globally
federated cluster of trusted "Identity Servers" (IS) are used to perform
authentication of the 3PID. Identity servers are also used to preserve the
mapping indefinitely, by replicating the mappings across multiple ISes.
Usage of an IS is not required in order for a client application to be part of
the Matrix ecosystem. However, without one clients will not be able to look up
user IDs using 3PIDs.
Kegan Dougal
committed
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
Presence
~~~~~~~~
.. NOTE::
This section is a work in progress.
Each user has the concept of presence information. This encodes the
"availability" of that user, suitable for display on other user's clients. This
is transmitted as an ``m.presence`` event and is one of the few events which
are sent *outside the context of a room*. The basic piece of presence
information is represented by the ``presence`` key, which is an enum of one of
the following:
- ``online`` : The default state when the user is connected to an event
stream.
- ``unavailable`` : The user is not reachable at this time.
- ``offline`` : The user is not connected to an event stream.
- ``free_for_chat`` : The user is generally willing to receive messages
moreso than default.
- ``hidden`` : Behaves as offline, but allows the user to see the client
state anyway and generally interact with client features. (Not yet
implemented in synapse).
This basic ``presence`` field applies to the user as a whole, regardless of how
many client devices they have connected. The home server should synchronise
this status choice among multiple devices to ensure the user gets a consistent
experience.
In addition, the server maintains a timestamp of the last time it saw an active
action from the user; either sending a message to a room, or changing presence
state from a lower to a higher level of availability (thus: changing state from
``unavailable`` to ``online`` will count as an action for being active, whereas
in the other direction will not). This timestamp is presented via a key called
``last_active_ago``, which gives the relative number of miliseconds since the
message is generated/emitted, that the user was last seen active.
Home servers can also use the user's choice of presence state as a signal for
how to handle new private one-to-one chat message requests. For example, it
might decide:
- ``free_for_chat`` : accept anything
- ``online`` : accept from anyone in my addres book list
- ``busy`` : accept from anyone in this "important people" group in my
address book list
Presence List
+++++++++++++
Each user's home server stores a "presence list" for that user. This stores a
list of other user IDs the user has chosen to add to it. To be added to this
list, the user being added must receive permission from the list owner. Once
granted, both user's HS(es) store this information. Since such subscriptions
are likely to be bidirectional, HSes may wish to automatically accept requests
when a reverse subscription already exists.
As a convenience, presence lists should support the ability to collect users
into groups, which could allow things like inviting the entire group to a new
("ad-hoc") chat room, or easy interaction with the profile information ACL
implementation of the HS.
Presence and Permissions
++++++++++++++++++++++++
For a viewing user to be allowed to see the presence information of a target
user, either:
- The target user has allowed the viewing user to add them to their presence
list, or
- The two users share at least one room in common
In the latter case, this allows for clients to display some minimal sense of
presence information in a user list for a room.
Profiles
~~~~~~~~
.. NOTE::
This section is a work in progress.
.. TODO-spec
- Metadata extensibility
Internally within Matrix users are referred to by their user ID, which is
typically a compact unique identifier. Profiles grant users the ability to see
human-readable names for other users that are in some way meaningful to them.
Additionally, profiles can publish additional information, such as the user's
age or location.
A Profile consists of a display name, an avatar picture, and a set of other
metadata fields that the user may wish to publish (email address, phone
numbers, website URLs, etc...). This specification puts no requirements on the
display name other than it being a valid unicode string. Avatar images are not
stored directly; instead the home server stores an ``http``-scheme URL where
clients may fetch it from.
Kegan Dougal
committed
API Standards
-------------
The mandatory baseline for communication in Matrix is exchanging JSON objects
over RESTful HTTP APIs. HTTPS is mandated as the baseline for server-server
(federation) communication. HTTPS is recommended for client-server
communication, although HTTP may be supported as a fallback to support basic
HTTP clients. More efficient optional transports for client-server
communication will in future be supported as optional extensions - e.g. a
packed binary encoding over stream-cipher encrypted TCP socket for
low-bandwidth/low-roundtrip mobile usage.
.. TODO
We need to specify capability negotiation for extensible transports
For the default HTTP transport, all API calls use a Content-Type of
``application/json``. In addition, all strings MUST be encoded as UTF-8.
Clients are authenticated using opaque ``access_token`` strings (see
Paul "LeoNerd" Evans
committed
`Registration and Login`_ for details), passed as a query string parameter on
all requests.
.. TODO
Need to specify any HMAC or access_token lifetime/ratcheting tricks
Any errors which occur on the Matrix API level MUST return a "standard error
response". This is a JSON object which looks like::
{
"errcode": "<error code>",
"error": "<error message>"
}
The ``error`` string will be a human-readable error message, usually a sentence
explaining what went wrong. The ``errcode`` string will be a unique string
which can be used to handle an error message e.g. ``M_FORBIDDEN``. These error
codes should have their namespace first in ALL CAPS, followed by a single _.
For example, if there was a custom namespace ``com.mydomain.here``, and a
``FORBIDDEN`` code, the error code should look like
``COM.MYDOMAIN.HERE_FORBIDDEN``. There may be additional keys depending on the
error, but the keys ``error`` and ``errcode`` MUST always be present.
Some standard error codes are below:
:``M_FORBIDDEN``:
Forbidden access, e.g. joining a room without permission, failed login.
:``M_UNKNOWN_TOKEN``:
The access token specified was not recognised.
:``M_BAD_JSON``:
Request contained valid JSON, but it was malformed in some way, e.g. missing
required keys, invalid values for keys.
:``M_NOT_JSON``:
Request did not contain valid JSON.
:``M_NOT_FOUND``:
No resource was found for this request.
Kegan Dougal
committed
:``M_LIMIT_EXCEEDED``:
Too many requests have been sent in a short period of time. Wait a while then
try again.
Some requests have unique error codes:
:``M_USER_IN_USE``:
Encountered when trying to register a user ID which has been taken.
:``M_ROOM_IN_USE``:
Encountered when trying to create a room which has been taken.
:``M_BAD_PAGINATION``:
Encountered when specifying bad pagination query parameters.
:``M_LOGIN_EMAIL_URL_NOT_YET``:
Encountered when polling for an email link which has not been clicked yet.
The C-S API typically uses ``HTTP POST`` to submit requests. This means these
requests are not idempotent. The C-S API also allows ``HTTP PUT`` to make
requests idempotent. In order to use a ``PUT``, paths should be suffixed with
``/{txnId}``. ``{txnId}`` is a unique client-generated transaction ID which
identifies the request, and is scoped to a given Client (identified by that
client's ``access_token``). Crucially, it **only** serves to identify new
requests from retransmits. After the request has finished, the ``{txnId}``
value should be changed (how is not specified; a monotonically increasing
integer is recommended). It is preferable to use ``HTTP PUT`` to make sure
requests to send messages do not get sent more than once should clients need to
retransmit requests.
POST /some/path/here?access_token=secret
PUT /some/path/here/11?access_token=secret
{
"key": "This is a put with a txnId of 11."
}
In contrast, these are invalid requests::
POST /some/path/here/11?access_token=secret
{
"key": "This is a post, but it has a txnId."
}
PUT /some/path/here?access_token=secret
{
"key": "This is a put but it is missing a txnId."
}
Kegan Dougal
committed
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
Glossary
--------
.. NOTE::
This section is a work in progress.
Backfilling:
The process of synchronising historic state from one home server to another,
to backfill the event storage so that scrollback can be presented to the
client(s). Not to be confused with pagination.
Context:
A single human-level entity of interest (currently, a chat room)
EDU (Ephemeral Data Unit):
A message that relates directly to a given pair of home servers that are
exchanging it. EDUs are short-lived messages that related only to one single
pair of servers; they are not persisted for a long time and are not forwarded
on to other servers. Because of this, they have no internal ID nor previous
EDUs reference chain.
Event:
A record of activity that records a single thing that happened on to a context
(currently, a chat room). These are the "chat messages" that Synapse makes
available.
PDU (Persistent Data Unit):
A message that relates to a single context, irrespective of the server that
is communicating it. PDUs either encode a single Event, or a single State
change. A PDU is referred to by its PDU ID; the pair of its origin server
and local reference from that server.
PDU ID:
The pair of PDU Origin and PDU Reference, that together globally uniquely
refers to a specific PDU.
PDU Origin:
The name of the origin server that generated a given PDU. This may not be the
server from which it has been received, due to the way they are copied around
from server to server. The origin always records the original server that
created it.
PDU Reference:
A local ID used to refer to a specific PDU from a given origin server. These
references are opaque at the protocol level, but may optionally have some
structured meaning within a given origin server or implementation.
Presence:
The concept of whether a user is currently online, how available they declare
they are, and so on. See also: doc/model/presence
Profile:
A set of metadata about a user, such as a display name, provided for the
benefit of other users. See also: doc/model/profiles
Room ID:
An opaque string (of as-yet undecided format) that identifies a particular
room and used in PDUs referring to it.
Room Alias:
A human-readable string of the form #name:some.domain that users can use as a
pointer to identify a room; a Directory Server will map this to its Room ID
State:
A set of metadata maintained about a Context, which is replicated among the
servers in addition to the history of Events.
User ID:
A string of the form @localpart:domain.name that identifies a user for
wire-protocol purposes. The localpart is meaningless outside of a particular
home server. This takes a human-readable form that end-users can use directly
if they so wish, avoiding the 3PIDs.
Transaction:
A message which relates to the communication between a given pair of servers.
A transaction contains possibly-empty lists of PDUs and EDUs.
.. TODO
This glossary contradicts the terms used above - especially on State Events v. "State"
and Non-State Events v. "Events". We need better consistent names.
Events
======
Kegan Dougal
committed
Receiving live updates on a client
----------------------------------
Clients can receive new events by long-polling the home server. This will hold
open the HTTP connection for a short period of time waiting for new events,
returning early if an event occurs. This is called the `Event Stream`_. All
events which are visible to the client will appear in the event stream. When
the request returns, an ``end`` token is included in the response. This token
can be used in the next request to continue where the client left off.
Paul "LeoNerd" Evans
committed
.. TODO-spec
Do we ever return multiple events in a single request? Don't we get lots of request
setup RTT latency if we only do one event per request? Do we ever support streaming
requests? Why not websockets?
Kegan Dougal
committed
When the client first logs in, they will need to initially synchronise with
their home server. This is achieved via the |initialSync|_ API. This API also
returns an ``end`` token which can be used with the event stream.
Kegan Dougal
committed
Room Events
-----------
.. NOTE::
This section is a work in progress.
This specification outlines several standard event types, all of which are
prefixed with ``m.``
``m.room.name``
Summary:
Set the human-readable name for the room.
Type:
State event
JSON format:
``{ "name" : "string" }``
Example:
``{ "name" : "My Room" }``
Description:
A room has an opaque room ID which is not human-friendly to read. A room
alias is human-friendly, but not all rooms have room aliases. The room name
is a human-friendly string designed to be displayed to the end-user. The
room name is not *unique*, as multiple rooms can have the same room name
set. The room name can also be set when creating a room using |createRoom|_
with the ``name`` key.
``m.room.topic``
Summary:
Set a topic for the room.
Type:
State event
JSON format:
``{ "topic" : "string" }``
Example:
``{ "topic" : "Welcome to the real world." }``
Description:
A topic is a short message detailing what is currently being discussed in
the room. It can also be used as a way to display extra information about
the room, which may not be suitable for the room name. The room topic can
also be set when creating a room using |createRoom|_ with the ``topic``
key.
``m.room.member``
Summary:
The current membership state of a user in the room.
Type:
State event
JSON format:
``{ "membership" : "enum[ invite|join|leave|ban ]" }``
Example:
``{ "membership" : "join" }``
Description:
Adjusts the membership state for a user in a room. It is preferable to use
the membership APIs (``/rooms/<room id>/invite`` etc) when performing
membership actions rather than adjusting the state directly as there are a
restricted set of valid transformations. For example, user A cannot force
user B to join a room, and trying to force this state change directly will
fail. See the `Rooms`_ section for how to use the membership APIs.
``m.room.create``
Summary:
The first event in the room.
Type:
State event
JSON format:
``{ "creator": "string"}``
Example:
``{ "creator": "@user:example.com" }``
Description:
This is the first event in a room and cannot be changed. It acts as the
root of all other events.
Kegan Dougal
committed
``m.room.join_rules``
Summary:
Descripes how/if people are allowed to join.
Type:
State event
JSON format:
``{ "join_rule": "enum [ public|knock|invite|private ]" }``
Example:
``{ "join_rule": "public" }``
Description:
TODO-doc : Use docs/models/rooms.rst
``m.room.power_levels``
Summary:
Defines the power levels of users in the room.
Type:
State event
JSON format:
``{ "<user_id>": <int>, ..., "default": <int>}``
Example:
``{ "@user:example.com": 5, "@user2:example.com": 10, "default": 0 }``
Description:
If a user is in the list, then they have the associated power level.
Otherwise they have the default level. If not ``default`` key is supplied,
it is assumed to be 0.
Kegan Dougal
committed
``m.room.add_state_level``
Summary:
Defines the minimum power level a user needs to add state.
Type:
State event
JSON format:
``{ "level": <int> }``
Example:
``{ "level": 5 }``
Description:
To add a new piece of state to the room a user must have the given power
level. This does not apply to updating current state, which is goverened
by the ``required_power_level`` event key.
Paul "LeoNerd" Evans
committed
``m.room.send_event_level``
Summary:
Defines the minimum power level a user needs to send an event.
Type:
State event
JSON format:
``{ "level": <int> }``
Example:
``{ "level": 0 }``
Description:
To send a new event into the room a user must have at least this power
level. This allows ops to make the room read only by increasing this level,
or muting individual users by lowering their power level below this
threshold.
``m.room.ops_levels``
Summary:
Defines the minimum power levels that a user must have before they can
kick and/or ban other users.
Type:
State event
JSON format:
``{ "ban_level": <int>, "kick_level": <int>, "redact_level": <int> }``
Example:
``{ "ban_level": 5, "kick_level": 5 }``
Description:
This defines who can ban and/or kick people in the room. Most of the time
``ban_level`` will be greater than or equal to ``kick_level`` since
banning is more severe than kicking.
``m.room.aliases``
Summary:
These state events are used to inform the room about what room aliases it
has.
Type:
State event
JSON format:
``{ "aliases": ["string", ...] }``
Example:
``{ "aliases": ["#foo:example.com"] }``
Description:
This event is sent by a homeserver directly to inform of changes to the
list of aliases it knows about for that room. As a special-case, the
``state_key`` of the event is the homeserver which owns the room alias.
For example, an event might look like::
{
"type": "m.room.aliases",
"event_id": "012345678ab",
"room_id": "!xAbCdEfG:example.com",
"state_key": "example.com",
"content": {
"aliases": ["#foo:example.com"]
}
}
The event contains the full list of aliases now stored by the home server
that emitted it; additions or deletions are not explicitly mentioned as
being such. The entire set of known aliases for the room is then the union
of the individual lists declared by all such keys, one from each home
server holding at least one alias.
Kegan Dougal
committed
Clients `should` check the validity of any room alias given in this list
before presenting it to the user as trusted fact. The lists given by this
event should be considered simply as advice on which aliases might exist,
for which the client can perform the lookup to confirm whether it receives
the correct room ID.
Kegan Dougal
committed
``m.room.message``
Summary:
A message.
Type:
Non-state event
JSON format:
``{ "msgtype": "string" }``
Example:
``{ "msgtype": "m.text", "body": "Testing" }``
Description:
This event is used when sending messages in a room. Messages are not
limited to be text. The ``msgtype`` key outlines the type of message, e.g.
text, audio, image, video, etc. Whilst not required, the ``body`` key
SHOULD be used with every kind of ``msgtype`` as a fallback mechanism when
a client cannot render the message. For more information on the types of
messages which can be sent, see `m.room.message msgtypes`_.
Kegan Dougal
committed
``m.room.message.feedback``
Summary:
A receipt for a message.
Type:
Non-state event
JSON format:
``{ "type": "enum [ delivered|read ]", "target_event_id": "string" }``
Example:
``{ "type": "delivered", "target_event_id": "e3b2icys" }``
Description:
Feedback events are events sent to acknowledge a message in some way. There
are two supported acknowledgements: ``delivered`` (sent when the event has
been received) and ``read`` (sent when the event has been observed by the
end-user). The ``target_event_id`` should reference the ``m.room.message``
event being acknowledged.
Kegan Dougal
committed
``m.room.redaction``
Summary:
Indicates a previous event has been redacted.
Type:
Non-state event
JSON format:
``{ "reason": "string" }``
Description:
Events can be redacted by either room or server admins. Redacting an event
means that all keys not required by the protocol are stripped off, allowing
admins to remove offensive or illegal content that may have been attached
to any event. This cannot be undone, allowing server owners to physically
delete the offending data. There is also a concept of a moderator hiding a
non-state event, which can be undone, but cannot be applied to state
events.
The event that has been redacted is specified in the ``redacts`` event
level key.
Paul "LeoNerd" Evans
committed
m.room.message msgtypes
~~~~~~~~~~~~~~~~~~~~~~~
Kegan Dougal
committed
.. TODO-spec
How a client should handle unknown message types.
Kegan Dougal
committed
Each ``m.room.message`` MUST have a ``msgtype`` key which identifies the type
of message being sent. Each type has their own required and optional keys, as
outlined below:
Kegan Dougal
committed
``m.text``
Required keys:
- ``body`` : "string" - The body of the message.
Optional keys:
None.
Example:
``{ "msgtype": "m.text", "body": "I am a fish" }``
Kegan Dougal
committed
``m.emote``
Required keys:
- ``body`` : "string" - The emote action to perform.
Optional keys:
None.
Example:
``{ "msgtype": "m.emote", "body": "tries to come up with a witty explanation" }``
``m.image``
Required keys:
- ``url`` : "string" - The URL to the image.
Optional keys:
- ``info`` : "string" - info : JSON object (ImageInfo) - The image info for
image referred to in ``url``.
- ``thumbnail_url`` : "string" - The URL to the thumbnail.
- ``thumbnail_info`` : JSON object (ImageInfo) - The image info for the
image referred to in ``thumbnail_url``.
- ``body`` : "string" - The alt text of the image, or some kind of content
description for accessibility e.g. "image attachment".
Kegan Dougal
committed
ImageInfo:
Information about an image::
{
"size" : integer (size of image in bytes),
"w" : integer (width of image in pixels),
"h" : integer (height of image in pixels),
"mimetype" : "string (e.g. image/jpeg)",
}
Paul "LeoNerd" Evans
committed
``m.audio``
Required keys:
- ``url`` : "string" - The URL to the audio.
Optional keys:
- ``info`` : JSON object (AudioInfo) - The audio info for the audio
referred to in ``url``.
- ``body`` : "string" - A description of the audio e.g. "Bee Gees - Stayin'
Alive", or some kind of content description for accessibility e.g.
"audio attachment".
AudioInfo:
Information about a piece of audio::
Paul "LeoNerd" Evans
committed
{
"mimetype" : "string (e.g. audio/aac)",
"size" : integer (size of audio in bytes),
"duration" : integer (duration of audio in milliseconds),
Paul "LeoNerd" Evans
committed
}
Kegan Dougal
committed
``m.video``
Required keys:
- ``url`` : "string" - The URL to the video.
Optional keys:
- ``info`` : JSON object (VideoInfo) - The video info for the video
referred to in ``url``.
- ``body`` : "string" - A description of the video e.g. "Gangnam style", or
some kind of content description for accessibility e.g. "video
attachment".
Kegan Dougal
committed
VideoInfo:
Information about a video::
Kegan Dougal
committed
{
"mimetype" : "string (e.g. video/mp4)",
"size" : integer (size of video in bytes),
"duration" : integer (duration of video in milliseconds),
"w" : integer (width of video in pixels),
"h" : integer (height of video in pixels),
"thumbnail_url" : "string (URL to image)",
"thumbanil_info" : JSON object (ImageInfo)
}
Kegan Dougal
committed
``m.location``
Required keys:
- ``geo_uri`` : "string" - The geo URI representing the location.
Optional keys:
- ``thumbnail_url`` : "string" - The URL to a thumnail of the location
being represented.
- ``thumbnail_info`` : JSON object (ImageInfo) - The image info for the
image referred to in ``thumbnail_url``.
- ``body`` : "string" - A description of the location e.g. "Big Ben,
London, UK", or some kind of content description for accessibility e.g.
"location attachment".
Kegan Dougal
committed
The following keys can be attached to any ``m.room.message``:
Kegan Dougal
committed
Optional keys:
- ``sender_ts`` : integer - A timestamp (ms resolution) representing the
wall-clock time when the message was sent from the client.
Kegan Dougal
committed
Events on Change of Profile Information
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Because the profile displayname and avatar information are likely to be used in
many places of a client's display, changes to these fields cause an automatic
propagation event to occur, informing likely-interested parties of the new
values. This change is conveyed using two separate mechanisms:
Kegan Dougal
committed
- a ``m.room.member`` event is sent to every room the user is a member of,
to update the ``displayname`` and ``avatar_url``.
- a presence status update is sent, again containing the new values of the
``displayname`` and ``avatar_url`` keys, in addition to the required
``presence`` key containing the current presence state of the user.
Kegan Dougal
committed
Both of these should be done automatically by the home server when a user
successfully changes their displayname or avatar URL fields.
Kegan Dougal
committed
Additionally, when home servers emit room membership events for their own
users, they should include the displayname and avatar URL fields in these
events so that clients already have these details to hand, and do not have to
perform extra roundtrips to query it.
Kegan Dougal
committed
Voice over IP
-------------
Matrix can also be used to set up VoIP calls. This is part of the core
specification, although is still in a very early stage. Voice (and video) over
Matrix is based on the WebRTC standards.
Kegan Dougal
committed
Call events are sent to a room, like any other event. This means that clients
must only send call events to rooms with exactly two participants as currently
the WebRTC standard is based around two-party communication.
Kegan Dougal
committed
Events
~~~~~~
``m.call.invite``
This event is sent by the caller when they wish to establish a call.
Kegan Dougal
committed
Required keys:
- ``call_id`` : "string" - A unique identifier for the call
- ``offer`` : "offer object" - The session description
- ``version`` : "integer" - The version of the VoIP specification this
message adheres to. This specification is version 0.
- ``lifetime`` : "integer" - The time in milliseconds that the invite is
valid for. Once the invite age exceeds this value, clients should discard
it. They should also no longer show the call as awaiting an answer in the
UI.
Optional keys:
None.
Example:
``{ "version" : 0, "call_id": "12345", "offer": { "type" : "offer", "sdp" : "v=0\r\no=- 6584580628695956864 2 IN IP4 127.0.0.1[...]" } }``
Kegan Dougal
committed
``Offer Object``
Required keys:
- ``type`` : "string" - The type of session description, in this case
'offer'
- ``sdp`` : "string" - The SDP text of the session description
Kegan Dougal
committed
``m.call.candidates``
This event is sent by callers after sending an invite and by the callee after
answering. Its purpose is to give the other party additional ICE candidates to
try using to communicate.
Kegan Dougal
committed
Required keys:
- ``call_id`` : "string" - The ID of the call this event relates to
- ``version`` : "integer" - The version of the VoIP specification this
messages adheres to. his specification is version 0.
- ``candidates`` : "array of candidate objects" - Array of object
describing the candidates.
Paul "LeoNerd" Evans
committed
Paul "LeoNerd" Evans
committed
Required Keys:
- ``sdpMid`` : "string" - The SDP media type this candidate is intended
for.
- ``sdpMLineIndex`` : "integer" - The index of the SDP 'm' line this
candidate is intended for
- ``candidate`` : "string" - The SDP 'a' line of the candidate
Paul "LeoNerd" Evans
committed
Paul "LeoNerd" Evans
committed
Required keys:
- ``call_id`` : "string" - The ID of the call this event relates to
- ``version`` : "integer" - The version of the VoIP specification this
messages
- ``answer`` : "answer object" - Object giving the SDK answer
Paul "LeoNerd" Evans
committed
Paul "LeoNerd" Evans
committed
Required keys:
- ``type`` : "string" - The type of session description. 'answer' in this
case.
- ``sdp`` : "string" - The SDP text of the session description
Kegan Dougal
committed
``m.call.hangup``
Sent by either party to signal their termination of the call. This can be sent
either once the call has has been established or before to abort the call.
Required keys:
- ``call_id`` : "string" - The ID of the call this event relates to
- ``version`` : "integer" - The version of the VoIP specification this
messages
Message Exchange
~~~~~~~~~~~~~~~~
A call is set up with messages exchanged as follows:
Paul "LeoNerd" Evans
committed
Caller Callee
m.call.invite ----------->
m.call.candidate -------->
[more candidates events]
User answers call
<------ m.call.answer