Requests via RelationshipTemplates
This guide explains the end-to-end flow of sending a Request via a RelationshipTemplate and responding to it. Usually, this flow happens between a Connector and the App, but for simplicity and more transparency, two Connectors are used here. To try out the examples in this guide on your own, you therefore need two Connectors.
You can use the Connector Setup guide if you need help installing the Connectors. Since understanding the process of sending a Request via a RelationshipTemplate requires knowledge about Requests in general, you should also take a look at our Request and Response introduction.
On the first Connector, which is referred to as the Sender, you construct the Request and create the RelationshipTemplate that contains the Request. The second Connector, which is referred to as the Recipient, receives the Request by loading the RelationshipTemplate. The Recipient then responds to the Request. Note that the Sender and the Recipient may or may not have already established a Relationship at the beginning.
A RelationshipTemplate is generally used to establish a Relationship between two Identities. A Request can be sent in this process of establishing a Relationship. Nevertheless, a RelationshipTemplate can also be used to exchange Requests between Identities that have already established a Relationship. For more information on how to establish Relationships, refer to the Establish Relationships scenario documentation.
Check the Request’s validity
The Sender wants to construct a Request that it can send to the Recipient by inserting it into a RelationshipTemplate.
Before the RelationshipTemplate is created, the Sender should first check the Request’s validity by proceeding as described in the documentation of the Check if outgoing Request can be created use case.
To do this, the Request must be specified in the content
property of the payload.
In this guide, an example Request is given that contains only a single AuthenticationRequestItem within its items
property. However, you can use any Request that suits you.
{
"content": {
// Specification of a Request
"title": "Example of a Request",
"items": [
{
"@type": "AuthenticationRequestItem",
"mustBeAccepted": true,
"title": "The Sender is asking for an authentication"
}
]
}
}
If a Request is contained within a RelationshipTemplate, its validity is automatically checked when the RelationshipTemplate is created. The RelationshipTemplate cannot be created if the Request is faulty. Nevertheless, the Request’s validity should be checked before attempting to create the RelationshipTemplate in order to obtain additional information about the reasons for the error in the case of a faulty Request.
Create the RelationshipTemplate
Next, the Sender wants to create the RelationshipTemplate, which contains the Request it wants to send to the Recipient. To specify a Request within a RelationshipTemplate, a data object of type RelationshipTemplateContent must be used within the content
property of the RelationshipTemplate.
A Request can be specified in the onNewRelationship
property or the onExistingRelationship
property of the RelationshipTemplateContent.
If no Relationship has yet been established between the Sender and the Recipient, the Recipient will receive the Request specified in the onNewRelationship
property when loading the RelationshipTemplate.
However, if an active Relationship already exists, the Recipient will receive the Request specified in the onExistingRelationship
property, if such is specified. The specification of a Request in the onNewRelationship
property is mandatory in contrast to the specification of a Request in the onExistingRelationship
property.
Note that the same Request can be specified in the onExistingRelationship
property as in the onNewRelationship
property, but a different Request can also be used.
These customization options are useful as the Recipient that loads the RelationshipTemplate may not be known in advance.
It is therefore possible that a Relationship between the Sender and the Recipient already exists or not.
In addition, it is possible to configure the RelationshipTemplate in such a way that it can be loaded by multiple Identities.
The creator of the RelationshipTemplate may have a Relationship to some of these Identities and none to others.
To create a RelationshipTemplate, the instructions of the Create own RelationshipTemplate use case documentation must be followed.
A RelationshipTemplateContent needs to be specified in the content
of the payload because the Sender wants to send the Recipient a Request via the RelationshipTemplate.
In the payload example below, the Request whose validity was already checked is contained both within the onNewRelationship
property and within the onExistingRelationship
property of the RelationshipTemplateContent. The same Request should therefore be sent regardless of whether a Relationship to the Recipient already exists or not.
{
"maxNumberOfAllocations": 1,
"expiresAt": "2026-01-01T00:00:00.000Z",
"content": {
// RelationshipTemplateContent
"@type": "RelationshipTemplateContent",
"onNewRelationship": {
// Specification of the Request whose validity was checked in the previous step.
// This Request is used if no active Relationship yet exists.
"title": "Example of a Request",
"items": [
{
"@type": "AuthenticationRequestItem",
"mustBeAccepted": true,
"title": "The Sender is asking for an authentication"
}
]
},
"onExistingRelationship": {
// Specification of the Request whose validity was checked in the previous step.
// This Request is used if an active Relationship already exists.
"title": "Example of a Request",
"items": [
{
"@type": "AuthenticationRequestItem",
"mustBeAccepted": true,
"title": "The Sender is asking for an authentication"
}
]
}
}
}
If the RelationshipTemplate has been successfully created, the Sender receives a success response from which its id
and truncatedReference
can be read. Note that the creation of a RelationshipTemplate which contains a Request does not yet lead to the creation of a corresponding LocalRequest. This is only created after the Recipient of the Request has responded to it.
Save the |
Receive the Request by loading the RelationshipTemplate
To receive a Request that is contained within a RelationshipTemplate, the Recipient has to load the RelationshipTemplate created by the Sender using the following payload, whereby the <...>
notation is used as a placeholder for the actual data as usual:
{
"reference": "<truncated reference of RelationshipTemplate>"
}
Loading the RelationshipTemplate triggers a process in the enmeshed Runtime that creates a new incoming Request for the Recipient. Depending on whether a Relationship has already been established between the Sender and the Recipient, the Recipient receives the Request specified in the onNewRelationship
property or in the onExistingRelationship
property of the RelationshipTemplateContent.
If a Relationship has already been established between the Sender and the Recipient and no Request has been specified in the onExistingRelationship
property, the Recipient will not receive an incoming Request when the RelationshipTemplate is loaded.
By proceeding as described in the Query incoming Requests use case documentation and specifying source.reference=<ID of RelationshipTemplate>
and status=ManualDecisionRequired
as query parameters, the new incoming Request can be queried. The result
contains the corresponding LocalRequest, from which you can read the id
of the Request.
Save the |
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 processes, check out our Event introduction.
Respond to the Request
After the Request has been received, the Recipient can reject or accept it. 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.
An AuthenticationRequestItem can be rejected by using the RejectRequestItemParameters.
In the case of the above example Request, the payload is therefore as follows:
{
"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 moves 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
.
An AuthenticationRequestItem can be accepted by using the AcceptRequestItemParameters.
In the case of the above example Request, the payload is therefore as follows:
{
"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.
Its creation content is of type RelationshipCreationContent and contains the Response to the Request.
This Relationship is sent back to the Sender via a Message.
Then, the Request is set to status
"Completed"
and you can query the Relationship using the query parameter template.id=<ID of RelationshipTemplate>
.
As long as the Relationship is "Pending"
, no new Request is created by loading the RelationshipTemplate.
The Sender can fetch the Relationship by synchronizing the updates of the Backbone. In the response you can see a new Relationship, which looks as follows:
{
"id": "REL...",
"template": {
// ...
},
"status": "Pending",
"peer": "did:e:...",
"creationContent": {
"@type": "RelationshipCreationContent",
"response": {
"items": [
{
"@type": "AcceptResponseItem",
"result": "Accepted"
}
],
"requestId": "REQ...",
"result": "Accepted"
}
}
}
Save the |
Now you can accept the Relationship on the Sender Connector with the id
of the Relationship.
When you synchronize the Recipient Connector, you can see that the Relationship now has the status
"Active"
on both Connectors.