Quickstart

Overview

Introduction

In this quick start guide we will be focusing on how to integrate the FriendlyScore WebComponent in order to make API calls for the Connect, Insights and Forecast products.

Please start by downloading the Quickstart App from Github. In order to run the App, you will first need to obtain the FriendlyScore API keys.

You can also see a working demo of the Quickstart app at: FriendlyScore Quickstart Demo

Running the Walkthrough App

git clone https://github.com/FriendlyScore/FriendlyScore-Quickstart-NodeJS-Example.git
cd FriendlyScore-Quickstart-NodeJS-Example
npm install

# If port and host is changed you MUST add origin with bellowed values in:
# https://friendlyscore.com/company/redirects
LISTEN_PORT=3000
LISTEN_HOST=127.0.0.1

# The user reference. In most cases user reference is
# a reference to user in your database.
USER_REFERENCE='{YOUR_USER_REFERENCE}'

# Shows credentials in the playgound page
SHOW_CREDENTIALS=true

# The URL of API
BASE_URL='https://sandbox.friendlyscore.com'

# Start the Quickstart with your API keys from the Dashboard
# https://friendlyscore.com/company/keys
CLIENT_ID='{YOUR_CLIENT_ID}'
CLIENT_SECRET='{YOUR_CLIENT_SECRET}'

node index.js
# Go to http://127.0.0.1:3000

Platform Overview

WebComponent Origin

By default, the FriendlyScore WebComponent is running on localhost on port 3000. If you want to run the WebComponent on a different host and port you MUST set a new origin at Developer Console.

API Keys

Obtain your client_id and client_secret from FriendlyScore API keys.

API Environments

Environment Description
sandbox Use test credentials then build out and test your integration. Unlimited API Calls
development Test your integration with live credentials. You will have access to limited Production API Calls
production Production API environment

Accessing the Data

Retrieve Access Token

The access token allows you to connect with the FriendlyScore API. Obtain your client_id and client_secret from FriendlyScore API keys.

Example OAuth Token Request

NodeJS Example: /services/authService.js

async function getAccessToken(clientId, clientSecret) {
  try {
    const config = {
      method: 'post',
      url: `${baseUrl}/oauth/v2/token`,
      headers: {
        "Content-Type": "application/json",
        "Accept": "application/json"
      },
      data: {
        "client_id": clientId,
        "client_secret": clientSecret,
        "grant_type": "client_credentials"
      }
    };
    const response = await axios(config);
    return response && response.data && response.data.access_token;
  } catch (e) {
    throw e;
  }
}

Example OAuth Token response

If you provided the correct client_id, client_secret and grant_type, you should get a successful response with an access_token. You can use this token to access user data from the FriendlyScore API.

{
    "access_token": "{YOUR_USER_ACCESS_TOKEN}",
    "expires_in": 3600,
    "token_type": "bearer",
    "scope": null
}

In Case of Errors

If you get an error here, such as 400 Bad Request, this could have multiple reasons. It could, for example, be an invalid client_id or an invalid client_secret.

Render WebComponent

Retrieve WebComponent One Time URL

The WebComponent One Time URL is used to render the FriendlyScore WebComponent inside an HTML element with id fs-component. In this section, we will show how to prepare parameters for obtaining the WebComponent One Time URL with NodeJS Quickstart Application.

Example WebComponent One Time URL Request

Prepare request parameters:

NodeJS Example: /routes/index.js

const userAgent = req.headers["user-agent"];
const host = req.headers.host;
const accessToken = await authService.getAccessToken();

Retrieve WebComponent One Time URL:

NodeJS Example: /services/webComponentOneTimeUrlService.js

async function getWebComponentOneTimeUrl(accessToken, userAgent, host) {
  try {
    const config = {
      method: 'post',
      url: `${baseUrl}/api/v1/component_auth/init`,
      headers: { "Authorization": `Bearer ${accessToken}`, ...defaultHeaders },
      data: {
        "ip": "1.2.3.4",
        "user_agent": userAgent,
        "user_reference": userReference,
        "origin": `http://${host}`
      }
    };
    const response = await axios(config);

    if (response) {
      const { status, data } = response;
      const webComponentOneTimeUrl = data.url;

      if (!!status && status !== 200) {
        throw new Error('{"title": "An error occurred", "error": "Probably origin sent in request is not present in allowed origins. Please setup allowed origins in customer panel"}')
      }

      return webComponentOneTimeUrl;
    }
  } catch (e) {
    throw e;
  }
}
Example WebComponent One Time URL Response

If you provided the correct access_token, user_agent, user_reference, origin, and ip, you should get a successful response with a url.

{
  "url": "{YOUR_WEB_COMPONENT_ONE_TIME_URL}",
  "created_at": 1566306425,
  "expires_in": 1800
}
In Case of Errors
  • The 400 Bad Request is returned when ip, user_agent, user_reference or origin is invalid or missing.
  • The 401 Unauthorized is returned when access_token is invalid or expired.
WebComponent One Time URL Usage

To use FriendlyScore WebComponent you need:

  • create html element with id fs-component
  • pass received WebComponent One Time URL into src attribute of html script tag

NodeJS Example: /templates/index.twig

<!doctype html>
<html>
<head>
    ...
</head>
<body>
    ...
    <div id="fs-component"></div>
    <script src="{YOUR_WEB_COMPONENT_ONE_TIME_URL}"></script>
    ...
</body>
</html>

Fetch Customers Data

GET /public/v1/customers

The customers endpoint returns a list of all customers in your app.

Prepare Request Parameters

const accessToken = await authService.getAccessToken();

Example Customers Request

NodeJS Example: /services/customerService.js

async function getCustomers(accessToken) {
  try {
    const config = {
      "method": "GET",
      "url": `${baseUrl}/public/v1/customers`,
      "qs": {
          "by-user-reference": userReference
      },
      "headers": { Authorization: `Bearer ${accessToken}`, ...defaultHeaders },
    };
    const response = await axios(config);

    if (response) {
      const { data } = response;
      return data.data;
    }
  } catch (e) {
    throw e;
  }
}

The defaultHeaders is defined in /config.js

{
  "Content-Type": "application/json",
  "Accept": "application/json"
}

Example Customers Response

{
  "data": [
    {
      "id": "1",
      "user_reference": "123456789"
    },
    {
      "id": "2",
      "user_reference": "987654321"
    }
  ]
}

In Case of Errors

  • The 401 Unauthorized is returned when access_token is invalid.
  • The 404 Not Found is returned when client_id does not exist in the FriendlyScore database.

Fetch Transaction Data

GET /public/v1/customers/{customerId}/transactions

Returns transaction collection by customer id

Prepare Request Parameters

NodeJS Example: /routes/transactions.js

const filterByDate = req.query.date; // get date query from http request object
const accessToken = await authService.getAccessToken();
const customers = await customerService.getCustomers(accessToken);
const customerId = customers[0].id;  // get id from first customer

Example Transaction Request

NodeJS Example: /services/transactionService.js

async function getTransactions(accessToken, customerId, filterByDate) {
  try {
    let url = _prepareTransactionsUrl(customerId, filterByDate);
    const config = {
      method: "GET",
      headers: { Authorization: `Bearer ${accessToken}`, ...defaultHeaders },
      url,
    };
    const response = await axios(config);

    if (response) {
      const { data } = response;
      return data;
    }
  } catch (e) {
    throw e;
  }
}

function _prepareTransactionsUrl(customerId, filterByDate) {
  let url = `${baseUrl}/public/v1/customers/${customerId}/transactions`;

  if (!!filterByDate) {
    url += `?date=${encodeURIComponent(filterByDate)}`;
  }

  return url;
}

The defaultHeaders is defined in /config.js

{
  "Content-Type": "application/json",
  "Accept": "application/json"
}

Example Transaction Response

{
  "transactions": [
    {
      "id": "1",
      "name": "TEST COMPANY SALARY JAN 8193873722188771",
      "amount": 3000,
      "currency": "EUR",
      "status": "Booked",
      "bank_slug": "fs-demo-bank",
      "account_number": "123-123-123-123",
      "category": "Lifestyle",
      "address_line": null,
      "value_date_time": 1546428919,
      "booking_date_time": 1546428919,
      "credit_debit_indicator": "Credit"
    },
    ...
  ]
}

In Case of Errors

  • The 401 Unauthorized is returned when access_token is invalid.
  • The 404 Not Found is returned when client_id not exist in the FriendlyScore database.

Fetch Insights Data

GET /public/v1/customers/{customerId}/insights

Returns insights by customer id

Prepare Request Parameters

NodeJS Example: /routes/insights.js

const accessToken = await authService.getAccessToken();
const customers = await customerService.getCustomers(accessToken);
const customerId = customers[0].id;  // get id from first customer

Example Insights Request

NodeJS Example: /services/insightsService.js

async function getInsights(accessToken, customerId) {
  try {
    const config = {
      method: "GET",
      url: `${baseUrl}/public/v1/customers/${customerId}/insights/current`,
      headers: { Authorization: `Bearer ${accessToken}`, ...defaultHeaders },
    };
    const response = await axios(config);

    if (response) {
      const { data } = response;
      return data;
    }
  } catch (e) {
    throw e;
  }
}

The defaultHeaders is defined in /config.js

{
  "Content-Type": "application/json",
  "Accept": "application/json"
}

Example Insights Response

{
  "currency": "GBP",
  "income": {
    "total": [
      {
        "year": 2019,
        "month": 12,
        "amount": 2231.23
      },
      {
        "year": 2019,
        "month": 11,
        "amount": 2131.23
      },
              ...
    ],
    "salary": [
              ...
    ],
    "loan_income": [
              ...
    ],
    "benefits": [
              ...
    ],
    "pension": [
              ...
    ],
    "investments": [
              ...
    ],
    "other": [
              ...
    ]
  },
  "expenditure": {
    "total": [
      {
        "year": 2019,
        "month": 12,
        "amount": 2212.22
      },
      {
        "year": 2019,
        "month": 11,
        "amount": 1812.22
      },
              ...
    ],
    "fixed": {
      "mortgage_rent": [
        {
          "year": 2019,
          "month": 12,
          "amount": 500.00
        },
        {
          "year": 2019,
          "month": 11,
          "amount": 500.00
        },
              ...
      ],
      "council_tax": [
              ...
      ],
      "furniture_appliance_rentals": [
              ...
      ],
      "tv_licence": [
              ...
      ],
      "debt_repayments": [
              ...
      ],
      "bank_charges": [
              ...
      ],
      "legal": [
              ...
      ],
      "utilities": [
              ...
      ],
      "insurance": [
              ...
      ],
      "healthcare": [
              ...
      ],
      "transport_travel": [
              ...
      ],
      "school_education": [
              ...
      ],
      "professional_services": [
              ...
      ],
      "membership_organisations": [
              ...
      ]
    },
    "flexible": {
      "communication_tv": [
              ...
      ],
      "hobbies_interests": [
              ...
      ],
      "entertainment": [
              ...
      ],
      "eating_out": [
              ...
      ],
      "gambling": [
              ...
      ],
      "social_activities": [
              ...
      ],
      "gifts_postage_stationery": [
              ...
      ],
      "groceries_housekeeping": [
              ...
      ],
      "family": [
              ...
      ],
      "home_improvement": [
              ...
      ],
      "clothing_fashion": [
              ...
      ],
      "health_beauty": [
              ...
      ],
      "general_retail": [
              ...
      ]
    }
  },
  "financial_patterns": {
    "mean_last_3m": {
      "total_balance": 100,
      "total_income": 500,
      "total_expenditure": 400,
              ...
    },
    "variance_last_3m": {
      "total_balance": 100,
      "total_income": 100,
      "total_expenditure": 50,
              ...
    },
    "max_last_3m": {
      "total_balance": 300,
      "total_income": 600,
      "total_expenditure": 550,
              ...
    },
    "min_last_3m": {
      "total_balance": 150,
      "total_income": 550,
              ...,
      "total_expenditure": 350,
              ...
    },
          ...
  },
  "financial_markers": {
    "returned_direct_debits": {
      "num_last_3m": {
        "timestamp_from": 1600466400,
        "timestamp_to": 1608418799,
        "count": 5
      },
      "num_last_6m": {
        "timestamp_from": 1592517600,
        "timestamp_to": 1608418799,
        "count": 7
      },
      "num_last_12m": {
        "timestamp_from": 1576710000,
        "timestamp_to": 1608418799,
        "count": 13
      }
    },
    "bank_charges": {
      "num_last_3m": {
        "timestamp_from": 1600466400,
        "timestamp_to": 1608418799,
        "count": 5
      },
      "num_last_6m": {
        "timestamp_from": 1592517600,
        "timestamp_to": 1608418799,
        "count": 7
      },
      "num_last_12m": {
        "timestamp_from": 1576710000,
        "timestamp_to": 1608418799,
        "count": 13
      }
    },
    "utility_payments": {
      "num_last_3m": {
        "timestamp_from": 1600466400,
        "timestamp_to": 1608418799,
        "count": 5
      },
      "num_last_6m": {
        "timestamp_from": 1592517600,
        "timestamp_to": 1608418799,
        "count": 7
      },
      "num_last_12m": {
        "timestamp_from": 1576710000,
        "timestamp_to": 1608418799,
        "count": 13
      }
    },
    "credit_card_payments": {
      "rate_of_charge": 0.66,
      "pred_next_month": 212.33,
      "ratio_to_income": 0.07
    },
    "gambling": {
      "rate_of_charge": 0.36,
      "pred_next_month": 112.33,
      "ratio_to_income": 0.03
    },
    "loan_repayments": {
      "rate_of_charge": ...,
      "pred_next_month": ...,
      "ratio_to_income": ...
    },
    "cash_withdrawals": {
      "rate_of_charge": ...,
      "pred_next_month": ...,
      "ratio_to_income": ...
    },
    "debit_bank_transfer": {
      "rate_of_charge": ...,
      "pred_next_month": ...,
      "ratio_to_income": ...
    },
    "new_debt_indicator": false,
    "debt_management_indicator": false,
    "negative_balance_ratio": 0.01
  },
  "employment": {
    "number_of_salaries": 2,
    "expected_salary": [
      {
        "salary_id": 0,
        "amount": 1800.00
      },
      {
        "salary_id": 1,
        "amount": 300.00
      }
    ],
    "expected_pay_date": [
      {
        "salary_id": 0,
        "date": 1578610800
      },
      {
        "salary_id": 1,
        "date": 1579042800
      }
    ],
    "pay_frequency": [
      {
        "salary_id": 0,
        "frequency": "monthly"
      },
      {
        "salary_id": 1,
        "frequency": "monthly"
      }
    ],
    "possible_loss_of_income_indicator": false,
    "out_of_work_benefit_indicator": false,
    "new_employer_indicator": true
  }
}

In Case of Errors

  • The 401 Unauthorized is returned when access_token is invalid.
  • The 404 Not Found is returned when client_id does not exist in the FriendlyScore database.

Fetch Forecast Data

GET /public/v1/customers/{customerId}/forecasts

Returns forecast by customer id

Prepare Request Parameters

NodeJS Example: /routes/forecast.js

const accessToken = await authService.getAccessToken();
const customers = await customerService.getCustomers(accessToken);
const customerId = customers[0].id;  // get id from first customer

Example Forecast Request

NodeJS Example: /services/forecastService.js

async function getForecast(accessToken, customerId) {
  try {
    const config = {
      method: "GET",
      url: `${baseUrl}/public/v1/customers/${customerId}/forecasts/current`,
      headers: { Authorization: `Bearer ${accessToken}`, ...defaultHeaders },
    };
    const response = await axios(config);

    if (response) {
      const { data } = response;
      return data;
    }
  } catch (e) {
    throw e;
  }
}

The defaultHeaders is defined in /config.js

{
  "Content-Type": "application/json",
  "Accept": "application/json"
}

Example Forecast Response

{
  "credit_score": {
    "generic": {
      "score": 700,
      "band": "b",
      "reason_codes": [
        "a",
        "b",
        "c"
      ]
    },
    "custom": {
      "score": 750,
      "band": "b",
      "reason_codes": [
        "a",
        "b"
      ]
    }
  },
  "affordability": {
    "score": 660,
    "band": "b"
  },
  "financial_forecast": [
    {
      "bank": {
        "name": "Iron Bank of Braavos",
        "slug": "iron-bank",
        "account": [
          {
            "currency": "GBP",
            "type": "Personal",
            "number": "12123412341234123412341234",
            "balance": {
              "actual": [
                {
                  "amount": 5681.31,
                  "date": 1571702400
                },
              ...
              ],
              "forecast": [
                {
                  "amount": 7380.31,
                  "date": 1579564800
                },
              ...
              ]
            }
          }
        ]
      }
    }
  ]
}

In Case of Errors

  • The 401 Unauthorized is returned when access_token is invalid.
  • The 404 Not Found is returned when client_id does not exist in the FriendlyScore database.

Next Steps

Integrate FriendlyScore Connect

Please integrate FriendlyScore Connect for Web component, iOS and Android. Once you have completed the client integrations, you can use the API to retrieve the data.

You can continue to integrate FriendlyScore Connect in your app in our Sandbox and Development environments. Once you have completed testing, you can request access to the Production environment in the developer console or speak directly to your account manager.

Support

Find commonly asked questions and answers in our F.A.Q. You can also contact us via email at developers@friendlyscore.com or speak directly with us on LiveChat.

You can find all the code for FriendlyScore Connect for Web component, iOS and Android on our GitHub.