# Generating an API Client Library
source: https://developer.mastercard.com/open-finance-us/documentation/integration-and-testing/generating-an-api-client-library/index.md

Once you have explored the APIs and are ready to consume the Open Finance APIs directly from your application code, you can speed things up by leveraging the API specification to generate a client library. This approach provides type-safe API calls and reduces the amount of boilerplate code you need to write.
[![](https://img.shields.io/github/stars/Mastercard/finicity-openapi.svg?label=View%20on%20GitHub&style=social)](https://github.com/Mastercard/open-banking-us-openapi)

## Prerequisites {#prerequisites}

Before generating a client library, you should:

1. [Generate your credentials](https://developer.mastercard.com/open-finance-us/documentation/quick-start-guide/index.md#generate-your-credentials) (Partner ID, Partner Secret, and App Key)
2. Install [OpenAPI Generator](https://openapi-generator.tech/docs/installation)

## Generate the Client Library {#generate-the-client-library}

1. Download [openbanking-us.yaml](https://static.developer.mastercard.com/content/open-finance-us/swagger/openbanking-us.yaml) (1MB)
2. Generate an Open Finance API client library using [OpenAPI Generator](https://openapi-generator.tech/docs/installation) and the development framework of your choice (see also: [Generators List](https://openapi-generator.tech/docs/generators/)):
   * Java
   * C#
   * Javascript
   * Python

   ```sh
   openapi-generator-cli generate -g java -i *.yaml -o api_client
   ```

   ```sh
   openapi-generator-cli generate -g csharp-netcore -i *.yaml -o api_client
   ```

   ```sh
   openapi-generator-cli generate -g javascript -i *.yaml -o api_client
   ```

   ```sh
   openapi-generator-cli generate -g python -i *.yaml -o api_client
   ```

## Adding Authentication {#adding-authentication}

Add some code to automatically attach the `Finicity-App-Token` and `Finicity-App-Key` HTTP headers to requests (see example [here](https://github.com/Mastercard/open-banking-us-openapi/blob/main/tests/src/test/java/com/mastercard/openbanking/client/test/OpenBankingAuthInterceptor.java#L16)):
* Java
* C#
* Javascript
* Python

```java
// An example of okHttp3 interceptor handling Mastercard Open Finance authentication.
public class OpenBankingAuthInterceptor implements Interceptor {

    private final AuthenticationApi authenticationApi;
    private final String partnerId;
    private final String partnerSecret;
    private final String appKey;

    private String token;
    private LocalDateTime tokenExpiryTime;

    public OpenBankingAuthInterceptor(String partnerId, String partnerSecret, String appKey) {
        this.partnerId = partnerId;
        this.partnerSecret = partnerSecret;
        this.appKey = appKey;
        this.authenticationApi = new AuthenticationApi();
    }

    @NotNull
    public Response intercept(@NotNull Chain chain) throws IOException {
        try {
            // Always add "Finicity-App-Key"
            var request = chain.request();
            var requestBuilder = request
                    .newBuilder()
                    .addHeader("Finicity-App-Key", this.appKey);

            var url = request.url().toString();
            if (url.contains("/authentication")) {
                // No "Finicity-App-Token" header needed for /authentication
                return chain.proceed(requestBuilder.build());
            }

            if (this.tokenExpiryTime == null || this.tokenExpiryTime.isBefore(LocalDateTime.now())) {
                this.refreshToken();
            }

            // Add access token to the "Finicity-App-Token" header
            requestBuilder = requestBuilder
                    .addHeader("Finicity-App-Token", this.token);
            return chain.proceed(requestBuilder.build());
        } catch (Exception e) {
            throw new IOException(e.getMessage());
        }
    }

    private void refreshToken() throws ApiException {
        this.token = createToken();
        this.tokenExpiryTime = LocalDateTime.now().plusMinutes(90);
    }

    private String createToken() throws ApiException {
        return authenticationApi.createToken(new PartnerCredentials()
                .partnerId(partnerId)
                .partnerSecret(partnerSecret)).getToken();
    }
  }
```

```csharp
// Create a FinicityApiClient.cs file that extends the partial ApiClient from ApiClient.cs
namespace Org.OpenAPITools.Client
{
    public partial class ApiClient
    {
        private readonly string _partnerId;
        private readonly string _partnerSecret;
        private readonly string _appKey;

        private string _token;
        private DateTime _tokenExpiryTime;

        public ApiClient(string partnerId, string partnerSecret, string appKey)
        {
            _baseUrl = GlobalConfiguration.Instance.BasePath;
            _appKey = appKey;
            _partnerId = partnerId;
            _partnerSecret = partnerSecret;
        }

        partial void InterceptRequest(IRestRequest request)
        {
            // Always add "Finicity-App-Key"
            request.AddHeader("Finicity-App-Key", _appKey);

            var url = request.Resource;
            if (url.Contains("/authentication")) {
                // No "Finicity-App-Token" header needed for /authentication
                return;
            }

            if (_tokenExpiryTime < DateTime.Now) {
                RefreshToken();
            }

            // Add access token to the "Finicity-App-Token" header
            request.AddHeader("Finicity-App-Token", _token);
        }

        private void RefreshToken() {
            _token = CreateToken();
            _tokenExpiryTime = DateTime.Now.AddMinutes(90);
        }

        private string CreateToken()
        {
            var credentials = new PartnerCredentials(_partnerId, _partnerSecret);
            var authenticationApi = new AuthenticationApi { Client = this };
            return authenticationApi.CreateToken(credentials).Token;
        }
    }
}
```

```javascript
// Credentials
const PARTNER_ID = "{{partnerId}}"
const PARTNER_SECRET = "{{partnerSecret}}"
const APP_KEY = "{{appKey}}"

// Token
let expiry = null
let token = null

// Create the API client
const createClient = function (openAPIClient) {
  // Use a promise to ensure the token has been added before sending the request
  return new Promise((resolve) => {
    let client = openAPIClient.ApiClient.instance;
    let authApi = new AuthenticationApi(client)

    // Add the Finicity-App-Key header for every request
    client.applyAuthToRequest = function (request) {
      const _end = request._end;
      request._end = function () {
        request.req.setHeader('Finicity-App-Key', APP_KEY);
        _end.call(request);
      };
      return request;
    };

    // If the token doesn't exist or has expired, refresh it
    let tokenPromise = function refreshToken() {
      return new Promise((resolve) => {
        if (expiry === null || expiry < new Date()) {
          authApi.createToken(new PartnerCredentials(PARTNER_ID, PARTNER_SECRET),
              (error, data, response) => {
                if (!error) {
                  expiry = new Date();
                  token = data.token;
                  resolve();
                }
              });
        } else {
          resolve()
        }
      })
    }

    // Apply the token to the request headers
    tokenPromise().then(() => {
      client.applyAuthToRequest = function (request) {
        const _end = request._end;
        request._end = function () {
          request.req.setHeader('Finicity-App-Key', APP_KEY);
          request.req.setHeader('Finicity-App-Token', token);
          _end.call(request);
        };
        return request;
      };
      resolve(client);
    })
  })
};
```

```python
import datetime
from functools import wraps

import openapi_client

from openapi_client.api.authentication_api import AuthenticationApi
from openapi_client.api.connect_api import ConnectApi
from openapi_client.models.connect_parameters import ConnectParameters


class ApiClient(object):
    # Credentials
    partner_id = "{{partnerId}}"
    partner_secret = "{{partnerSecret}}"
    app_key = "{{appKey}}"

    # API Client
    api_client = None

    # Token details
    token = None
    expiry = None

    @classmethod
    def __init__(self):
        conf = openapi_client.Configuration()
        conf.verify_ssl = False
        conf.ssl_ca_cert = None
        conf.assert_hostname = False
        conf.cert_file = None

        api_client = openapi_client.ApiClient(conf)
        self.add_authentication(self=self, api_client=api_client)
        self.api_client = api_client

    def add_authentication(self, api_client):
        api_client.rest_client.request = self.authenticate(self, api_client.rest_client.request)

    def authenticate(self, func):
        @wraps(func)
        def call_api_function(*args, **kwargs):
            kwargs['headers']['Finicity-App-Key'] = self.app_key
            if self.expiry is None or self.expiry < datetime.datetime.now():
                self.refresh_token(self)
                kwargs['headers']['Finicity-App-Token'] = self.token

            return func(*args, **kwargs)

        return call_api_function

    def refresh_token(self):
        current_date = datetime.datetime.now()
        expiry_date = current_date + datetime.timedelta(minutes=90)
        self.expiry = expiry_date

        request_body = {
            'partner_id': self.partner_id,
            'partner_secret': self.partner_secret
        }
        auth_response = AuthenticationApi(self.api_client).create_token(partner_credentials=request_body)
        self.token = auth_response.token
```

<br />

## Using the Client Library {#using-the-client-library}

Configure your `ApiClient` instance and use one of the `*Api` classes (see example [here](https://github.com/Mastercard/open-banking-us-openapi/blob/main/tests/src/test/java/com/mastercard/openbanking/client/test/BaseTest.java#L44)):
* Java
* C#
* Javascript
* Python

```java
var apiClient = Configuration.getDefaultApiClient();
apiClient.setDebugging(true);
apiClient.setConnectTimeout(240000);
apiClient.setReadTimeout(240000);
apiClient.setHttpClient(
        apiClient.getHttpClient()
                .newBuilder()
                .addInterceptor(new FinicityAuthInterceptor("{{partnerId}}", "{{partnerSecret}}", "{{appKey}}"))
                .build());

// Generate a Data Connect URL
var api = new ConnectApi(apiClient);
var params = new ConnectParameters()
        .customerId(CUSTOMER_ID)
        .partnerId(PARTNER_ID);
var connectUrl = api.generateConnectUrl(params);
var link = connectUrl.getLink();
```

```csharp
var apiClient = new ApiClient("{{partnerId}}", "{{partnerSecret}}", "{{appKey}}");

// Generate a Data Connect URL
var connectApi = new ConnectApi { Client = apiClient };
var connectParameters = new ConnectParameters(PartnerId, CustomerId);
var connectUrl = connectApi.GenerateConnectUrl(connectParameters);
var link = connectUrl.Link;
```

```javascript
let client = await createClient(OpenAPIClient);

// Generate a Data Connect URL
let connectApi = new ConnectApi(client)
let connectParameters = new ConnectParameters(CUSTOMER_ID, PARTNER_ID)

let connectResponse

api.generateConnectUrl(connectParameters,
  (error, data, response) => {
    connectResponse = response
    done();
  });
done();
```

```python
customer_id = "{{customerId}}"
api_client = ApiClient()
connect_parameters = ConnectParameters(
  partner_id=api_client.partner_id,
  customer_id=customer_id)

# Generate a Data Connect URL
response = ConnectApi(api_client.api_client).generate_connect_url(connect_parameters=connect_parameters)

print("Data Connect URL: ", response.link)
```

<br />

You are now ready to use Mastercard Open Finance in your application.

![Data Connect URL from IntelliJ](https://static.developer.mastercard.com/content/open-finance-us/uploads/intellij-test.png)

## See Also {#see-also}

* [Quick Start Guide](https://developer.mastercard.com/open-finance-us/documentation/quick-start-guide/index.md)
* [Using the Postman Collection](https://developer.mastercard.com/open-finance-us/documentation/integration-and-testing/postman-collection/index.md)
* [Test Profiles](https://developer.mastercard.com/open-finance-us/documentation/integration-and-testing/test-the-apis/index.md)
* [API Reference](https://developer.mastercard.com/open-finance-us/documentation/api-reference/index.md)
