Fiserv Banking APIs Made Simple — Part 1: Authentication

Chintana Wilamuna
4 min readMay 27, 2023
Building of a bank (generated with AI)

Fiserv is a prominent global financial services technology company that plays a vital role in the industry. With a wide range of software and services, it caters to financial institutions worldwide, including banks, credit unions, investment firms, and insurance companies. Fiserv’s technologies facilitate various financial transactions such as online banking, mobile payments, card processing, and electronic billing, among others.

This blog post explores how Fiserv APIs can be integrated to provide a simplified experience for app developers. Ballerina language is used to quickly create APIs.

Authentication with Fiserv APIs

First step is figuring out the authentication logic. After authentication is successful, we can call any API from the catalog depending on the use case. Note that after authentication, Fiserv APIs require setting some headers and we’ll get to that in a second.

Let’s define a function to call the auth APIs and get an access token.

import ballerina/http;
import ballerina/mime;

type Token record {
string access_token;
string token_type;
string expires_in;
};

function getAccessToken() returns Token|error {
http:Request tokenReq = new;
tokenReq.setTextPayload("grant_type=client_credentials");
tokenReq.setHeader(mime:CONTENT_TYPE, mime:APPLICATION_FORM_URLENCODED);
http:Client req = check new(hostname,
auth = {
username: clientID,
password: clientSecret
}
);
json tokenRes = check req->post("/fts-apim/oauth2/v2", tokenReq);
Token token = check tokenRes.cloneWithType(Token);
return token;
}

Even if you’re new to Ballerina, you should be able to read it fairy easily.

  • Import http and mime modules
  • Define a type to represent a token. This maps nicely to the JSON payload format we get from Fiserv. Field names here maps 1:1 to field names returned in the JSON message
  • A function name getAccessToken that returns either a Token object OR an error
  • We create the http request object and set the payload as grant type client_credentials This is standard OAuth jargon and the grant type is used for system to system authentication
  • Set the content type header — Note that Ballerina provides us with constants defined in the mime module so we don’t have to type these as strings
  • We set clientId and clientSecret as authentication params. Actual values are generated from the Fiserv dev portal
  • We call the auth API, convert the JSON payload to the token type we defined earlier and return it

Then we can incrementally add stuff to this program and create our integration.

Creating an HTTP service

Let’s create a simple service skeleton and use the access token and see what we get. I’m just showing the relevant imports to make the code readable.

import ballerina/http;
import ballerina/jwt;

service / on new http:Listener(9090) {
resource function get accountDetails() returns error? {
Token authToken = check getAccessToken();
[jwt:Header, jwt:Payload] [header, payload] = check jwt:decode(authToken.access_token);
io:println("Header: ", header);
io:println("Payload: ", payload);
}
}

Let’s see what’s going on here,

  • Importing http and jwt libraries
  • Defining a new service on / (root path) with port 9090
  • Defining a resource function — This represent the path after the hostname, like http://hostname:port/<path>. So above definition maps to http://localhost:9090/accountDetails
  • After we get the access token we can decode the JWT (JSON Web Token) using the jwt library and display the header and payload portion
  • The payload is important because we can figure out things like who issued this token, expiration time and other metadata

Credential management

Before calling this service we have to provide actual credentials we got from Fiserv portal.

In Ballerina, we don’t have to hard code these credentials to the program itself. Language provides an in-built mechanism where we can define a variable that’s going to be available at runtime. This is named as “configurables”

For our example, it’ll be,

configurable string clientID = ?;
configurable string clientSecret = ?;
configurable string hostname = ?;

When we’re running this locally, we can provide these values in a file. This file should be in the root directory of the project and named Config.toml. Content is a simple key value pair,

clientID = "fY3..."
clientSecret = "kyn..."
hostname = "https://cert.api.fiservapps.com"

Here’s the full source for the program so far,

import ballerina/http;
import ballerina/mime;
import ballerina/io;
import ballerina/jwt;

configurable string clientID = ?;
configurable string clientSecret = ?;
configurable string hostname = ?;

type Token record {
string access_token;
string token_type;
string expires_in;
};

service / on new http:Listener(9090) {
resource function get accountDetails() returns error? {
Token authToken = check getAccessToken();
[jwt:Header, jwt:Payload] [header, payload] = check jwt:decode(authToken.access_token);
io:println("Header: ", header);
io:println("Payload: ", payload);
}
}

function getAccessToken() returns Token|error {
http:Request tokenReq = new;
tokenReq.setTextPayload("grant_type=client_credentials");
tokenReq.setHeader(mime:CONTENT_TYPE, mime:APPLICATION_FORM_URLENCODED);
http:Client req = check new(hostname,
auth = {
username: clientID,
password: clientSecret
}
);
json tokenRes = check req->post("/fts-apim/oauth2/v2", tokenReq);
Token token = check tokenRes.cloneWithType(Token);
return token;
}

When we run this we should see a token printed on the command line (I formatted the JSON for readability. This will be printed on the console as a single line),

Header: 
{
"alg": "RS256",
"kid": "1",
"pi.atm": "aauq"
}
Payload:
{
"iss": "https://fdc-fedsso-cat.firstdata.com",
"exp": 1685149003,
"scope": "",
"authorization_details": [],
"client_id": "fY3...",
"channel": "online",
"vendorId": "9999...",
"applicationId": "9999...",
"applicationName": "BHTRIALAPP",
"fsFriendlyId": "Docp..."
}

Now that we successfully authenticated to the API the next step is to call which ever API we want from the catalog.

Continued Part 2 — API Calls and Data Mapping

--

--