Quickstart
The Quickstart covers the entire workflow from setting up Truv Bridge to retrieving data with the API.
Introduction
Truv lets you connect to your users to collect data from financial and payroll providers. Get started with Truv and follow the sections below.
Tip
For no-code solutions, use the Truv Postman Collection to get started with Truv's API.
View the complete workflow for getting started with Truv when you clone the Quickstart app. The repository covers each step from initializing Truv Bridge to retrieving data using the API.
Prerequisites
You’ll need the following to get setup with Truv.
- Truv account and Dashboard
- Truv GitHub Quickstart
- API keys
Sign up for Truv through the Dashboard and collect your API keys. With those values, you can start making requests with the API.
Find your API keys under the Development section of your dashboard. Find examples of client_id
and access_key
or Access secret values below.
Value | Description | Example |
---|---|---|
client_id | Private identifier for your team | dd21ca23c12142b6a0970b1e0afedf16 |
access_key | Private key, one for each of the three environments | sandbox-a57b3109f1f4a8b3f2ebbc1c526950f1795464af |
Get the Client ID and Access secret by clicking the Development -> API keys menu item in the Dashboard. Each environment has its own access_key
.
Warning
The Client ID and Access key provide access to sensitive information. Save these values and store them in a secure and private location.
Environments
View the descriptions for sandbox, development, and production environments below.
- Sandbox - For development with test credentials, unlimited requests and free
- Development - For testing integration with live credentials, includes 50 free
Successful
Tasks - Production - For your production environment, all successful Tasks are billed
Tip
Contact [email protected] for any support throughout all steps in the Quickstart.
Configuring your app
When you have your API keys, you can run the Quickstart from Truv's GitHub on your local machine. Truv's GitHub page has examples from the these languages as well.
For mobile platforms, use the Quickstart apps for iOS and Android.
Instructions
The code instructions below guide you through the process on your local machine. It covers cloning the Quickstart repository, customizing the .env
file with your Truv Client ID and Access Secret, and then building and running the app.
# Clone the Quickstart repository
git clone https://github.com/truvhq/quickstart.git
# Open Quickstart
cd quickstart
# Create .env file
make env
# Update the values in .env file by adding in your Client ID and Sandbox Access key.
# API_CLIENT_ID=<Your Client ID here>
# API_SECRET=<Your Access key here>
# Also, in .env uncomment the line with API_PRODUCT_TYPE that you want to use
# API_PRODUCT_TYPE=employment
# API_PRODUCT_TYPE=income
# API_PRODUCT_TYPE=deposit_switch
# API_PRODUCT_TYPE=pll
# API_PRODUCT_TYPE=admin
# Run the make script for your coding language
make python_local
# Clone the Quickstart repository
git clone https://github.com/citadelid/quickstart.git
# Open Quickstart in your coding language
cd quickstart/python
# Copy the .env.example file to a new file in the same directory and name it .env.
cp .env.example .env
# Update the values adding in the your Client ID and Sandbox Access key.
#API_CLIENT_ID=<Your Client ID here>
#API_SECRET=<Your Access key here>
# Uncomment the line with API_PRODUCT_TYPE that you want to use
#API_PRODUCT_TYPE=employment
#Run the make script for your coding language
make python_docker
/*
Clone the Quickstart repository:
git clone https://github.com/truvhq/quickstart-ios.git
Open Quickstart:
cd quickstart-ios
Create constants file:
touch truv-quickstart/Constants.swift
*/
import Foundation
var TruvClientID = "<client_id>"
var TruvClientSecret = "<access_key>"
var TruvAPIUrl = "https://prod.truv.com/v1/"
var TruvProductType = "<employment or income>"
/*
Open the project in XCode and run the app
*/
/*
Clone the Quickstart repository:
git clone https://github.com/truvhq/quickstart-android.git
Open Quickstart:
cd quickstart-android
Create constants file:
touch local.properties
*/
truvClientId="<client_id>"
truvSecret="<access_key>"
truvApiUrl="https://prod.truv.com/v1/"
truvProductType="<employment or income>"
/*
Open the project in Android Studio and run the app
*/
Your app will be running at http://localhost:5000
. iOS and Android mobile apps launch in Xcode or Android Studio, respectively.
Creating your first Link
The Truv Link is a login attempt at a payroll provider, work account or financial institution. The Truv API requests interact with Links to exchange end-user credentials for access to payroll provider information. Links contain the required context to represent the end-user.
Users can have a single or multiple accounts with different providers. Links act as the connection between a user’s payroll provider and employer.
For users, the number of links is related to the number of payroll providers using that login information. The table below has examples of users, employers, payrolls, and Link totals.
User | Employer & payroll provider | Number of Links |
---|---|---|
John Doe | - Company A, provider A - Company B, provider A | 1 |
Jane Smith | - Company C, provider B - Company D, provider C | 2 |
Adding Link to app in sandbox environment
After you’ve run your Quickstart app, add your first Link in the sandbox. When your Quickstart app is open, click Connect and follow the instructions in Truv Bridge.
Use the sandbox credentials below for simulating a successful login. The sandbox environment allows you to login with multiple credentials. These provide various scenarios for testing data.
- username -
goodlogin
- password -
goodpassword
- For multi-factor authentication prompts -
12345
To view the data from Truv, click Done at the end of the Bridge session.
Truv process summary
The Truv workflow covers your application, Truv Bridge, your server, and the Truv API. View the steps below to learn more about the communication between each component.
- The application uses the
bridge_token
to make a request to your server. - Your server makes a POST request with the user information to the Truv API.
- After the API processes the exchange, your application then prompts the user to connect payroll information in Truv Bridge.
- When successful, Truv Bridge returns the required credentials to your application.
- During this step, your server monitors webhook events from the Truv API.
- With the
public_token
, your application makes an exchange to your server and the Truv API for access. - After your server collects the appropriate credentials, it can complete the request to get data from the Truv API.
Summary of sequence diagram
The chart below is an overview of the steps in the process.
Requesting bridge_token value
The bridge_token
is the first value required to authenticate your app with Truv Bridge. This is a temporary single-use token for a user. When you create a new user, make a request to the Create a bridge token endpoint for the bridge_token value.
You can also pass environment variables from the Quickstart configuration as parameters. This helps you streamline the experience for your users with auto-populating or pre-filling information.
def create_user(self, **kwargs) -> dict:
logging.info("TRUV: Requesting new user from https://prod.truv.com/v1/users/")
payload = {
"external_user_id": f"qs-{uuid4().hex}",
"first_name": "John",
"last_name": "Johnson",
"email": "[email protected]",
**kwargs,
}
return self.post("users/", json=payload)
def create_user_bridge_token(self, user_id: str) -> dict:
logging.info(
"TRUV: Requesting user bridge token from https://prod.truv.com/v1/users/{user_id}/tokens"
)
logging.info("TRUV: User ID - %s", user_id)
payload = {
"product_type": self.product_type,
"tracking_info": "1338-0111-A",
}
if self.product_type in ["deposit_switch", "pll"]:
payload["account"] = {
"account_number": "16002600",
"account_type": "checking",
"routing_number": "12345678",
"bank_name": "Example Bank",
}
if self.product_type == "pll":
payload["account"].update(
{
"deposit_type": "amount",
"deposit_value": "100",
}
)
return self.post(f"users/{user_id}/tokens/", json=payload)
const createUser = async () => {
console.log('TRUV: Requesting a user from https://prod.truv.com/v1/users/');
const bodyObj = {
external_user_id: `qs-${uuidv4()}`,
first_name: 'John',
last_name: 'Johnson',
email: '[email protected]',
};
const body = JSON.stringify(bodyObj);
const responseBody = await sendRequest('users/', { body });
return responseBody;
};
const createUserBridgeToken = async (user_id) => {
console.log('TRUV: Requesting user bridge token from https://prod.truv.com/v1/users/{user_id}/tokens');
console.log(`TRUV: User ID - ${user_id}`);
const bodyObj = {
product_type: API_PRODUCT_TYPE,
client_name: 'Truv Quickstart',
tracking_info: '1338-0111-A',
};
if (API_PRODUCT_TYPE === 'pll' || API_PRODUCT_TYPE === 'deposit_switch') {
bodyObj.account = {
account_number: '16002600',
account_type: 'checking',
routing_number: '123456789',
bank_name: 'TD Bank',
};
if (API_PRODUCT_TYPE === 'pll') {
bodyObj.account = { ...bodyObj.account, deposit_type: 'amount', deposit_value: '100' };
}
}
const body = JSON.stringify(bodyObj);
const responseBody = await sendRequest(`users/${user_id}/tokens/`, { body });
return responseBody;
};
func createUser() (string, error) {
log.Println("TRUV: Requesting new user from https://prod.truv.com/v1/users/")
uniqueNumber := time.Now().UnixNano() / (1 << 22)
userRequest := UserRequest{
ExternalUserId: fmt.Sprintf("qs-%d", uniqueNumber),
FirstName: "John",
LastName: "Johnson",
Email: "[email protected]",
}
userJson, _ := json.Marshal(userRequest)
request, err := getRequest("users/", "POST", userJson)
if err != nil {
return "", err
}
client := &http.Client{}
res, err := client.Do(request)
if err != nil {
return "", err
}
defer res.Body.Close()
user := UserResponse{}
err = json.NewDecoder(res.Body).Decode(&user)
return user.UserId, nil
}
func createUserBridgeToken(userId string) (string, error) {
log.Println("TRUV: Requesting user bridge token from https://prod.truv.com/v1/users/{user_id}/tokens")
log.Printf("TRUV: User ID - %s\n", userId)
productType := os.Getenv("API_PRODUCT_TYPE")
bridgeTokenRequest := BridgeTokenRequest{
ProductType: productType,
TrackingInfo: "1338-0111-A",
}
if productType == "pll" || productType == "deposit_switch" {
account := AccountRequest{
AccountNumber: "1600200",
AccountType: "checking",
RoutingNumber: "123456789",
BankName: "TD Bank",
}
if productType == "pll" {
account.DepositType = "amount"
account.DepositValue = "1"
}
bridgeTokenRequest.Account = &account
}
bridgeJson, _ := json.Marshal(bridgeTokenRequest)
request, err := getRequest(fmt.Sprintf("users/%s/tokens/", userId), "POST", bridgeJson)
if err != nil {
return "", err
}
client := &http.Client{}
response, err := client.Do(request)
if err != nil {
return "", err
}
defer response.Body.Close()
data, _ := ioutil.ReadAll(response.Body)
return (string(data)), nil
}
Initializing Truv Bridge
Users log into their payroll accounts through Truv Bridge. After retrieving the bridge_token
, use that value to initialize the Bridge. Truv Bridge is a client-side module to handle the authentication process. It’s available as a drop-in for web clients, iOS, and Android platforms.
For the Quickstart app, the Bridge module is on the web. It uses a JavaScript integration triggered from client-side code. In the front-end, the application runs TruvBridge.init to pass the bridge_token
from the back-end. From there, it assigns callback functions as needed. View the code sample below for more details.
const bridge = TruvBridge.init({
bridgeToken: bridgeToken.bridge_token,
onLoad: function() { ... },
onSuccess: function(public_token, meta) { ... },
onEvent: function(event_type, payload) { ... },
onClose: function() { ... }
});
window.bridge = bridge;
Submitting credentials for public_token
Truv Bridge provides you with a public_token value after a user submits their credentials. This happens through the onSuccess callback. The JavaScript code below covers the public_token
exchange between the client-side code and the server.
onSuccess: async function (token) {
console.log('token: ', token);
successClosing = true
const content = document.querySelector('.spinnerContainer');
content.classList.remove('hidden');
let verificationInfo;
try {
verificationInfo = await apiRequests.getVerificationInfoByToken(token);
} catch(e) {
console.error(e)
content.classList.add('hidden');
return;
}
content.classList.add('hidden');
if (!verificationInfo.length) {
return;
}
},
...
onClose: function () {
console.log('closed');
if (successClosing !== true) {
renderEmploymentHistory([{ company: { address: {} } }]);
}
},
Note
The
public_token
is temporary and expires after 6 hours.
Server side exchanges
The quickstart application goes through the server to Retrieve a link token for the access_token
and a link_id
. These two new values are required to identify a Link. Truv API endpoints also require these values as arguments. Like with other important values, store the access_token
and link_id
in a secure and private location when making API requests.
The code samples below demonstrate the server actions.
def get_access_token(self, public_token: str) -> dict:
logging.info(
"TRUV: Exchanging a public_token for an access_token from https://prod.truv.com/v1/link-access-tokens"
)
logging.info("TRUV: Public Token - %s", public_token)
return self.post(
"link-access-tokens/",
json={
"public_token": public_token,
},
)
const getAccessToken = async (public_token) => {
console.log('TRUV: Exchanging a public_token for an access_token from https://prod.truv.com/v1/link-access-tokens');
console.log(`TRUV: Public Token - ${public_token}`);
const body = JSON.stringify({
public_token: public_token,
});
const responseBody = await sendRequest('link-access-tokens/', { body });
return responseBody;
};
func getAccessToken(public_token string) (string, error) {
log.Println("TRUV: Exchanging a public_token for an access_token from https://prod.truv.com/v1/link-access-tokens")
log.Printf("TRUV: Public Token - %s\n", public_token)
publicToken := PublicTokenRequest{PublicToken: public_token}
jsonPublicToken, _ := json.Marshal(publicToken)
accessToken := AccessTokenResponse{}
request, err := getRequest("link-access-tokens/", "POST", jsonPublicToken)
if err != nil {
return "", err
}
client := &http.Client{}
res, err := client.Do(request)
if err != nil {
return "", err
}
defer res.Body.Close()
err = json.NewDecoder(res.Body).Decode(&accessToken)
if err != nil {
return "", err
}
return accessToken.AccessToken, nil
}
Example income and employment report
The examples below go over requesting an income and employment report after a successful connection. These use the quickstart app to Retrieve an income and employment report for more about the user’s profile, company, and other employment information.
def get_income_info_by_link_id(self, link_id: str) -> dict:
logging.info(
"TRUV: Requesting income report data from https://prod.truv.com/v1/links/:link_id/income/report"
)
logging.info("TRUV: Link ID - %s", link_id)
return self.get(f"links/{link_id}/income/report")
const getIncomeInfoByLinkId = async (link_id) => {
console.log(
'TRUV: Requesting income verification data from https://prod.truv.com/v1/links/:link_id/income/report',
);
console.log(`TRUV: Link ID - ${link_id}`);
return await sendRequest('links/${link_id}/income/report', { method: "GET" });
};
func getIncomeInfoByLinkId(link_id string) (string, error) {
log.Println("TRUV: Requesting income verification data from https://prod.truv.com/v1/links/:link_id/income/report")
log.Printf("TRUV: Link ID - %s\n", link_id)
request, err := getRequest(fmt.Sprintf("links/%s/income/report", link_id), "GET", nil)
if err != nil {
return "", err
}
client := &http.Client{}
res, err := client.Do(request)
if err != nil {
return "", err
}
defer res.Body.Close()
data, _ := ioutil.ReadAll(res.Body)
return string(data), nil
}
Example response data
This JSON object is a sample payload for the income and employment report request.
{
"id": "24d7e80942ce4ad58a93f70ce4115f5c",
"status": "new",
"completed_at": "2021-04-06 11:30:00+00:00",
"access_token": "48427a36d43c4d5aa6324bc06c692456",
"tracking_info": "user123456",
"refresh_status": "new",
"employments": [
{
"id": "24d7e80942ce4ad58a93f70ce4115f5c",
"job_title": "PR associate",
"job_type": "F",
"start_date": "2018-01-01",
"end_date": "2019-08-24",
"external_last_updated": "2019-08-24",
"original_hire_date": "2017-06-21",
"is_active": false,
"dates_from_statements": false,
"derived_fields": [
"is_active"
],
"missing_data_fields": [
"w2s"
],
"profile": {
"first_name": "John",
"last_name": "Doe",
"middle_initials": "K",
"ssn": "123456789",
"email": "[email protected]",
"date_of_birth": "1992-03-03",
"home_address": {
"street": "1 Morgan Ave",
"city": "Los Angeles",
"state": "CA",
"zip": "90210"
}
},
"company": {
"name": "Facebook Demo",
"address": {
"street": "1 Hacker Way",
"city": "Menlo Park",
"state": "CA",
"zip": "94025"
},
"phone": "6503087300"
},
"income": "70000.00",
"income_unit": "YEARLY",
"pay_frequency": "M",
"manager_name": "Jenny McDouglas",
"statements": [
{
"id": "24d7e80942ce4ad58a93f70ce4115f5c",
"pay_date": "2018-05-15",
"net_pay": "11500.32",
"net_pay_ytd": "31980.64",
"gross_pay": "13900.11",
"gross_pay_ytd": "49200.00",
"bonus": "100.00",
"commission": "12000.00",
"hours": "40.00",
"basis_of_pay": "S",
"period_start": "2018-05-01",
"period_end": "2018-05-15",
"regular": "1695.11",
"regular_ytd": "23000.00",
"bonus_ytd": "1000.00",
"commission_ytd": "24000.00",
"overtime": "45.00",
"overtime_ytd": "500.00",
"other_pay": "60.00",
"other_pay_ytd": "700.00",
"earnings": [
{}
],
"earnings_ytd": [
{}
],
"deductions": [
{}
],
"deductions_ytd": [
{}
],
"md5sum": "03639d6a6624f69a54a88ea90bd25e9d",
"file": "https://citadelid-resources.s3-us-west-2.amazonaws.com/paystub_sample.pdf"
}
],
"annual_income_summary": [
{
"id": "24d7e80942ce4ad58a93f70ce4115f5c",
"year": 2018,
"regular": "23000.00",
"bonus": "1000.00",
"commission": "24000.00",
"overtime": "500.00",
"other_pay": "700.00",
"net_pay": "31980.64",
"gross_pay": "49200.00"
}
],
"bank_accounts": [
{
"account_number": "1234567890",
"routing_number": "123456789",
"account_name": "My Bank",
"account_type": "C",
"deposit_type": "A",
"deposit_value": "200.00",
"bank_name": "TD Bank"
}
],
"annual_salary": "70000.00",
"hourly_salary": "36.40",
"w2s": [
{
"file": "https://citadelid-resources.s3-us-west-2.amazonaws.com/W2_sample.pdf",
"md5sum": "f65e30c39124ad707ac4b3aeaee923a7",
"year": 2020
}
]
}
],
"provider": "adp"
}
Next steps
Congratulations!
You've completed the Truv Quickstart!
Use the quickstart code samples as an opportunity to expand on your experience with the Truv API.
Product guides
Learn more about our products through the guides below.
- Income and Employment, VOIE
- Employment History, VOE
- Direct Deposit Switch, DDS
- Paycheck Linked Loans, PLL
Mobile integrations
For mobile integrations of Truv, learn more about getting started through the Bridge SDK .
Demo applications
Our sample apps page has additional examples, including real-world use cases.
Updated about 2 months ago
Learn more about other products, such as verifying income and employment and other guides and check out our Postman Collection as well.