This guide explains how to send and receive a Request over enmeshed Messages using two Connectors. The first of them, which we will refer to as the Sender, will send the Request. The second, which we will refer to as the Recipient, can decide, whether they want to accept or reject the Request. We’ll go through the steps of validating and creating the Request, sending and receiving it, and finally accepting or rejecting the Request.

This guide assumes that you already have an active Relationship between the two Connectors, e.g. from following the Integration Example or the scenario page Requests over Templates. If that is not the case, either take a look at those guides first or follow the instructions of how to establish a Relationship to another Identity.

In order to send a Message to the Recipient, it is required to know their enmeshed Address. To retrieve it, the Sender can query their Relationships and look for the right one.

[
  // ...
  {
    "id": "REL..",
    "status": "Active",
    // ...
    "peer": "id1..."
  }
]

Look for the correct Relationship and save its peer property. You are going to need it later.

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, checkout our Request and Response Introduction.

Even though the peer property is optional, it is recommended to specify it whenever possible. This allows additional validation rules to execute. If you are sending a Request over Message, you’ll always know the peer, as it is the recipient of the Message.

{
  "content": {
    "items": [
      {
        "@type": "AuthenticationRequestItem",
        "mustBeAccepted": true,
        "title": "The Sender is asking for an authentication."
      }
    ]
  },
  "peer": "<the address of the Recipient Connector>"
}

Create the Request

If the previous step was successful, you can create the Request. For this, use the same payload you just validated.

In the response, you can see that the Request currently has the status Draft. Also, note that the content was extented by the @type property and a generated id, that you didn’t have to specify manually.

Example response:

{
  "id": "REQ...",
  "isOwn": true,
  "peer": "<the address of the Recipient Connector>",
  "createdAt": "<time-of-creation>",
  "content": {
    "@type": "Request",
    "id": "REQ...",
    "items": [
      {
        "@type": "AuthenticationRequestItem",
        "mustBeAccepted": true,
        "title": "The Sender is asking for an authentication."
      }
    ]
  },
  "status": "Draft"
}

Save the complete content of the response. You will need it in the next step.

Send the Request

Now let’s transmit the Request to the Recipient. To do so, send a Message using the following payload and make sure to use the content you copied from the response, which has the @type property. This is important for the Request to be processed correctly, since it is possible to send different types of objects via Message.

{
  "recipients": ["<the address of the Recipient Connector>"],
  "content": {
    // the content you copied from the response in the step before
  }
}

This is where the automation of the enmeshed Runtime steps in and moves the Request from status Draft to status Open. You can observe this behaviour by querying the Request on the Sender Connector.

Fetch the Request

In order to fetch the Message with the Request, you have to synchronize the Recipient Connector. The enmeshed Runtime will read the Message and create a new incoming Request. You can observe this by long polling the incoming Requests and optionally use the query params source.reference=<id-of-the-message> and status=ManualDecisionRequired to filter for Requests that belong to the Message that contained the Request.

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 to help you automating your business process are supported by enmeshed, check out our Event introduction.

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

Answer the Request

Accept

Firstly, let’s consider the case the Recipient wants to accept the Request. For this, use the id of the Request you saved in the 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
    }
  ]
}

Note that if you have multiple RequestItems or RequestItemGroups, they must be accepted in the exact order they were specified in in the Request.

Reject

Now, 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
    }
  ]
}

Runtime automation

No matter if you accepted or rejected the Request, the response will be similar. You can see that the Request moved to status Decided. This is where the enmeshed Runtime steps in and handles the Request based on you decision. It will move the Request to status Completed and send the Response to the Sender via a Message. This behavior can be observed by querying the Request again after a few seconds.

Sync the Response

The Sender will receive the Response via a Message. For this, you have to synchronize the Sender Connector.

After a few seconds the Request has moved to status Completed and the Response is available in the response property of the Request. You can observe this by querying the Request on the Sender Connector.