You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1265 lines
41 KiB

  1. =========================
  2. Synapse Client-Server API
  3. =========================
  4. The following specification outlines how a client can send and receive data from
  5. a home server.
  6. [[TODO(kegan): 4/7/14 Grilling
  7. - Mechanism for getting historical state changes (e.g. topic updates) - add
  8. query param flag?
  9. - Generic mechanism for linking first class events (e.g. feedback) with other s
  10. first class events (e.g. messages)?
  11. - Generic mechanism for updating 'stuff about the room' (e.g. favourite coffee)
  12. AND specifying clobbering rules (clobber/add to list/etc)?
  13. - How to ensure a consistent view for clients paginating through room lists?
  14. They aren't really ordered in any way, and if you're paginating
  15. through them, how can you show them a consistent result set? Temporary 'room
  16. list versions' akin to event version? How does that work?
  17. ]]
  18. [[TODO(kegan):
  19. Outstanding problems / missing spec:
  20. - Push
  21. - Typing notifications
  22. ]]
  23. Terminology
  24. -----------
  25. Stream Tokens:
  26. An opaque token used to make further streaming requests. When using any
  27. pagination streaming API, responses will contain a start and end stream token.
  28. When reconnecting to the stream, these tokens can be used to tell the server
  29. where the client got up to in the stream.
  30. Event ID:
  31. Every event that comes down the event stream or that is returned from the REST
  32. API has an associated event ID (event_id). This ID will be the same between the
  33. REST API and the event stream, so any duplicate events can be clobbered
  34. correctly without knowing anything else about the event.
  35. Message ID:
  36. The ID of a message sent by a client in a room. Clients send IMs to each other
  37. in rooms. Each IM sent by a client must have a unique message ID which is unique
  38. for that particular client.
  39. User ID:
  40. The @username:host style ID of the client. When registering for an account, the
  41. client specifies their username. The user_id is this username along with the
  42. home server's unique hostname. When federating between home servers, the user_id
  43. is used to uniquely identify users across multiple home servers.
  44. Room ID:
  45. The room_id@host style ID for the room. When rooms are created, the client either
  46. specifies or is allocated a room ID. This room ID must be used to send messages
  47. in that room. Like with clients, there may be multiple rooms with the same ID
  48. across multiple home servers. The room_id is used to uniquely identify a room
  49. when federating.
  50. Global message ID:
  51. The globally unique ID for a message. This ID is formed from the msg_id, the
  52. client's user_id and the room_id. This uniquely identifies any
  53. message. It is represented with '-' as the delimeter between IDs. The
  54. global_msg_id is of the form: room_id-user_id-msg_id
  55. REST API and the Event Stream
  56. -----------------------------
  57. Clients send data to the server via a RESTful API. They can receive data via
  58. this API or from an event stream. An event stream is a special path which
  59. streams all events the client may be interested in. This makes it easy to
  60. immediately receive updates from the REST API. All data is represented as JSON.
  61. Pagination streaming API
  62. ========================
  63. Clients are often interested in very large datasets. The data itself could
  64. be 1000s of messages in a given room, 1000s of rooms in a public room list, or
  65. 1000s of events (presence, typing, messages, etc) in the system. It is not
  66. practical to send vast quantities of data to the client every time they
  67. request a list of public rooms for example. There needs to be a way to show a
  68. subset of this data, and apply various filters to it. This is what the pagination
  69. streaming API is. This API defines standard request/response parameters which
  70. can be used when navigating this stream of data.
  71. Pagination Request Query Parameters
  72. -----------------------------------
  73. Clients may wish to paginate results from the event stream, or other sources of
  74. information where the amount of information may be a problem,
  75. e.g. in a room with 10,000s messages. The pagination query parameters provide a
  76. way to navigate a 'window' around a large set of data. These
  77. parameters are only valid for GET requests.
  78. S e r v e r - s i d e d a t a
  79. |-------------------------------------------------|
  80. START ^ ^ END
  81. |_______________|
  82. |
  83. Client-extraction
  84. 'START' and 'END' are magic token values which specify the start and end of the
  85. dataset respectively.
  86. Query parameters:
  87. from : $streamtoken - The opaque token to start streaming from.
  88. to : $streamtoken - The opaque token to end streaming at. Typically,
  89. clients will not know the item of data to end at, so this will usually be
  90. START or END.
  91. limit : integer - An integer representing the maximum number of items to
  92. return.
  93. For example, the event stream has events E1 -> E15. The client wants the last 5
  94. events and doesn't know any previous events:
  95. S E
  96. |-E1-E2-E3-E4-E5-E6-E7-E8-E9-E10-E11-E12-E13-E14-E15-|
  97. | | |
  98. | _____| |
  99. |__________________ | ___________________|
  100. | | |
  101. GET /events?to=START&limit=5&from=END
  102. Returns:
  103. E15,E14,E13,E12,E11
  104. Another example: a public room list has rooms R1 -> R17. The client is showing 5
  105. rooms at a time on screen, and is on page 2. They want to
  106. now show page 3 (rooms R11 -> 15):
  107. S E
  108. | 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | stream token
  109. |-R1-R2-R3-R4-R5-R6-R7-R8-R9-R10-R11-R12-R13-R14-R15-R16-R17| room
  110. |____________| |________________|
  111. | |
  112. Currently |
  113. viewing |
  114. |
  115. GET /rooms/list?from=9&to=END&limit=5
  116. Returns: R11,R12,R13,R14,R15
  117. Note that tokens are treated in an *exclusive*, not inclusive, manner. The end
  118. token from the intial request was '9' which corresponded to R10. When the 2nd
  119. request was made, R10 did not appear again, even though from=9 was specified. If
  120. you know the token, you already have the data.
  121. Pagination Response
  122. -------------------
  123. Responses to pagination requests MUST follow the format:
  124. {
  125. "chunk": [ ... , Responses , ... ],
  126. "start" : $streamtoken,
  127. "end" : $streamtoken
  128. }
  129. Where $streamtoken is an opaque token which can be used in another query to
  130. get the next set of results. The "start" and "end" keys can only be omitted if
  131. the complete dataset is provided in "chunk".
  132. If the client wants earlier results, they should use from=$start_streamtoken,
  133. to=START. Likewise, if the client wants later results, they should use
  134. from=$end_streamtoken, to=END.
  135. Unless specified, the default pagination parameters are from=START, to=END,
  136. without a limit set. This allows you to hit an API like
  137. /events without any query parameters to get everything.
  138. The Event Stream
  139. ----------------
  140. The event stream returns events using the pagination streaming API. When the
  141. client disconnects for a while and wants to reconnect to the event stream, they
  142. should specify from=$end_streamtoken. This lets the server know where in the
  143. event stream the client is. These tokens are completely opaque, and the client
  144. cannot infer anything from them.
  145. GET /events?from=$LAST_STREAM_TOKEN
  146. REST Path: /events
  147. Returns (success): A JSON array of Event Data.
  148. Returns (failure): An Error Response
  149. LAST_STREAM_TOKEN is the last stream token obtained from the event stream. If the
  150. client is connecting for the first time and does not know any stream tokens,
  151. they can use "START" to request all events from the start. For more information
  152. on this, see "Pagination Request Query Parameters".
  153. The event stream supports shortpoll and longpoll with the "timeout" query
  154. parameter. This parameter specifies the number of milliseconds the server should
  155. hold onto the connection waiting for incoming events. If no events occur in this
  156. period, the connection will be closed and an empty chunk will be returned. To
  157. use shortpoll, specify "timeout=0".
  158. Event Data
  159. ----------
  160. This is a JSON object which looks like:
  161. {
  162. "event_id" : $EVENT_ID,
  163. "type" : $EVENT_TYPE,
  164. $URL_ARGS,
  165. "content" : {
  166. $EVENT_CONTENT
  167. }
  168. }
  169. EVENT_ID
  170. An ID identifying this event. This is so duplicate events can be suppressed on
  171. the client.
  172. EVENT_TYPE
  173. The namespaced event type (m.*)
  174. URL_ARGS
  175. Path specific data from the REST API.
  176. EVENT_CONTENT
  177. The event content, matching the REST content PUT previously.
  178. Events are differentiated via the event type "type" key. This is the type of
  179. event being received. This can be expanded upon by using different namespaces.
  180. Every event MUST have a 'type' key.
  181. Most events will have a corresponding REST URL. This URL will generally have
  182. data in it to represent the resource being modified,
  183. e.g. /rooms/$room_id. The event data will contain extra top-level keys to expose
  184. this information to clients listening on an event
  185. stream. The event content maps directly to the contents submitted via the REST
  186. API.
  187. For example:
  188. Event Type: m.example.room.members
  189. REST Path: /examples/room/$room_id/members/$user_id
  190. REST Content: { "membership" : "invited" }
  191. is represented in the event stream as:
  192. {
  193. "event_id" : "e_some_event_id",
  194. "type" : "m.example.room.members",
  195. "room_id" : $room_id,
  196. "user_id" : $user_id,
  197. "content" : {
  198. "membership" : "invited"
  199. }
  200. }
  201. As convention, the URL variable "$varname" will map directly onto the name
  202. of the JSON key "varname".
  203. Error Responses
  204. ---------------
  205. If the client sends an invalid request, the server MAY respond with an error
  206. response. This is of the form:
  207. {
  208. "error" : "string",
  209. "errcode" : "string"
  210. }
  211. The 'error' string will be a human-readable error message, usually a sentence
  212. explaining what went wrong.
  213. The 'errcode' string will be a unique string which can be used to handle an
  214. error message e.g. "M_FORBIDDEN". These error codes should have their namespace
  215. first in ALL CAPS, followed by a single _. For example, if there was a custom
  216. namespace com.mydomain.here, and a "FORBIDDEN" code, the error code should look
  217. like "COM.MYDOMAIN.HERE_FORBIDDEN". There may be additional keys depending on
  218. the error, but the keys 'error' and 'errcode' will always be present.
  219. Some standard error codes are below:
  220. M_FORBIDDEN:
  221. Forbidden access, e.g. bad access token, failed login.
  222. M_BAD_JSON:
  223. Request contained valid JSON, but it was malformed in some way, e.g. missing
  224. required keys, invalid values for keys.
  225. M_NOT_JSON:
  226. Request did not contain valid JSON.
  227. M_NOT_FOUND:
  228. No resource was found for this request.
  229. Some requests have unique error codes:
  230. M_USER_IN_USE:
  231. Encountered when trying to register a user ID which has been taken.
  232. M_ROOM_IN_USE:
  233. Encountered when trying to create a room which has been taken.
  234. M_BAD_PAGINATION:
  235. Encountered when specifying bad pagination values to a Pagination Streaming API.
  236. ========
  237. REST API
  238. ========
  239. All content must be application/json. Some keys are required, while others are
  240. optional. Unless otherwise specified,
  241. all HTTP PUT/POST/DELETEs will return a 200 OK with an empty response body on
  242. success, and a 4xx/5xx with an optional Error Response on failure. When sending
  243. data, if there are no keys to send, an empty JSON object should be sent.
  244. All POST/PUT/GET/DELETE requests MUST have an 'access_token' query parameter to
  245. allow the server to authenticate the client. All
  246. POST requests MUST be submitted as application/json.
  247. All paths MUST be namespaced by the version of the API being used. This should
  248. be:
  249. /matrix/client/api/v1
  250. All REST paths in this section MUST be prefixed with this. E.g.
  251. REST Path: /rooms/$room_id
  252. Absolute Path: /matrix/client/api/v1/rooms/$room_id
  253. Registration
  254. ============
  255. Clients must register with the server in order to use the service. After
  256. registering, the client will be given an
  257. access token which must be used in ALL requests as a query parameter
  258. 'access_token'.
  259. Registering for an account
  260. --------------------------
  261. POST /register
  262. With: A JSON object containing the key "user_id" which contains the desired
  263. user_id, or an empty JSON object to have the server allocate a user_id
  264. automatically.
  265. Returns (success): 200 OK with a JSON object:
  266. {
  267. "user_id" : "string [user_id]",
  268. "access_token" : "string"
  269. }
  270. Returns (failure): An Error Response. M_USER_IN_USE if the user ID is taken.
  271. Unregistering an account
  272. ------------------------
  273. POST /unregister
  274. With query parameters: access_token=$ACCESS_TOKEN
  275. Returns (success): 200 OK
  276. Returns (failure): An Error Response.
  277. Logging in to an existing account
  278. =================================
  279. If the client has already registered, they need to be able to login to their
  280. account. The home server may provide many different ways of logging in, such
  281. as user/password auth, login via a social network (OAuth), login by confirming
  282. a token sent to their email address, etc. This section does NOT define how home
  283. servers should authorise their users who want to login to their existing
  284. accounts. This section defines the standard interface which implementations
  285. should follow so that ANY client can login to ANY home server.
  286. The login process breaks down into the following:
  287. 1: Get login process info.
  288. 2: Submit the login stage credentials.
  289. 3: Get access token or be told the next stage in the login process and repeat
  290. step 2.
  291. Getting login process info:
  292. GET /login
  293. Returns (success): 200 OK with LoginInfo.
  294. Returns (failure): An Error Response.
  295. Submitting the login stage credentials:
  296. POST /login
  297. With: LoginSubmission
  298. Returns (success): 200 OK with LoginResult
  299. Returns (failure): An Error Response
  300. Where LoginInfo is a JSON object which MUST have a "type" key which denotes the
  301. login type. If there are multiple login stages, this object MUST also contain a
  302. "stages" key, which has a JSON array of login types denoting all the steps in
  303. order to login, including the first stage which is in "type". This allows the
  304. client to make an informed decision as to whether or not they can natively
  305. handle the entire login process, or whether they should fallback (see below).
  306. Where LoginSubmission is a JSON object which MUST have a "type" key.
  307. Where LoginResult is a JSON object which MUST have either a "next" key OR an
  308. "access_token" key, depending if the login process is over or not. This object
  309. MUST have a "session" key if multiple POSTs need to be sent to /login.
  310. Fallback
  311. --------
  312. If the client does NOT know how to handle the given type, they should:
  313. GET /login/fallback
  314. This MUST return an HTML page which can perform the entire login process.
  315. Password-based
  316. --------------
  317. Type: "m.login.password"
  318. LoginSubmission:
  319. {
  320. "type": "m.login.password",
  321. "user": <user_id>,
  322. "password": <password>
  323. }
  324. Example:
  325. Assume you are @bob:matrix.org and you wish to login on another mobile device.
  326. First, you GET /login which returns:
  327. {
  328. "type": "m.login.password"
  329. }
  330. Your client knows how to handle this, so your client prompts the user to enter
  331. their username and password. This is then submitted:
  332. {
  333. "type": "m.login.password",
  334. "user": "@bob:matrix.org",
  335. "password": "monkey"
  336. }
  337. The server checks this, finds it is valid, and returns:
  338. {
  339. "access_token": "abcdef0123456789"
  340. }
  341. OAuth2-based
  342. ------------
  343. Type: "m.login.oauth2"
  344. This is a multi-stage login.
  345. LoginSubmission:
  346. {
  347. "type": "m.login.oauth2",
  348. "user": <user_id>
  349. }
  350. Returns:
  351. {
  352. "uri": <Authorization Request uri OR service selection uri>
  353. }
  354. The home server acts as a 'confidential' Client for the purposes of OAuth2.
  355. If the uri is a "sevice selection uri", it is a simple page which prompts the
  356. user to choose which service to authorize with. On selection of a service, they
  357. link through to Authorization Request URIs. If there is only 1 service which the
  358. home server accepts when logging in, this indirection can be skipped and the
  359. "uri" key can be the Authorization Request URI.
  360. The client visits the Authorization Request URI, which then shows the OAuth2
  361. Allow/Deny prompt. Hitting 'Allow' returns the redirect URI with the auth code.
  362. Home servers can choose any path for the redirect URI. The client should visit
  363. the redirect URI, which will then finish the OAuth2 login process, granting the
  364. home server an access token for the chosen service. When the home server gets
  365. this access token, it knows that the cilent has authed with the 3rd party, and
  366. so can return a LoginResult.
  367. The OAuth redirect URI (with auth code) MUST return a LoginResult.
  368. Example:
  369. Assume you are @bob:matrix.org and you wish to login on another mobile device.
  370. First, you GET /login which returns:
  371. {
  372. "type": "m.login.oauth2"
  373. }
  374. Your client knows how to handle this, so your client prompts the user to enter
  375. their username. This is then submitted:
  376. {
  377. "type": "m.login.oauth2",
  378. "user": "@bob:matrix.org"
  379. }
  380. The server only accepts auth from Google, so returns the Authorization Request
  381. URI for Google:
  382. {
  383. "uri": "https://accounts.google.com/o/oauth2/auth?response_type=code&
  384. client_id=CLIENT_ID&redirect_uri=REDIRECT_URI&scope=photos"
  385. }
  386. The client then visits this URI and authorizes the home server. The client then
  387. visits the REDIRECT_URI with the auth code= query parameter which returns:
  388. {
  389. "access_token": "0123456789abcdef"
  390. }
  391. Email-based (code)
  392. ------------------
  393. Type: "m.login.email.code"
  394. This is a multi-stage login.
  395. First LoginSubmission:
  396. {
  397. "type": "m.login.email.code",
  398. "user": <user_id>
  399. "email": <email address>
  400. }
  401. Returns:
  402. {
  403. "session": <session id>
  404. }
  405. The email contains a code which must be sent in the next LoginSubmission:
  406. {
  407. "type": "m.login.email.code",
  408. "session": <session id>,
  409. "code": <code in email sent>
  410. }
  411. Returns:
  412. {
  413. "access_token": <access token>
  414. }
  415. Example:
  416. Assume you are @bob:matrix.org and you wish to login on another mobile device.
  417. First, you GET /login which returns:
  418. {
  419. "type": "m.login.email.code"
  420. }
  421. Your client knows how to handle this, so your client prompts the user to enter
  422. their email address. This is then submitted:
  423. {
  424. "type": "m.login.email.code",
  425. "user": "@bob:matrix.org",
  426. "email": "bob@mydomain.com"
  427. }
  428. The server confirms that bob@mydomain.com is linked to @bob:matrix.org, then
  429. sends an email to this address and returns:
  430. {
  431. "session": "ewuigf7462"
  432. }
  433. The client's screen changes to a code submission page. The email arrives and it
  434. says something to the effect of "please enter 2348623 into the app". This is
  435. the submitted along with the session:
  436. {
  437. "type": "m.login.email.code",
  438. "session": "ewuigf7462",
  439. "code": "2348623"
  440. }
  441. The server accepts this and returns:
  442. {
  443. "access_token": "abcdef0123456789"
  444. }
  445. Email-based (url)
  446. -----------------
  447. Type: "m.login.email.url"
  448. This is a multi-stage login.
  449. First LoginSubmission:
  450. {
  451. "type": "m.login.email.url",
  452. "user": <user_id>
  453. "email": <email address>
  454. }
  455. Returns:
  456. {
  457. "session": <session id>
  458. }
  459. The email contains a URL which must be clicked. After it has been clicked, the
  460. client should perform a request:
  461. {
  462. "type": "m.login.email.code",
  463. "session": <session id>
  464. }
  465. Returns:
  466. {
  467. "access_token": <access token>
  468. }
  469. Example:
  470. Assume you are @bob:matrix.org and you wish to login on another mobile device.
  471. First, you GET /login which returns:
  472. {
  473. "type": "m.login.email.url"
  474. }
  475. Your client knows how to handle this, so your client prompts the user to enter
  476. their email address. This is then submitted:
  477. {
  478. "type": "m.login.email.url",
  479. "user": "@bob:matrix.org",
  480. "email": "bob@mydomain.com"
  481. }
  482. The server confirms that bob@mydomain.com is linked to @bob:matrix.org, then
  483. sends an email to this address and returns:
  484. {
  485. "session": "ewuigf7462"
  486. }
  487. The client then starts polling the server with the following:
  488. {
  489. "type": "m.login.email.url",
  490. "session": "ewuigf7462"
  491. }
  492. (Alternatively, the server could send the device a push notification when the
  493. email has been validated). The email arrives and it contains a URL to click on.
  494. The user clicks on the which completes the login process with the server. The
  495. next time the client polls, it returns:
  496. {
  497. "access_token": "abcdef0123456789"
  498. }
  499. N-Factor auth
  500. -------------
  501. Multiple login stages can be combined with the "next" key in the LoginResult.
  502. Example:
  503. A server demands an email.code then password auth before logging in. First, the
  504. client performs a GET /login which returns:
  505. {
  506. "type": "m.login.email.code",
  507. "stages": ["m.login.email.code", "m.login.password"]
  508. }
  509. The client performs the email login (See "Email-based (code)"), but instead of
  510. returning an access_token, it returns:
  511. {
  512. "next": "m.login.password"
  513. }
  514. The client then presents a user/password screen and the login continues until
  515. this is complete (See "Password-based"), which then returns the "access_token".
  516. Rooms
  517. =====
  518. A room is a conceptual place where users can send and receive messages. Rooms
  519. can be created, joined and left. Messages are sent
  520. to a room, and all participants in that room will receive the message. Rooms are
  521. uniquely identified via the room_id.
  522. Creating a room (with a room ID)
  523. --------------------------------
  524. Event Type: m.room.create [TODO(kegan): Do we generate events for this?]
  525. REST Path: /rooms/$room_id
  526. Valid methods: PUT
  527. Required keys: None.
  528. Optional keys:
  529. visibility : [public|private] - Set whether this room shows up in the public
  530. room list.
  531. Returns:
  532. On Failure: MAY return a suggested alternative room ID if this room ID is
  533. taken.
  534. {
  535. suggested_room_id : $new_room_id
  536. error : "Room already in use."
  537. errcode : "M_ROOM_IN_USE"
  538. }
  539. Creating a room (without a room ID)
  540. -----------------------------------
  541. Event Type: m.room.create [TODO(kegan): Do we generate events for this?]
  542. REST Path: /rooms
  543. Valid methods: POST
  544. Required keys: None.
  545. Optional keys:
  546. visibility : [public|private] - Set whether this room shows up in the public
  547. room list.
  548. Returns:
  549. On Success: The allocated room ID. Additional information about the room
  550. such as the visibility MAY be included as extra keys in this response.
  551. {
  552. room_id : $room_id
  553. }
  554. Setting the topic for a room
  555. ----------------------------
  556. Event Type: m.room.topic
  557. REST Path: /rooms/$room_id/topic
  558. Valid methods: GET/PUT
  559. Required keys:
  560. topic : $topicname - Set the topic to $topicname in room $room_id.
  561. See a list of public rooms
  562. --------------------------
  563. REST Path: /public/rooms?pagination_query_parameters
  564. Valid methods: GET
  565. This API can use pagination query parameters.
  566. Returns:
  567. {
  568. "chunk" : JSON array of RoomInfo JSON objects - Required.
  569. "start" : "string (start token)" - See Pagination Response.
  570. "end" : "string (end token)" - See Pagination Response.
  571. "total" : integer - Optional. The total number of rooms.
  572. }
  573. RoomInfo: Information about a single room.
  574. Servers MUST send the key: room_id
  575. Servers MAY send the keys: topic, num_members
  576. {
  577. "room_id" : "string",
  578. "topic" : "string",
  579. "num_members" : integer
  580. }
  581. Room Members
  582. ============
  583. Invite/Joining/Leaving a room
  584. -----------------------------
  585. Event Type: m.room.member
  586. REST Path: /rooms/$room_id/members/$user_id/state
  587. Valid methods: PUT/GET/DELETE
  588. Required keys:
  589. membership : [join|invite] - The membership state of $user_id in room
  590. $room_id.
  591. Where:
  592. join - Indicate you ($user_id) are joining the room $room_id.
  593. invite - Indicate that $user_id has been invited to room $room_id.
  594. User $user_id can leave room $room_id by DELETEing this path.
  595. Checking the user list of a room
  596. --------------------------------
  597. REST Path: /rooms/$room_id/members/list
  598. This API can use pagination query parameters.
  599. Valid methods: GET
  600. Returns:
  601. A pagination response with chunk data as m.room.member events.
  602. Messages
  603. ========
  604. Users send messages to other users in rooms. These messages may be text, images,
  605. video, etc. Clients may also want to acknowledge messages by sending feedback,
  606. in the form of delivery/read receipts.
  607. Server-attached keys
  608. --------------------
  609. The server MAY attach additional keys to messages and feedback. If a client
  610. submits keys with the same name, they will be clobbered by
  611. the server.
  612. Required keys:
  613. from : "string [user_id]"
  614. The user_id of the user who sent the message/feedback.
  615. Optional keys:
  616. hsob_ts : integer
  617. A timestamp (ms resolution) representing when the message/feedback got to the
  618. sender's home server ("home server outbound timestamp").
  619. hsib_ts : integer
  620. A timestamp (ms resolution) representing when the
  621. message/feedback got to the receiver's home server ("home server inbound
  622. timestamp"). This may be the same as hsob_ts if the sender/receiver are on the
  623. same home server.
  624. Sending messages
  625. ----------------
  626. Event Type: m.room.message
  627. REST Path: /rooms/$room_id/messages/$from/$msg_id
  628. Valid methods: GET/PUT
  629. URL parameters:
  630. $from : user_id - The sender's user_id. This value will be clobbered by the
  631. server before sending.
  632. Required keys:
  633. msgtype: [m.text|m.emote|m.image|m.audio|m.video|m.location|m.file] -
  634. The type of message. Not to be confused with the Event 'type'.
  635. Optional keys:
  636. sender_ts : integer - A timestamp (ms resolution) representing the
  637. wall-clock time when the message was sent from the client.
  638. Reserved keys:
  639. body : "string" - The human readable string for compatibility with clients
  640. which cannot process a given msgtype. This key is optional, but
  641. if it is included, it MUST be human readable text
  642. describing the message. See individual msgtypes for more
  643. info on what this means in practice.
  644. Each msgtype may have required fields of their own.
  645. msgtype: m.text
  646. ----------------
  647. Required keys:
  648. body : "string" - The body of the message.
  649. Optional keys:
  650. None.
  651. msgtype: m.emote
  652. -----------------
  653. Required keys:
  654. body : "string" - *tries to come up with a witty explanation*.
  655. Optional keys:
  656. None.
  657. msgtype: m.image
  658. -----------------
  659. Required keys:
  660. url : "string" - The URL to the image.
  661. Optional keys:
  662. body : "string" - info : JSON object (ImageInfo) - The image info for image
  663. referred to in 'url'.
  664. thumbnail_url : "string" - The URL to the thumbnail.
  665. thumbnail_info : JSON object (ImageInfo) - The image info for the image
  666. referred to in 'thumbnail_url'.
  667. ImageInfo: Information about an image.
  668. {
  669. "size" : integer (size of image in bytes),
  670. "w" : integer (width of image in pixels),
  671. "h" : integer (height of image in pixels),
  672. "mimetype" : "string (e.g. image/jpeg)"
  673. }
  674. Interpretation of 'body' key: The alt text of the image, or some kind of content
  675. description for accessibility e.g. "image attachment".
  676. msgtype: m.audio
  677. -----------------
  678. Required keys:
  679. url : "string" - The URL to the audio.
  680. Optional keys:
  681. info : JSON object (AudioInfo) - The audio info for the audio referred to in
  682. 'url'.
  683. AudioInfo: Information about a piece of audio.
  684. {
  685. "mimetype" : "string (e.g. audio/aac)",
  686. "size" : integer (size of audio in bytes),
  687. "duration" : integer (duration of audio in milliseconds)
  688. }
  689. Interpretation of 'body' key: A description of the audio e.g. "Bee Gees -
  690. Stayin' Alive", or some kind of content description for accessibility e.g.
  691. "audio attachment".
  692. msgtype: m.video
  693. -----------------
  694. Required keys:
  695. url : "string" - The URL to the video.
  696. Optional keys:
  697. info : JSON object (VideoInfo) - The video info for the video referred to in
  698. 'url'.
  699. VideoInfo: Information about a video.
  700. {
  701. "mimetype" : "string (e.g. video/mp4)",
  702. "size" : integer (size of video in bytes),
  703. "duration" : integer (duration of video in milliseconds),
  704. "w" : integer (width of video in pixels),
  705. "h" : integer (height of video in pixels),
  706. "thumbnail_url" : "string (URL to image)",
  707. "thumbanil_info" : JSON object (ImageInfo)
  708. }
  709. Interpretation of 'body' key: A description of the video e.g. "Gangnam style",
  710. or some kind of content description for accessibility e.g. "video attachment".
  711. msgtype: m.location
  712. --------------------
  713. Required keys:
  714. geo_uri : "string" - The geo URI representing the location.
  715. Optional keys:
  716. thumbnail_url : "string" - The URL to a thumnail of the location being
  717. represented.
  718. thumbnail_info : JSON object (ImageInfo) - The image info for the image
  719. referred to in 'thumbnail_url'.
  720. Interpretation of 'body' key: A description of the location e.g. "Big Ben,
  721. London, UK", or some kind of content description for accessibility e.g.
  722. "location attachment".
  723. Sending feedback
  724. ----------------
  725. When you receive a message, you may want to send delivery receipt to let the
  726. sender know that the message arrived. You may also want to send a read receipt
  727. when the user has read the message. These receipts are collectively known as
  728. 'feedback'.
  729. Event Type: m.room.message.feedback
  730. REST Path: /rooms/$room_id/messages/$msgfrom/$msg_id/feedback/$from/$feedback
  731. Valid methods: GET/PUT
  732. URL parameters:
  733. $msgfrom - The sender of the message's user_id.
  734. $from : user_id - The sender of the feedback's user_id. This value will be
  735. clobbered by the server before sending.
  736. $feedback : [d|r] - Specify if this is a [d]elivery or [r]ead receipt.
  737. Required keys:
  738. None.
  739. Optional keys:
  740. sender_ts : integer - A timestamp (ms resolution) representing the
  741. wall-clock time when the receipt was sent from the client.
  742. Receiving messages (bulk/pagination)
  743. ------------------------------------
  744. Event Type: m.room.message
  745. REST Path: /rooms/$room_id/messages/list
  746. Valid methods: GET
  747. Query Parameters:
  748. feedback : [true|false] - Specify if feedback should be bundled with each
  749. message.
  750. This API can use pagination query parameters.
  751. Returns:
  752. A JSON array of Event Data in "chunk" (see Pagination Response). If the
  753. "feedback" parameter was set, the Event Data will also contain a "feedback"
  754. key which contains a JSON array of feedback, with each element as Event Data
  755. with compressed feedback for this message.
  756. Event Data with compressed feedback is a special type of feedback with
  757. contextual keys removed. It is designed to limit the amount of redundant data
  758. being sent for feedback. This removes the type, event_id, room ID,
  759. message sender ID and message ID keys.
  760. ORIGINAL (via event streaming)
  761. {
  762. "event_id":"e1247632487",
  763. "type":"m.room.message.feedback",
  764. "from":"string [user_id]",
  765. "feedback":"string [d|r]",
  766. "room_id":"$room_id",
  767. "msg_id":"$msg_id",
  768. "msgfrom":"$msgfromid",
  769. "content":{
  770. "sender_ts":139880943
  771. }
  772. }
  773. COMPRESSED (via /messages/list)
  774. {
  775. "from":"string [user_id]",
  776. "feedback":"string [d|r]",
  777. "content":{
  778. "sender_ts":139880943
  779. }
  780. }
  781. When you join a room $room_id, you may want the last 10 messages with feedback.
  782. This is represented as:
  783. GET
  784. /rooms/$room_id/messages/list?from=END&to=START&limit=10&feedback=true
  785. You may want to get 10 messages even earlier than that without feedback. If the
  786. start stream token from the previous request was stok_019173, this request would
  787. be:
  788. GET
  789. /rooms/$room_id/messages/list?from=stok_019173&to=START&limit=10&
  790. feedback=false
  791. NOTE: Care must be taken when using this API in conjunction with event
  792. streaming. It is possible that this will return a message which will
  793. then come down the event stream, resulting in a duplicate message. Clients
  794. should clobber based on the global message ID, or event ID.
  795. Get current state for all rooms (aka IM Initial Sync API)
  796. -------------------------------
  797. REST Path: /im/sync
  798. Valid methods: GET
  799. This API can use pagination query parameters. Pagination is applied on a per
  800. *room* basis. E.g. limit=1 means "get 1 message for each room" and not "get 1
  801. room's messages". If there is no limit, all messages for all rooms will be
  802. returned.
  803. If you want 1 room's messages, see "Receiving messages (bulk/pagination)".
  804. Additional query parameters:
  805. feedback: [true] - Bundles feedback with messages.
  806. Returns:
  807. An array of RoomStateInfo.
  808. RoomStateInfo: A snapshot of information about a single room.
  809. {
  810. "room_id" : "string",
  811. "membership" : "string [join|invite]",
  812. "messages" : {
  813. "start": "string",
  814. "end": "string",
  815. "chunk":
  816. m.room.message pagination stream events (with feedback if specified),
  817. this is the same as "Receiving messages (bulk/pagination)".
  818. }
  819. }
  820. The "membership" key is the calling user's membership state in the given
  821. "room_id". The "messages" key may be omitted if the "membership" value is
  822. "invite". Additional keys may be added to the top-level object, such as:
  823. "topic" : "string" - The topic for the room in question.
  824. "room_image_url" : "string" - The URL of the room image if specified.
  825. "num_members" : integer - The number of members in the room.
  826. Profiles
  827. ========
  828. Getting/Setting your own displayname
  829. ------------------------------------
  830. REST Path: /profile/$user_id/displayname
  831. Valid methods: GET/PUT
  832. Required keys:
  833. displayname : The displayname text
  834. Getting/Setting your own avatar image URL
  835. -----------------------------------------
  836. The homeserver does not currently store the avatar image itself, but offers
  837. storage for the user to specify a web URL that points at the required image,
  838. leaving it up to clients to fetch it themselves.
  839. REST Path: /profile/$user_id/avatar_url
  840. Valid methods: GET/PUT
  841. Required keys:
  842. avatar_url : The URL path to the required image
  843. Getting other user's profile information
  844. ----------------------------------------
  845. Either of the above REST methods may be used to fetch other user's profile
  846. information by the client, either on other local users on the same homeserver or
  847. for users from other servers entirely.
  848. Presence
  849. ========
  850. In the following messages, the presence state is an integer enumeration of the
  851. following states:
  852. 0 : OFFLINE
  853. 1 : BUSY
  854. 2 : ONLINE
  855. 3 : FREE_TO_CHAT
  856. Aside from OFFLINE, the protocol doesn't assign any special meaning to these
  857. states; they are provided as an approximate signal for users to give to other
  858. users and for clients to present them in some way that may be useful. Clients
  859. could have different behaviours for different states of the user's presence, for
  860. example to decide how much prominence or sound to use for incoming event
  861. notifications.
  862. Getting/Setting your own presence state
  863. ---------------------------------------
  864. REST Path: /presence/$user_id/status
  865. Valid methods: GET/PUT
  866. Required keys:
  867. state : [0|1|2|3] - The user's new presence state
  868. Optional keys:
  869. status_msg : text string provided by the user to explain their status
  870. Fetching your presence list
  871. ---------------------------
  872. REST Path: /presence_list/$user_id
  873. Valid methods: GET/(post)
  874. Returns:
  875. An array of presence list entries. Each entry is an object with the
  876. following keys:
  877. {
  878. "user_id" : string giving the observed user's ID
  879. "state" : int giving their status
  880. "status_msg" : optional text string
  881. "displayname" : optional text string from the user's profile
  882. "avatar_url" : optional text string from the user's profile
  883. }
  884. Maintaining your presence list
  885. ------------------------------
  886. REST Path: /presence_list/$user_id
  887. Valid methods: POST/(get)
  888. With: A JSON object optionally containing either of the following keys:
  889. "invite" : a list of strings giving user IDs to invite for presence
  890. subscription
  891. "drop" : a list of strings giving user IDs to remove from your presence
  892. list
  893. Receiving presence update events
  894. --------------------------------
  895. Event Type: m.presence
  896. Keys of the event's content are the same as those returned by the presence
  897. list.
  898. Examples
  899. ========
  900. The following example is the story of "bob", who signs up at "sy.org" and joins
  901. the public room "room_beta@sy.org". They get the 2 most recent
  902. messages (with feedback) in that room and then send a message in that room.
  903. For context, here is the complete chat log for room_beta@sy.org:
  904. Room: "Hello world" (room_beta@sy.org)
  905. Members: (2) alice@randomhost.org, friend_of_alice@randomhost.org
  906. Messages:
  907. alice@randomhost.org : hi friend!
  908. [friend_of_alice@randomhost.org DELIVERED]
  909. alice@randomhost.org : you're my only friend
  910. [friend_of_alice@randomhost.org DELIVERED]
  911. alice@randomhost.org : afk
  912. [friend_of_alice@randomhost.org DELIVERED]
  913. [ bob@sy.org joins ]
  914. bob@sy.org : Hi everyone
  915. [ alice@randomhost.org changes the topic to "FRIENDS ONLY" ]
  916. alice@randomhost.org : Hello!!!!
  917. alice@randomhost.org : Let's go to another room
  918. alice@randomhost.org : You're not my friend
  919. [ alice@randomhost.org invites bob@sy.org to the room
  920. commoners@randomhost.org]
  921. REGISTER FOR AN ACCOUNT
  922. POST: /register
  923. Content: {}
  924. Returns: { "user_id" : "bob@sy.org" , "access_token" : "abcdef0123456789" }
  925. GET PUBLIC ROOM LIST
  926. GET: /rooms/list?access_token=abcdef0123456789
  927. Returns:
  928. {
  929. "total":3,
  930. "chunk":
  931. [
  932. { "room_id":"room_alpha@sy.org", "topic":"I am a fish" },
  933. { "room_id":"room_beta@sy.org", "topic":"Hello world" },
  934. { "room_id":"room_xyz@sy.org", "topic":"Goodbye cruel world" }
  935. ]
  936. }
  937. JOIN ROOM room_beta@sy.org
  938. PUT
  939. /rooms/room_beta%40sy.org/members/bob%40sy.org/state?
  940. access_token=abcdef0123456789
  941. Content: { "membership" : "join" }
  942. Returns: 200 OK
  943. GET LATEST 2 MESSAGES WITH FEEDBACK
  944. GET
  945. /rooms/room_beta%40sy.org/messages/list?from=END&to=START&limit=2&
  946. feedback=true&access_token=abcdef0123456789
  947. Returns:
  948. {
  949. "chunk":
  950. [
  951. {
  952. "event_id":"01948374",
  953. "type":"m.room.message",
  954. "room_id":"room_beta@sy.org",
  955. "msg_id":"avefifu",
  956. "from":"alice@randomhost.org",
  957. "hs_ts":139985736,
  958. "content":{
  959. "msgtype":"m.text",
  960. "body":"afk"
  961. }
  962. "feedback": [
  963. {
  964. "from":"friend_of_alice@randomhost.org",
  965. "feedback":"d",
  966. "hs_ts":139985850,
  967. "content":{
  968. "sender_ts":139985843
  969. }
  970. }
  971. ]
  972. },
  973. {
  974. "event_id":"028dfe8373",
  975. "type":"m.room.message",
  976. "room_id":"room_beta@sy.org",
  977. "msg_id":"afhgfff",
  978. "from":"alice@randomhost.org",
  979. "hs_ts":139970006,
  980. "content":{
  981. "msgtype":"m.text",
  982. "body":"you're my only friend"
  983. }
  984. "feedback": [
  985. {
  986. "from":"friend_of_alice@randomhost.org",
  987. "feedback":"d",
  988. "hs_ts":139970144,
  989. "content":{
  990. "sender_ts":139970122
  991. }
  992. }
  993. ]
  994. },
  995. ],
  996. "start": "stok_04823947",
  997. "end": "etok_1426425"
  998. }
  999. SEND MESSAGE IN ROOM
  1000. PUT
  1001. /rooms/room_beta%40sy.org/messages/bob%40sy.org/m0001?
  1002. access_token=abcdef0123456789
  1003. Content: { "msgtype" : "text" , "body" : "Hi everyone" }
  1004. Returns: 200 OK
  1005. Checking the event stream for this user:
  1006. GET: /events?from=START&access_token=abcdef0123456789
  1007. Returns:
  1008. {
  1009. "chunk":
  1010. [
  1011. {
  1012. "event_id":"e10f3d2b",
  1013. "type":"m.room.member",
  1014. "room_id":"room_beta@sy.org",
  1015. "user_id":"bob@sy.org",
  1016. "content":{
  1017. "membership":"join"
  1018. }
  1019. },
  1020. {
  1021. "event_id":"1b352d32",
  1022. "type":"m.room.message",
  1023. "room_id":"room_beta@sy.org",
  1024. "msg_id":"m0001",
  1025. "from":"bob@sy.org",
  1026. "hs_ts":140193857,
  1027. "content":{
  1028. "msgtype":"m.text",
  1029. "body":"Hi everyone"
  1030. }
  1031. }
  1032. ],
  1033. "start": "stok_9348635",
  1034. "end": "etok_1984723"
  1035. }
  1036. Client disconnects for a while and the topic is updated in this room, 3 new
  1037. messages arrive whilst offline, and bob is invited to another room.
  1038. GET /events?from=etok_1984723&access_token=abcdef0123456789
  1039. Returns:
  1040. {
  1041. "chunk":
  1042. [
  1043. {
  1044. "event_id":"feee0294",
  1045. "type":"m.room.topic",
  1046. "room_id":"room_beta@sy.org",
  1047. "from":"alice@randomhost.org",
  1048. "content":{
  1049. "topic":"FRIENDS ONLY",
  1050. }
  1051. },
  1052. {
  1053. "event_id":"a028bd9e",
  1054. "type":"m.room.message",
  1055. "room_id":"room_beta@sy.org",
  1056. "msg_id":"z839409",
  1057. "from":"alice@randomhost.org",
  1058. "hs_ts":140195000,
  1059. "content":{
  1060. "msgtype":"m.text",
  1061. "body":"Hello!!!"
  1062. }
  1063. },
  1064. {
  1065. "event_id":"49372d9e",
  1066. "type":"m.room.message",
  1067. "room_id":"room_beta@sy.org",
  1068. "msg_id":"z839410",
  1069. "from":"alice@randomhost.org",
  1070. "hs_ts":140196000,
  1071. "content":{
  1072. "msgtype":"m.text",
  1073. "body":"Let's go to another room"
  1074. }
  1075. },
  1076. {
  1077. "event_id":"10abdd01",
  1078. "type":"m.room.message",
  1079. "room_id":"room_beta@sy.org",
  1080. "msg_id":"z839411",
  1081. "from":"alice@randomhost.org",
  1082. "hs_ts":140197000,
  1083. "content":{
  1084. "msgtype":"m.text",
  1085. "body":"You're not my friend"
  1086. }
  1087. },
  1088. {
  1089. "event_id":"0018453d",
  1090. "type":"m.room.member",
  1091. "room_id":"commoners@randomhost.org",
  1092. "from":"alice@randomhost.org",
  1093. "user_id":"bob@sy.org",
  1094. "content":{
  1095. "membership":"invite"
  1096. }
  1097. },
  1098. ],
  1099. "start": "stok_0184288",
  1100. "end": "etok_1348723"
  1101. }