GuidesAPI ReferenceChangelog
Log In


Pinwheel Link is a front-end modal that allows users to search for their employers and payroll providers and seamlessly authenticate with their payroll platform credentials in order to authorize access to their payroll account.

There are several methods for implementing Pinwheel Link. For web application you can embed Pinwheel Link directly into your site. For mobile development we recommend using one of our Link SDKs: React Native, Android, and iOS.


We understand how important it is to have a cohesive user experience, so we’ve made Pinwheel Link highly customizable. All customizations are done via Link token creation. Some of the most notable customizations include:

  • Skipping the Pinwheel intro screen
  • Building your own search functionality
  • Disabling partial direct deposit switch
  • Language localization

For more information on navigating these customizations please take a look at our Implementation Guide.

Link Tokens

In order to initialize Pinwheel Link, your server side code will need to generate a short-lived Link token by sending a POST request to the /link_tokens endpoint. Link tokens are intended to be single-use and expire after one hour. Your server should generate a new Link token each time you wish to launch Pinwheel Link.



Do not ever send this request from the client side and publicly expose your API Secret.


POST /v1/link_tokens
Content-Type: application/json
x-api-secret: YOUR-API-SECRET
  "org_name": "YOUR APP NAME",
  "required_jobs": ["employment", "income"],


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



The id returned here is identical to the link_token_id included with webhooks, and should be stored accordingly. The optional end_user_id you provide in this request is also included in any subsequent webhooks events. While this parameter is optional, it is recommended as it will make it easier to track end-user conversion. You can find recommendations for storing identifiers here.

Link Events

Link events are returned to your client and will give you visibility into what is happening in the modal as the user moves through Pinwheel Link. The nine different event types are outlined below. It is up to you to determine how to use these events for tracking.

openModal was opened{}
select_employerUser selected an employer{ selectedEmployerId: string, selectedEmployerName: string }
select_platformUser selected a platform{ selectedPlatformId: string, selectedPlatformName: string }
incorrect_platform_givenClient has incorrect platform in token{}
login_attemptUser has submitted login attempt for the first time{ platformId: string }
loginUser logged in successfully{ accountId: string, platformId: string }
input_amount (deprecated)User inputted an amount. Note that this event is deprecated in favor of input_allocation, which provides more detail on what was input by the user{ value: number, unit: '$' | '%' }
input_allocationUser has submitted an allocation{ action: string, allocation?: { type: string, value?: number, target?: { accountName: string, accountType: string } }
exitModal was exitedPinwheelError | {}
successUser reached the success screen. For direct deposit jobs, this will occur when the job has completed successfully. For all other jobs this will be when the user logs in successfully, as these jobs are completed in the background.LinkResult
errorUser was shown an errorPinwheelError

For On Demand Updates, the select_employer, select_platform, and incorrect_platform_given events are not sent since the account_id is already associated with a platform. Additionally, the login_attempt event is only sent if user input is required and an attempt to login is made.

You can find more detail on Link errors and error handling here.

Reference Types

The following types should be used while integrating Link into your application.


{ type: string; code: string; message: string, pendingRetry: boolean }

The boolean pendingRetry is true when the job results in an error but will be retried asynchronously. Your user will be notified that their request is pending. This is available starting Link v2.3 and above.


type InitializationParams = {
  linkToken: string;
  onLogin?: (result: { accountId: string, platformId: string }) => void;
  onSuccess?: (result: LinkResult) => void;
  onError?: (error: PinwheelError) => void;
  onExit?: (error?: PinwheelError) => void;
  onEvent?: (name: string, payload: EventPayload) => void;
linkTokenThe Link token created using the /link_tokens endpoint.
onLogin (optional)Callback whenever a user successfully logs in to their payroll account.
onSuccess (optional)Callback whenever a user reaches the success screen. For direct deposit jobs, this will occur when the job has completed successfully. For Income and Employment jobs this will be when the user logs in successfully, as these jobs are completed in the background.
onError (optional)Callback anytime an error occurs during the flow. This could be a user error like incorrect credentials or a system error. Receiving this callback does not necessarily mean the flow cannot proceed.
onExit (optional)Callback whenever a user exits the modal either explicitly or if an error occurred that crashed the modal.
onEvent (optional)Callback with more granular events to help you track usage. All possible events are listed here.


Note that the params object is deprecated. Please use the input_allocation event to determine the amount and type of allocation that the user submitted.

  accountId: string;
  platformId: string;
  job: string;
  params: {
    amount?: {value: number, unit: '%' | '$'}

Please contact [email protected] for access to our Developer Dashboard.