Implementation

Follow this step-by-step guide to integrate your VOIE solution.

Verifying income and employment data for your applicants results in increased conversion, reduced risk, and lower costs for your business. Over the years, we have helped many customers integrate Argyle and start using real-time employment data to improve their business outcomes.
We suggest integrating Argyle in two phases:

  • Scoping - determine how you want to use Argyle and how to present the Argyle experience to your clients.
  • Technical implementation (this guide) - a quickstart guide to get you up and running.

Step 1: Upload your logo

Upload logoUpload logo

You can upload your logo under the Company details tab in your Settings menu via Argyle Console.


Step 2: Implement Argyle Link

If you want the users to connect their employment accounts while they are on your website or app, you need to integrate Argyle Link. See below an example configuration to start:

VOIE Link configuration

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
  </head>
  <body>
    <script src="https://plugin.argyle.com/argyle.web.v3.js"></script>
    <script type="text/javascript">
      const argyle = Argyle.create({
        linkKey: 'YOUR_LINK_KEY', // insert your Link key here. It can be found in the Argyle Console.
        apiHost: 'https://api-sandbox.argyle.com/v1', // sandbox environment is used in this example. Change to production environment before launching.
        linkItems: [], // add Link item IDs (e.g. ‘Starbox’) if you want to constrain the Link item list in the search screen.
        onAccountConnected: ({ accountId, userId, linkItemId }) => {
          console.log('Account connected: ', accountId, ' User ID:', userId, ' Link Item ID:', linkItemId) // save the accountId
        },
        onUserCreated: ({ userId, userToken }) => {
          console.log('User created: ', userId, 'User token:', userToken)
        } // save the userId and userToken
      })
      argyle.open()
    </script>
  </body>
</html>
class ViewController: UIViewController {

  override func viewDidLoad() {
    _ = Argyle.shared
      .loginWith(
        linkKey: "YOUR_LINK_KEY", // insert your Link key here. It can be found in the Argyle Console.
        apiHost: "https://api-sandbox.argyle.com/v1") // sandbox environment is used in this example. Change to production environment before launching.
      .linkItems([]) // add Link item IDs (e.g. "Starbox") if you want to constrain the Link item list in the search screen.
      .resultListener(self)
  }

  @IBAction func argyleNewUser(_ sender: Any) {
    let argyle = Argyle.shared.controller
    argyle.modalPresentationStyle = .fullScreen
    self.present(argyle, animated: true, completion: nil)
  }
}

extension ViewController: ArgyleResultListener {

    func onUserCreated(token: String, userId: String) {
        print("APP: onUserCreated((token: \(token), userId: \(userId))")
        // save user token and userId
    }

    func onAccountConnected(accountId: String, userId: String, linkItemId: String) {
        print("APP: onAccountConnected(accountId: \(accountId), userId: \(userId), linkItemId: \(linkItemId))")
        // save accountId
    }
    // rest of callbacks (all callbacks must be implemented)
}
val config = ArgyleConfig.Builder()
    .loginWith(
        "YOUR_LINK_KEY", // insert your Link key here. It can be found in the Argyle Console.
        "https://api-sandbox.argyle.com/v1", // sandbox environment is used in this example. Change to production environment before launching.
        "")
    .linkItems(arrayOf("")) // add Link item IDs (e.g. "Starbox") if you want to constrain the Link item list in the search screen.
    .setCallbackListener(object : Argyle.ArgyleResultListener {

        override fun onUserCreated(userToken: String, userId: String) {
            // save userToken and userId 
            Log.d("Result", "onUserCreated:  userId: $userId, userToken: $userToken")
        }

        override fun onAccountConnected(accountId: String, userId: String, linkItemId: String) {
            // save accountId
            Log.d("Result", "onAccountConnected: accountId: $accountId, userId: $userId, linkItemId: $linkItemId")
        }
        // more callbacks available
    })
    .build()

Argyle.instance.init(config)
Argyle.instance.startSDK(this)
import ArgyleSdk from '@argyleio/argyle-plugin-react-native'

// Configure the SDK before hand, once. only call ArgyleSdk.start() when the UI is needed
ArgyleSdk.loginWith(
    "YOUR_LINK_KEY", // insert your Link key here. It can be found in the Argyle Console.
    "https://api-sandbox.argyle.com/v1", // sandbox environment is used in this example. Change to production environment before launching. 
    "")

ArgyleSdk.onUserCreated(res => console.log("onUserCreated", res)) // save userToken and userId 
ArgyleSdk.onAccountConnected(res => console.log("onAccountConnected", res))
// more callbacks available

ArgyleSdk.linkItems([])  // add Link item IDs (e.g. "Starbox") if you want to constrain the Link item list in the search screen.

// Launch the SDK
ArgyleSdk.start()

👍

You can also integrate Argyle Link for Android, iOS, or React Native.

Notice that the apiHost configuration parameter in the example code points to https://api-sandbox.argyle.com/v1. This ensures that the plugin starts in a sandbox environment where you can use the sandbox credentials below to test Argyle Link.

Save these three values to be used later:

  • accountId - the onAccountConnected callback passes the accountId when an employment account is successfully connected. You need this later to discover when the employment information has been fully synchronized.
  • userId - the onUserCreated callback passes the userId when a user is created. The userId connects all accountIds in the case where a user has more than one employer (e.g. two part-time jobs).
  • userToken - the onUserCreated callback passes the userToken when a user is created. You need this later to ensure user's permissions are scoped to the specified user's data. This allows users to add new accounts or revoke access to their existing accounts. The token is short-lived and a new one should be generated using API at some point.

User tokens

User tokens are temporary access keys that allow you to start Argyle Link for an already existing user.

They are JWT tokens that contain an expiry date you can use to determine if it is necessary to create a new user token. Newly issued tokens expire in 30 days. You can always decode the token to discover the exact expiration date (check exp field).

Suggested flow for user token usage:

  1. When a new user is created, save the userId and userToken.

  2. When the same user is returning to Link, check if userToken has not expired and is still valid.

  3. If userToken is still valid, provide it to Link in the config.

  4. If userToken has expired:

    • Create a new userToken by calling the /user-tokens endpoint in the Argyle API to generate a new userToken.

    • Provide it to Link in the config. Make sure that you request user tokens on your server-side and your client_id and client_secret are never exposed on the front-end.

Link initialization for a returning user

<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
  </head>
  <body>
    <script src="https://plugin.argyle.com/argyle.web.v3.js"></script>
    <script type="text/javascript">
      const argyle = Argyle.create({
        linkKey: 'YOUR_LINK_KEY', // insert your Link key here. It can be found in the Argyle Console.
        apiHost: 'https://api-sandbox.argyle.com/v1', // sandbox environment is used in this example. Change to production environment before launching.
        userToken: 'USER_TOKEN', // insert the old or new user token here
        linkItems: [] // add Link item IDs (e.g. ‘Starbox’) if you want to constrain the Link item list in the search screen.
      })
      argyle.open()
    </script>
  </body>
</html>
_ = Argyle.shared
    .loginWith(
        linkKey: "YOUR_LINK_KEY", // insert your Link key here. It can be found in the Argyle Console.
        apiHost: "https://api-sandbox.argyle.com/v1") // sandbox environment is used in this example. Change to production environment before launching.
    .linkItems([]) // add Link item IDs (e.g. "Starbox") if you want to constrain the Link item list in the search screen.
    .resultListener(self)

let argyle = Argyle.shared.updateToken("USER_TOKEN").controller // insert the old or new user token here
argyle.modalPresentationStyle = .fullScreen
self.present(argyle, animated: true, completion: nil)
val config = ArgyleConfig.Builder()
    .loginWith(
        "YOUR_LINK_KEY", // insert your Link key here. It can be found in the Argyle Console.
        "https://api-sandbox.argyle.com/v1", // sandbox environment is used in this example. Change to production environment before launching.
        "USER_TOKEN") // insert the old or new user token here
    .linkItems(arrayOf()) // add Link item IDs (e.g. "Starbox") if you want to constrain the Link item list in the search screen.
    .setCallbackListener(object : Argyle.ArgyleResultListener {

        override fun onUserCreated(userToken: String, userId: String) {
            // save userId and userToken
            Log.d("Result", "onUserCreated:  userId: $userId, userToken: $userToken")
        }
    })
    .build()

Argyle.instance.init(config)
Argyle.instance.startSDK(this)
import ArgyleSdk from '@argyleio/argyle-plugin-react-native'

ArgyleSdk.loginWith(
    "YOUR_LINK_KEY", // insert your Link key here. It can be found in the Argyle Console.
    "https://api-sandbox.argyle.com/v1", // sandbox environment is used in this example. Change to production environment before launching.
    "USER_TOKEN") // insert the old or new user token here
ArgyleSdk.linkItems([]) // add Link item IDs (e.g. "Starbox") if you want to constrain the Link item list in the search screen.

ArgyleSdk.start()

Step 3: Connect test accounts

Within the Sandbox environment, Argyle provides two slightly different data sets:

  • Rideshare/Delivery — if you select a gig company like Uber or Doordash, the data has more activity information (duration, distance, etc).
  • General — if you select any other company or payroll platform, the data reflects traditional employment records.

When running in a Sandbox environment, you can connect work accounts with the provided sandbox credentials only:

BobSarahJoe
Email[email protected][email protected][email protected]
Usernametest_1test_2test_3
Passwordpassgoodpassgoodpassgood
Verification code808180828083
Phone number(800) 900-0001(800) 900-0002(800) 900-0003
Driver's licenseD1230001D1230002D1230003

Make sure to select the appropriate credentials item. For example, Walmart requires username and password while Uber requires email and password.

Before proceeding to the next step, make sure to click on one of the Link items and use one of the sandbox credentials to connect it.


Step 4: Check account sync status

It takes some time for Argyle to retrieve the employment information after a user connects their account. The average sync times are based on the length of employment:

Data structureData structure

If you want to have all the employment information before proceeding, query the account object via the Argyle API with your user’s accountId saved previously:

GET https://api-sandbox.argyle.com/v1/accounts/<accountId>

// insert your user’s accountId in the request.
// this example uses the sandbox environment. Don't forget to switch to the production environment if you are testing in production.

Here is an example response:

{
  "id": "ac81e2bc-2157-4535-8ca4-fb1f068df1fc",
  "user": "53fe928d-9c6a-460b-b5ac-19d67304d106",
  "employers": [
    "homedepot"
  ],
  "link_item": "homedepot",
  "source": "workday",
  "created_at": "2019-11-27T15:55:56.771322Z",
  "updated_at": "2019-11-29T08:37:42.164522Z",
  "connection": {
    "status": "connected",
    "error_code": null,
    "error_message": null,
    "updated_at": "2019-11-29T08:37:42.112859"
  },
  "pay_distribution": {
    "status": "success",
    "error": null,
    "error_message": null,
    "updated_at": "2019-11-29T08:37:42.164522Z"
  },
  "availability": {
    "profiles": {
      "status": "synced",
      "updated_at": "2019-11-29T08:37:42.164522Z"
    },
    "employments": {
      "status": "synced",
      "updated_at": "2019-11-29T08:37:42.164522Z"
    },
    "reputations": {
      "status": "synced",
      "updated_at": "2019-11-29T08:37:42.164522Z"
    },
    "documents": {
      "status": "synced",
      "updated_at": "2019-11-29T08:37:42.164522Z"
    },
    "vehicles": {
      "status": "synced",
      "updated_at": "2019-11-29T08:37:42.164522Z"
    },
    "pay_allocations": {
      "status": "synced",
      "updated_at": "2019-11-29T08:37:42.164522Z"
    },
    "payouts": {
      "status": "synced",
      "updated_at": "2019-11-29T08:37:42.164522Z",
      "available_count": 3,
      "available_from": "2019-10-30T00:00:00Z",
      "available_to": "2018-11-27T00:00:00Z"
    },
    "activities": {
      "status": "synced",
      "updated_at": "2019-11-29T08:37:42.164522Z",
      "available_count": 146,
      "available_to": "2019-11-29T08:37:42.164522Z",
      "available_from": "2018-12-15T20:40:50.399677Z"

    }
  }
}
  • availability shows the progress of the employment information synchronization.
  • availability.profiles.status, availability.employments.status, and availability.payouts.status should be synced to make sure all the data was retrieved.

Step 5: Retrieve employment information

For employment verification, fetch the following fields from the employments endpoint:

  • hire_datetime
  • status
  • job_title

Submit a GET request to the Argyle API:

GET https://api-sandbox.argyle.com/v1/employments?account=<accountId>

// insert your user's accountId in the request.
// this example uses the sandbox environment. Don't forget to switch to the production environment if you are testing in production.

Here is an example response:

{
   "id":"857b4aad-1a55-4200-84f7-311cd3dc3432",
   "account":"021a1749-6973-4e47-a82a-307008ca88cc",
   "employer":"walmart",
   "created_at":"2020-10-27T17:29:08.724441Z",
   "updated_at":"2020-10-27T17:29:08.724520Z",
   "status":"active",
   "type":"part-time",
   "job_title":"cashier",
   "hire_datetime":"2018-10-27T17:29:08.724441Z",
   "termination_datetime":null,
   "termination_reason":null,
   "base_pay":{
      "amount":36400,
      "period":"annual",
      "currency":"USD"
   },
   "pay_cycle":"monthly",
   "platform_ids":{
      "employee_id":"47FJ06ON8",
      "position_id":"INA609028",
      "platform_user_id":"H3WTY0FHMQ24ERDN"
   },
   "metadata":{}
}

For income verification, fetch the following fields from the payouts endpoint:

  • gross_pay
  • net_pay
  • taxes
  • deductions

A payout object represents a single paystub. You will want to retrieve all the payout objects for a relevant timeframe.

Submit a GET request to the Argyle API:

GET https://api-sandbox.argyle.com/v1/payouts?account=<accountId>&from_start_date=2020-01-01&to_start_date=2021-01-01

// insert your user's accountId in the request.
// insert relevant dates for the from_start_date and to_start_date parameters.
// this example uses the sandbox environment. Don't forget to switch to the production environment if you are testing in production.
//

In this example request, the number of payouts (paystubs) is limited to the 20-21’ period.

You could also retrieve the YTD income by using only the from_start_date parameter and setting it to 2021-01-01 or inserting the value programmatically to receive payouts for the last 12 months. Here is an example response of a single payout:

{
   "id":"a6b95412-e43a-4584-be9f-1dc101aa349a",
   "account":"f8bf3e18-09ba-428c-b197-6798f1b2b834",
   "document_id":"97f21592-b6b6-352a-91d7-e221bf0dd6e9",
   "employer":"walmart",
   "status":"completed",
   "type":"direct_deposit",
   "payout_date":"2020-04-22T00:00:00Z",
   "payout_period":{
      "start_date":"2019-12-28T00:00:00Z",
      "end_date":"2020-01-10T00:00:00Z"
   },
   "currency":"USD",
   "gross_pay":"1730.77",
   "reimbursements":"279.87",
   "deductions":"68.68",
   "deduction_list":[
      {
         "amount":"68.68",
         "name":"Health Benefits - Pretax",
         "tax_classification":"pre_tax"
      }
   ],
   "taxes":"224.68",
   "tax_list":[
      {
         "amount":"171.28",
         "name":"Fed Withholdng",
         "type":"federal"
      },
      {
         "amount":"53.40",
         "name":"Fed OASDI/EE",
         "type":"fica"
      }
   ],
   "fees":null,
   "net_pay":"1717.28",
   "bonuses":"0.00",
   "commission":"0.00",
   "overtime":"0.00",
   "hours":"80.00",
   "employer_address":{
      "line1":"4 Jackson St",
      "line2":"Apt C",
      "city":"Norton",
      "state":"MA",
      "postal_code":"27660",
      "country":"US"
   },
   "filing_status":[
      {
         "type":"federal",
         "location":null,
         "status":"single"
      },
      {
         "type":"state",
         "location":"MD",
         "status":"single"
      }
   ],
   "metadata":{
      "hours_breakdown":[
         {
            "hours":"80",
            "amount":"1730.77",
            "description":"Work Hours"
         }
      ]
   }
}

For additional data fields, please refer to the Argyle API reference.


Step 6: Trigger a periodic scan

In the Production environment, new data for connected accounts are constantly generated and delivered to you (for example, new payouts, activities) during periodic data scans. For testing purposes, you can trigger a periodic scan yourself to get new data for an already connected account. Please use the following endpoint:

https://api-sandbox.argyle.com/v1/accounts/<accountId>/periodic-scan

It accepts POST requests with an empty body.

accountId has to be a Sandbox accounts.id, otherwise, an error is returned:

{
    "account": [
        "Periodic scan can be manually scheduled only for sandbox accounts."
    ]
}

Periodic scan data

A periodic scan for Sandbox accounts returns 1-5 new payouts and activities. It is possible to trigger a periodic scan as many times as you need for testing.


Step 7: Set up webhooks

To receive regular updates on a user's accounts and employment records, subscribe to webhooks.

Webhooks send notifications to your system every time something occurs, for example when an account is connected, removed, or updated. Read about how Argyle clients use webhooks here.

To monitor new and existing accounts, Argyle recommends subscribing to the following webhooks:

  • accounts.added - sends a notification upon a user submitting their login credentials in Link.
  • accounts.connected - sends a notification if the submitted credentials are correct and the connection is successful.
  • accounts.failed - sends a notification if a problem occurs and the connection is unsuccessful. Additional information about the problem is provided in the error_code and error_message fields of the webhook payload.
  • accounts.removed - sends a notification when an account is removed (either by you or the user via Argyle Link).

To monitor changes to employment records, Argyle recommends subscribing to the following webhooks:

  • employments.updated - sends a notification when some information in the employment changes. You are notified if a user is terminated, their base pay changes, etc.
  • payouts.partially_synced - when subscribing to this webhook, you can specify days_synced to be notified when a particular amount of data is available (for example, after a month's or year's worth of payouts are available).
  • payouts.added - sends a notification when a new payout is added to a user's account. It helps you to continuously verify if a user is still receiving income.

📘

Consult the Webhooks reference for a complete list of available webhooks.


Step 8: Going live and scaling

After a successful implementation and multiple tests run in the Sandbox environment, you can switch to the Production environment:

Change the apiHost

Firstly, change the apiHost in your Link configuration from:

https://api-sandbox.argyle.com/v1

to:

https://api.argyle.com/v1

The same logic applies to any API requests that you have previously used, so:

GET https://api-sandbox.argyle.com/v1/employments/<accountId>

change to:

GET https://api.argyle.com/v1/employments/<accountId>

Change the linkKey

The linkKey can be found in the API keys section of the Console in the Link key row. Use the production Link key when moving to the production environment.

Start slow

For your first Production accounts, you can test on yourself if Argyle supports your employer. Another option for Production testing is to create an account with a freelance platform like Upwork and connect that account.

Launch and scale

After testing with your personal accounts, you can test with your real users. We recommend starting with a small subset of your users to make sure that everything is working as expected. Then, advance gradually to your full user base.


Did this page help you?