There are many situations in which an Identity is interested in an IdentityAttribute or a RelationshipAttribute of another Identity, for example:

  • A company must know the age of a customer in order to carry out an age check if they want to purchase alcohol or other age-restricted goods.
  • A company needs the street address of a customer so that it can send them an invoice after the customer has made a purchase from the company.
  • An organization is interested in the birth date of a member so that it can wish them a happy birthday every year.
  • A university needs to know the email address of a student in order to be able to send them emails.

In this guide, we explain how a Connector, hereinafter referred to as the Sender, can read an Attribute of another Connector, the so-called Recipient. Since understanding this reading process requires knowledge about Requests and how to use them in general, you should take a look at our Request and Response introduction before continuing reading this guide.

Please note that the general procedure is the same if the Connector wants to read an Attribute of an App user instead of another Connector. For reasons of clarity, this guide focuses on the reading process with two Connectors.

Request for reading Attributes

The Sender wants to read an Attribute of the Recipient. To do this, the Sender must first create a suitable Request, which it can then send to the Recipient. In the following subsections, we describe the general appearance of a Request for reading Attributes.

Role of ReadAttributeRequestItem

For reading a single Attribute, the Sender needs to insert a single RequestItem of type ReadAttributeRequestItem into the items property of the Request. The input it has to provide for the query property of the ReadAttributeRequestItem depends on what type of Attribute it wants to get. If the Sender wants to read an IdentityAttribute, it can use an appropriate IdentityAttributeQuery. Only IdentityAttributes that are owned by the Recipient can be requested by the Sender. It makes no sense for the Sender to request a RelationshipAttribute from the Recipient that already exists in the context of their Relationship to each other. However, the Sender may want to create a RelationshipAttribute for this Relationship whose value is set by the Recipient. This can be done by using a RelationshipAttributeQuery.

The Sender can use a ReadAttributeRequestItem to create a RelationshipAttribute in the context of a Relationship between itself and the Recipient if it wants the RelationshipAttributeValue to be set by the Recipient. Even if it seems misleading to use a ReadAttributeRequestItem to create a RelationshipAttribute, this terminology makes sense insofar as the RelationshipAttributeValue should be read from the Recipient in order to be able to create it.

Note that the Sender cannot explicitly specify the Recipient’s address as the value for the owner property of the RelationshipAttributeQuery because the address does not have to be known beforehand. This is the case if the Request is sent via a RelationshipTemplate and not via a Message. Therefore, an empty string must be specified as the owner instead if the Sender wants the RelationshipAttribute to be owned by the Recipient. If the Sender is interested in a RelationshipAttribute that the Recipient has in the context of a Relationship with a third party, a ThirdPartyRelationshipAttributeQuery can be used. In addition, it is also permitted to specify an IQLQuery for the query property of the ReadAttributeRequestItem.

Combinations and usage scenarios of ReadAttributeRequestItem

The following table provides an overview of the possible kinds of Attributes that the Sender can read from the Recipient using the ReadAttributeRequestItem. It must be taken into account whether the Attribute is an IdentityAttribute or a RelationshipAttribute and which Identity is its owner. If the Sender wants to read a RelationshipAttribute from the Recipient, a distinction must be made between which Identities the Relationship in question exists.

Type and context Owner Possible? Automation Remarks, reasons and examples
IdentityAttribute Sender N/A It makes no sense for the Sender to read IdentityAttributes that are owned by itself. Instead, it can create IdentityAttributes for itself.
IdentityAttribute Recipient USER_DECISION Example: A company asks a customer for their delivery address.
IdentityAttribute Third party N/A An IdentityAttribute that is owned by a third party cannot be shared by the Recipient.
RelationshipAttribute that exists in the context of the Relationship between the Sender and the Recipient Sender USER_DECISION With this combination, the Sender gives the Recipient the one-time permission to create a RelationshipAttribute that exists in the context of their Relationship and that is owned by the Sender.
Example: An electricity provider asks a new customer for their electricity meter number.
RelationshipAttribute that exists in the context of the Relationship between the Sender and the Recipient Recipient USER_DECISION With this combination, the Sender gives the Recipient the one-time permission to create a RelationshipAttribute that exists in the context of their Relationship and that is owned by the Recipient.
Example: A company asks a customer if they want to subscribe to its newsletter.
RelationshipAttribute that exists in the context of a Relationship between the Recipient and a third party Recipient ✓ or ✗ -
depending on confidentiality
USER_DECISION If its confidentiality is not "private", the Sender is able to request to read an existing RelationshipAttribute that exists in a Relationship between the Recipient and a third party and that is owned by the Recipient.
Example: A social network asks for the Facebook privacy settings of a user to get senseful defaults of its own privacy settings.
RelationshipAttribute that exists in the context of a Relationship between the Recipient and a third party Third party ✓ or ✗ -
depending on confidentiality
USER_DECISION If its confidentiality is not "private", the Sender is able to request to read an existing RelationshipAttribute that exists in a Relationship between the Recipient and a third party and that is owned by the third party.
Example: An online shop asks for the Payback customer ID of a user to book the order on their account.

Example of reading an IdentityAttribute

We assume that the Sender wants to read an IdentityAttribute of type EMailAddress of the Recipient. To do this, it inserts the corresponding IdentityAttributeQuery into the query property of the ReadAttributeRequestItem, which is contained within the items property of the Request for reading Attributes. In our example, we have chosen to set the value of the mustBeAccepted property of the ReadAttributeRequestItem to true.

{
  "@type": "Request",
  "items": [
    {
      "@type": "ReadAttributeRequestItem",
      "mustBeAccepted": true,
      "query": {
        "@type": "IdentityAttributeQuery",
        "valueType": "EMailAddress"
      }
    }
  ]
}

Example of reading a RelationshipAttribute without a third party involved

We now consider the case that the Sender has an active Relationship established with the Recipient and that it wants to create a RelationshipAttribute for this Relationship whose value is read from the Recipient. Then the associated ReadAttributeRequestItem, which is contained in the items property of the Request for reading Attributes created by the Sender, must contain an appropriate RelationshipAttributeQuery in its query property. For example, if the Sender wants to request a RelationshipAttribute of type ProprietaryString that is owned by the Recipient and whose confidentiality is "public", the Request could look like this:

{
  "@type": "Request",
  "items": [
    {
      "@type": "ReadAttributeRequestItem",
      "mustBeAccepted": true,
      "query": {
        "@type": "RelationshipAttributeQuery",
        "key": "<key of RelationshipAttribute>",
        "owner": "",
        "attributeCreationHints": {
          "title": "<title of RelationshipAttribute>",
          "valueType": "ProprietaryString",
          "confidentiality": "public"
        }
      }
    }
  ]
}

Note that an empty string must be specified as the value for the owner property of the RelationshipAttributeQuery if the Sender wants the requested RelationshipAttribute to be owned by the Recipient and that the <...> notation is used as a placeholder for the actual data as usual.

Example of reading a RelationshipAttribute with a third party involved

If the Sender has established an active Relationship with the Recipient and the Recipient has also established an active Relationship with a third party, the Sender can request to read RelationshipAttributes that exist in the context of the Relationship between the Recipient and the third party. To do this, a corresponding ThirdPartyRelationshipAttributeQuery must be used. The Sender inserts it into the query property of the ReadAttributeRequestItem, which is contained within the items property of the Request for reading Attributes. For example, if the Sender wants to request a RelationshipAttribute that is owned by the Recipient and that exists in the context of the Relationship between the Recipient and a specific third party, the Request could look like this:

{
  "@type": "Request",
  "items": [
    {
      "@type": "ReadAttributeRequestItem",
      "mustBeAccepted": true,
      "query": {
        "@type": "ThirdPartyRelationshipAttributeQuery",
        "key": "<key of RelationshipAttribute>",
        "owner": "recipient",
        "thirdParty": ["<address of third party>"]
      }
    }
  ]
}

Note that the string "recipient" must be specified as the value for the owner property of the ThirdPartyRelationshipAttributeQuery if the Sender wants the requested RelationshipAttribute to be owned by the Recipient. RelationshipAttributes that exist in the context of the Relationship between the Recipient and the third party and whose confidentitality is "private" cannot be sent by the Recipient to the Sender.

Read multiple Attributes

Requesting read access is not limited to just a single Attribute, but it is possible to request read access to multiple Attributes at the same time. Several ReadAttributeRequestItems or suitable RequestItemGroups can be inserted into the items property of the Request for reading Attributes for this purpose. If you want to use a RequestItemGroup in order to request read access to multiple Attributes of the Recipient at the same time, you must insert corresponding ReadAttributeRequestItems into the items property of it.

Send and receive the Request

The Sender that wants to read an Attribute of the Recipient may or may not already have a Relationship with the Recipient. Depending on which is the case, a different method can be used to send the Request for reading Attributes. There are two ways to send the Request for reading Attributes created by the Sender to the Recipient.

Request via RelationshipTemplate

If there is currently no Relationship between the Sender and the Recipient, this approach must be used. But it is also possible for the Sender to use a RelationshipTemplate to send a Request to the Recipient if there is already an active Relationship between them. All details on how to send and receive a Request via a RelationshipTemplate in general can be found in the Requests via RelationshipTemplates guide.

Request via Message

The Sender only has the option of sending a Request to the Recipient via a Message if there is already an active Relationship between them. All information on how to send and receive a Request via a Message can be found in the Requests via Messages guide.

Accept the Request

After the Recipient has received the Request for reading Attributes, it can accept it to give the Sender read access to all or some of the requested Attributes. To do this, proceed as described in the Accept incoming Request use case documentation and specify the id of the received Request. You must also decide and specify for each ReadAttributeRequestItem contained in the Request for reading Attributes whether you want to accept or reject it.

If the Recipient does not want the Sender to read any of its Attributes and, therefore, does not want to accept the Request for reading Attributes of the Sender, it can reject it as a whole as well. For this, follow the instructions of the Reject incoming Request use case.

Accept a ReadAttributeRequestItem

If the Recipient agrees to share a requested Attribute with the Sender, it can accept the associated ReadAttributeRequestItem contained in the Request for reading Attributes. In particular, it must then provide the Attribute requested via the query property of the ReadAttributeRequestItem for its Response to the Request. Depending on whether the Recipient wants to share an Attribute that already exists as a LocalAttribute or that has to be created first, different AcceptReadAttributeRequestItemParameters must be used for this. As already indicated, a RelationshipAttributeQuery can only be validly answered with a new Attribute, and a ThirdPartyRelationshipAttributeQuery can only be validly answered with an existing Attribute.

Otherwise, the error code error.consumption.requests.invalidAcceptParameters arises. Furthermore, an error with the code error.consumption.requests.attributeQueryMismatch is thrown if the Attribute provided by the Recipient does not match the AttributeQuery specified in the query property of the ReadAttributeRequestItem.

Accepting a ReadAttributeRequestItem with a new Attribute or an existing, that isn’t shared with the Sender already neither itself nor any of its predecessing versions, leads to the creation of a LocalAttribute with a LocalAttributeShareInfo contained within its shareInfo property, whose underlying content is given by the shared Attribute. An appropriate AcceptResponseItem of type ReadAttributeAcceptResponseItem is generated, which incorporates the id of the LocalAttribute with the LocalAttributeShareInfo in its attributeId property and the shared Attribute in its attribute property. If a new IdentityAttribute is to be shared, a corresponding LocalAttribute without a LocalAttributeShareInfo will additionally be created for the Recipient beforehand.

If the ReadAttributeRequestItem is accepted with an existing Attribute that the Recipient already shared with the Sender, an AttributeAlreadySharedAcceptResponseItem will be generated, given that the own shared LocalAttribute doesn’t have "DeletedByPeer" or "ToBeDeletedByPeer" as deletionInfo.deletionStatus. Instead of creating a further own shared/peer shared Attribute pair, the id of the already existing shared LocalAttributes is returned. Note that the id of the shared Attribute of the Sender matches the id of the corresponding shared Attribute of the Recipient.

Lastly, if the ReadAttributeRequestItem is accepted with an existing Attribute of which the Recipient already shared a predecessor with the Sender, an AttributeSuccessionAcceptResponseItem will be generated, given that the own shared predecessor doesn’t have "DeletedByPeer" or "ToBeDeletedByPeer" as deletionInfo.deletionStatus. Instead of creating an independent own shared/peer shared Attribute pair, internally an Attribute succession is performed. The id of the already existing shared LocalAttribute predecessor is returned, as well as the id and content of the newly created successor. When the Sender of the Request receives the AttributeSuccessionAcceptResponseItem, the according succession is automatically performed for them.

In any case, the respective AcceptResponseItem will be included in the items property of the Response to the Request for reading Attributes that will be transferred to the Sender.

Reject a ReadAttributeRequestItem

Even if the Recipient accepts the Request for reading Attributes as a whole, it may decide not to share every requested Attribute with the Sender. To be more precise, the Recipient has the option of rejecting ReadAttributeRequestItems that have the value false specified in their mustBeAccepted property. To reject a ReadAttributeRequestItem, use the RejectRequestItemParameters. The rejection of a ReadAttributeRequestItem leads to the creation of a ResponseItem of type RejectResponseItem. This will be contained within the items property of the Response to the Request for reading Attributes.

Example of accepting a RequestItemGroup

Let’s look at an example where the Sender is interested in the Recipient’s BirthDate and contact information in the form of an EMailAddress or a PhoneNumber. To ask the Recipient for this data, the Sender creates a Request for reading Attributes, which contains a ReadAttributeRequestItem belonging to the BirthDate and a RequestItemGroup belonging to the contact information in its items property. The RequestItemGroup itself contains two ReadAttributeRequestItems in its items property, namely one for the EMailAddress and one for the PhoneNumber.

{
  "@type": "Request",
  "items": [
    {
      "@type": "ReadAttributeRequestItem",
      "mustBeAccepted": false,
      "query": {
        "@type": "IdentityAttributeQuery",
        "valueType": "BirthDate"
      }
    },
    {
      "@type": "RequestItemGroup",
      "items": [
        {
          "@type": "ReadAttributeRequestItem",
          "mustBeAccepted": true,
          "query": {
            "@type": "IdentityAttributeQuery",
            "valueType": "EMailAddress"
          }
        },
        {
          "@type": "ReadAttributeRequestItem",
          "mustBeAccepted": false,
          "query": {
            "@type": "IdentityAttributeQuery",
            "valueType": "PhoneNumber"
          }
        }
      ]
    }
  ]
}

In our example, the Sender only requires the Recipient to share its EMailAddress, which is why the individual ReadAttributeRequestItems within the Request have specified corresponding values in their mustBeAccepted property. We assume that the Recipient wants to accept the Request and only wants to share its EMailAddress, which is already saved as an appropriate LocalAttribute, with the Sender.

If the Recipient wants to accept the Request for reading Attributes, it must accept all ReadAttributeRequestItems for which the mustBeAccepted property is set to true. It is therefore not permitted, for example, for the Recipient to refuse to share its EMailAddress and instead share its PhoneNumber.

The Recipient refuses to share its BirthDate with the Sender and accepts at least one ReadAttributeRequestItem of the RequestItemGroup. Also, the Recipient accepts the sharing of its EMailAddress and rejects the sharing of its PhoneNumber. Thus, it responds to the Request for reading Attributes as follows:

{
  "items": [
    {
      // Reject sharing of BirthDate
      "accept": false
    },
    {
      "items": [
        {
          // Accept sharing of existing EMailAddress
          "accept": true,
          "existingAttributeId": "<ID of LocalAttribute of EMailAddress>"
        },
        {
          // Reject sharing of PhoneNumber
          "accept": false
        }
      ]
    }
  ]
}

Note that it is important to respond to RequestItems, some of which may be contained in a RequestItemGroup, in the same order in which they were received.

Get the Attributes

We now assume that the Recipient has accepted the Request for reading Attributes of the Sender. In order for the Sender to receive the Response of the Recipient, it needs to synchronize the updates of the Backbone. Please note that this synchronization can also be automated by using the Sync Module.

To view the Response to the Request, search for it in the synchronization result or proceed as described in the Query outgoing Requests use case documentation and use the following query parameter:

The Integrator of the Sender can now get the Response of the Recipient from the response.content property of the result. In particular, each requested and shared Attribute that belongs to an accepted ReadAttributeRequestItem can be read from a corresponding ReadAttributeAcceptResponseItem within the items property of the Response. Internally, the shared attribute that can be read from the ReadAttributeAcceptResponseItem is used to create an appropriate LocalAttribute with a LocalAttributeShareInfo of the Sender. On the other hand, there is a corresponding RejectResponseItem in the items property of the Response for each rejected ReadAttributeRequestItem.

In case of an error, ErrorResponseItems can also be included in the Response. If the Request for reading Attributes contains a RequestItemGroup in its items property, the Response to this Request contains a corresponding ResponseItemGroup in its items property.

What’s next?

Take a look at our Integration example if you want to see how an Attribute of a peer is read by an Identity in the context of a larger process. Also note that it is not only possible to request the reading of an Attribute from a peer, but that you can share an Attribute with a peer as well. Consult the Share Attributes with peer guide for this.