···
7
+
Internet Engineering Task Force (IETF) N. Jenkins
8
+
Request for Comments: 8620 Fastmail
9
+
Category: Standards Track C. Newman
10
+
ISSN: 2070-1721 Oracle
14
+
The JSON Meta Application Protocol (JMAP)
18
+
This document specifies a protocol for clients to efficiently query,
19
+
fetch, and modify JSON-based data objects, with support for push
20
+
notification of changes and fast resynchronisation and for out-of-
21
+
band binary data upload/download.
25
+
This is an Internet Standards Track document.
27
+
This document is a product of the Internet Engineering Task Force
28
+
(IETF). It represents the consensus of the IETF community. It has
29
+
received public review and has been approved for publication by the
30
+
Internet Engineering Steering Group (IESG). Further information on
31
+
Internet Standards is available in Section 2 of RFC 7841.
33
+
Information about the current status of this document, any errata,
34
+
and how to provide feedback on it may be obtained at
35
+
https://www.rfc-editor.org/info/rfc8620.
39
+
Copyright (c) 2019 IETF Trust and the persons identified as the
40
+
document authors. All rights reserved.
42
+
This document is subject to BCP 78 and the IETF Trust's Legal
43
+
Provisions Relating to IETF Documents
44
+
(https://trustee.ietf.org/license-info) in effect on the date of
45
+
publication of this document. Please review these documents
46
+
carefully, as they describe your rights and restrictions with respect
47
+
to this document. Code Components extracted from this document must
48
+
include Simplified BSD License text as described in Section 4.e of
49
+
the Trust Legal Provisions and are provided without warranty as
50
+
described in the Simplified BSD License.
58
+
Jenkins & Newman Standards Track [Page 1]
60
+
RFC 8620 JMAP July 2019
65
+
1. Introduction . . . . . . . . . . . . . . . . . . . . . . . . 4
66
+
1.1. Notational Conventions . . . . . . . . . . . . . . . . . 4
67
+
1.2. The Id Data Type . . . . . . . . . . . . . . . . . . . . 6
68
+
1.3. The Int and UnsignedInt Data Types . . . . . . . . . . . 6
69
+
1.4. The Date and UTCDate Data Types . . . . . . . . . . . . . 7
70
+
1.5. JSON as the Data Encoding Format . . . . . . . . . . . . 7
71
+
1.6. Terminology . . . . . . . . . . . . . . . . . . . . . . . 7
72
+
1.6.1. User . . . . . . . . . . . . . . . . . . . . . . . . 7
73
+
1.6.2. Accounts . . . . . . . . . . . . . . . . . . . . . . 7
74
+
1.6.3. Data Types and Records . . . . . . . . . . . . . . . 8
75
+
1.7. The JMAP API Model . . . . . . . . . . . . . . . . . . . 8
76
+
1.8. Vendor-Specific Extensions . . . . . . . . . . . . . . . 9
77
+
2. The JMAP Session Resource . . . . . . . . . . . . . . . . . . 9
78
+
2.1. Example . . . . . . . . . . . . . . . . . . . . . . . . . 14
79
+
2.2. Service Autodiscovery . . . . . . . . . . . . . . . . . . 15
80
+
3. Structured Data Exchange . . . . . . . . . . . . . . . . . . 16
81
+
3.1. Making an API Request . . . . . . . . . . . . . . . . . . 16
82
+
3.2. The Invocation Data Type . . . . . . . . . . . . . . . . 16
83
+
3.3. The Request Object . . . . . . . . . . . . . . . . . . . 16
84
+
3.3.1. Example Request . . . . . . . . . . . . . . . . . . . 18
85
+
3.4. The Response Object . . . . . . . . . . . . . . . . . . . 18
86
+
3.4.1. Example Response . . . . . . . . . . . . . . . . . . 19
87
+
3.5. Omitting Arguments . . . . . . . . . . . . . . . . . . . 19
88
+
3.6. Errors . . . . . . . . . . . . . . . . . . . . . . . . . 19
89
+
3.6.1. Request-Level Errors . . . . . . . . . . . . . . . . 20
90
+
3.6.2. Method-Level Errors . . . . . . . . . . . . . . . . . 21
91
+
3.7. References to Previous Method Results . . . . . . . . . . 22
92
+
3.8. Localisation of User-Visible Strings . . . . . . . . . . 27
93
+
3.9. Security . . . . . . . . . . . . . . . . . . . . . . . . 28
94
+
3.10. Concurrency . . . . . . . . . . . . . . . . . . . . . . . 28
95
+
4. The Core/echo Method . . . . . . . . . . . . . . . . . . . . 28
96
+
4.1. Example . . . . . . . . . . . . . . . . . . . . . . . . . 28
97
+
5. Standard Methods and Naming Convention . . . . . . . . . . . 29
98
+
5.1. /get . . . . . . . . . . . . . . . . . . . . . . . . . . 29
99
+
5.2. /changes . . . . . . . . . . . . . . . . . . . . . . . . 30
100
+
5.3. /set . . . . . . . . . . . . . . . . . . . . . . . . . . 34
101
+
5.4. /copy . . . . . . . . . . . . . . . . . . . . . . . . . . 40
102
+
5.5. /query . . . . . . . . . . . . . . . . . . . . . . . . . 42
103
+
5.6. /queryChanges . . . . . . . . . . . . . . . . . . . . . . 48
104
+
5.7. Examples . . . . . . . . . . . . . . . . . . . . . . . . 51
105
+
5.8. Proxy Considerations . . . . . . . . . . . . . . . . . . 58
106
+
6. Binary Data . . . . . . . . . . . . . . . . . . . . . . . . . 58
107
+
6.1. Uploading Binary Data . . . . . . . . . . . . . . . . . . 59
108
+
6.2. Downloading Binary Data . . . . . . . . . . . . . . . . . 60
109
+
6.3. Blob/copy . . . . . . . . . . . . . . . . . . . . . . . . 61
114
+
Jenkins & Newman Standards Track [Page 2]
116
+
RFC 8620 JMAP July 2019
119
+
7. Push . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62
120
+
7.1. The StateChange Object . . . . . . . . . . . . . . . . . 63
121
+
7.1.1. Example . . . . . . . . . . . . . . . . . . . . . . . 64
122
+
7.2. PushSubscription . . . . . . . . . . . . . . . . . . . . 64
123
+
7.2.1. PushSubscription/get . . . . . . . . . . . . . . . . 67
124
+
7.2.2. PushSubscription/set . . . . . . . . . . . . . . . . 68
125
+
7.2.3. Example . . . . . . . . . . . . . . . . . . . . . . . 69
126
+
7.3. Event Source . . . . . . . . . . . . . . . . . . . . . . 71
127
+
8. Security Considerations . . . . . . . . . . . . . . . . . . . 73
128
+
8.1. Transport Confidentiality . . . . . . . . . . . . . . . . 73
129
+
8.2. Authentication Scheme . . . . . . . . . . . . . . . . . . 73
130
+
8.3. Service Autodiscovery . . . . . . . . . . . . . . . . . . 73
131
+
8.4. JSON Parsing . . . . . . . . . . . . . . . . . . . . . . 74
132
+
8.5. Denial of Service . . . . . . . . . . . . . . . . . . . . 74
133
+
8.6. Connection to Unknown Push Server . . . . . . . . . . . . 74
134
+
8.7. Push Encryption . . . . . . . . . . . . . . . . . . . . . 75
135
+
8.8. Traffic Analysis . . . . . . . . . . . . . . . . . . . . 76
136
+
9. IANA Considerations . . . . . . . . . . . . . . . . . . . . . 76
137
+
9.1. Assignment of jmap Service Name . . . . . . . . . . . . . 76
138
+
9.2. Registration of Well-Known URI Suffix for JMAP . . . . . 76
139
+
9.3. Registration of the jmap URN Sub-namespace . . . . . . . 77
140
+
9.4. Creation of "JMAP Capabilities" Registry . . . . . . . . 77
141
+
9.4.1. Preliminary Community Review . . . . . . . . . . . . 77
142
+
9.4.2. Submit Request to IANA . . . . . . . . . . . . . . . 78
143
+
9.4.3. Designated Expert Review . . . . . . . . . . . . . . 78
144
+
9.4.4. Change Procedures . . . . . . . . . . . . . . . . . . 78
145
+
9.4.5. JMAP Capabilities Registry Template . . . . . . . . . 79
146
+
9.4.6. Initial Registration for JMAP Core . . . . . . . . . 79
147
+
9.4.7. Registration for JMAP Error Placeholder in JMAP
148
+
Capabilities Registry . . . . . . . . . . . . . . . . 80
149
+
9.5. Creation of "JMAP Error Codes" Registry . . . . . . . . . 80
150
+
9.5.1. Expert Review . . . . . . . . . . . . . . . . . . . . 80
151
+
9.5.2. JMAP Error Codes Registry Template . . . . . . . . . 81
152
+
9.5.3. Initial Contents for the JMAP Error Codes Registry . 81
153
+
10. References . . . . . . . . . . . . . . . . . . . . . . . . . 86
154
+
10.1. Normative References . . . . . . . . . . . . . . . . . . 86
155
+
10.2. Informative References . . . . . . . . . . . . . . . . . 89
156
+
Authors' Addresses . . . . . . . . . . . . . . . . . . . . . . . 90
170
+
Jenkins & Newman Standards Track [Page 3]
172
+
RFC 8620 JMAP July 2019
177
+
The JSON Meta Application Protocol (JMAP) is used for synchronising
178
+
data, such as mail, calendars, or contacts, between a client and a
179
+
server. It is optimised for mobile and web environments and aims to
180
+
provide a consistent interface to different data types.
182
+
This specification is for the generic mechanism of data
183
+
synchronisation. Further specifications define the data models for
184
+
different data types that may be synchronised via JMAP.
186
+
JMAP is designed to make efficient use of limited network resources.
187
+
Multiple API calls may be batched in a single request to the server,
188
+
reducing round trips and improving battery life on mobile devices.
189
+
Push connections remove the need for polling, and an efficient delta
190
+
update mechanism ensures a minimum amount of data is transferred.
192
+
JMAP is designed to be horizontally scalable to a very large number
193
+
of users. This is facilitated by separate endpoints for users after
194
+
login, the separation of binary and structured data, and a data model
195
+
for sharing that does not allow data dependencies between accounts.
197
+
1.1. Notational Conventions
199
+
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
200
+
"SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and
201
+
"OPTIONAL" in this document are to be interpreted as described in
202
+
BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all
203
+
capitals, as shown here.
205
+
The underlying format used for this specification is JSON.
206
+
Consequently, the terms "object" and "array" as well as the four
207
+
primitive types (strings, numbers, booleans, and null) are to be
208
+
interpreted as described in Section 1 of [RFC8259]. Unless otherwise
209
+
noted, all the property names and values are case sensitive.
211
+
Some examples in this document contain "partial" JSON documents used
212
+
for illustrative purposes. In these examples, three periods "..."
213
+
are used to indicate a portion of the document that has been removed
216
+
For compatibility with publishing requirements, line breaks have been
217
+
inserted inside long JSON strings, with the following continuation
218
+
lines indented. To form the valid JSON example, any line breaks
219
+
inside a string must be replaced with a space and any other white
220
+
space after the line break removed.
226
+
Jenkins & Newman Standards Track [Page 4]
228
+
RFC 8620 JMAP July 2019
231
+
Unless otherwise specified, examples of API exchanges only show the
232
+
methodCalls array of the Request object or the methodResponses array
233
+
of the Response object. For compactness, the rest of the Request/
234
+
Response object is omitted.
236
+
Type signatures are given for all JSON values in this document. The
237
+
following conventions are used:
239
+
o "*" - The type is undefined (the value could be any type, although
240
+
permitted values may be constrained by the context of this value).
242
+
o "String" - The JSON string type.
244
+
o "Number" - The JSON number type.
246
+
o "Boolean" - The JSON boolean type.
248
+
o "A[B]" - A JSON object where the keys are all of type "A", and the
249
+
values are all of type "B".
251
+
o "A[]" - An array of values of type "A".
253
+
o "A|B" - The value is either of type "A" or of type "B".
255
+
Other types may also be given, with their representation defined
256
+
elsewhere in this document.
258
+
Object properties may also have a set of attributes defined along
259
+
with the type signature. These have the following meanings:
261
+
o "server-set" -- Only the server can set the value for this
262
+
property. The client MUST NOT send this property when creating a
263
+
new object of this type.
265
+
o "immutable" -- The value MUST NOT change after the object is
268
+
o "default" -- (This is followed by a JSON value). The value that
269
+
will be used for this property if it is omitted in an argument or
270
+
when creating a new object of this type.
282
+
Jenkins & Newman Standards Track [Page 5]
284
+
RFC 8620 JMAP July 2019
287
+
1.2. The Id Data Type
289
+
All record ids are assigned by the server and are immutable.
291
+
Where "Id" is given as a data type, it means a "String" of at least 1
292
+
and a maximum of 255 octets in size, and it MUST only contain
293
+
characters from the "URL and Filename Safe" base64 alphabet, as
294
+
defined in Section 5 of [RFC4648], excluding the pad character ("=").
295
+
This means the allowed characters are the ASCII alphanumeric
296
+
characters ("A-Za-z0-9"), hyphen ("-"), and underscore ("_").
298
+
These characters are safe to use in almost any context (e.g.,
299
+
filesystems, URIs, and IMAP atoms). For maximum safety, servers
300
+
SHOULD also follow defensive allocation strategies to avoid creating
301
+
risks where glob completion or data type detection may be present
302
+
(e.g., on filesystems or in spreadsheets). In particular, it is wise
305
+
o Ids starting with a dash
307
+
o Ids starting with digits
309
+
o Ids that contain only digits
311
+
o Ids that differ only by ASCII case (for example, A vs. a)
313
+
o the specific sequence of three characters "NIL" (because this
314
+
sequence can be confused with the IMAP protocol expression of the
317
+
A good solution to these issues is to prefix every id with a single
318
+
alphabetical character.
320
+
1.3. The Int and UnsignedInt Data Types
322
+
Where "Int" is given as a data type, it means an integer in the range
323
+
-2^53+1 <= value <= 2^53-1, the safe range for integers stored in a
324
+
floating-point double, represented as a JSON "Number".
326
+
Where "UnsignedInt" is given as a data type, it means an "Int" where
327
+
the value MUST be in the range 0 <= value <= 2^53-1.
338
+
Jenkins & Newman Standards Track [Page 6]
340
+
RFC 8620 JMAP July 2019
343
+
1.4. The Date and UTCDate Data Types
345
+
Where "Date" is given as a type, it means a string in "date-time"
346
+
format [RFC3339]. To ensure a normalised form, the "time-secfrac"
347
+
MUST always be omitted if zero, and any letters in the string (e.g.,
348
+
"T" and "Z") MUST be uppercase. For example,
349
+
"2014-10-30T14:12:00+08:00".
351
+
Where "UTCDate" is given as a type, it means a "Date" where the
352
+
"time-offset" component MUST be "Z" (i.e., it must be in UTC time).
353
+
For example, "2014-10-30T06:12:00Z".
355
+
1.5. JSON as the Data Encoding Format
357
+
JSON is a text-based data interchange format as specified in
358
+
[RFC8259]. The Internet JSON (I-JSON) format defined in [RFC7493] is
359
+
a strict subset of this, adding restrictions to avoid potentially
360
+
confusing scenarios (for example, it mandates that an object MUST NOT
361
+
have two members with the same name).
363
+
All data sent from the client to the server or from the server to the
364
+
client (except binary file upload/download) MUST be valid I-JSON
365
+
according to the RFC and is therefore case sensitive and encoded in
372
+
A user is a person accessing data via JMAP. A user has a set of
373
+
permissions determining the data that they can see.
377
+
An account is a collection of data. A single account may contain an
378
+
arbitrary set of data types, for example, a collection of mail,
379
+
contacts, and calendars. Most JMAP methods take a mandatory
380
+
"accountId" argument that specifies on which account the operations
383
+
An account is not the same as a user, although it is common for a
384
+
primary account to directly belong to the user. For example, you may
385
+
have an account that contains data for a group or business, to which
386
+
multiple users have access.
394
+
Jenkins & Newman Standards Track [Page 7]
396
+
RFC 8620 JMAP July 2019
399
+
A single set of credentials may provide access to multiple accounts,
400
+
for example, if another user is sharing their work calendar with the
401
+
authenticated user or if there is a group mailbox for a support-desk
404
+
In the event of a severe internal error, a server may have to
405
+
reallocate ids or do something else that violates standard JMAP data
406
+
constraints for an account. In this situation, the data on the
407
+
server is no longer compatible with cached data the client may have
408
+
from before. The server MUST treat this as though the account has
409
+
been deleted and then recreated with a new account id. Clients will
410
+
then be forced to throw away any data with the old account id and
411
+
refetch all data from scratch.
413
+
1.6.3. Data Types and Records
415
+
JMAP provides a uniform interface for creating, retrieving, updating,
416
+
and deleting various types of objects. A "data type" is a collection
417
+
of named, typed properties, just like the schema for a database
418
+
table. Each instance of a data type is called a "record".
420
+
The id of a record is immutable and assigned by the server. The id
421
+
MUST be unique among all records of the *same type* within the *same
422
+
account*. Ids may clash across accounts or for two records of
423
+
different types within the same account.
425
+
1.7. The JMAP API Model
427
+
JMAP uses HTTP [RFC7230] to expose API, push, upload, and download
428
+
resources. All HTTP requests MUST use the "https://" scheme (HTTP
429
+
over TLS [RFC2818]). All HTTP requests MUST be authenticated.
431
+
An authenticated client can fetch the user's Session object with
432
+
details about the data and capabilities the server can provide as
433
+
shown in Section 2. The client may then exchange data with the
434
+
server in the following ways:
436
+
1. The client may make an API request to the server to get or set
437
+
structured data. This request consists of an ordered series of
438
+
method calls. These are processed by the server, which then
439
+
returns an ordered series of responses. This is described in
440
+
Sections 3, 4, and 5.
442
+
2. The client may download or upload binary files from/to the
443
+
server. This is detailed in Section 6.
445
+
3. The client may connect to a push channel on the server, to be
446
+
notified when data has changed. This is explained in Section 7.
450
+
Jenkins & Newman Standards Track [Page 8]
452
+
RFC 8620 JMAP July 2019
455
+
1.8. Vendor-Specific Extensions
457
+
Individual services will have custom features they wish to expose
458
+
over JMAP. This may take the form of extra data types and/or methods
459
+
not in the spec, extra arguments to JMAP methods, or extra properties
460
+
on existing data types (which may also appear in arguments to methods
461
+
that take property names).
463
+
The server can advertise custom extensions it supports by including
464
+
the identifiers in the capabilities object. Identifiers for vendor
465
+
extensions MUST be a URL belonging to a domain owned by the vendor,
466
+
to avoid conflict. The URL SHOULD resolve to documentation for the
467
+
changes the extension makes.
469
+
The client MUST opt in to use an extension by passing the appropriate
470
+
capability identifier in the "using" array of the Request object, as
471
+
described in Section 3.3. The server MUST only follow the
472
+
specifications that are opted into and behave as though it does not
473
+
implement anything else when processing a request. This is to ensure
474
+
compatibility with clients that don't know about a specific custom
475
+
extension and for compatibility with future versions of JMAP.
477
+
2. The JMAP Session Resource
479
+
You need two things to connect to a JMAP server:
481
+
1. The URL for the JMAP Session resource. This may be requested
482
+
directly from the user or discovered automatically based on a
483
+
username domain (see Section 2.2 below).
485
+
2. Credentials to authenticate with. How to obtain credentials is
486
+
out of scope for this document.
488
+
A successful authenticated GET request to the JMAP Session resource
489
+
MUST return a JSON-encoded *Session* object, giving details about the
490
+
data and capabilities the server can provide to the client given
491
+
those credentials. It has the following properties:
493
+
o capabilities: "String[Object]"
495
+
An object specifying the capabilities of this server. Each key is
496
+
a URI for a capability supported by the server. The value for
497
+
each of these keys is an object with further information about the
498
+
server's capabilities in relation to that capability.
500
+
The client MUST ignore any properties it does not understand.
506
+
Jenkins & Newman Standards Track [Page 9]
508
+
RFC 8620 JMAP July 2019
511
+
The capabilities object MUST include a property called
512
+
"urn:ietf:params:jmap:core". The value of this property is an
513
+
object that MUST contain the following information on server
514
+
capabilities (suggested minimum values for limits are supplied
515
+
that allow clients to make efficient use of the network):
517
+
* maxSizeUpload: "UnsignedInt"
519
+
The maximum file size, in octets, that the server will accept
520
+
for a single file upload (for any purpose). Suggested minimum:
523
+
* maxConcurrentUpload: "UnsignedInt"
525
+
The maximum number of concurrent requests the server will
526
+
accept to the upload endpoint. Suggested minimum: 4.
528
+
* maxSizeRequest: "UnsignedInt"
530
+
The maximum size, in octets, that the server will accept for a
531
+
single request to the API endpoint. Suggested minimum:
534
+
* maxConcurrentRequests: "UnsignedInt"
536
+
The maximum number of concurrent requests the server will
537
+
accept to the API endpoint. Suggested minimum: 4.
539
+
* maxCallsInRequest: "UnsignedInt"
541
+
The maximum number of method calls the server will accept in a
542
+
single request to the API endpoint. Suggested minimum: 16.
544
+
* maxObjectsInGet: "UnsignedInt"
546
+
The maximum number of objects that the client may request in a
547
+
single /get type method call. Suggested minimum: 500.
549
+
* maxObjectsInSet: "UnsignedInt"
551
+
The maximum number of objects the client may send to create,
552
+
update, or destroy in a single /set type method call. This is
553
+
the combined total, e.g., if the maximum is 10, you could not
554
+
create 7 objects and destroy 6, as this would be 13 actions,
555
+
which exceeds the limit. Suggested minimum: 500.
562
+
Jenkins & Newman Standards Track [Page 10]
564
+
RFC 8620 JMAP July 2019
567
+
* collationAlgorithms: "String[]"
569
+
A list of identifiers for algorithms registered in the
570
+
collation registry, as defined in [RFC4790], that the server
571
+
supports for sorting when querying records.
573
+
Specifications for future capabilities will define their own
574
+
properties on the capabilities object.
576
+
Servers MAY advertise vendor-specific JMAP extensions, as
577
+
described in Section 1.8. To avoid conflict, an identifier for a
578
+
vendor-specific extension MUST be a URL with a domain owned by the
579
+
vendor. Clients MUST opt in to any capability it wishes to use
582
+
o accounts: "Id[Account]"
584
+
A map of an account id to an Account object for each account (see
585
+
Section 1.6.2) the user has access to. An *Account* object has
586
+
the following properties:
590
+
A user-friendly string to show when presenting content from
591
+
this account, e.g., the email address representing the owner of
594
+
* isPersonal: "Boolean"
596
+
This is true if the account belongs to the authenticated user
597
+
rather than a group account or a personal account of another
598
+
user that has been shared with them.
600
+
* isReadOnly: "Boolean"
602
+
This is true if the entire account is read-only.
604
+
* accountCapabilities: "String[Object]"
606
+
The set of capability URIs for the methods supported in this
607
+
account. Each key is a URI for a capability that has methods
608
+
you can use with this account. The value for each of these
609
+
keys is an object with further information about the account's
610
+
permissions and restrictions with respect to this capability,
611
+
as defined in the capability's specification.
613
+
The client MUST ignore any properties it does not understand.
618
+
Jenkins & Newman Standards Track [Page 11]
620
+
RFC 8620 JMAP July 2019
623
+
The server advertises the full list of capabilities it supports
624
+
in the capabilities object, as defined above. If the
625
+
capability defines new methods, the server MUST include it in
626
+
the accountCapabilities object if the user may use those
627
+
methods with this account. It MUST NOT include it in the
628
+
accountCapabilities object if the user cannot use those methods
631
+
For example, you may have access to your own account with mail,
632
+
calendars, and contacts data and also a shared account that
633
+
only has contacts data (a business address book, for example).
634
+
In this case, the accountCapabilities property on the first
635
+
account would include something like
636
+
"urn:ietf:params:jmap:mail", "urn:ietf:params:jmap:calendars",
637
+
and "urn:ietf:params:jmap:contacts", while the second account
638
+
would just have the last of these.
640
+
Attempts to use the methods defined in a capability with one of
641
+
the accounts that does not support that capability are rejected
642
+
with an "accountNotSupportedByMethod" error (see "Method-Level
643
+
Errors", Section 3.6.2).
645
+
o primaryAccounts: "String[Id]"
647
+
A map of capability URIs (as found in accountCapabilities) to the
648
+
account id that is considered to be the user's main or default
649
+
account for data pertaining to that capability. If no account
650
+
being returned belongs to the user, or in any other way there is
651
+
no appropriate way to determine a default account, there MAY be no
652
+
entry for a particular URI, even though that capability is
653
+
supported by the server (and in the capabilities object).
654
+
"urn:ietf:params:jmap:core" SHOULD NOT be present.
656
+
o username: "String"
658
+
The username associated with the given credentials, or the empty
663
+
The URL to use for JMAP API requests.
674
+
Jenkins & Newman Standards Track [Page 12]
676
+
RFC 8620 JMAP July 2019
679
+
o downloadUrl: "String"
681
+
The URL endpoint to use when downloading files, in URI Template
682
+
(level 1) format [RFC6570]. The URL MUST contain variables called
683
+
"accountId", "blobId", "type", and "name". The use of these
684
+
variables is described in Section 6.2. Due to potential encoding
685
+
issues with slashes in content types, it is RECOMMENDED to put the
686
+
"type" variable in the query section of the URL.
688
+
o uploadUrl: "String"
690
+
The URL endpoint to use when uploading files, in URI Template
691
+
(level 1) format [RFC6570]. The URL MUST contain a variable
692
+
called "accountId". The use of this variable is described in
695
+
o eventSourceUrl: "String"
697
+
The URL to connect to for push events, as described in
698
+
Section 7.3, in URI Template (level 1) format [RFC6570]. The URL
699
+
MUST contain variables called "types", "closeafter", and "ping".
700
+
The use of these variables is described in Section 7.3.
704
+
A (preferably short) string representing the state of this object
705
+
on the server. If the value of any other property on the Session
706
+
object changes, this string will change. The current value is
707
+
also returned on the API Response object (see Section 3.4),
708
+
allowing clients to quickly determine if the session information
709
+
has changed (e.g., an account has been added or removed), so they
710
+
need to refetch the object.
712
+
To ensure future compatibility, other properties MAY be included on
713
+
the Session object. Clients MUST ignore any properties they are not
716
+
Implementors must take care to avoid inappropriate caching of the
717
+
Session object at the HTTP layer. Since the client should only
718
+
refetch when it detects there is a change (via the sessionState
719
+
property of an API response), it is RECOMMENDED to disable HTTP
720
+
caching altogether, for example, by setting "Cache-Control: no-cache,
721
+
no-store, must-revalidate" on the response.
730
+
Jenkins & Newman Standards Track [Page 13]
732
+
RFC 8620 JMAP July 2019
737
+
In the following example Session object, the user has access to their
738
+
own mail and contacts via JMAP, as well as read-only access to shared
739
+
mail from another user. The server is advertising a custom
740
+
"https://example.com/apis/foobar" capability.
744
+
"urn:ietf:params:jmap:core": {
745
+
"maxSizeUpload": 50000000,
746
+
"maxConcurrentUpload": 8,
747
+
"maxSizeRequest": 10000000,
748
+
"maxConcurrentRequest": 8,
749
+
"maxCallsInRequest": 32,
750
+
"maxObjectsInGet": 256,
751
+
"maxObjectsInSet": 128,
752
+
"collationAlgorithms": [
755
+
"i;unicode-casemap"
758
+
"urn:ietf:params:jmap:mail": {}
759
+
"urn:ietf:params:jmap:contacts": {},
760
+
"https://example.com/apis/foobar": {
761
+
"maxFoosFinangled": 42
766
+
"name": "john@example.com",
767
+
"isPersonal": true,
768
+
"isReadOnly": false,
769
+
"accountCapabilities": {
770
+
"urn:ietf:params:jmap:mail": {
771
+
"maxMailboxesPerEmail": null,
772
+
"maxMailboxDepth": 10,
775
+
"urn:ietf:params:jmap:contacts": {
786
+
Jenkins & Newman Standards Track [Page 14]
788
+
RFC 8620 JMAP July 2019
792
+
"name": "jane@example.com",
793
+
"isPersonal": false,
794
+
"isReadOnly": true,
795
+
"accountCapabilities": {
796
+
"urn:ietf:params:jmap:mail": {
797
+
"maxMailboxesPerEmail": 1,
798
+
"maxMailboxDepth": 10,
804
+
"primaryAccounts": {
805
+
"urn:ietf:params:jmap:mail": "A13824",
806
+
"urn:ietf:params:jmap:contacts": "A13824"
808
+
"username": "john@example.com",
809
+
"apiUrl": "https://jmap.example.com/api/",
810
+
"downloadUrl": "https://jmap.example.com
811
+
/download/{accountId}/{blobId}/{name}?accept={type}",
812
+
"uploadUrl": "https://jmap.example.com/upload/{accountId}/",
813
+
"eventSourceUrl": "https://jmap.example.com
814
+
/eventsource/?types={types}&closeafter={closeafter}&ping={ping}",
815
+
"state": "75128aab4b1b"
818
+
2.2. Service Autodiscovery
820
+
There are two standardised autodiscovery methods in use for Internet
823
+
o DNS SRV (see [RFC2782], [RFC6186], and [RFC6764])
825
+
o .well-known/servicename (see [RFC8615])
827
+
A JMAP-supporting host for the domain "example.com" SHOULD publish a
828
+
SRV record "_jmap._tcp.example.com" that gives a hostname and port
829
+
(usually port "443"). The JMAP Session resource is then
830
+
"https://${hostname}[:${port}]/.well-known/jmap" (following any
833
+
If the client has a username in the form of an email address, it MAY
834
+
use the domain portion of this to attempt autodiscovery of the JMAP
842
+
Jenkins & Newman Standards Track [Page 15]
844
+
RFC 8620 JMAP July 2019
847
+
3. Structured Data Exchange
849
+
The client may make an API request to the server to get or set
850
+
structured data. This request consists of an ordered series of
851
+
method calls. These are processed by the server, which then returns
852
+
an ordered series of responses.
854
+
3.1. Making an API Request
856
+
To make an API request, the client makes an authenticated POST
857
+
request to the API resource, which is defined by the "apiUrl"
858
+
property in the Session object (see Section 2).
860
+
The request MUST be of type "application/json" and consist of a
861
+
single JSON-encoded "Request" object, as defined in Section 3.3. If
862
+
successful, the response MUST also be of type "application/json" and
863
+
consist of a single "Response" object, as defined in Section 3.4.
865
+
3.2. The Invocation Data Type
867
+
Method calls and responses are represented by the *Invocation* data
868
+
type. This is a tuple, represented as a JSON array containing three
871
+
1. A "String" *name* of the method to call or of the response.
873
+
2. A "String[*]" object containing named *arguments* for that method
876
+
3. A "String" *method call id*: an arbitrary string from the client
877
+
to be echoed back with the responses emitted by that method call
878
+
(a method may return 1 or more responses, as it may make implicit
879
+
calls to other methods; all responses initiated by this method
880
+
call get the same method call id in the response).
882
+
3.3. The Request Object
884
+
A *Request* object has the following properties:
886
+
o using: "String[]"
888
+
The set of capabilities the client wishes to use. The client MAY
889
+
include capability identifiers even if the method calls it makes
890
+
do not utilise those capabilities. The server advertises the set
891
+
of specifications it supports in the Session object (see
892
+
Section 2), as keys on the "capabilities" property.
898
+
Jenkins & Newman Standards Track [Page 16]
900
+
RFC 8620 JMAP July 2019
903
+
o methodCalls: "Invocation[]"
905
+
An array of method calls to process on the server. The method
906
+
calls MUST be processed sequentially, in order.
908
+
o createdIds: "Id[Id]" (optional)
910
+
A map of a (client-specified) creation id to the id the server
911
+
assigned when a record was successfully created.
913
+
As described later in this specification, some records may have a
914
+
property that contains the id of another record. To allow more
915
+
efficient network usage, you can set this property to reference a
916
+
record created earlier in the same API request. Since the real id
917
+
is unknown when the request is created, the client can instead
918
+
specify the creation id it assigned, prefixed with a "#" (see
919
+
Section 5.3 for more details).
921
+
As the server processes API requests, any time it successfully
922
+
creates a new record, it adds the creation id to this map (see the
923
+
"create" argument to /set in Section 5.3), with the server-
924
+
assigned real id as the value. If it comes across a reference to
925
+
a creation id in a create/update, it looks it up in the map and
926
+
replaces the reference with the real id, if found.
928
+
The client can pass an initial value for this map as the
929
+
"createdIds" property of the Request object. This may be an empty
930
+
object. If given in the request, the response will also include a
931
+
createdIds property. This allows proxy servers to easily split a
932
+
JMAP request into multiple JMAP requests to send to different
933
+
servers. For example, it could send the first two method calls to
934
+
server A, then the third to server B, before sending the fourth to
935
+
server A again. By passing the createdIds of the previous
936
+
response to the next request, it can ensure all of these still
937
+
resolve. See Section 5.8 for further discussion of proxy
940
+
Future specifications MAY add further properties to the Request
941
+
object to extend the semantics. To ensure forwards compatibility, a
942
+
server MUST ignore any other properties it does not understand on the
943
+
JMAP Request object.
954
+
Jenkins & Newman Standards Track [Page 17]
956
+
RFC 8620 JMAP July 2019
959
+
3.3.1. Example Request
962
+
"using": [ "urn:ietf:params:jmap:core", "urn:ietf:params:jmap:mail" ],
965
+
"arg1": "arg1data",
971
+
[ "method3", {}, "c3" ]
975
+
3.4. The Response Object
977
+
A *Response* object has the following properties:
979
+
o methodResponses: "Invocation[]"
981
+
An array of responses, in the same format as the "methodCalls" on
982
+
the Request object. The output of the methods MUST be added to
983
+
the "methodResponses" array in the same order that the methods are
986
+
o createdIds: "Id[Id]" (optional; only returned if given in the
989
+
A map of a (client-specified) creation id to the id the server
990
+
assigned when a record was successfully created. This MUST
991
+
include all creation ids passed in the original createdIds
992
+
parameter of the Request object, as well as any additional ones
993
+
added for newly created records.
995
+
o sessionState: "String"
997
+
The current value of the "state" string on the Session object, as
998
+
described in Section 2. Clients may use this to detect if this
999
+
object has changed and needs to be refetched.
1001
+
Unless otherwise specified, if the method call completed
1002
+
successfully, its response name is the same as the method name in the
1010
+
Jenkins & Newman Standards Track [Page 18]
1012
+
RFC 8620 JMAP July 2019
1015
+
3.4.1. Example Response
1018
+
"methodResponses": [
1026
+
[ "anotherResponseFromMethod2", {
1028
+
"yetmoredata": "Hello"
1031
+
"type":"unknownMethod"
1034
+
"sessionState": "75128aab4b1b"
1037
+
3.5. Omitting Arguments
1039
+
An argument to a method may be specified to have a default value. If
1040
+
omitted by the client, the server MUST treat the method call the same
1041
+
as if the default value had been specified. Similarly, the server
1042
+
MAY omit any argument in a response that has the default value.
1044
+
Unless otherwise specified in a method description, null is the
1045
+
default value for any argument in a request or response where this is
1046
+
allowed by the type signature. Other arguments may only be omitted
1047
+
if an explicit default value is defined in the method description.
1051
+
There are three different levels of granularity at which an error may
1052
+
be returned in JMAP.
1054
+
When an API request is made, the request as a whole may be rejected
1055
+
due to rate limiting, malformed JSON, request for an unknown
1056
+
capability, etc. In this case, the entire request is rejected with
1057
+
an appropriate HTTP error response code and an additional JSON body
1058
+
with more detail for the client.
1060
+
Provided the request itself is syntactically valid (the JSON is valid
1061
+
and when decoded, it matches the type signature of a Request object),
1062
+
the methods within it are executed sequentially by the server. Each
1066
+
Jenkins & Newman Standards Track [Page 19]
1068
+
RFC 8620 JMAP July 2019
1071
+
method may individually fail, for example, if invalid arguments are
1072
+
given or an unknown method name is called.
1074
+
Finally, methods that make changes to the server state often act upon
1075
+
a number of different records within a single call. Each record
1076
+
change may be separately rejected with a SetError, as described in
1079
+
3.6.1. Request-Level Errors
1081
+
When an HTTP error response is returned to the client, the server
1082
+
SHOULD return a JSON "problem details" object as the response body,
1085
+
The following problem types are defined:
1087
+
o "urn:ietf:params:jmap:error:unknownCapability"
1088
+
The client included a capability in the "using" property of the
1089
+
request that the server does not support.
1091
+
o "urn:ietf:params:jmap:error:notJSON"
1092
+
The content type of the request was not "application/json" or the
1093
+
request did not parse as I-JSON.
1095
+
o "urn:ietf:params:jmap:error:notRequest"
1096
+
The request parsed as JSON but did not match the type signature of
1097
+
the Request object.
1099
+
o "urn:ietf:params:jmap:error:limit"
1100
+
The request was not processed as it would have exceeded one of the
1101
+
request limits defined on the capability object, such as
1102
+
maxSizeRequest, maxCallsInRequest, or maxConcurrentRequests. A
1103
+
"limit" property MUST also be present on the "problem details"
1104
+
object, containing the name of the limit being applied.
1109
+
"type": "urn:ietf:params:jmap:error:unknownCapability",
1111
+
"detail": "The Request object used capability
1112
+
'https://example.com/apis/foobar', which is not supported
1122
+
Jenkins & Newman Standards Track [Page 20]
1124
+
RFC 8620 JMAP July 2019
1130
+
"type": "urn:ietf:params:jmap:error:limit",
1131
+
"limit": "maxSizeRequest",
1133
+
"detail": "The request is larger than the server is willing to
1137
+
3.6.2. Method-Level Errors
1139
+
If a method encounters an error, the appropriate "error" response
1140
+
MUST be inserted at the current point in the "methodResponses" array
1141
+
and, unless otherwise specified, further processing MUST NOT happen
1142
+
within that method call.
1144
+
Any further method calls in the request MUST then be processed as
1145
+
normal. Errors at the method level MUST NOT generate an HTTP-level
1148
+
An "error" response looks like this:
1151
+
"type": "unknownMethod"
1154
+
The response name is "error", and it MUST have a type property.
1155
+
Other properties may be present with further information; these are
1156
+
detailed in the error type descriptions where appropriate.
1158
+
With the exception of when the "serverPartialFail" error is returned,
1159
+
the externally visible state of the server MUST NOT have changed if
1160
+
an error is returned at the method level.
1162
+
The following error types are defined, which may be returned for any
1163
+
method call where appropriate:
1165
+
"serverUnavailable": Some internal server resource was temporarily
1166
+
unavailable. Attempting the same operation later (perhaps after a
1167
+
backoff with a random factor) may succeed.
1169
+
"serverFail": An unexpected or unknown error occurred during the
1170
+
processing of the call. A "description" property should provide more
1171
+
details about the error. The method call made no changes to the
1172
+
server's state. Attempting the same operation again is expected to
1173
+
fail again. Contacting the service administrator is likely necessary
1174
+
to resolve this problem if it is persistent.
1178
+
Jenkins & Newman Standards Track [Page 21]
1180
+
RFC 8620 JMAP July 2019
1183
+
"serverPartialFail": Some, but not all, expected changes described by
1184
+
the method occurred. The client MUST resynchronise impacted data to
1185
+
determine server state. Use of this error is strongly discouraged.
1187
+
"unknownMethod": The server does not recognise this method name.
1189
+
"invalidArguments": One of the arguments is of the wrong type or is
1190
+
otherwise invalid, or a required argument is missing. A
1191
+
"description" property MAY be present to help debug with an
1192
+
explanation of what the problem was. This is a non-localised string,
1193
+
and it is not intended to be shown directly to end users.
1195
+
"invalidResultReference": The method used a result reference for one
1196
+
of its arguments (see Section 3.7), but this failed to resolve.
1198
+
"forbidden": The method and arguments are valid, but executing the
1199
+
method would violate an Access Control List (ACL) or other
1200
+
permissions policy.
1202
+
"accountNotFound": The accountId does not correspond to a valid
1205
+
"accountNotSupportedByMethod": The accountId given corresponds to a
1206
+
valid account, but the account does not support this method or data
1209
+
"accountReadOnly": This method modifies state, but the account is
1210
+
read-only (as returned on the corresponding Account object in the
1211
+
JMAP Session resource).
1213
+
Further possible errors for a particular method are specified in the
1214
+
method descriptions.
1216
+
Further general errors MAY be defined in future RFCs. Should a
1217
+
client receive an error type it does not understand, it MUST treat it
1218
+
the same as the "serverFail" type.
1220
+
3.7. References to Previous Method Results
1222
+
To allow clients to make more efficient use of the network and avoid
1223
+
round trips, an argument to one method can be taken from the result
1224
+
of a previous method call in the same request.
1226
+
To do this, the client prefixes the argument name with "#" (an
1227
+
octothorpe). The value is a ResultReference object as described
1228
+
below. When processing a method call, the server MUST first check
1229
+
the arguments object for any names beginning with "#". If found, the
1230
+
result reference should be resolved and the value used as the "real"
1234
+
Jenkins & Newman Standards Track [Page 22]
1236
+
RFC 8620 JMAP July 2019
1239
+
argument. The method is then processed as normal. If any result
1240
+
reference fails to resolve, the whole method MUST be rejected with an
1241
+
"invalidResultReference" error. If an arguments object contains the
1242
+
same argument name in normal and referenced form (e.g., "foo" and
1243
+
"#foo"), the method MUST return an "invalidArguments" error.
1245
+
A *ResultReference* object has the following properties:
1247
+
o resultOf: "String"
1249
+
The method call id (see Section 3.2) of a previous method call in
1250
+
the current request.
1254
+
The required name of a response to that method call.
1258
+
A pointer into the arguments of the response selected via the name
1259
+
and resultOf properties. This is a JSON Pointer [RFC6901], except
1260
+
it also allows the use of "*" to map through an array (see the
1261
+
description below).
1265
+
1. Find the first response with a method call id identical to the
1266
+
"resultOf" property of the ResultReference in the
1267
+
"methodResponses" array from previously processed method calls in
1268
+
the same request. If none, evaluation fails.
1270
+
2. If the response name is not identical to the "name" property of
1271
+
the ResultReference, evaluation fails.
1273
+
3. Apply the "path" to the arguments object of the response (the
1274
+
second item in the response array) following the JSON Pointer
1275
+
algorithm [RFC6901], except with the following addition in
1276
+
"Evaluation" (see Section 4):
1278
+
If the currently referenced value is a JSON array, the reference
1279
+
token may be exactly the single character "*", making the new
1280
+
referenced value the result of applying the rest of the JSON
1281
+
Pointer tokens to every item in the array and returning the
1282
+
results in the same order in a new array. If the result of
1283
+
applying the rest of the pointer tokens to each item was itself
1284
+
an array, the contents of this array are added to the output
1285
+
rather than the array itself (i.e., the result is flattened from
1286
+
an array of arrays to a single array). If the result of applying
1290
+
Jenkins & Newman Standards Track [Page 23]
1292
+
RFC 8620 JMAP July 2019
1295
+
the rest of the pointer tokens to a value was itself an array,
1296
+
its items should be included individually in the output rather
1297
+
than including the array itself (i.e., the result is flattened
1298
+
from an array of arrays to a single array).
1300
+
As a simple example, suppose we have the following API request
1303
+
[[ "Foo/changes", {
1304
+
"accountId": "A1",
1305
+
"sinceState": "abcdef"
1308
+
"accountId": "A1",
1311
+
"name": "Foo/changes",
1312
+
"path": "/created"
1316
+
After executing the first method call, the "methodResponses" array
1319
+
[[ "Foo/changes", {
1320
+
"accountId": "A1",
1321
+
"oldState": "abcdef",
1322
+
"newState": "123456",
1323
+
"hasMoreChanges": false,
1324
+
"created": [ "f1", "f4" ],
1329
+
To execute the "Foo/get" call, we look through the arguments and find
1330
+
there is one with a "#" prefix. To resolve this, we apply the
1333
+
1. Find the first response with method call id "t0". The "Foo/
1334
+
changes" response fulfils this criterion.
1336
+
2. Check that the response name is the same as in the result
1337
+
reference. It is, so this is fine.
1339
+
3. Apply the "path" as a JSON Pointer to the arguments object. This
1340
+
simply selects the "created" property, so the result of
1341
+
evaluating is: [ "f1", "f4" ].
1346
+
Jenkins & Newman Standards Track [Page 24]
1348
+
RFC 8620 JMAP July 2019
1351
+
The JMAP server now continues to process the "Foo/get" call as though
1352
+
the arguments were:
1355
+
"accountId": "A1",
1356
+
"ids": [ "f1", "f4" ]
1359
+
Now, a more complicated example using the JMAP Mail data model: fetch
1360
+
the "from"/"date"/"subject" for every Email in the first 10 Threads
1361
+
in the inbox (sorted newest first):
1363
+
[[ "Email/query", {
1364
+
"accountId": "A1",
1365
+
"filter": { "inMailbox": "id_of_inbox" },
1366
+
"sort": [{ "property": "receivedAt", "isAscending": false }],
1367
+
"collapseThreads": true,
1370
+
"calculateTotal": true
1373
+
"accountId": "A1",
1376
+
"name": "Email/query",
1379
+
"properties": [ "threadId" ]
1382
+
"accountId": "A1",
1385
+
"name": "Email/get",
1386
+
"path": "/list/*/threadId"
1390
+
"accountId": "A1",
1393
+
"name": "Thread/get",
1394
+
"path": "/list/*/emailIds"
1396
+
"properties": [ "from", "receivedAt", "subject" ]
1402
+
Jenkins & Newman Standards Track [Page 25]
1404
+
RFC 8620 JMAP July 2019
1407
+
After executing the first 3 method calls, the "methodResponses" array
1410
+
[[ "Email/query", {
1411
+
"accountId": "A1",
1412
+
"queryState": "abcdefg",
1413
+
"canCalculateChanges": true,
1416
+
"ids": [ "msg1023", "msg223", "msg110", "msg93", "msg91",
1417
+
"msg38", "msg36", "msg33", "msg11", "msg1" ]
1420
+
"accountId": "A1",
1421
+
"state": "123456",
1424
+
"threadId": "trd194"
1427
+
"threadId": "trd114"
1434
+
"accountId": "A1",
1435
+
"state": "123456",
1438
+
"emailIds": [ "msg1020", "msg1021", "msg1023" ]
1441
+
"emailIds": [ "msg201", "msg223" ]
1448
+
To execute the final "Email/get" call, we look through the arguments
1449
+
and find there is one with a "#" prefix. To resolve this, we apply
1452
+
1. Find the first response with method call id "t2". The "Thread/
1453
+
get" response fulfils this criterion.
1458
+
Jenkins & Newman Standards Track [Page 26]
1460
+
RFC 8620 JMAP July 2019
1463
+
2. "Thread/get" is the name specified in the result reference, so
1466
+
3. Apply the "path" as a JSON Pointer to the arguments object.
1469
+
1. "list": get the array of thread objects
1471
+
2. "*": for each of the items in the array:
1473
+
a. "emailIds": get the array of Email ids
1475
+
b. Concatenate these into a single array of all the ids in
1478
+
The JMAP server now continues to process the "Email/get" call as
1479
+
though the arguments were:
1482
+
"accountId": "A1",
1483
+
"ids": [ "msg1020", "msg1021", "msg1023", "msg201", "msg223", ... ],
1484
+
"properties": [ "from", "receivedAt", "subject" ]
1487
+
The ResultReference performs a similar role to that of the creation
1488
+
id, in that it allows a chained method call to refer to information
1489
+
not available when the request is generated. However, they are
1490
+
different things and not interchangeable; the only commonality is the
1491
+
octothorpe used to indicate them.
1493
+
3.8. Localisation of User-Visible Strings
1495
+
If returning a custom string to be displayed to the user, for
1496
+
example, an error message, the server SHOULD use information from the
1497
+
Accept-Language header of the request (as defined in Section 5.3.5 of
1498
+
[RFC7231]) to choose the best available localisation. The Content-
1499
+
Language header of the response (see Section 3.1.3.2 of [RFC7231])
1500
+
SHOULD indicate the language being used for user-visible strings.
1502
+
For example, suppose a request was made with the following header:
1504
+
Accept-Language: fr-CH, fr;q=0.9, de;q=0.8, en;q=0.7, *;q=0.5
1506
+
and a method generated an error to display to the user. The server
1507
+
has translations of the error message in English and German. Looking
1508
+
at the Accept-Language header, the user's preferred language is
1509
+
French. Since we don't have a translation for this, we look at the
1514
+
Jenkins & Newman Standards Track [Page 27]
1516
+
RFC 8620 JMAP July 2019
1519
+
next most preferred, which is German. We have a German translation,
1520
+
so the server returns this and indicates the language chosen in a
1521
+
Content-Language header like so:
1523
+
Content-Language: de
1527
+
As always, the server must be strict about data received from the
1528
+
client. Arguments need to be checked for validity; a malicious user
1529
+
could attempt to find an exploit through the API. In case of invalid
1530
+
arguments (unknown/insufficient/wrong type for data, etc.), the
1531
+
method MUST return an "invalidArguments" error and terminate.
1535
+
Method calls within a single request MUST be executed in order.
1536
+
However, method calls from different concurrent API requests may be
1537
+
interleaved. This means that the data on the server may change
1538
+
between two method calls within a single API request.
1540
+
4. The Core/echo Method
1542
+
The "Core/echo" method returns exactly the same arguments as it is
1543
+
given. It is useful for testing if you have a valid authenticated
1544
+
connection to a JMAP API endpoint.
1570
+
Jenkins & Newman Standards Track [Page 28]
1572
+
RFC 8620 JMAP July 2019
1575
+
5. Standard Methods and Naming Convention
1577
+
JMAP provides a uniform interface for creating, retrieving, updating,
1578
+
and deleting objects of a particular type. For a "Foo" data type,
1579
+
records of that type would be fetched via a "Foo/get" call and
1580
+
modified via a "Foo/set" call. Delta updates may be fetched via a
1581
+
"Foo/changes" call. These methods all follow a standard format as
1584
+
Some types may not have all these methods. Specifications defining
1585
+
types MUST specify which methods are available for the type.
1589
+
Objects of type Foo are fetched via a call to "Foo/get".
1591
+
It takes the following arguments:
1595
+
The id of the account to use.
1597
+
o ids: "Id[]|null"
1599
+
The ids of the Foo objects to return. If null, then *all* records
1600
+
of the data type are returned, if this is supported for that data
1601
+
type and the number of records does not exceed the
1602
+
"maxObjectsInGet" limit.
1604
+
o properties: "String[]|null"
1606
+
If supplied, only the properties listed in the array are returned
1607
+
for each Foo object. If null, all properties of the object are
1608
+
returned. The id property of the object is *always* returned,
1609
+
even if not explicitly requested. If an invalid property is
1610
+
requested, the call MUST be rejected with an "invalidArguments"
1613
+
The response has the following arguments:
1617
+
The id of the account used for the call.
1626
+
Jenkins & Newman Standards Track [Page 29]
1628
+
RFC 8620 JMAP July 2019
1633
+
A (preferably short) string representing the state on the server
1634
+
for *all* the data of this type in the account (not just the
1635
+
objects returned in this call). If the data changes, this string
1636
+
MUST change. If the Foo data is unchanged, servers SHOULD return
1637
+
the same state string on subsequent requests for this data type.
1638
+
When a client receives a response with a different state string to
1639
+
a previous call, it MUST either throw away all currently cached
1640
+
objects for the type or call "Foo/changes" to get the exact
1645
+
An array of the Foo objects requested. This is the *empty array*
1646
+
if no objects were found or if the "ids" argument passed in was
1647
+
also an empty array. The results MAY be in a different order to
1648
+
the "ids" in the request arguments. If an identical id is
1649
+
included more than once in the request, the server MUST only
1650
+
include it once in either the "list" or the "notFound" argument of
1653
+
o notFound: "Id[]"
1655
+
This array contains the ids passed to the method for records that
1656
+
do not exist. The array is empty if all requested ids were found
1657
+
or if the "ids" argument passed in was either null or an empty
1660
+
The following additional error may be returned instead of the "Foo/
1663
+
"requestTooLarge": The number of ids requested by the client exceeds
1664
+
the maximum number the server is willing to process in a single
1669
+
When the state of the set of Foo records in an account changes on the
1670
+
server (whether due to creation, updates, or deletion), the "state"
1671
+
property of the "Foo/get" response will change. The "Foo/changes"
1672
+
method allows a client to efficiently update the state of its Foo
1673
+
cache to match the new state on the server. It takes the following
1678
+
The id of the account to use.
1682
+
Jenkins & Newman Standards Track [Page 30]
1684
+
RFC 8620 JMAP July 2019
1687
+
o sinceState: "String"
1689
+
The current state of the client. This is the string that was
1690
+
returned as the "state" argument in the "Foo/get" response. The
1691
+
server will return the changes that have occurred since this
1694
+
o maxChanges: "UnsignedInt|null"
1696
+
The maximum number of ids to return in the response. The server
1697
+
MAY choose to return fewer than this value but MUST NOT return
1698
+
more. If not given by the client, the server may choose how many
1699
+
to return. If supplied by the client, the value MUST be a
1700
+
positive integer greater than 0. If a value outside of this range
1701
+
is given, the server MUST reject the call with an
1702
+
"invalidArguments" error.
1704
+
The response has the following arguments:
1708
+
The id of the account used for the call.
1710
+
o oldState: "String"
1712
+
This is the "sinceState" argument echoed back; it's the state from
1713
+
which the server is returning changes.
1715
+
o newState: "String"
1717
+
This is the state the client will be in after applying the set of
1718
+
changes to the old state.
1720
+
o hasMoreChanges: "Boolean"
1722
+
If true, the client may call "Foo/changes" again with the
1723
+
"newState" returned to get further updates. If false, "newState"
1724
+
is the current server state.
1728
+
An array of ids for records that have been created since the old
1733
+
An array of ids for records that have been updated since the old
1738
+
Jenkins & Newman Standards Track [Page 31]
1740
+
RFC 8620 JMAP July 2019
1743
+
o destroyed: "Id[]"
1745
+
An array of ids for records that have been destroyed since the old
1748
+
If a record has been created AND updated since the old state, the
1749
+
server SHOULD just return the id in the "created" list but MAY return
1750
+
it in the "updated" list as well.
1752
+
If a record has been updated AND destroyed since the old state, the
1753
+
server SHOULD just return the id in the "destroyed" list but MAY
1754
+
return it in the "updated" list as well.
1756
+
If a record has been created AND destroyed since the old state, the
1757
+
server SHOULD remove the id from the response entirely. However, it
1758
+
MAY include it in just the "destroyed" list or in both the
1759
+
"destroyed" and "created" lists.
1761
+
If a "maxChanges" is supplied, or set automatically by the server,
1762
+
the server MUST ensure the number of ids returned across "created",
1763
+
"updated", and "destroyed" does not exceed this limit. If there are
1764
+
more changes than this between the client's state and the current
1765
+
server state, the server SHOULD generate an update to take the client
1766
+
to an intermediate state, from which the client can continue to call
1767
+
"Foo/changes" until it is fully up to date. If it is unable to
1768
+
calculate an intermediate state, it MUST return a
1769
+
"cannotCalculateChanges" error response instead.
1771
+
When generating intermediate states, the server may choose how to
1772
+
divide up the changes. For many types, it will provide a better user
1773
+
experience to return the more recent changes first, as this is more
1774
+
likely to be what the user is most interested in. The client can
1775
+
then continue to page in the older changes while the user is viewing
1776
+
the newer data. For example, suppose a server went through the
1779
+
A -> B -> C -> D -> E
1781
+
And a client asks for changes from state "B". The server might first
1782
+
get the ids of records created, updated, or destroyed between states
1783
+
D and E, returning them with:
1786
+
hasMoreChanges: true
1794
+
Jenkins & Newman Standards Track [Page 32]
1796
+
RFC 8620 JMAP July 2019
1799
+
The client will then ask for the change from state "B-D-E", and the
1800
+
server can return the changes between states C and D, returning:
1803
+
hasMoreChanges: true
1805
+
Finally, the client will request the changes from "B-C-E", and the
1806
+
server can return the changes between states B and C, returning:
1809
+
hasMoreChanges: false
1811
+
Should the state on the server be modified in the middle of all this
1812
+
(to "F"), the server still does the same, but now when the update to
1813
+
state "E" is returned, it would indicate that it still has more
1814
+
changes for the client to fetch.
1816
+
Where multiple changes to a record are split across different
1817
+
intermediate states, the server MUST NOT return a record as created
1818
+
after a response that deems it as updated or destroyed, and it MUST
1819
+
NOT return a record as destroyed before a response that deems it as
1820
+
created or updated. The server may have to coalesce multiple changes
1821
+
to a record to satisfy this requirement.
1823
+
The following additional errors may be returned instead of the "Foo/
1824
+
changes" response:
1826
+
"cannotCalculateChanges": The server cannot calculate the changes
1827
+
from the state string given by the client. Usually, this is due to
1828
+
the client's state being too old or the server being unable to
1829
+
produce an update to an intermediate state when there are too many
1830
+
updates. The client MUST invalidate its Foo cache.
1832
+
Maintaining state to allow calculation of "Foo/changes" can be
1833
+
expensive for the server, but always returning
1834
+
"cannotCalculateChanges" severely increases network traffic and
1835
+
resource usage for the client. To allow efficient sync, servers
1836
+
SHOULD be able to calculate changes from any state string that was
1837
+
given to a client within the last 30 days (but of course may support
1838
+
calculating updates from states older than this).
1850
+
Jenkins & Newman Standards Track [Page 33]
1852
+
RFC 8620 JMAP July 2019
1857
+
Modifying the state of Foo objects on the server is done via the
1858
+
"Foo/set" method. This encompasses creating, updating, and
1859
+
destroying Foo records. This allows the server to sort out ordering
1860
+
and dependencies that may exist if doing multiple operations at once
1861
+
(for example, to ensure there is always a minimum number of a certain
1864
+
The "Foo/set" method takes the following arguments:
1868
+
The id of the account to use.
1870
+
o ifInState: "String|null"
1872
+
This is a state string as returned by the "Foo/get" method
1873
+
(representing the state of all objects of this type in the
1874
+
account). If supplied, the string must match the current state;
1875
+
otherwise, the method will be aborted and a "stateMismatch" error
1876
+
returned. If null, any changes will be applied to the current
1879
+
o create: "Id[Foo]|null"
1881
+
A map of a *creation id* (a temporary id set by the client) to Foo
1882
+
objects, or null if no objects are to be created.
1884
+
The Foo object type definition may define default values for
1885
+
properties. Any such property may be omitted by the client.
1887
+
The client MUST omit any properties that may only be set by the
1888
+
server (for example, the "id" property on most object types).
1890
+
o update: "Id[PatchObject]|null"
1892
+
A map of an id to a Patch object to apply to the current Foo
1893
+
object with that id, or null if no objects are to be updated.
1895
+
A *PatchObject* is of type "String[*]" and represents an unordered
1896
+
set of patches. The keys are a path in JSON Pointer format
1897
+
[RFC6901], with an implicit leading "/" (i.e., prefix each key
1898
+
with "/" before applying the JSON Pointer evaluation algorithm).
1900
+
All paths MUST also conform to the following restrictions; if
1901
+
there is any violation, the update MUST be rejected with an
1902
+
"invalidPatch" error:
1906
+
Jenkins & Newman Standards Track [Page 34]
1908
+
RFC 8620 JMAP July 2019
1911
+
* The pointer MUST NOT reference inside an array (i.e., you MUST
1912
+
NOT insert/delete from an array; the array MUST be replaced in
1913
+
its entirety instead).
1915
+
* All parts prior to the last (i.e., the value after the final
1916
+
slash) MUST already exist on the object being patched.
1918
+
* There MUST NOT be two patches in the PatchObject where the
1919
+
pointer of one is the prefix of the pointer of the other, e.g.,
1920
+
"alerts/1/offset" and "alerts".
1922
+
The value associated with each pointer determines how to apply
1925
+
* If null, set to the default value if specified for this
1926
+
property; otherwise, remove the property from the patched
1927
+
object. If the key is not present in the parent, this a no-op.
1929
+
* Anything else: The value to set for this property (this may be
1930
+
a replacement or addition to the object being patched).
1932
+
Any server-set properties MAY be included in the patch if their
1933
+
value is identical to the current server value (before applying
1934
+
the patches to the object). Otherwise, the update MUST be
1935
+
rejected with an "invalidProperties" SetError.
1937
+
This patch definition is designed such that an entire Foo object
1938
+
is also a valid PatchObject. The client may choose to optimise
1939
+
network usage by just sending the diff or may send the whole
1940
+
object; the server processes it the same either way.
1942
+
o destroy: "Id[]|null"
1944
+
A list of ids for Foo objects to permanently delete, or null if no
1945
+
objects are to be destroyed.
1947
+
Each creation, modification, or destruction of an object is
1948
+
considered an atomic unit. It is permissible for the server to
1949
+
commit changes to some objects but not others; however, it MUST NOT
1950
+
only commit part of an update to a single record (e.g., update a
1951
+
"name" property but not a "count" property, if both are supplied in
1952
+
the update object).
1954
+
The final state MUST be valid after the "Foo/set" is finished;
1955
+
however, the server may have to transition through invalid
1956
+
intermediate states (not exposed to the client) while processing the
1957
+
individual create/update/destroy requests. For example, suppose
1958
+
there is a "name" property that must be unique. A single method call
1962
+
Jenkins & Newman Standards Track [Page 35]
1964
+
RFC 8620 JMAP July 2019
1967
+
could rename an object A => B and simultaneously rename another
1968
+
object B => A. If the final state is valid, this is allowed.
1969
+
Otherwise, each creation, modification, or destruction of an object
1970
+
should be processed sequentially and accepted/rejected based on the
1971
+
current server state.
1973
+
If a create, update, or destroy is rejected, the appropriate error
1974
+
MUST be added to the notCreated/notUpdated/notDestroyed property of
1975
+
the response, and the server MUST continue to the next create/update/
1976
+
destroy. It does not terminate the method.
1978
+
If an id given cannot be found, the update or destroy MUST be
1979
+
rejected with a "notFound" set error.
1981
+
The server MAY skip an update (rejecting it with a "willDestroy"
1982
+
SetError) if that object is destroyed in the same /set request.
1984
+
Some records may hold references to other records (foreign keys).
1985
+
That reference may be set (via create or update) in the same request
1986
+
as the referenced record is created. To do this, the client refers
1987
+
to the new record using its creation id prefixed with a "#". The
1988
+
order of the method calls in the request by the client MUST be such
1989
+
that the record being referenced is created in the same or an earlier
1990
+
call. Thus, the server never has to look ahead. Instead, while
1991
+
processing a request, the server MUST keep a simple map for the
1992
+
duration of the request of creation id to record id for each newly
1993
+
created record, so it can substitute in the correct value if
1994
+
necessary in later method calls. In the case of records with
1995
+
references to the same type, the server MUST order the creates and
1996
+
updates within a single method call so that creates happen before
1997
+
their creation ids are referenced by another create/update/destroy in
2000
+
Creation ids are not scoped by type but are a single map for all
2001
+
types. A client SHOULD NOT reuse a creation id anywhere in the same
2002
+
API request. If a creation id is reused, the server MUST map the
2003
+
creation id to the most recently created item with that id. To allow
2004
+
easy proxying of API requests, an initial set of creation id to real
2005
+
id values may be passed with a request (see "The Request Object",
2006
+
Section 3.3) and the final state of the map passed out with the
2007
+
response (see "The Response Object", Section 3.4).
2009
+
The response has the following arguments:
2013
+
The id of the account used for the call.
2018
+
Jenkins & Newman Standards Track [Page 36]
2020
+
RFC 8620 JMAP July 2019
2023
+
o oldState: "String|null"
2025
+
The state string that would have been returned by "Foo/get" before
2026
+
making the requested changes, or null if the server doesn't know
2027
+
what the previous state string was.
2029
+
o newState: "String"
2031
+
The state string that will now be returned by "Foo/get".
2033
+
o created: "Id[Foo]|null"
2035
+
A map of the creation id to an object containing any properties of
2036
+
the created Foo object that were not sent by the client. This
2037
+
includes all server-set properties (such as the "id" in most
2038
+
object types) and any properties that were omitted by the client
2039
+
and thus set to a default by the server.
2041
+
This argument is null if no Foo objects were successfully created.
2043
+
o updated: "Id[Foo|null]|null"
2045
+
The keys in this map are the ids of all Foos that were
2046
+
successfully updated.
2048
+
The value for each id is a Foo object containing any property that
2049
+
changed in a way *not* explicitly requested by the PatchObject
2050
+
sent to the server, or null if none. This lets the client know of
2051
+
any changes to server-set or computed properties.
2053
+
This argument is null if no Foo objects were successfully updated.
2055
+
o destroyed: "Id[]|null"
2057
+
A list of Foo ids for records that were successfully destroyed, or
2060
+
o notCreated: "Id[SetError]|null"
2062
+
A map of the creation id to a SetError object for each record that
2063
+
failed to be created, or null if all successful.
2065
+
o notUpdated: "Id[SetError]|null"
2067
+
A map of the Foo id to a SetError object for each record that
2068
+
failed to be updated, or null if all successful.
2074
+
Jenkins & Newman Standards Track [Page 37]
2076
+
RFC 8620 JMAP July 2019
2079
+
o notDestroyed: "Id[SetError]|null"
2081
+
A map of the Foo id to a SetError object for each record that
2082
+
failed to be destroyed, or null if all successful.
2084
+
A *SetError* object has the following properties:
2088
+
The type of error.
2090
+
o description: "String|null"
2092
+
A description of the error to help with debugging that includes an
2093
+
explanation of what the problem was. This is a non-localised
2094
+
string and is not intended to be shown directly to end users.
2096
+
The following SetError types are defined and may be returned for set
2097
+
operations on any record type where appropriate:
2099
+
o "forbidden": (create; update; destroy). The create/update/destroy
2100
+
would violate an ACL or other permissions policy.
2102
+
o "overQuota": (create; update). The create would exceed a server-
2103
+
defined limit on the number or total size of objects of this type.
2105
+
o "tooLarge": (create; update). The create/update would result in
2106
+
an object that exceeds a server-defined limit for the maximum size
2107
+
of a single object of this type.
2109
+
o "rateLimit": (create). Too many objects of this type have been
2110
+
created recently, and a server-defined rate limit has been
2111
+
reached. It may work if tried again later.
2113
+
o "notFound": (update; destroy). The id given to update/destroy
2116
+
o "invalidPatch": (update). The PatchObject given to update the
2117
+
record was not a valid patch (see the patch description).
2119
+
o "willDestroy": (update). The client requested that an object be
2120
+
both updated and destroyed in the same /set request, and the
2121
+
server has decided to therefore ignore the update.
2130
+
Jenkins & Newman Standards Track [Page 38]
2132
+
RFC 8620 JMAP July 2019
2135
+
o "invalidProperties": (create; update). The record given is
2136
+
invalid in some way. For example:
2138
+
* It contains properties that are invalid according to the type
2139
+
specification of this record type.
2141
+
* It contains a property that may only be set by the server
2142
+
(e.g., "id") and is different to the current value. Note, to
2143
+
allow clients to pass whole objects back, it is not an error to
2144
+
include a server-set property in an update as long as the value
2145
+
is identical to the current value on the server.
2147
+
* There is a reference to another record (foreign key), and the
2148
+
given id does not correspond to a valid record.
2150
+
The SetError object SHOULD also have a property called
2151
+
"properties" of type "String[]" that lists *all* the properties
2152
+
that were invalid.
2154
+
Individual methods MAY specify more specific errors for certain
2155
+
conditions that would otherwise result in an invalidProperties
2156
+
error. If the condition of one of these is met, it MUST be
2157
+
returned instead of the invalidProperties error.
2159
+
o "singleton": (create; destroy). This is a singleton type, so you
2160
+
cannot create another one or destroy the existing one.
2162
+
Other possible SetError types MAY be given in specific method
2163
+
descriptions. Other properties MAY also be present on the SetError
2164
+
object, as described in the relevant methods.
2166
+
The following additional errors may be returned instead of the "Foo/
2169
+
"requestTooLarge": The total number of objects to create, update, or
2170
+
destroy exceeds the maximum number the server is willing to process
2171
+
in a single method call.
2173
+
"stateMismatch": An "ifInState" argument was supplied, and it does
2174
+
not match the current state.
2186
+
Jenkins & Newman Standards Track [Page 39]
2188
+
RFC 8620 JMAP July 2019
2193
+
The only way to move Foo records *between* two different accounts is
2194
+
to copy them using the "Foo/copy" method; once the copy has
2195
+
succeeded, delete the original. The "onSuccessDestroyOriginal"
2196
+
argument allows you to try to do this in one method call; however,
2197
+
note that the two different actions are not atomic, so it is possible
2198
+
for the copy to succeed but the original not to be destroyed for some
2201
+
The copy is conceptually in three phases:
2203
+
1. Reading the current values from the "from" account.
2205
+
2. Writing the new copies to the other account.
2207
+
3. Destroying the originals in the "from" account, if requested.
2209
+
Data may change in between phases due to concurrent requests.
2211
+
The "Foo/copy" method takes the following arguments:
2213
+
o fromAccountId: "Id"
2215
+
The id of the account to copy records from.
2217
+
o ifFromInState: "String|null"
2219
+
This is a state string as returned by the "Foo/get" method. If
2220
+
supplied, the string must match the current state of the account
2221
+
referenced by the fromAccountId when reading the data to be
2222
+
copied; otherwise, the method will be aborted and a
2223
+
"stateMismatch" error returned. If null, the data will be read
2224
+
from the current state.
2228
+
The id of the account to copy records to. This MUST be different
2229
+
to the "fromAccountId".
2231
+
o ifInState: "String|null"
2233
+
This is a state string as returned by the "Foo/get" method. If
2234
+
supplied, the string must match the current state of the account
2235
+
referenced by the accountId; otherwise, the method will be aborted
2236
+
and a "stateMismatch" error returned. If null, any changes will
2237
+
be applied to the current state.
2242
+
Jenkins & Newman Standards Track [Page 40]
2244
+
RFC 8620 JMAP July 2019
2247
+
o create: "Id[Foo]"
2249
+
A map of the *creation id* to a Foo object. The Foo object MUST
2250
+
contain an "id" property, which is the id (in the fromAccount) of
2251
+
the record to be copied. When creating the copy, any other
2252
+
properties included are used instead of the current value for that
2253
+
property on the original.
2255
+
o onSuccessDestroyOriginal: "Boolean" (default: false)
2257
+
If true, an attempt will be made to destroy the original records
2258
+
that were successfully copied: after emitting the "Foo/copy"
2259
+
response, but before processing the next method, the server MUST
2260
+
make a single call to "Foo/set" to destroy the original of each
2261
+
successfully copied record; the output of this is added to the
2262
+
responses as normal, to be returned to the client.
2264
+
o destroyFromIfInState: "String|null"
2266
+
This argument is passed on as the "ifInState" argument to the
2267
+
implicit "Foo/set" call, if made at the end of this request to
2268
+
destroy the originals that were successfully copied.
2270
+
Each record copy is considered an atomic unit that may succeed or
2271
+
fail individually.
2273
+
The response has the following arguments:
2275
+
o fromAccountId: "Id"
2277
+
The id of the account records were copied from.
2281
+
The id of the account records were copied to.
2283
+
o oldState: "String|null"
2285
+
The state string that would have been returned by "Foo/get" on the
2286
+
account records that were copied to before making the requested
2287
+
changes, or null if the server doesn't know what the previous
2290
+
o newState: "String"
2292
+
The state string that will now be returned by "Foo/get" on the
2293
+
account records were copied to.
2298
+
Jenkins & Newman Standards Track [Page 41]
2300
+
RFC 8620 JMAP July 2019
2303
+
o created: "Id[Foo]|null"
2305
+
A map of the creation id to an object containing any properties of
2306
+
the copied Foo object that are set by the server (such as the "id"
2307
+
in most object types; note, the id is likely to be different to
2308
+
the id of the object in the account it was copied from).
2310
+
This argument is null if no Foo objects were successfully copied.
2312
+
o notCreated: "Id[SetError]|null"
2314
+
A map of the creation id to a SetError object for each record that
2315
+
failed to be copied, or null if none.
2317
+
The SetError may be any of the standard set errors returned for a
2318
+
create or update. In addition, the following SetError is defined:
2320
+
"alreadyExists": The server forbids duplicates, and the record
2321
+
already exists in the target account. An "existingId" property of
2322
+
type "Id" MUST be included on the SetError object with the id of the
2325
+
The following additional errors may be returned instead of the "Foo/
2328
+
"fromAccountNotFound": The "fromAccountId" does not correspond to a
2331
+
"fromAccountNotSupportedByMethod": The "fromAccountId" given
2332
+
corresponds to a valid account, but the account does not support this
2335
+
"stateMismatch": An "ifInState" argument was supplied and it does not
2336
+
match the current state, or an "ifFromInState" argument was supplied
2337
+
and it does not match the current state in the from account.
2341
+
For data sets where the total amount of data is expected to be very
2342
+
small, clients can just fetch the complete set of data and then do
2343
+
any sorting/filtering locally. However, for large data sets (e.g.,
2344
+
multi-gigabyte mailboxes), the client needs to be able to
2345
+
search/sort/window the data type on the server.
2347
+
A query on the set of Foos in an account is made by calling "Foo/
2348
+
query". This takes a number of arguments to determine which records
2349
+
to include, how they should be sorted, and which part of the result
2354
+
Jenkins & Newman Standards Track [Page 42]
2356
+
RFC 8620 JMAP July 2019
2359
+
should be returned (the full list may be *very* long). The result is
2360
+
returned as a list of Foo ids.
2362
+
A call to "Foo/query" takes the following arguments:
2366
+
The id of the account to use.
2368
+
o filter: "FilterOperator|FilterCondition|null"
2370
+
Determines the set of Foos returned in the results. If null, all
2371
+
objects in the account of this type are included in the results.
2372
+
A *FilterOperator* object has the following properties:
2374
+
* operator: "String"
2376
+
This MUST be one of the following strings:
2378
+
+ "AND": All of the conditions must match for the filter to
2381
+
+ "OR": At least one of the conditions must match for the
2384
+
+ "NOT": None of the conditions must match for the filter to
2387
+
* conditions: "(FilterOperator|FilterCondition)[]"
2389
+
The conditions to evaluate against each record.
2391
+
A *FilterCondition* is an "object" whose allowed properties and
2392
+
semantics depend on the data type and is defined in the /query
2393
+
method specification for that type. It MUST NOT have an
2394
+
"operator" property.
2396
+
o sort: "Comparator[]|null"
2398
+
Lists the names of properties to compare between two Foo records,
2399
+
and how to compare them, to determine which comes first in the
2400
+
sort. If two Foo records have an identical value for the first
2401
+
comparator, the next comparator will be considered, and so on. If
2402
+
all comparators are the same (this includes the case where an
2403
+
empty array or null is given as the "sort" argument), the sort
2404
+
order is server dependent, but it MUST be stable between calls to
2405
+
"Foo/query". A *Comparator* has the following properties:
2410
+
Jenkins & Newman Standards Track [Page 43]
2412
+
RFC 8620 JMAP July 2019
2415
+
* property: "String"
2417
+
The name of the property on the Foo objects to compare.
2419
+
* isAscending: "Boolean" (optional; default: true)
2421
+
If true, sort in ascending order. If false, reverse the
2422
+
comparator's results to sort in descending order.
2424
+
* collation: "String" (optional; default is server-dependent)
2426
+
The identifier, as registered in the collation registry defined
2427
+
in [RFC4790], for the algorithm to use when comparing the order
2428
+
of strings. The algorithms the server supports are advertised
2429
+
in the capabilities object returned with the Session object
2432
+
If omitted, the default algorithm is server dependent, but:
2434
+
1. It MUST be unicode-aware.
2436
+
2. It MAY be selected based on an Accept-Language header in
2437
+
the request (as defined in [RFC7231], Section 5.3.5) or
2438
+
out-of-band information about the user's language/locale.
2440
+
3. It SHOULD be case insensitive where such a concept makes
2441
+
sense for a language/locale. Where the user's language is
2442
+
unknown, it is RECOMMENDED to follow the advice in
2443
+
Section 5.2.3 of [RFC8264].
2445
+
The "i;unicode-casemap" collation [RFC5051] and the Unicode
2446
+
Collation Algorithm (<http://www.unicode.org/reports/tr10/>)
2447
+
are two examples that fulfil these criterion and provide
2448
+
reasonable behaviour for a large number of languages.
2450
+
When the property being compared is not a string, the
2451
+
"collation" property is ignored, and the following comparison
2452
+
rules apply based on the type. In ascending order:
2454
+
+ "Boolean": false comes before true.
2456
+
+ "Number": A lower number comes before a higher number.
2458
+
+ "Date"/"UTCDate": The earlier date comes first.
2460
+
The Comparator object may also have additional properties as
2461
+
required for specific sort operations defined in a type's /query
2466
+
Jenkins & Newman Standards Track [Page 44]
2468
+
RFC 8620 JMAP July 2019
2471
+
o position: "Int" (default: 0)
2473
+
The zero-based index of the first id in the full list of results
2476
+
If a negative value is given, it is an offset from the end of the
2477
+
list. Specifically, the negative value MUST be added to the total
2478
+
number of results given the filter, and if still negative, it's
2479
+
clamped to "0". This is now the zero-based index of the first id
2482
+
If the index is greater than or equal to the total number of
2483
+
objects in the results list, then the "ids" array in the response
2484
+
will be empty, but this is not an error.
2486
+
o anchor: "Id|null"
2488
+
A Foo id. If supplied, the "position" argument is ignored. The
2489
+
index of this id in the results will be used in combination with
2490
+
the "anchorOffset" argument to determine the index of the first
2491
+
result to return (see below for more details).
2493
+
o anchorOffset: "Int" (default: 0)
2495
+
The index of the first result to return relative to the index of
2496
+
the anchor, if an anchor is given. This MAY be negative. For
2497
+
example, "-1" means the Foo immediately preceding the anchor is
2498
+
the first result in the list returned (see below for more
2501
+
o limit: "UnsignedInt|null"
2503
+
The maximum number of results to return. If null, no limit
2504
+
presumed. The server MAY choose to enforce a maximum "limit"
2505
+
argument. In this case, if a greater value is given (or if it is
2506
+
null), the limit is clamped to the maximum; the new limit is
2507
+
returned with the response so the client is aware. If a negative
2508
+
value is given, the call MUST be rejected with an
2509
+
"invalidArguments" error.
2511
+
o calculateTotal: "Boolean" (default: false)
2513
+
Does the client wish to know the total number of results in the
2514
+
query? This may be slow and expensive for servers to calculate,
2515
+
particularly with complex filters, so clients should take care to
2516
+
only request the total when needed.
2522
+
Jenkins & Newman Standards Track [Page 45]
2524
+
RFC 8620 JMAP July 2019
2527
+
If an "anchor" argument is given, the anchor is looked for in the
2528
+
results after filtering and sorting. If found, the "anchorOffset" is
2529
+
then added to its index. If the resulting index is now negative, it
2530
+
is clamped to 0. This index is now used exactly as though it were
2531
+
supplied as the "position" argument. If the anchor is not found, the
2532
+
call is rejected with an "anchorNotFound" error.
2534
+
If an "anchor" is specified, any position argument supplied by the
2535
+
client MUST be ignored. If no "anchor" is supplied, any
2536
+
"anchorOffset" argument MUST be ignored.
2538
+
A client can use "anchor" instead of "position" to find the index of
2539
+
an id within a large set of results.
2541
+
The response has the following arguments:
2545
+
The id of the account used for the call.
2547
+
o queryState: "String"
2549
+
A string encoding the current state of the query on the server.
2550
+
This string MUST change if the results of the query (i.e., the
2551
+
matching ids and their sort order) have changed. The queryState
2552
+
string MAY change if something has changed on the server, which
2553
+
means the results may have changed but the server doesn't know for
2556
+
The queryState string only represents the ordered list of ids that
2557
+
match the particular query (including its sort/filter). There is
2558
+
no requirement for it to change if a property on an object
2559
+
matching the query changes but the query results are unaffected
2560
+
(indeed, it is more efficient if the queryState string does not
2561
+
change in this case). The queryState string only has meaning when
2562
+
compared to future responses to a query with the same type/sort/
2563
+
filter or when used with /queryChanges to fetch changes.
2565
+
Should a client receive back a response with a different
2566
+
queryState string to a previous call, it MUST either throw away
2567
+
the currently cached query and fetch it again (note, this does not
2568
+
require fetching the records again, just the list of ids) or call
2569
+
"Foo/queryChanges" to get the difference.
2578
+
Jenkins & Newman Standards Track [Page 46]
2580
+
RFC 8620 JMAP July 2019
2583
+
o canCalculateChanges: "Boolean"
2585
+
This is true if the server supports calling "Foo/queryChanges"
2586
+
with these "filter"/"sort" parameters. Note, this does not
2587
+
guarantee that the "Foo/queryChanges" call will succeed, as it may
2588
+
only be possible for a limited time afterwards due to server
2589
+
internal implementation details.
2591
+
o position: "UnsignedInt"
2593
+
The zero-based index of the first result in the "ids" array within
2594
+
the complete list of query results.
2598
+
The list of ids for each Foo in the query results, starting at the
2599
+
index given by the "position" argument of this response and
2600
+
continuing until it hits the end of the results or reaches the
2601
+
"limit" number of ids. If "position" is >= "total", this MUST be
2604
+
o total: "UnsignedInt" (only if requested)
2606
+
The total number of Foos in the results (given the "filter").
2607
+
This argument MUST be omitted if the "calculateTotal" request
2608
+
argument is not true.
2610
+
o limit: "UnsignedInt" (if set by the server)
2612
+
The limit enforced by the server on the maximum number of results
2613
+
to return. This is only returned if the server set a limit or
2614
+
used a different limit than that given in the request.
2616
+
The following additional errors may be returned instead of the "Foo/
2619
+
"anchorNotFound": An anchor argument was supplied, but it cannot be
2620
+
found in the results of the query.
2622
+
"unsupportedSort": The "sort" is syntactically valid, but it includes
2623
+
a property the server does not support sorting on or a collation
2624
+
method it does not recognise.
2626
+
"unsupportedFilter": The "filter" is syntactically valid, but the
2627
+
server cannot process it. If the filter was the result of a user's
2628
+
search input, the client SHOULD suggest that the user simplify their
2634
+
Jenkins & Newman Standards Track [Page 47]
2636
+
RFC 8620 JMAP July 2019
2639
+
5.6. /queryChanges
2641
+
The "Foo/queryChanges" method allows a client to efficiently update
2642
+
the state of a cached query to match the new state on the server. It
2643
+
takes the following arguments:
2647
+
The id of the account to use.
2649
+
o filter: "FilterOperator|FilterCondition|null"
2651
+
The filter argument that was used with "Foo/query".
2653
+
o sort: "Comparator[]|null"
2655
+
The sort argument that was used with "Foo/query".
2657
+
o sinceQueryState: "String"
2659
+
The current state of the query in the client. This is the string
2660
+
that was returned as the "queryState" argument in the "Foo/query"
2661
+
response with the same sort/filter. The server will return the
2662
+
changes made to the query since this state.
2664
+
o maxChanges: "UnsignedInt|null"
2666
+
The maximum number of changes to return in the response. See
2667
+
error descriptions below for more details.
2669
+
o upToId: "Id|null"
2671
+
The last (highest-index) id the client currently has cached from
2672
+
the query results. When there are a large number of results, in a
2673
+
common case, the client may have only downloaded and cached a
2674
+
small subset from the beginning of the results. If the sort and
2675
+
filter are both only on immutable properties, this allows the
2676
+
server to omit changes after this point in the results, which can
2677
+
significantly increase efficiency. If they are not immutable,
2678
+
this argument is ignored.
2680
+
o calculateTotal: "Boolean" (default: false)
2682
+
Does the client wish to know the total number of results now in
2683
+
the query? This may be slow and expensive for servers to
2684
+
calculate, particularly with complex filters, so clients should
2685
+
take care to only request the total when needed.
2690
+
Jenkins & Newman Standards Track [Page 48]
2692
+
RFC 8620 JMAP July 2019
2695
+
The response has the following arguments:
2699
+
The id of the account used for the call.
2701
+
o oldQueryState: "String"
2703
+
This is the "sinceQueryState" argument echoed back; that is, the
2704
+
state from which the server is returning changes.
2706
+
o newQueryState: "String"
2708
+
This is the state the query will be in after applying the set of
2709
+
changes to the old state.
2711
+
o total: "UnsignedInt" (only if requested)
2713
+
The total number of Foos in the results (given the "filter").
2714
+
This argument MUST be omitted if the "calculateTotal" request
2715
+
argument is not true.
2719
+
The "id" for every Foo that was in the query results in the old
2720
+
state and that is not in the results in the new state.
2722
+
If the server cannot calculate this exactly, the server MAY return
2723
+
the ids of extra Foos in addition that may have been in the old
2724
+
results but are not in the new results.
2726
+
If the sort and filter are both only on immutable properties and
2727
+
an "upToId" is supplied and exists in the results, any ids that
2728
+
were removed but have a higher index than "upToId" SHOULD be
2731
+
If the "filter" or "sort" includes a mutable property, the server
2732
+
MUST include all Foos in the current results for which this
2733
+
property may have changed. The position of these may have moved
2734
+
in the results, so they must be reinserted by the client to ensure
2735
+
its query cache is correct.
2746
+
Jenkins & Newman Standards Track [Page 49]
2748
+
RFC 8620 JMAP July 2019
2751
+
o added: "AddedItem[]"
2753
+
The id and index in the query results (in the new state) for every
2754
+
Foo that has been added to the results since the old state AND
2755
+
every Foo in the current results that was included in the
2756
+
"removed" array (due to a filter or sort based upon a mutable
2759
+
If the sort and filter are both only on immutable properties and
2760
+
an "upToId" is supplied and exists in the results, any ids that
2761
+
were added but have a higher index than "upToId" SHOULD be
2764
+
The array MUST be sorted in order of index, with the lowest index
2767
+
An *AddedItem* object has the following properties:
2771
+
* index: "UnsignedInt"
2773
+
The result of this is that if the client has a cached sparse array of
2774
+
Foo ids corresponding to the results in the old state, then:
2776
+
fooIds = [ "id1", "id2", null, null, "id3", "id4", null, null, null ]
2778
+
If it *splices out* all ids in the removed array that it has in its
2779
+
cached results, then:
2781
+
removed = [ "id2", "id31", ... ];
2782
+
fooIds => [ "id1", null, null, "id3", "id4", null, null, null ]
2784
+
and *splices in* (one by one in order, starting with the lowest
2785
+
index) all of the ids in the added array:
2787
+
added = [{ id: "id5", index: 0, ... }];
2788
+
fooIds => [ "id5", "id1", null, null, "id3", "id4", null, null, null ]
2790
+
and *truncates* or *extends* to the new total length, then the
2791
+
results will now be in the new state.
2793
+
Note: splicing in adds the item at the given index, incrementing the
2794
+
index of all items previously at that or a higher index. Splicing
2795
+
out is the inverse, removing the item and decrementing the index of
2796
+
every item after it in the array.
2802
+
Jenkins & Newman Standards Track [Page 50]
2804
+
RFC 8620 JMAP July 2019
2807
+
The following additional errors may be returned instead of the "Foo/
2808
+
queryChanges" response:
2810
+
"tooManyChanges": There are more changes than the client's
2811
+
"maxChanges" argument. Each item in the removed or added array is
2812
+
considered to be one change. The client may retry with higher max
2813
+
changes or invalidate its cache of the query results.
2815
+
"cannotCalculateChanges": The server cannot calculate the changes
2816
+
from the queryState string given by the client, usually due to the
2817
+
client's state being too old. The client MUST invalidate its cache
2818
+
of the query results.
2822
+
Suppose we have a type *Todo* with the following properties:
2824
+
o id: "Id" (immutable; server-set)
2826
+
The id of the object.
2830
+
A brief summary of what is to be done.
2832
+
o keywords: "String[Boolean]" (default: {})
2834
+
A set of keywords that apply to the Todo. The set is represented
2835
+
as an object, with the keys being the "keywords". The value for
2836
+
each key in the object MUST be true. (This format allows you to
2837
+
update an individual key using patch syntax rather than having to
2838
+
update the whole set of keywords as one, which a "String[]"
2839
+
representation would require.)
2841
+
o neuralNetworkTimeEstimation: "Number" (server-set)
2843
+
The title and keywords are fed into the server's state-of-the-art
2844
+
neural network to get an estimation of how long this Todo will
2847
+
o subTodoIds: "Id[]|null"
2849
+
The ids of a list of other Todos to complete as part of this Todo.
2851
+
Suppose also that all the standard methods are defined for this type
2852
+
and the FilterCondition object supports a "hasKeyword" property to
2853
+
match Todos with the given keyword.
2858
+
Jenkins & Newman Standards Track [Page 51]
2860
+
RFC 8620 JMAP July 2019
2863
+
A client might want to display the list of Todos with either a
2864
+
"music" keyword or a "video" keyword, so it makes the following
2867
+
[[ "Todo/query", {
2872
+
{ "hasKeyword": "music" },
2873
+
{ "hasKeyword": "video" }
2876
+
"sort": [{ "property": "title" }],
2884
+
"name": "Todo/query",
2914
+
Jenkins & Newman Standards Track [Page 52]
2916
+
RFC 8620 JMAP July 2019
2919
+
This would query the server for the set of Todos with a keyword of
2920
+
either "music" or "video", sorted by title, and limited to the first
2921
+
10 results. It fetches the full object for each of these Todos using
2922
+
back-references to reference the result of the query. The response
2923
+
might look something like:
2925
+
[[ "Todo/query", {
2927
+
"queryState": "y13213",
2928
+
"canCalculateChanges": true,
2930
+
"ids": [ "a", "b", "c", "d", "e", "f", "g", "h", "i", "j" ]
2937
+
"title": "Practise Piano",
2940
+
"beethoven": true,
2943
+
"rachmaninov": true
2945
+
"neuralNetworkTimeEstimation": 3600
2948
+
"title": "Watch Daft Punk music video",
2954
+
"neuralNetworkTimeEstimation": 18000
2970
+
Jenkins & Newman Standards Track [Page 53]
2972
+
RFC 8620 JMAP July 2019
2975
+
Now, suppose the user adds a keyword "chopin" and removes the keyword
2976
+
"mozart" from the "Practise Piano" task. The client may send the
2977
+
whole object to the server, as this is a valid PatchObject:
2981
+
"ifInState": "10324",
2985
+
"title": "Practise Piano",
2988
+
"beethoven": true,
2991
+
"rachmaninov": true
2993
+
"neuralNetworkTimeEstimation": 360
2998
+
or it may send a minimal patch:
3002
+
"ifInState": "10324",
3005
+
"keywords/chopin": true,
3006
+
"keywords/mozart": null
3026
+
Jenkins & Newman Standards Track [Page 54]
3028
+
RFC 8620 JMAP July 2019
3031
+
The effect is exactly the same on the server in either case, and
3032
+
presuming the server is still in state "10324", it will probably
3037
+
"oldState": "10324",
3038
+
"newState": "10329",
3041
+
"neuralNetworkTimeEstimation": 5400
3046
+
The server changed the "neuralNetworkTimeEstimation" property on the
3047
+
object as part of this change; as this changed in a way *not*
3048
+
explicitly requested by the PatchObject sent to the server, it is
3049
+
returned with the "updated" confirmation.
3051
+
Let us now add a sub-Todo to our new "Practise Piano" Todo. In this
3052
+
example, we can see the use of a reference to a creation id to allow
3053
+
us to set a foreign key reference to a record created in the same
3060
+
"title": "Warm up with scales"
3065
+
"subTodoIds": [ "#k15" ]
3082
+
Jenkins & Newman Standards Track [Page 55]
3084
+
RFC 8620 JMAP July 2019
3087
+
Now, suppose another user deleted the "Listen to Daft Punk" Todo.
3088
+
The first user will receive a push notification (see Section 7) with
3089
+
the changed state string for the "Todo" type. Since the new string
3090
+
does not match its current state, it knows it needs to check for
3091
+
updates. It may make a request like:
3093
+
[[ "Todo/changes", {
3095
+
"sinceState": "10324",
3098
+
[ "Todo/queryChanges", {
3103
+
{ "hasKeyword": "music" },
3104
+
{ "hasKeyword": "video" }
3107
+
"sort": [{ "property": "title" }],
3108
+
"sinceQueryState": "y13213",
3112
+
and receive in response:
3114
+
[[ "Todo/changes", {
3116
+
"oldState": "10324",
3117
+
"newState": "871903",
3118
+
"hasMoreChanges": false,
3121
+
"destroyed": ["b"]
3123
+
[ "Todo/queryChanges", {
3125
+
"oldQueryState": "y13213",
3126
+
"newQueryState": "y13218",
3138
+
Jenkins & Newman Standards Track [Page 56]
3140
+
RFC 8620 JMAP July 2019
3143
+
Suppose the user has access to another account "y", for example, a
3144
+
team account shared between multiple users. To move an existing Todo
3145
+
from account "x", the client would call:
3148
+
"fromAccountId": "x",
3155
+
"onSuccessDestroyOriginal": true
3158
+
The server successfully copies the Todo to a new account (where it
3159
+
receives a new id) and deletes the original. Due to the implicit
3160
+
call to "Todo/set", there are two responses to the single method
3161
+
call, both with the same method call id:
3164
+
"fromAccountId": "x",
3171
+
"oldState": "c1d64ecb038c",
3172
+
"newState": "33844835152b"
3176
+
"oldState": "871903",
3177
+
"newState": "871909",
3178
+
"destroyed": [ "a" ],
3194
+
Jenkins & Newman Standards Track [Page 57]
3196
+
RFC 8620 JMAP July 2019
3199
+
5.8. Proxy Considerations
3201
+
JMAP has been designed to allow an API endpoint to easily proxy
3202
+
through to one or more JMAP servers. This may be useful for load
3203
+
balancing, augmenting capabilities, or presenting a single endpoint
3204
+
to accounts hosted on different JMAP servers (splitting the request
3205
+
based on each method's "accountId" argument). The proxy need only
3206
+
understand the general structure of a JMAP Request object; it does
3207
+
not need to know anything specifically about the methods and
3208
+
arguments it will pass through to other servers.
3210
+
If splitting up the methods in a request to call them on different
3211
+
backend servers, the proxy must do two things to ensure back-
3212
+
references and creation-id references resolve the same as if the
3213
+
entire request were processed on a single server:
3215
+
1. It must pass a "createdIds" property with each subrequest. If
3216
+
this is not given by the client, an empty object should be used
3217
+
for the first subrequest. The "createdIds" property of each
3218
+
subresponse should be passed on in the next subrequest.
3220
+
2. It must resolve back-references to previous method results that
3221
+
were processed on a different server. This is a relatively
3222
+
simple syntactic substitution, described in Section 3.7.
3224
+
When splitting a request based on accountId, proxy implementors do
3225
+
need to be aware of "/copy" methods that copy between accounts. If
3226
+
the accounts are on different servers, the proxy will have to
3227
+
implement this functionality directly.
3231
+
Binary data is referenced by a *blobId* in JMAP and uploaded/
3232
+
downloaded separately to the core API. The blobId solely represents
3233
+
the raw bytes of data, not any associated metadata such as a file
3234
+
name or content type. Such metadata is stored alongside the blobId
3235
+
in the object referencing it. The data represented by a blobId is
3238
+
Any blobId that exists within an account may be used when creating/
3239
+
updating another object in that account. For example, an Email type
3240
+
may have a blobId that represents the object in Internet Message
3241
+
Format [RFC5322]. A client could create a new Email object with an
3242
+
attachment and use this blobId, in effect attaching the old message
3243
+
to the new one. Similarly, it could attach any existing attachment
3244
+
of an old message without having to download and upload it again.
3250
+
Jenkins & Newman Standards Track [Page 58]
3252
+
RFC 8620 JMAP July 2019
3255
+
When the client uses a blobId in a create/update, the server MAY
3256
+
assign a new blobId to refer to the same binary data within the new/
3257
+
updated object. If it does so, it MUST return any properties that
3258
+
contain a changed blobId in the created/updated response, so the
3259
+
client gets the new ids.
3261
+
A blob that is not referenced by a JMAP object (e.g., as a message
3262
+
attachment) MAY be deleted by the server to free up resources.
3263
+
Uploads (see below) are initially unreferenced blobs. To ensure
3266
+
o The server SHOULD use a separate quota for unreferenced blobs to
3267
+
the account's usual quota. In the case of shared accounts, this
3268
+
quota SHOULD be separate per user.
3270
+
o This quota SHOULD be at least the maximum total size that a single
3271
+
object can reference on this server. For example, if supporting
3272
+
JMAP Mail, this should be at least the maximum total attachments
3273
+
size for a message.
3275
+
o When an upload would take the user over quota, the server MUST
3276
+
delete unreferenced blobs in date order, oldest first, until there
3277
+
is room for the new blob.
3279
+
o Except where quota restrictions force early deletion, an
3280
+
unreferenced blob MUST NOT be deleted for at least 1 hour from the
3281
+
time of upload; if reuploaded, the same blobId MAY be returned,
3282
+
but this SHOULD reset the expiry time.
3284
+
o A blob MUST NOT be deleted during the method call that removed the
3285
+
last reference, so that a client can issue a create and a destroy
3286
+
that both reference the blob within the same method call.
3288
+
6.1. Uploading Binary Data
3290
+
There is a single endpoint that handles all file uploads for an
3291
+
account, regardless of what they are to be used for. The Session
3292
+
object (see Section 2) has an "uploadUrl" property in URI Template
3293
+
(level 1) format [RFC6570], which MUST contain a variable called
3294
+
"accountId". The client may use this template in combination with an
3295
+
"accountId" to get the URL of the file upload resource.
3297
+
To upload a file, the client submits an authenticated POST request to
3298
+
the file upload resource.
3306
+
Jenkins & Newman Standards Track [Page 59]
3308
+
RFC 8620 JMAP July 2019
3311
+
A successful request MUST return a single JSON object with the
3312
+
following properties as the response:
3316
+
The id of the account used for the call.
3320
+
The id representing the binary data uploaded. The data for this
3321
+
id is immutable. The id *only* refers to the binary data, not any
3326
+
The media type of the file (as specified in [RFC6838],
3327
+
Section 4.2) as set in the Content-Type header of the upload HTTP
3330
+
o size: "UnsignedInt"
3332
+
The size of the file in octets.
3334
+
If identical binary content to an existing blob in the account is
3335
+
uploaded, the existing blobId MAY be returned.
3337
+
Clients should use the blobId returned in a timely manner. Under
3338
+
rare circumstances, the server may have deleted the blob before the
3339
+
client uses it; the client should keep a reference to the local file
3340
+
so it can upload it again in such a situation.
3342
+
When an HTTP error response is returned to the client, the server
3343
+
SHOULD return a JSON "problem details" object as the response body,
3346
+
As access controls are often determined by the object holding the
3347
+
reference to a blob, unreferenced blobs MUST only be accessible to
3348
+
the uploader, even in shared accounts.
3350
+
6.2. Downloading Binary Data
3352
+
The Session object (see Section 2) has a "downloadUrl" property,
3353
+
which is in URI Template (level 1) format [RFC6570]. The URL MUST
3354
+
contain variables called "accountId", "blobId", "type", and "name".
3362
+
Jenkins & Newman Standards Track [Page 60]
3364
+
RFC 8620 JMAP July 2019
3367
+
To download a file, the client makes an authenticated GET request to
3368
+
the download URL with the appropriate variables substituted in:
3370
+
o "accountId": The id of the account to which the record with the
3373
+
o "blobId": The blobId representing the data of the file to
3376
+
o "type": The type for the server to set in the "Content-Type"
3377
+
header of the response; the blobId only represents the binary data
3378
+
and does not have a content-type innately associated with it.
3380
+
o "name": The name for the file; the server MUST return this as the
3381
+
filename if it sets a "Content-Disposition" header.
3383
+
As the data for a particular blobId is immutable, and thus the
3384
+
response in the generated download URL is too, implementors are
3385
+
recommended to set long cache times and use the "immutable" Cache-
3386
+
Control extension [RFC8246] for successful responses, for example,
3387
+
"Cache-Control: private, immutable, max-age=31536000".
3389
+
When an HTTP error response is returned to the client, the server
3390
+
SHOULD return a JSON "problem details" object as the response body,
3395
+
Binary data may be copied *between* two different accounts using the
3396
+
"Blob/copy" method rather than having to download and then reupload
3399
+
The "Blob/copy" method takes the following arguments:
3401
+
o fromAccountId: "Id"
3403
+
The id of the account to copy blobs from.
3407
+
The id of the account to copy blobs to.
3411
+
A list of ids of blobs to copy to the other account.
3418
+
Jenkins & Newman Standards Track [Page 61]
3420
+
RFC 8620 JMAP July 2019
3423
+
The response has the following arguments:
3425
+
o fromAccountId: "Id"
3427
+
The id of the account blobs were copied from.
3431
+
The id of the account blobs were copied to.
3433
+
o copied: "Id[Id]|null"
3435
+
A map of the blobId in the fromAccount to the id for the blob in
3436
+
the account it was copied to, or null if none were successfully
3439
+
o notCopied: "Id[SetError]|null"
3441
+
A map of blobId to a SetError object for each blob that failed to
3442
+
be copied, or null if none.
3444
+
The SetError may be any of the standard set errors that may be
3445
+
returned for a create, as defined in Section 5.3. In addition, the
3446
+
"notFound" SetError error may be returned if the blobId to be copied
3449
+
The following additional method-level error may be returned instead
3450
+
of the "Blob/copy" response:
3452
+
"fromAccountNotFound": The "fromAccountId" included with the request
3453
+
does not correspond to a valid account.
3457
+
Push notifications allow clients to efficiently update (almost)
3458
+
instantly to stay in sync with data changes on the server. The
3459
+
general model for push is simple and sends minimal data over the push
3460
+
channel: just enough for the client to know whether it needs to
3461
+
resync. The format allows multiple changes to be coalesced into a
3462
+
single push update and the frequency of pushes to be rate limited by
3463
+
the server. It doesn't matter if some push events are dropped before
3464
+
they reach the client; the next time it gets/sets any records of a
3465
+
changed type, it will discover the data has changed and still sync
3474
+
Jenkins & Newman Standards Track [Page 62]
3476
+
RFC 8620 JMAP July 2019
3479
+
There are two different mechanisms by which a client can receive push
3480
+
notifications, to allow for the different environments in which a
3481
+
client may exist. An event source resource (see Section 7.3) allows
3482
+
clients that can hold transport connections open to receive push
3483
+
notifications directly from the JMAP server. This is simple and
3484
+
avoids third parties, but it is often not feasible on constrained
3485
+
platforms such as mobile devices. Alternatively, clients can make
3486
+
use of any push service supported by their environment. A URL for
3487
+
the push service is registered with the JMAP server (see
3488
+
Section 7.2); the server then POSTs each notification to that URL.
3489
+
The push service is then responsible for routing these to the client.
3491
+
7.1. The StateChange Object
3493
+
When something changes on the server, the server pushes a StateChange
3494
+
object to the client. A *StateChange* object has the following
3499
+
This MUST be the string "StateChange".
3501
+
o changed: "Id[TypeState]"
3503
+
A map of an "account id" to an object encoding the state of data
3504
+
types that have changed for that account since the last
3505
+
StateChange object was pushed, for each of the accounts to which
3506
+
the user has access and for which something has changed.
3508
+
A *TypeState* object is a map. The keys are the type name "Foo"
3509
+
(e.g., "Mailbox" or "Email"), and the value is the "state"
3510
+
property that would currently be returned by a call to "Foo/get".
3512
+
The client can compare the new state strings with its current
3513
+
values to see whether it has the current data for these types. If
3514
+
not, the changes can then be efficiently fetched in a single
3515
+
standard API request (using the /changes type methods).
3530
+
Jenkins & Newman Standards Track [Page 63]
3532
+
RFC 8620 JMAP July 2019
3537
+
In this example, the server has amalgamated a few changes together
3538
+
across two different accounts the user has access to, before pushing
3539
+
the following StateChange object to the client:
3542
+
"@type": "StateChange",
3545
+
"Email": "d35ecb040aab",
3546
+
"EmailDelivery": "428d565f2440",
3547
+
"CalendarEvent": "87accfac587a"
3550
+
"Mailbox": "0af7a512ce70",
3551
+
"CalendarEvent": "7a4297cecd76"
3556
+
The client can compare the state strings with its current state for
3557
+
the Email, CalendarEvent, etc., object types in the appropriate
3558
+
accounts to see if it needs to fetch changes.
3560
+
If the client is itself making changes, it may receive a StateChange
3561
+
object while the /set API call is in flight. It can wait until the
3562
+
call completes and then compare if the new state string after the
3563
+
/set is the same as was pushed in the StateChange object; if so, and
3564
+
the old state of the /set response matches the client's previous
3565
+
state, it does not need to waste a request asking for changes it
3568
+
7.2. PushSubscription
3570
+
Clients may create a PushSubscription to register a URL with the JMAP
3571
+
server. The JMAP server will then make an HTTP POST request to this
3572
+
URL for each push notification it wishes to send to the client.
3574
+
As a push subscription causes the JMAP server to make a number of
3575
+
requests to a previously unknown endpoint, it can be used as a vector
3576
+
for launching a denial-of-service attack. To prevent this, when a
3577
+
subscription is created, the JMAP server immediately sends a
3578
+
PushVerification object to that URL (see Section 7.2.2). The JMAP
3579
+
server MUST NOT make any further requests to the URL until the client
3580
+
receives the push and updates the subscription with the correct
3581
+
verification code.
3586
+
Jenkins & Newman Standards Track [Page 64]
3588
+
RFC 8620 JMAP July 2019
3591
+
A *PushSubscription* object has the following properties:
3593
+
o id: "Id" (immutable; server-set)
3595
+
The id of the push subscription.
3597
+
o deviceClientId: "String" (immutable)
3599
+
An id that uniquely identifies the client + device it is running
3600
+
on. The purpose of this is to allow clients to identify which
3601
+
PushSubscription objects they created even if they lose their
3602
+
local state, so they can revoke or update them. This string MUST
3603
+
be different on different devices and be different from apps from
3604
+
other vendors. It SHOULD be easy to regenerate and not depend on
3605
+
persisted state. It is RECOMMENDED to use a secure hash of a
3606
+
string that contains:
3608
+
1. A unique identifier associated with the device where the JMAP
3609
+
client is running, normally supplied by the device's operating
3612
+
2. A custom vendor/app id, including a domain controlled by the
3613
+
vendor of the JMAP client.
3615
+
To protect the privacy of the user, the deviceClientId id MUST NOT
3616
+
contain an unobfuscated device id.
3618
+
o url: "String" (immutable)
3620
+
An absolute URL where the JMAP server will POST the data for the
3621
+
push message. This MUST begin with "https://".
3623
+
o keys: "Object|null" (immutable)
3625
+
Client-generated encryption keys. If supplied, the server MUST
3626
+
use them as specified in [RFC8291] to encrypt all data sent to the
3627
+
push subscription. The object MUST have the following properties:
3629
+
* p256dh: "String"
3631
+
The P-256 Elliptic Curve Diffie-Hellman (ECDH) public key as
3632
+
described in [RFC8291], encoded in URL-safe base64
3633
+
representation as defined in [RFC4648].
3637
+
The authentication secret as described in [RFC8291], encoded in
3638
+
URL-safe base64 representation as defined in [RFC4648].
3642
+
Jenkins & Newman Standards Track [Page 65]
3644
+
RFC 8620 JMAP July 2019
3647
+
o verificationCode: "String|null"
3649
+
This MUST be null (or omitted) when the subscription is created.
3650
+
The JMAP server then generates a verification code and sends it in
3651
+
a push message, and the client updates the PushSubscription object
3652
+
with the code; see Section 7.2.2 for details.
3654
+
o expires: "UTCDate|null"
3656
+
The time this push subscription expires. If specified, the JMAP
3657
+
server MUST NOT make further requests to this resource after this
3658
+
time. It MAY automatically destroy the push subscription at or
3661
+
The server MAY choose to set an expiry if none is given by the
3662
+
client or modify the expiry time given by the client to a shorter
3665
+
o types: "String[]|null"
3667
+
A list of types the client is interested in (using the same names
3668
+
as the keys in the TypeState object defined in the previous
3669
+
section). A StateChange notification will only be sent if the
3670
+
data for one of these types changes. Other types are omitted from
3671
+
the TypeState object. If null, changes will be pushed for all
3674
+
The POST request MUST have a content type of "application/json" and
3675
+
contain the UTF-8 JSON-encoded object as the body. The request MUST
3676
+
have a "TTL" header and MAY have "Urgency" and/or "Topic" headers, as
3677
+
specified in Section 5 of [RFC8030]. The JMAP server is expected to
3678
+
understand and handle HTTP status responses in a reasonable manner.
3679
+
A "429" (Too Many Requests) response MUST cause the JMAP server to
3680
+
reduce the frequency of pushes; the JMAP push structure allows
3681
+
multiple changes to be coalesced into a single minimal StateChange
3682
+
object. See the security considerations in Section 8.6 for a
3683
+
discussion of the risks in connecting to unknown servers.
3685
+
The JMAP server acts as an application server as defined in
3686
+
[RFC8030]. A client MAY use the rest of [RFC8030] in combination
3687
+
with its own push service to form a complete end-to-end solution, or
3688
+
it MAY rely on alternative mechanisms to ensure the delivery of the
3689
+
pushed data after it leaves the JMAP server.
3691
+
The push subscription is tied to the credentials used to authenticate
3692
+
the API request that created it. Should these credentials expire or
3693
+
be revoked, the push subscription MUST be destroyed by the JMAP
3698
+
Jenkins & Newman Standards Track [Page 66]
3700
+
RFC 8620 JMAP July 2019
3703
+
server. Only subscriptions created by these credentials are returned
3704
+
when the client fetches existing subscriptions.
3706
+
When these credentials have their own expiry (i.e., it is a session
3707
+
with a timeout), the server SHOULD NOT set or bound the expiry time
3708
+
for the push subscription given by the client but MUST expire it when
3709
+
the session expires.
3711
+
When these credentials are not time bounded (e.g., Basic
3712
+
authentication [RFC7617]), the server SHOULD set an expiry time for
3713
+
the push subscription if none is given and limit the expiry time if
3714
+
set too far in the future. This maximum expiry time MUST be at least
3715
+
48 hours in the future and SHOULD be at least 7 days in the future.
3716
+
An app running on a mobile device may only be able to refresh the
3717
+
push subscription lifetime when it is in the foreground, so this
3718
+
gives a reasonable time frame to allow this to happen.
3720
+
In the case of separate access and refresh credentials, as in Oauth
3721
+
2.0 [RFC6749], the server SHOULD tie the push subscription to the
3722
+
validity of the refresh token rather than the access token and behave
3723
+
according to whether this is time-limited or not.
3725
+
When a push subscription is destroyed, the server MUST securely erase
3726
+
the URL and encryption keys from memory and storage as soon as
3729
+
7.2.1. PushSubscription/get
3731
+
Standard /get method as described in Section 5.1, except it does
3732
+
*not* take or return an "accountId" argument, as push subscriptions
3733
+
are not tied to specific accounts. It also does *not* return a
3734
+
"state" argument. The "ids" argument may be null to fetch all at
3737
+
The server MUST only return push subscriptions that were created
3738
+
using the same authentication credentials as for this
3739
+
"PushSubscription/get" request.
3741
+
As the "url" and "keys" properties may contain data that is private
3742
+
to a particular device, the values for these properties MUST NOT be
3743
+
returned. If the "properties" argument is null or omitted, the
3744
+
server MUST default to all properties excluding these two. If one of
3745
+
them is explicitly requested, the method call MUST be rejected with a
3746
+
"forbidden" error.
3754
+
Jenkins & Newman Standards Track [Page 67]
3756
+
RFC 8620 JMAP July 2019
3759
+
7.2.2. PushSubscription/set
3761
+
Standard /set method as described in Section 5.3, except it does
3762
+
*not* take or return an "accountId" argument, as push subscriptions
3763
+
are not tied to specific accounts. It also does *not* take an
3764
+
"ifInState" argument or return "oldState" or "newState" arguments.
3766
+
The "url" and "keys" properties are immutable; if the client wishes
3767
+
to change these, it must destroy the current push subscription and
3770
+
When a PushSubscription is created, the server MUST immediately push
3771
+
a *PushVerification* object to the URL. It has the following
3776
+
This MUST be the string "PushVerification".
3778
+
o pushSubscriptionId: "String"
3780
+
The id of the push subscription that was created.
3782
+
o verificationCode: "String"
3784
+
The verification code to add to the push subscription. This MUST
3785
+
contain sufficient entropy to avoid the client being able to guess
3786
+
the code via brute force.
3788
+
The client MUST update the push subscription with the correct
3789
+
verification code before the server makes any further requests to the
3790
+
subscription's URL. Attempts to update the subscription with an
3791
+
invalid verification code MUST be rejected by the server with an
3792
+
"invalidProperties" SetError.
3794
+
The client may update the "expires" property to extend (or, less
3795
+
commonly, shorten) the lifetime of a push subscription. The server
3796
+
MAY modify the proposed new expiry time to enforce server-defined
3797
+
limits. Extending the lifetime does not require the subscription to
3798
+
be verified again.
3800
+
Clients SHOULD NOT update or destroy a push subscription that they
3801
+
did not create (i.e., has a "deviceClientId" that they do not
3810
+
Jenkins & Newman Standards Track [Page 68]
3812
+
RFC 8620 JMAP July 2019
3817
+
At "2018-07-06T02:14:29Z", a client with deviceClientId "a889-ffea-
3818
+
910" fetches the set of push subscriptions currently on the server,
3819
+
making an API request with:
3821
+
[[ "PushSubscription/get", {
3827
+
[[ "PushSubscription/get", {
3829
+
"id": "e50b2c1d-9553-41a3-b0a7-a7d26b599ee1",
3830
+
"deviceClientId": "b37ff8001ca0",
3831
+
"verificationCode": "b210ef734fe5f439c1ca386421359f7b",
3832
+
"expires": "2018-07-31T00:13:21Z",
3833
+
"types": [ "Todo" ]
3835
+
"id": "f2d0aab5-e976-4e8b-ad4b-b380a5b987e4",
3836
+
"deviceClientId": "X8980fc",
3837
+
"verificationCode": "f3d4618a9ae15c8b7f5582533786d531",
3838
+
"expires": "2018-07-12T05:55:00Z",
3839
+
"types": [ "Mailbox", "Email", "EmailDelivery" ]
3844
+
Since neither of the returned push subscription objects have the
3845
+
client's deviceClientId, it knows it does not have a current push
3846
+
subscription active on the server. So it creates one, sending this
3849
+
[[ "PushSubscription/set", {
3852
+
"deviceClientId": "a889-ffea-910",
3853
+
"url": "https://example.com/push/?device=X8980fc&client=12c6d086",
3866
+
Jenkins & Newman Standards Track [Page 69]
3868
+
RFC 8620 JMAP July 2019
3871
+
The server creates the push subscription but limits the expiry time
3872
+
to 7 days in the future, returning this response:
3874
+
[[ "PushSubscription/set", {
3877
+
"id": "P43dcfa4-1dd4-41ef-9156-2c89b3b19c60",
3879
+
"expires": "2018-07-13T02:14:29Z"
3884
+
The server also immediately makes a POST request to
3885
+
"https://example.com/push/?device=X8980fc&client=12c6d086" with the
3889
+
"@type": "PushVerification",
3890
+
"pushSubscriptionId": "P43dcfa4-1dd4-41ef-9156-2c89b3b19c60",
3891
+
"verificationCode": "da1f097b11ca17f06424e30bf02bfa67"
3894
+
The client receives this and updates the subscription with the
3895
+
verification code (note there is a potential race condition here; the
3896
+
client MUST be able to handle receiving the push while the request
3897
+
creating the subscription is still in progress):
3899
+
[[ "PushSubscription/set", {
3901
+
"P43dcfa4-1dd4-41ef-9156-2c89b3b19c60": {
3902
+
"verificationCode": "da1f097b11ca17f06424e30bf02bfa67"
3907
+
The server confirms the update was successful and will now make
3908
+
requests to the registered URL when the state changes.
3922
+
Jenkins & Newman Standards Track [Page 70]
3924
+
RFC 8620 JMAP July 2019
3927
+
Two days later, the client updates the subscription to extend its
3928
+
lifetime, sending this request:
3930
+
[[ "PushSubscription/set", {
3932
+
"P43dcfa4-1dd4-41ef-9156-2c89b3b19c60": {
3933
+
"expires": "2018-08-13T00:00:00Z"
3938
+
The server extends the expiry time, but only again to its maximum
3939
+
limit of 7 days in the future, returning this response:
3941
+
[[ "PushSubscription/set", {
3943
+
"P43dcfa4-1dd4-41ef-9156-2c89b3b19c60": {
3944
+
"expires": "2018-07-15T02:22:50Z"
3951
+
Clients that can hold transport connections open can connect directly
3952
+
to the JMAP server to receive push notifications via a "text/event-
3953
+
stream" resource, as described in [EventSource]. This is a long
3954
+
running HTTP request, where the server can push data to the client by
3955
+
appending data without ending the response.
3957
+
When a change occurs in the data on the server, it pushes an event
3958
+
called "state" to any connected clients, with the StateChange object
3961
+
The server SHOULD also send a new event id that encodes the entire
3962
+
server state visible to the user immediately after sending a "state"
3963
+
event. When a new connection is made to the event-source endpoint, a
3964
+
client following the server-sent events specification will send a
3965
+
Last-Event-ID HTTP header field with the last id it saw, which the
3966
+
server can use to work out whether the client has missed some
3967
+
changes. If so, it SHOULD send these changes immediately on
3970
+
The Session object (see Section 2) has an "eventSourceUrl" property,
3971
+
which is in URI Template (level 1) format [RFC6570]. The URL MUST
3972
+
contain variables called "types", "closeafter", and "ping".
3978
+
Jenkins & Newman Standards Track [Page 71]
3980
+
RFC 8620 JMAP July 2019
3983
+
To connect to the resource, the client makes an authenticated GET
3984
+
request to the event-source URL with the appropriate variables
3987
+
o "types": This MUST be either:
3989
+
* A comma-separated list of type names, e.g.,
3990
+
"Email,CalendarEvent". The server MUST only push changes for
3991
+
the types in this list.
3993
+
* The single character: "*". Changes to all types are pushed.
3995
+
o "closeafter": This MUST be one of the following values:
3997
+
* "state": The server MUST end the HTTP response after pushing a
3998
+
state event. This can be used by clients in environments where
3999
+
buffering proxies prevent the pushed data from arriving
4000
+
immediately, or indeed at all, when operating in the usual
4003
+
* "no": The connection is persisted by the server as a standard
4004
+
event-source resource.
4006
+
o "ping": A positive integer value representing a length of time in
4007
+
seconds, e.g., "300". If non-zero, the server MUST send an event
4008
+
called "ping" whenever this time elapses since the previous event
4009
+
was sent. This MUST NOT set a new event id. If the value is "0",
4010
+
the server MUST NOT send ping events.
4012
+
The server MAY modify a requested ping interval to be subject to a
4013
+
minimum and/or maximum value. For interoperability, servers MUST
4014
+
NOT have a minimum allowed value higher than 30 or a maximum
4015
+
allowed value less than 300.
4017
+
The data for the ping event MUST be a JSON object containing an
4018
+
"interval" property, the value (type "UnsignedInt") being the
4019
+
interval in seconds the server is using to send pings (this may be
4020
+
different to the requested value if the server clamped it to be
4021
+
within a min/max value).
4023
+
Clients can monitor for the ping event to help determine when the
4024
+
closeafter mode may be required.
4026
+
A client MAY hold open multiple connections to the event-source
4027
+
resource, although it SHOULD try to use a single connection for
4034
+
Jenkins & Newman Standards Track [Page 72]
4036
+
RFC 8620 JMAP July 2019
4039
+
8. Security Considerations
4041
+
8.1. Transport Confidentiality
4043
+
To ensure the confidentiality and integrity of data sent and received
4044
+
via JMAP, all requests MUST use TLS 1.2 [RFC5246] [RFC8446] or later,
4045
+
following the recommendations in [RFC7525]. Servers SHOULD support
4046
+
TLS 1.3 [RFC8446] or later.
4048
+
Clients MUST validate TLS certificate chains to protect against
4049
+
man-in-the-middle attacks [RFC5280].
4051
+
8.2. Authentication Scheme
4053
+
A number of HTTP authentication schemes have been standardised (see
4054
+
<https://www.iana.org/assignments/http-authschemes/>). Servers
4055
+
should take care to assess the security characteristics of different
4056
+
schemes in relation to their needs when deciding what to implement.
4058
+
Use of the Basic authentication scheme is NOT RECOMMENDED. Services
4059
+
that choose to use it are strongly recommended to require generation
4060
+
of a unique "app password" via some external mechanism for each
4061
+
client they wish to connect. This allows connections from different
4062
+
devices to be differentiated by the server and access to be
4063
+
individually revoked.
4065
+
8.3. Service Autodiscovery
4067
+
Unless secured by something like DNSSEC, autodiscovery of server
4068
+
details using SRV DNS records is vulnerable to a DNS poisoning
4069
+
attack, which can lead to the client talking to an attacker's server
4070
+
instead of the real JMAP server. The attacker may then intercept
4071
+
requests to execute man-in-the-middle attacks and, depending on the
4072
+
authentication scheme, steal credentials to generate its own
4075
+
Clients that do not support SRV lookups are likely to try just using
4076
+
the "/.well-known/jmap" path directly against the domain of the
4077
+
username over HTTPS. Servers SHOULD ensure this path resolves or
4078
+
redirects to the correct JMAP Session resource to allow this to work.
4079
+
If this is not feasible, servers MUST ensure this path cannot be
4080
+
controlled by an attacker, as again it may be used to steal
4090
+
Jenkins & Newman Standards Track [Page 73]
4092
+
RFC 8620 JMAP July 2019
4097
+
The Security Considerations of [RFC8259] apply to the use of JSON as
4098
+
the data interchange format.
4100
+
As for any serialization format, parsers need to thoroughly check the
4101
+
syntax of the supplied data. JSON uses opening and closing tags for
4102
+
several types and structures, and it is possible that the end of the
4103
+
supplied data will be reached when scanning for a matching closing
4104
+
tag; this is an error condition, and implementations need to stop
4105
+
scanning at the end of the supplied data.
4107
+
JSON also uses a string encoding with some escape sequences to encode
4108
+
special characters within a string. Care is needed when processing
4109
+
these escape sequences to ensure that they are fully formed before
4110
+
the special processing is triggered, with special care taken when the
4111
+
escape sequences appear adjacent to other (non-escaped) special
4112
+
characters or adjacent to the end of data (as in the previous
4115
+
If parsing JSON into a non-textual structured data format,
4116
+
implementations may need to allocate storage to hold JSON string
4117
+
elements. Since JSON does not use explicit string lengths, the risk
4118
+
of denial of service due to resource exhaustion is small, but
4119
+
implementations may still wish to place limits on the size of
4120
+
allocations they are willing to make in any given context, to avoid
4121
+
untrusted data causing excessive memory allocation.
4123
+
8.5. Denial of Service
4125
+
A small request may result in a very large response and require
4126
+
considerable work on the server if resource limits are not enforced.
4127
+
JMAP provides mechanisms for advertising and enforcing a wide variety
4128
+
of limits for mitigating this threat, including limits on the number
4129
+
of objects fetched in a single method call, number of methods in a
4130
+
single request, number of concurrent requests, etc.
4132
+
JMAP servers MUST implement sensible limits to mitigate against
4133
+
resource exhaustion attacks.
4135
+
8.6. Connection to Unknown Push Server
4137
+
When a push subscription is registered, the application server will
4138
+
make POST requests to the given URL. There are a number of security
4139
+
considerations that MUST be considered when implementing this.
4146
+
Jenkins & Newman Standards Track [Page 74]
4148
+
RFC 8620 JMAP July 2019
4151
+
The server MUST ensure the URL is externally resolvable to avoid
4152
+
server-side request forgery, where the server makes a request to a
4153
+
resource on its internal network.
4155
+
A malicious client may use the push subscription to attempt to flood
4156
+
a third party server with requests, creating a denial-of-service
4157
+
attack and masking the attacker's true identity. There is no
4158
+
guarantee that the URL given to the JMAP server is actually a valid
4159
+
push server. Upon creation of a push subscription, the JMAP server
4160
+
sends a PushVerification object to the URL and MUST NOT send any
4161
+
further requests until the client verifies it has received the
4162
+
initial push. The verification code MUST contain sufficient entropy
4163
+
to prevent the client from being able to verify the subscription via
4166
+
The verification code does not guarantee the URL is a valid push
4167
+
server, only that the client is able to access the data submitted to
4168
+
it. While the verification step significantly reduces the set of
4169
+
potential targets, there is still a risk that the server is unrelated
4170
+
to the client and being targeted for a denial-of-service attack.
4172
+
The server MUST limit the number of push subscriptions any one user
4173
+
may have to ensure the user cannot cause the server to send a large
4174
+
number of push notifications at once, which could again be used as
4175
+
part of a denial-of-service attack. The rate of creation MUST also
4176
+
be limited to minimise the ability to abuse the verification request
4177
+
as an attack vector.
4179
+
8.7. Push Encryption
4181
+
When data changes, a small object is pushed with the new state
4182
+
strings for the types that have changed. While the data here is
4183
+
minimal, a passive man-in-the-middle attacker may be able to gain
4184
+
useful information. To ensure confidentiality and integrity, if the
4185
+
push is sent via a third party outside of the control of the client
4186
+
and JMAP server, the client MUST specify encryption keys when
4187
+
establishing the PushSubscription and ignore any push notification
4188
+
received that is not encrypted with those keys.
4190
+
The privacy and security considerations of [RFC8030] and [RFC8291]
4191
+
also apply to the use of the PushSubscription mechanism.
4193
+
As there is no crypto algorithm agility in Web Push Encryption
4194
+
[RFC8291], a new specification will be needed to provide this if new
4195
+
algorithms are required in the future.
4202
+
Jenkins & Newman Standards Track [Page 75]
4204
+
RFC 8620 JMAP July 2019
4207
+
8.8. Traffic Analysis
4209
+
While the data is encrypted, a passive observer with the ability to
4210
+
monitor network traffic may be able to glean information from the
4211
+
timing of API requests and push notifications. For example, suppose
4212
+
an email or calendar invitation is sent from User A (hosted on Server
4213
+
X) to User B (hosted on Server Y). If Server X hosts data for many
4214
+
users, a passive observer can see that the two servers connected but
4215
+
does not know who the data was for. However, if a push notification
4216
+
is immediately sent to User B and the attacker can observe this as
4217
+
well, they may reasonably conclude that someone on Server X is
4218
+
connecting to User B.
4220
+
9. IANA Considerations
4222
+
9.1. Assignment of jmap Service Name
4224
+
IANA has assigned the 'jmap' service name in the "Service Name and
4225
+
Transport Protocol Port Number Registry" [RFC6335].
4227
+
Service Name: jmap
4229
+
Transport Protocol(s): tcp
4233
+
Contact: IETF Chair
4235
+
Description: JSON Meta Application Protocol
4237
+
Reference: RFC 8620
4239
+
Assignment Notes: This service name was previously assigned under the
4240
+
name "JSON Mail Access Protocol". This has been de-assigned and
4241
+
re-assigned with the approval of the previous assignee.
4243
+
9.2. Registration of Well-Known URI Suffix for JMAP
4245
+
IANA has registered the following suffix in the "Well-Known URIs"
4246
+
registry for JMAP, as described in [RFC8615]:
4250
+
Change Controller: IETF
4252
+
Specification Document: RFC 8620, Section 2.2.
4258
+
Jenkins & Newman Standards Track [Page 76]
4260
+
RFC 8620 JMAP July 2019
4263
+
9.3. Registration of the jmap URN Sub-namespace
4265
+
IANA has registered the following URN sub-namespace in the "IETF URN
4266
+
Sub-namespace for Registered Protocol Parameter Identifiers" registry
4267
+
within the "Uniform Resource Name (URN) Namespace for IETF Use"
4268
+
registry as described in [RFC3553].
4270
+
Registered Parameter Identifier: jmap
4272
+
Reference: RFC 8620, Section 9.4
4274
+
IANA Registry Reference: http://www.iana.org/assignments/jmap
4276
+
9.4. Creation of "JMAP Capabilities" Registry
4278
+
IANA has created the "JMAP Capabilities" registry as described in
4279
+
Section 2. JMAP capabilities are advertised in the "capabilities"
4280
+
property of the JMAP Session resource. They are used to extend the
4281
+
functionality of a JMAP server. A capability is referenced by a URI.
4282
+
The JMAP capability URI can be a URN starting with
4283
+
"urn:ietf:params:jmap:" plus a unique suffix that is the index value
4284
+
in the jmap URN sub-namespace. Registration of a JMAP capability
4285
+
with another form of URI has no impact on the jmap URN sub-namespace.
4287
+
This registry follows the expert review process unless the "intended
4288
+
use" field is "common" or "placeholder", in which case registration
4289
+
follows the specification required process.
4291
+
A JMAP capability registration can have an intended use of "common",
4292
+
"placeholder", "limited", or "obsolete". IANA will list common-use
4293
+
registrations prominently and separately from those with other
4294
+
intended use values.
4296
+
The JMAP capability registration procedure is not a formal standards
4297
+
process but rather an administrative procedure intended to allow
4298
+
community comment and sanity checking without excessive time delay.
4300
+
A "placeholder" registration reserves part of the jmap URN namespace
4301
+
for another purpose but is typically not included in the
4302
+
"capabilities" property of the JMAP Session resource.
4304
+
9.4.1. Preliminary Community Review
4306
+
Notice of a potential JMAP common-use registration SHOULD be sent to
4307
+
the JMAP mailing list <jmap@ietf.org> for review. This mailing list
4308
+
is appropriate to solicit community feedback on a proposed JMAP
4314
+
Jenkins & Newman Standards Track [Page 77]
4316
+
RFC 8620 JMAP July 2019
4319
+
capability. Registrations that are not intended for common use MAY
4320
+
be sent to the list for review as well; doing so is entirely
4321
+
OPTIONAL, but is encouraged.
4323
+
The intent of the public posting to this list is to solicit comments
4324
+
and feedback on the choice of the capability name, the unambiguity of
4325
+
the specification document, and a review of any interoperability or
4326
+
security considerations. The submitter may submit a revised
4327
+
registration proposal or abandon the registration completely at any
4330
+
9.4.2. Submit Request to IANA
4332
+
Registration requests can be sent to <iana@iana.org>.
4334
+
9.4.3. Designated Expert Review
4336
+
For a limited-use registration, the primary concern of the designated
4337
+
expert (DE) is preventing name collisions and encouraging the
4338
+
submitter to document security and privacy considerations; a
4339
+
published specification is not required. For a common-use
4340
+
registration, the DE is expected to confirm that suitable
4341
+
documentation, as described in Section 4.6 of [RFC8126], is
4342
+
available. The DE should also verify that the capability does not
4343
+
conflict with work that is active or already published within the
4346
+
Before a period of 30 days has passed, the DE will either approve or
4347
+
deny the registration request and publish a notice of the decision to
4348
+
the JMAP WG mailing list or its successor, as well as inform IANA. A
4349
+
denial notice must be justified by an explanation, and, in the cases
4350
+
where it is possible, concrete suggestions on how the request can be
4351
+
modified so as to become acceptable should be provided.
4353
+
If the DE does not respond within 30 days, the registrant may request
4354
+
the IESG take action to process the request in a timely manner.
4356
+
9.4.4. Change Procedures
4358
+
Once a JMAP capability has been published by the IANA, the change
4359
+
controller may request a change to its definition. The same
4360
+
procedure that would be appropriate for the original registration
4361
+
request is used to process a change request.
4363
+
JMAP capability registrations may not be deleted; capabilities that
4364
+
are no longer believed appropriate for use can be declared obsolete
4365
+
by a change to their "intended use" field; such capabilities will be
4366
+
clearly marked in the lists published by the IANA.
4370
+
Jenkins & Newman Standards Track [Page 78]
4372
+
RFC 8620 JMAP July 2019
4375
+
Significant changes to a capability's definition should be requested
4376
+
only when there are serious omissions or errors in the published
4377
+
specification. When review is required, a change request may be
4378
+
denied if it renders entities that were valid under the previous
4379
+
definition invalid under the new definition.
4381
+
The owner of a JMAP capability may pass responsibility to another
4382
+
person or agency by informing the IANA; this can be done without
4383
+
discussion or review.
4385
+
The IESG may reassign responsibility for a JMAP capability. The most
4386
+
common case of this will be to enable changes to be made to
4387
+
capabilities where the author of the registration has died, moved out
4388
+
of contact, or is otherwise unable to make changes that are important
4391
+
9.4.5. JMAP Capabilities Registry Template
4393
+
Capability name: (see capability property in Section 2)
4395
+
Specification document:
4397
+
Intended use: (one of common, limited, placeholder, or obsolete)
4399
+
Change controller: ("IETF" for Standards Track / BCP RFCs)
4401
+
Security and privacy considerations:
4403
+
9.4.6. Initial Registration for JMAP Core
4405
+
Capability Name: "urn:ietf:params:jmap:core"
4407
+
Specification document: RFC 8620, Section 2
4409
+
Intended use: common
4411
+
Change Controller: IETF
4413
+
Security and privacy considerations: RFC 8620, Section 8.
4426
+
Jenkins & Newman Standards Track [Page 79]
4428
+
RFC 8620 JMAP July 2019
4431
+
9.4.7. Registration for JMAP Error Placeholder in JMAP Capabilities
4434
+
Capability Name: "urn:ietf:params:jmap:error:"
4436
+
Specification document: RFC 8620, Section 9.5
4438
+
Intended use: placeholder
4440
+
Change Controller: IETF
4442
+
Security and privacy considerations: RFC 8620, Section 8.
4444
+
9.5. Creation of "JMAP Error Codes" Registry
4446
+
IANA has created the "JMAP Error Codes" registry. JMAP error codes
4447
+
appear in the "type" member of a JSON problem details object (as
4448
+
described in Section 3.6.1), the "type" member in a JMAP error object
4449
+
(as described in Section 3.6.2), or the "type" member of a JMAP
4450
+
method-specific error object (such as SetError in Section 5.3). When
4451
+
used in a problem details object, the prefix
4452
+
"urn:ietf:params:jmap:error:" is always included; when used in JMAP
4453
+
objects, the prefix is always omitted.
4455
+
This registry follows the expert review process. Preliminary
4456
+
community review for this registry follows the same procedures as the
4457
+
"JMAP Capabilities" registry, but it is optional. The change
4458
+
procedures for this registry are the same as the change procedures
4459
+
for the "JMAP Capabilities" registry.
4461
+
9.5.1. Expert Review
4463
+
The designated expert should review the following aspects of the
4466
+
1. Verify the error code does not conflict with existing names.
4468
+
2. Verify the error code follows the syntax limitations (does not
4469
+
require URI encoding).
4471
+
3. Encourage the submitter to follow the naming convention of
4472
+
previously registered errors.
4474
+
4. Encourage the submitter to describe client behaviours that are
4475
+
recommended in response to the error code. These may distinguish
4476
+
the error code from other error codes.
4482
+
Jenkins & Newman Standards Track [Page 80]
4484
+
RFC 8620 JMAP July 2019
4487
+
5. Encourage the submitter to describe when the server should issue
4488
+
the error as opposed to some other error code.
4490
+
6. Encourage the submitter to note any security considerations
4491
+
associated with the error, if any (e.g., an error code that might
4492
+
disclose existence of data the authenticated user does not have
4493
+
permission to know about).
4495
+
Steps 3-6 are meant to promote a higher-quality registry. However,
4496
+
the expert is encouraged to approve any registration that would not
4497
+
actively harm JMAP interoperability to make this a relatively
4498
+
lightweight process.
4500
+
9.5.2. JMAP Error Codes Registry Template
4504
+
Intended use: (one of "common", "limited", "obsolete")
4506
+
Change Controller: ("IETF" for Standards Track / BCP RFCs)
4508
+
Reference: (Optional. Only required if defined in an RFC.)
4512
+
9.5.3. Initial Contents for the JMAP Error Codes Registry
4514
+
o JMAP Error Code: accountNotFound
4515
+
Intended Use: Common
4516
+
Change Controller: IETF
4517
+
Reference: RFC 8620, Section 3.6.2
4518
+
Description: The accountId does not correspond to a valid account.
4520
+
o JMAP Error Code: accountNotSupportedByMethod
4521
+
Intended Use: Common
4522
+
Change Controller: IETF
4523
+
Reference: RFC 8620, Section 3.6.2
4524
+
Description: The accountId given corresponds to a valid account,
4525
+
but the account does not support this method or data type.
4527
+
o JMAP Error Code: accountReadOnly
4528
+
Intended Use: Common
4529
+
Change Controller: IETF
4530
+
Reference: RFC 8620, Section 3.6.2
4531
+
Description: This method modifies state, but the account is read-
4532
+
only (as returned on the corresponding Account object in the JMAP
4533
+
Session resource).
4538
+
Jenkins & Newman Standards Track [Page 81]
4540
+
RFC 8620 JMAP July 2019
4543
+
o JMAP Error Code: anchorNotFound
4544
+
Intended Use: Common
4545
+
Change Controller: IETF
4546
+
Reference: RFC 8620, Section 5.5
4547
+
Description: An anchor argument was supplied, but it cannot be
4548
+
found in the results of the query.
4550
+
o JMAP Error Code: alreadyExists
4551
+
Intended Use: Common
4552
+
Change Controller: IETF
4553
+
Reference: RFC 8620, Section 5.4
4554
+
Description: The server forbids duplicates, and the record already
4555
+
exists in the target account. An existingId property of type Id
4556
+
MUST be included on the SetError object with the id of the
4559
+
o JMAP Error Code: cannotCalculateChanges
4560
+
Intended Use: Common
4561
+
Change Controller: IETF
4562
+
Reference: RFC 8620, Sections 5.2 and 5.6
4563
+
Description: The server cannot calculate the changes from the
4564
+
state string given by the client.
4566
+
o JMAP Error Code: forbidden
4567
+
Intended Use: Common
4568
+
Change Controller: IETF
4569
+
Reference: RFC 8620, Sections 3.6.2, 5.3, and 7.2.1
4570
+
Description: The action would violate an ACL or other permissions
4573
+
o JMAP Error Code: fromAccountNotFound
4574
+
Intended Use: Common
4575
+
Change Controller: IETF
4576
+
Reference: RFC 8620, Sections 5.4 and 6.3
4577
+
Description: The fromAccountId does not correspond to a valid
4580
+
o JMAP Error Code: fromAccountNotSupportedByMethod
4581
+
Intended Use: Common
4582
+
Change Controller: IETF
4583
+
Reference: RFC 8620, Section 5.4
4584
+
Description: The fromAccountId given corresponds to a valid
4585
+
account, but the account does not support this data type.
4594
+
Jenkins & Newman Standards Track [Page 82]
4596
+
RFC 8620 JMAP July 2019
4599
+
o JMAP Error Code: invalidArguments
4600
+
Intended Use: Common
4601
+
Change Controller: IETF
4602
+
Reference: RFC 8620, Section 3.6.2
4603
+
Description: One of the arguments is of the wrong type or
4604
+
otherwise invalid, or a required argument is missing.
4606
+
o JMAP Error Code: invalidPatch
4607
+
Intended Use: Common
4608
+
Change Controller: IETF
4609
+
Reference: RFC 8620, Section 5.3
4610
+
Description: The PatchObject given to update the record was not a
4613
+
o JMAP Error Code: invalidProperties
4614
+
Intended Use: Common
4615
+
Change Controller: IETF
4616
+
Reference: RFC 8620, Section 5.3
4617
+
Description: The record given is invalid.
4619
+
o JMAP Error Code: notFound
4620
+
Intended Use: Common
4621
+
Change Controller: IETF
4622
+
Reference: RFC 8620, Section 5.3
4623
+
Description: The id given cannot be found.
4625
+
o JMAP Error Code: notJSON
4626
+
Intended Use: Common
4627
+
Change Controller: IETF
4628
+
Reference: RFC 8620, Section 3.6.1
4629
+
Description: The content type of the request was not application/
4630
+
json, or the request did not parse as I-JSON.
4632
+
o JMAP Error Code: notRequest
4633
+
Intended Use: Common
4634
+
Change Controller: IETF
4635
+
Reference: RFC 8620, Section 3.6.1
4636
+
Description: The request parsed as JSON but did not match the type
4637
+
signature of the Request object.
4639
+
o JMAP Error Code: overQuota
4640
+
Intended Use: Common
4641
+
Change Controller: IETF
4642
+
Reference: RFC 8620, Section 5.3
4643
+
Description: The create would exceed a server-defined limit on the
4644
+
number or total size of objects of this type.
4650
+
Jenkins & Newman Standards Track [Page 83]
4652
+
RFC 8620 JMAP July 2019
4655
+
o JMAP Error Code: rateLimit
4656
+
Intended Use: Common
4657
+
Change Controller: IETF
4658
+
Reference: RFC 8620, Section 5.3
4659
+
Description: Too many objects of this type have been created
4660
+
recently, and a server-defined rate limit has been reached. It
4661
+
may work if tried again later.
4663
+
o JMAP Error Code: requestTooLarge
4664
+
Intended Use: Common
4665
+
Change Controller: IETF
4666
+
Reference: RFC 8620, Sections 5.1 and 5.3
4667
+
Description: The total number of actions exceeds the maximum
4668
+
number the server is willing to process in a single method call.
4670
+
o JMAP Error Code: invalidResultReference
4671
+
Intended Use: Common
4672
+
Change Controller: IETF
4673
+
Reference: RFC 8620, Section 3.6.2
4674
+
Description: The method used a result reference for one of its
4675
+
arguments, but this failed to resolve.
4677
+
o JMAP Error Code: serverFail
4678
+
Intended Use: Common
4679
+
Change Controller: IETF
4680
+
Reference: RFC 8620, Section 3.6.2
4681
+
Description: An unexpected or unknown error occurred during the
4682
+
processing of the call. The method call made no changes to the
4685
+
o JMAP Error Code: serverPartialFail
4686
+
Intended Use: Limited
4687
+
Change Controller: IETF
4688
+
Reference: RFC 8620, Section 3.6.2
4689
+
Description: Some, but not all, expected changes described by the
4690
+
method occurred. The client MUST resynchronise impacted data to
4691
+
determine the server state. Use of this error is strongly
4694
+
o JMAP Error Code: serverUnavailable
4695
+
Intended Use: Common
4696
+
Change Controller: IETF
4697
+
Reference: RFC 8620, Section 3.6.2
4698
+
Description: Some internal server resource was temporarily
4699
+
unavailable. Attempting the same operation later (perhaps after a
4700
+
backoff with a random factor) may succeed.
4706
+
Jenkins & Newman Standards Track [Page 84]
4708
+
RFC 8620 JMAP July 2019
4711
+
o JMAP Error Code: singleton
4712
+
Intended Use: Common
4713
+
Change Controller: IETF
4714
+
Reference: RFC 8620, Section 5.3
4715
+
Description: This is a singleton type, so you cannot create
4716
+
another one or destroy the existing one.
4718
+
o JMAP Error Code: stateMismatch
4719
+
Intended Use: Common
4720
+
Change Controller: IETF
4721
+
Reference: RFC 8620, Section 5.3
4722
+
Description: An ifInState argument was supplied, and it does not
4723
+
match the current state.
4725
+
o JMAP Error Code: tooLarge
4726
+
Intended Use: Common
4727
+
Change Controller: IETF
4728
+
Reference: RFC 8620, Section 5.3
4729
+
Description: The action would result in an object that exceeds a
4730
+
server-defined limit for the maximum size of a single object of
4733
+
o JMAP Error Code: tooManyChanges
4734
+
Intended Use: Common
4735
+
Change Controller: IETF
4736
+
Reference: RFC 8620, Section 5.6
4737
+
Description: There are more changes than the client's maxChanges
4740
+
o JMAP Error Code: unknownCapability
4741
+
Intended Use: Common
4742
+
Change Controller: IETF
4743
+
Reference: RFC 8620, Section 3.6.1
4744
+
Description: The client included a capability in the "using"
4745
+
property of the request that the server does not support.
4747
+
o JMAP Error Code: unknownMethod
4748
+
Intended Use: Common
4749
+
Change Controller: IETF
4750
+
Reference: RFC 8620, Section 3.6.2
4751
+
Description: The server does not recognise this method name.
4753
+
o JMAP Error Code: unsupportedFilter
4754
+
Intended Use: Common
4755
+
Change Controller: IETF
4756
+
Reference: RFC 8620, Section 5.5
4757
+
Description: The filter is syntactically valid, but the server
4758
+
cannot process it.
4762
+
Jenkins & Newman Standards Track [Page 85]
4764
+
RFC 8620 JMAP July 2019
4767
+
o JMAP Error Code: unsupportedSort
4768
+
Intended Use: Common
4769
+
Change Controller: IETF
4770
+
Reference: RFC 8620, Section 5.5
4771
+
Description: The sort is syntactically valid but includes a
4772
+
property the server does not support sorting on or a collation
4773
+
method it does not recognise.
4775
+
o JMAP Error Code: willDestroy
4776
+
Intended Use: Common
4777
+
Change Controller: IETF
4778
+
Reference: RFC 8620, Section 5.3
4779
+
Description: The client requested an object be both updated and
4780
+
destroyed in the same /set request, and the server has decided to
4781
+
therefore ignore the update.
4785
+
10.1. Normative References
4788
+
Hickson, I., "Server-Sent Events", World Wide Web
4789
+
Consortium Recommendation REC-eventsource-20150203,
4790
+
February 2015, <https://www.w3.org/TR/eventsource/>.
4792
+
[RFC2119] Bradner, S., "Key words for use in RFCs to Indicate
4793
+
Requirement Levels", BCP 14, RFC 2119,
4794
+
DOI 10.17487/RFC2119, March 1997,
4795
+
<https://www.rfc-editor.org/info/rfc2119>.
4797
+
[RFC2782] Gulbrandsen, A., Vixie, P., and L. Esibov, "A DNS RR for
4798
+
specifying the location of services (DNS SRV)", RFC 2782,
4799
+
DOI 10.17487/RFC2782, February 2000,
4800
+
<https://www.rfc-editor.org/info/rfc2782>.
4802
+
[RFC2818] Rescorla, E., "HTTP Over TLS", RFC 2818,
4803
+
DOI 10.17487/RFC2818, May 2000,
4804
+
<https://www.rfc-editor.org/info/rfc2818>.
4806
+
[RFC3339] Klyne, G. and C. Newman, "Date and Time on the Internet:
4807
+
Timestamps", RFC 3339, DOI 10.17487/RFC3339, July 2002,
4808
+
<https://www.rfc-editor.org/info/rfc3339>.
4810
+
[RFC3553] Mealling, M., Masinter, L., Hardie, T., and G. Klyne, "An
4811
+
IETF URN Sub-namespace for Registered Protocol
4812
+
Parameters", BCP 73, RFC 3553, DOI 10.17487/RFC3553, June
4813
+
2003, <https://www.rfc-editor.org/info/rfc3553>.
4818
+
Jenkins & Newman Standards Track [Page 86]
4820
+
RFC 8620 JMAP July 2019
4823
+
[RFC3629] Yergeau, F., "UTF-8, a transformation format of ISO
4824
+
10646", STD 63, RFC 3629, DOI 10.17487/RFC3629, November
4825
+
2003, <https://www.rfc-editor.org/info/rfc3629>.
4827
+
[RFC4648] Josefsson, S., "The Base16, Base32, and Base64 Data
4828
+
Encodings", RFC 4648, DOI 10.17487/RFC4648, October 2006,
4829
+
<https://www.rfc-editor.org/info/rfc4648>.
4831
+
[RFC4790] Newman, C., Duerst, M., and A. Gulbrandsen, "Internet
4832
+
Application Protocol Collation Registry", RFC 4790,
4833
+
DOI 10.17487/RFC4790, March 2007,
4834
+
<https://www.rfc-editor.org/info/rfc4790>.
4836
+
[RFC5051] Crispin, M., "i;unicode-casemap - Simple Unicode Collation
4837
+
Algorithm", RFC 5051, DOI 10.17487/RFC5051, October 2007,
4838
+
<https://www.rfc-editor.org/info/rfc5051>.
4840
+
[RFC5246] Dierks, T. and E. Rescorla, "The Transport Layer Security
4841
+
(TLS) Protocol Version 1.2", RFC 5246,
4842
+
DOI 10.17487/RFC5246, August 2008,
4843
+
<https://www.rfc-editor.org/info/rfc5246>.
4845
+
[RFC5280] Cooper, D., Santesson, S., Farrell, S., Boeyen, S.,
4846
+
Housley, R., and W. Polk, "Internet X.509 Public Key
4847
+
Infrastructure Certificate and Certificate Revocation List
4848
+
(CRL) Profile", RFC 5280, DOI 10.17487/RFC5280, May 2008,
4849
+
<https://www.rfc-editor.org/info/rfc5280>.
4851
+
[RFC5322] Resnick, P., Ed., "Internet Message Format", RFC 5322,
4852
+
DOI 10.17487/RFC5322, October 2008,
4853
+
<https://www.rfc-editor.org/info/rfc5322>.
4855
+
[RFC6186] Daboo, C., "Use of SRV Records for Locating Email
4856
+
Submission/Access Services", RFC 6186,
4857
+
DOI 10.17487/RFC6186, March 2011,
4858
+
<https://www.rfc-editor.org/info/rfc6186>.
4860
+
[RFC6335] Cotton, M., Eggert, L., Touch, J., Westerlund, M., and S.
4861
+
Cheshire, "Internet Assigned Numbers Authority (IANA)
4862
+
Procedures for the Management of the Service Name and
4863
+
Transport Protocol Port Number Registry", BCP 165,
4864
+
RFC 6335, DOI 10.17487/RFC6335, August 2011,
4865
+
<https://www.rfc-editor.org/info/rfc6335>.
4867
+
[RFC6570] Gregorio, J., Fielding, R., Hadley, M., Nottingham, M.,
4868
+
and D. Orchard, "URI Template", RFC 6570,
4869
+
DOI 10.17487/RFC6570, March 2012,
4870
+
<https://www.rfc-editor.org/info/rfc6570>.
4874
+
Jenkins & Newman Standards Track [Page 87]
4876
+
RFC 8620 JMAP July 2019
4879
+
[RFC6749] Hardt, D., Ed., "The OAuth 2.0 Authorization Framework",
4880
+
RFC 6749, DOI 10.17487/RFC6749, October 2012,
4881
+
<https://www.rfc-editor.org/info/rfc6749>.
4883
+
[RFC6764] Daboo, C., "Locating Services for Calendaring Extensions
4884
+
to WebDAV (CalDAV) and vCard Extensions to WebDAV
4885
+
(CardDAV)", RFC 6764, DOI 10.17487/RFC6764, February 2013,
4886
+
<https://www.rfc-editor.org/info/rfc6764>.
4888
+
[RFC6838] Freed, N., Klensin, J., and T. Hansen, "Media Type
4889
+
Specifications and Registration Procedures", BCP 13,
4890
+
RFC 6838, DOI 10.17487/RFC6838, January 2013,
4891
+
<https://www.rfc-editor.org/info/rfc6838>.
4893
+
[RFC6901] Bryan, P., Ed., Zyp, K., and M. Nottingham, Ed.,
4894
+
"JavaScript Object Notation (JSON) Pointer", RFC 6901,
4895
+
DOI 10.17487/RFC6901, April 2013,
4896
+
<https://www.rfc-editor.org/info/rfc6901>.
4898
+
[RFC7230] Fielding, R., Ed. and J. Reschke, Ed., "Hypertext Transfer
4899
+
Protocol (HTTP/1.1): Message Syntax and Routing",
4900
+
RFC 7230, DOI 10.17487/RFC7230, June 2014,
4901
+
<https://www.rfc-editor.org/info/rfc7230>.
4903
+
[RFC7231] Fielding, R., Ed. and J. Reschke, Ed., "Hypertext Transfer
4904
+
Protocol (HTTP/1.1): Semantics and Content", RFC 7231,
4905
+
DOI 10.17487/RFC7231, June 2014,
4906
+
<https://www.rfc-editor.org/info/rfc7231>.
4908
+
[RFC7493] Bray, T., Ed., "The I-JSON Message Format", RFC 7493,
4909
+
DOI 10.17487/RFC7493, March 2015,
4910
+
<https://www.rfc-editor.org/info/rfc7493>.
4912
+
[RFC7525] Sheffer, Y., Holz, R., and P. Saint-Andre,
4913
+
"Recommendations for Secure Use of Transport Layer
4914
+
Security (TLS) and Datagram Transport Layer Security
4915
+
(DTLS)", BCP 195, RFC 7525, DOI 10.17487/RFC7525, May
4916
+
2015, <https://www.rfc-editor.org/info/rfc7525>.
4918
+
[RFC7617] Reschke, J., "The 'Basic' HTTP Authentication Scheme",
4919
+
RFC 7617, DOI 10.17487/RFC7617, September 2015,
4920
+
<https://www.rfc-editor.org/info/rfc7617>.
4922
+
[RFC7807] Nottingham, M. and E. Wilde, "Problem Details for HTTP
4923
+
APIs", RFC 7807, DOI 10.17487/RFC7807, March 2016,
4924
+
<https://www.rfc-editor.org/info/rfc7807>.
4930
+
Jenkins & Newman Standards Track [Page 88]
4932
+
RFC 8620 JMAP July 2019
4935
+
[RFC8030] Thomson, M., Damaggio, E., and B. Raymor, Ed., "Generic
4936
+
Event Delivery Using HTTP Push", RFC 8030,
4937
+
DOI 10.17487/RFC8030, December 2016,
4938
+
<https://www.rfc-editor.org/info/rfc8030>.
4940
+
[RFC8126] Cotton, M., Leiba, B., and T. Narten, "Guidelines for
4941
+
Writing an IANA Considerations Section in RFCs", BCP 26,
4942
+
RFC 8126, DOI 10.17487/RFC8126, June 2017,
4943
+
<https://www.rfc-editor.org/info/rfc8126>.
4945
+
[RFC8174] Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC
4946
+
2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174,
4947
+
May 2017, <https://www.rfc-editor.org/info/rfc8174>.
4949
+
[RFC8259] Bray, T., Ed., "The JavaScript Object Notation (JSON) Data
4950
+
Interchange Format", STD 90, RFC 8259,
4951
+
DOI 10.17487/RFC8259, December 2017,
4952
+
<https://www.rfc-editor.org/info/rfc8259>.
4954
+
[RFC8264] Saint-Andre, P. and M. Blanchet, "PRECIS Framework:
4955
+
Preparation, Enforcement, and Comparison of
4956
+
Internationalized Strings in Application Protocols",
4957
+
RFC 8264, DOI 10.17487/RFC8264, October 2017,
4958
+
<https://www.rfc-editor.org/info/rfc8264>.
4960
+
[RFC8291] Thomson, M., "Message Encryption for Web Push", RFC 8291,
4961
+
DOI 10.17487/RFC8291, November 2017,
4962
+
<https://www.rfc-editor.org/info/rfc8291>.
4964
+
[RFC8446] Rescorla, E., "The Transport Layer Security (TLS) Protocol
4965
+
Version 1.3", RFC 8446, DOI 10.17487/RFC8446, August 2018,
4966
+
<https://www.rfc-editor.org/info/rfc8446>.
4968
+
[RFC8615] Nottingham, M., "Well-Known Uniform Resource Identifiers
4969
+
(URIs)", RFC 8615, DOI 10.17487/RFC8615, May 2019,
4970
+
<https://www.rfc-editor.org/info/rfc8615>.
4972
+
10.2. Informative References
4974
+
[RFC8246] McManus, P., "HTTP Immutable Responses", RFC 8246,
4975
+
DOI 10.17487/RFC8246, September 2017,
4976
+
<https://www.rfc-editor.org/info/rfc8246>.
4986
+
Jenkins & Newman Standards Track [Page 89]
4988
+
RFC 8620 JMAP July 2019
4991
+
Authors' Addresses
4995
+
PO Box 234, Collins St. West
4996
+
Melbourne, VIC 8007
4999
+
Email: neilj@fastmailteam.com
5000
+
URI: https://www.fastmail.com
5005
+
440 E. Huntington Dr., Suite 400
5007
+
United States of America
5009
+
Email: chris.newman@oracle.com
5042
+
Jenkins & Newman Standards Track [Page 90]