GuidesAPI ReferenceChangelog
Log In

Technical Implementation

This guide explains how to access Verify. For an overview of concepts in the Pinwheel system that are referenced in this doc, review the Platform Overview.

Step 1: Subscribe to webhook events

Pinwheel sends webhook events to alert you when up-to-date Verify data is available or Monitoring has detected a change to a user's information.

Register a webhook endpoint using the POST /v1/webhooks with the data you're interested in receiving updates for (e.g. income.added or employment.added). See Webhooks for additional configuration details and instructions on authenticating webhook events.

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 a Link token specifying the jobs that your application requires using required_jobs.

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"]
}

Note: The end_user_id is your internal reference to the end user. See User Model for more information.

The response includes a short-lived token that expires after 15 minutes 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",
  }
}

Step 3: Initialize Link

Using the Link token that was created, open the Link modal in your client application. In addition to passing in the token, you can optionally pass in 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 you persisted earlier, you can 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
  }
}
{
  "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,
    "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"
  }
}
{
  "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"
  }
}
{
  "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",
    "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 we are still collecting data, while a status of complete mean we are done. See Verify Webhooks Events for more details and additional webhook events for paystubs and shifts.

Step 5: Retrieving data

To retrieve Verify data, you must use the account_id from the webhook event that you received and the endpoint associated with the data you're retrieving. Examples for employment and income are below.

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": {
    "id": "077f2bf2-acfe-44b6-9751-efafc5f97341",
    "account_id": "03bbc20e-bc39-464a-b4dc-4b63ffb7213d",
    "status": "employed",
    "title": "Sales Associate",
    "start_date": "2019-03-27",
    "employer_name": "Walmart",
    "created_at": "2021-01-09T21:21:25.256571+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"
  }
}

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 to 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",
      "params": {
        "amount": null
      }
    }
  ]
}

Step 7 (Optional): Performing an On Demand Update

There are times when a user's account loses connection or you need the latest information for a user. We recognize that asking the user to log in multiple times introduces friction, so we've added the ability to re-access the payroll account without needing the user to re-enter credentials.

Enabling this functionality is similar to the way standard Link tokens are created. When creating 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 any time 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 is persisted from the initial connection.

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