Activity - Use the Consent API


Introduction and workflow tasks

The Consent API may be used as the data backend for an Open Banking account requests API. For more information about Open Banking, see Open Banking.

In this activity, a third-party payment processor (Company A) makes an account request to an account servicing provider (Company B) on behalf of the account holder (Customer). Company A needs permission to access specific account data. To move forward with the transaction, a consent request must be sent to the Customer, and a consent record must be created to capture the consent response.

This scenario illustrates some common open banking operations supported by the Consent API, including:

  • Creating a consent record.
  • Checking the state of an existing consent record.
  • Retrieving localized consent prompt text.
  • Updating a consent record.

The actors in this scenario are:

  • The Customer

    This is the account holder who must provide consent so that the third party can access account data.

  • Third-Party Provider (Company A)

    This is the third-party client that requires access to the customer’s account data.

  • Account Servicing Payment Servicing Provider (Company B)

    This is the service that processes the customer’s accounts and consents. This service consists of:

    • A data governance server, which provides the Open Banking account requests API.
    • A PingFederate server, which handles OpenID Connect authentication and OAuth2 authorization in conjunction with a Consent Capture Web Application.
    • A directory server, which provides the Consent Service and the Consent Capture Web Application.

Workflow order of operations

To request the Customer’s consent, the following tasks must be completed successfully:

  1. Company A makes a POST request to the /account-requests service on the data governance server at Company B. This POST specifies the list of permissions that Company A needs to be granted through the consent request.

  2. Company B makes a POST request to /consents on its directory server to create a consent record with the consent status value set to pending.

  3. Using the consent record id generated in step 2, Company A can now make a GET request to Company B’s consent capture app to check the account request state to see if the Customer has accepted or denied consent.

  4. If the consent state is pending, the consent capture app prompts the Customer to grant authorization. The app makes a GET request to the /definitions/<consentDefinitionName>/localizations service for the specified consent definition.

  5. The Customer grants or denies authorization, and the consent capture app makes a PATCH request to /consents to update the consent record based on the Customer’s response.

Step 1: Create the account request

Company A needs the following common open banking permissions from the Customer:

  • ReadAccountsDetail
  • ReadBalances
  • ReadBeneficiariesDetail
  • ReadDirectDebits
  • ReadProducts

Company A knows that Company B has a standard consent definition called OpenBankingAccountsConsent that can be used to capture consent from the Customer for these permissions.

The POST /account-requests operation initiates the consent request. The request body specifies these permissions.

curl -X POST "https://api.companyb.com/v1/account-requests" \
-H "accept: application/hal+json" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer jwtToken" \
-d "{
  "data": {
    "permissions": [
    "ReadAccountsDetail",
    "ReadBalances",
    "ReadBeneficiariesDetail",
    "ReadDirectDebits",
    "ReadProducts"
    ]
  }
}"

The response data shows the requested permissions as well as the AccountRequestId and the status of the account request.

Company B creates a consent record to capture and store the Customer’s response to the consent request on its directory server. The request body must provide values for the status, subject, actor, and audience properties. In this case, the status property value is set to pending. In addition, the request can define additional properties to store custom data relevant to the consent request, such as the permissions requested by Company A.

The POST /consents/ operation creates a new consent record.

curl -X POST "https://api.companyb.com/consent/v1/consents" \
-H "accept: application/hal+json" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer jwtToken" \
-d "{
  "status": "pending",
  "subject": "Customer",
  "actor": "Customer",
  "audience": "CompanyA",
  "definition": {
    "id": "OpenBankingAccountsConsent", \
    "version": "1.0\",
    "locale": "en-US" },
  "data": {
    "Permissions": [
      "ReadAccountsDetail", \
      "ReadBalances", \
      "ReadBeneficiariesDetail", \
      "ReadDirectDebits", \
      "ReadProducts"
    ]
  }
}"

If successful, the operation returns a 201: Success message and shows the consent record data. The consent record id and other properties shown in the consent record data can be converted into an open banking response sent to Company A for further action. The consent record data looks like this:

{
  "_links": {},
  "_embedded": {},
  "status": "pending",
  "subject": "Customer",
  "actor": "Customer",
  "audience": "CompanyA",
  "definition": {
    "id": "OpenBankingAccountsConsent",
    "version": "1.0",
    "locale": "en-US"
  },
  "id": "f0c0ac1d-a493-426d-9211-224255145d28",
  "dataText": "Allow access to your financial accounts.",
  "purposeText": "This data is required to complete your transaction.",
  "data": {
    "Permissions": [
      "ReadAccountsDetail", \
      "ReadBalances", \
      "ReadBeneficiariesDetail", \
      "ReadDirectDebits", \
      "ReadProducts"
      ]
    },
  "consentContext": {}
}

Step 3: Check the account request state

Company A checks the consent status of the Customer’s account. It makes a GET request to the /account-requests/{AccountRequestId} service on the data governance server at Company B using the AccountRequestId property value returned in Step 1. Company B checks the consent status by making a GET request to the /consents/{consentRecordId} service on its directory server.

The GET /consents/{consentRecordId} operation finds the consent record data for the consentRecordId returned in Step 2.

curl -X GET "https://api.companyb.com/consent/v1/consents/550e8400-e29b-41d4-a716-446655440000" \
-H "accept: application/hal+json" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer jwtToken"

In this case, the resulting consent record data shows the status property as pending, which tells company A that it needs to move forward by prompting the Customer to grant authorization.

{
  ...
  "status": "pending",
  "subject": "Customer",
  "actor": "Customer",
  "audience": "CompanyA",
  ...
}

Company B gets the consent definition’s localized text to display a consent prompt to the Customer. The consent capture app makes a GET request to the /definitions/{id}/localizations service on the directory server.

The GET definitions/OpenBankingAccountsConsent/localizations operation gets the consent record data for the OpenBankingAccountsConsent consent definition.

curl -X GET "https://api.companyb.com/consent/v1/definitions/OpenBankingAccountsConsent/localizations" \
-H "accept: application/hal+json" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer jwtToken"

The response data shows the current consent definition localizations. For this consent definition, there are two localizations resources: en-US and fr-CA.

{
  "count": 2,
  "size": 2,
  "_links":{
    "self":{
      "href":"https://api.companyb.com/consent/v1/definitions/OpenBankingAccountsConsent/localizations"
    }
  },
  "_embedded":{
    "localizations":[
      {
        "_links":{
          "parent":{
            "href":"https://api.companyb.com/consent/v1/definitions/OpenBankingAccountsConsent"
          },
          "self":{
            "href":"https://api.companyb.com/consent/v1/definitions/OpenBankingAccountsConsent/localizations/en-US"
          }
        },
        "id":"en-US",
        "locale":"en-US",
        "version":"1.1",
        "dataText":"Allow access to your financial accounts.",
        "purposeText":"This data is required to complete your transaction."
      },
      {
        "_links":{
          "parent":{
            "href":"https://api.companyb.com/consent/v1/definitions/OpenBankingAccountsConsent"
          },
          "self":{
            "href":"https://api.companyb.com/consent/v1/definitions/OpenBankingAccountsConsent/localizations/fr-CA"
          }
        },
        "id":"fr-CA",
        "locale":"fr-CA",
        "version":"1.2",
        "dataText":"Autoriser l'accès à vos comptes financiers.",
        "purposeText":"Ces données sont nécessaires pour compléter votre transaction."
      }
    ]
  }
}

After the Customer responds to the consent prompt, the authorization or denial of consent is added to the consent record. The consent capture app makes a PATCH request to the /consents/{id} service to update the Customer’s consent record. The updated record stores the information collected by the consent capture app from the Customer’s response to the consent prompt.

The PATCH /consents/{consentRecordId} operation updates an existing consent record, modifying the record to reflect only the new property values specified in the request body. The consentRecordId value obtained in Step 2 is added to the request URL to identify the Customer’s consent record.

curl -X PATCH "https://api.companyb.com/consent/v1/consents/f0c0ac1d-a493-426d-9211-224255145d28" \
-H "accept: application/hal+json" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer jwtToken" \
-d "{
  "status": "accepted"
  }
}"

In this sample, the Customer is prompted to ALLOW/DENY authorization to Company A for all data-sharing permissions. The request body specifies a modification to only the status property value to reflect the Customer’s response. The updated consent record looks like this:

{
  "_links": {},
  "_embedded": {},
  "status": "accepted",
  "subject": "Customer",
  "actor": "Customer",
  "audience": "CompanyA",
  "definition": {
    "id": "OpenBankingAccountsConsent",
    "version": "1.0",
    "locale": "en-US"
  },
  "id": "f0c0ac1d-a493-426d-9211-224255145d28",
  "dataText": "Allow access to your financial accounts.",
  "purposeText": "This data is required to complete your transaction.",
  "data": {
    "Permissions": [
      "ReadAccountsDetail", \
      "ReadBalances", \
      "ReadBeneficiariesDetail", \
      "ReadDirectDebits", \
      "ReadProducts"
      ]
    },
  "consentContext": {}
}

If the Customer chooses to terminate the relationship with Company A, the Customer can revoke consent. In this case, to honor the Customer’s revocation request, Company A makes a DELETE request to the /account-requests/{accountId} service on Company B’s data governance server. To complete the operation, Company B makes a PATCH request to the /consent/v1/consents/{consentRecordId} service on the directory server, specifying the change in status for the account.

curl -X PATCH "https://api.companyb.com/consent/v1/consents/f0c0ac1d-a493-426d-9211-224255145d28" \
-H "accept: application/hal+json" \
-H "Content-Type: application/json" \
-H "Authorization: Bearer jwtToken" \
-d "{
  "status": "revoked"
  }
}"