···11+22+33+44+55+66+77+Internet Engineering Task Force (IETF) N. Jenkins
88+Request for Comments: 8620 Fastmail
99+Category: Standards Track C. Newman
1010+ISSN: 2070-1721 Oracle
1111+ July 2019
1212+1313+1414+ The JSON Meta Application Protocol (JMAP)
1515+1616+Abstract
1717+1818+ This document specifies a protocol for clients to efficiently query,
1919+ fetch, and modify JSON-based data objects, with support for push
2020+ notification of changes and fast resynchronisation and for out-of-
2121+ band binary data upload/download.
2222+2323+Status of This Memo
2424+2525+ This is an Internet Standards Track document.
2626+2727+ This document is a product of the Internet Engineering Task Force
2828+ (IETF). It represents the consensus of the IETF community. It has
2929+ received public review and has been approved for publication by the
3030+ Internet Engineering Steering Group (IESG). Further information on
3131+ Internet Standards is available in Section 2 of RFC 7841.
3232+3333+ Information about the current status of this document, any errata,
3434+ and how to provide feedback on it may be obtained at
3535+ https://www.rfc-editor.org/info/rfc8620.
3636+3737+Copyright Notice
3838+3939+ Copyright (c) 2019 IETF Trust and the persons identified as the
4040+ document authors. All rights reserved.
4141+4242+ This document is subject to BCP 78 and the IETF Trust's Legal
4343+ Provisions Relating to IETF Documents
4444+ (https://trustee.ietf.org/license-info) in effect on the date of
4545+ publication of this document. Please review these documents
4646+ carefully, as they describe your rights and restrictions with respect
4747+ to this document. Code Components extracted from this document must
4848+ include Simplified BSD License text as described in Section 4.e of
4949+ the Trust Legal Provisions and are provided without warranty as
5050+ described in the Simplified BSD License.
5151+5252+5353+5454+5555+5656+5757+5858+Jenkins & Newman Standards Track [Page 1]
5959+6060+RFC 8620 JMAP July 2019
6161+6262+6363+Table of Contents
6464+6565+ 1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . 4
6666+ 1.1. Notational Conventions . . . . . . . . . . . . . . . . . 4
6767+ 1.2. The Id Data Type . . . . . . . . . . . . . . . . . . . . 6
6868+ 1.3. The Int and UnsignedInt Data Types . . . . . . . . . . . 6
6969+ 1.4. The Date and UTCDate Data Types . . . . . . . . . . . . . 7
7070+ 1.5. JSON as the Data Encoding Format . . . . . . . . . . . . 7
7171+ 1.6. Terminology . . . . . . . . . . . . . . . . . . . . . . . 7
7272+ 1.6.1. User . . . . . . . . . . . . . . . . . . . . . . . . 7
7373+ 1.6.2. Accounts . . . . . . . . . . . . . . . . . . . . . . 7
7474+ 1.6.3. Data Types and Records . . . . . . . . . . . . . . . 8
7575+ 1.7. The JMAP API Model . . . . . . . . . . . . . . . . . . . 8
7676+ 1.8. Vendor-Specific Extensions . . . . . . . . . . . . . . . 9
7777+ 2. The JMAP Session Resource . . . . . . . . . . . . . . . . . . 9
7878+ 2.1. Example . . . . . . . . . . . . . . . . . . . . . . . . . 14
7979+ 2.2. Service Autodiscovery . . . . . . . . . . . . . . . . . . 15
8080+ 3. Structured Data Exchange . . . . . . . . . . . . . . . . . . 16
8181+ 3.1. Making an API Request . . . . . . . . . . . . . . . . . . 16
8282+ 3.2. The Invocation Data Type . . . . . . . . . . . . . . . . 16
8383+ 3.3. The Request Object . . . . . . . . . . . . . . . . . . . 16
8484+ 3.3.1. Example Request . . . . . . . . . . . . . . . . . . . 18
8585+ 3.4. The Response Object . . . . . . . . . . . . . . . . . . . 18
8686+ 3.4.1. Example Response . . . . . . . . . . . . . . . . . . 19
8787+ 3.5. Omitting Arguments . . . . . . . . . . . . . . . . . . . 19
8888+ 3.6. Errors . . . . . . . . . . . . . . . . . . . . . . . . . 19
8989+ 3.6.1. Request-Level Errors . . . . . . . . . . . . . . . . 20
9090+ 3.6.2. Method-Level Errors . . . . . . . . . . . . . . . . . 21
9191+ 3.7. References to Previous Method Results . . . . . . . . . . 22
9292+ 3.8. Localisation of User-Visible Strings . . . . . . . . . . 27
9393+ 3.9. Security . . . . . . . . . . . . . . . . . . . . . . . . 28
9494+ 3.10. Concurrency . . . . . . . . . . . . . . . . . . . . . . . 28
9595+ 4. The Core/echo Method . . . . . . . . . . . . . . . . . . . . 28
9696+ 4.1. Example . . . . . . . . . . . . . . . . . . . . . . . . . 28
9797+ 5. Standard Methods and Naming Convention . . . . . . . . . . . 29
9898+ 5.1. /get . . . . . . . . . . . . . . . . . . . . . . . . . . 29
9999+ 5.2. /changes . . . . . . . . . . . . . . . . . . . . . . . . 30
100100+ 5.3. /set . . . . . . . . . . . . . . . . . . . . . . . . . . 34
101101+ 5.4. /copy . . . . . . . . . . . . . . . . . . . . . . . . . . 40
102102+ 5.5. /query . . . . . . . . . . . . . . . . . . . . . . . . . 42
103103+ 5.6. /queryChanges . . . . . . . . . . . . . . . . . . . . . . 48
104104+ 5.7. Examples . . . . . . . . . . . . . . . . . . . . . . . . 51
105105+ 5.8. Proxy Considerations . . . . . . . . . . . . . . . . . . 58
106106+ 6. Binary Data . . . . . . . . . . . . . . . . . . . . . . . . . 58
107107+ 6.1. Uploading Binary Data . . . . . . . . . . . . . . . . . . 59
108108+ 6.2. Downloading Binary Data . . . . . . . . . . . . . . . . . 60
109109+ 6.3. Blob/copy . . . . . . . . . . . . . . . . . . . . . . . . 61
110110+111111+112112+113113+114114+Jenkins & Newman Standards Track [Page 2]
115115+116116+RFC 8620 JMAP July 2019
117117+118118+119119+ 7. Push . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62
120120+ 7.1. The StateChange Object . . . . . . . . . . . . . . . . . 63
121121+ 7.1.1. Example . . . . . . . . . . . . . . . . . . . . . . . 64
122122+ 7.2. PushSubscription . . . . . . . . . . . . . . . . . . . . 64
123123+ 7.2.1. PushSubscription/get . . . . . . . . . . . . . . . . 67
124124+ 7.2.2. PushSubscription/set . . . . . . . . . . . . . . . . 68
125125+ 7.2.3. Example . . . . . . . . . . . . . . . . . . . . . . . 69
126126+ 7.3. Event Source . . . . . . . . . . . . . . . . . . . . . . 71
127127+ 8. Security Considerations . . . . . . . . . . . . . . . . . . . 73
128128+ 8.1. Transport Confidentiality . . . . . . . . . . . . . . . . 73
129129+ 8.2. Authentication Scheme . . . . . . . . . . . . . . . . . . 73
130130+ 8.3. Service Autodiscovery . . . . . . . . . . . . . . . . . . 73
131131+ 8.4. JSON Parsing . . . . . . . . . . . . . . . . . . . . . . 74
132132+ 8.5. Denial of Service . . . . . . . . . . . . . . . . . . . . 74
133133+ 8.6. Connection to Unknown Push Server . . . . . . . . . . . . 74
134134+ 8.7. Push Encryption . . . . . . . . . . . . . . . . . . . . . 75
135135+ 8.8. Traffic Analysis . . . . . . . . . . . . . . . . . . . . 76
136136+ 9. IANA Considerations . . . . . . . . . . . . . . . . . . . . . 76
137137+ 9.1. Assignment of jmap Service Name . . . . . . . . . . . . . 76
138138+ 9.2. Registration of Well-Known URI Suffix for JMAP . . . . . 76
139139+ 9.3. Registration of the jmap URN Sub-namespace . . . . . . . 77
140140+ 9.4. Creation of "JMAP Capabilities" Registry . . . . . . . . 77
141141+ 9.4.1. Preliminary Community Review . . . . . . . . . . . . 77
142142+ 9.4.2. Submit Request to IANA . . . . . . . . . . . . . . . 78
143143+ 9.4.3. Designated Expert Review . . . . . . . . . . . . . . 78
144144+ 9.4.4. Change Procedures . . . . . . . . . . . . . . . . . . 78
145145+ 9.4.5. JMAP Capabilities Registry Template . . . . . . . . . 79
146146+ 9.4.6. Initial Registration for JMAP Core . . . . . . . . . 79
147147+ 9.4.7. Registration for JMAP Error Placeholder in JMAP
148148+ Capabilities Registry . . . . . . . . . . . . . . . . 80
149149+ 9.5. Creation of "JMAP Error Codes" Registry . . . . . . . . . 80
150150+ 9.5.1. Expert Review . . . . . . . . . . . . . . . . . . . . 80
151151+ 9.5.2. JMAP Error Codes Registry Template . . . . . . . . . 81
152152+ 9.5.3. Initial Contents for the JMAP Error Codes Registry . 81
153153+ 10. References . . . . . . . . . . . . . . . . . . . . . . . . . 86
154154+ 10.1. Normative References . . . . . . . . . . . . . . . . . . 86
155155+ 10.2. Informative References . . . . . . . . . . . . . . . . . 89
156156+ Authors' Addresses . . . . . . . . . . . . . . . . . . . . . . . 90
157157+158158+159159+160160+161161+162162+163163+164164+165165+166166+167167+168168+169169+170170+Jenkins & Newman Standards Track [Page 3]
171171+172172+RFC 8620 JMAP July 2019
173173+174174+175175+1. Introduction
176176+177177+ The JSON Meta Application Protocol (JMAP) is used for synchronising
178178+ data, such as mail, calendars, or contacts, between a client and a
179179+ server. It is optimised for mobile and web environments and aims to
180180+ provide a consistent interface to different data types.
181181+182182+ This specification is for the generic mechanism of data
183183+ synchronisation. Further specifications define the data models for
184184+ different data types that may be synchronised via JMAP.
185185+186186+ JMAP is designed to make efficient use of limited network resources.
187187+ Multiple API calls may be batched in a single request to the server,
188188+ reducing round trips and improving battery life on mobile devices.
189189+ Push connections remove the need for polling, and an efficient delta
190190+ update mechanism ensures a minimum amount of data is transferred.
191191+192192+ JMAP is designed to be horizontally scalable to a very large number
193193+ of users. This is facilitated by separate endpoints for users after
194194+ login, the separation of binary and structured data, and a data model
195195+ for sharing that does not allow data dependencies between accounts.
196196+197197+1.1. Notational Conventions
198198+199199+ The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
200200+ "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and
201201+ "OPTIONAL" in this document are to be interpreted as described in
202202+ BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all
203203+ capitals, as shown here.
204204+205205+ The underlying format used for this specification is JSON.
206206+ Consequently, the terms "object" and "array" as well as the four
207207+ primitive types (strings, numbers, booleans, and null) are to be
208208+ interpreted as described in Section 1 of [RFC8259]. Unless otherwise
209209+ noted, all the property names and values are case sensitive.
210210+211211+ Some examples in this document contain "partial" JSON documents used
212212+ for illustrative purposes. In these examples, three periods "..."
213213+ are used to indicate a portion of the document that has been removed
214214+ for compactness.
215215+216216+ For compatibility with publishing requirements, line breaks have been
217217+ inserted inside long JSON strings, with the following continuation
218218+ lines indented. To form the valid JSON example, any line breaks
219219+ inside a string must be replaced with a space and any other white
220220+ space after the line break removed.
221221+222222+223223+224224+225225+226226+Jenkins & Newman Standards Track [Page 4]
227227+228228+RFC 8620 JMAP July 2019
229229+230230+231231+ Unless otherwise specified, examples of API exchanges only show the
232232+ methodCalls array of the Request object or the methodResponses array
233233+ of the Response object. For compactness, the rest of the Request/
234234+ Response object is omitted.
235235+236236+ Type signatures are given for all JSON values in this document. The
237237+ following conventions are used:
238238+239239+ o "*" - The type is undefined (the value could be any type, although
240240+ permitted values may be constrained by the context of this value).
241241+242242+ o "String" - The JSON string type.
243243+244244+ o "Number" - The JSON number type.
245245+246246+ o "Boolean" - The JSON boolean type.
247247+248248+ o "A[B]" - A JSON object where the keys are all of type "A", and the
249249+ values are all of type "B".
250250+251251+ o "A[]" - An array of values of type "A".
252252+253253+ o "A|B" - The value is either of type "A" or of type "B".
254254+255255+ Other types may also be given, with their representation defined
256256+ elsewhere in this document.
257257+258258+ Object properties may also have a set of attributes defined along
259259+ with the type signature. These have the following meanings:
260260+261261+ o "server-set" -- Only the server can set the value for this
262262+ property. The client MUST NOT send this property when creating a
263263+ new object of this type.
264264+265265+ o "immutable" -- The value MUST NOT change after the object is
266266+ created.
267267+268268+ o "default" -- (This is followed by a JSON value). The value that
269269+ will be used for this property if it is omitted in an argument or
270270+ when creating a new object of this type.
271271+272272+273273+274274+275275+276276+277277+278278+279279+280280+281281+282282+Jenkins & Newman Standards Track [Page 5]
283283+284284+RFC 8620 JMAP July 2019
285285+286286+287287+1.2. The Id Data Type
288288+289289+ All record ids are assigned by the server and are immutable.
290290+291291+ Where "Id" is given as a data type, it means a "String" of at least 1
292292+ and a maximum of 255 octets in size, and it MUST only contain
293293+ characters from the "URL and Filename Safe" base64 alphabet, as
294294+ defined in Section 5 of [RFC4648], excluding the pad character ("=").
295295+ This means the allowed characters are the ASCII alphanumeric
296296+ characters ("A-Za-z0-9"), hyphen ("-"), and underscore ("_").
297297+298298+ These characters are safe to use in almost any context (e.g.,
299299+ filesystems, URIs, and IMAP atoms). For maximum safety, servers
300300+ SHOULD also follow defensive allocation strategies to avoid creating
301301+ risks where glob completion or data type detection may be present
302302+ (e.g., on filesystems or in spreadsheets). In particular, it is wise
303303+ to avoid:
304304+305305+ o Ids starting with a dash
306306+307307+ o Ids starting with digits
308308+309309+ o Ids that contain only digits
310310+311311+ o Ids that differ only by ASCII case (for example, A vs. a)
312312+313313+ o the specific sequence of three characters "NIL" (because this
314314+ sequence can be confused with the IMAP protocol expression of the
315315+ null value)
316316+317317+ A good solution to these issues is to prefix every id with a single
318318+ alphabetical character.
319319+320320+1.3. The Int and UnsignedInt Data Types
321321+322322+ Where "Int" is given as a data type, it means an integer in the range
323323+ -2^53+1 <= value <= 2^53-1, the safe range for integers stored in a
324324+ floating-point double, represented as a JSON "Number".
325325+326326+ Where "UnsignedInt" is given as a data type, it means an "Int" where
327327+ the value MUST be in the range 0 <= value <= 2^53-1.
328328+329329+330330+331331+332332+333333+334334+335335+336336+337337+338338+Jenkins & Newman Standards Track [Page 6]
339339+340340+RFC 8620 JMAP July 2019
341341+342342+343343+1.4. The Date and UTCDate Data Types
344344+345345+ Where "Date" is given as a type, it means a string in "date-time"
346346+ format [RFC3339]. To ensure a normalised form, the "time-secfrac"
347347+ MUST always be omitted if zero, and any letters in the string (e.g.,
348348+ "T" and "Z") MUST be uppercase. For example,
349349+ "2014-10-30T14:12:00+08:00".
350350+351351+ Where "UTCDate" is given as a type, it means a "Date" where the
352352+ "time-offset" component MUST be "Z" (i.e., it must be in UTC time).
353353+ For example, "2014-10-30T06:12:00Z".
354354+355355+1.5. JSON as the Data Encoding Format
356356+357357+ JSON is a text-based data interchange format as specified in
358358+ [RFC8259]. The Internet JSON (I-JSON) format defined in [RFC7493] is
359359+ a strict subset of this, adding restrictions to avoid potentially
360360+ confusing scenarios (for example, it mandates that an object MUST NOT
361361+ have two members with the same name).
362362+363363+ All data sent from the client to the server or from the server to the
364364+ client (except binary file upload/download) MUST be valid I-JSON
365365+ according to the RFC and is therefore case sensitive and encoded in
366366+ UTF-8 [RFC3629].
367367+368368+1.6. Terminology
369369+370370+1.6.1. User
371371+372372+ A user is a person accessing data via JMAP. A user has a set of
373373+ permissions determining the data that they can see.
374374+375375+1.6.2. Accounts
376376+377377+ An account is a collection of data. A single account may contain an
378378+ arbitrary set of data types, for example, a collection of mail,
379379+ contacts, and calendars. Most JMAP methods take a mandatory
380380+ "accountId" argument that specifies on which account the operations
381381+ are to take place.
382382+383383+ An account is not the same as a user, although it is common for a
384384+ primary account to directly belong to the user. For example, you may
385385+ have an account that contains data for a group or business, to which
386386+ multiple users have access.
387387+388388+389389+390390+391391+392392+393393+394394+Jenkins & Newman Standards Track [Page 7]
395395+396396+RFC 8620 JMAP July 2019
397397+398398+399399+ A single set of credentials may provide access to multiple accounts,
400400+ for example, if another user is sharing their work calendar with the
401401+ authenticated user or if there is a group mailbox for a support-desk
402402+ inbox.
403403+404404+ In the event of a severe internal error, a server may have to
405405+ reallocate ids or do something else that violates standard JMAP data
406406+ constraints for an account. In this situation, the data on the
407407+ server is no longer compatible with cached data the client may have
408408+ from before. The server MUST treat this as though the account has
409409+ been deleted and then recreated with a new account id. Clients will
410410+ then be forced to throw away any data with the old account id and
411411+ refetch all data from scratch.
412412+413413+1.6.3. Data Types and Records
414414+415415+ JMAP provides a uniform interface for creating, retrieving, updating,
416416+ and deleting various types of objects. A "data type" is a collection
417417+ of named, typed properties, just like the schema for a database
418418+ table. Each instance of a data type is called a "record".
419419+420420+ The id of a record is immutable and assigned by the server. The id
421421+ MUST be unique among all records of the *same type* within the *same
422422+ account*. Ids may clash across accounts or for two records of
423423+ different types within the same account.
424424+425425+1.7. The JMAP API Model
426426+427427+ JMAP uses HTTP [RFC7230] to expose API, push, upload, and download
428428+ resources. All HTTP requests MUST use the "https://" scheme (HTTP
429429+ over TLS [RFC2818]). All HTTP requests MUST be authenticated.
430430+431431+ An authenticated client can fetch the user's Session object with
432432+ details about the data and capabilities the server can provide as
433433+ shown in Section 2. The client may then exchange data with the
434434+ server in the following ways:
435435+436436+ 1. The client may make an API request to the server to get or set
437437+ structured data. This request consists of an ordered series of
438438+ method calls. These are processed by the server, which then
439439+ returns an ordered series of responses. This is described in
440440+ Sections 3, 4, and 5.
441441+442442+ 2. The client may download or upload binary files from/to the
443443+ server. This is detailed in Section 6.
444444+445445+ 3. The client may connect to a push channel on the server, to be
446446+ notified when data has changed. This is explained in Section 7.
447447+448448+449449+450450+Jenkins & Newman Standards Track [Page 8]
451451+452452+RFC 8620 JMAP July 2019
453453+454454+455455+1.8. Vendor-Specific Extensions
456456+457457+ Individual services will have custom features they wish to expose
458458+ over JMAP. This may take the form of extra data types and/or methods
459459+ not in the spec, extra arguments to JMAP methods, or extra properties
460460+ on existing data types (which may also appear in arguments to methods
461461+ that take property names).
462462+463463+ The server can advertise custom extensions it supports by including
464464+ the identifiers in the capabilities object. Identifiers for vendor
465465+ extensions MUST be a URL belonging to a domain owned by the vendor,
466466+ to avoid conflict. The URL SHOULD resolve to documentation for the
467467+ changes the extension makes.
468468+469469+ The client MUST opt in to use an extension by passing the appropriate
470470+ capability identifier in the "using" array of the Request object, as
471471+ described in Section 3.3. The server MUST only follow the
472472+ specifications that are opted into and behave as though it does not
473473+ implement anything else when processing a request. This is to ensure
474474+ compatibility with clients that don't know about a specific custom
475475+ extension and for compatibility with future versions of JMAP.
476476+477477+2. The JMAP Session Resource
478478+479479+ You need two things to connect to a JMAP server:
480480+481481+ 1. The URL for the JMAP Session resource. This may be requested
482482+ directly from the user or discovered automatically based on a
483483+ username domain (see Section 2.2 below).
484484+485485+ 2. Credentials to authenticate with. How to obtain credentials is
486486+ out of scope for this document.
487487+488488+ A successful authenticated GET request to the JMAP Session resource
489489+ MUST return a JSON-encoded *Session* object, giving details about the
490490+ data and capabilities the server can provide to the client given
491491+ those credentials. It has the following properties:
492492+493493+ o capabilities: "String[Object]"
494494+495495+ An object specifying the capabilities of this server. Each key is
496496+ a URI for a capability supported by the server. The value for
497497+ each of these keys is an object with further information about the
498498+ server's capabilities in relation to that capability.
499499+500500+ The client MUST ignore any properties it does not understand.
501501+502502+503503+504504+505505+506506+Jenkins & Newman Standards Track [Page 9]
507507+508508+RFC 8620 JMAP July 2019
509509+510510+511511+ The capabilities object MUST include a property called
512512+ "urn:ietf:params:jmap:core". The value of this property is an
513513+ object that MUST contain the following information on server
514514+ capabilities (suggested minimum values for limits are supplied
515515+ that allow clients to make efficient use of the network):
516516+517517+ * maxSizeUpload: "UnsignedInt"
518518+519519+ The maximum file size, in octets, that the server will accept
520520+ for a single file upload (for any purpose). Suggested minimum:
521521+ 50,000,000.
522522+523523+ * maxConcurrentUpload: "UnsignedInt"
524524+525525+ The maximum number of concurrent requests the server will
526526+ accept to the upload endpoint. Suggested minimum: 4.
527527+528528+ * maxSizeRequest: "UnsignedInt"
529529+530530+ The maximum size, in octets, that the server will accept for a
531531+ single request to the API endpoint. Suggested minimum:
532532+ 10,000,000.
533533+534534+ * maxConcurrentRequests: "UnsignedInt"
535535+536536+ The maximum number of concurrent requests the server will
537537+ accept to the API endpoint. Suggested minimum: 4.
538538+539539+ * maxCallsInRequest: "UnsignedInt"
540540+541541+ The maximum number of method calls the server will accept in a
542542+ single request to the API endpoint. Suggested minimum: 16.
543543+544544+ * maxObjectsInGet: "UnsignedInt"
545545+546546+ The maximum number of objects that the client may request in a
547547+ single /get type method call. Suggested minimum: 500.
548548+549549+ * maxObjectsInSet: "UnsignedInt"
550550+551551+ The maximum number of objects the client may send to create,
552552+ update, or destroy in a single /set type method call. This is
553553+ the combined total, e.g., if the maximum is 10, you could not
554554+ create 7 objects and destroy 6, as this would be 13 actions,
555555+ which exceeds the limit. Suggested minimum: 500.
556556+557557+558558+559559+560560+561561+562562+Jenkins & Newman Standards Track [Page 10]
563563+564564+RFC 8620 JMAP July 2019
565565+566566+567567+ * collationAlgorithms: "String[]"
568568+569569+ A list of identifiers for algorithms registered in the
570570+ collation registry, as defined in [RFC4790], that the server
571571+ supports for sorting when querying records.
572572+573573+ Specifications for future capabilities will define their own
574574+ properties on the capabilities object.
575575+576576+ Servers MAY advertise vendor-specific JMAP extensions, as
577577+ described in Section 1.8. To avoid conflict, an identifier for a
578578+ vendor-specific extension MUST be a URL with a domain owned by the
579579+ vendor. Clients MUST opt in to any capability it wishes to use
580580+ (see Section 3.3).
581581+582582+ o accounts: "Id[Account]"
583583+584584+ A map of an account id to an Account object for each account (see
585585+ Section 1.6.2) the user has access to. An *Account* object has
586586+ the following properties:
587587+588588+ * name: "String"
589589+590590+ A user-friendly string to show when presenting content from
591591+ this account, e.g., the email address representing the owner of
592592+ the account.
593593+594594+ * isPersonal: "Boolean"
595595+596596+ This is true if the account belongs to the authenticated user
597597+ rather than a group account or a personal account of another
598598+ user that has been shared with them.
599599+600600+ * isReadOnly: "Boolean"
601601+602602+ This is true if the entire account is read-only.
603603+604604+ * accountCapabilities: "String[Object]"
605605+606606+ The set of capability URIs for the methods supported in this
607607+ account. Each key is a URI for a capability that has methods
608608+ you can use with this account. The value for each of these
609609+ keys is an object with further information about the account's
610610+ permissions and restrictions with respect to this capability,
611611+ as defined in the capability's specification.
612612+613613+ The client MUST ignore any properties it does not understand.
614614+615615+616616+617617+618618+Jenkins & Newman Standards Track [Page 11]
619619+620620+RFC 8620 JMAP July 2019
621621+622622+623623+ The server advertises the full list of capabilities it supports
624624+ in the capabilities object, as defined above. If the
625625+ capability defines new methods, the server MUST include it in
626626+ the accountCapabilities object if the user may use those
627627+ methods with this account. It MUST NOT include it in the
628628+ accountCapabilities object if the user cannot use those methods
629629+ with this account.
630630+631631+ For example, you may have access to your own account with mail,
632632+ calendars, and contacts data and also a shared account that
633633+ only has contacts data (a business address book, for example).
634634+ In this case, the accountCapabilities property on the first
635635+ account would include something like
636636+ "urn:ietf:params:jmap:mail", "urn:ietf:params:jmap:calendars",
637637+ and "urn:ietf:params:jmap:contacts", while the second account
638638+ would just have the last of these.
639639+640640+ Attempts to use the methods defined in a capability with one of
641641+ the accounts that does not support that capability are rejected
642642+ with an "accountNotSupportedByMethod" error (see "Method-Level
643643+ Errors", Section 3.6.2).
644644+645645+ o primaryAccounts: "String[Id]"
646646+647647+ A map of capability URIs (as found in accountCapabilities) to the
648648+ account id that is considered to be the user's main or default
649649+ account for data pertaining to that capability. If no account
650650+ being returned belongs to the user, or in any other way there is
651651+ no appropriate way to determine a default account, there MAY be no
652652+ entry for a particular URI, even though that capability is
653653+ supported by the server (and in the capabilities object).
654654+ "urn:ietf:params:jmap:core" SHOULD NOT be present.
655655+656656+ o username: "String"
657657+658658+ The username associated with the given credentials, or the empty
659659+ string if none.
660660+661661+ o apiUrl: "String"
662662+663663+ The URL to use for JMAP API requests.
664664+665665+666666+667667+668668+669669+670670+671671+672672+673673+674674+Jenkins & Newman Standards Track [Page 12]
675675+676676+RFC 8620 JMAP July 2019
677677+678678+679679+ o downloadUrl: "String"
680680+681681+ The URL endpoint to use when downloading files, in URI Template
682682+ (level 1) format [RFC6570]. The URL MUST contain variables called
683683+ "accountId", "blobId", "type", and "name". The use of these
684684+ variables is described in Section 6.2. Due to potential encoding
685685+ issues with slashes in content types, it is RECOMMENDED to put the
686686+ "type" variable in the query section of the URL.
687687+688688+ o uploadUrl: "String"
689689+690690+ The URL endpoint to use when uploading files, in URI Template
691691+ (level 1) format [RFC6570]. The URL MUST contain a variable
692692+ called "accountId". The use of this variable is described in
693693+ Section 6.1.
694694+695695+ o eventSourceUrl: "String"
696696+697697+ The URL to connect to for push events, as described in
698698+ Section 7.3, in URI Template (level 1) format [RFC6570]. The URL
699699+ MUST contain variables called "types", "closeafter", and "ping".
700700+ The use of these variables is described in Section 7.3.
701701+702702+ o state: "String"
703703+704704+ A (preferably short) string representing the state of this object
705705+ on the server. If the value of any other property on the Session
706706+ object changes, this string will change. The current value is
707707+ also returned on the API Response object (see Section 3.4),
708708+ allowing clients to quickly determine if the session information
709709+ has changed (e.g., an account has been added or removed), so they
710710+ need to refetch the object.
711711+712712+ To ensure future compatibility, other properties MAY be included on
713713+ the Session object. Clients MUST ignore any properties they are not
714714+ expecting.
715715+716716+ Implementors must take care to avoid inappropriate caching of the
717717+ Session object at the HTTP layer. Since the client should only
718718+ refetch when it detects there is a change (via the sessionState
719719+ property of an API response), it is RECOMMENDED to disable HTTP
720720+ caching altogether, for example, by setting "Cache-Control: no-cache,
721721+ no-store, must-revalidate" on the response.
722722+723723+724724+725725+726726+727727+728728+729729+730730+Jenkins & Newman Standards Track [Page 13]
731731+732732+RFC 8620 JMAP July 2019
733733+734734+735735+2.1. Example
736736+737737+ In the following example Session object, the user has access to their
738738+ own mail and contacts via JMAP, as well as read-only access to shared
739739+ mail from another user. The server is advertising a custom
740740+ "https://example.com/apis/foobar" capability.
741741+742742+ {
743743+ "capabilities": {
744744+ "urn:ietf:params:jmap:core": {
745745+ "maxSizeUpload": 50000000,
746746+ "maxConcurrentUpload": 8,
747747+ "maxSizeRequest": 10000000,
748748+ "maxConcurrentRequest": 8,
749749+ "maxCallsInRequest": 32,
750750+ "maxObjectsInGet": 256,
751751+ "maxObjectsInSet": 128,
752752+ "collationAlgorithms": [
753753+ "i;ascii-numeric",
754754+ "i;ascii-casemap",
755755+ "i;unicode-casemap"
756756+ ]
757757+ },
758758+ "urn:ietf:params:jmap:mail": {}
759759+ "urn:ietf:params:jmap:contacts": {},
760760+ "https://example.com/apis/foobar": {
761761+ "maxFoosFinangled": 42
762762+ }
763763+ },
764764+ "accounts": {
765765+ "A13824": {
766766+ "name": "john@example.com",
767767+ "isPersonal": true,
768768+ "isReadOnly": false,
769769+ "accountCapabilities": {
770770+ "urn:ietf:params:jmap:mail": {
771771+ "maxMailboxesPerEmail": null,
772772+ "maxMailboxDepth": 10,
773773+ ...
774774+ },
775775+ "urn:ietf:params:jmap:contacts": {
776776+ ...
777777+ }
778778+ }
779779+ },
780780+781781+782782+783783+784784+785785+786786+Jenkins & Newman Standards Track [Page 14]
787787+788788+RFC 8620 JMAP July 2019
789789+790790+791791+ "A97813": {
792792+ "name": "jane@example.com",
793793+ "isPersonal": false,
794794+ "isReadOnly": true,
795795+ "accountCapabilities": {
796796+ "urn:ietf:params:jmap:mail": {
797797+ "maxMailboxesPerEmail": 1,
798798+ "maxMailboxDepth": 10,
799799+ ...
800800+ }
801801+ }
802802+ }
803803+ },
804804+ "primaryAccounts": {
805805+ "urn:ietf:params:jmap:mail": "A13824",
806806+ "urn:ietf:params:jmap:contacts": "A13824"
807807+ },
808808+ "username": "john@example.com",
809809+ "apiUrl": "https://jmap.example.com/api/",
810810+ "downloadUrl": "https://jmap.example.com
811811+ /download/{accountId}/{blobId}/{name}?accept={type}",
812812+ "uploadUrl": "https://jmap.example.com/upload/{accountId}/",
813813+ "eventSourceUrl": "https://jmap.example.com
814814+ /eventsource/?types={types}&closeafter={closeafter}&ping={ping}",
815815+ "state": "75128aab4b1b"
816816+ }
817817+818818+2.2. Service Autodiscovery
819819+820820+ There are two standardised autodiscovery methods in use for Internet
821821+ protocols:
822822+823823+ o DNS SRV (see [RFC2782], [RFC6186], and [RFC6764])
824824+825825+ o .well-known/servicename (see [RFC8615])
826826+827827+ A JMAP-supporting host for the domain "example.com" SHOULD publish a
828828+ SRV record "_jmap._tcp.example.com" that gives a hostname and port
829829+ (usually port "443"). The JMAP Session resource is then
830830+ "https://${hostname}[:${port}]/.well-known/jmap" (following any
831831+ redirects).
832832+833833+ If the client has a username in the form of an email address, it MAY
834834+ use the domain portion of this to attempt autodiscovery of the JMAP
835835+ server.
836836+837837+838838+839839+840840+841841+842842+Jenkins & Newman Standards Track [Page 15]
843843+844844+RFC 8620 JMAP July 2019
845845+846846+847847+3. Structured Data Exchange
848848+849849+ The client may make an API request to the server to get or set
850850+ structured data. This request consists of an ordered series of
851851+ method calls. These are processed by the server, which then returns
852852+ an ordered series of responses.
853853+854854+3.1. Making an API Request
855855+856856+ To make an API request, the client makes an authenticated POST
857857+ request to the API resource, which is defined by the "apiUrl"
858858+ property in the Session object (see Section 2).
859859+860860+ The request MUST be of type "application/json" and consist of a
861861+ single JSON-encoded "Request" object, as defined in Section 3.3. If
862862+ successful, the response MUST also be of type "application/json" and
863863+ consist of a single "Response" object, as defined in Section 3.4.
864864+865865+3.2. The Invocation Data Type
866866+867867+ Method calls and responses are represented by the *Invocation* data
868868+ type. This is a tuple, represented as a JSON array containing three
869869+ elements:
870870+871871+ 1. A "String" *name* of the method to call or of the response.
872872+873873+ 2. A "String[*]" object containing named *arguments* for that method
874874+ or response.
875875+876876+ 3. A "String" *method call id*: an arbitrary string from the client
877877+ to be echoed back with the responses emitted by that method call
878878+ (a method may return 1 or more responses, as it may make implicit
879879+ calls to other methods; all responses initiated by this method
880880+ call get the same method call id in the response).
881881+882882+3.3. The Request Object
883883+884884+ A *Request* object has the following properties:
885885+886886+ o using: "String[]"
887887+888888+ The set of capabilities the client wishes to use. The client MAY
889889+ include capability identifiers even if the method calls it makes
890890+ do not utilise those capabilities. The server advertises the set
891891+ of specifications it supports in the Session object (see
892892+ Section 2), as keys on the "capabilities" property.
893893+894894+895895+896896+897897+898898+Jenkins & Newman Standards Track [Page 16]
899899+900900+RFC 8620 JMAP July 2019
901901+902902+903903+ o methodCalls: "Invocation[]"
904904+905905+ An array of method calls to process on the server. The method
906906+ calls MUST be processed sequentially, in order.
907907+908908+ o createdIds: "Id[Id]" (optional)
909909+910910+ A map of a (client-specified) creation id to the id the server
911911+ assigned when a record was successfully created.
912912+913913+ As described later in this specification, some records may have a
914914+ property that contains the id of another record. To allow more
915915+ efficient network usage, you can set this property to reference a
916916+ record created earlier in the same API request. Since the real id
917917+ is unknown when the request is created, the client can instead
918918+ specify the creation id it assigned, prefixed with a "#" (see
919919+ Section 5.3 for more details).
920920+921921+ As the server processes API requests, any time it successfully
922922+ creates a new record, it adds the creation id to this map (see the
923923+ "create" argument to /set in Section 5.3), with the server-
924924+ assigned real id as the value. If it comes across a reference to
925925+ a creation id in a create/update, it looks it up in the map and
926926+ replaces the reference with the real id, if found.
927927+928928+ The client can pass an initial value for this map as the
929929+ "createdIds" property of the Request object. This may be an empty
930930+ object. If given in the request, the response will also include a
931931+ createdIds property. This allows proxy servers to easily split a
932932+ JMAP request into multiple JMAP requests to send to different
933933+ servers. For example, it could send the first two method calls to
934934+ server A, then the third to server B, before sending the fourth to
935935+ server A again. By passing the createdIds of the previous
936936+ response to the next request, it can ensure all of these still
937937+ resolve. See Section 5.8 for further discussion of proxy
938938+ considerations.
939939+940940+ Future specifications MAY add further properties to the Request
941941+ object to extend the semantics. To ensure forwards compatibility, a
942942+ server MUST ignore any other properties it does not understand on the
943943+ JMAP Request object.
944944+945945+946946+947947+948948+949949+950950+951951+952952+953953+954954+Jenkins & Newman Standards Track [Page 17]
955955+956956+RFC 8620 JMAP July 2019
957957+958958+959959+3.3.1. Example Request
960960+961961+{
962962+ "using": [ "urn:ietf:params:jmap:core", "urn:ietf:params:jmap:mail" ],
963963+ "methodCalls": [
964964+ [ "method1", {
965965+ "arg1": "arg1data",
966966+ "arg2": "arg2data"
967967+ }, "c1" ],
968968+ [ "method2", {
969969+ "arg1": "arg1data"
970970+ }, "c2" ],
971971+ [ "method3", {}, "c3" ]
972972+ ]
973973+}
974974+975975+3.4. The Response Object
976976+977977+ A *Response* object has the following properties:
978978+979979+ o methodResponses: "Invocation[]"
980980+981981+ An array of responses, in the same format as the "methodCalls" on
982982+ the Request object. The output of the methods MUST be added to
983983+ the "methodResponses" array in the same order that the methods are
984984+ processed.
985985+986986+ o createdIds: "Id[Id]" (optional; only returned if given in the
987987+ request)
988988+989989+ A map of a (client-specified) creation id to the id the server
990990+ assigned when a record was successfully created. This MUST
991991+ include all creation ids passed in the original createdIds
992992+ parameter of the Request object, as well as any additional ones
993993+ added for newly created records.
994994+995995+ o sessionState: "String"
996996+997997+ The current value of the "state" string on the Session object, as
998998+ described in Section 2. Clients may use this to detect if this
999999+ object has changed and needs to be refetched.
10001000+10011001+ Unless otherwise specified, if the method call completed
10021002+ successfully, its response name is the same as the method name in the
10031003+ request.
10041004+10051005+10061006+10071007+10081008+10091009+10101010+Jenkins & Newman Standards Track [Page 18]
10111011+10121012+RFC 8620 JMAP July 2019
10131013+10141014+10151015+3.4.1. Example Response
10161016+10171017+ {
10181018+ "methodResponses": [
10191019+ [ "method1", {
10201020+ "arg1": 3,
10211021+ "arg2": "foo"
10221022+ }, "c1" ],
10231023+ [ "method2", {
10241024+ "isBlah": true
10251025+ }, "c2" ],
10261026+ [ "anotherResponseFromMethod2", {
10271027+ "data": 10,
10281028+ "yetmoredata": "Hello"
10291029+ }, "c2"],
10301030+ [ "error", {
10311031+ "type":"unknownMethod"
10321032+ }, "c3" ]
10331033+ ],
10341034+ "sessionState": "75128aab4b1b"
10351035+ }
10361036+10371037+3.5. Omitting Arguments
10381038+10391039+ An argument to a method may be specified to have a default value. If
10401040+ omitted by the client, the server MUST treat the method call the same
10411041+ as if the default value had been specified. Similarly, the server
10421042+ MAY omit any argument in a response that has the default value.
10431043+10441044+ Unless otherwise specified in a method description, null is the
10451045+ default value for any argument in a request or response where this is
10461046+ allowed by the type signature. Other arguments may only be omitted
10471047+ if an explicit default value is defined in the method description.
10481048+10491049+3.6. Errors
10501050+10511051+ There are three different levels of granularity at which an error may
10521052+ be returned in JMAP.
10531053+10541054+ When an API request is made, the request as a whole may be rejected
10551055+ due to rate limiting, malformed JSON, request for an unknown
10561056+ capability, etc. In this case, the entire request is rejected with
10571057+ an appropriate HTTP error response code and an additional JSON body
10581058+ with more detail for the client.
10591059+10601060+ Provided the request itself is syntactically valid (the JSON is valid
10611061+ and when decoded, it matches the type signature of a Request object),
10621062+ the methods within it are executed sequentially by the server. Each
10631063+10641064+10651065+10661066+Jenkins & Newman Standards Track [Page 19]
10671067+10681068+RFC 8620 JMAP July 2019
10691069+10701070+10711071+ method may individually fail, for example, if invalid arguments are
10721072+ given or an unknown method name is called.
10731073+10741074+ Finally, methods that make changes to the server state often act upon
10751075+ a number of different records within a single call. Each record
10761076+ change may be separately rejected with a SetError, as described in
10771077+ Section 5.3.
10781078+10791079+3.6.1. Request-Level Errors
10801080+10811081+ When an HTTP error response is returned to the client, the server
10821082+ SHOULD return a JSON "problem details" object as the response body,
10831083+ as per [RFC7807].
10841084+10851085+ The following problem types are defined:
10861086+10871087+ o "urn:ietf:params:jmap:error:unknownCapability"
10881088+ The client included a capability in the "using" property of the
10891089+ request that the server does not support.
10901090+10911091+ o "urn:ietf:params:jmap:error:notJSON"
10921092+ The content type of the request was not "application/json" or the
10931093+ request did not parse as I-JSON.
10941094+10951095+ o "urn:ietf:params:jmap:error:notRequest"
10961096+ The request parsed as JSON but did not match the type signature of
10971097+ the Request object.
10981098+10991099+ o "urn:ietf:params:jmap:error:limit"
11001100+ The request was not processed as it would have exceeded one of the
11011101+ request limits defined on the capability object, such as
11021102+ maxSizeRequest, maxCallsInRequest, or maxConcurrentRequests. A
11031103+ "limit" property MUST also be present on the "problem details"
11041104+ object, containing the name of the limit being applied.
11051105+11061106+3.6.1.1. Example
11071107+11081108+ {
11091109+ "type": "urn:ietf:params:jmap:error:unknownCapability",
11101110+ "status": 400,
11111111+ "detail": "The Request object used capability
11121112+ 'https://example.com/apis/foobar', which is not supported
11131113+ by this server."
11141114+ }
11151115+11161116+11171117+11181118+11191119+11201120+11211121+11221122+Jenkins & Newman Standards Track [Page 20]
11231123+11241124+RFC 8620 JMAP July 2019
11251125+11261126+11271127+ Another example:
11281128+11291129+ {
11301130+ "type": "urn:ietf:params:jmap:error:limit",
11311131+ "limit": "maxSizeRequest",
11321132+ "status": 400,
11331133+ "detail": "The request is larger than the server is willing to
11341134+ process."
11351135+ }
11361136+11371137+3.6.2. Method-Level Errors
11381138+11391139+ If a method encounters an error, the appropriate "error" response
11401140+ MUST be inserted at the current point in the "methodResponses" array
11411141+ and, unless otherwise specified, further processing MUST NOT happen
11421142+ within that method call.
11431143+11441144+ Any further method calls in the request MUST then be processed as
11451145+ normal. Errors at the method level MUST NOT generate an HTTP-level
11461146+ error.
11471147+11481148+ An "error" response looks like this:
11491149+11501150+ [ "error", {
11511151+ "type": "unknownMethod"
11521152+ }, "call-id" ]
11531153+11541154+ The response name is "error", and it MUST have a type property.
11551155+ Other properties may be present with further information; these are
11561156+ detailed in the error type descriptions where appropriate.
11571157+11581158+ With the exception of when the "serverPartialFail" error is returned,
11591159+ the externally visible state of the server MUST NOT have changed if
11601160+ an error is returned at the method level.
11611161+11621162+ The following error types are defined, which may be returned for any
11631163+ method call where appropriate:
11641164+11651165+ "serverUnavailable": Some internal server resource was temporarily
11661166+ unavailable. Attempting the same operation later (perhaps after a
11671167+ backoff with a random factor) may succeed.
11681168+11691169+ "serverFail": An unexpected or unknown error occurred during the
11701170+ processing of the call. A "description" property should provide more
11711171+ details about the error. The method call made no changes to the
11721172+ server's state. Attempting the same operation again is expected to
11731173+ fail again. Contacting the service administrator is likely necessary
11741174+ to resolve this problem if it is persistent.
11751175+11761176+11771177+11781178+Jenkins & Newman Standards Track [Page 21]
11791179+11801180+RFC 8620 JMAP July 2019
11811181+11821182+11831183+ "serverPartialFail": Some, but not all, expected changes described by
11841184+ the method occurred. The client MUST resynchronise impacted data to
11851185+ determine server state. Use of this error is strongly discouraged.
11861186+11871187+ "unknownMethod": The server does not recognise this method name.
11881188+11891189+ "invalidArguments": One of the arguments is of the wrong type or is
11901190+ otherwise invalid, or a required argument is missing. A
11911191+ "description" property MAY be present to help debug with an
11921192+ explanation of what the problem was. This is a non-localised string,
11931193+ and it is not intended to be shown directly to end users.
11941194+11951195+ "invalidResultReference": The method used a result reference for one
11961196+ of its arguments (see Section 3.7), but this failed to resolve.
11971197+11981198+ "forbidden": The method and arguments are valid, but executing the
11991199+ method would violate an Access Control List (ACL) or other
12001200+ permissions policy.
12011201+12021202+ "accountNotFound": The accountId does not correspond to a valid
12031203+ account.
12041204+12051205+ "accountNotSupportedByMethod": The accountId given corresponds to a
12061206+ valid account, but the account does not support this method or data
12071207+ type.
12081208+12091209+ "accountReadOnly": This method modifies state, but the account is
12101210+ read-only (as returned on the corresponding Account object in the
12111211+ JMAP Session resource).
12121212+12131213+ Further possible errors for a particular method are specified in the
12141214+ method descriptions.
12151215+12161216+ Further general errors MAY be defined in future RFCs. Should a
12171217+ client receive an error type it does not understand, it MUST treat it
12181218+ the same as the "serverFail" type.
12191219+12201220+3.7. References to Previous Method Results
12211221+12221222+ To allow clients to make more efficient use of the network and avoid
12231223+ round trips, an argument to one method can be taken from the result
12241224+ of a previous method call in the same request.
12251225+12261226+ To do this, the client prefixes the argument name with "#" (an
12271227+ octothorpe). The value is a ResultReference object as described
12281228+ below. When processing a method call, the server MUST first check
12291229+ the arguments object for any names beginning with "#". If found, the
12301230+ result reference should be resolved and the value used as the "real"
12311231+12321232+12331233+12341234+Jenkins & Newman Standards Track [Page 22]
12351235+12361236+RFC 8620 JMAP July 2019
12371237+12381238+12391239+ argument. The method is then processed as normal. If any result
12401240+ reference fails to resolve, the whole method MUST be rejected with an
12411241+ "invalidResultReference" error. If an arguments object contains the
12421242+ same argument name in normal and referenced form (e.g., "foo" and
12431243+ "#foo"), the method MUST return an "invalidArguments" error.
12441244+12451245+ A *ResultReference* object has the following properties:
12461246+12471247+ o resultOf: "String"
12481248+12491249+ The method call id (see Section 3.2) of a previous method call in
12501250+ the current request.
12511251+12521252+ o name: "String"
12531253+12541254+ The required name of a response to that method call.
12551255+12561256+ o path: "String"
12571257+12581258+ A pointer into the arguments of the response selected via the name
12591259+ and resultOf properties. This is a JSON Pointer [RFC6901], except
12601260+ it also allows the use of "*" to map through an array (see the
12611261+ description below).
12621262+12631263+ To resolve:
12641264+12651265+ 1. Find the first response with a method call id identical to the
12661266+ "resultOf" property of the ResultReference in the
12671267+ "methodResponses" array from previously processed method calls in
12681268+ the same request. If none, evaluation fails.
12691269+12701270+ 2. If the response name is not identical to the "name" property of
12711271+ the ResultReference, evaluation fails.
12721272+12731273+ 3. Apply the "path" to the arguments object of the response (the
12741274+ second item in the response array) following the JSON Pointer
12751275+ algorithm [RFC6901], except with the following addition in
12761276+ "Evaluation" (see Section 4):
12771277+12781278+ If the currently referenced value is a JSON array, the reference
12791279+ token may be exactly the single character "*", making the new
12801280+ referenced value the result of applying the rest of the JSON
12811281+ Pointer tokens to every item in the array and returning the
12821282+ results in the same order in a new array. If the result of
12831283+ applying the rest of the pointer tokens to each item was itself
12841284+ an array, the contents of this array are added to the output
12851285+ rather than the array itself (i.e., the result is flattened from
12861286+ an array of arrays to a single array). If the result of applying
12871287+12881288+12891289+12901290+Jenkins & Newman Standards Track [Page 23]
12911291+12921292+RFC 8620 JMAP July 2019
12931293+12941294+12951295+ the rest of the pointer tokens to a value was itself an array,
12961296+ its items should be included individually in the output rather
12971297+ than including the array itself (i.e., the result is flattened
12981298+ from an array of arrays to a single array).
12991299+13001300+ As a simple example, suppose we have the following API request
13011301+ "methodCalls":
13021302+13031303+ [[ "Foo/changes", {
13041304+ "accountId": "A1",
13051305+ "sinceState": "abcdef"
13061306+ }, "t0" ],
13071307+ [ "Foo/get", {
13081308+ "accountId": "A1",
13091309+ "#ids": {
13101310+ "resultOf": "t0",
13111311+ "name": "Foo/changes",
13121312+ "path": "/created"
13131313+ }
13141314+ }, "t1" ]]
13151315+13161316+ After executing the first method call, the "methodResponses" array
13171317+ is:
13181318+13191319+ [[ "Foo/changes", {
13201320+ "accountId": "A1",
13211321+ "oldState": "abcdef",
13221322+ "newState": "123456",
13231323+ "hasMoreChanges": false,
13241324+ "created": [ "f1", "f4" ],
13251325+ "updated": [],
13261326+ "destroyed": []
13271327+ }, "t0" ]]
13281328+13291329+ To execute the "Foo/get" call, we look through the arguments and find
13301330+ there is one with a "#" prefix. To resolve this, we apply the
13311331+ algorithm above:
13321332+13331333+ 1. Find the first response with method call id "t0". The "Foo/
13341334+ changes" response fulfils this criterion.
13351335+13361336+ 2. Check that the response name is the same as in the result
13371337+ reference. It is, so this is fine.
13381338+13391339+ 3. Apply the "path" as a JSON Pointer to the arguments object. This
13401340+ simply selects the "created" property, so the result of
13411341+ evaluating is: [ "f1", "f4" ].
13421342+13431343+13441344+13451345+13461346+Jenkins & Newman Standards Track [Page 24]
13471347+13481348+RFC 8620 JMAP July 2019
13491349+13501350+13511351+ The JMAP server now continues to process the "Foo/get" call as though
13521352+ the arguments were:
13531353+13541354+ {
13551355+ "accountId": "A1",
13561356+ "ids": [ "f1", "f4" ]
13571357+ }
13581358+13591359+ Now, a more complicated example using the JMAP Mail data model: fetch
13601360+ the "from"/"date"/"subject" for every Email in the first 10 Threads
13611361+ in the inbox (sorted newest first):
13621362+13631363+ [[ "Email/query", {
13641364+ "accountId": "A1",
13651365+ "filter": { "inMailbox": "id_of_inbox" },
13661366+ "sort": [{ "property": "receivedAt", "isAscending": false }],
13671367+ "collapseThreads": true,
13681368+ "position": 0,
13691369+ "limit": 10,
13701370+ "calculateTotal": true
13711371+ }, "t0" ],
13721372+ [ "Email/get", {
13731373+ "accountId": "A1",
13741374+ "#ids": {
13751375+ "resultOf": "t0",
13761376+ "name": "Email/query",
13771377+ "path": "/ids"
13781378+ },
13791379+ "properties": [ "threadId" ]
13801380+ }, "t1" ],
13811381+ [ "Thread/get", {
13821382+ "accountId": "A1",
13831383+ "#ids": {
13841384+ "resultOf": "t1",
13851385+ "name": "Email/get",
13861386+ "path": "/list/*/threadId"
13871387+ }
13881388+ }, "t2" ],
13891389+ [ "Email/get", {
13901390+ "accountId": "A1",
13911391+ "#ids": {
13921392+ "resultOf": "t2",
13931393+ "name": "Thread/get",
13941394+ "path": "/list/*/emailIds"
13951395+ },
13961396+ "properties": [ "from", "receivedAt", "subject" ]
13971397+ }, "t3" ]]
13981398+13991399+14001400+14011401+14021402+Jenkins & Newman Standards Track [Page 25]
14031403+14041404+RFC 8620 JMAP July 2019
14051405+14061406+14071407+ After executing the first 3 method calls, the "methodResponses" array
14081408+ might be:
14091409+14101410+ [[ "Email/query", {
14111411+ "accountId": "A1",
14121412+ "queryState": "abcdefg",
14131413+ "canCalculateChanges": true,
14141414+ "position": 0,
14151415+ "total": 101,
14161416+ "ids": [ "msg1023", "msg223", "msg110", "msg93", "msg91",
14171417+ "msg38", "msg36", "msg33", "msg11", "msg1" ]
14181418+ }, "t0" ],
14191419+ [ "Email/get", {
14201420+ "accountId": "A1",
14211421+ "state": "123456",
14221422+ "list": [{
14231423+ "id": "msg1023",
14241424+ "threadId": "trd194"
14251425+ }, {
14261426+ "id": "msg223",
14271427+ "threadId": "trd114"
14281428+ },
14291429+ ...
14301430+ ],
14311431+ "notFound": []
14321432+ }, "t1" ],
14331433+ [ "Thread/get", {
14341434+ "accountId": "A1",
14351435+ "state": "123456",
14361436+ "list": [{
14371437+ "id": "trd194",
14381438+ "emailIds": [ "msg1020", "msg1021", "msg1023" ]
14391439+ }, {
14401440+ "id": "trd114",
14411441+ "emailIds": [ "msg201", "msg223" ]
14421442+ },
14431443+ ...
14441444+ ],
14451445+ "notFound": []
14461446+ }, "t2" ]]
14471447+14481448+ To execute the final "Email/get" call, we look through the arguments
14491449+ and find there is one with a "#" prefix. To resolve this, we apply
14501450+ the algorithm:
14511451+14521452+ 1. Find the first response with method call id "t2". The "Thread/
14531453+ get" response fulfils this criterion.
14541454+14551455+14561456+14571457+14581458+Jenkins & Newman Standards Track [Page 26]
14591459+14601460+RFC 8620 JMAP July 2019
14611461+14621462+14631463+ 2. "Thread/get" is the name specified in the result reference, so
14641464+ this is fine.
14651465+14661466+ 3. Apply the "path" as a JSON Pointer to the arguments object.
14671467+ Token by token:
14681468+14691469+ 1. "list": get the array of thread objects
14701470+14711471+ 2. "*": for each of the items in the array:
14721472+14731473+ a. "emailIds": get the array of Email ids
14741474+14751475+ b. Concatenate these into a single array of all the ids in
14761476+ the result.
14771477+14781478+ The JMAP server now continues to process the "Email/get" call as
14791479+ though the arguments were:
14801480+14811481+{
14821482+ "accountId": "A1",
14831483+ "ids": [ "msg1020", "msg1021", "msg1023", "msg201", "msg223", ... ],
14841484+ "properties": [ "from", "receivedAt", "subject" ]
14851485+}
14861486+14871487+ The ResultReference performs a similar role to that of the creation
14881488+ id, in that it allows a chained method call to refer to information
14891489+ not available when the request is generated. However, they are
14901490+ different things and not interchangeable; the only commonality is the
14911491+ octothorpe used to indicate them.
14921492+14931493+3.8. Localisation of User-Visible Strings
14941494+14951495+ If returning a custom string to be displayed to the user, for
14961496+ example, an error message, the server SHOULD use information from the
14971497+ Accept-Language header of the request (as defined in Section 5.3.5 of
14981498+ [RFC7231]) to choose the best available localisation. The Content-
14991499+ Language header of the response (see Section 3.1.3.2 of [RFC7231])
15001500+ SHOULD indicate the language being used for user-visible strings.
15011501+15021502+ For example, suppose a request was made with the following header:
15031503+15041504+ Accept-Language: fr-CH, fr;q=0.9, de;q=0.8, en;q=0.7, *;q=0.5
15051505+15061506+ and a method generated an error to display to the user. The server
15071507+ has translations of the error message in English and German. Looking
15081508+ at the Accept-Language header, the user's preferred language is
15091509+ French. Since we don't have a translation for this, we look at the
15101510+15111511+15121512+15131513+15141514+Jenkins & Newman Standards Track [Page 27]
15151515+15161516+RFC 8620 JMAP July 2019
15171517+15181518+15191519+ next most preferred, which is German. We have a German translation,
15201520+ so the server returns this and indicates the language chosen in a
15211521+ Content-Language header like so:
15221522+15231523+ Content-Language: de
15241524+15251525+3.9. Security
15261526+15271527+ As always, the server must be strict about data received from the
15281528+ client. Arguments need to be checked for validity; a malicious user
15291529+ could attempt to find an exploit through the API. In case of invalid
15301530+ arguments (unknown/insufficient/wrong type for data, etc.), the
15311531+ method MUST return an "invalidArguments" error and terminate.
15321532+15331533+3.10. Concurrency
15341534+15351535+ Method calls within a single request MUST be executed in order.
15361536+ However, method calls from different concurrent API requests may be
15371537+ interleaved. This means that the data on the server may change
15381538+ between two method calls within a single API request.
15391539+15401540+4. The Core/echo Method
15411541+15421542+ The "Core/echo" method returns exactly the same arguments as it is
15431543+ given. It is useful for testing if you have a valid authenticated
15441544+ connection to a JMAP API endpoint.
15451545+15461546+4.1. Example
15471547+15481548+ Request:
15491549+15501550+ [[ "Core/echo", {
15511551+ "hello": true,
15521552+ "high": 5
15531553+ }, "b3ff" ]]
15541554+15551555+ Response:
15561556+15571557+ [[ "Core/echo", {
15581558+ "hello": true,
15591559+ "high": 5
15601560+ }, "b3ff" ]]
15611561+15621562+15631563+15641564+15651565+15661566+15671567+15681568+15691569+15701570+Jenkins & Newman Standards Track [Page 28]
15711571+15721572+RFC 8620 JMAP July 2019
15731573+15741574+15751575+5. Standard Methods and Naming Convention
15761576+15771577+ JMAP provides a uniform interface for creating, retrieving, updating,
15781578+ and deleting objects of a particular type. For a "Foo" data type,
15791579+ records of that type would be fetched via a "Foo/get" call and
15801580+ modified via a "Foo/set" call. Delta updates may be fetched via a
15811581+ "Foo/changes" call. These methods all follow a standard format as
15821582+ described below.
15831583+15841584+ Some types may not have all these methods. Specifications defining
15851585+ types MUST specify which methods are available for the type.
15861586+15871587+5.1. /get
15881588+15891589+ Objects of type Foo are fetched via a call to "Foo/get".
15901590+15911591+ It takes the following arguments:
15921592+15931593+ o accountId: "Id"
15941594+15951595+ The id of the account to use.
15961596+15971597+ o ids: "Id[]|null"
15981598+15991599+ The ids of the Foo objects to return. If null, then *all* records
16001600+ of the data type are returned, if this is supported for that data
16011601+ type and the number of records does not exceed the
16021602+ "maxObjectsInGet" limit.
16031603+16041604+ o properties: "String[]|null"
16051605+16061606+ If supplied, only the properties listed in the array are returned
16071607+ for each Foo object. If null, all properties of the object are
16081608+ returned. The id property of the object is *always* returned,
16091609+ even if not explicitly requested. If an invalid property is
16101610+ requested, the call MUST be rejected with an "invalidArguments"
16111611+ error.
16121612+16131613+ The response has the following arguments:
16141614+16151615+ o accountId: "Id"
16161616+16171617+ The id of the account used for the call.
16181618+16191619+16201620+16211621+16221622+16231623+16241624+16251625+16261626+Jenkins & Newman Standards Track [Page 29]
16271627+16281628+RFC 8620 JMAP July 2019
16291629+16301630+16311631+ o state: "String"
16321632+16331633+ A (preferably short) string representing the state on the server
16341634+ for *all* the data of this type in the account (not just the
16351635+ objects returned in this call). If the data changes, this string
16361636+ MUST change. If the Foo data is unchanged, servers SHOULD return
16371637+ the same state string on subsequent requests for this data type.
16381638+ When a client receives a response with a different state string to
16391639+ a previous call, it MUST either throw away all currently cached
16401640+ objects for the type or call "Foo/changes" to get the exact
16411641+ changes.
16421642+16431643+ o list: "Foo[]"
16441644+16451645+ An array of the Foo objects requested. This is the *empty array*
16461646+ if no objects were found or if the "ids" argument passed in was
16471647+ also an empty array. The results MAY be in a different order to
16481648+ the "ids" in the request arguments. If an identical id is
16491649+ included more than once in the request, the server MUST only
16501650+ include it once in either the "list" or the "notFound" argument of
16511651+ the response.
16521652+16531653+ o notFound: "Id[]"
16541654+16551655+ This array contains the ids passed to the method for records that
16561656+ do not exist. The array is empty if all requested ids were found
16571657+ or if the "ids" argument passed in was either null or an empty
16581658+ array.
16591659+16601660+ The following additional error may be returned instead of the "Foo/
16611661+ get" response:
16621662+16631663+ "requestTooLarge": The number of ids requested by the client exceeds
16641664+ the maximum number the server is willing to process in a single
16651665+ method call.
16661666+16671667+5.2. /changes
16681668+16691669+ When the state of the set of Foo records in an account changes on the
16701670+ server (whether due to creation, updates, or deletion), the "state"
16711671+ property of the "Foo/get" response will change. The "Foo/changes"
16721672+ method allows a client to efficiently update the state of its Foo
16731673+ cache to match the new state on the server. It takes the following
16741674+ arguments:
16751675+16761676+ o accountId: "Id"
16771677+16781678+ The id of the account to use.
16791679+16801680+16811681+16821682+Jenkins & Newman Standards Track [Page 30]
16831683+16841684+RFC 8620 JMAP July 2019
16851685+16861686+16871687+ o sinceState: "String"
16881688+16891689+ The current state of the client. This is the string that was
16901690+ returned as the "state" argument in the "Foo/get" response. The
16911691+ server will return the changes that have occurred since this
16921692+ state.
16931693+16941694+ o maxChanges: "UnsignedInt|null"
16951695+16961696+ The maximum number of ids to return in the response. The server
16971697+ MAY choose to return fewer than this value but MUST NOT return
16981698+ more. If not given by the client, the server may choose how many
16991699+ to return. If supplied by the client, the value MUST be a
17001700+ positive integer greater than 0. If a value outside of this range
17011701+ is given, the server MUST reject the call with an
17021702+ "invalidArguments" error.
17031703+17041704+ The response has the following arguments:
17051705+17061706+ o accountId: "Id"
17071707+17081708+ The id of the account used for the call.
17091709+17101710+ o oldState: "String"
17111711+17121712+ This is the "sinceState" argument echoed back; it's the state from
17131713+ which the server is returning changes.
17141714+17151715+ o newState: "String"
17161716+17171717+ This is the state the client will be in after applying the set of
17181718+ changes to the old state.
17191719+17201720+ o hasMoreChanges: "Boolean"
17211721+17221722+ If true, the client may call "Foo/changes" again with the
17231723+ "newState" returned to get further updates. If false, "newState"
17241724+ is the current server state.
17251725+17261726+ o created: "Id[]"
17271727+17281728+ An array of ids for records that have been created since the old
17291729+ state.
17301730+17311731+ o updated: "Id[]"
17321732+17331733+ An array of ids for records that have been updated since the old
17341734+ state.
17351735+17361736+17371737+17381738+Jenkins & Newman Standards Track [Page 31]
17391739+17401740+RFC 8620 JMAP July 2019
17411741+17421742+17431743+ o destroyed: "Id[]"
17441744+17451745+ An array of ids for records that have been destroyed since the old
17461746+ state.
17471747+17481748+ If a record has been created AND updated since the old state, the
17491749+ server SHOULD just return the id in the "created" list but MAY return
17501750+ it in the "updated" list as well.
17511751+17521752+ If a record has been updated AND destroyed since the old state, the
17531753+ server SHOULD just return the id in the "destroyed" list but MAY
17541754+ return it in the "updated" list as well.
17551755+17561756+ If a record has been created AND destroyed since the old state, the
17571757+ server SHOULD remove the id from the response entirely. However, it
17581758+ MAY include it in just the "destroyed" list or in both the
17591759+ "destroyed" and "created" lists.
17601760+17611761+ If a "maxChanges" is supplied, or set automatically by the server,
17621762+ the server MUST ensure the number of ids returned across "created",
17631763+ "updated", and "destroyed" does not exceed this limit. If there are
17641764+ more changes than this between the client's state and the current
17651765+ server state, the server SHOULD generate an update to take the client
17661766+ to an intermediate state, from which the client can continue to call
17671767+ "Foo/changes" until it is fully up to date. If it is unable to
17681768+ calculate an intermediate state, it MUST return a
17691769+ "cannotCalculateChanges" error response instead.
17701770+17711771+ When generating intermediate states, the server may choose how to
17721772+ divide up the changes. For many types, it will provide a better user
17731773+ experience to return the more recent changes first, as this is more
17741774+ likely to be what the user is most interested in. The client can
17751775+ then continue to page in the older changes while the user is viewing
17761776+ the newer data. For example, suppose a server went through the
17771777+ following states:
17781778+17791779+ A -> B -> C -> D -> E
17801780+17811781+ And a client asks for changes from state "B". The server might first
17821782+ get the ids of records created, updated, or destroyed between states
17831783+ D and E, returning them with:
17841784+17851785+ state: "B-D-E"
17861786+ hasMoreChanges: true
17871787+17881788+17891789+17901790+17911791+17921792+17931793+17941794+Jenkins & Newman Standards Track [Page 32]
17951795+17961796+RFC 8620 JMAP July 2019
17971797+17981798+17991799+ The client will then ask for the change from state "B-D-E", and the
18001800+ server can return the changes between states C and D, returning:
18011801+18021802+ state: "B-C-E"
18031803+ hasMoreChanges: true
18041804+18051805+ Finally, the client will request the changes from "B-C-E", and the
18061806+ server can return the changes between states B and C, returning:
18071807+18081808+ state: "E"
18091809+ hasMoreChanges: false
18101810+18111811+ Should the state on the server be modified in the middle of all this
18121812+ (to "F"), the server still does the same, but now when the update to
18131813+ state "E" is returned, it would indicate that it still has more
18141814+ changes for the client to fetch.
18151815+18161816+ Where multiple changes to a record are split across different
18171817+ intermediate states, the server MUST NOT return a record as created
18181818+ after a response that deems it as updated or destroyed, and it MUST
18191819+ NOT return a record as destroyed before a response that deems it as
18201820+ created or updated. The server may have to coalesce multiple changes
18211821+ to a record to satisfy this requirement.
18221822+18231823+ The following additional errors may be returned instead of the "Foo/
18241824+ changes" response:
18251825+18261826+ "cannotCalculateChanges": The server cannot calculate the changes
18271827+ from the state string given by the client. Usually, this is due to
18281828+ the client's state being too old or the server being unable to
18291829+ produce an update to an intermediate state when there are too many
18301830+ updates. The client MUST invalidate its Foo cache.
18311831+18321832+ Maintaining state to allow calculation of "Foo/changes" can be
18331833+ expensive for the server, but always returning
18341834+ "cannotCalculateChanges" severely increases network traffic and
18351835+ resource usage for the client. To allow efficient sync, servers
18361836+ SHOULD be able to calculate changes from any state string that was
18371837+ given to a client within the last 30 days (but of course may support
18381838+ calculating updates from states older than this).
18391839+18401840+18411841+18421842+18431843+18441844+18451845+18461846+18471847+18481848+18491849+18501850+Jenkins & Newman Standards Track [Page 33]
18511851+18521852+RFC 8620 JMAP July 2019
18531853+18541854+18551855+5.3. /set
18561856+18571857+ Modifying the state of Foo objects on the server is done via the
18581858+ "Foo/set" method. This encompasses creating, updating, and
18591859+ destroying Foo records. This allows the server to sort out ordering
18601860+ and dependencies that may exist if doing multiple operations at once
18611861+ (for example, to ensure there is always a minimum number of a certain
18621862+ record type).
18631863+18641864+ The "Foo/set" method takes the following arguments:
18651865+18661866+ o accountId: "Id"
18671867+18681868+ The id of the account to use.
18691869+18701870+ o ifInState: "String|null"
18711871+18721872+ This is a state string as returned by the "Foo/get" method
18731873+ (representing the state of all objects of this type in the
18741874+ account). If supplied, the string must match the current state;
18751875+ otherwise, the method will be aborted and a "stateMismatch" error
18761876+ returned. If null, any changes will be applied to the current
18771877+ state.
18781878+18791879+ o create: "Id[Foo]|null"
18801880+18811881+ A map of a *creation id* (a temporary id set by the client) to Foo
18821882+ objects, or null if no objects are to be created.
18831883+18841884+ The Foo object type definition may define default values for
18851885+ properties. Any such property may be omitted by the client.
18861886+18871887+ The client MUST omit any properties that may only be set by the
18881888+ server (for example, the "id" property on most object types).
18891889+18901890+ o update: "Id[PatchObject]|null"
18911891+18921892+ A map of an id to a Patch object to apply to the current Foo
18931893+ object with that id, or null if no objects are to be updated.
18941894+18951895+ A *PatchObject* is of type "String[*]" and represents an unordered
18961896+ set of patches. The keys are a path in JSON Pointer format
18971897+ [RFC6901], with an implicit leading "/" (i.e., prefix each key
18981898+ with "/" before applying the JSON Pointer evaluation algorithm).
18991899+19001900+ All paths MUST also conform to the following restrictions; if
19011901+ there is any violation, the update MUST be rejected with an
19021902+ "invalidPatch" error:
19031903+19041904+19051905+19061906+Jenkins & Newman Standards Track [Page 34]
19071907+19081908+RFC 8620 JMAP July 2019
19091909+19101910+19111911+ * The pointer MUST NOT reference inside an array (i.e., you MUST
19121912+ NOT insert/delete from an array; the array MUST be replaced in
19131913+ its entirety instead).
19141914+19151915+ * All parts prior to the last (i.e., the value after the final
19161916+ slash) MUST already exist on the object being patched.
19171917+19181918+ * There MUST NOT be two patches in the PatchObject where the
19191919+ pointer of one is the prefix of the pointer of the other, e.g.,
19201920+ "alerts/1/offset" and "alerts".
19211921+19221922+ The value associated with each pointer determines how to apply
19231923+ that patch:
19241924+19251925+ * If null, set to the default value if specified for this
19261926+ property; otherwise, remove the property from the patched
19271927+ object. If the key is not present in the parent, this a no-op.
19281928+19291929+ * Anything else: The value to set for this property (this may be
19301930+ a replacement or addition to the object being patched).
19311931+19321932+ Any server-set properties MAY be included in the patch if their
19331933+ value is identical to the current server value (before applying
19341934+ the patches to the object). Otherwise, the update MUST be
19351935+ rejected with an "invalidProperties" SetError.
19361936+19371937+ This patch definition is designed such that an entire Foo object
19381938+ is also a valid PatchObject. The client may choose to optimise
19391939+ network usage by just sending the diff or may send the whole
19401940+ object; the server processes it the same either way.
19411941+19421942+ o destroy: "Id[]|null"
19431943+19441944+ A list of ids for Foo objects to permanently delete, or null if no
19451945+ objects are to be destroyed.
19461946+19471947+ Each creation, modification, or destruction of an object is
19481948+ considered an atomic unit. It is permissible for the server to
19491949+ commit changes to some objects but not others; however, it MUST NOT
19501950+ only commit part of an update to a single record (e.g., update a
19511951+ "name" property but not a "count" property, if both are supplied in
19521952+ the update object).
19531953+19541954+ The final state MUST be valid after the "Foo/set" is finished;
19551955+ however, the server may have to transition through invalid
19561956+ intermediate states (not exposed to the client) while processing the
19571957+ individual create/update/destroy requests. For example, suppose
19581958+ there is a "name" property that must be unique. A single method call
19591959+19601960+19611961+19621962+Jenkins & Newman Standards Track [Page 35]
19631963+19641964+RFC 8620 JMAP July 2019
19651965+19661966+19671967+ could rename an object A => B and simultaneously rename another
19681968+ object B => A. If the final state is valid, this is allowed.
19691969+ Otherwise, each creation, modification, or destruction of an object
19701970+ should be processed sequentially and accepted/rejected based on the
19711971+ current server state.
19721972+19731973+ If a create, update, or destroy is rejected, the appropriate error
19741974+ MUST be added to the notCreated/notUpdated/notDestroyed property of
19751975+ the response, and the server MUST continue to the next create/update/
19761976+ destroy. It does not terminate the method.
19771977+19781978+ If an id given cannot be found, the update or destroy MUST be
19791979+ rejected with a "notFound" set error.
19801980+19811981+ The server MAY skip an update (rejecting it with a "willDestroy"
19821982+ SetError) if that object is destroyed in the same /set request.
19831983+19841984+ Some records may hold references to other records (foreign keys).
19851985+ That reference may be set (via create or update) in the same request
19861986+ as the referenced record is created. To do this, the client refers
19871987+ to the new record using its creation id prefixed with a "#". The
19881988+ order of the method calls in the request by the client MUST be such
19891989+ that the record being referenced is created in the same or an earlier
19901990+ call. Thus, the server never has to look ahead. Instead, while
19911991+ processing a request, the server MUST keep a simple map for the
19921992+ duration of the request of creation id to record id for each newly
19931993+ created record, so it can substitute in the correct value if
19941994+ necessary in later method calls. In the case of records with
19951995+ references to the same type, the server MUST order the creates and
19961996+ updates within a single method call so that creates happen before
19971997+ their creation ids are referenced by another create/update/destroy in
19981998+ the same call.
19991999+20002000+ Creation ids are not scoped by type but are a single map for all
20012001+ types. A client SHOULD NOT reuse a creation id anywhere in the same
20022002+ API request. If a creation id is reused, the server MUST map the
20032003+ creation id to the most recently created item with that id. To allow
20042004+ easy proxying of API requests, an initial set of creation id to real
20052005+ id values may be passed with a request (see "The Request Object",
20062006+ Section 3.3) and the final state of the map passed out with the
20072007+ response (see "The Response Object", Section 3.4).
20082008+20092009+ The response has the following arguments:
20102010+20112011+ o accountId: "Id"
20122012+20132013+ The id of the account used for the call.
20142014+20152015+20162016+20172017+20182018+Jenkins & Newman Standards Track [Page 36]
20192019+20202020+RFC 8620 JMAP July 2019
20212021+20222022+20232023+ o oldState: "String|null"
20242024+20252025+ The state string that would have been returned by "Foo/get" before
20262026+ making the requested changes, or null if the server doesn't know
20272027+ what the previous state string was.
20282028+20292029+ o newState: "String"
20302030+20312031+ The state string that will now be returned by "Foo/get".
20322032+20332033+ o created: "Id[Foo]|null"
20342034+20352035+ A map of the creation id to an object containing any properties of
20362036+ the created Foo object that were not sent by the client. This
20372037+ includes all server-set properties (such as the "id" in most
20382038+ object types) and any properties that were omitted by the client
20392039+ and thus set to a default by the server.
20402040+20412041+ This argument is null if no Foo objects were successfully created.
20422042+20432043+ o updated: "Id[Foo|null]|null"
20442044+20452045+ The keys in this map are the ids of all Foos that were
20462046+ successfully updated.
20472047+20482048+ The value for each id is a Foo object containing any property that
20492049+ changed in a way *not* explicitly requested by the PatchObject
20502050+ sent to the server, or null if none. This lets the client know of
20512051+ any changes to server-set or computed properties.
20522052+20532053+ This argument is null if no Foo objects were successfully updated.
20542054+20552055+ o destroyed: "Id[]|null"
20562056+20572057+ A list of Foo ids for records that were successfully destroyed, or
20582058+ null if none.
20592059+20602060+ o notCreated: "Id[SetError]|null"
20612061+20622062+ A map of the creation id to a SetError object for each record that
20632063+ failed to be created, or null if all successful.
20642064+20652065+ o notUpdated: "Id[SetError]|null"
20662066+20672067+ A map of the Foo id to a SetError object for each record that
20682068+ failed to be updated, or null if all successful.
20692069+20702070+20712071+20722072+20732073+20742074+Jenkins & Newman Standards Track [Page 37]
20752075+20762076+RFC 8620 JMAP July 2019
20772077+20782078+20792079+ o notDestroyed: "Id[SetError]|null"
20802080+20812081+ A map of the Foo id to a SetError object for each record that
20822082+ failed to be destroyed, or null if all successful.
20832083+20842084+ A *SetError* object has the following properties:
20852085+20862086+ o type: "String"
20872087+20882088+ The type of error.
20892089+20902090+ o description: "String|null"
20912091+20922092+ A description of the error to help with debugging that includes an
20932093+ explanation of what the problem was. This is a non-localised
20942094+ string and is not intended to be shown directly to end users.
20952095+20962096+ The following SetError types are defined and may be returned for set
20972097+ operations on any record type where appropriate:
20982098+20992099+ o "forbidden": (create; update; destroy). The create/update/destroy
21002100+ would violate an ACL or other permissions policy.
21012101+21022102+ o "overQuota": (create; update). The create would exceed a server-
21032103+ defined limit on the number or total size of objects of this type.
21042104+21052105+ o "tooLarge": (create; update). The create/update would result in
21062106+ an object that exceeds a server-defined limit for the maximum size
21072107+ of a single object of this type.
21082108+21092109+ o "rateLimit": (create). Too many objects of this type have been
21102110+ created recently, and a server-defined rate limit has been
21112111+ reached. It may work if tried again later.
21122112+21132113+ o "notFound": (update; destroy). The id given to update/destroy
21142114+ cannot be found.
21152115+21162116+ o "invalidPatch": (update). The PatchObject given to update the
21172117+ record was not a valid patch (see the patch description).
21182118+21192119+ o "willDestroy": (update). The client requested that an object be
21202120+ both updated and destroyed in the same /set request, and the
21212121+ server has decided to therefore ignore the update.
21222122+21232123+21242124+21252125+21262126+21272127+21282128+21292129+21302130+Jenkins & Newman Standards Track [Page 38]
21312131+21322132+RFC 8620 JMAP July 2019
21332133+21342134+21352135+ o "invalidProperties": (create; update). The record given is
21362136+ invalid in some way. For example:
21372137+21382138+ * It contains properties that are invalid according to the type
21392139+ specification of this record type.
21402140+21412141+ * It contains a property that may only be set by the server
21422142+ (e.g., "id") and is different to the current value. Note, to
21432143+ allow clients to pass whole objects back, it is not an error to
21442144+ include a server-set property in an update as long as the value
21452145+ is identical to the current value on the server.
21462146+21472147+ * There is a reference to another record (foreign key), and the
21482148+ given id does not correspond to a valid record.
21492149+21502150+ The SetError object SHOULD also have a property called
21512151+ "properties" of type "String[]" that lists *all* the properties
21522152+ that were invalid.
21532153+21542154+ Individual methods MAY specify more specific errors for certain
21552155+ conditions that would otherwise result in an invalidProperties
21562156+ error. If the condition of one of these is met, it MUST be
21572157+ returned instead of the invalidProperties error.
21582158+21592159+ o "singleton": (create; destroy). This is a singleton type, so you
21602160+ cannot create another one or destroy the existing one.
21612161+21622162+ Other possible SetError types MAY be given in specific method
21632163+ descriptions. Other properties MAY also be present on the SetError
21642164+ object, as described in the relevant methods.
21652165+21662166+ The following additional errors may be returned instead of the "Foo/
21672167+ set" response:
21682168+21692169+ "requestTooLarge": The total number of objects to create, update, or
21702170+ destroy exceeds the maximum number the server is willing to process
21712171+ in a single method call.
21722172+21732173+ "stateMismatch": An "ifInState" argument was supplied, and it does
21742174+ not match the current state.
21752175+21762176+21772177+21782178+21792179+21802180+21812181+21822182+21832183+21842184+21852185+21862186+Jenkins & Newman Standards Track [Page 39]
21872187+21882188+RFC 8620 JMAP July 2019
21892189+21902190+21912191+5.4. /copy
21922192+21932193+ The only way to move Foo records *between* two different accounts is
21942194+ to copy them using the "Foo/copy" method; once the copy has
21952195+ succeeded, delete the original. The "onSuccessDestroyOriginal"
21962196+ argument allows you to try to do this in one method call; however,
21972197+ note that the two different actions are not atomic, so it is possible
21982198+ for the copy to succeed but the original not to be destroyed for some
21992199+ reason.
22002200+22012201+ The copy is conceptually in three phases:
22022202+22032203+ 1. Reading the current values from the "from" account.
22042204+22052205+ 2. Writing the new copies to the other account.
22062206+22072207+ 3. Destroying the originals in the "from" account, if requested.
22082208+22092209+ Data may change in between phases due to concurrent requests.
22102210+22112211+ The "Foo/copy" method takes the following arguments:
22122212+22132213+ o fromAccountId: "Id"
22142214+22152215+ The id of the account to copy records from.
22162216+22172217+ o ifFromInState: "String|null"
22182218+22192219+ This is a state string as returned by the "Foo/get" method. If
22202220+ supplied, the string must match the current state of the account
22212221+ referenced by the fromAccountId when reading the data to be
22222222+ copied; otherwise, the method will be aborted and a
22232223+ "stateMismatch" error returned. If null, the data will be read
22242224+ from the current state.
22252225+22262226+ o accountId: "Id"
22272227+22282228+ The id of the account to copy records to. This MUST be different
22292229+ to the "fromAccountId".
22302230+22312231+ o ifInState: "String|null"
22322232+22332233+ This is a state string as returned by the "Foo/get" method. If
22342234+ supplied, the string must match the current state of the account
22352235+ referenced by the accountId; otherwise, the method will be aborted
22362236+ and a "stateMismatch" error returned. If null, any changes will
22372237+ be applied to the current state.
22382238+22392239+22402240+22412241+22422242+Jenkins & Newman Standards Track [Page 40]
22432243+22442244+RFC 8620 JMAP July 2019
22452245+22462246+22472247+ o create: "Id[Foo]"
22482248+22492249+ A map of the *creation id* to a Foo object. The Foo object MUST
22502250+ contain an "id" property, which is the id (in the fromAccount) of
22512251+ the record to be copied. When creating the copy, any other
22522252+ properties included are used instead of the current value for that
22532253+ property on the original.
22542254+22552255+ o onSuccessDestroyOriginal: "Boolean" (default: false)
22562256+22572257+ If true, an attempt will be made to destroy the original records
22582258+ that were successfully copied: after emitting the "Foo/copy"
22592259+ response, but before processing the next method, the server MUST
22602260+ make a single call to "Foo/set" to destroy the original of each
22612261+ successfully copied record; the output of this is added to the
22622262+ responses as normal, to be returned to the client.
22632263+22642264+ o destroyFromIfInState: "String|null"
22652265+22662266+ This argument is passed on as the "ifInState" argument to the
22672267+ implicit "Foo/set" call, if made at the end of this request to
22682268+ destroy the originals that were successfully copied.
22692269+22702270+ Each record copy is considered an atomic unit that may succeed or
22712271+ fail individually.
22722272+22732273+ The response has the following arguments:
22742274+22752275+ o fromAccountId: "Id"
22762276+22772277+ The id of the account records were copied from.
22782278+22792279+ o accountId: "Id"
22802280+22812281+ The id of the account records were copied to.
22822282+22832283+ o oldState: "String|null"
22842284+22852285+ The state string that would have been returned by "Foo/get" on the
22862286+ account records that were copied to before making the requested
22872287+ changes, or null if the server doesn't know what the previous
22882288+ state string was.
22892289+22902290+ o newState: "String"
22912291+22922292+ The state string that will now be returned by "Foo/get" on the
22932293+ account records were copied to.
22942294+22952295+22962296+22972297+22982298+Jenkins & Newman Standards Track [Page 41]
22992299+23002300+RFC 8620 JMAP July 2019
23012301+23022302+23032303+ o created: "Id[Foo]|null"
23042304+23052305+ A map of the creation id to an object containing any properties of
23062306+ the copied Foo object that are set by the server (such as the "id"
23072307+ in most object types; note, the id is likely to be different to
23082308+ the id of the object in the account it was copied from).
23092309+23102310+ This argument is null if no Foo objects were successfully copied.
23112311+23122312+ o notCreated: "Id[SetError]|null"
23132313+23142314+ A map of the creation id to a SetError object for each record that
23152315+ failed to be copied, or null if none.
23162316+23172317+ The SetError may be any of the standard set errors returned for a
23182318+ create or update. In addition, the following SetError is defined:
23192319+23202320+ "alreadyExists": The server forbids duplicates, and the record
23212321+ already exists in the target account. An "existingId" property of
23222322+ type "Id" MUST be included on the SetError object with the id of the
23232323+ existing record.
23242324+23252325+ The following additional errors may be returned instead of the "Foo/
23262326+ copy" response:
23272327+23282328+ "fromAccountNotFound": The "fromAccountId" does not correspond to a
23292329+ valid account.
23302330+23312331+ "fromAccountNotSupportedByMethod": The "fromAccountId" given
23322332+ corresponds to a valid account, but the account does not support this
23332333+ data type.
23342334+23352335+ "stateMismatch": An "ifInState" argument was supplied and it does not
23362336+ match the current state, or an "ifFromInState" argument was supplied
23372337+ and it does not match the current state in the from account.
23382338+23392339+5.5. /query
23402340+23412341+ For data sets where the total amount of data is expected to be very
23422342+ small, clients can just fetch the complete set of data and then do
23432343+ any sorting/filtering locally. However, for large data sets (e.g.,
23442344+ multi-gigabyte mailboxes), the client needs to be able to
23452345+ search/sort/window the data type on the server.
23462346+23472347+ A query on the set of Foos in an account is made by calling "Foo/
23482348+ query". This takes a number of arguments to determine which records
23492349+ to include, how they should be sorted, and which part of the result
23502350+23512351+23522352+23532353+23542354+Jenkins & Newman Standards Track [Page 42]
23552355+23562356+RFC 8620 JMAP July 2019
23572357+23582358+23592359+ should be returned (the full list may be *very* long). The result is
23602360+ returned as a list of Foo ids.
23612361+23622362+ A call to "Foo/query" takes the following arguments:
23632363+23642364+ o accountId: "Id"
23652365+23662366+ The id of the account to use.
23672367+23682368+ o filter: "FilterOperator|FilterCondition|null"
23692369+23702370+ Determines the set of Foos returned in the results. If null, all
23712371+ objects in the account of this type are included in the results.
23722372+ A *FilterOperator* object has the following properties:
23732373+23742374+ * operator: "String"
23752375+23762376+ This MUST be one of the following strings:
23772377+23782378+ + "AND": All of the conditions must match for the filter to
23792379+ match.
23802380+23812381+ + "OR": At least one of the conditions must match for the
23822382+ filter to match.
23832383+23842384+ + "NOT": None of the conditions must match for the filter to
23852385+ match.
23862386+23872387+ * conditions: "(FilterOperator|FilterCondition)[]"
23882388+23892389+ The conditions to evaluate against each record.
23902390+23912391+ A *FilterCondition* is an "object" whose allowed properties and
23922392+ semantics depend on the data type and is defined in the /query
23932393+ method specification for that type. It MUST NOT have an
23942394+ "operator" property.
23952395+23962396+ o sort: "Comparator[]|null"
23972397+23982398+ Lists the names of properties to compare between two Foo records,
23992399+ and how to compare them, to determine which comes first in the
24002400+ sort. If two Foo records have an identical value for the first
24012401+ comparator, the next comparator will be considered, and so on. If
24022402+ all comparators are the same (this includes the case where an
24032403+ empty array or null is given as the "sort" argument), the sort
24042404+ order is server dependent, but it MUST be stable between calls to
24052405+ "Foo/query". A *Comparator* has the following properties:
24062406+24072407+24082408+24092409+24102410+Jenkins & Newman Standards Track [Page 43]
24112411+24122412+RFC 8620 JMAP July 2019
24132413+24142414+24152415+ * property: "String"
24162416+24172417+ The name of the property on the Foo objects to compare.
24182418+24192419+ * isAscending: "Boolean" (optional; default: true)
24202420+24212421+ If true, sort in ascending order. If false, reverse the
24222422+ comparator's results to sort in descending order.
24232423+24242424+ * collation: "String" (optional; default is server-dependent)
24252425+24262426+ The identifier, as registered in the collation registry defined
24272427+ in [RFC4790], for the algorithm to use when comparing the order
24282428+ of strings. The algorithms the server supports are advertised
24292429+ in the capabilities object returned with the Session object
24302430+ (see Section 2).
24312431+24322432+ If omitted, the default algorithm is server dependent, but:
24332433+24342434+ 1. It MUST be unicode-aware.
24352435+24362436+ 2. It MAY be selected based on an Accept-Language header in
24372437+ the request (as defined in [RFC7231], Section 5.3.5) or
24382438+ out-of-band information about the user's language/locale.
24392439+24402440+ 3. It SHOULD be case insensitive where such a concept makes
24412441+ sense for a language/locale. Where the user's language is
24422442+ unknown, it is RECOMMENDED to follow the advice in
24432443+ Section 5.2.3 of [RFC8264].
24442444+24452445+ The "i;unicode-casemap" collation [RFC5051] and the Unicode
24462446+ Collation Algorithm (<http://www.unicode.org/reports/tr10/>)
24472447+ are two examples that fulfil these criterion and provide
24482448+ reasonable behaviour for a large number of languages.
24492449+24502450+ When the property being compared is not a string, the
24512451+ "collation" property is ignored, and the following comparison
24522452+ rules apply based on the type. In ascending order:
24532453+24542454+ + "Boolean": false comes before true.
24552455+24562456+ + "Number": A lower number comes before a higher number.
24572457+24582458+ + "Date"/"UTCDate": The earlier date comes first.
24592459+24602460+ The Comparator object may also have additional properties as
24612461+ required for specific sort operations defined in a type's /query
24622462+ method.
24632463+24642464+24652465+24662466+Jenkins & Newman Standards Track [Page 44]
24672467+24682468+RFC 8620 JMAP July 2019
24692469+24702470+24712471+ o position: "Int" (default: 0)
24722472+24732473+ The zero-based index of the first id in the full list of results
24742474+ to return.
24752475+24762476+ If a negative value is given, it is an offset from the end of the
24772477+ list. Specifically, the negative value MUST be added to the total
24782478+ number of results given the filter, and if still negative, it's
24792479+ clamped to "0". This is now the zero-based index of the first id
24802480+ to return.
24812481+24822482+ If the index is greater than or equal to the total number of
24832483+ objects in the results list, then the "ids" array in the response
24842484+ will be empty, but this is not an error.
24852485+24862486+ o anchor: "Id|null"
24872487+24882488+ A Foo id. If supplied, the "position" argument is ignored. The
24892489+ index of this id in the results will be used in combination with
24902490+ the "anchorOffset" argument to determine the index of the first
24912491+ result to return (see below for more details).
24922492+24932493+ o anchorOffset: "Int" (default: 0)
24942494+24952495+ The index of the first result to return relative to the index of
24962496+ the anchor, if an anchor is given. This MAY be negative. For
24972497+ example, "-1" means the Foo immediately preceding the anchor is
24982498+ the first result in the list returned (see below for more
24992499+ details).
25002500+25012501+ o limit: "UnsignedInt|null"
25022502+25032503+ The maximum number of results to return. If null, no limit
25042504+ presumed. The server MAY choose to enforce a maximum "limit"
25052505+ argument. In this case, if a greater value is given (or if it is
25062506+ null), the limit is clamped to the maximum; the new limit is
25072507+ returned with the response so the client is aware. If a negative
25082508+ value is given, the call MUST be rejected with an
25092509+ "invalidArguments" error.
25102510+25112511+ o calculateTotal: "Boolean" (default: false)
25122512+25132513+ Does the client wish to know the total number of results in the
25142514+ query? This may be slow and expensive for servers to calculate,
25152515+ particularly with complex filters, so clients should take care to
25162516+ only request the total when needed.
25172517+25182518+25192519+25202520+25212521+25222522+Jenkins & Newman Standards Track [Page 45]
25232523+25242524+RFC 8620 JMAP July 2019
25252525+25262526+25272527+ If an "anchor" argument is given, the anchor is looked for in the
25282528+ results after filtering and sorting. If found, the "anchorOffset" is
25292529+ then added to its index. If the resulting index is now negative, it
25302530+ is clamped to 0. This index is now used exactly as though it were
25312531+ supplied as the "position" argument. If the anchor is not found, the
25322532+ call is rejected with an "anchorNotFound" error.
25332533+25342534+ If an "anchor" is specified, any position argument supplied by the
25352535+ client MUST be ignored. If no "anchor" is supplied, any
25362536+ "anchorOffset" argument MUST be ignored.
25372537+25382538+ A client can use "anchor" instead of "position" to find the index of
25392539+ an id within a large set of results.
25402540+25412541+ The response has the following arguments:
25422542+25432543+ o accountId: "Id"
25442544+25452545+ The id of the account used for the call.
25462546+25472547+ o queryState: "String"
25482548+25492549+ A string encoding the current state of the query on the server.
25502550+ This string MUST change if the results of the query (i.e., the
25512551+ matching ids and their sort order) have changed. The queryState
25522552+ string MAY change if something has changed on the server, which
25532553+ means the results may have changed but the server doesn't know for
25542554+ sure.
25552555+25562556+ The queryState string only represents the ordered list of ids that
25572557+ match the particular query (including its sort/filter). There is
25582558+ no requirement for it to change if a property on an object
25592559+ matching the query changes but the query results are unaffected
25602560+ (indeed, it is more efficient if the queryState string does not
25612561+ change in this case). The queryState string only has meaning when
25622562+ compared to future responses to a query with the same type/sort/
25632563+ filter or when used with /queryChanges to fetch changes.
25642564+25652565+ Should a client receive back a response with a different
25662566+ queryState string to a previous call, it MUST either throw away
25672567+ the currently cached query and fetch it again (note, this does not
25682568+ require fetching the records again, just the list of ids) or call
25692569+ "Foo/queryChanges" to get the difference.
25702570+25712571+25722572+25732573+25742574+25752575+25762576+25772577+25782578+Jenkins & Newman Standards Track [Page 46]
25792579+25802580+RFC 8620 JMAP July 2019
25812581+25822582+25832583+ o canCalculateChanges: "Boolean"
25842584+25852585+ This is true if the server supports calling "Foo/queryChanges"
25862586+ with these "filter"/"sort" parameters. Note, this does not
25872587+ guarantee that the "Foo/queryChanges" call will succeed, as it may
25882588+ only be possible for a limited time afterwards due to server
25892589+ internal implementation details.
25902590+25912591+ o position: "UnsignedInt"
25922592+25932593+ The zero-based index of the first result in the "ids" array within
25942594+ the complete list of query results.
25952595+25962596+ o ids: "Id[]"
25972597+25982598+ The list of ids for each Foo in the query results, starting at the
25992599+ index given by the "position" argument of this response and
26002600+ continuing until it hits the end of the results or reaches the
26012601+ "limit" number of ids. If "position" is >= "total", this MUST be
26022602+ the empty list.
26032603+26042604+ o total: "UnsignedInt" (only if requested)
26052605+26062606+ The total number of Foos in the results (given the "filter").
26072607+ This argument MUST be omitted if the "calculateTotal" request
26082608+ argument is not true.
26092609+26102610+ o limit: "UnsignedInt" (if set by the server)
26112611+26122612+ The limit enforced by the server on the maximum number of results
26132613+ to return. This is only returned if the server set a limit or
26142614+ used a different limit than that given in the request.
26152615+26162616+ The following additional errors may be returned instead of the "Foo/
26172617+ query" response:
26182618+26192619+ "anchorNotFound": An anchor argument was supplied, but it cannot be
26202620+ found in the results of the query.
26212621+26222622+ "unsupportedSort": The "sort" is syntactically valid, but it includes
26232623+ a property the server does not support sorting on or a collation
26242624+ method it does not recognise.
26252625+26262626+ "unsupportedFilter": The "filter" is syntactically valid, but the
26272627+ server cannot process it. If the filter was the result of a user's
26282628+ search input, the client SHOULD suggest that the user simplify their
26292629+ search.
26302630+26312631+26322632+26332633+26342634+Jenkins & Newman Standards Track [Page 47]
26352635+26362636+RFC 8620 JMAP July 2019
26372637+26382638+26392639+5.6. /queryChanges
26402640+26412641+ The "Foo/queryChanges" method allows a client to efficiently update
26422642+ the state of a cached query to match the new state on the server. It
26432643+ takes the following arguments:
26442644+26452645+ o accountId: "Id"
26462646+26472647+ The id of the account to use.
26482648+26492649+ o filter: "FilterOperator|FilterCondition|null"
26502650+26512651+ The filter argument that was used with "Foo/query".
26522652+26532653+ o sort: "Comparator[]|null"
26542654+26552655+ The sort argument that was used with "Foo/query".
26562656+26572657+ o sinceQueryState: "String"
26582658+26592659+ The current state of the query in the client. This is the string
26602660+ that was returned as the "queryState" argument in the "Foo/query"
26612661+ response with the same sort/filter. The server will return the
26622662+ changes made to the query since this state.
26632663+26642664+ o maxChanges: "UnsignedInt|null"
26652665+26662666+ The maximum number of changes to return in the response. See
26672667+ error descriptions below for more details.
26682668+26692669+ o upToId: "Id|null"
26702670+26712671+ The last (highest-index) id the client currently has cached from
26722672+ the query results. When there are a large number of results, in a
26732673+ common case, the client may have only downloaded and cached a
26742674+ small subset from the beginning of the results. If the sort and
26752675+ filter are both only on immutable properties, this allows the
26762676+ server to omit changes after this point in the results, which can
26772677+ significantly increase efficiency. If they are not immutable,
26782678+ this argument is ignored.
26792679+26802680+ o calculateTotal: "Boolean" (default: false)
26812681+26822682+ Does the client wish to know the total number of results now in
26832683+ the query? This may be slow and expensive for servers to
26842684+ calculate, particularly with complex filters, so clients should
26852685+ take care to only request the total when needed.
26862686+26872687+26882688+26892689+26902690+Jenkins & Newman Standards Track [Page 48]
26912691+26922692+RFC 8620 JMAP July 2019
26932693+26942694+26952695+ The response has the following arguments:
26962696+26972697+ o accountId: "Id"
26982698+26992699+ The id of the account used for the call.
27002700+27012701+ o oldQueryState: "String"
27022702+27032703+ This is the "sinceQueryState" argument echoed back; that is, the
27042704+ state from which the server is returning changes.
27052705+27062706+ o newQueryState: "String"
27072707+27082708+ This is the state the query will be in after applying the set of
27092709+ changes to the old state.
27102710+27112711+ o total: "UnsignedInt" (only if requested)
27122712+27132713+ The total number of Foos in the results (given the "filter").
27142714+ This argument MUST be omitted if the "calculateTotal" request
27152715+ argument is not true.
27162716+27172717+ o removed: "Id[]"
27182718+27192719+ The "id" for every Foo that was in the query results in the old
27202720+ state and that is not in the results in the new state.
27212721+27222722+ If the server cannot calculate this exactly, the server MAY return
27232723+ the ids of extra Foos in addition that may have been in the old
27242724+ results but are not in the new results.
27252725+27262726+ If the sort and filter are both only on immutable properties and
27272727+ an "upToId" is supplied and exists in the results, any ids that
27282728+ were removed but have a higher index than "upToId" SHOULD be
27292729+ omitted.
27302730+27312731+ If the "filter" or "sort" includes a mutable property, the server
27322732+ MUST include all Foos in the current results for which this
27332733+ property may have changed. The position of these may have moved
27342734+ in the results, so they must be reinserted by the client to ensure
27352735+ its query cache is correct.
27362736+27372737+27382738+27392739+27402740+27412741+27422742+27432743+27442744+27452745+27462746+Jenkins & Newman Standards Track [Page 49]
27472747+27482748+RFC 8620 JMAP July 2019
27492749+27502750+27512751+ o added: "AddedItem[]"
27522752+27532753+ The id and index in the query results (in the new state) for every
27542754+ Foo that has been added to the results since the old state AND
27552755+ every Foo in the current results that was included in the
27562756+ "removed" array (due to a filter or sort based upon a mutable
27572757+ property).
27582758+27592759+ If the sort and filter are both only on immutable properties and
27602760+ an "upToId" is supplied and exists in the results, any ids that
27612761+ were added but have a higher index than "upToId" SHOULD be
27622762+ omitted.
27632763+27642764+ The array MUST be sorted in order of index, with the lowest index
27652765+ first.
27662766+27672767+ An *AddedItem* object has the following properties:
27682768+27692769+ * id: "Id"
27702770+27712771+ * index: "UnsignedInt"
27722772+27732773+ The result of this is that if the client has a cached sparse array of
27742774+ Foo ids corresponding to the results in the old state, then:
27752775+27762776+ fooIds = [ "id1", "id2", null, null, "id3", "id4", null, null, null ]
27772777+27782778+ If it *splices out* all ids in the removed array that it has in its
27792779+ cached results, then:
27802780+27812781+ removed = [ "id2", "id31", ... ];
27822782+ fooIds => [ "id1", null, null, "id3", "id4", null, null, null ]
27832783+27842784+ and *splices in* (one by one in order, starting with the lowest
27852785+ index) all of the ids in the added array:
27862786+27872787+ added = [{ id: "id5", index: 0, ... }];
27882788+ fooIds => [ "id5", "id1", null, null, "id3", "id4", null, null, null ]
27892789+27902790+ and *truncates* or *extends* to the new total length, then the
27912791+ results will now be in the new state.
27922792+27932793+ Note: splicing in adds the item at the given index, incrementing the
27942794+ index of all items previously at that or a higher index. Splicing
27952795+ out is the inverse, removing the item and decrementing the index of
27962796+ every item after it in the array.
27972797+27982798+27992799+28002800+28012801+28022802+Jenkins & Newman Standards Track [Page 50]
28032803+28042804+RFC 8620 JMAP July 2019
28052805+28062806+28072807+ The following additional errors may be returned instead of the "Foo/
28082808+ queryChanges" response:
28092809+28102810+ "tooManyChanges": There are more changes than the client's
28112811+ "maxChanges" argument. Each item in the removed or added array is
28122812+ considered to be one change. The client may retry with higher max
28132813+ changes or invalidate its cache of the query results.
28142814+28152815+ "cannotCalculateChanges": The server cannot calculate the changes
28162816+ from the queryState string given by the client, usually due to the
28172817+ client's state being too old. The client MUST invalidate its cache
28182818+ of the query results.
28192819+28202820+5.7. Examples
28212821+28222822+ Suppose we have a type *Todo* with the following properties:
28232823+28242824+ o id: "Id" (immutable; server-set)
28252825+28262826+ The id of the object.
28272827+28282828+ o title: "String"
28292829+28302830+ A brief summary of what is to be done.
28312831+28322832+ o keywords: "String[Boolean]" (default: {})
28332833+28342834+ A set of keywords that apply to the Todo. The set is represented
28352835+ as an object, with the keys being the "keywords". The value for
28362836+ each key in the object MUST be true. (This format allows you to
28372837+ update an individual key using patch syntax rather than having to
28382838+ update the whole set of keywords as one, which a "String[]"
28392839+ representation would require.)
28402840+28412841+ o neuralNetworkTimeEstimation: "Number" (server-set)
28422842+28432843+ The title and keywords are fed into the server's state-of-the-art
28442844+ neural network to get an estimation of how long this Todo will
28452845+ take, in seconds.
28462846+28472847+ o subTodoIds: "Id[]|null"
28482848+28492849+ The ids of a list of other Todos to complete as part of this Todo.
28502850+28512851+ Suppose also that all the standard methods are defined for this type
28522852+ and the FilterCondition object supports a "hasKeyword" property to
28532853+ match Todos with the given keyword.
28542854+28552855+28562856+28572857+28582858+Jenkins & Newman Standards Track [Page 51]
28592859+28602860+RFC 8620 JMAP July 2019
28612861+28622862+28632863+ A client might want to display the list of Todos with either a
28642864+ "music" keyword or a "video" keyword, so it makes the following
28652865+ method call:
28662866+28672867+ [[ "Todo/query", {
28682868+ "accountId": "x",
28692869+ "filter": {
28702870+ "operator": "OR",
28712871+ "conditions": [
28722872+ { "hasKeyword": "music" },
28732873+ { "hasKeyword": "video" }
28742874+ ]
28752875+ },
28762876+ "sort": [{ "property": "title" }],
28772877+ "position": 0,
28782878+ "limit": 10
28792879+ }, "0" ],
28802880+ [ "Todo/get", {
28812881+ "accountId": "x",
28822882+ "#ids": {
28832883+ "resultOf": "0",
28842884+ "name": "Todo/query",
28852885+ "path": "/ids"
28862886+ }
28872887+ }, "1" ]]
28882888+28892889+28902890+28912891+28922892+28932893+28942894+28952895+28962896+28972897+28982898+28992899+29002900+29012901+29022902+29032903+29042904+29052905+29062906+29072907+29082908+29092909+29102910+29112911+29122912+29132913+29142914+Jenkins & Newman Standards Track [Page 52]
29152915+29162916+RFC 8620 JMAP July 2019
29172917+29182918+29192919+ This would query the server for the set of Todos with a keyword of
29202920+ either "music" or "video", sorted by title, and limited to the first
29212921+ 10 results. It fetches the full object for each of these Todos using
29222922+ back-references to reference the result of the query. The response
29232923+ might look something like:
29242924+29252925+ [[ "Todo/query", {
29262926+ "accountId": "x",
29272927+ "queryState": "y13213",
29282928+ "canCalculateChanges": true,
29292929+ "position": 0,
29302930+ "ids": [ "a", "b", "c", "d", "e", "f", "g", "h", "i", "j" ]
29312931+ }, "0" ],
29322932+ [ "Todo/get", {
29332933+ "accountId": "x",
29342934+ "state": "10324",
29352935+ "list": [{
29362936+ "id": "a",
29372937+ "title": "Practise Piano",
29382938+ "keywords": {
29392939+ "music": true,
29402940+ "beethoven": true,
29412941+ "mozart": true,
29422942+ "liszt": true,
29432943+ "rachmaninov": true
29442944+ },
29452945+ "neuralNetworkTimeEstimation": 3600
29462946+ }, {
29472947+ "id": "b",
29482948+ "title": "Watch Daft Punk music video",
29492949+ "keywords": {
29502950+ "music": true,
29512951+ "video": true,
29522952+ "trance": true
29532953+ },
29542954+ "neuralNetworkTimeEstimation": 18000
29552955+ },
29562956+ ...
29572957+ ]
29582958+ }, "1" ]]
29592959+29602960+29612961+29622962+29632963+29642964+29652965+29662966+29672967+29682968+29692969+29702970+Jenkins & Newman Standards Track [Page 53]
29712971+29722972+RFC 8620 JMAP July 2019
29732973+29742974+29752975+ Now, suppose the user adds a keyword "chopin" and removes the keyword
29762976+ "mozart" from the "Practise Piano" task. The client may send the
29772977+ whole object to the server, as this is a valid PatchObject:
29782978+29792979+ [[ "Todo/set", {
29802980+ "accountId": "x",
29812981+ "ifInState": "10324",
29822982+ "update": {
29832983+ "a": {
29842984+ "id": "a",
29852985+ "title": "Practise Piano",
29862986+ "keywords": {
29872987+ "music": true,
29882988+ "beethoven": true,
29892989+ "chopin": true,
29902990+ "liszt": true,
29912991+ "rachmaninov": true
29922992+ },
29932993+ "neuralNetworkTimeEstimation": 360
29942994+ }
29952995+ }
29962996+ }, "0" ]]
29972997+29982998+ or it may send a minimal patch:
29992999+30003000+ [[ "Todo/set", {
30013001+ "accountId": "x",
30023002+ "ifInState": "10324",
30033003+ "update": {
30043004+ "a": {
30053005+ "keywords/chopin": true,
30063006+ "keywords/mozart": null
30073007+ }
30083008+ }
30093009+ }, "0" ]]
30103010+30113011+30123012+30133013+30143014+30153015+30163016+30173017+30183018+30193019+30203020+30213021+30223022+30233023+30243024+30253025+30263026+Jenkins & Newman Standards Track [Page 54]
30273027+30283028+RFC 8620 JMAP July 2019
30293029+30303030+30313031+ The effect is exactly the same on the server in either case, and
30323032+ presuming the server is still in state "10324", it will probably
30333033+ return success:
30343034+30353035+ [[ "Todo/set", {
30363036+ "accountId": "x",
30373037+ "oldState": "10324",
30383038+ "newState": "10329",
30393039+ "updated": {
30403040+ "a": {
30413041+ "neuralNetworkTimeEstimation": 5400
30423042+ }
30433043+ }
30443044+ }, "0" ]]
30453045+30463046+ The server changed the "neuralNetworkTimeEstimation" property on the
30473047+ object as part of this change; as this changed in a way *not*
30483048+ explicitly requested by the PatchObject sent to the server, it is
30493049+ returned with the "updated" confirmation.
30503050+30513051+ Let us now add a sub-Todo to our new "Practise Piano" Todo. In this
30523052+ example, we can see the use of a reference to a creation id to allow
30533053+ us to set a foreign key reference to a record created in the same
30543054+ request:
30553055+30563056+ [[ "Todo/set", {
30573057+ "accountId": "x",
30583058+ "create": {
30593059+ "k15": {
30603060+ "title": "Warm up with scales"
30613061+ }
30623062+ },
30633063+ "update": {
30643064+ "a": {
30653065+ "subTodoIds": [ "#k15" ]
30663066+ }
30673067+ }
30683068+ }, "0" ]]
30693069+30703070+30713071+30723072+30733073+30743074+30753075+30763076+30773077+30783078+30793079+30803080+30813081+30823082+Jenkins & Newman Standards Track [Page 55]
30833083+30843084+RFC 8620 JMAP July 2019
30853085+30863086+30873087+ Now, suppose another user deleted the "Listen to Daft Punk" Todo.
30883088+ The first user will receive a push notification (see Section 7) with
30893089+ the changed state string for the "Todo" type. Since the new string
30903090+ does not match its current state, it knows it needs to check for
30913091+ updates. It may make a request like:
30923092+30933093+ [[ "Todo/changes", {
30943094+ "accountId": "x",
30953095+ "sinceState": "10324",
30963096+ "maxChanges": 50
30973097+ }, "0" ],
30983098+ [ "Todo/queryChanges", {
30993099+ "accountId": "x",
31003100+ "filter": {
31013101+ "operator": "OR",
31023102+ "conditions": [
31033103+ { "hasKeyword": "music" },
31043104+ { "hasKeyword": "video" }
31053105+ ]
31063106+ },
31073107+ "sort": [{ "property": "title" }],
31083108+ "sinceQueryState": "y13213",
31093109+ "maxChanges": 50
31103110+ }, "1" ]]
31113111+31123112+ and receive in response:
31133113+31143114+ [[ "Todo/changes", {
31153115+ "accountId": "x",
31163116+ "oldState": "10324",
31173117+ "newState": "871903",
31183118+ "hasMoreChanges": false,
31193119+ "created": [],
31203120+ "updated": [],
31213121+ "destroyed": ["b"]
31223122+ }, "0" ],
31233123+ [ "Todo/queryChanges", {
31243124+ "accountId": "x",
31253125+ "oldQueryState": "y13213",
31263126+ "newQueryState": "y13218",
31273127+ "removed": ["b"],
31283128+ "added": null
31293129+ }, "1" ]]
31303130+31313131+31323132+31333133+31343134+31353135+31363136+31373137+31383138+Jenkins & Newman Standards Track [Page 56]
31393139+31403140+RFC 8620 JMAP July 2019
31413141+31423142+31433143+ Suppose the user has access to another account "y", for example, a
31443144+ team account shared between multiple users. To move an existing Todo
31453145+ from account "x", the client would call:
31463146+31473147+ [[ "Todo/copy", {
31483148+ "fromAccountId": "x",
31493149+ "accountId": "y",
31503150+ "create": {
31513151+ "k5122": {
31523152+ "id": "a"
31533153+ }
31543154+ },
31553155+ "onSuccessDestroyOriginal": true
31563156+ }, "0" ]]
31573157+31583158+ The server successfully copies the Todo to a new account (where it
31593159+ receives a new id) and deletes the original. Due to the implicit
31603160+ call to "Todo/set", there are two responses to the single method
31613161+ call, both with the same method call id:
31623162+31633163+ [[ "Todo/copy", {
31643164+ "fromAccountId": "x",
31653165+ "accountId": "y",
31663166+ "created": {
31673167+ "k5122": {
31683168+ "id": "DAf97"
31693169+ }
31703170+ },
31713171+ "oldState": "c1d64ecb038c",
31723172+ "newState": "33844835152b"
31733173+ }, "0" ],
31743174+ [ "Todo/set", {
31753175+ "accountId": "x",
31763176+ "oldState": "871903",
31773177+ "newState": "871909",
31783178+ "destroyed": [ "a" ],
31793179+ ...
31803180+ }, "0" ]]
31813181+31823182+31833183+31843184+31853185+31863186+31873187+31883188+31893189+31903190+31913191+31923192+31933193+31943194+Jenkins & Newman Standards Track [Page 57]
31953195+31963196+RFC 8620 JMAP July 2019
31973197+31983198+31993199+5.8. Proxy Considerations
32003200+32013201+ JMAP has been designed to allow an API endpoint to easily proxy
32023202+ through to one or more JMAP servers. This may be useful for load
32033203+ balancing, augmenting capabilities, or presenting a single endpoint
32043204+ to accounts hosted on different JMAP servers (splitting the request
32053205+ based on each method's "accountId" argument). The proxy need only
32063206+ understand the general structure of a JMAP Request object; it does
32073207+ not need to know anything specifically about the methods and
32083208+ arguments it will pass through to other servers.
32093209+32103210+ If splitting up the methods in a request to call them on different
32113211+ backend servers, the proxy must do two things to ensure back-
32123212+ references and creation-id references resolve the same as if the
32133213+ entire request were processed on a single server:
32143214+32153215+ 1. It must pass a "createdIds" property with each subrequest. If
32163216+ this is not given by the client, an empty object should be used
32173217+ for the first subrequest. The "createdIds" property of each
32183218+ subresponse should be passed on in the next subrequest.
32193219+32203220+ 2. It must resolve back-references to previous method results that
32213221+ were processed on a different server. This is a relatively
32223222+ simple syntactic substitution, described in Section 3.7.
32233223+32243224+ When splitting a request based on accountId, proxy implementors do
32253225+ need to be aware of "/copy" methods that copy between accounts. If
32263226+ the accounts are on different servers, the proxy will have to
32273227+ implement this functionality directly.
32283228+32293229+6. Binary Data
32303230+32313231+ Binary data is referenced by a *blobId* in JMAP and uploaded/
32323232+ downloaded separately to the core API. The blobId solely represents
32333233+ the raw bytes of data, not any associated metadata such as a file
32343234+ name or content type. Such metadata is stored alongside the blobId
32353235+ in the object referencing it. The data represented by a blobId is
32363236+ immutable.
32373237+32383238+ Any blobId that exists within an account may be used when creating/
32393239+ updating another object in that account. For example, an Email type
32403240+ may have a blobId that represents the object in Internet Message
32413241+ Format [RFC5322]. A client could create a new Email object with an
32423242+ attachment and use this blobId, in effect attaching the old message
32433243+ to the new one. Similarly, it could attach any existing attachment
32443244+ of an old message without having to download and upload it again.
32453245+32463246+32473247+32483248+32493249+32503250+Jenkins & Newman Standards Track [Page 58]
32513251+32523252+RFC 8620 JMAP July 2019
32533253+32543254+32553255+ When the client uses a blobId in a create/update, the server MAY
32563256+ assign a new blobId to refer to the same binary data within the new/
32573257+ updated object. If it does so, it MUST return any properties that
32583258+ contain a changed blobId in the created/updated response, so the
32593259+ client gets the new ids.
32603260+32613261+ A blob that is not referenced by a JMAP object (e.g., as a message
32623262+ attachment) MAY be deleted by the server to free up resources.
32633263+ Uploads (see below) are initially unreferenced blobs. To ensure
32643264+ interoperability:
32653265+32663266+ o The server SHOULD use a separate quota for unreferenced blobs to
32673267+ the account's usual quota. In the case of shared accounts, this
32683268+ quota SHOULD be separate per user.
32693269+32703270+ o This quota SHOULD be at least the maximum total size that a single
32713271+ object can reference on this server. For example, if supporting
32723272+ JMAP Mail, this should be at least the maximum total attachments
32733273+ size for a message.
32743274+32753275+ o When an upload would take the user over quota, the server MUST
32763276+ delete unreferenced blobs in date order, oldest first, until there
32773277+ is room for the new blob.
32783278+32793279+ o Except where quota restrictions force early deletion, an
32803280+ unreferenced blob MUST NOT be deleted for at least 1 hour from the
32813281+ time of upload; if reuploaded, the same blobId MAY be returned,
32823282+ but this SHOULD reset the expiry time.
32833283+32843284+ o A blob MUST NOT be deleted during the method call that removed the
32853285+ last reference, so that a client can issue a create and a destroy
32863286+ that both reference the blob within the same method call.
32873287+32883288+6.1. Uploading Binary Data
32893289+32903290+ There is a single endpoint that handles all file uploads for an
32913291+ account, regardless of what they are to be used for. The Session
32923292+ object (see Section 2) has an "uploadUrl" property in URI Template
32933293+ (level 1) format [RFC6570], which MUST contain a variable called
32943294+ "accountId". The client may use this template in combination with an
32953295+ "accountId" to get the URL of the file upload resource.
32963296+32973297+ To upload a file, the client submits an authenticated POST request to
32983298+ the file upload resource.
32993299+33003300+33013301+33023302+33033303+33043304+33053305+33063306+Jenkins & Newman Standards Track [Page 59]
33073307+33083308+RFC 8620 JMAP July 2019
33093309+33103310+33113311+ A successful request MUST return a single JSON object with the
33123312+ following properties as the response:
33133313+33143314+ o accountId: "Id"
33153315+33163316+ The id of the account used for the call.
33173317+33183318+ o blobId: "Id"
33193319+33203320+ The id representing the binary data uploaded. The data for this
33213321+ id is immutable. The id *only* refers to the binary data, not any
33223322+ metadata.
33233323+33243324+ o type: "String"
33253325+33263326+ The media type of the file (as specified in [RFC6838],
33273327+ Section 4.2) as set in the Content-Type header of the upload HTTP
33283328+ request.
33293329+33303330+ o size: "UnsignedInt"
33313331+33323332+ The size of the file in octets.
33333333+33343334+ If identical binary content to an existing blob in the account is
33353335+ uploaded, the existing blobId MAY be returned.
33363336+33373337+ Clients should use the blobId returned in a timely manner. Under
33383338+ rare circumstances, the server may have deleted the blob before the
33393339+ client uses it; the client should keep a reference to the local file
33403340+ so it can upload it again in such a situation.
33413341+33423342+ When an HTTP error response is returned to the client, the server
33433343+ SHOULD return a JSON "problem details" object as the response body,
33443344+ as per [RFC7807].
33453345+33463346+ As access controls are often determined by the object holding the
33473347+ reference to a blob, unreferenced blobs MUST only be accessible to
33483348+ the uploader, even in shared accounts.
33493349+33503350+6.2. Downloading Binary Data
33513351+33523352+ The Session object (see Section 2) has a "downloadUrl" property,
33533353+ which is in URI Template (level 1) format [RFC6570]. The URL MUST
33543354+ contain variables called "accountId", "blobId", "type", and "name".
33553355+33563356+33573357+33583358+33593359+33603360+33613361+33623362+Jenkins & Newman Standards Track [Page 60]
33633363+33643364+RFC 8620 JMAP July 2019
33653365+33663366+33673367+ To download a file, the client makes an authenticated GET request to
33683368+ the download URL with the appropriate variables substituted in:
33693369+33703370+ o "accountId": The id of the account to which the record with the
33713371+ blobId belongs.
33723372+33733373+ o "blobId": The blobId representing the data of the file to
33743374+ download.
33753375+33763376+ o "type": The type for the server to set in the "Content-Type"
33773377+ header of the response; the blobId only represents the binary data
33783378+ and does not have a content-type innately associated with it.
33793379+33803380+ o "name": The name for the file; the server MUST return this as the
33813381+ filename if it sets a "Content-Disposition" header.
33823382+33833383+ As the data for a particular blobId is immutable, and thus the
33843384+ response in the generated download URL is too, implementors are
33853385+ recommended to set long cache times and use the "immutable" Cache-
33863386+ Control extension [RFC8246] for successful responses, for example,
33873387+ "Cache-Control: private, immutable, max-age=31536000".
33883388+33893389+ When an HTTP error response is returned to the client, the server
33903390+ SHOULD return a JSON "problem details" object as the response body,
33913391+ as per [RFC7807].
33923392+33933393+6.3. Blob/copy
33943394+33953395+ Binary data may be copied *between* two different accounts using the
33963396+ "Blob/copy" method rather than having to download and then reupload
33973397+ on the client.
33983398+33993399+ The "Blob/copy" method takes the following arguments:
34003400+34013401+ o fromAccountId: "Id"
34023402+34033403+ The id of the account to copy blobs from.
34043404+34053405+ o accountId: "Id"
34063406+34073407+ The id of the account to copy blobs to.
34083408+34093409+ o blobIds: "Id[]"
34103410+34113411+ A list of ids of blobs to copy to the other account.
34123412+34133413+34143414+34153415+34163416+34173417+34183418+Jenkins & Newman Standards Track [Page 61]
34193419+34203420+RFC 8620 JMAP July 2019
34213421+34223422+34233423+ The response has the following arguments:
34243424+34253425+ o fromAccountId: "Id"
34263426+34273427+ The id of the account blobs were copied from.
34283428+34293429+ o accountId: "Id"
34303430+34313431+ The id of the account blobs were copied to.
34323432+34333433+ o copied: "Id[Id]|null"
34343434+34353435+ A map of the blobId in the fromAccount to the id for the blob in
34363436+ the account it was copied to, or null if none were successfully
34373437+ copied.
34383438+34393439+ o notCopied: "Id[SetError]|null"
34403440+34413441+ A map of blobId to a SetError object for each blob that failed to
34423442+ be copied, or null if none.
34433443+34443444+ The SetError may be any of the standard set errors that may be
34453445+ returned for a create, as defined in Section 5.3. In addition, the
34463446+ "notFound" SetError error may be returned if the blobId to be copied
34473447+ cannot be found.
34483448+34493449+ The following additional method-level error may be returned instead
34503450+ of the "Blob/copy" response:
34513451+34523452+ "fromAccountNotFound": The "fromAccountId" included with the request
34533453+ does not correspond to a valid account.
34543454+34553455+7. Push
34563456+34573457+ Push notifications allow clients to efficiently update (almost)
34583458+ instantly to stay in sync with data changes on the server. The
34593459+ general model for push is simple and sends minimal data over the push
34603460+ channel: just enough for the client to know whether it needs to
34613461+ resync. The format allows multiple changes to be coalesced into a
34623462+ single push update and the frequency of pushes to be rate limited by
34633463+ the server. It doesn't matter if some push events are dropped before
34643464+ they reach the client; the next time it gets/sets any records of a
34653465+ changed type, it will discover the data has changed and still sync
34663466+ all changes.
34673467+34683468+34693469+34703470+34713471+34723472+34733473+34743474+Jenkins & Newman Standards Track [Page 62]
34753475+34763476+RFC 8620 JMAP July 2019
34773477+34783478+34793479+ There are two different mechanisms by which a client can receive push
34803480+ notifications, to allow for the different environments in which a
34813481+ client may exist. An event source resource (see Section 7.3) allows
34823482+ clients that can hold transport connections open to receive push
34833483+ notifications directly from the JMAP server. This is simple and
34843484+ avoids third parties, but it is often not feasible on constrained
34853485+ platforms such as mobile devices. Alternatively, clients can make
34863486+ use of any push service supported by their environment. A URL for
34873487+ the push service is registered with the JMAP server (see
34883488+ Section 7.2); the server then POSTs each notification to that URL.
34893489+ The push service is then responsible for routing these to the client.
34903490+34913491+7.1. The StateChange Object
34923492+34933493+ When something changes on the server, the server pushes a StateChange
34943494+ object to the client. A *StateChange* object has the following
34953495+ properties:
34963496+34973497+ o @type: "String"
34983498+34993499+ This MUST be the string "StateChange".
35003500+35013501+ o changed: "Id[TypeState]"
35023502+35033503+ A map of an "account id" to an object encoding the state of data
35043504+ types that have changed for that account since the last
35053505+ StateChange object was pushed, for each of the accounts to which
35063506+ the user has access and for which something has changed.
35073507+35083508+ A *TypeState* object is a map. The keys are the type name "Foo"
35093509+ (e.g., "Mailbox" or "Email"), and the value is the "state"
35103510+ property that would currently be returned by a call to "Foo/get".
35113511+35123512+ The client can compare the new state strings with its current
35133513+ values to see whether it has the current data for these types. If
35143514+ not, the changes can then be efficiently fetched in a single
35153515+ standard API request (using the /changes type methods).
35163516+35173517+35183518+35193519+35203520+35213521+35223522+35233523+35243524+35253525+35263526+35273527+35283528+35293529+35303530+Jenkins & Newman Standards Track [Page 63]
35313531+35323532+RFC 8620 JMAP July 2019
35333533+35343534+35353535+7.1.1. Example
35363536+35373537+ In this example, the server has amalgamated a few changes together
35383538+ across two different accounts the user has access to, before pushing
35393539+ the following StateChange object to the client:
35403540+35413541+ {
35423542+ "@type": "StateChange",
35433543+ "changed": {
35443544+ "a3123": {
35453545+ "Email": "d35ecb040aab",
35463546+ "EmailDelivery": "428d565f2440",
35473547+ "CalendarEvent": "87accfac587a"
35483548+ },
35493549+ "a43461d": {
35503550+ "Mailbox": "0af7a512ce70",
35513551+ "CalendarEvent": "7a4297cecd76"
35523552+ }
35533553+ }
35543554+ }
35553555+35563556+ The client can compare the state strings with its current state for
35573557+ the Email, CalendarEvent, etc., object types in the appropriate
35583558+ accounts to see if it needs to fetch changes.
35593559+35603560+ If the client is itself making changes, it may receive a StateChange
35613561+ object while the /set API call is in flight. It can wait until the
35623562+ call completes and then compare if the new state string after the
35633563+ /set is the same as was pushed in the StateChange object; if so, and
35643564+ the old state of the /set response matches the client's previous
35653565+ state, it does not need to waste a request asking for changes it
35663566+ already knows.
35673567+35683568+7.2. PushSubscription
35693569+35703570+ Clients may create a PushSubscription to register a URL with the JMAP
35713571+ server. The JMAP server will then make an HTTP POST request to this
35723572+ URL for each push notification it wishes to send to the client.
35733573+35743574+ As a push subscription causes the JMAP server to make a number of
35753575+ requests to a previously unknown endpoint, it can be used as a vector
35763576+ for launching a denial-of-service attack. To prevent this, when a
35773577+ subscription is created, the JMAP server immediately sends a
35783578+ PushVerification object to that URL (see Section 7.2.2). The JMAP
35793579+ server MUST NOT make any further requests to the URL until the client
35803580+ receives the push and updates the subscription with the correct
35813581+ verification code.
35823582+35833583+35843584+35853585+35863586+Jenkins & Newman Standards Track [Page 64]
35873587+35883588+RFC 8620 JMAP July 2019
35893589+35903590+35913591+ A *PushSubscription* object has the following properties:
35923592+35933593+ o id: "Id" (immutable; server-set)
35943594+35953595+ The id of the push subscription.
35963596+35973597+ o deviceClientId: "String" (immutable)
35983598+35993599+ An id that uniquely identifies the client + device it is running
36003600+ on. The purpose of this is to allow clients to identify which
36013601+ PushSubscription objects they created even if they lose their
36023602+ local state, so they can revoke or update them. This string MUST
36033603+ be different on different devices and be different from apps from
36043604+ other vendors. It SHOULD be easy to regenerate and not depend on
36053605+ persisted state. It is RECOMMENDED to use a secure hash of a
36063606+ string that contains:
36073607+36083608+ 1. A unique identifier associated with the device where the JMAP
36093609+ client is running, normally supplied by the device's operating
36103610+ system.
36113611+36123612+ 2. A custom vendor/app id, including a domain controlled by the
36133613+ vendor of the JMAP client.
36143614+36153615+ To protect the privacy of the user, the deviceClientId id MUST NOT
36163616+ contain an unobfuscated device id.
36173617+36183618+ o url: "String" (immutable)
36193619+36203620+ An absolute URL where the JMAP server will POST the data for the
36213621+ push message. This MUST begin with "https://".
36223622+36233623+ o keys: "Object|null" (immutable)
36243624+36253625+ Client-generated encryption keys. If supplied, the server MUST
36263626+ use them as specified in [RFC8291] to encrypt all data sent to the
36273627+ push subscription. The object MUST have the following properties:
36283628+36293629+ * p256dh: "String"
36303630+36313631+ The P-256 Elliptic Curve Diffie-Hellman (ECDH) public key as
36323632+ described in [RFC8291], encoded in URL-safe base64
36333633+ representation as defined in [RFC4648].
36343634+36353635+ * auth: "String"
36363636+36373637+ The authentication secret as described in [RFC8291], encoded in
36383638+ URL-safe base64 representation as defined in [RFC4648].
36393639+36403640+36413641+36423642+Jenkins & Newman Standards Track [Page 65]
36433643+36443644+RFC 8620 JMAP July 2019
36453645+36463646+36473647+ o verificationCode: "String|null"
36483648+36493649+ This MUST be null (or omitted) when the subscription is created.
36503650+ The JMAP server then generates a verification code and sends it in
36513651+ a push message, and the client updates the PushSubscription object
36523652+ with the code; see Section 7.2.2 for details.
36533653+36543654+ o expires: "UTCDate|null"
36553655+36563656+ The time this push subscription expires. If specified, the JMAP
36573657+ server MUST NOT make further requests to this resource after this
36583658+ time. It MAY automatically destroy the push subscription at or
36593659+ after this time.
36603660+36613661+ The server MAY choose to set an expiry if none is given by the
36623662+ client or modify the expiry time given by the client to a shorter
36633663+ duration.
36643664+36653665+ o types: "String[]|null"
36663666+36673667+ A list of types the client is interested in (using the same names
36683668+ as the keys in the TypeState object defined in the previous
36693669+ section). A StateChange notification will only be sent if the
36703670+ data for one of these types changes. Other types are omitted from
36713671+ the TypeState object. If null, changes will be pushed for all
36723672+ types.
36733673+36743674+ The POST request MUST have a content type of "application/json" and
36753675+ contain the UTF-8 JSON-encoded object as the body. The request MUST
36763676+ have a "TTL" header and MAY have "Urgency" and/or "Topic" headers, as
36773677+ specified in Section 5 of [RFC8030]. The JMAP server is expected to
36783678+ understand and handle HTTP status responses in a reasonable manner.
36793679+ A "429" (Too Many Requests) response MUST cause the JMAP server to
36803680+ reduce the frequency of pushes; the JMAP push structure allows
36813681+ multiple changes to be coalesced into a single minimal StateChange
36823682+ object. See the security considerations in Section 8.6 for a
36833683+ discussion of the risks in connecting to unknown servers.
36843684+36853685+ The JMAP server acts as an application server as defined in
36863686+ [RFC8030]. A client MAY use the rest of [RFC8030] in combination
36873687+ with its own push service to form a complete end-to-end solution, or
36883688+ it MAY rely on alternative mechanisms to ensure the delivery of the
36893689+ pushed data after it leaves the JMAP server.
36903690+36913691+ The push subscription is tied to the credentials used to authenticate
36923692+ the API request that created it. Should these credentials expire or
36933693+ be revoked, the push subscription MUST be destroyed by the JMAP
36943694+36953695+36963696+36973697+36983698+Jenkins & Newman Standards Track [Page 66]
36993699+37003700+RFC 8620 JMAP July 2019
37013701+37023702+37033703+ server. Only subscriptions created by these credentials are returned
37043704+ when the client fetches existing subscriptions.
37053705+37063706+ When these credentials have their own expiry (i.e., it is a session
37073707+ with a timeout), the server SHOULD NOT set or bound the expiry time
37083708+ for the push subscription given by the client but MUST expire it when
37093709+ the session expires.
37103710+37113711+ When these credentials are not time bounded (e.g., Basic
37123712+ authentication [RFC7617]), the server SHOULD set an expiry time for
37133713+ the push subscription if none is given and limit the expiry time if
37143714+ set too far in the future. This maximum expiry time MUST be at least
37153715+ 48 hours in the future and SHOULD be at least 7 days in the future.
37163716+ An app running on a mobile device may only be able to refresh the
37173717+ push subscription lifetime when it is in the foreground, so this
37183718+ gives a reasonable time frame to allow this to happen.
37193719+37203720+ In the case of separate access and refresh credentials, as in Oauth
37213721+ 2.0 [RFC6749], the server SHOULD tie the push subscription to the
37223722+ validity of the refresh token rather than the access token and behave
37233723+ according to whether this is time-limited or not.
37243724+37253725+ When a push subscription is destroyed, the server MUST securely erase
37263726+ the URL and encryption keys from memory and storage as soon as
37273727+ possible.
37283728+37293729+7.2.1. PushSubscription/get
37303730+37313731+ Standard /get method as described in Section 5.1, except it does
37323732+ *not* take or return an "accountId" argument, as push subscriptions
37333733+ are not tied to specific accounts. It also does *not* return a
37343734+ "state" argument. The "ids" argument may be null to fetch all at
37353735+ once.
37363736+37373737+ The server MUST only return push subscriptions that were created
37383738+ using the same authentication credentials as for this
37393739+ "PushSubscription/get" request.
37403740+37413741+ As the "url" and "keys" properties may contain data that is private
37423742+ to a particular device, the values for these properties MUST NOT be
37433743+ returned. If the "properties" argument is null or omitted, the
37443744+ server MUST default to all properties excluding these two. If one of
37453745+ them is explicitly requested, the method call MUST be rejected with a
37463746+ "forbidden" error.
37473747+37483748+37493749+37503750+37513751+37523752+37533753+37543754+Jenkins & Newman Standards Track [Page 67]
37553755+37563756+RFC 8620 JMAP July 2019
37573757+37583758+37593759+7.2.2. PushSubscription/set
37603760+37613761+ Standard /set method as described in Section 5.3, except it does
37623762+ *not* take or return an "accountId" argument, as push subscriptions
37633763+ are not tied to specific accounts. It also does *not* take an
37643764+ "ifInState" argument or return "oldState" or "newState" arguments.
37653765+37663766+ The "url" and "keys" properties are immutable; if the client wishes
37673767+ to change these, it must destroy the current push subscription and
37683768+ create a new one.
37693769+37703770+ When a PushSubscription is created, the server MUST immediately push
37713771+ a *PushVerification* object to the URL. It has the following
37723772+ properties:
37733773+37743774+ o @type: "String"
37753775+37763776+ This MUST be the string "PushVerification".
37773777+37783778+ o pushSubscriptionId: "String"
37793779+37803780+ The id of the push subscription that was created.
37813781+37823782+ o verificationCode: "String"
37833783+37843784+ The verification code to add to the push subscription. This MUST
37853785+ contain sufficient entropy to avoid the client being able to guess
37863786+ the code via brute force.
37873787+37883788+ The client MUST update the push subscription with the correct
37893789+ verification code before the server makes any further requests to the
37903790+ subscription's URL. Attempts to update the subscription with an
37913791+ invalid verification code MUST be rejected by the server with an
37923792+ "invalidProperties" SetError.
37933793+37943794+ The client may update the "expires" property to extend (or, less
37953795+ commonly, shorten) the lifetime of a push subscription. The server
37963796+ MAY modify the proposed new expiry time to enforce server-defined
37973797+ limits. Extending the lifetime does not require the subscription to
37983798+ be verified again.
37993799+38003800+ Clients SHOULD NOT update or destroy a push subscription that they
38013801+ did not create (i.e., has a "deviceClientId" that they do not
38023802+ recognise).
38033803+38043804+38053805+38063806+38073807+38083808+38093809+38103810+Jenkins & Newman Standards Track [Page 68]
38113811+38123812+RFC 8620 JMAP July 2019
38133813+38143814+38153815+7.2.3. Example
38163816+38173817+ At "2018-07-06T02:14:29Z", a client with deviceClientId "a889-ffea-
38183818+ 910" fetches the set of push subscriptions currently on the server,
38193819+ making an API request with:
38203820+38213821+ [[ "PushSubscription/get", {
38223822+ "ids": null
38233823+ }, "0" ]]
38243824+38253825+ Which returns:
38263826+38273827+ [[ "PushSubscription/get", {
38283828+ "list": [{
38293829+ "id": "e50b2c1d-9553-41a3-b0a7-a7d26b599ee1",
38303830+ "deviceClientId": "b37ff8001ca0",
38313831+ "verificationCode": "b210ef734fe5f439c1ca386421359f7b",
38323832+ "expires": "2018-07-31T00:13:21Z",
38333833+ "types": [ "Todo" ]
38343834+ }, {
38353835+ "id": "f2d0aab5-e976-4e8b-ad4b-b380a5b987e4",
38363836+ "deviceClientId": "X8980fc",
38373837+ "verificationCode": "f3d4618a9ae15c8b7f5582533786d531",
38383838+ "expires": "2018-07-12T05:55:00Z",
38393839+ "types": [ "Mailbox", "Email", "EmailDelivery" ]
38403840+ }],
38413841+ "notFound": []
38423842+ }, "0" ]]
38433843+38443844+ Since neither of the returned push subscription objects have the
38453845+ client's deviceClientId, it knows it does not have a current push
38463846+ subscription active on the server. So it creates one, sending this
38473847+ request:
38483848+38493849+[[ "PushSubscription/set", {
38503850+ "create": {
38513851+ "4f29": {
38523852+ "deviceClientId": "a889-ffea-910",
38533853+ "url": "https://example.com/push/?device=X8980fc&client=12c6d086",
38543854+ "types": null
38553855+ }
38563856+ }
38573857+}, "0" ]]
38583858+38593859+38603860+38613861+38623862+38633863+38643864+38653865+38663866+Jenkins & Newman Standards Track [Page 69]
38673867+38683868+RFC 8620 JMAP July 2019
38693869+38703870+38713871+ The server creates the push subscription but limits the expiry time
38723872+ to 7 days in the future, returning this response:
38733873+38743874+ [[ "PushSubscription/set", {
38753875+ "created": {
38763876+ "4f29": {
38773877+ "id": "P43dcfa4-1dd4-41ef-9156-2c89b3b19c60",
38783878+ "keys": null,
38793879+ "expires": "2018-07-13T02:14:29Z"
38803880+ }
38813881+ }
38823882+ }, "0" ]]
38833883+38843884+ The server also immediately makes a POST request to
38853885+ "https://example.com/push/?device=X8980fc&client=12c6d086" with the
38863886+ data:
38873887+38883888+ {
38893889+ "@type": "PushVerification",
38903890+ "pushSubscriptionId": "P43dcfa4-1dd4-41ef-9156-2c89b3b19c60",
38913891+ "verificationCode": "da1f097b11ca17f06424e30bf02bfa67"
38923892+ }
38933893+38943894+ The client receives this and updates the subscription with the
38953895+ verification code (note there is a potential race condition here; the
38963896+ client MUST be able to handle receiving the push while the request
38973897+ creating the subscription is still in progress):
38983898+38993899+ [[ "PushSubscription/set", {
39003900+ "update": {
39013901+ "P43dcfa4-1dd4-41ef-9156-2c89b3b19c60": {
39023902+ "verificationCode": "da1f097b11ca17f06424e30bf02bfa67"
39033903+ }
39043904+ }
39053905+ }, "0" ]]
39063906+39073907+ The server confirms the update was successful and will now make
39083908+ requests to the registered URL when the state changes.
39093909+39103910+39113911+39123912+39133913+39143914+39153915+39163916+39173917+39183918+39193919+39203920+39213921+39223922+Jenkins & Newman Standards Track [Page 70]
39233923+39243924+RFC 8620 JMAP July 2019
39253925+39263926+39273927+ Two days later, the client updates the subscription to extend its
39283928+ lifetime, sending this request:
39293929+39303930+ [[ "PushSubscription/set", {
39313931+ "update": {
39323932+ "P43dcfa4-1dd4-41ef-9156-2c89b3b19c60": {
39333933+ "expires": "2018-08-13T00:00:00Z"
39343934+ }
39353935+ }
39363936+ }, "0" ]]
39373937+39383938+ The server extends the expiry time, but only again to its maximum
39393939+ limit of 7 days in the future, returning this response:
39403940+39413941+ [[ "PushSubscription/set", {
39423942+ "updated": {
39433943+ "P43dcfa4-1dd4-41ef-9156-2c89b3b19c60": {
39443944+ "expires": "2018-07-15T02:22:50Z"
39453945+ }
39463946+ }
39473947+ }, "0" ]]
39483948+39493949+7.3. Event Source
39503950+39513951+ Clients that can hold transport connections open can connect directly
39523952+ to the JMAP server to receive push notifications via a "text/event-
39533953+ stream" resource, as described in [EventSource]. This is a long
39543954+ running HTTP request, where the server can push data to the client by
39553955+ appending data without ending the response.
39563956+39573957+ When a change occurs in the data on the server, it pushes an event
39583958+ called "state" to any connected clients, with the StateChange object
39593959+ as the data.
39603960+39613961+ The server SHOULD also send a new event id that encodes the entire
39623962+ server state visible to the user immediately after sending a "state"
39633963+ event. When a new connection is made to the event-source endpoint, a
39643964+ client following the server-sent events specification will send a
39653965+ Last-Event-ID HTTP header field with the last id it saw, which the
39663966+ server can use to work out whether the client has missed some
39673967+ changes. If so, it SHOULD send these changes immediately on
39683968+ connection.
39693969+39703970+ The Session object (see Section 2) has an "eventSourceUrl" property,
39713971+ which is in URI Template (level 1) format [RFC6570]. The URL MUST
39723972+ contain variables called "types", "closeafter", and "ping".
39733973+39743974+39753975+39763976+39773977+39783978+Jenkins & Newman Standards Track [Page 71]
39793979+39803980+RFC 8620 JMAP July 2019
39813981+39823982+39833983+ To connect to the resource, the client makes an authenticated GET
39843984+ request to the event-source URL with the appropriate variables
39853985+ substituted in:
39863986+39873987+ o "types": This MUST be either:
39883988+39893989+ * A comma-separated list of type names, e.g.,
39903990+ "Email,CalendarEvent". The server MUST only push changes for
39913991+ the types in this list.
39923992+39933993+ * The single character: "*". Changes to all types are pushed.
39943994+39953995+ o "closeafter": This MUST be one of the following values:
39963996+39973997+ * "state": The server MUST end the HTTP response after pushing a
39983998+ state event. This can be used by clients in environments where
39993999+ buffering proxies prevent the pushed data from arriving
40004000+ immediately, or indeed at all, when operating in the usual
40014001+ mode.
40024002+40034003+ * "no": The connection is persisted by the server as a standard
40044004+ event-source resource.
40054005+40064006+ o "ping": A positive integer value representing a length of time in
40074007+ seconds, e.g., "300". If non-zero, the server MUST send an event
40084008+ called "ping" whenever this time elapses since the previous event
40094009+ was sent. This MUST NOT set a new event id. If the value is "0",
40104010+ the server MUST NOT send ping events.
40114011+40124012+ The server MAY modify a requested ping interval to be subject to a
40134013+ minimum and/or maximum value. For interoperability, servers MUST
40144014+ NOT have a minimum allowed value higher than 30 or a maximum
40154015+ allowed value less than 300.
40164016+40174017+ The data for the ping event MUST be a JSON object containing an
40184018+ "interval" property, the value (type "UnsignedInt") being the
40194019+ interval in seconds the server is using to send pings (this may be
40204020+ different to the requested value if the server clamped it to be
40214021+ within a min/max value).
40224022+40234023+ Clients can monitor for the ping event to help determine when the
40244024+ closeafter mode may be required.
40254025+40264026+ A client MAY hold open multiple connections to the event-source
40274027+ resource, although it SHOULD try to use a single connection for
40284028+ efficiency.
40294029+40304030+40314031+40324032+40334033+40344034+Jenkins & Newman Standards Track [Page 72]
40354035+40364036+RFC 8620 JMAP July 2019
40374037+40384038+40394039+8. Security Considerations
40404040+40414041+8.1. Transport Confidentiality
40424042+40434043+ To ensure the confidentiality and integrity of data sent and received
40444044+ via JMAP, all requests MUST use TLS 1.2 [RFC5246] [RFC8446] or later,
40454045+ following the recommendations in [RFC7525]. Servers SHOULD support
40464046+ TLS 1.3 [RFC8446] or later.
40474047+40484048+ Clients MUST validate TLS certificate chains to protect against
40494049+ man-in-the-middle attacks [RFC5280].
40504050+40514051+8.2. Authentication Scheme
40524052+40534053+ A number of HTTP authentication schemes have been standardised (see
40544054+ <https://www.iana.org/assignments/http-authschemes/>). Servers
40554055+ should take care to assess the security characteristics of different
40564056+ schemes in relation to their needs when deciding what to implement.
40574057+40584058+ Use of the Basic authentication scheme is NOT RECOMMENDED. Services
40594059+ that choose to use it are strongly recommended to require generation
40604060+ of a unique "app password" via some external mechanism for each
40614061+ client they wish to connect. This allows connections from different
40624062+ devices to be differentiated by the server and access to be
40634063+ individually revoked.
40644064+40654065+8.3. Service Autodiscovery
40664066+40674067+ Unless secured by something like DNSSEC, autodiscovery of server
40684068+ details using SRV DNS records is vulnerable to a DNS poisoning
40694069+ attack, which can lead to the client talking to an attacker's server
40704070+ instead of the real JMAP server. The attacker may then intercept
40714071+ requests to execute man-in-the-middle attacks and, depending on the
40724072+ authentication scheme, steal credentials to generate its own
40734073+ requests.
40744074+40754075+ Clients that do not support SRV lookups are likely to try just using
40764076+ the "/.well-known/jmap" path directly against the domain of the
40774077+ username over HTTPS. Servers SHOULD ensure this path resolves or
40784078+ redirects to the correct JMAP Session resource to allow this to work.
40794079+ If this is not feasible, servers MUST ensure this path cannot be
40804080+ controlled by an attacker, as again it may be used to steal
40814081+ credentials.
40824082+40834083+40844084+40854085+40864086+40874087+40884088+40894089+40904090+Jenkins & Newman Standards Track [Page 73]
40914091+40924092+RFC 8620 JMAP July 2019
40934093+40944094+40954095+8.4. JSON Parsing
40964096+40974097+ The Security Considerations of [RFC8259] apply to the use of JSON as
40984098+ the data interchange format.
40994099+41004100+ As for any serialization format, parsers need to thoroughly check the
41014101+ syntax of the supplied data. JSON uses opening and closing tags for
41024102+ several types and structures, and it is possible that the end of the
41034103+ supplied data will be reached when scanning for a matching closing
41044104+ tag; this is an error condition, and implementations need to stop
41054105+ scanning at the end of the supplied data.
41064106+41074107+ JSON also uses a string encoding with some escape sequences to encode
41084108+ special characters within a string. Care is needed when processing
41094109+ these escape sequences to ensure that they are fully formed before
41104110+ the special processing is triggered, with special care taken when the
41114111+ escape sequences appear adjacent to other (non-escaped) special
41124112+ characters or adjacent to the end of data (as in the previous
41134113+ paragraph).
41144114+41154115+ If parsing JSON into a non-textual structured data format,
41164116+ implementations may need to allocate storage to hold JSON string
41174117+ elements. Since JSON does not use explicit string lengths, the risk
41184118+ of denial of service due to resource exhaustion is small, but
41194119+ implementations may still wish to place limits on the size of
41204120+ allocations they are willing to make in any given context, to avoid
41214121+ untrusted data causing excessive memory allocation.
41224122+41234123+8.5. Denial of Service
41244124+41254125+ A small request may result in a very large response and require
41264126+ considerable work on the server if resource limits are not enforced.
41274127+ JMAP provides mechanisms for advertising and enforcing a wide variety
41284128+ of limits for mitigating this threat, including limits on the number
41294129+ of objects fetched in a single method call, number of methods in a
41304130+ single request, number of concurrent requests, etc.
41314131+41324132+ JMAP servers MUST implement sensible limits to mitigate against
41334133+ resource exhaustion attacks.
41344134+41354135+8.6. Connection to Unknown Push Server
41364136+41374137+ When a push subscription is registered, the application server will
41384138+ make POST requests to the given URL. There are a number of security
41394139+ considerations that MUST be considered when implementing this.
41404140+41414141+41424142+41434143+41444144+41454145+41464146+Jenkins & Newman Standards Track [Page 74]
41474147+41484148+RFC 8620 JMAP July 2019
41494149+41504150+41514151+ The server MUST ensure the URL is externally resolvable to avoid
41524152+ server-side request forgery, where the server makes a request to a
41534153+ resource on its internal network.
41544154+41554155+ A malicious client may use the push subscription to attempt to flood
41564156+ a third party server with requests, creating a denial-of-service
41574157+ attack and masking the attacker's true identity. There is no
41584158+ guarantee that the URL given to the JMAP server is actually a valid
41594159+ push server. Upon creation of a push subscription, the JMAP server
41604160+ sends a PushVerification object to the URL and MUST NOT send any
41614161+ further requests until the client verifies it has received the
41624162+ initial push. The verification code MUST contain sufficient entropy
41634163+ to prevent the client from being able to verify the subscription via
41644164+ brute force.
41654165+41664166+ The verification code does not guarantee the URL is a valid push
41674167+ server, only that the client is able to access the data submitted to
41684168+ it. While the verification step significantly reduces the set of
41694169+ potential targets, there is still a risk that the server is unrelated
41704170+ to the client and being targeted for a denial-of-service attack.
41714171+41724172+ The server MUST limit the number of push subscriptions any one user
41734173+ may have to ensure the user cannot cause the server to send a large
41744174+ number of push notifications at once, which could again be used as
41754175+ part of a denial-of-service attack. The rate of creation MUST also
41764176+ be limited to minimise the ability to abuse the verification request
41774177+ as an attack vector.
41784178+41794179+8.7. Push Encryption
41804180+41814181+ When data changes, a small object is pushed with the new state
41824182+ strings for the types that have changed. While the data here is
41834183+ minimal, a passive man-in-the-middle attacker may be able to gain
41844184+ useful information. To ensure confidentiality and integrity, if the
41854185+ push is sent via a third party outside of the control of the client
41864186+ and JMAP server, the client MUST specify encryption keys when
41874187+ establishing the PushSubscription and ignore any push notification
41884188+ received that is not encrypted with those keys.
41894189+41904190+ The privacy and security considerations of [RFC8030] and [RFC8291]
41914191+ also apply to the use of the PushSubscription mechanism.
41924192+41934193+ As there is no crypto algorithm agility in Web Push Encryption
41944194+ [RFC8291], a new specification will be needed to provide this if new
41954195+ algorithms are required in the future.
41964196+41974197+41984198+41994199+42004200+42014201+42024202+Jenkins & Newman Standards Track [Page 75]
42034203+42044204+RFC 8620 JMAP July 2019
42054205+42064206+42074207+8.8. Traffic Analysis
42084208+42094209+ While the data is encrypted, a passive observer with the ability to
42104210+ monitor network traffic may be able to glean information from the
42114211+ timing of API requests and push notifications. For example, suppose
42124212+ an email or calendar invitation is sent from User A (hosted on Server
42134213+ X) to User B (hosted on Server Y). If Server X hosts data for many
42144214+ users, a passive observer can see that the two servers connected but
42154215+ does not know who the data was for. However, if a push notification
42164216+ is immediately sent to User B and the attacker can observe this as
42174217+ well, they may reasonably conclude that someone on Server X is
42184218+ connecting to User B.
42194219+42204220+9. IANA Considerations
42214221+42224222+9.1. Assignment of jmap Service Name
42234223+42244224+ IANA has assigned the 'jmap' service name in the "Service Name and
42254225+ Transport Protocol Port Number Registry" [RFC6335].
42264226+42274227+ Service Name: jmap
42284228+42294229+ Transport Protocol(s): tcp
42304230+42314231+ Assignee: IESG
42324232+42334233+ Contact: IETF Chair
42344234+42354235+ Description: JSON Meta Application Protocol
42364236+42374237+ Reference: RFC 8620
42384238+42394239+ Assignment Notes: This service name was previously assigned under the
42404240+ name "JSON Mail Access Protocol". This has been de-assigned and
42414241+ re-assigned with the approval of the previous assignee.
42424242+42434243+9.2. Registration of Well-Known URI Suffix for JMAP
42444244+42454245+ IANA has registered the following suffix in the "Well-Known URIs"
42464246+ registry for JMAP, as described in [RFC8615]:
42474247+42484248+ URI Suffix: jmap
42494249+42504250+ Change Controller: IETF
42514251+42524252+ Specification Document: RFC 8620, Section 2.2.
42534253+42544254+42554255+42564256+42574257+42584258+Jenkins & Newman Standards Track [Page 76]
42594259+42604260+RFC 8620 JMAP July 2019
42614261+42624262+42634263+9.3. Registration of the jmap URN Sub-namespace
42644264+42654265+ IANA has registered the following URN sub-namespace in the "IETF URN
42664266+ Sub-namespace for Registered Protocol Parameter Identifiers" registry
42674267+ within the "Uniform Resource Name (URN) Namespace for IETF Use"
42684268+ registry as described in [RFC3553].
42694269+42704270+ Registered Parameter Identifier: jmap
42714271+42724272+ Reference: RFC 8620, Section 9.4
42734273+42744274+ IANA Registry Reference: http://www.iana.org/assignments/jmap
42754275+42764276+9.4. Creation of "JMAP Capabilities" Registry
42774277+42784278+ IANA has created the "JMAP Capabilities" registry as described in
42794279+ Section 2. JMAP capabilities are advertised in the "capabilities"
42804280+ property of the JMAP Session resource. They are used to extend the
42814281+ functionality of a JMAP server. A capability is referenced by a URI.
42824282+ The JMAP capability URI can be a URN starting with
42834283+ "urn:ietf:params:jmap:" plus a unique suffix that is the index value
42844284+ in the jmap URN sub-namespace. Registration of a JMAP capability
42854285+ with another form of URI has no impact on the jmap URN sub-namespace.
42864286+42874287+ This registry follows the expert review process unless the "intended
42884288+ use" field is "common" or "placeholder", in which case registration
42894289+ follows the specification required process.
42904290+42914291+ A JMAP capability registration can have an intended use of "common",
42924292+ "placeholder", "limited", or "obsolete". IANA will list common-use
42934293+ registrations prominently and separately from those with other
42944294+ intended use values.
42954295+42964296+ The JMAP capability registration procedure is not a formal standards
42974297+ process but rather an administrative procedure intended to allow
42984298+ community comment and sanity checking without excessive time delay.
42994299+43004300+ A "placeholder" registration reserves part of the jmap URN namespace
43014301+ for another purpose but is typically not included in the
43024302+ "capabilities" property of the JMAP Session resource.
43034303+43044304+9.4.1. Preliminary Community Review
43054305+43064306+ Notice of a potential JMAP common-use registration SHOULD be sent to
43074307+ the JMAP mailing list <jmap@ietf.org> for review. This mailing list
43084308+ is appropriate to solicit community feedback on a proposed JMAP
43094309+43104310+43114311+43124312+43134313+43144314+Jenkins & Newman Standards Track [Page 77]
43154315+43164316+RFC 8620 JMAP July 2019
43174317+43184318+43194319+ capability. Registrations that are not intended for common use MAY
43204320+ be sent to the list for review as well; doing so is entirely
43214321+ OPTIONAL, but is encouraged.
43224322+43234323+ The intent of the public posting to this list is to solicit comments
43244324+ and feedback on the choice of the capability name, the unambiguity of
43254325+ the specification document, and a review of any interoperability or
43264326+ security considerations. The submitter may submit a revised
43274327+ registration proposal or abandon the registration completely at any
43284328+ time.
43294329+43304330+9.4.2. Submit Request to IANA
43314331+43324332+ Registration requests can be sent to <iana@iana.org>.
43334333+43344334+9.4.3. Designated Expert Review
43354335+43364336+ For a limited-use registration, the primary concern of the designated
43374337+ expert (DE) is preventing name collisions and encouraging the
43384338+ submitter to document security and privacy considerations; a
43394339+ published specification is not required. For a common-use
43404340+ registration, the DE is expected to confirm that suitable
43414341+ documentation, as described in Section 4.6 of [RFC8126], is
43424342+ available. The DE should also verify that the capability does not
43434343+ conflict with work that is active or already published within the
43444344+ IETF.
43454345+43464346+ Before a period of 30 days has passed, the DE will either approve or
43474347+ deny the registration request and publish a notice of the decision to
43484348+ the JMAP WG mailing list or its successor, as well as inform IANA. A
43494349+ denial notice must be justified by an explanation, and, in the cases
43504350+ where it is possible, concrete suggestions on how the request can be
43514351+ modified so as to become acceptable should be provided.
43524352+43534353+ If the DE does not respond within 30 days, the registrant may request
43544354+ the IESG take action to process the request in a timely manner.
43554355+43564356+9.4.4. Change Procedures
43574357+43584358+ Once a JMAP capability has been published by the IANA, the change
43594359+ controller may request a change to its definition. The same
43604360+ procedure that would be appropriate for the original registration
43614361+ request is used to process a change request.
43624362+43634363+ JMAP capability registrations may not be deleted; capabilities that
43644364+ are no longer believed appropriate for use can be declared obsolete
43654365+ by a change to their "intended use" field; such capabilities will be
43664366+ clearly marked in the lists published by the IANA.
43674367+43684368+43694369+43704370+Jenkins & Newman Standards Track [Page 78]
43714371+43724372+RFC 8620 JMAP July 2019
43734373+43744374+43754375+ Significant changes to a capability's definition should be requested
43764376+ only when there are serious omissions or errors in the published
43774377+ specification. When review is required, a change request may be
43784378+ denied if it renders entities that were valid under the previous
43794379+ definition invalid under the new definition.
43804380+43814381+ The owner of a JMAP capability may pass responsibility to another
43824382+ person or agency by informing the IANA; this can be done without
43834383+ discussion or review.
43844384+43854385+ The IESG may reassign responsibility for a JMAP capability. The most
43864386+ common case of this will be to enable changes to be made to
43874387+ capabilities where the author of the registration has died, moved out
43884388+ of contact, or is otherwise unable to make changes that are important
43894389+ to the community.
43904390+43914391+9.4.5. JMAP Capabilities Registry Template
43924392+43934393+ Capability name: (see capability property in Section 2)
43944394+43954395+ Specification document:
43964396+43974397+ Intended use: (one of common, limited, placeholder, or obsolete)
43984398+43994399+ Change controller: ("IETF" for Standards Track / BCP RFCs)
44004400+44014401+ Security and privacy considerations:
44024402+44034403+9.4.6. Initial Registration for JMAP Core
44044404+44054405+ Capability Name: "urn:ietf:params:jmap:core"
44064406+44074407+ Specification document: RFC 8620, Section 2
44084408+44094409+ Intended use: common
44104410+44114411+ Change Controller: IETF
44124412+44134413+ Security and privacy considerations: RFC 8620, Section 8.
44144414+44154415+44164416+44174417+44184418+44194419+44204420+44214421+44224422+44234423+44244424+44254425+44264426+Jenkins & Newman Standards Track [Page 79]
44274427+44284428+RFC 8620 JMAP July 2019
44294429+44304430+44314431+9.4.7. Registration for JMAP Error Placeholder in JMAP Capabilities
44324432+ Registry
44334433+44344434+ Capability Name: "urn:ietf:params:jmap:error:"
44354435+44364436+ Specification document: RFC 8620, Section 9.5
44374437+44384438+ Intended use: placeholder
44394439+44404440+ Change Controller: IETF
44414441+44424442+ Security and privacy considerations: RFC 8620, Section 8.
44434443+44444444+9.5. Creation of "JMAP Error Codes" Registry
44454445+44464446+ IANA has created the "JMAP Error Codes" registry. JMAP error codes
44474447+ appear in the "type" member of a JSON problem details object (as
44484448+ described in Section 3.6.1), the "type" member in a JMAP error object
44494449+ (as described in Section 3.6.2), or the "type" member of a JMAP
44504450+ method-specific error object (such as SetError in Section 5.3). When
44514451+ used in a problem details object, the prefix
44524452+ "urn:ietf:params:jmap:error:" is always included; when used in JMAP
44534453+ objects, the prefix is always omitted.
44544454+44554455+ This registry follows the expert review process. Preliminary
44564456+ community review for this registry follows the same procedures as the
44574457+ "JMAP Capabilities" registry, but it is optional. The change
44584458+ procedures for this registry are the same as the change procedures
44594459+ for the "JMAP Capabilities" registry.
44604460+44614461+9.5.1. Expert Review
44624462+44634463+ The designated expert should review the following aspects of the
44644464+ registration:
44654465+44664466+ 1. Verify the error code does not conflict with existing names.
44674467+44684468+ 2. Verify the error code follows the syntax limitations (does not
44694469+ require URI encoding).
44704470+44714471+ 3. Encourage the submitter to follow the naming convention of
44724472+ previously registered errors.
44734473+44744474+ 4. Encourage the submitter to describe client behaviours that are
44754475+ recommended in response to the error code. These may distinguish
44764476+ the error code from other error codes.
44774477+44784478+44794479+44804480+44814481+44824482+Jenkins & Newman Standards Track [Page 80]
44834483+44844484+RFC 8620 JMAP July 2019
44854485+44864486+44874487+ 5. Encourage the submitter to describe when the server should issue
44884488+ the error as opposed to some other error code.
44894489+44904490+ 6. Encourage the submitter to note any security considerations
44914491+ associated with the error, if any (e.g., an error code that might
44924492+ disclose existence of data the authenticated user does not have
44934493+ permission to know about).
44944494+44954495+ Steps 3-6 are meant to promote a higher-quality registry. However,
44964496+ the expert is encouraged to approve any registration that would not
44974497+ actively harm JMAP interoperability to make this a relatively
44984498+ lightweight process.
44994499+45004500+9.5.2. JMAP Error Codes Registry Template
45014501+45024502+ JMAP Error Code:
45034503+45044504+ Intended use: (one of "common", "limited", "obsolete")
45054505+45064506+ Change Controller: ("IETF" for Standards Track / BCP RFCs)
45074507+45084508+ Reference: (Optional. Only required if defined in an RFC.)
45094509+45104510+ Description:
45114511+45124512+9.5.3. Initial Contents for the JMAP Error Codes Registry
45134513+45144514+ o JMAP Error Code: accountNotFound
45154515+ Intended Use: Common
45164516+ Change Controller: IETF
45174517+ Reference: RFC 8620, Section 3.6.2
45184518+ Description: The accountId does not correspond to a valid account.
45194519+45204520+ o JMAP Error Code: accountNotSupportedByMethod
45214521+ Intended Use: Common
45224522+ Change Controller: IETF
45234523+ Reference: RFC 8620, Section 3.6.2
45244524+ Description: The accountId given corresponds to a valid account,
45254525+ but the account does not support this method or data type.
45264526+45274527+ o JMAP Error Code: accountReadOnly
45284528+ Intended Use: Common
45294529+ Change Controller: IETF
45304530+ Reference: RFC 8620, Section 3.6.2
45314531+ Description: This method modifies state, but the account is read-
45324532+ only (as returned on the corresponding Account object in the JMAP
45334533+ Session resource).
45344534+45354535+45364536+45374537+45384538+Jenkins & Newman Standards Track [Page 81]
45394539+45404540+RFC 8620 JMAP July 2019
45414541+45424542+45434543+ o JMAP Error Code: anchorNotFound
45444544+ Intended Use: Common
45454545+ Change Controller: IETF
45464546+ Reference: RFC 8620, Section 5.5
45474547+ Description: An anchor argument was supplied, but it cannot be
45484548+ found in the results of the query.
45494549+45504550+ o JMAP Error Code: alreadyExists
45514551+ Intended Use: Common
45524552+ Change Controller: IETF
45534553+ Reference: RFC 8620, Section 5.4
45544554+ Description: The server forbids duplicates, and the record already
45554555+ exists in the target account. An existingId property of type Id
45564556+ MUST be included on the SetError object with the id of the
45574557+ existing record.
45584558+45594559+ o JMAP Error Code: cannotCalculateChanges
45604560+ Intended Use: Common
45614561+ Change Controller: IETF
45624562+ Reference: RFC 8620, Sections 5.2 and 5.6
45634563+ Description: The server cannot calculate the changes from the
45644564+ state string given by the client.
45654565+45664566+ o JMAP Error Code: forbidden
45674567+ Intended Use: Common
45684568+ Change Controller: IETF
45694569+ Reference: RFC 8620, Sections 3.6.2, 5.3, and 7.2.1
45704570+ Description: The action would violate an ACL or other permissions
45714571+ policy.
45724572+45734573+ o JMAP Error Code: fromAccountNotFound
45744574+ Intended Use: Common
45754575+ Change Controller: IETF
45764576+ Reference: RFC 8620, Sections 5.4 and 6.3
45774577+ Description: The fromAccountId does not correspond to a valid
45784578+ account.
45794579+45804580+ o JMAP Error Code: fromAccountNotSupportedByMethod
45814581+ Intended Use: Common
45824582+ Change Controller: IETF
45834583+ Reference: RFC 8620, Section 5.4
45844584+ Description: The fromAccountId given corresponds to a valid
45854585+ account, but the account does not support this data type.
45864586+45874587+45884588+45894589+45904590+45914591+45924592+45934593+45944594+Jenkins & Newman Standards Track [Page 82]
45954595+45964596+RFC 8620 JMAP July 2019
45974597+45984598+45994599+ o JMAP Error Code: invalidArguments
46004600+ Intended Use: Common
46014601+ Change Controller: IETF
46024602+ Reference: RFC 8620, Section 3.6.2
46034603+ Description: One of the arguments is of the wrong type or
46044604+ otherwise invalid, or a required argument is missing.
46054605+46064606+ o JMAP Error Code: invalidPatch
46074607+ Intended Use: Common
46084608+ Change Controller: IETF
46094609+ Reference: RFC 8620, Section 5.3
46104610+ Description: The PatchObject given to update the record was not a
46114611+ valid patch.
46124612+46134613+ o JMAP Error Code: invalidProperties
46144614+ Intended Use: Common
46154615+ Change Controller: IETF
46164616+ Reference: RFC 8620, Section 5.3
46174617+ Description: The record given is invalid.
46184618+46194619+ o JMAP Error Code: notFound
46204620+ Intended Use: Common
46214621+ Change Controller: IETF
46224622+ Reference: RFC 8620, Section 5.3
46234623+ Description: The id given cannot be found.
46244624+46254625+ o JMAP Error Code: notJSON
46264626+ Intended Use: Common
46274627+ Change Controller: IETF
46284628+ Reference: RFC 8620, Section 3.6.1
46294629+ Description: The content type of the request was not application/
46304630+ json, or the request did not parse as I-JSON.
46314631+46324632+ o JMAP Error Code: notRequest
46334633+ Intended Use: Common
46344634+ Change Controller: IETF
46354635+ Reference: RFC 8620, Section 3.6.1
46364636+ Description: The request parsed as JSON but did not match the type
46374637+ signature of the Request object.
46384638+46394639+ o JMAP Error Code: overQuota
46404640+ Intended Use: Common
46414641+ Change Controller: IETF
46424642+ Reference: RFC 8620, Section 5.3
46434643+ Description: The create would exceed a server-defined limit on the
46444644+ number or total size of objects of this type.
46454645+46464646+46474647+46484648+46494649+46504650+Jenkins & Newman Standards Track [Page 83]
46514651+46524652+RFC 8620 JMAP July 2019
46534653+46544654+46554655+ o JMAP Error Code: rateLimit
46564656+ Intended Use: Common
46574657+ Change Controller: IETF
46584658+ Reference: RFC 8620, Section 5.3
46594659+ Description: Too many objects of this type have been created
46604660+ recently, and a server-defined rate limit has been reached. It
46614661+ may work if tried again later.
46624662+46634663+ o JMAP Error Code: requestTooLarge
46644664+ Intended Use: Common
46654665+ Change Controller: IETF
46664666+ Reference: RFC 8620, Sections 5.1 and 5.3
46674667+ Description: The total number of actions exceeds the maximum
46684668+ number the server is willing to process in a single method call.
46694669+46704670+ o JMAP Error Code: invalidResultReference
46714671+ Intended Use: Common
46724672+ Change Controller: IETF
46734673+ Reference: RFC 8620, Section 3.6.2
46744674+ Description: The method used a result reference for one of its
46754675+ arguments, but this failed to resolve.
46764676+46774677+ o JMAP Error Code: serverFail
46784678+ Intended Use: Common
46794679+ Change Controller: IETF
46804680+ Reference: RFC 8620, Section 3.6.2
46814681+ Description: An unexpected or unknown error occurred during the
46824682+ processing of the call. The method call made no changes to the
46834683+ server's state.
46844684+46854685+ o JMAP Error Code: serverPartialFail
46864686+ Intended Use: Limited
46874687+ Change Controller: IETF
46884688+ Reference: RFC 8620, Section 3.6.2
46894689+ Description: Some, but not all, expected changes described by the
46904690+ method occurred. The client MUST resynchronise impacted data to
46914691+ determine the server state. Use of this error is strongly
46924692+ discouraged.
46934693+46944694+ o JMAP Error Code: serverUnavailable
46954695+ Intended Use: Common
46964696+ Change Controller: IETF
46974697+ Reference: RFC 8620, Section 3.6.2
46984698+ Description: Some internal server resource was temporarily
46994699+ unavailable. Attempting the same operation later (perhaps after a
47004700+ backoff with a random factor) may succeed.
47014701+47024702+47034703+47044704+47054705+47064706+Jenkins & Newman Standards Track [Page 84]
47074707+47084708+RFC 8620 JMAP July 2019
47094709+47104710+47114711+ o JMAP Error Code: singleton
47124712+ Intended Use: Common
47134713+ Change Controller: IETF
47144714+ Reference: RFC 8620, Section 5.3
47154715+ Description: This is a singleton type, so you cannot create
47164716+ another one or destroy the existing one.
47174717+47184718+ o JMAP Error Code: stateMismatch
47194719+ Intended Use: Common
47204720+ Change Controller: IETF
47214721+ Reference: RFC 8620, Section 5.3
47224722+ Description: An ifInState argument was supplied, and it does not
47234723+ match the current state.
47244724+47254725+ o JMAP Error Code: tooLarge
47264726+ Intended Use: Common
47274727+ Change Controller: IETF
47284728+ Reference: RFC 8620, Section 5.3
47294729+ Description: The action would result in an object that exceeds a
47304730+ server-defined limit for the maximum size of a single object of
47314731+ this type.
47324732+47334733+ o JMAP Error Code: tooManyChanges
47344734+ Intended Use: Common
47354735+ Change Controller: IETF
47364736+ Reference: RFC 8620, Section 5.6
47374737+ Description: There are more changes than the client's maxChanges
47384738+ argument.
47394739+47404740+ o JMAP Error Code: unknownCapability
47414741+ Intended Use: Common
47424742+ Change Controller: IETF
47434743+ Reference: RFC 8620, Section 3.6.1
47444744+ Description: The client included a capability in the "using"
47454745+ property of the request that the server does not support.
47464746+47474747+ o JMAP Error Code: unknownMethod
47484748+ Intended Use: Common
47494749+ Change Controller: IETF
47504750+ Reference: RFC 8620, Section 3.6.2
47514751+ Description: The server does not recognise this method name.
47524752+47534753+ o JMAP Error Code: unsupportedFilter
47544754+ Intended Use: Common
47554755+ Change Controller: IETF
47564756+ Reference: RFC 8620, Section 5.5
47574757+ Description: The filter is syntactically valid, but the server
47584758+ cannot process it.
47594759+47604760+47614761+47624762+Jenkins & Newman Standards Track [Page 85]
47634763+47644764+RFC 8620 JMAP July 2019
47654765+47664766+47674767+ o JMAP Error Code: unsupportedSort
47684768+ Intended Use: Common
47694769+ Change Controller: IETF
47704770+ Reference: RFC 8620, Section 5.5
47714771+ Description: The sort is syntactically valid but includes a
47724772+ property the server does not support sorting on or a collation
47734773+ method it does not recognise.
47744774+47754775+ o JMAP Error Code: willDestroy
47764776+ Intended Use: Common
47774777+ Change Controller: IETF
47784778+ Reference: RFC 8620, Section 5.3
47794779+ Description: The client requested an object be both updated and
47804780+ destroyed in the same /set request, and the server has decided to
47814781+ therefore ignore the update.
47824782+47834783+10. References
47844784+47854785+10.1. Normative References
47864786+47874787+ [EventSource]
47884788+ Hickson, I., "Server-Sent Events", World Wide Web
47894789+ Consortium Recommendation REC-eventsource-20150203,
47904790+ February 2015, <https://www.w3.org/TR/eventsource/>.
47914791+47924792+ [RFC2119] Bradner, S., "Key words for use in RFCs to Indicate
47934793+ Requirement Levels", BCP 14, RFC 2119,
47944794+ DOI 10.17487/RFC2119, March 1997,
47954795+ <https://www.rfc-editor.org/info/rfc2119>.
47964796+47974797+ [RFC2782] Gulbrandsen, A., Vixie, P., and L. Esibov, "A DNS RR for
47984798+ specifying the location of services (DNS SRV)", RFC 2782,
47994799+ DOI 10.17487/RFC2782, February 2000,
48004800+ <https://www.rfc-editor.org/info/rfc2782>.
48014801+48024802+ [RFC2818] Rescorla, E., "HTTP Over TLS", RFC 2818,
48034803+ DOI 10.17487/RFC2818, May 2000,
48044804+ <https://www.rfc-editor.org/info/rfc2818>.
48054805+48064806+ [RFC3339] Klyne, G. and C. Newman, "Date and Time on the Internet:
48074807+ Timestamps", RFC 3339, DOI 10.17487/RFC3339, July 2002,
48084808+ <https://www.rfc-editor.org/info/rfc3339>.
48094809+48104810+ [RFC3553] Mealling, M., Masinter, L., Hardie, T., and G. Klyne, "An
48114811+ IETF URN Sub-namespace for Registered Protocol
48124812+ Parameters", BCP 73, RFC 3553, DOI 10.17487/RFC3553, June
48134813+ 2003, <https://www.rfc-editor.org/info/rfc3553>.
48144814+48154815+48164816+48174817+48184818+Jenkins & Newman Standards Track [Page 86]
48194819+48204820+RFC 8620 JMAP July 2019
48214821+48224822+48234823+ [RFC3629] Yergeau, F., "UTF-8, a transformation format of ISO
48244824+ 10646", STD 63, RFC 3629, DOI 10.17487/RFC3629, November
48254825+ 2003, <https://www.rfc-editor.org/info/rfc3629>.
48264826+48274827+ [RFC4648] Josefsson, S., "The Base16, Base32, and Base64 Data
48284828+ Encodings", RFC 4648, DOI 10.17487/RFC4648, October 2006,
48294829+ <https://www.rfc-editor.org/info/rfc4648>.
48304830+48314831+ [RFC4790] Newman, C., Duerst, M., and A. Gulbrandsen, "Internet
48324832+ Application Protocol Collation Registry", RFC 4790,
48334833+ DOI 10.17487/RFC4790, March 2007,
48344834+ <https://www.rfc-editor.org/info/rfc4790>.
48354835+48364836+ [RFC5051] Crispin, M., "i;unicode-casemap - Simple Unicode Collation
48374837+ Algorithm", RFC 5051, DOI 10.17487/RFC5051, October 2007,
48384838+ <https://www.rfc-editor.org/info/rfc5051>.
48394839+48404840+ [RFC5246] Dierks, T. and E. Rescorla, "The Transport Layer Security
48414841+ (TLS) Protocol Version 1.2", RFC 5246,
48424842+ DOI 10.17487/RFC5246, August 2008,
48434843+ <https://www.rfc-editor.org/info/rfc5246>.
48444844+48454845+ [RFC5280] Cooper, D., Santesson, S., Farrell, S., Boeyen, S.,
48464846+ Housley, R., and W. Polk, "Internet X.509 Public Key
48474847+ Infrastructure Certificate and Certificate Revocation List
48484848+ (CRL) Profile", RFC 5280, DOI 10.17487/RFC5280, May 2008,
48494849+ <https://www.rfc-editor.org/info/rfc5280>.
48504850+48514851+ [RFC5322] Resnick, P., Ed., "Internet Message Format", RFC 5322,
48524852+ DOI 10.17487/RFC5322, October 2008,
48534853+ <https://www.rfc-editor.org/info/rfc5322>.
48544854+48554855+ [RFC6186] Daboo, C., "Use of SRV Records for Locating Email
48564856+ Submission/Access Services", RFC 6186,
48574857+ DOI 10.17487/RFC6186, March 2011,
48584858+ <https://www.rfc-editor.org/info/rfc6186>.
48594859+48604860+ [RFC6335] Cotton, M., Eggert, L., Touch, J., Westerlund, M., and S.
48614861+ Cheshire, "Internet Assigned Numbers Authority (IANA)
48624862+ Procedures for the Management of the Service Name and
48634863+ Transport Protocol Port Number Registry", BCP 165,
48644864+ RFC 6335, DOI 10.17487/RFC6335, August 2011,
48654865+ <https://www.rfc-editor.org/info/rfc6335>.
48664866+48674867+ [RFC6570] Gregorio, J., Fielding, R., Hadley, M., Nottingham, M.,
48684868+ and D. Orchard, "URI Template", RFC 6570,
48694869+ DOI 10.17487/RFC6570, March 2012,
48704870+ <https://www.rfc-editor.org/info/rfc6570>.
48714871+48724872+48734873+48744874+Jenkins & Newman Standards Track [Page 87]
48754875+48764876+RFC 8620 JMAP July 2019
48774877+48784878+48794879+ [RFC6749] Hardt, D., Ed., "The OAuth 2.0 Authorization Framework",
48804880+ RFC 6749, DOI 10.17487/RFC6749, October 2012,
48814881+ <https://www.rfc-editor.org/info/rfc6749>.
48824882+48834883+ [RFC6764] Daboo, C., "Locating Services for Calendaring Extensions
48844884+ to WebDAV (CalDAV) and vCard Extensions to WebDAV
48854885+ (CardDAV)", RFC 6764, DOI 10.17487/RFC6764, February 2013,
48864886+ <https://www.rfc-editor.org/info/rfc6764>.
48874887+48884888+ [RFC6838] Freed, N., Klensin, J., and T. Hansen, "Media Type
48894889+ Specifications and Registration Procedures", BCP 13,
48904890+ RFC 6838, DOI 10.17487/RFC6838, January 2013,
48914891+ <https://www.rfc-editor.org/info/rfc6838>.
48924892+48934893+ [RFC6901] Bryan, P., Ed., Zyp, K., and M. Nottingham, Ed.,
48944894+ "JavaScript Object Notation (JSON) Pointer", RFC 6901,
48954895+ DOI 10.17487/RFC6901, April 2013,
48964896+ <https://www.rfc-editor.org/info/rfc6901>.
48974897+48984898+ [RFC7230] Fielding, R., Ed. and J. Reschke, Ed., "Hypertext Transfer
48994899+ Protocol (HTTP/1.1): Message Syntax and Routing",
49004900+ RFC 7230, DOI 10.17487/RFC7230, June 2014,
49014901+ <https://www.rfc-editor.org/info/rfc7230>.
49024902+49034903+ [RFC7231] Fielding, R., Ed. and J. Reschke, Ed., "Hypertext Transfer
49044904+ Protocol (HTTP/1.1): Semantics and Content", RFC 7231,
49054905+ DOI 10.17487/RFC7231, June 2014,
49064906+ <https://www.rfc-editor.org/info/rfc7231>.
49074907+49084908+ [RFC7493] Bray, T., Ed., "The I-JSON Message Format", RFC 7493,
49094909+ DOI 10.17487/RFC7493, March 2015,
49104910+ <https://www.rfc-editor.org/info/rfc7493>.
49114911+49124912+ [RFC7525] Sheffer, Y., Holz, R., and P. Saint-Andre,
49134913+ "Recommendations for Secure Use of Transport Layer
49144914+ Security (TLS) and Datagram Transport Layer Security
49154915+ (DTLS)", BCP 195, RFC 7525, DOI 10.17487/RFC7525, May
49164916+ 2015, <https://www.rfc-editor.org/info/rfc7525>.
49174917+49184918+ [RFC7617] Reschke, J., "The 'Basic' HTTP Authentication Scheme",
49194919+ RFC 7617, DOI 10.17487/RFC7617, September 2015,
49204920+ <https://www.rfc-editor.org/info/rfc7617>.
49214921+49224922+ [RFC7807] Nottingham, M. and E. Wilde, "Problem Details for HTTP
49234923+ APIs", RFC 7807, DOI 10.17487/RFC7807, March 2016,
49244924+ <https://www.rfc-editor.org/info/rfc7807>.
49254925+49264926+49274927+49284928+49294929+49304930+Jenkins & Newman Standards Track [Page 88]
49314931+49324932+RFC 8620 JMAP July 2019
49334933+49344934+49354935+ [RFC8030] Thomson, M., Damaggio, E., and B. Raymor, Ed., "Generic
49364936+ Event Delivery Using HTTP Push", RFC 8030,
49374937+ DOI 10.17487/RFC8030, December 2016,
49384938+ <https://www.rfc-editor.org/info/rfc8030>.
49394939+49404940+ [RFC8126] Cotton, M., Leiba, B., and T. Narten, "Guidelines for
49414941+ Writing an IANA Considerations Section in RFCs", BCP 26,
49424942+ RFC 8126, DOI 10.17487/RFC8126, June 2017,
49434943+ <https://www.rfc-editor.org/info/rfc8126>.
49444944+49454945+ [RFC8174] Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC
49464946+ 2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174,
49474947+ May 2017, <https://www.rfc-editor.org/info/rfc8174>.
49484948+49494949+ [RFC8259] Bray, T., Ed., "The JavaScript Object Notation (JSON) Data
49504950+ Interchange Format", STD 90, RFC 8259,
49514951+ DOI 10.17487/RFC8259, December 2017,
49524952+ <https://www.rfc-editor.org/info/rfc8259>.
49534953+49544954+ [RFC8264] Saint-Andre, P. and M. Blanchet, "PRECIS Framework:
49554955+ Preparation, Enforcement, and Comparison of
49564956+ Internationalized Strings in Application Protocols",
49574957+ RFC 8264, DOI 10.17487/RFC8264, October 2017,
49584958+ <https://www.rfc-editor.org/info/rfc8264>.
49594959+49604960+ [RFC8291] Thomson, M., "Message Encryption for Web Push", RFC 8291,
49614961+ DOI 10.17487/RFC8291, November 2017,
49624962+ <https://www.rfc-editor.org/info/rfc8291>.
49634963+49644964+ [RFC8446] Rescorla, E., "The Transport Layer Security (TLS) Protocol
49654965+ Version 1.3", RFC 8446, DOI 10.17487/RFC8446, August 2018,
49664966+ <https://www.rfc-editor.org/info/rfc8446>.
49674967+49684968+ [RFC8615] Nottingham, M., "Well-Known Uniform Resource Identifiers
49694969+ (URIs)", RFC 8615, DOI 10.17487/RFC8615, May 2019,
49704970+ <https://www.rfc-editor.org/info/rfc8615>.
49714971+49724972+10.2. Informative References
49734973+49744974+ [RFC8246] McManus, P., "HTTP Immutable Responses", RFC 8246,
49754975+ DOI 10.17487/RFC8246, September 2017,
49764976+ <https://www.rfc-editor.org/info/rfc8246>.
49774977+49784978+49794979+49804980+49814981+49824982+49834983+49844984+49854985+49864986+Jenkins & Newman Standards Track [Page 89]
49874987+49884988+RFC 8620 JMAP July 2019
49894989+49904990+49914991+Authors' Addresses
49924992+49934993+ Neil Jenkins
49944994+ Fastmail
49954995+ PO Box 234, Collins St. West
49964996+ Melbourne, VIC 8007
49974997+ Australia
49984998+49994999+ Email: neilj@fastmailteam.com
50005000+ URI: https://www.fastmail.com
50015001+50025002+50035003+ Chris Newman
50045004+ Oracle
50055005+ 440 E. Huntington Dr., Suite 400
50065006+ Arcadia, CA 91006
50075007+ United States of America
50085008+50095009+ Email: chris.newman@oracle.com
50105010+50115011+50125012+50135013+50145014+50155015+50165016+50175017+50185018+50195019+50205020+50215021+50225022+50235023+50245024+50255025+50265026+50275027+50285028+50295029+50305030+50315031+50325032+50335033+50345034+50355035+50365036+50375037+50385038+50395039+50405040+50415041+50425042+Jenkins & Newman Standards Track [Page 90]
50435043+