Aggregation Integration

Use this guide to integrate with the Frollo Platform’s aggregation features. It will demonstrate how to connect accounts with CDR Data Holders using both our whitelabel Frollo Link interface and directly via APIs. You can also fallback to non-CDR providers via our Yodlee integration.

Setup

Make sure you have configured the following for your environment:

Variable Value
Base URL https://frollolabs-staging.frollo.us
OAuth2 iDP URL https://frollolabs-staging.frollo.us
Redirect URL clientname://authorize
Client ID <CLIENT_ID>
Username <EMAIL>
Password <PASSWORD>

Authentication

Register User

You can skip this step and use an existing account if you have one or have been provided with one. See Authenticate User

To create a new call the Register User endpoint.

POST /api/v2/user/register

Request Body

{
  "email": "test@example.com",
  "password": "Pass1234@!",
  "client_id" : "{{CLIENT_ID}}",
  "first_name": "FirstName",
  "last_name": "LastName",
  "auth_type": "email",
  "device_id": "device-1234",
  "device_name": "Home iPhone",
  "device_type": "Unknown"
}

The request body should look like the above. Change all the fields required, to get more information on the API see Register User.

Expected Response

{
	"refresh_token": "eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJyZWZyZXNoIiwiaXNzIjoiZnJvbGxvbGFicyIsImF1ZCI6MywiaWF0IjoxNjI2NjQ5NDM1LCJyZXZpc2lvbiI6IjEuMCJ9.Rw4EdFL1FmjRBHmurJN4eylzc6eg2715fbx7FqA16-g",
	"access_token": "eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJhY2Nlc3MiLCJpc3MiOiJmcm9sbG9sYWJzIiwiYXVkIjozLCJpYXQiOjE2MjY2NDk0MzUsImV4cCI6MTYyNjY1MTIzNSwicmV2aXNpb24iOiIxLjEifQ.dQCqB5Q5nWpmMwSHsIiU5OJ20Wdq8Rbvzop4Tq95l6U",
	"access_token_exp": 1626651235,
	"id": 123,
	"registration_date": "2021-07-19",
	"first_name": "Test",
	"last_name": "User",
	"email": "test@example.com",
	"email_verified": false,
	"status": "registered",
	"primary_currency": "AUD",
	"features": [
		{
			"feature": "aggregation",
			"enabled": true
		}
	],
	"register_complete": false,
	"valid_password": true
}

The response will provide the refresh token and the access token that can be used to call APIs.

Login

Authenticating a user can be done by calling the Refresh Token OAuth 2.0 endpoint using the ROPC grant type.

POST /oauth/token

Request Body

{
    "username": "{{USER_NAME}}",
    "password": "{{PASSWORD}}",
    "client_id": "{{CLIENT_ID}}",
    "grant_type": "password",
    "domain": "{{DOMAIN}}",
    "scope": ""
}

The default session time is 30 minutes after that the User need to be authenticated again.

Expected Result

{
    "access_token": "eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOjE3LCJpc3MiOiJmcm9sbG9sYWJzIiwiZXhwIjoxNjI2Mzk5NzQ4LCJpYXQiOjE2MjYzOTc5NDgsImp0aSI6ImZiZmQyMTBjLThiNjYtNGM1Ni04YWM2LTBiY2ZkMDMxZjFhYSJ9.gvQ13PbW_TY1_R4r_3JtAx6SKH0sAANmbA4GZBLTe3gVgCN4dc5MNDs0ra7cYyDRuG_-bXzTK1x4l1s3gdjRqw",
    
	"token_type": "Bearer",
    "expires_in": 1800,
    "refresh_token": "H5NpmSAbTv5plXy5UmNetCWptYwDOWd6-n7ebl29UR0",
    "created_at": 1626397948
}

The above is an example result, the access_token and refresh_token, and created_at will be different from the example response.

*Important things to notice If you have not noticed before that we had no access token in our environment field. The result of this request will populate the token field in the environment. Check if the response “access_token” is also present in the environment field.

Get User Details

The next step to follow after getting the token is to call an API like Get User Details check if the token is working as needed.

Expected Response

{
    "id": 123,
    "registration_date": "2021-07-14",
    "first_name": "Test",
    "last_name": "User",
    "email": "test@example.com",
    "email_verified": false,
    "status": "budget_ready",
    "primary_currency": "AUD",
    "features": [
        {
            "feature": "aggregation",
            "enabled": true
        }
    ],
    "register_complete": false,
    "valid_password": true
}

Link Accounts

Linking accounts can be done in two ways:

  • Frollo Link - link accounts with our customisable web and mobile Frollo Link UI
  • API - build your own user interface and directly call our APIs to link accounts

Link Accounts with Frollo Link

One way to connect with a bank account is using the Frollo Link web interface. The following steps will walk through to connect with Frollo Mock Bank.

  1. Go to https://frollolabs.staging.link.cdr.systems/consent/link/start to log in.

  2. Use the provided username and password credentials to log in.

  3. Click the See More Banks button and Search and select Frollo Mock Bank

  1. Select the preferred data sharing consent duration

  2. Select the type of data to share - In this instance select ‘account balance details’ and ‘transaction details’.

  3. Continue the prompt until the connect button. The connect button will redirect to the Bank consent URL.

  4. Input 1 in the mobile number field and press Next.

  1. It is not necessary to select or input any values. Continue with the prompt until it finishes.

  2. After it is finished the following page will be displayed which suggests that the User is successfully connected with Frollo Mock Bank. Close the tab.

Link Accounts via API

There are two ways to connect accounts through API.

For both of the processes, the user needs to authenticate. To get more information about authentication Frollo use, see Authentication

Linking a CDR Account

To connect through CDR API, Provider ID is required. To find Provider ID, follow the step below Find the Provider ID of the Bank.

The Provider response will show what permissions are supported. Call the Create Consent API with the selected provider_id and the permissions you want to give along with a sharing_duration in seconds.

This example is for consenting with Frollo Mock Bank. The Provider ID of Frollo Mock Bank is 30777.

Request Body

{
    "provider_id": 30777,
    "sharing_duration": 10368000,
    "permissions": ["transaction_details","account_details", "payee_details"],
    "additional_permissions": {
        "suggest_ways_to_save_money": true,
        "analyse_spending_behaviour": true
    },
    "delete_redundant_data": true
}

In the request body, replace provider_id with the Provider ID of the required Bank.

Expected Response

{
    "id": 105,
    "provider_id": 30777,
    "provider_account_id": 412,
    "status": "pending",
    "sharing_duration": 10368000,
    "permissions": [
        "transaction_details",
        "account_details"
    ],
    "additional_permissions": {
        "suggest_ways_to_save_money": true,
        "analyse_spending_behaviour": true
    },
    "delete_redundant_data": true,
    "authorisation_request_url": "https://cba-demo.frollo.us/authorisation/start-flow?redirect_uri=https%3A%2F%2Fcdrtest-staging.frollo.us%2Fcdr%2Fauthorisation%2Fcallback&client_id=frollo-mock-bank&state=9da56d3a-1f2d-492e-a783-3672d0d7fbae&nonce=4440039a-96b9-4cb8-9fbe-02f94aa8ce94&scope=openid+bank%3Atransactions%3Aread+bank%3Aaccounts.basic%3Aread+bank%3Apayees%3Aread&response_type=code+id_token&request=eyJ0eXAiOiJKV1QiLCJraWQiOm51bGwsImFsZyI6IlBTMjU2In0.eyJpc3MiOiJmcm9sbG8tbW9jay1iYW5rIiwic2NvcGUiOiJvcGVuaWQgYmFuazp0cmFuc2FjdGlvbnM6cmVhZCBiYW5rOmFjY291bnRzLmJhc2ljOnJlYWQgYmFuazpwYXllZXM6cmVhZCIsInJlc3BvbnNlX3R5cGUiOiJjb2RlIGlkX3Rva2VuIiwicmVkaXJlY3RfdXJpIjoiaHR0cHM6Ly9jZHJ0ZXN0LXN0YWdpbmcuZnJvbGxvLnVzL2Nkci9hdXRob3Jpc2F0aW9uL2NhbGxiYWNrIiwibm9uY2UiOiI0NDQwMDM5YS05NmI5LTRjYjgtOWZiZS0wMmY5NGFhOGNlOTQiLCJzdGF0ZSI6IjlkYTU2ZDNhLTFmMmQtNDkyZS1hNzgzLTM2NzJkMGQ3ZmJhZSIsImNsaWVudF9pZCI6ImZyb2xsby1tb2NrLWJhbmsiLCJhdWQiOiIiLCJleHAiOjE2MjY2NTIxNzYsImNsYWltcyI6eyJzaGFyaW5nX2R1cmF0aW9uIjoxMDM2ODAwMCwiaWRfdG9rZW4iOnsiYWNyIjp7InZhbHVlcyI6WyJ1cm46Y2RzLmF1OmNkcjozIl0sImVzc2VudGlhbCI6dHJ1ZX0sInJlZnJlc2hfdG9rZW5fZXhwaXJlc19hdCI6eyJlc3NlbnRpYWwiOnRydWV9LCJzaGFyaW5nX2V4cGlyZXNfYXQiOnsiZXNzZW50aWFsIjp0cnVlfX0sInVzZXJpbmZvIjp7ImdpdmVuX25hbWUiOnsiZXNzZW50aWFsIjp0cnVlfSwiZmFtaWx5X25hbWUiOnsiZXNzZW50aWFsIjp0cnVlfSwiYXV0aF90aW1lIjp7ImVzc2VudGlhbCI6dHJ1ZX0sIm5hbWUiOnsiZXNzZW50aWFsIjp0cnVlfSwidXBkYXRlZF9hdCI6eyJlc3NlbnRpYWwiOnRydWV9LCJyZWZyZXNoX3Rva2VuX2V4cGlyZXNfYXQiOnsiZXNzZW50aWFsIjp0cnVlfSwic2hhcmluZ19leHBpcmVzX2F0Ijp7ImVzc2VudGlhbCI6dHJ1ZX19fX0.B6pHwXWDRfgKLpO-lVI8goZYT4W-vPx8imausgygzP_N2ZQXXk2irJJEillHfzCsNv_wT1cw2bAvwPweEkOE7xbynbm7g1k1ZHvBOjIgHY8-VcNC4VNdnuFp9d04g-Ar786K_sD0ElvYkgShz5AjpNrTeg1kyszr5OiOx01NfZIIjli4CwLG9_yW1QXR4CqupXOPSdtTVxK6CFUrPSuMNyYOtmbsi6UJkLyZSOFTqed5gu4uWBnup5nVNbQ4e1-PokOR7w2SgOqfirFGO8zTJwgTrANnYuq53LWxAHHI3gkcpXMtcVNlT1ncqTPjB2_dFcAq3rfK7ny351X7mokX8Q",
    "context": "14556f61-2a49-4754-9de2-338f87727be1"
}

Consent URL

Copy the authorisation_request_url from the above expected response to open the URL. The page from the URL should look like this.

Input 1 on the mobile number field and continue till the end. This process only takes few seconds

Check Consent

To verify the Consent has been created call the List Consents endpoint.

Expected Response
[
    {
        "id": 105,
        "provider_id": 30777,
        "provider_account_id": 412,
        "status": "active",
        "sharing_started_at": "2021-07-19",
        "sharing_duration": 10368000,
        "permissions": [
            "transaction_details",
            "account_details"
        ],
        "additional_permissions": {
            "suggest_ways_to_save_money": true,
            "analyse_spending_behaviour": true
        },
        "delete_redundant_data": true,
        "confirmation_pdf_url": "https://frollolabs-staging.frollo.us/api/v2/cdr/consents/105/pdfs/confirmation",
        "context": "14556f61-2a49-4754-9de2-338f87727be1"
    }
]

Check the provider_id on the response body and check if it matches with the requested Provider Id. If it matches then the Provider and User are connected.

Linking a Yodlee Account

To connect the current User to the Provider (Bank). The following example will walkthrough connecting with a test Provider called DagBank.

1: Find the Provider ID of the Bank

Currently, Frollo API does not have search functionality to look for Providers. To search for the Provider ID of the Providers, a search needs to be done on the result of List of Providers after an API call.

To fetch all available Providers list call the List Providers endpoint.

Search the results to find the Dag Bank Provider.

Expected Response

The expected result is a list of Providers. An example for the DagBank is below:

{
        "id": 15954,
        "name": "DagBank",
        "small_logo_url": "https://frollo-staging.s3.amazonaws.com/providers/15954/small/download_(3)_copy.png?1520329655",
        "small_logo_revision": 1,
        "large_logo_url": "https://frollo-staging.s3.amazonaws.com/providers/15954/large/download_(3).png?1520329654",
        "large_logo_revision": 1,
        "status": "supported",
        "popular": false,
        "container_names": [
            "bank"
        ],
        "login_url": "http://dag2.yodlee.com/dag/index.do",
        "aggregator_type": "yodlee",
        "permissions": [
            "account_details",
            "transaction_details"
        ]
    },

Note down the ID from the bank that you would like to connect.

2: Get the Provider Login Details

Use the Provider ID retrieved from the previous step to get Provider login form details. To receive Provider login form details call the Get Provider endpoint with the Provider ID parameter. For example for the DagBank from the above response, it would like this{{URL}}/api/v2/aggregation/providers/15954.

Expected Response
{
    "id": 15954,
    "name": "DagBank",
    "small_logo_url": "https://frollo-staging.s3.amazonaws.com/providers/15954/small/download_(3)_copy.png?1520329655",
    "small_logo_revision": 1,
    "status": "supported",
    "popular": false,
    "large_logo_url": "https://frollo-staging.s3.amazonaws.com/providers/15954/large/download_(3).png?1520329654",
    "container_names": [
        "bank"
    ],
    "large_logo_revision": 1,
    "login_url": "http://dag2.yodlee.com/dag/index.do",
    "base_url": "http://64.14.28.129/dag/index.do",
    "forget_password_url": "http://dag2.yodlee.com/dag/index.do",
    "o_auth_site": false,
    "auth_type": "credentials",
    "login_form": {
        "id": "8395",
        "forgetPasswordURL": "http://dag2.yodlee.com/dag/index.do",
        "formType": "login",
        "row": [
            {
                "id": "22059",
                "label": "Username",
                "form": "0001",
                "fieldRowChoice": "0001",
                "field": [
                    {
                        "id": "16664",
                        "name": "LOGIN",
                        "type": "text",
                        "value": "",
                        "isOptional": false,
                        "valueEditable": true
                    }
                ]
            },
            {
                "id": "22058",
                "label": "Password",
                "form": "0001",
                "fieldRowChoice": "0002",
                "field": [
                    {
                        "id": "16663",
                        "name": "PASSWORD1",
                        "type": "password",
                        "value": "",
                        "isOptional": false,
                        "valueEditable": true
                    }
                ]
            }
        ]
    },
    "encryption": {
        "encryption_type": "encrypt_values",
        "alias": "09282016_1",
        "pem": "-----BEGIN PUBLIC KEY-----\r\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1eXKHvPBlS4A41OvQqFn0SfNH7OgEs2MXMLeyp3xKorEipEKuzv/JDtHFHRAfYwyeiC0q+me0R8GLA6NEDGDfpxGv/XUFyza609ZqtCTOiGCp8DcjLG0mPljdGA1Df0BKhF3y5uata1y0dKSI8aY8lXPza+Tsw4TtjdmHbJ2rR3sFZkYch1RTmNKxKDxMgUmtIk785lIfLJ2x6lvh4ZS9QhuAnsoVM91WWKHrLHYfAeA/zD1TxHDm5/4wPbmFLEBe2+5zGae19nsA/9zDwKP4whpte9HuDDQa5Vsq+aWj5pDJuvFgwA/DStqcHGijn5gzB/JXEoE9qx+dcG92PpvfwIDAQAB\r\n-----END PUBLIC KEY-----"
    },
    "aggregator_type": "yodlee",
    "permissions": [
        "account_details",
        "transaction_details"
    ],
    "products_available": false
}

The important things to note down and focus on are within the login_form object.

"login_form": {
        "id": "8395",
        "forgetPasswordURL": "http://dag2.yodlee.com/dag/index.do",
        "formType": "login",
        "row": [
            {
                "id": "22059",
                "label": "Username",
                "form": "0001",
                "fieldRowChoice": "0001",
                "field": [
                    {
                        "id": "16664",
                        "name": "LOGIN",
                        "type": "text",
                        "value": "",
                        "isOptional": false,
                        "valueEditable": true
                    }
                ]
            },
            {
                "id": "22058",
                "label": "Password",
                "form": "0001",
                "fieldRowChoice": "0002",
                "field": [
                    {
                        "id": "16663",
                        "name": "PASSWORD1",
                        "type": "password",
                        "value": "",
                        "isOptional": false,
                        "valueEditable": true
                    }
                ]
            }
        ]
    },

The essential part of the above to note is the rows section each row section is divided into email and password. In this case name and password are as follows:

Name:

{
	"id": "22059",
	"label": "Username",
	"form": "0001",
	"fieldRowChoice": "0001",
	"field": [
		{
			"id": "16664",
			"name": "LOGIN",
			"type": "text",
			"value": "",
			"isOptional": false,
			"valueEditable": true
		}
	]
},

Password

{
	"id": "22058",
	"label": "Password",
	"form": "0001",
	"fieldRowChoice": "0002",
	"field": [
		{
			"id": "16663",
			"name": "PASSWORD1",
			"type": "password",
			"value": "",
			"isOptional": false,
			"valueEditable": true
		}
   ]
}

Within this section, the focus needs to be on the value of each name and password. This value corresponds to Users bank name and password.

3: Use the above Provider ID and Provider Login Details

The final step is to create a Provider Account with the login details. Calling the Create Provider Account endpoint with the login_form will start the Yodlee syncing process.

Initial Body
{
"provider_id": "",
"login_form": {
		"row": [
			{
				"field": [
					{	
						"id": "16664",
						"value": "1"
					}
				]
			},
			{
				"field": [
					{
						"id": "16663",
						"value": "1"
					}
				]
			}
		]
	}
}

Input Provider ID in the provider_id field of the body. Copy the Provider Login Form and replace the login_form fields from the body. Within the value fields input the required value for the username and password and send.

For example, the request body for the DagBank will look like this:

Request Body
{
  "provider_id": "15954",
  "login_form": {
        "id": "8395",
        "forgetPasswordURL": "http://dag2.yodlee.com/dag/index.do",
        "formType": "login",
        "row": [
            {
                "id": "22059",
                "label": "Username",
                "form": "0001",
                "fieldRowChoice": "0001",
                "field": [
                    {
                        "id": "16664",
                        "name": "LOGIN",
                        "type": "text",
                        "value": "1",
                        "isOptional": false,
                        "valueEditable": true
                    }
                ]
            },
            {
                "id": "22058",
                "label": "Password",
                "form": "0001",
                "fieldRowChoice": "0002",
                "field": [
                    {
                        "id": "16663",
                        "name": "PASSWORD1",
                        "type": "password",
                        "value": "1",
                        "isOptional": false,
                        "valueEditable": true
                    }
                ]
            }
        ]
    }
}

The values correspond to User email/Id and password credentials. All these are information only for test use cases. For production these fields need to be encrypted before sending the information to Frollo. This is done by:

  • List item getting the public key from GET provider details API
  • Hex encode the binary form of the string
  • Use the public key to encrypt the hex value using RSA and making sure PKCS1 padding is used
  • Fill the JSON with the key alias followed by the encrypted value separated by a colon - $alias:$encrypted
Expected Response
{
    "id": 410,
    "external_id": "24917343",
    "provider_id": 15954,
    "editable": true,
    "refresh_status": {
        "status": "adding"
    }
}

Refresh until the status is active. If the active status is active then the User and the Provider are connected.

Troubleshooting

Common errors can be found on the main documentation Errors page.

Next Steps

After the Bank is connected, the User is exposed to a more useful API. Information for all the API is provided here