RFC 9610

JSON Meta Application Protocol (JMAP) for Contacts

πŸ“… published December 2024, from ietf

RFC 9610: JSON Meta Application Protocol (JMAP) for Contacts πŸ’–

Okay bestie, this one is the spec for syncing contacts with a server using JMAP πŸ“‡βœ¨ It's a Standards Track document, so it's an actual official Internet standard, not just a vibe. Written by N. Jenkins, Ed. from Fastmail πŸ¦‹ It came out in December 2024, and its ISSN is 2070-1721. The title block doesn't list anything it obsoletes or updates, so nothing gets replaced or patched here 🌸

Abstract

This doc defines a data model for syncing contact data with a server using the JSON Meta Application Protocol (JMAP) πŸ“‡πŸ«Ά

Status of This Memo πŸ’…

This is an Internet Standards Track document.

It's a product of the Internet Engineering Task Force (IETF), so it represents the IETF community's consensus. It went through public review and got approved for publication by the Internet Engineering Steering Group (IESG) πŸŽ€ If you want the full scoop on Internet Standards, check out Section 2 of RFC 7841 ✨

Info about its current status, any errata, and how to send feedback lives at https://www.rfc-editor.org/info/rfc9610 πŸ”₯

Copyright (c) 2024 IETF Trust and the persons identified as the document authors. All rights reserved. 🌈

This document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (https://trustee.ietf.org/license-info) as they stand on the date of publication. Please actually read these, bestie, because they explain your rights and restrictions for this document πŸ™ˆ Any Code Components pulled out of this document must include Revised BSD License text, as described in Section 4.e of the Trust Legal Provisions, and they come without warranty, as described in the Revised BSD License ⚠️

Table of Contents πŸ“

1.  Introduction
  1.1.  Notational Conventions
  1.2.  Terminology
  1.3.  Data Model Overview
  1.4.  Addition to the Capabilities Object
    1.4.1.  urn:ietf:params:jmap:contacts
2.  AddressBooks
  2.1.  AddressBook/get
  2.2.  AddressBook/changes
  2.3.  AddressBook/set
3.  ContactCards
  3.1.  ContactCard/get
  3.2.  ContactCard/changes
  3.3.  ContactCard/query
    3.3.1.  Filtering
    3.3.2.  Sorting
  3.4.  ContactCard/queryChanges
  3.5.  ContactCard/set
  3.6.  ContactCard/copy
4.  Examples
  4.1.  Fetching Initial Data
  4.2.  Changing the Default Address Book
5.  Internationalisation Considerations
6.  Security Considerations
7.  IANA Considerations
  7.1.  JMAP Capability Registration for "contacts"
  7.2.  JMAP Data Type Registration for "AddressBook"
  7.3.  JMAP Data Type Registration for "ContactCard"
  7.4.  JMAP Error Codes Registry
    7.4.1.  addressBookHasContents
  7.5.  JSContact Property Registrations
    7.5.1.  id
    7.5.2.  addressBookIds
    7.5.3.  blobId
8.  References
  8.1.  Normative References
  8.2.  Informative References
Author's Address

1. Introduction ✨

JMAP [RFC8620] is a generic protocol for syncing data like mail, calendars, or contacts between a client and a server. It's optimised for mobile and web, and it wants to give you one consistent interface across different data types πŸ’œ

This spec defines a data model for syncing contacts between a client and a server using JMAP πŸ¦‹

1.1. Notational Conventions

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all capitals, as shown here πŸŽ€

Type signatures, examples, and property descriptions in this document follow the conventions set out in Section 1.1 of [RFC8620]. The Id, UnsignedInt, and UTCDate data types defined in Sections 1.2, 1.3, and 1.4 of [RFC8620] are also used in this document 🧚

1.2. Terminology

The same terminology used in the core JMAP spec (see Section 1.6 of [RFC8620]) is also used in this document πŸ’…

The terms AddressBook and ContactCard (with these specific capitalizations) refer to the data types defined in this document, and to instances of those data types 🌸

1.3. Data Model Overview

An Account (see Section 1.6.2 of [RFC8620]) that supports the contact data model contains zero or more AddressBook objects. Each AddressBook is a named collection of zero or more ContactCards. A ContactCard represents a person, a company, an entity, or a group of such entities, in JSContact Card format as defined in Section 2 of [RFC9553] πŸ“‡ Every ContactCard belongs to one or more AddressBooks 🫢

In servers that support JMAP Sharing [RFC9670], users can see and configure sharing of their contact data with others. Sharing permissions are managed per AddressBook πŸ”₯

1.4. Addition to the Capabilities Object

The capabilities object comes back as part of the JMAP Session object; see Section 2 of [RFC8620]. This document defines one additional capability URI 🌈

1.4.1. urn:ietf:params:jmap:contacts

This represents support for the AddressBook and ContactCard data types and their associated API methods. In the JMAP Session capabilities property, the value for this is an empty object πŸ“

In an account's accountCapabilities property, the value for this is an object that MUST contain the following information about server capabilities and permissions for that account πŸ‘‘

  • maxAddressBooksPerCard: UnsignedInt|null The maximum number of AddressBooks (see Section 2) that can be assigned to a single ContactCard object (see Section 3). This MUST be an integer >= 1, or null for no limit (or rather, the limit is always the number of AddressBooks in the account) πŸ¦‹
  • mayCreateAddressBook: Boolean The user may create an AddressBook in this account if, and only if, this is true πŸ’–

2. AddressBooks πŸ“š

An AddressBook is a named collection of ContactCards. All ContactCards are associated with one or more AddressBooks πŸŽ€

An AddressBook object has the following properties 🧚

  • id: Id (immutable; server-set) The id of the AddressBook.
  • name: String The user-visible name of the AddressBook. This MUST NOT be the empty string and MUST NOT be greater than 255 octets in size when encoded as UTF-8 πŸ’…
  • description: String|null (default: null) An optional long-form description of the AddressBook that gives context in shared environments where users need more than just the name 🌸
  • sortOrder: UnsignedInt (default: 0) Defines the sort order of AddressBooks when they're shown in the client's UI, so it's consistent across devices. The number MUST be an integer in the range 0 <= sortOrder < 2^31.

An AddressBook with a lower order is displayed before an AddressBook with a higher order in any list of AddressBooks in the client's UI. AddressBooks with equal order should be sorted alphabetically by name. The sorting should take locale-specific character order conventions into account πŸ“Ά

  • isDefault: Boolean (server-set) This SHOULD be true for exactly one AddressBook in any account, and it MUST NOT be true for more than one AddressBook within an account. The default AddressBook should be used by clients whenever they need to choose an AddressBook for the user within this account and they have no other information to go on. For example, if the user creates a new contact card, the client may automatically set the card as belonging to the default AddressBook from the user's primary account πŸ‘‘
  • isSubscribed: Boolean True if the user has indicated they want to see this AddressBook in their client. This SHOULD default to false for AddressBooks in shared accounts that the user has access to, and true for any new AddressBooks the user creates themself πŸ™ˆ

If false, the AddressBook and its contents SHOULD only be displayed when the user explicitly asks for them. The UI may offer the user the option of subscribing to it 🫣

  • shareWith: Id[AddressBookRights]|null (default: null) A map of the Principal id (Section 2 of [RFC9670]) to rights, for Principals this AddressBook is shared with. The Principal to which this AddressBook belongs MUST NOT be in this set. This is null if the AddressBook isn't shared with anyone, or if the server doesn't support [RFC9670]. The value may be modified only if the user has the "mayShare" right. The account id for the Principals may be found in the urn:ietf:params:jmap:principals:owner capability of the Account the AddressBook belongs to 🌈
  • myRights: AddressBookRights (server-set) The set of access rights the user has in relation to this AddressBook πŸ”

An AddressBookRights object has the following properties πŸŽ€

  • mayRead: Boolean The user may fetch the ContactCards in this AddressBook πŸ‘€
  • mayWrite: Boolean The user may create, modify, or destroy all ContactCards in this AddressBook, or move them to or from this AddressBook ✍️
  • mayShare: Boolean The user may modify the "shareWith" property for this AddressBook 🀝
  • mayDelete: Boolean The user may delete the AddressBook itself πŸ—‘οΈ

2.1. AddressBook/get

This is a standard "/get" method as described in Section 5.1 of [RFC8620]. The "ids" argument may be null to fetch everything at once 🧺

2.2. AddressBook/changes

This is a standard "/changes" method as described in Section 5.2 of [RFC8620]. πŸ¦‹

2.3. AddressBook/set

okay so this one is a standard "/set" method, just like Section 5.3 of [RFC8620] says, but it comes with two extra request arguments πŸ’…πŸŽ€

  • onDestroyRemoveContents: Boolean (default: false) If false, any attempt to destroy an AddressBook that still has a ContactCard in it gets rejected with an addressBookHasContents SetError πŸ™…β€β™€οΈ. If true, every ContactCard in that AddressBook gets removed from it, and if a ContactCard doesn't belong to any other AddressBook, it gets destroyed πŸ’€.
  • onSuccessSetIsDefault: Id|null If you give an id, and every create, update, and destroy (if there are any) succeeds with no errors, the server will try to make this AddressBook the default πŸ‘‘. (When you're referencing an AddressBook that's being created, it works like a creation-reference, so the id is the creation id with a "#" in front of it.)

If the id can't be found, or the server won't allow the change for policy reasons, it MUST be ignored and the current default AddressBook (if there is one) stays the default. No error comes back to the client in that case 🫢.

As per Section 5.3 of [RFC8620], if the default AddressBook gets changed successfully, any changed objects MUST be reported in either the created or updated argument in the response, as appropriate, with the server-set value included ✨.

The shareWith property can only be set by users who have the mayShare right πŸ”. When you're changing shareWith, you can't give a right to a Principal who didn't already have it, unless the user making the change also has that right. Any attempt to do that MUST be rejected with a forbidden SetError 🚫.

Users can subscribe or unsubscribe to an AddressBook by setting the isSubscribed property πŸ¦‹. The server MAY forbid users from subscribing to certain AddressBooks, even if they're allowed to see them, and it'll reject the update with a forbidden SetError πŸ’….

There's one extra SetError type for "destroy" 😭:

  • addressBookHasContents: The AddressBook has at least one ContactCard assigned to it, and the onDestroyRemoveContents argument was false.

3. ContactCards πŸ’–

A ContactCard object holds info about a person, a company, or some other entity, or it represents a group of those entities 🌸. It's a JSContact Card object as defined in Section 2 of [RFC9553], plus these extra properties:

  • id: Id (immutable; server-set) This is the id of the ContactCard. The id property MAY be different from the ContactCard's uid property (as defined in Section 2.1.9 of [RFC9553]). But there MUST NOT be more than one ContactCard with the same uid in an Account πŸ™…β€β™€οΈ.
  • addressBookIds: Id[Boolean] This is the set of AddressBook ids that this ContactCard belongs to πŸ“š. A card MUST belong to at least one AddressBook at all times (until it's destroyed). The set is an object, where each key is an AddressBook id. The value for each key in the object MUST be true βœ….

For any Media object in the card (see Section 2.6.4 of [RFC9553]), there's a new property πŸŽ€:

  • blobId: Id This is an id for the Blob that holds the binary contents of the resource.

When you're returning ContactCards, any Media with a URI that uses the "data:" URL scheme [RFC2397] SHOULD return a blobId property and leave out the uri property 🧚. This lets clients load the (potentially huge) image file only when they actually need it, and skips the overhead of Base64 encoding πŸ’œ. The mediaType property MUST also be set. Similarly, when creating or updating a ContactCard, clients MAY send a blobId instead of the uri property for a Media object πŸ“.

A contact card with a kind property equal to group represents a group of contacts πŸ‘―β€β™€οΈ. Clients often show these separately from other contact cards. The members property, as defined in Section 2.1.6 of [RFC9553], holds a set of uids (as defined in Section 2.1.9 of [RFC9553]) for the other contacts who are members of this group. Clients should consider the group to contain any ContactCard with a matching uid from any account they can access that supports the urn:ietf:params:jmap:contacts capability. Any uid that can't be found SHOULD be ignored but preserved 🫧. Here's an example: say a user adds contacts from a shared address book to their private group, and then temporarily loses access to that address book. The uids can't be resolved, so those contacts disappear from the group 😭. But if they get permission to access the data again, the uids are found and the contacts reappear πŸ₯Ή.

3.1. ContactCard/get

This is a standard "/get" method as described in Section 5.1 of [RFC8620] πŸ’….

3.2. ContactCard/changes

This is a standard "/changes" method as described in Section 5.2 of [RFC8620] πŸ¦‹.

3.3. ContactCard/query

This is a standard "/query" method as described in Section 5.5 of [RFC8620] πŸ”.

3.3.1. Filtering

A FilterCondition object has the following properties, and any of them can be left out 🧁:

  • inAddressBook: Id An AddressBook id. A card must be in this address book to match the condition.
  • uid: String A card must have this exact string as its uid (as defined in Section 2.1.9 of [RFC9553]) to match.
  • hasMember: String A card must have a members property (as defined in Section 2.1.6 of [RFC9553]) that contains this string as one of the uids in the set to match.
  • kind: String A card must have a kind property (as defined in Section 2.1.4 of [RFC9553]) that equals this string exactly to match.
  • createdBefore: UTCDate The created date-time of the ContactCard (as defined in Section 2.1.3 of [RFC9553]) must be before this date-time to match the condition βͺ.
  • createdAfter: UTCDate The created date-time of the ContactCard (as defined in Section 2.1.3 of [RFC9553]) must be the same as or after this date-time to match the condition ⏩.
  • updatedBefore: UTCDate The updated date-time of the ContactCard (as defined in Section 2.1.10 of [RFC9553]) must be before this date-time to match the condition.
  • updatedAfter: UTCDate The updated date-time of the ContactCard (as defined in Section 2.1.10 of [RFC9553]) must be the same as or after this date-time to match the condition.
  • text: String A card matches this condition if the text matches text in the card πŸ”Ž.
  • name: String A card matches this condition if the value of any NameComponent in the name property, or the full property inside the name property of the card (as defined in Section 2.2.1.2 of [RFC9553]), matches the value 🏷️.
  • name/given: String A card matches this condition if the value of a NameComponent with kind given inside the name property of the card (as defined in Section 2.2.1.2 of [RFC9553]) matches the value.
  • name/surname: String A card matches this condition if the value of a NameComponent with kind surname inside the name property of the card (as defined in Section 2.2.1.2 of [RFC9553]) matches the value.
  • name/surname2: String A card matches this condition if the value of a NameComponent with kind surname2 inside the name property of the card (as defined in Section 2.2.1.2 of [RFC9553]) matches the value.
  • nickname: String A card matches this condition if the name of any Nickname in the nicknames property of the card (as defined in Section 2.2.2 of [RFC9553]) matches the value 🎭.
  • organization: String A card matches this condition if the name of any Organization in the organizations property of the card (as defined in Section 2.2.3 of [RFC9553]) matches the value 🏒.
  • email: String A card matches this condition if the address or label of any EmailAddress in the emails property of the card (as defined in Section 2.3.1 of [RFC9553]) matches the value πŸ“§.
  • phone: String A card matches this condition if the number or label of any Phone in the phones property of the card (as defined in Section 2.3.3 of [RFC9553]) matches the value πŸ“ž.
  • onlineService: String A card matches this condition if the service, uri, user, or label of any OnlineService in the onlineServices property of the card (as defined in Section 2.3.2 of [RFC9553]) matches the value 🌐.
  • address: String A card matches this condition if the value of any AddressComponent in the addresses property, or the full property in the addresses property of the card (as defined in Section 2.5.1 of [RFC9553]) matches the value 🏑.
  • note: String A card matches this condition if the note of any Note in the notes property of the card (as defined in Section 2.8.3 of [RFC9553]) matches the value πŸ“.

If zero properties are specified on the FilterCondition, the condition MUST always evaluate to true πŸ’―. If multiple properties are specified, ALL must apply for the condition to be true. (That's the same as splitting the object into one-property conditions and making them all children of an AND filter operator 🧠.)

The exact semantics for matching String fields are deliberately not defined, so implementers have room to be flexible with how they index things 🧩. But there are a few rules:

  • Text SHOULD be matched in a case-insensitive manner πŸ”‘.
  • Text inside single or double quotes SHOULD be treated as a phrase search. That means a match is required for that exact sequence of words, not counting the surrounding quotation marks. Use \", \', and \\ to match a literal ", ', and \ respectively inside a phrase πŸ’¬.
  • Outside of a phrase, whitespace SHOULD be treated as dividing separate tokens, which can be searched for separately in the contact, but they MUST all be present for the contact to match the filter βœ‚οΈ.
  • Tokens MAY be matched on a whole-word basis using stemming (for example, a text search for bus would match "buses", but not "business") 🚌.

3.3.2. Sorting

The following values for the property field on the Comparator object MUST be supported for sorting πŸ“Š:

  • "created" - The created date on the ContactCard.
  • "updated" - The updated date on the ContactCard.

The following values for the property field on the Comparator object SHOULD be supported for sorting 🌈:

  • "name/given" - The value of the first NameComponent in the name property whose kind is given.
  • "name/surname" - The value of the first NameComponent in the name property whose kind is surname.
  • "name/surname2" - The value of the first NameComponent in the name property whose kind is surname2.

3.4. ContactCard/queryChanges

This is a standard "/queryChanges" method as described in Section 5.6 of [RFC8620] πŸ¦‹.

3.5. ContactCard/set

This is a standard "/set" method as described in Section 5.3 of [RFC8620] ✍️.

To set a new photo, the file has to be uploaded first, using the upload mechanism described in Section 6.1 of [RFC8620]. That gives the client a valid blobId, size, and type to use πŸ“Έ. The server MUST reject any attempt to set a file that isn't a recognised image type as the photo for a card 🚫.

3.6. ContactCard/copy

This is a standard "/copy" method as described in Section 5.4 of [RFC8620] πŸ’–.


4. Examples 🧚

For brevity, only the methodCalls property of the Request object and the methodResponses property of the Response object are shown in the following examples πŸŽ€.

4.1. Fetching Initial Data

Okay so a user has logged in and the client has grabbed the JMAP Session object πŸ’… It finds a single Account with the "urn:ietf:params:jmap:contacts" capability, id "a0x9", and it wants every address book and every contact. It might send this request:

[
  ["AddressBook/get", {
    "accountId": "a0x9"
  }, "0"],
  ["ContactCard/get", {
    "accountId": "a0x9"
  }, "1"]
]

Figure 1: "methodCalls" Property of a JMAP Request

The server might reply with something like this πŸŽ€:

[
  ["AddressBook/get", {
    "accountId": "a0x9",
    "list": [{
      "id": "062adcfa-105d-455c-bc60-6db68b69c3f3",
      "name": "Personal",
      "description": null,
      "sortOrder": 0,
      "isDefault": true,
      "isSubscribed": true,
      "shareWith": {
        "3f1502e0-63fe-4335-9ff3-e739c188f5dd": {
          "mayRead": true,
          "mayWrite": false,
          "mayShare": false,
          "mayDelete": false
        }
      },
      "myRights": {
        "mayRead": true,
        "mayWrite": true,
        "mayShare": true,
        "mayDelete": false
      }
    }, {
      "id": "cd40089d-35f9-4fd7-980b-ba3a9f1d74fe",
      "name": "Autosaved",
      "description": null,
      "sortOrder": 1,
      "isDefault": false,
      "isSubscribed": true,
      "shareWith": null,
      "myRights": {
        "mayRead": true,
        "mayWrite": true,
        "mayShare": true,
        "mayDelete": false
      }
    }],
    "notFound": [],
    "state": "~4144"
  }, "0"],
  ["ContactCard/get", {
    "accountId": "a0x9",
    "list": [{
      "id": "3",
      "addressBookIds": {
        "062adcfa-105d-455c-bc60-6db68b69c3f3": true
      },
      "name": {
        "components": [
          { "kind": "given", "value": "Joe" },
          { "kind": "surname", "value": "Bloggs" }
        ],
        "isOrdered": true
      },
      "emails": {
        "0": {
          "contexts": {
            "private": true
          },
          "address": "joe.bloggs@example.com"
        }
      }
    }],
    "notFound": [],
    "state": "ewarbckaqJ::112"
  }, "1"]
]

Figure 2: "methodResponses" Property of a JMAP Response

4.2. Changing the Default Address Book

Next up, the client tries to switch the default address book from "Personal" to "Autosaved" πŸ¦‹ and it makes no other change:

[
  ["AddressBook/set", {
    "accountId": "a0x9",
    "onSuccessSetIsDefault": "cd40089d-35f9-4fd7-980b-ba3a9f1d74fe"
  }, "0"]
]

Figure 3: "methodCalls" Property of a JMAP Request

The server allows it and sends back this response 🌸:

[
  ["AddressBook/set", {
    "accountId": "a0x9",
    "updated": {
      "cd40089d-35f9-4fd7-980b-ba3a9f1d74fe": {
        "isDefault": true
      },
      "062adcfa-105d-455c-bc60-6db68b69c3f3": {
        "isDefault": false
      },
      "oldState": "~4144",
      "newState": "~4148"
    }
  }, "0"]
]

Figure 4: "methodResponses" Property of a JMAP Response


5. Internationalisation Considerations ✨

Okay, this one is so important 🌈 Experience has shown that letting Unicode run totally wild can cause chaos: inconsistent rendering, users reading text differently than intended, and weird results when copying text from one place to another πŸ’€ Servers MAY choose to mitigate this by restricting the set of characters allowed in otherwise unconstrained String fields. The FreeformClass, as documented in Section 4.3 of [RFC8264], might be a good starting point for this πŸ’œ

Setting a value with code points outside the permissible set can be handled a few ways by the server. The server could strip the forbidden characters, or replace them with U+FFFD (the Unicode replacement character), and store the resulting string. This is likely to be appropriate for non-printable characters, such as the "Control Codes" defined in Section 23.1 (https://www.unicode.org/versions/latest/core-spec/chapter-23/#G20365) of [UNICODE], excluding newline (U+000A), carriage return (U+000D), and tab (U+0009). These can sneak into data by accident through copy-and-paste and are invisible to the end user πŸ™ˆ JMAP lets the server transform data on create/update as long as any changed properties are returned to the client in the "/set" response, so it knows what changed, as per Section 5.3 of [RFC8620]. Alternatively, the server MAY just reject the create/update with an "invalidProperties" SetError.


6. Security Considerations πŸ”₯

Okay, security is the main event here bestie 😭 All security considerations of JMAP [RFC8620] apply to this specification. Additional considerations specific to the data types and functionality introduced by this document are described in the following subsection.

Contacts are almost entirely private, personally identifiable information, and they represent the social connections of users. Privacy leaks can have real-world consequences, so contact servers and clients MUST be mindful of the need to keep all data secure πŸ”’

Servers MUST enforce the Access Control Lists (ACLs) set on address books to ensure only authorised data is shared πŸ‘‘


7. IANA Considerations πŸ“‹

7.1. JMAP Capability Registration for "contacts"

IANA has registered "contacts" in the "JMAP Capabilities" registry as follows:

Capability Name:  urn:ietf:params:jmap:contacts
Intended Use:  common
Change Controller:  IETF
Security and Privacy Considerations:  this document, Section 6
Reference:  this document

7.2. JMAP Data Type Registration for "AddressBook"

IANA has registered "AddressBook" in the "JMAP Data Types" registry as follows:

Type Name:  AddressBook
Can Reference Blobs:  No
Can Use for State Change:  Yes
Capability:  urn:ietf:params:jmap:contacts
Reference:  this document

7.3. JMAP Data Type Registration for "ContactCard"

IANA has registered "ContactCard" in the "JMAP Data Types" registry as follows:

Type Name:  ContactCard
Can Reference Blobs:  Yes
Can Use for State Change:  Yes
Capability:  urn:ietf:params:jmap:contacts
Reference:  this document

7.4. JMAP Error Codes Registry

The following subsection has registered a new error code in the "JMAP Error Codes" registry, as defined in Section 9 of [RFC8620].

7.4.1. addressBookHasContents

JMAP Error Code:  addressBookHasContents
Intended Use:  common
Change Controller:  IETF
Description:  The AddressBook has at least one ContactCard assigned
   to it, and the "onDestroyRemoveContents" argument was false.
Reference:  This document, Section 2.3

7.5. JSContact Property Registrations

IANA has registered the following additional properties in the "JSContact Properties" registry, as defined in Section 3 of [RFC9553].

7.5.1. id

Property Name:  id
Property Type:  not applicable
Property Context:  Card
Intended Usage:  reserved
Since Version:  1.0
Change Controller:  IETF
Reference:  this document

7.5.2. addressBookIds

Property Name:  addressBookIds
Property Type:  not applicable
Property Context:  Card
Intended Usage:  reserved
Since Version:  1.0
Change Controller:  IETF
Reference:  this document

7.5.3. blobId

Property Name:  blobId
Property Type:  not applicable
Property Context:  Media
Intended Usage:  reserved
Since Version:  1.0
Change Controller:  IETF
Reference:  this document

8. References πŸ“š

8.1. Normative References

[RFC2119]  Bradner, S., "Key words for use in RFCs to Indicate
           Requirement Levels", BCP 14, RFC 2119,
           DOI 10.17487/RFC2119, March 1997,
           <https://www.rfc-editor.org/info/rfc2119>.

[RFC2397]  Masinter, L., "The "data" URL scheme", RFC 2397,
           DOI 10.17487/RFC2397, August 1998,
           <https://www.rfc-editor.org/info/rfc2397>.

[RFC8174]  Leiba, B., "Ambiguity of Uppercase vs Lowercase in RFC
           2119 Key Words", BCP 14, RFC 8174, DOI 10.17487/RFC8174,
           May 2017, <https://www.rfc-editor.org/info/rfc8174>.

[RFC8620]  Jenkins, N. and C. Newman, "The JSON Meta Application
           Protocol (JMAP)", RFC 8620, DOI 10.17487/RFC8620, July
           2019, <https://www.rfc-editor.org/info/rfc8620>.

[RFC9553]  Stepanek, R. and M. Loffredo, "JSContact: A JSON
           Representation of Contact Data", RFC 9553,
           DOI 10.17487/RFC9553, May 2024,
           <https://www.rfc-editor.org/info/rfc9553>.

[RFC9670]  Jenkins, N., Ed., "JSON Meta Application Protocol (JMAP)
           Sharing", RFC 9670, DOI 10.17487/RFC9670, November 2024,
           <https://www.rfc-editor.org/info/rfc9670>.

8.2. Informative References

[RFC8264]  Saint-Andre, P. and M. Blanchet, "PRECIS Framework:
           Preparation, Enforcement, and Comparison of
           Internationalized Strings in Application Protocols",
           RFC 8264, DOI 10.17487/RFC8264, October 2017,
           <https://www.rfc-editor.org/info/rfc8264>.

[UNICODE]  The Unicode Consortium, "The Unicode Standard",
           <https://www.unicode.org/versions/latest/>.

Author's Address

Neil Jenkins (editor)
Fastmail
PO Box 234, Collins St West
Melbourne  VIC 8007
Australia
Email: neilj@fastmailteam.com
URI:   https://www.fastmail.com
πŸ“¦ where this page comes from