GuidesAPI ReferenceChangelog
Log In

Implement Core Data

You can access core data to verify customers' information, manage lending risk, improve the loan application process, and more. Individual core data are associated with a payroll_account_id.

Step 1: Subscribe to webhook events

Subscribe to Pinwheel Verify Webhook Events to receive instant notifications when up-to-date Verify data is available or Monitoring detects a change in a user's information.

  • employment.added: Notifies you when information about a customer's employment is added.
  • income.added: Notifies you when information about a customer's income is added.

Register a webhook endpoint using Pinwheel's Create Webhook as the following example illustrates.

POST /v1/webhooks
Host: api.getpinwheel.com
Content-Type: application/json
x-api-secret: YOUR-API-SECRET
{
  "url": "https://your-domain.com/webhook_endpoint",
  "status": "ACTIVE",
  "enabled_events": [
    "employment.added",
    "income.added",
    "paystubs.added"
  ]
}

Step 2: Create a Link token

Create Link Token by sending the POST request to the link_tokens endpoint.

In the following request payload, you can see the fields that are required to create a link token for use with Pinwheel Verify:

POST /v1/link_tokens
Host: api.getpinwheel.com
Content-Type: application/json
x-api-secret: YOUR-API-SECRET
{
  "org_name": "YOUR APP NAME",
  "end_user_id": "my_user_12345",
  "required_jobs": ["employment", "income", "paystubs"]
}
  • org_name: The name of your organization.
  • required_jobs: The jobs run to get employment and income data. At least one of these jobs is required.
  • end_user_id: The company's internal reference to the end user. See User Model for more information.
  • language - The language that the link modal uses.

The response to this call returns a link token you can use to launch the Link Modal in your app and a unique id. Persist the id in your database.

{
  "data": {
    "id": "97f420ff-5d0a-46ee-9cfc-6f17d5d31256",
    "expires": "2021-01-09T02:52:26+00:00",
    "mode": "production",
    "token": "eyJ0eXAiOiJKV1QiLCJhbGci...cyldX8fILelb6A0XKmdWsXZHMH4W1o",
  }
}

It is not necessary to pass end_user_id when creating Link tokens for On Demand Updates, as the information is persisted from the initial connection.

Once you've created the Link token, follow Step 3 to initialize the Link. When the user is presented with the Pinwheel Link flow, they are directed to the payroll platform associated with their account, bypassing login if possible.

Step 3: Initialize Link

Use the Link token to open the Link modal in your client application. In addition to passing in the token, you can optionally pass several callback handlers.

<!DOCTYPE html>
<html>
  <head>
    <script src="https://cdn.getpinwheel.com/pinwheel-v2.3.js"></script>
    <script>
      window.addEventListener("load", () => {
        Pinwheel.open({
          linkToken: "INSERT LINK TOKEN",
        });
      });
    </script>
  </head>
  <body></body>
</html>

Calling Pinwheel.open() renders the Link modal in full-screen mode.

Step 4: Respond to webhook events

The account.added webhook event is published after a user logs in to their payroll account. Using the link_token_id that you persisted earlier, associate the account with the user who logged in with Link.

{
  "event": "account.added",
  "event_id": "5a141122-4235-4fa1-bd76-0628573880b0",
  "payload": {
    "account_id": "03bbc20e-bc39-464a-b4dc-4b63ffb7213d",
    "end_user_id": "my_user_12345",
    "link_token_id": "97f420ff-5d0a-46ee-9cfc-6f17d5d31256",
    "platform_id": "fce3eee0-285b-496f-9b36-30e976194736",
    "created_at": "2021-01-12T02:36:01.287148+00:00",
    "connected": true
  }
}

Subsequent webhook events are published when data for a job is available. For example, the employment.added event is sent once employment data is ready.

{
  "event": "employment.added",
  "event_id": "5a141122-4235-4fa1-bd76-0628573880b0",
  "payload": {
    "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
    "account_id": "03bbc20e-bc39-464a-b4dc-4b63ffb7213d",
    "end_user_id": "my_user_12345",
    "link_token_id": "7c4ac4be-4a0e-4468-ab26-c42b249b233b",
    "name": "employment",
    "timestamp": "2021-01-21T20:16:28+00:00",
    "outcome": "success",
    "error_code": null,
    "error_type": null
  }
}
{
  "event": "paystubs.added",
  "event_id": "5a141122-4235-4fa1-bd76-0628573880b0",
  "payload": {
    "id": "24fe697f-a893-42a5-adca-a727f11ad792",
    "account_id": "03bbc20e-bc39-464a-b4dc-4b63ffb7213d",
    "end_user_id": "my_user_12345",
    "link_token_id": "7c4ac4be-4a0e-4468-ab26-c42b249b233b",
    "name": "paystubs",
    "timestamp": "2021-01-21T20:16:28+00:00",
    "outcome": "success",
    "error_code": null,
    "error_type": null,
    "added": [{"id": "dbff9830-55ce-4aa5-82f1-e04f196da041"}],
    "deleted": [{"id": "57043868-6fb3-47e8-a2b7-c993bd023f25"}],
    "params": {
      "from_pay_date": "2020-10-01",
      "to_pay_date": "2020-12-31",
      "count": 6,
      "sync_status": "in_progress",
    }
  }
}
{
  "event": "income.added",
  "event_id": "5a141122-4235-4fa1-bd76-0628573880b0",
  "payload": {
    "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
    "account_id": "449e7a5c-69d3-4b8a-aaaf-5c9b713ebc65",
    "end_user_id": "my_user_12345",
    "link_token_id": "4787acbc-11cf-4db3-998c-5ea7c4feebcd",
    "name": "income",
    "timestamp": "2021-01-12T02:36:01.287148+00:00",
    "outcome": "success",
    "error_code": null,
    "error_type": null
  }
}
{
  "event": "identity.added",
  "event_id": "5a141122-4235-4fa1-bd76-0628573880b0",
  "payload": {
    "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
    "account_id": "449e7a5c-69d3-4b8a-aaaf-5c9b713ebc65",
    "end_user_id": "my_user_12345",
    "link_token_id": "4787acbc-11cf-4db3-998c-5ea7c4feebcd",
    "name": "identity",
    "timestamp": "2021-01-12T02:36:01.287148+00:00",
    "outcome": "success",
    "error_code": null,
    "error_type": null
  }
}
{
  "event": "shifts.added",
  "event_id": "5a141122-4235-4fa1-bd76-0628573880b0",
  "payload": {
    "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
    "account_id": "449e7a5c-69d3-4b8a-aaaf-5c9b713ebc65",
    "end_user_id": "my_user_12345",
    "link_token_id": "4787acbc-11cf-4db3-998c-5ea7c4feebcd",
    "name": "shifts",
    "timestamp": "2021-01-12T02:36:01.287148+00:00",
    "outcome": "success",
    "error_code": null,
    "error_type": null,
    "added": [{"id": "dbff9830-55ce-4aa5-82f1-e04f196da041"}],
    "deleted": [{"id": "57043868-6fb3-47e8-a2b7-c993bd023f25"}],
    "params": {
      "count": 14,
      "sync_status": "complete",
    }
  }
}

For accounts with a lot of data, gathering every available shift and paystub can take quite some time. To communicate this progress, both the paystubs.added and shifts.added webhook events have a payload.parms.sync_status field letting you know when Pinwheel is done syncing data from your user's payroll platform. A status of in_progress means Pinwheel is still collecting data, while a status of complete indicates the process is done. See Verify Webhooks Events for more details and additional webhook events for paystubs and shifts.

Step 5: Retrieve data

To retrieve core data, you must use the account_id from the webhook event that you received and the endpoint associated with the data you're retrieving.

Here are examples to retrieve employment and income data:

Employment

Request

GET /v1/accounts/03bbc20e-bc39-464a-b4dc-4b63ffb7213d/employment
Host: api.getpinwheel.com
Content-Type: application/json
x-api-secret: YOUR-API-SECRET

Response

See the full Employment API reference here.

{
  "data": {
    "account_id": "eb240ec6-a227-47ca-b7c7-fbbdfe7170a0",
    "created_at": "2021-01-06T15:59:13.530178+00:00",
    "employer_address": {
      "city": "Washington",
      "country": "US",
      "line1": "1234 Main St",
      "line2": "Suite 3",
      "postal_code": "20036",
      "raw": "1234 Main St, Suite 3, Washington, DC, 20036, USA",
      "state": "DC"
    },
    "employer_name": "Acme Corporation",
    "employer_phone_number": {
      "type": "mobile",
      "value": "+14155552671"
    },
    "id": "9d3309c3-b1d5-47dd-a175-20acf291f419",
    "start_date": "2020-06-01",
    "status": "employed",
    "termination_date": null,
    "title": "Engineer",
    "updated_at": "2021-01-12T00:00:00.000000+00:00"
  }
}

Income

Request

GET /v1/accounts/03bbc20e-bc39-464a-b4dc-4b63ffb7213d/income
Host: api.getpinwheel.com
Content-Type: application/json
x-api-secret: YOUR-API-SECRET

Response

See the full Income API reference here.

{
  "data": {
    "id": "6309e185-9c87-4384-aaae-767c7875775e",
    "account_id": "03bbc20e-bc39-464a-b4dc-4b63ffb7213d",
    "created_at": "2021-01-06T15:59:13.530178+00:00",
    "compensation_amount": 400000,
    "compensation_unit": "monthly",
    "currency": "USD",
    "pay_frequency": "monthly",
  }
}

Step 6 (Optional): Query for Job Results

If your application never subscribed to webhook events, or your application server failed to handle the webhook events, you can query the Jobs endpoint with the link_token_id used to initialize Link and fetch the results.

Request

GET /v1/jobs?link_token_id=97f420ff-5d0a-46ee-9cfc-6f17d5d31256&job_types=employment
Host: api.getpinwheel.com
Content-Type: application/json
x-api-secret: YOUR-API-SECRET

Response

{
  "meta": {
    "count": 1
  },
  "data": [
    {
      "id": "497f6eca-6276-4993-bfeb-53cbbbba6f08",
      "account_id": "03bbc20e-bc39-464a-b4dc-4b63ffb7213d",
      "link_token_id": "7c4ac4be-4a0e-4468-ab26-c42b249b233b",
      "name": "employment",
      "timestamp": "2021-01-12T02:36:01.287148+00:00",
      "outcome": "success",
      "error_code": null,
      "error_type": null,
      "params": {
        "amount": null
      }
    }
  ]
}

Step 7 (Optional): Perform an On Demand Update

When a user's account loses connection or you need the latest information for a user, asking the user to log in multiple times introduces friction. Pinwheel has added the ability to reaccess the payroll account without needing the user to re-enter credentials.

Enabling this functionality is similar to the way standard Link tokens are created. To create the Link token, pass in the account_id parameter from a prior account.added webhook event or from the login client side event in Link. The account_id can be preserved and passed in whenever you have it for a user.

POST /v1/link_tokens
Host: api.getpinwheel.com
Content-Type: application/json
X-API-SECRET: YOUR-API-SECRET
{
  "org_name": "YOUR APP NAME",
  "end_user_id": "my_user_12345",
  "required_jobs": ["employment", "income"],
  "account_id": "03bbc20e-bc39-464a-b4dc-4b63ffb7213d"
}

It is not necessary to pass end_user_id when creating Link tokens for on-demand updates, as the information persists from the initial connection.

Once you've created the Link token, follow Step 3 to initialize the link. When the user is presented with the Pinwheel Link flow, they are directed to the payroll platform associated with their account, bypassing login if possible.