This guide will explain the end-to-end flow of sharing and answering a Request via a RelationshipTemplate. Usually, this flow happens between a Connector and the App, but for simplicity and more transparency we will use two Connectors in this example. Thus, you’ll need two Connectors, that either already have a Relationship with each other or not yet.

You can use the Connector Installation Guide if you need help setting up the Connectors.

On the first Connector, which we will refer to as the Sender, you will create the Request and the RelationshipTemplate. The second Connector, which we will refer to as the Recipient, will receive the RelationshipTemplate and respond to the Request.

Check your Request’s validity

Firstly, you should check if your Request is valid. As an example, we use a Request with just an AuthenticationRequestItem, but you can use any Request you want. For an overview of the available RequestItems, check out our Request and Response introduction.

{
  "content": {
    "items": [
      {
        "@type": "AuthenticationRequestItem",
        "mustBeAccepted": true,
        "title": "The Sender is asking for an authentication."
      }
    ]
  }
}

Even though the Requests are validated during the RelationshipTemplate creation you should not skip this step as it gives you additional information in case of validation errors.

Create the RelationshipTemplate

Next, create a RelationshipTemplate on the Sender Connector, using a RelationshipTemplateContent. If there is no Relationship between the Connectors, yet, you must put the content property of the payload of the previous step in the onNewRelationship property of the RelationshipTemplateContent. However, if the Connectors already have a Relationship with each other, you must put it in the onExistingRelationship property of the RelationshipTemplateContent. But note, that the onNewRelationship property is required and must, therefore, always be set.

{
  "maxNumberOfAllocations": 1,
  "expiresAt": "2025-01-01T00:00:00.000Z",
  "content": {
    "@type": "RelationshipTemplateContent",
    "title": "Requests via RelationshipTemplates example",
    "onNewRelationship": {
      // the content property of the payload of the previous step,
      // if the Connectors don't have a Relationship with each other, yet
      ...
    },
    "onExistingRelationship": {
      // the content property of the payload of the previous step,
      // if the Connectors already have a Relationship with each other
      ...
    }
  }
}

You will receive a response with the complete RelationshipTemplate.

{
  "id": "RLT..",
  // ...
  "truncatedReference": "UkxU..."
}

Save the truncatedReference and the id of the RelationshipTemplate. You will need them in the next steps.

Load the RelationshipTemplate and get the Request

Now you have to load the RelationshipTemplate on the Recipient Connector using the following payload:

{
  "reference": "<truncated reference of RelationshipTemplate>"
}

This will trigger a process in the enmeshed Runtime, which will create a new incoming Request. You can observe this by long polling the incoming Requests and optionally use the query parameters source.reference=<ID of the RelationshipTemplate> and status=ManualDecisionRequired to filter for Requests that belong to the RelationshipTemplate you are currently working on.

In a productive environment, however, we recommend using the Sync module and waiting for a consumption.incomingRequestReceived Connector Event. To learn more about events, how to use them in the context of enmeshed and which modules are supported by enmeshed to help you automating your business process, check out our Event introduction.

After you received the Request, save its id for the next step.

Answer the Request

If you want to test the full flow, we recommend to reject the Request first. Afterwards, you can create a new one by loading the RelationshipTemplate again and accept it.

Reject

Let’s consider the case the Recipient wants to reject the Request. For this, use the id of the Request you saved in the previous step. In the payload you have to reject all RequestItems. In case of the example Request, the payload is the following:

{
  "items": [
    {
      "accept": false
    }
  ]
}

In the response you can see that the Request has moved to status "Decided". This is where the enmeshed Runtime steps in and handles the Request based on your decision. It creates a Response with the appropriate RejectResponseItems and returns it to the Sender of the Request. Then, it will move the Request to status "Completed". This can be observed by querying the Request again after a few seconds.

Accept

If you tried out the rejection before this step, make sure to create a new Request by loading the RelationshipTemplate again with the same truncatedReference.

To accept the Request, you need its id that you saved in a previous step. In the payload you have to accept at least all RequestItems where the mustBeAccepted property is set to true. In case of the example Request, the payload is the following:

{
  "items": [
    {
      "accept": true
    }
  ]
}

In the response you can see the Request has moved to status "Decided". This behavior can be observed by querying the Request again after a few seconds. Now, the enmeshed Runtime steps in and handles the Request based on your decision. The Response is created with the appropriate ResponseItems.

If there is already an active Relationship between the Connectors, the Response will be sent back to the Sender via a Message and the Request will move to status "Completed". The Sender, then, can fetch it by synchronizing the updates of the Backbone.

However, if there is no active Relationship between the Connectors, yet, a Relationship will be created, which has the status "Pending" for now. It contains a RelationshipChangeRequest with a content of type RelationshipCreationChangeRequestContent, that in turn contains the Response to the Request. This Relationship will be sent back to the Sender via a Message. Then, the Request will be set to status "Completed" and you can query the Relationship using the query parameter template.id=<ID of the RelationshipTemplate>. Until the RelationshipChangeRequest is answered, no new Request will be created by loading the RelationshipTemplate.

The Sender can fetch the Relationship by synchronizing the updates of the Backbone. In the response you will see a new Relationship, which looks as follows:

{
  "id": "REL...",
  "template": {
    // ...
  },
  "status": "Active",
  "peer": "id1...",
  // ...
  "changes": [
    {
      "id": "RCH...",
      "request": {
        "createdBy": "id1...",
        "createdByDevice": "DVC...",
        "createdAt": "<time of creation>",
        "content": {
          "@type": "RelationshipCreationChangeRequestContent",
          "response": {
            "items": [
              {
                "@type": "AcceptResponseItem",
                "result": "Accepted"
              }
            ],
            "requestId": "REQ...",
            "result": "Accepted"
          }
        }
      },
      "status": "Accepted",
      "type": "Creation"
      // ...
    }
  ]
}

Save the id of the Relationship and of the RelationshipChange to accept the RelationshipChange.

Now you can accept the RelationshipChange on the Sender Connector with the id of the Relationship and the id of the RelationshipChange.

When you synchronize the Recipient Connector, you can see that the Relationship now has the status "Active" on both Connectors.