idnits 2.17.1 draft-jenkins-jmap-00.txt: Checking boilerplate required by RFC 5378 and the IETF Trust (see https://trustee.ietf.org/license-info): ---------------------------------------------------------------------------- No issues found here. Checking nits according to https://www.ietf.org/id-info/1id-guidelines.txt: ---------------------------------------------------------------------------- No issues found here. Checking nits according to https://www.ietf.org/id-info/checklist : ---------------------------------------------------------------------------- ** The document seems to lack an IANA Considerations section. (See Section 2.2 of https://www.ietf.org/id-info/checklist for how to handle the case when there are no actions for IANA.) ** There is 1 instance of too long lines in the document, the longest one being 5 characters in excess of 72. Miscellaneous warnings: ---------------------------------------------------------------------------- == The copyright year in the IETF Trust and authors Copyright Line does not match the current year -- The document date (October 19, 2016) is 2743 days in the past. Is this intentional? Checking references for intended status: Proposed Standard ---------------------------------------------------------------------------- (See RFCs 3967 and 4897 for information about using normative references to lower-maturity documents in RFCs) -- Looks like a reference, but probably isn't: '1' on line 1686 -- Looks like a reference, but probably isn't: '2' on line 1688 -- Looks like a reference, but probably isn't: '3' on line 1690 -- Looks like a reference, but probably isn't: '4' on line 1692 ** Obsolete normative reference: RFC 5785 (Obsoleted by RFC 8615) ** Obsolete normative reference: RFC 7159 (Obsoleted by RFC 8259) Summary: 4 errors (**), 0 flaws (~~), 1 warning (==), 5 comments (--). Run idnits with the --verbose option for more detailed information about the items above. -------------------------------------------------------------------------------- 2 JMAP N. Jenkins 3 Internet-Draft FastMail 4 Intended status: Standards Track October 19, 2016 5 Expires: April 22, 2017 7 JSON Meta Application Protocol 8 draft-jenkins-jmap-00 10 Abstract 12 This document specifies a protocol for synchronising JSON-based data 13 objects efficiently, with support for push and out-of-band binary 14 data upload/download. 16 Status of This Memo 18 This Internet-Draft is submitted in full conformance with the 19 provisions of BCP 78 and BCP 79. 21 Internet-Drafts are working documents of the Internet Engineering 22 Task Force (IETF). Note that other groups may also distribute 23 working documents as Internet-Drafts. The list of current Internet- 24 Drafts is at http://datatracker.ietf.org/drafts/current/. 26 Internet-Drafts are draft documents valid for a maximum of six months 27 and may be updated, replaced, or obsoleted by other documents at any 28 time. It is inappropriate to use Internet-Drafts as reference 29 material or to cite them other than as "work in progress." 31 This Internet-Draft will expire on April 22, 2017. 33 Copyright Notice 35 Copyright (c) 2016 IETF Trust and the persons identified as the 36 document authors. All rights reserved. 38 This document is subject to BCP 78 and the IETF Trust's Legal 39 Provisions Relating to IETF Documents 40 (http://trustee.ietf.org/license-info) in effect on the date of 41 publication of this document. Please review these documents 42 carefully, as they describe your rights and restrictions with respect 43 to this document. Code Components extracted from this document must 44 include Simplified BSD License text as described in Section 4.e of 45 the Trust Legal Provisions and are provided without warranty as 46 described in the Simplified BSD License. 48 Table of Contents 50 1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . 3 51 1.1. Notational Conventions . . . . . . . . . . . . . . . . . 4 52 1.2. Terminology . . . . . . . . . . . . . . . . . . . . . . . 4 53 1.2.1. User . . . . . . . . . . . . . . . . . . . . . . . . 4 54 1.2.2. Accounts . . . . . . . . . . . . . . . . . . . . . . 5 55 1.2.3. Data types and records . . . . . . . . . . . . . . . 5 56 1.3. Ids . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 57 1.4. JSON as the data encoding format . . . . . . . . . . . . 5 58 1.5. The JMAP API model . . . . . . . . . . . . . . . . . . . 6 59 2. Authentication . . . . . . . . . . . . . . . . . . . . . . . 6 60 2.1. Service autodiscovery . . . . . . . . . . . . . . . . . . 6 61 2.2. Getting an access token . . . . . . . . . . . . . . . . . 7 62 2.2.1. 200: Success, but more authorization required. . . . 8 63 2.2.2. 201: Authentication is complete, access token 64 created. . . . . . . . . . . . . . . . . . . . . . . 11 65 2.2.3. 400: Malformed request . . . . . . . . . . . . . . . 13 66 2.2.4. 403: Authentication step failed, but client may try 67 again . . . . . . . . . . . . . . . . . . . . . . . . 13 68 2.2.5. 404: Not found . . . . . . . . . . . . . . . . . . . 13 69 2.2.6. 410: Restart authentication . . . . . . . . . . . . . 14 70 2.2.7. 429: Rate limited . . . . . . . . . . . . . . . . . . 14 71 2.2.8. 500: Internal server error . . . . . . . . . . . . . 14 72 2.2.9. 503: Service unavailable . . . . . . . . . . . . . . 14 73 2.3. Refetching URL endpoints . . . . . . . . . . . . . . . . 14 74 2.3.1. 201: Authentication is complete, access token 75 created. . . . . . . . . . . . . . . . . . . . . . . 14 76 2.3.2. 403: Restart authentication . . . . . . . . . . . . . 15 77 2.3.3. 404: Not found . . . . . . . . . . . . . . . . . . . 15 78 2.3.4. 500: Internal server error . . . . . . . . . . . . . 15 79 2.3.5. 503: Service unavailable . . . . . . . . . . . . . . 15 80 2.4. Revoking an access token . . . . . . . . . . . . . . . . 15 81 2.4.1. 204: Success . . . . . . . . . . . . . . . . . . . . 16 82 2.4.2. 401: Unauthorized . . . . . . . . . . . . . . . . . . 16 83 2.5. Authenticating HTTP requests . . . . . . . . . . . . . . 16 84 2.5.1. Signed GET requests . . . . . . . . . . . . . . . . . 16 85 3. Structured data exchange . . . . . . . . . . . . . . . . . . 18 86 3.1. Making an API request . . . . . . . . . . . . . . . . . . 18 87 3.1.1. 200: OK . . . . . . . . . . . . . . . . . . . . . . . 18 88 3.1.2. 400: Bad Request . . . . . . . . . . . . . . . . . . 18 89 3.1.3. 401: Unauthorized . . . . . . . . . . . . . . . . . . 18 90 3.1.4. 404: Not Found . . . . . . . . . . . . . . . . . . . 19 91 3.1.5. 413: Payload Too Large . . . . . . . . . . . . . . . 19 92 3.1.6. 429: Rate limited . . . . . . . . . . . . . . . . . . 19 93 3.1.7. 500: Internal Server Error . . . . . . . . . . . . . 19 94 3.1.8. 503: Service Unavailable . . . . . . . . . . . . . . 19 95 3.2. The structure of an API request . . . . . . . . . . . . . 19 96 3.3. Errors . . . . . . . . . . . . . . . . . . . . . . . . . 20 97 3.4. Vendor-specific extensions . . . . . . . . . . . . . . . 21 98 3.5. Security . . . . . . . . . . . . . . . . . . . . . . . . 21 99 3.6. Concurrency . . . . . . . . . . . . . . . . . . . . . . . 21 100 3.7. The Number datatype . . . . . . . . . . . . . . . . . . . 22 101 3.8. The Date datatypes . . . . . . . . . . . . . . . . . . . 22 102 3.9. Use of null . . . . . . . . . . . . . . . . . . . . . . . 22 103 3.10. CRUD methods . . . . . . . . . . . . . . . . . . . . . . 22 104 3.10.1. getFoos . . . . . . . . . . . . . . . . . . . . . . 23 105 3.10.2. getFooUpdates . . . . . . . . . . . . . . . . . . . 24 106 3.10.3. setFoos . . . . . . . . . . . . . . . . . . . . . . 26 107 4. Downloading binary data . . . . . . . . . . . . . . . . . . . 29 108 4.1. 200: OK . . . . . . . . . . . . . . . . . . . . . . . . . 30 109 4.2. 401: Unauthorized . . . . . . . . . . . . . . . . . . . . 30 110 4.3. 404: Not Found . . . . . . . . . . . . . . . . . . . . . 30 111 4.4. 503: Service Unavailable . . . . . . . . . . . . . . . . 30 112 5. Uploading binary data . . . . . . . . . . . . . . . . . . . . 30 113 5.1. 201: File uploaded successfully . . . . . . . . . . . . . 30 114 5.2. 400: Bad request . . . . . . . . . . . . . . . . . . . . 31 115 5.3. 401: Unauthorized . . . . . . . . . . . . . . . . . . . . 31 116 5.4. 404: Not Found . . . . . . . . . . . . . . . . . . . . . 32 117 5.5. 413: Request Entity Too Large . . . . . . . . . . . . . . 32 118 5.6. 415: Unsupported Media Type . . . . . . . . . . . . . . . 32 119 5.6.1. 429: Rate limited . . . . . . . . . . . . . . . . . . 32 120 5.7. 503: Service Unavailable . . . . . . . . . . . . . . . . 32 121 6. Push . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32 122 6.1. Event Source . . . . . . . . . . . . . . . . . . . . . . 33 123 6.2. Web hook . . . . . . . . . . . . . . . . . . . . . . . . 34 124 6.2.1. setPushCallback . . . . . . . . . . . . . . . . . . . 34 125 6.2.2. getPushCallback . . . . . . . . . . . . . . . . . . . 35 126 7. References . . . . . . . . . . . . . . . . . . . . . . . . . 35 127 7.1. Normative References . . . . . . . . . . . . . . . . . . 35 128 7.2. URIs . . . . . . . . . . . . . . . . . . . . . . . . . . 36 129 Author's Address . . . . . . . . . . . . . . . . . . . . . . . . 36 131 1. Introduction 133 JMAP is a generic protocol for synchronising data, such as mail, 134 calendars or contacts, between a client and a server. It is 135 optimised for mobile and web environments, and aims to provide a 136 consistent interface to different data types. 138 This specification is for the generic mechanism of authentication and 139 synchronisation. Further specifications define the data models for 140 different data types that may be synchronised via JMAP. 142 JMAP is designed to make efficient use of limited network resources. 143 Multiple API calls may be batched in a single request to the server, 144 reducing round trips and improving battery life on mobile devices. 145 Push connections remove the need for polling, and an efficient delta 146 update mechanism ensures a minimum of data is transferred. 148 JMAP is designed to be horizontally scalable to a very large number 149 of users. This is facilitated by the separate end points for users 150 after login, the separation of binary and structured data, and a 151 shared data model that does not allow data dependencies between 152 accounts. 154 1.1. Notational Conventions 156 The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", 157 "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this 158 document are to be interpreted as described in [RFC2119]. 160 The underlying format used for this specification is JSON. 161 Consequently, the terms "object" and "array" as well as the four 162 primitive types (strings, numbers, booleans, and null) are to be 163 interpreted as described in Section 1 of [RFC7159]. 165 Some examples in this document contain "partial" JSON documents used 166 for illustrative purposes. In these examples, three periods "..." 167 are used to indicate a portion of the document that has been removed 168 for compactness. 170 Types signatures are given for all JSON objects in this document. 171 The following conventions are used: 173 o "Boolean|String" - The value is either a JSON "Boolean" value, or 174 a JSON "String" value. 176 o "Foo" - Any name that is not a native JSON type means an object 177 for which the properties (and their types) are defined elsewhere 178 within this document. 180 o "Foo[]" - An array of objects of type "Foo". 182 o "String[Foo]" - A JSON "Object" being used as a map (associative 183 array), where all the values are of type "Foo". 185 1.2. Terminology 187 1.2.1. User 189 A user represents a set of permissions relating to what data can be 190 seen. To access data in JMAP, you first authenticate as a particular 191 user. 193 1.2.2. Accounts 195 An account is a collection of data. 197 All data, other than the Account objects themselves, belong to a 198 single account. A single account may contain an arbitrary set of 199 data, for example a collection of mail, contacts and calendars. Most 200 operations in JMAP are isolated to a single account; there are a few 201 explicit operations to copy data between them. Certain properties 202 are guaranteed for data within the same account, for example 203 uniqueness of ids within a type in that account. 205 An account is not the same as a user, although it is common for the 206 primary account to directly belong to the user. For example, you may 207 have an account that contains data for a group or business, to which 208 multiple users have access. Users may also have access to accounts 209 belonging to another user if that user is sharing some of their data. 211 1.2.3. Data types and records 213 JMAP provides a uniform interface for creating, retrieving, updating 214 and deleting various types of objects. A *data type* is a collection 215 of named, typed properties, just like the schema for a database 216 table. Each instance of a data type is called a *record*. 218 1.3. Ids 220 All object ids are assigned by the server, and are immutable. They 221 MUST be unique among all objects of the *same type* within the *same 222 account*. Ids may clash across accounts, or for two objects of 223 different types within the same account. 225 Ids are always "String"s. An id MUST be a valid UTF-8 string of at 226 least 1 character in length and maximum 256 bytes in size, but MUST 227 NOT start with the "#" character, as this is reserved for doing back 228 references during object creation (see the _setFoos_ description). 230 1.4. JSON as the data encoding format 232 JSON is a text-based data interchange format as specified in 233 [RFC7159]. The I-JSON format defined in [RFC7493] is a strict subset 234 of this, adding restrictions to avoid potentially confusing scenarios 235 (for example, it mandates that an object MUST NOT have two properties 236 with the same key). 238 All data sent from the client to the server or from the server to the 239 client (except binary file upload/download) MUST be valid I-JSON 240 according to the RFC, and is therefore case-sensitive and encoded in 241 UTF-8. 243 1.5. The JMAP API model 245 All data exchanges are authenticated using an access token. 246 Authentication is covered in section 2. 248 An authenticated client may exchange data with the server using four 249 different mechanisms: 251 1. The client may make an API request to the server to get or set 252 structured data. This request consists of an ordered series of 253 method calls. These are processed by the server, which then 254 returns an ordered series of responses. This is described in 255 section 3. 257 2. The client may download binary files from the server. This is 258 detailed in section 4. 260 3. The client may upload binary files to the server. This is 261 specified in section 5. 263 4. The client may connect to a push channel on the server, to be 264 notified when data has changed. This is explained in section 6. 266 2. Authentication 268 When connecting to any JMAP server, the client must first gain an 269 access token. It cannot just use a username/password directly. This 270 allows the server to know (and show the user) which clients currently 271 have access to the account, and to be able to revoke access 272 individually. 274 The server may support multiple different mechanisms for 275 authenticating a user to gain the access token. It is expected that 276 further types may be added in future extensions to the JMAP 277 specification. 279 2.1. Service autodiscovery 281 To begin authentication, the client needs to know the authentication 282 URL for the JMAP server. 284 There are two standardised autodiscovery methods in use for internet 285 protocols: 287 o *DNS srv* See [RFC6186] and [RFC6764] 288 o *.well-known/servicename* See [RFC5785] 290 A JMAP-supporting host for the domain "example.com" SHOULD publish a 291 SRV record "_jmaps._tcp.example.com" which gives a _hostname_ and 292 _port_ (usually port "443"). The authentication URL is then 293 "https://${hostname}[:${port}]/.well-known/jmap" (following any 294 redirects). 296 If the client has a username in the form of an email address, it MAY 297 use the domain portion of this to attempt autodiscovery of the JMAP 298 server. 300 To support clients that are unable to do SRV lookups, the server 301 SHOULD make the _hostname_ the same domain as the username if 302 possible. 304 2.2. Getting an access token 306 Authorization always starts with the client making a POST request to 307 the authentication URL (found either via service autodiscovery or 308 manual entry). The request MUST be of type "application/json" and 309 specify an "Accept: application/json" header. The body of the 310 request MUST be a single JSON object, encoded in UTF-8, with the 311 following properties: 313 o *username*: "String" The username the client wishes to 314 authenticate. This is normally the primary email address of the 315 user. 317 o *clientName*: "String" The name of the client software. e.g. 318 "Mozilla Thunderbird". 320 o *clientVersion*: "String" Information to identify the version of 321 the client. This MUST change for any changed client code (e.g. a 322 version control tag or counter for development software) and 323 SHOULD sort lexically later for newer versions. 325 o *deviceName*: "String" A human-friendly string to identify the 326 device making the request, e.g. "Joe Blogg's iPhone". 328 The server may use the client/device information to help identify the 329 login to the user in a login log or other security reporting. 330 Although hopefully unnecessary, they may also be helpful for working 331 around client bugs in the future. 333 The server will respond with one of the following HTTP status codes: 335 2.2.1. 200: Success, but more authorization required. 337 The response body will be a single JSON object with the following 338 properties. 340 o *loginId*: "String" An id from the server to allow it to connect 341 the next request with previous requests in the login process. 342 This SHOULD be of limited time validity (e.g. 15 minutes from 343 previous call). 345 o *methods*: "AuthMethod[]" A list of the supported authentication 346 methods to continue with authentication. See below for definition 347 of the *AuthMethod* object. 349 o *prompt*: "String|null" A message to display in the client to the 350 user. The client MUST treat this as plain text, but SHOULD 351 automatically hyperlink any URLs it finds if a system browser is 352 available. 354 This is the standard response to an initial request. Note, a server 355 may return this even if the username is not actually active, to 356 prevent enumeration. The client should then pick one of the 357 _methods_ from the list in the response to continue with 358 authentication (if no methods supported by the client are in the 359 list, it will not be able to get an access token). 361 An *AuthMethod* object MUST have a *type* property. This is a 362 "String" representing the method of authentication. For some types, 363 there may be other values required on the AuthMethod object in 364 addition; see the description of types below. The following types 365 are currently defined, but more may be added in the future. A client 366 SHOULD offer the user the option to choose any of the method types 367 returned that the client supports. The client MUST ignore any types 368 it does not understand: 370 o "external": The user must do something out-of-band to authorize 371 the app. The server SHOULD use the _prompt_ property of the 372 response to tell the user what they need to do. A client that 373 supports the _external_ authorisation type MUST offer a mechanism 374 for the user to indicate to the client when they have completed 375 the out-of-band authentication. 377 o "oauth": OAuth based authentication. For OAuth integration, see 378 the docs of the service in question, since every service 379 implements it slightly differently and the client must register 380 with the service beforehand to use it. If using this method, an 381 access token is obtained entirely through the OAuth mechanism from 382 this point on, and requests will be authenticated as per the OAuth 383 spec. See the "Refetching URL endpoints" section below for how to 384 obtain the URL endpoints after successfully authenticating using 385 OAuth. 387 o "password": The user must input their current password for the 388 account. 390 o "totp": The user must input a TOTP [1] code from a device 391 registered with the account. 393 o "yubikeyotp": The user must input a Yubico OTP [2] code from a 394 Yubikey registered with the account. 396 o "u2f": The user must sign a challenge using a FIDO U2F [3] key 397 registered with the account. The AuthMethod object for this type 398 MUST also have the following properties: 400 * *appId*: "String" The app id to use. 402 * *signChallenge*: "String" The challenge to be signed by the U2F 403 key. 405 * *registeredKeys*: "RegisteredKey[]" The keys associated with 406 this user. A *RegisteredKey* object has the following 407 properties: 409 * *version*: "String" The U2F protocol version. 411 * *keyHandle*: "String" The key handle of the registered key. 413 o "sms": The user must input a one-time code sent via SMS to a phone 414 number registered with the account. The AuthMethod object for 415 this type MUST also have the following property: 417 * *phoneNumbers*: "LoginPhone[]|null" An array of *LoginPhone* 418 objects, each of which represents a phone registered with the 419 account. A *LoginPhone* object has the following properties: 421 + *id*: "String" The id of the phone. This is used when 422 asking the server to send a code. 424 + *number*: "String" The phone number to display to the user 425 to remind them which number the SMS will be/was sent to. 426 This MAY have some characters replaced with an "X" or other 427 "blanked-out" character if the server does not wish to 428 disclose the full phone number at this point. e.g. if the 429 phone registered with the account is "+61 123 456 789", the 430 server might return "+61 1XX XXX X89" as the number. 432 + *isCodeSent*: "Boolean" Has the verification code been sent 433 to this number yet? The server MAY choose to send the SMS 434 before the first time this auth option is returned, or may 435 wait for the user to explicitly request it. 437 If not using ""oauth"", the user will at some point indicate to the 438 client to continue authentication (after inputing any required 439 token/code/password dependent on the auth method chosed). At this 440 point the client submits a POST request to the same URL as before, 441 with the body being a single JSON object with the following 442 properties: 444 o *loginId*: "String" The _loginId_ the server sent from the 445 previous request. 447 o *type*: "String" The type of the method chosen to continue 448 authentication. 450 o *value*: "*" The value as appropriate for the given type: 452 * "external": "null" 454 * "password"/"totp"/"yubikeyotp"/"sms": "String" - the password/ 455 one-time code. 457 * "u2f": "SignResponse" - an object with _keyHandle_, 458 _signatureData_ and _clientData_ "String" properties, as 459 defined in the U2F spec. 461 Note: The client SHOULD NOT store any password/code the user has 462 entered beyond what is required to submit it to the server in this 463 step. 465 The server will then return one of the same set of responses as 466 before, which should be handled the same (for example, if two-factor 467 authentication is required, a "200" response may be returned again 468 and TOTP/U2F prompted for). 470 If the user chooses to authenticate using SMS, they may need to 471 request the server to send the code to a particular number before 472 they can submit a code. To do this, the client submits a POST 473 request to the same URL as before, with the body being a single JSON 474 object with the following properties: 476 o *loginId*: "String" The _loginId_ the server sent from the 477 previous request. 479 o *sendCodeTo*: "String" The id of the phone number to send the code 480 to. 482 The server SHOULD send the code to the given phone if the phone id is 483 valid. If the code has already been sent, it is server-dependent 484 whether it is sent again or ignored. The server MUST return one of 485 the same set of responses as before, which should be handled the same 486 (in most cases this will be a "200" response identical to before 487 except that the _isCodeSent_ property for the phone will now be 488 "true"). 490 2.2.2. 201: Authentication is complete, access token created. 492 The response body will be a single JSON object with the following 493 properties. 495 o *username*: "String" The username that was successfully 496 authenticated. 498 o *accessToken*: "String" The secret token to be used by the client 499 to authenticate all future JMAP requests. The client should keep 500 this secure, preferably in an OS keychain or the like. Since 501 tokens should not be reused across devices or clients, the client 502 SHOULD NOT reveal this token to the user. 504 o *accounts*: "String[Account]" A map of *account id* to Account 505 object for each account the user has access to. A single access 506 token may provide access to multiple accounts, for example if 507 another user is sharing their mail with the logged in user, or if 508 there is an account that contains data for a group or business. 509 All data belongs to a single account. With the exception of a few 510 explicit operations to copy data between accounts, all JMAP 511 methods take an _accountId_ argument that specifies on which 512 account the operations are to take place. This argument is always 513 optional; if not specified, the primary account is used. All ids 514 (other than Account ids of course) are only unique within their 515 account. In the event of a severe internal error, a server may 516 have to reallocate ids or do something else that violates standard 517 JMAP data constraints. In this situation, the data on the server 518 is no longer compatible with cached data the client may have from 519 before. The server MUST treat this as though the account has been 520 deleted and then recreated with a new account id. Clients will 521 then be forced to throw away any data with the old account id and 522 refetch all data from scratch. An *Account* object has the 523 following properties: 525 * *name*: "String" A user-friendly string to show when presenting 526 content from this account, e.g. the email address representing 527 the owner of the account. 529 * *isPrimary*: "Boolean" This MUST be true for exactly one of the 530 accounts returned. This is to be considered the user's main or 531 default account by the client. 533 * *isReadOnly*: "Boolean" This is "true" if the entire account is 534 read-only. 536 * *hasDataFor*: "String[]" A list of the data profiles available 537 in this account. Each future JMAP data types specification 538 will define a profile name to encompass that set of types. 540 o *capabilities*: "String[Object]" An object specifying the 541 capabilities of this server. The keys are URIs, which specify the 542 specifications supported by the server. The value for each of 543 these keys is an object that MAY include further information about 544 the server's capabilities in relation to that spec. The client 545 MUST ignore any properties it does not understand. The 546 capabilities object MUST include a property called "{TODO: URI for 547 this spec}". The value of this property is an object which SHOULD 548 contain the following information on server capabilities: 550 * *maxSizeUpload*: "Number" The maximum file size, in bytes, that 551 the server will accept for a single file upload (for any 552 purpose). 554 * *maxConcurrentUpload*: "Number" The maximum number of 555 concurrent requests the server will accept to the upload 556 endpoint. 558 * *maxSizeRequest*: "Number" The maximum size, in bytes, that the 559 server will accept for a single request to the API endpoint. 561 * *maxConcurrentRequests*: "Number" The maximum number of 562 concurrent requests the server will accept to the API endpoint. 564 * *maxCallsInRequest*: "Number" The maximum number of method 565 calls the server will accept in a single request to the API 566 endpoint. 568 * *maxObjectsInGet*: "Number" The maximum number of obje ts that 569 the client may request in a single "getFoos" type method call. 571 * *maxObjectsInSet*: "Number" The maximum number of objects the 572 client may send to create, update or destroy in a single 573 "setFoos" type method call. 575 Future specifications will define their own properties on the 576 capabilities object. 578 o *apiUrl*: "String" The URL to use for JMAP API requests. 580 o *downloadUrl*: "String" The URL endpoint to use when downloading 581 files (see the Download section of this spec), in [RFC6570] URI 582 Template (level 1) format. The URL MUST contain a variable called 583 "blobId". The URL SHOULD contain a variable called "name". 585 o *uploadUrl*: "String" The URL endpoint to use when uploading files 586 (see the Upload section of this spec). 588 o *eventSourceUrl*: "String" The URL to connect to for push events 589 (see the Push section of this spec). 591 URLs are returned only after logging in. This allows different URLs 592 to be used for users located in different geographic datacentres 593 within the same service. 595 Note, if authentication is done via IP or mobile subscriber ID or 596 some similar mechanism, a "201" response MAY be returned in response 597 to the initial request (with just the username and client info). 599 2.2.3. 400: Malformed request 601 The request is of the wrong content type, or does not contain data in 602 the expected format. The client MUST NOT retry the same request. 603 There is no content in the response. 605 2.2.4. 403: Authentication step failed, but client may try again 607 Returned in response to a continuation request which failed (e.g. the 608 password entered was not correct, or the out-of-band step was not 609 completed successfully). The response body will be a single JSON 610 object with the same properties as the "200" response, and the client 611 may try again. 613 2.2.5. 404: Not found 615 The JMAP authentication server is not available at this address. The 616 client needs to rediscover the authentication URL. There is no 617 content in the response. 619 2.2.6. 410: Restart authentication 621 The login attempt has failed permanently. This may be due to a 622 password being incorrect, the login id expiring, or any other reason. 623 The client MUST restart authentication (go back to sending the 624 username and client info to the server). There is no content in the 625 response. 627 2.2.7. 429: Rate limited 629 Returned if the server is temporarily blocking this IP/client from 630 authenticating. This may be due to too many failed password 631 attempts, or detected username enumeration attempts, or any other 632 reason. (Legitimate) clients should wait a while then try again. 633 There is no content in the response. 635 2.2.8. 500: Internal server error 637 Something has gone wrong internally, and the server is in a broken 638 state. Don't automatically retry. There is no content in the 639 response. 641 2.2.9. 503: Service unavailable 643 The server is currently down. Try again later with exponential 644 backoff. There is no content in the response. 646 2.3. Refetching URL endpoints 648 A server MAY (although SHOULD NOT) move end points for any services 649 other than authentication at any time. If a request to the API/file 650 upload/event source endpoint returns a "404", the client MUST refetch 651 the URL endpoints. To do this, it should make an authenticated GET 652 request to the authentication URL (see below for how to authenticate 653 requests). 655 For OAuth logins, this is how the URLs may be fetched initially as 656 well. 658 The server MUST respond with one of the following status codes: 660 2.3.1. 201: Authentication is complete, access token created. 662 The request was successful. The response will be of type 663 "application/json" and consists of a single JSON object containing 664 the following properties: 666 o *username*: "String" The username that was successfully 667 authenticated. 669 o *accounts*: "String[Account]" An object representing the accounts 670 the user has access to. See the full description above. 672 o *capabilities*: "String[Object]" An object specifying the 673 capabilities of this server. See the full description above. 675 o *apiUrl*: "String" The URL to use for JMAP API requests. 677 o *downloadUrl*: "String" The URL endpoint to use when downloading 678 files (see above). 680 o *uploadUrl*: "String" The URL endpoint to use when uploading files 681 (see the Upload section of this spec). 683 o *eventSourceUrl*: "String" The URL to connect to for push events 684 (see the Push section of this spec). 686 2.3.2. 403: Restart authentication 688 The "Authorization" header was missing or did not contain a valid 689 token. Reauthenticate and then retry the request. There is no 690 content in the response. 692 2.3.3. 404: Not found 694 The JMAP server is no longer here. There is no content in the 695 response. 697 2.3.4. 500: Internal server error 699 Something has gone wrong internally, and the server is in a broken 700 state. Don't automatically retry. There is no content in the 701 response. 703 2.3.5. 503: Service unavailable 705 The server is currently down. Try again later with exponential 706 backoff. There is no content in the response. 708 2.4. Revoking an access token 710 The validity of an access token is determined by the server. It may 711 be valid for a limited time only, or expire after a certain time of 712 inactivity, or be valid indefinitely etc. If an access token 713 expires, it MUST NOT be resurrected. The client MUST restart the 714 authentication process to get a new access token. 716 For OAuth, see the provider's documentation on revoking access 717 tokens. 719 Otherwise, a client may revoke an access token at any time by making 720 an authenticated DELETE HTTP request to the authentication URL (the 721 one used to get the token in the first place). The response from the 722 server will be one of the following: 724 2.4.1. 204: Success 726 The access token has now been revoked. There is no content in the 727 response. 729 2.4.2. 401: Unauthorized 731 Failed due to missing "Authorization" header, or the "Authorization" 732 header did not contain a valid access token. As per the HTTP spec, 733 the response MUST have a "WWW-Authenticate: Bearer" header. There is 734 no content in the response. 736 2.5. Authenticating HTTP requests 738 All HTTP requests other than to the authentication URL must be 739 authenticated. To do this, the client MUST add an "Authorization" 740 header to each request. 742 Once authenticated, the client will have an access token. This is 743 used with the "Bearer" scheme as specified in [RFC6750] to 744 authenticate HTTP requests. 746 For example, if _user@example.com_ successfully logged in and the 747 client received an _accessToken_ of "abcdef1234567890", to 748 authenticate requests you would add the following header: 750 Authorization: Bearer abcdef1234567890 752 2.5.1. Signed GET requests 754 Sometimes, particularly in the browser context, authenticating a GET 755 request using the usual "Authorization" header is not easily 756 implemented. In such situations, a client may use a signed request 757 instead. A signed request is an unauthenticated GET request 758 containing a special query string parameter (a so-called "token"). 759 The process below describes how a client can obtain such a token, 760 then use it to download the file: 762 1. The client makes an authenticated POST request to the URL for 763 which it is unable to make an authenticated GET request. If 764 authorization is granted, the server MUST send the token back as 765 the body of the response, in one of the following forms: 767 * A JSON Web Token [4], in this case the response MUST have a 768 "Content-Type" of "application/jwt". 770 * A plain "String" or any other data structure, in this case the 771 response SHOULD have a "Content-Type" of "text/plain" unless 772 another standardised MIME type is applicable. 774 2. The client makes an unauthenticated GET request to the same URL 775 but with "access_token=" 776 appended to the query part (see [RFC3986] section 3.4 for 777 details). If no query part was present in the URL before this 778 operation, a new query part is created. The server MUST send 779 back the contents of the requested file, as if it were requested 780 through a standard authenticated GET request to the URL. 782 The server SHOULD expire any given signing "token" quickly for 783 obvious security reasons, but the actual expiration policy is up to 784 the server implementation. 786 Sample HTTP exchange demonstrating the use of a signed request to 787 download a file: 789 o Obtain a token 791 POST /jmap/download/act1/blob2/mydocument.pdf HTTP/1.1 792 Host: server.example.com 793 Authorization: Bearer abcdef1234567890 795 HTTP/1.1 200 OK 796 Content-Type: text/plain 797 Content-Length: 10 799 abcDEfGhIJ 801 o Download the file 803 GET /jmap/download/act1/blob2/mydocument.pdf?access_token=abcDEfGhIJ HTTP/1.1 804 Host: server.example.com 806 HTTP/1.1 200 OK 807 Content-Type: application/pdf 808 Content-Length: 987654 810 << binary content >> 812 3. Structured data exchange 814 The client may make an API request to the server to get or set 815 structured data. This request consists of an ordered series of 816 method calls. These are processed by the server, which then returns 817 an ordered series of responses. 819 3.1. Making an API request 821 To make an API request, the client makes an authenticated POST 822 request to the API URL; see the Authentication section of the spec 823 for how to discover this URL and how to authenticate requests. 825 The request MUST have a content type of "application/json" and be 826 encoded in UTF-8. 828 The server SHOULD respond with one of the following HTTP response 829 codes: 831 3.1.1. 200: OK 833 The API request was successful. The response will be of type 834 "application/json" and consists of the response to the API calls, as 835 described below. 837 3.1.2. 400: Bad Request 839 The request was malformed. For example, it may have had the wrong 840 content type, or have had a JSON object that did not conform to the 841 API calling structure (see _The structure of an API request_ below). 842 The client SHOULD NOT retry the same request. There is no content in 843 the response. 845 3.1.3. 401: Unauthorized 847 The "Authorization" header was missing or did not contain a valid 848 token. Reauthenticate and then retry the request. As per the HTTP 849 spec, the response MUST have a "WWW-Authenticate" header listing the 850 available authentication schemes. There is no content in the 851 response. 853 3.1.4. 404: Not Found 855 The API endpoint has moved. See the Authentication section of the 856 spec for how to rediscover the current URL to use. There is no 857 content in the response. 859 3.1.5. 413: Payload Too Large 861 Returned if the client makes a request with more method calls than 862 the server is willing to accept in a single request, or if the total 863 bytes of the request is larger than the max size the server is 864 willing to accept. 866 3.1.6. 429: Rate limited 868 Returned if the client has made too many requests recently, or has 869 too many concurrent requests currently in progress. Clients SHOULD 870 wait a while then try again. The response MAY include a "Retry- 871 After" header indicating how long to wait before making a new 872 request. 874 3.1.7. 500: Internal Server Error 876 Something has gone wrong internally, and the server is in a broken 877 state. Don't automatically retry. There is no content in the 878 response. 880 3.1.8. 503: Service Unavailable 882 The server is currently down. Try again later with exponential 883 backoff. There is no content in the response. 885 3.2. The structure of an API request 887 The client initiates an API request by sending the server a JSON 888 array. Each element in this array is another array representing a 889 method invocation on the server. The server will process the method 890 calls and return a response consisting of an array in the same 891 format. Each method call always contains three elements: 893 1. The *name* of the method to call, or the name of the response 894 from the server. This is a "String". 896 2. An "Object" containing _named_ *arguments* for that method or 897 response. 899 3. A *client id*: an arbitrary "String" to be echoed back with the 900 responses emitted by that method call (as we'll see lower down, a 901 method may return 1 or more responses, as some methods make 902 implicit calls to other ones). 904 Example query: 906 [ 907 ["method1", {"arg1": "arg1data", "arg2": "arg2data"}, "#1"], 908 ["method2", {"arg1": "arg1data"}, "#2"], 909 ["method3", {}, "#3"] 910 ] 912 The method calls MUST be processed sequentially, in order. Each API 913 request (which, as shown, may contain multiple method calls) receives 914 a JSON response in exactly the same format. The output of the 915 methods MUST be added to the array in the same order as the methods 916 are processed. 918 Example response: 920 [ 921 ["responseFromMethod1", {"arg1": 3, "arg2": "foo"}, "#1"], 922 ["responseFromMethod2", {"isBlah": true}, "#2"], 923 ["anotherResponseFromMethod2", { 924 "data": 10, 925 "yetmoredata": "Hello" 926 }, "#2"], 927 ["aResponseFromMethod3", {}, "#3"] 928 ] 930 3.3. Errors 932 If the data sent as an API request is not valid JSON or does not 933 match the structure above, an error will be returned at the transport 934 level. For example, when using JMAP over HTTP, a "400 Bad Request" 935 error will be returned at the HTTP level. 937 Possible errors for each method are specified in the method 938 descriptions. If a method encounters an error, the appropriate 939 "error" response MUST be inserted at the current point in the output 940 array and, unless otherwise specified, further processing MUST NOT 941 happen within that method call. 943 Any further method calls in the request MUST then be processed as 944 normal. 946 An "error" response looks like this: 948 ["error", { 949 type: "unknownMethod" 950 }, "client-id"] 952 The response name is "error", and it has a type property as specified 953 in the method description. Other properties may be present with 954 further information; these are detailed in the method descriptions 955 where appropriate. 957 Any method MAY return an error of type "serverError" if an unexpected 958 or unknown error occurs during the processing of that call. The 959 state of the server after such an error is undefined. 961 If an unknown method is called, an "unknownMethod" error (this is the 962 type shown in the example above) MUST be inserted and then the next 963 method call MUST be processed as normal. 965 If an unknown argument or invalid arguments (wrong type, or in 966 violation of other specified constraints) are supplied to a method, 967 an "invalidArguments" error MUST be inserted and then the next method 968 call MUST be processed as normal. 970 3.4. Vendor-specific extensions 972 Individual services will have custom features they wish to expose 973 over JMAP. This may take the form of extra datatypes and/or methods 974 not in the spec, or extra arguments to JMAP methods, or extra 975 properties on existing data types (which may also appear in arguments 976 to methods that take property names). To ensure compatibility with 977 clients that don't know about a specific custom extension, and for 978 compatibility with future versions of JMAP, the server MUST ONLY 979 expose these extensions if the client explicitly opts in. Without 980 opt-in, the server MUST follow the spec and reject anything that does 981 not conform to it as specified. 983 3.5. Security 985 As always, the server must be strict about data received from the 986 client. Arguments need to be checked for validity; a malicious user 987 could attempt to find an exploit through the API. In case of invalid 988 arguments (unknown/insufficient/wrong type for data etc.) the method 989 MUST return an "invalidArguments" error and terminate. 991 3.6. Concurrency 993 To ensure the client always sees a consistent view of the data, the 994 state accessed by a method call MUST NOT change during the execution 995 of the method, except due to actions by the method call itself. The 996 state MAY change in-between method calls (even within a single API 997 request). 999 3.7. The Number datatype 1001 The JSON datatypes are limited to those found in JavaScript. A 1002 "Number" in JavaScript is represented as a signed double (64-bit 1003 floating point). However, except where explicitly specified, all 1004 numbers used in this API are unsigned integers <= 2^53 (the maximum 1005 integer that may be reliably stored in a double). This implicitly 1006 limits the maximum length of message lists in queries and the like. 1008 3.8. The Date datatypes 1010 Where a JMAP API specifies "Date" as a type, it means a string in 1011 [RFC3339] _date-time_ format, with the _time-offset_ component always 1012 "Z" (i.e. the date-time MUST be in UTC time) and _time-secfrac_ 1013 always omitted. The "T" and "Z" MUST always be upper-case. For 1014 example, ""2014-10-30T14:12:00Z"". 1016 3.9. Use of null 1018 Unless otherwise specified, a missing property in the arguments 1019 object of a request (from the client), or a response (from the 1020 server) MUST be intepreted exactly the same as that property having 1021 the value "null". 1023 Unless otherwise specified, a missing property in a data object MUST 1024 be interpreted in the following ways: - In the response to a 1025 _getFoos_ style call, or when *creating* an object in a _setFoos_ 1026 style call, a missing property MUST be interpreted as though it had 1027 the default value for that type, or "null" if no default is 1028 specified. - When *updating* an object in a _setFoos_ style call, a 1029 missing property MUST be interpreted as the existing value for that 1030 property (i.e. don't update it). 1032 For network efficiency, when fetching the server and client may make 1033 use of the above and omit properties which have the default value for 1034 the data type. 1036 3.10. CRUD methods 1038 JMAP provides a uniform interface for creating, retrieving, updating 1039 and deleting various types of objects. For a "Foo" data type, 1040 records of that type would be fetched via a "getFoos" call and 1041 modified via a "setFoos" call. Delta updates may be fetched via a 1042 "getFooUpdates" call. These methods all follow a standard format as 1043 described below. 1045 3.10.1. getFoos 1047 Objects of type *Foo* are fetched via a call to _getFoos_. Methods 1048 with a name starting with "get" MUST NOT alter state on the server. 1050 This method may take some or all of the following arguments; see the 1051 definition of the data type in question. However, if one of the 1052 following arguments is available, it will behave exactly as specified 1053 below. 1055 o *accountId*: "String|null" The id of the Account to use. If 1056 "null", the primary account is used. 1058 o *ids*: "String[]|null" The ids of the Foo objects to return. If 1059 "null" then *all* records of the data type are returned, if this 1060 is supported for that data type. 1062 o *properties*: "String[]|null" If supplied, only the properties 1063 listed in the array are returned for each Foo object. If "null", 1064 all properties of the object are returned. The id of the object 1065 is *always* returned, even if not explicitly requested. 1067 The response to "getFoos" is called "foos". It has the following 1068 arguments: 1070 o *accountId*: "String" The id of the account used for the call. 1072 o *state*: "String" A string representing the state on the server 1073 for *all* the data of this type. If the data changes, this string 1074 will change. It is used to get delta updates, if supported for 1075 the type. 1077 o *list*: "Foo[]" An array of the Foo objects requested. This is 1078 the *empty array* if no objects were found, or if the _ids_ 1079 argument passed in was also the empty array. 1081 o *notFound*: "String[]|null" This array contains the ids passed to 1082 the method for records that do not exist. This property is "null" 1083 if all requested ids were found, or if the _ids_ argument passed 1084 in was either "null" or the empty array. 1086 The following error may be returned instead of the "foos" response: 1088 "accountNotFound": Returned if an _accountId_ was explicitly included 1089 with the request, but it does not correspond to a valid account. 1091 "accountNotSupportedByMethod": Returned if the _accountId_ given 1092 corresponds to a valid account, but the account does not support this 1093 data type. 1095 "requestTooLarge": Returned if the number of _ids_ requested by the 1096 client exceeds the maximum number the server is willing to process in 1097 a single method call. 1099 "invalidArguments": Returned if one of the arguments is of the wrong 1100 type, or otherwise invalid. A "description" property MAY be present 1101 on the response object to help debug with an explanation of what the 1102 problem was. 1104 3.10.2. getFooUpdates 1106 When the state of the set of Foo records changes on the server 1107 (whether due to creation, updates or deletion), the _state_ property 1108 of the _foos_ response will change. The _getFooUpdates_ call allows 1109 a client to efficiently update the state of any its Foo cache to 1110 match the new state on the server. It takes the following arguments: 1112 o *accountId*: "String|null" The id of the Account to use. If 1113 "null", the primary account is used. 1115 o *sinceState*: "String" The current state of the client. This is 1116 the string that was returned as the _state_ argument in the _foos_ 1117 response. The server will return the changes made since this 1118 state. 1120 o *maxChanges*: "Number|null" The maximum number of Foo ids to 1121 return in the response. The server MAY choose to return fewer 1122 than this value, but MUST NOT return more. If not given by the 1123 client, the server may choose how many to return. If supplied by 1124 the client, the value MUST be a positive integer greater than 0. 1125 If a value outside of this range is given, the server MUST reject 1126 the call with an "invalidArguments" error. 1128 o *fetchRecords*: "Boolean|null" If "true", immediately after 1129 outputting the _fooUpdates_ response, the server will make an 1130 implicit call to _getFoos_ with the _changed_ property of the 1131 response as the _ids_ argument. If "false" or "null", no implicit 1132 call will be made. 1134 o *fetchRecordProperties*: "String[]|null" If the _getFoos_ method 1135 takes a _properties_ argument, this argument is passed through on 1136 implicit calls (see the _fetchRecords_ argument). 1138 The response to _getFooUpdates_ is called _fooUpdates_. It has the 1139 following arguments: 1141 o *accountId*: "String" The id of the account used for the call. 1143 o *oldState*: "String" This is the _sinceState_ argument echoed 1144 back; the state from which the server is returning changes. 1146 o *newState*: "String" This is the state the client will be in after 1147 applying the set of changes to the old state. 1149 o *hasMoreUpdates*: "Boolean" If "true", the client may call 1150 _getFooUpdates_ again with the _newState_ returned to get further 1151 updates. If "false", _newState_ is the current server state. 1153 o *changed*: "String[]" An array of Foo ids for records which have 1154 been created or changed but not destroyed since the oldState. 1156 o *removed*: "String[]" An array of Foo ids for records which have 1157 been destroyed since the old state. 1159 The _maxChanges_ argument (and _hasMoreUpdates_ response argument) is 1160 available for data types with potentially large amounts of data (i.e. 1161 those for which there is a _getFooList_ method available for loading 1162 the data in pages). If a _maxChanges_ is supplied, or set 1163 automatically by the server, the server must try to limit the number 1164 of ids across _changed_ and _removed_ to the number given. If there 1165 are more changes than this between the client's state and the current 1166 server state, the update returned MUST take the client to an 1167 intermediate state, from which the client can continue to call 1168 _getFooUpdates_ until it is fully up to date. The server MUST NOT 1169 return more ids than the _maxChanges_ total. If the server is unable 1170 to calculate a suitable intermediate state, it MUST return a 1171 "cannotCalculateChanges" error. 1173 If a Foo record has been modified AND deleted since the oldState, the 1174 server SHOULD just return the id in the _removed_ response, but MAY 1175 return it in the changed response as well. If a Foo record has been 1176 created AND deleted since the oldState, the server SHOULD remove the 1177 Foo id from the response entirely, but MAY include it in the 1178 _removed_ response. 1180 The following errors may be returned instead of the _fooUpdates_ 1181 response: 1183 "accountNotFound": Returned if an _accountId_ was explicitly included 1184 with the request, but it does not correspond to a valid account. 1186 "accountNotSupportedByMethod": Returned if the _accountId_ given 1187 corresponds to a valid account, but the account does not support this 1188 data type. 1190 "invalidArguments": Returned if the request does not include one of 1191 the required arguments, or one of the arguments is of the wrong type, 1192 or otherwise invalid. A _description_ property MAY be present on the 1193 response object to help debug with an explanation of what the problem 1194 was. 1196 "cannotCalculateChanges": Returned if the server cannot calculate the 1197 changes from the state string given by the client. Usually due to 1198 the client's state being too old, or the server being unable to 1199 produce an update to an intermediate state when there are too many 1200 updates. The client MUST invalidate its Foo cache. 1202 3.10.3. setFoos 1204 Modifying the state of Foo objects on the server is done via the 1205 _setFoos_ method. This encompasses creating, updating and destroying 1206 Foo records. This has two benefits: 1208 1. It allows the server to sort out ordering and dependencies that 1209 may exist if doing multiple operations at once (for example to 1210 ensure there is always a minimum number of a certain record 1211 type). 1213 2. A single call can make all the changes you want to a particular 1214 type. If the client wants to use _ifInState_ to guard its 1215 changes, it can only make one call that modifies a particular 1216 type per request, since it will need the new state following that 1217 call to make the next modification. 1219 The _setFoos_ method takes the following arguments: 1221 o *accountId*: "String|null" The id of the Account to use. If 1222 "null", the primary account is used. 1224 o *ifInState*: "String|null" This is a state string as returned by 1225 the _getFoos_ method. If supplied, the string must match the 1226 current state, otherwise the method will be aborted and a 1227 "stateMismatch" error returned. If "null", any changes will be 1228 applied to the current state. 1230 o *create*: "String[Foo]|null" A map of _creation id_ (an arbitrary 1231 string set by the client) to Foo objects (containing all 1232 properties except the id, unless otherwise stated in the specific 1233 documentation of the data type). If "null", no objects will be 1234 created. 1236 o *update*: "String[Foo]|null" A map of id to Foo objects. The 1237 object may omit any property; only properties that have changed 1238 need be included. If "null", no objects will be updated. 1240 o *destroy*: "String[]|null" A list of ids for Foo objects to 1241 permanently delete. If "null", no objects will be deleted. 1243 Each create, update or destroy is considered an atomic unit. It is 1244 permissible for the server to commit some of the changes but not 1245 others, however it is not permissible to only commit part of an 1246 update to a single record (e.g. update a _name_ property but not a 1247 _count_ property, if both are supplied in the update object). 1249 If a create, update or destroy is rejected, the appropriate error 1250 MUST be added to the notCreated/notUpdated/notDestroyed property of 1251 the response and the server MUST continue to the next create/update/ 1252 destroy. It does not terminate the method. 1254 If an id given cannot be found, the update or destroy MUST be 1255 rejected with a "notFound" set error. 1257 Some record objects may hold references to others (foreign keys). 1258 When records are created or modified, they may reference other 1259 records being created _in the same API request_ by using the creation 1260 id prefixed with a "#". The order of the method calls in the request 1261 by the client MUST be such that the record being referenced is 1262 created in the same or an earlier call. The server thus never has to 1263 look ahead. Instead, while processing a request (a series of method 1264 calls), the server MUST keep a simple map for the duration of the 1265 request of creation id to record id for each newly created record, so 1266 it can substitute in the correct value if necessary in later method 1267 calls. Creation ids sent by the client SHOULD be unique within the 1268 single API request for a particular data type. If a creation id is 1269 reused, the server MUST map the creation id to the most recently 1270 created item with that id. 1272 The response to _setFoos_ is called _foosSet_. It has the following 1273 arguments: 1275 o *accountId*: "String" The id of the account used for the call. 1277 o *oldState*: "String|null" The state string that would have been 1278 returned by _getFoos_ before making the requested changes, or 1279 "null" if the server doesn't know what the previous state string 1280 was. 1282 o *newState*: "String" The state string that will now be returned by 1283 _getFoos_. 1285 o *created*: "String[Foo]" A map of the creation id to an object 1286 containing any *server-assigned* properties of the Foo object 1287 (including the id) for all successfully created records. 1289 o *updated*: "String[]" A list of Foo ids for records that were 1290 successfully updated. 1292 o *destroyed*: "String[]" A list of Foo ids for records that were 1293 successfully destroyed. 1295 o *notCreated*: "String[SetError]" A map of creation id to a 1296 SetError object for each record that failed to be created. The 1297 possible errors are defined in the description of the method for 1298 specific data types. 1300 o *notUpdated*: "String[SetError]" A map of Foo id to a SetError 1301 object for each record that failed to be updated. The possible 1302 errors are defined in the description of the method for specific 1303 data types. 1305 o *notDestroyed*: "String[SetError]" A map of Foo id to a SetError 1306 object for each record that failed to be destroyed. The possible 1307 errors are defined in the description of the method for specific 1308 data types. 1310 A *SetError* object has the following properties: 1312 o *type*: "String" The type of error. 1314 o *description*: "String|null" A description of the error to display 1315 to the user. 1317 Other properties may also be present on the object, as described in 1318 the relevant methods. 1320 The following errors may be returned instead of the "foosSet" 1321 response: 1323 "accountNotFound": Returned if an _accountId_ was explicitly included 1324 with the request, but it does not correspond to a valid account. 1326 "accountNotSupportedByMethod": Returned if the _accountId_ given 1327 corresponds to a valid account, but the account does not support this 1328 data type. 1330 "accountReadOnly": Returned if the account has isReadOnly == true. 1332 "requestTooLarge": Returned if the total number of objects to create, 1333 update or destroy exceeds the maximum number the server is willing to 1334 process in a single method call. 1336 "invalidArguments": Returned if one of the arguments is of the wrong 1337 type, or otherwise invalid. A "description" property MAY be present 1338 on the response object to help debug with an explanation of what the 1339 problem was. 1341 "stateMismatch": Returned if an "ifInState" argument was supplied and 1342 it does not match the current state. 1344 4. Downloading binary data 1346 Binary data is referenced by a _blobId_ in JMAP. A blob id does not 1347 have a name inherent to it, but this is normally given in the same 1348 object that contains the blob id. 1350 After completing authentication, the client will receive a 1351 _downloadUrl_ as part of the response. This is in [RFC6570] URI 1352 Template (level 1) format. The URL MUST contain variables called 1353 "accountId" and "blobId". The URL SHOULD contain a variable called 1354 "name". 1356 The client may use this template in combination with an accountId and 1357 blobId to download any binary data (files) referenced by other 1358 objects. Since a blob is not associated with a particular name, the 1359 template SHOULD allow a name to be substituted in as well; the server 1360 will return this as the filename if it sets a "Content-Disposition" 1361 header. 1363 To download the data the client MUST make an authenticated GET 1364 request to the download URL with the appropriate variables 1365 substituted in, and then follow any redirects. In situations where 1366 it's not easy to authenticate the download request (e.g.: when 1367 downloading a file through a link in a HTML document), the client MAY 1368 use a signed GET request (see below for how to issue a signed 1369 request). 1371 After following redirects, the server MUST return one of the 1372 following responses to a request to the download URL: 1374 4.1. 200: OK 1376 Request successful. The binary data is returned. The "Content-Type" 1377 header SHOULD be set to the correct content type for the content. 1379 4.2. 401: Unauthorized 1381 The "Authorization" header was missing or did not contain a valid 1382 token and there was no "access_token" query parameter, or it did not 1383 contain a valid token. Reauthenticate and then retry the request. 1384 As per the HTTP spec, the response MUST have a "WWW-Authenticate" 1385 header listing the available authentication schemes. 1387 The server MAY return an HTML page response, which clients MAY show 1388 to the user. This is primarily for when the URL is passed off to the 1389 browser, and the JMAP client may not see the actual response. 1391 4.3. 404: Not Found 1393 The file was not found at this address. 1395 4.4. 503: Service Unavailable 1397 The server is currently down. The client should try again later with 1398 exponential backoff. There is no content in the response. 1400 5. Uploading binary data 1402 There is a single endpoint which handles all file uploads, regardless 1403 of what they are to be used for. To upload a file, the client 1404 submits a POST request to the file upload endpoint (see the 1405 authentication section for information on how to obtain this URL). 1406 The Content-Type MUST be correctly set for the type of the file being 1407 uploaded. The request MUST be authenticated as per any HTTP request. 1408 The request MAY include an "X-JMAP-AccountId" header, with the value 1409 being the account to use for the request. Otherwise, the default 1410 account will be used. 1412 The server will respond with one of the following HTTP response 1413 codes: 1415 5.1. 201: File uploaded successfully 1417 The content of the response is a single JSON object with the 1418 following properties: 1420 o *accountId*: "String" The id of the account used for the call. 1422 o *blobId*: "String", The id representing the binary data uploaded. 1423 The data for this id is immutable. The id _only_ refers to the 1424 binary data, not any metadata. 1426 o *type*: "String" The content type of the file. 1428 o *size*: "Number" The size of the file in bytes. 1430 o *expires*: "Date" The date the file will be deleted from tempoary 1431 storage if not referenced by another object, e.g. used in a draft. 1433 Once the file has been used, for example attached to a draft message, 1434 the file will no longer expire, and is instead guaranteed to exist 1435 while at least one other object references it. Once no other object 1436 references it, the server MAY immediately delete the file at any 1437 time. It MUST NOT delete the file during the method call which 1438 removed the last reference, so that if there is a create and a delete 1439 within the same call that both reference the file, this always works. 1441 If uploading a file would take the user over quota, the server SHOULD 1442 delete previously uploaded (but unused) files before their expiry 1443 time. This means a client does not have to explicitly delete unused 1444 temporary files (indeed, there is no way for it to do so). 1446 If identical binary content is uploaded, the same _blobId_ SHOULD be 1447 returned. 1449 The server MUST return one of the following responses to a request to 1450 the upload URL: 1452 5.2. 400: Bad request 1454 The request was malformed (this includes the case where an "X-JMAP- 1455 AccountId" header is sent with a value that does not exist). The 1456 client SHOULD NOT retry the same request. There is no content in the 1457 response. 1459 5.3. 401: Unauthorized 1461 The "Authorization" header was missing or did not contain a valid 1462 token. Reauthenticate and then retry the request. As per the HTTP 1463 spec, the response MUST have a "WWW-Authenticate" header listing the 1464 available authentication schemes. There is no content in the 1465 response. 1467 5.4. 404: Not Found 1469 The upload endpoint has moved. See the Authentication section of the 1470 spec for how to rediscover the current URL to use. There is no 1471 content in the response. 1473 5.5. 413: Request Entity Too Large 1475 The file is larger than the maximum size the server is willing to 1476 accept for a single file. The client SHOULD NOT retry uploading the 1477 same file. There is no content in the response. The client may 1478 discover the maximum size the server is prepared to accept by 1479 inspecting the server _capabilities_ object, returned with the 1480 successful authentication response. 1482 5.6. 415: Unsupported Media Type 1484 The server MAY choose to not allow certain content types to be 1485 uploaded, such as executable files. This error response is returned 1486 if an unacceptable type is uploaded. The client SHOULD NOT retry 1487 uploading the same file. There is no content in the response. 1489 5.6.1. 429: Rate limited 1491 Returned if the client has made too many upload requests recently, or 1492 has too many concurrent uploads currently in progress. Clients 1493 SHOULD wait a while then try again. The response MAY include a 1494 "Retry-After" header indicating how long to wait before making a new 1495 request. 1497 5.7. 503: Service Unavailable 1499 The server is currently down. The client should try again later with 1500 exponential backoff. There is no content in the response. 1502 6. Push 1504 Any modern email client should be able to update instantly whenever 1505 the data on the server is changed by another client or message 1506 delivery. Push notifications in JMAP occur out-of-band (i.e. not 1507 over the same connection as API exchanges) so that they can make use 1508 of efficient native push mechanisms on different platforms. 1510 The general model for push is simple and does not send any sensitive 1511 data over the push channel, making it suitable for use with less 1512 trusted 3rd party intermediaries. The format allows multiple changes 1513 to be coalesced into a single push update, and the frequency of 1514 pushes to be rate limited by the server. It doesn't matter if some 1515 push events are dropped before they reach the client; it will still 1516 get all changes next time it syncs. 1518 When something changes on the server, the server pushes a small JSON 1519 object to the client with the following property: 1521 o *changed*: "String[ChangedStates]" A map of _account id_ to an 1522 object encoding the state of data types which have changed for 1523 that account since the last push event, for each of the accounts 1524 to which the user has access and for which something has changed. 1526 A *ChangedStates* object is a map of the type name (e.g. "Mailbox" 1527 or "Message") to the current state token for that type (i.e. the 1528 "state" property that would currently be returned by a call to 1529 "getMailboxes" or "getMessages", as appropriate). The types in JMAP 1530 are "Mailbox", "Thread", "Message", "ContactGroup", "Contact", 1531 "Calendar", "CalendarEvent". 1533 Upon receiving this data, the client can compare the new state 1534 strings with its current values to see whether it has the current 1535 data for these types. The actual changes can then be efficiently 1536 fetched in a single standard API request (using the _getFooUpdates_ 1537 type methods). 1539 6.1. Event Source 1541 There are two mechanisms by which the client can receive the push 1542 events. The first is directly via a "text/event-stream" resource, as 1543 described in . This is 1544 essentially a long running HTTP request down which the server can 1545 push data. When a change occurs, the server MUST push an event 1546 called *state* to any connected clients. 1548 The server MAY also set a new "Last-Event-Id" that encodes the entire 1549 server state visible to the user. When a new connection is made to 1550 the event-source endpoint, the server can then work out whether the 1551 client has missed some changes which it should send immediately. 1553 The server MUST also send an event called *ping* with an empty object 1554 as the data if a maximum of 5 minutes has elapsed since the previous 1555 event. This MUST NOT set a new "Last-Event-Id". A client may detect 1556 the absence of these to determine that the HTTP connection has been 1557 dropped somewhere along the route and so it needs to re-establish the 1558 connection. 1560 Refer to the Authentication section of this spec for details on how 1561 to get the URL for the event-source endpoint. The request must be 1562 authenticated using an "Authorization" header like any HTTP request. 1564 A client MAY hold open multiple connections to the event-source, 1565 although it SHOULD try to use a single connection for efficiency. 1567 6.2. Web hook 1569 The second push mechanism is to register a callback URL to which the 1570 JMAP server will make an HTTPS POST request whenever the event 1571 occurs. The request MUST have a content type of "application/json" 1572 and contain the same UTF-8 JSON encoded object as described above as 1573 the body. 1575 The JMAP server MUST also set the following headers in the POST 1576 request: - "X-JMAP-EventType: state" - "X-JMAP-User: ${username}" 1577 where "${username}" is the username of the authenticated user for 1578 which the push event occurred. 1580 The JMAP server MUST follow any redirects. If the final response 1581 code from the server is "2xx", the callback is considered a success. 1582 If the response code is "503" (Service Unavailable), the JMAP server 1583 MAY try again later (but may also just drop the event). If the 1584 response code is "429" (Too Many Requests) the JMAP server SHOULD 1585 attempt to reduce the frequency of pushes to that URL. Any other 1586 response code MUST be considered a *permanent failure* and the 1587 callback should be deregistered (not tried again even for future 1588 events unless explicitly re-registered by the client). 1590 The URL set by the client MUST use the HTTPS protocol and SHOULD 1591 encode within it a unique token that can be verified by the server to 1592 know that the request comes from the JMAP server the authenticated 1593 client connected to. 1595 The callback is tied to the access token used to create it. Should 1596 the access token expire or be revoked, the callback MUST be removed 1597 by the JMAP server. The client MUST re-register the callback after 1598 reauthenticating to resume callbacks. 1600 Each session may only have a single callback URL registered. It can 1601 be set or retrieved using the following API calls. 1603 6.2.1. setPushCallback 1605 To set the web hook, make a call to _setPushCallback_. It takes the 1606 following argument: 1608 o *callback*: "String|null" The (HTTPS) URL the JMAP server should 1609 POST events to. This will replace any previously set URL. Set to 1610 "null" to just remove any previously set callback URL. 1612 The response to _setPushCallback_ is called _pushCallbackSet_. It has 1613 the following argument: 1615 o *callback*: "String|null" Echoed back from the call. 1617 The following error may be returned instead of the _mailboxesSet_ 1618 response: 1620 "invalidUrl": Returned if the URL does not begin with "https://", or 1621 is otherwise syntactically invalid or does not resolve. 1623 6.2.2. getPushCallback 1625 To check the currently set callback URL (if any), make a call to 1626 _getPushCallback_. It does not take any arguments. The response to 1627 _getPushCallback_ is called "pushCallback". It has a single 1628 argument: 1630 o *callback*: "String|null" The URL the JMAP server is currently 1631 posting push events to, or "null" if none. 1633 7. References 1635 7.1. Normative References 1637 [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate 1638 Requirement Levels", BCP 14, RFC 2119, 1639 DOI 10.17487/RFC2119, March 1997, 1640 . 1642 [RFC3339] Klyne, G. and C. Newman, "Date and Time on the Internet: 1643 Timestamps", RFC 3339, DOI 10.17487/RFC3339, July 2002, 1644 . 1646 [RFC3986] Berners-Lee, T., Fielding, R., and L. Masinter, "Uniform 1647 Resource Identifier (URI): Generic Syntax", STD 66, 1648 RFC 3986, DOI 10.17487/RFC3986, January 2005, 1649 . 1651 [RFC5785] Nottingham, M. and E. Hammer-Lahav, "Defining Well-Known 1652 Uniform Resource Identifiers (URIs)", RFC 5785, 1653 DOI 10.17487/RFC5785, April 2010, 1654 . 1656 [RFC6186] Daboo, C., "Use of SRV Records for Locating Email 1657 Submission/Access Services", RFC 6186, 1658 DOI 10.17487/RFC6186, March 2011, 1659 . 1661 [RFC6570] Gregorio, J., Fielding, R., Hadley, M., Nottingham, M., 1662 and D. Orchard, "URI Template", RFC 6570, 1663 DOI 10.17487/RFC6570, March 2012, 1664 . 1666 [RFC6750] Jones, M. and D. Hardt, "The OAuth 2.0 Authorization 1667 Framework: Bearer Token Usage", RFC 6750, 1668 DOI 10.17487/RFC6750, October 2012, 1669 . 1671 [RFC6764] Daboo, C., "Locating Services for Calendaring Extensions 1672 to WebDAV (CalDAV) and vCard Extensions to WebDAV 1673 (CardDAV)", RFC 6764, DOI 10.17487/RFC6764, February 2013, 1674 . 1676 [RFC7159] Bray, T., Ed., "The JavaScript Object Notation (JSON) Data 1677 Interchange Format", RFC 7159, DOI 10.17487/RFC7159, March 1678 2014, . 1680 [RFC7493] Bray, T., Ed., "The I-JSON Message Format", RFC 7493, 1681 DOI 10.17487/RFC7493, March 2015, 1682 . 1684 7.2. URIs 1686 [1] https://tools.ietf.org/html/rfc6238 1688 [2] https://developers.yubico.com/OTP/ 1690 [3] https://fidoalliance.org/specifications/download/ 1692 [4] https://jwt.io/ 1694 Author's Address 1696 Neil Jenkins 1697 FastMail 1698 Level 1, 91 William St 1699 Melbourne VIC 3000 1700 Australia 1702 Email: neilj@fastmail.com 1703 URI: https://www.fastmail.com