GuidesAPI ReferenceChangelog
Log In
Hey! These docs are for version 2021-07-28, which is no longer officially supported. Click here for the latest version, 2023-11-22!


# Introduction

Webhooks allow you to subscribe to server-side notifications of events, like completing jobs and newly available data. Webhooks are helpful to optimize your Pinwheel integration.

# Subscribing to Webhook Events

You can register a webhook endpoint by sending a request to [create a webhook](🔗) specifying the events to subscribe to with the `enabled_events` parameter. You should explicitly enumerate the events you'd like to subscribe to (e.g., `['direct_deposit_payment.added', 'income.added']`). Webhook endpoints must be `https://` so that the event payloads can be transmitted securely.



## Webhook Pause Policy

Webhook endpoints that fail to return a successful response code (200 OK) for 30 consecutive days will be set to `status: paused` to avoid unnecessary delivery attempts.

# Webhook Event Handling

Webhook events are delivered over HTTPS to the endpoint you registered. An example event is:



## Verifying Pinwheel is the Sender

Pinwheel signs all webhook events it sends to your endpoints by including a signature in each event's `x-pinwheel-signature` header. You can use this signature to verify that the events were sent by Pinwheel, not by a third party. Learn more at [Webhook Signature Verification](🔗).

## Retry Policy

Pinwheel expects a response within 15 seconds from your endpoint. Pinwheel will redeliver a webhook event if your webhook endpoint returns a failure (5XX status codes or network issues). Up to 5 subsequent delivery attempts will be made with exponential backoff including jitter in the 15 minutes following the initial delivery attempt.

## Handling Duplicate Events

The `event_id` request body parameter is unique for each webhook event. This can be used to guard against potential duplicate events and make your system idempotent. It can also be used to troubleshoot webhook event specific issues, so we recommend logging this identifier.

Webhook events are delivered with "at least once" guarantees, meaning that (rarely) the same webhook event will be delivered to your system multiple times.

## Webhook Request Body

All webhook requests have a JSON body with the following parameters:

ParamTypeDescription
`event`stringWebhook event, e.g., `direct_deposit_payment.added`.
`event_id`stringUnique ID for each webhook event.
`payload`objectPayload attributes vary based on event.

## Webhook Request Headers

All webhook requests have the following headers:

HeaderTypeDescription
`x-pinwheel-signature`stringSee [Webhook Signature Verification](🔗).
`x-pinwheel-webhook-id`stringID of the webhook created via the [POST /webhooks](🔗) endpoint.
`x-timestamp`integerWhen the request was sent in Unix epoch time seconds.

## Pending Webhook Job Outcomes

All job-associated webhook events include an `outcome` in the payload. The `outcome` represents the status of a job, and it can be either `success`, `error`, or `pending`. A `pending` status indicates that a job was unable to be completed on its first attempt and will be retried up to 24 hours after the initial attempt. A job with a `pending` status will transition to either an `error` or a `success` within the 24-hour window, and you will be notified with another webhook event.

# Webhook Events

## Account Webhook Events

### account.added

User successfully logs into their payroll accounts. This webhook correlates to the onLogin callback.

#### Payload Schema

Payload ParamTypeDescription
`account_id`stringUUID of the payroll account.
`link_token_id`stringUUID of the Link token used to initialize Link.
`platform_id`stringUUID of the payroll platform associated with this account.
`platform_name`stringThe name of the payroll platform associated with this account.
`created_at`stringISO 8601 timestamp of payroll account creation.
`connected`booleanIf set to true, you can retrieve new information for the account on a recurring basis.
`monitoring_status`stringDescribes the automated ability of Pinwheel to retrieve new account information. See [account.monitoring_status.updated](🔗) for possible values.

#### Sample Webhook Event



### account.monitoring_status.updated

Pinwheel's ability monitor a payroll account has changed (i.e. [DDA](🔗) and [I&E](🔗)).

Several monitoring statuses are possible:

monitoring_statusDescription
`active`Pinwheel is monitoring for data changes daily.
`degraded`Pinwheel is trying to monitor but seeing spurious errors and may be unable to return data for the time being. You may want to use this to inform users about laggy data.
`user_action_required`You need to use On Demand Updates to have a user re-complete the login process.
`unavailable`Pinwheel doesn’t support monitoring for this account.
`customer_disabled`You used `POST /v1/accounts/{id}/disable_monitoring` to manually turn off monitoring.

#### Payload Schema

Payload ParamTypeDescription
`account_id`stringUUID of the payroll account.
`updated_at`stringISO 8601 timestamp of when Pinwheel updated the monitoring_status for this account.
`current_monitoring_status`stringThe latest monitoring status for the account. See the table above for a set of possible values.

#### Sample Webhook Event



## Direct Deposit Webhook Events

Direct Deposit webhook events will notify you when new direct deposit allocation data is available for a payroll account or a direct deposit job completed.

### direct_deposit_allocations.added

Direct deposit allocations data is now available for the payroll account.

#### Payload Schema

Payload ParamTypeDescription
`account_id`stringUUID of the payroll account.
`outcome`stringThe outcome of the job, either `success`, `error`, or `pending`. If `pending` you will receive another webhook with `outcome` as `success` or `error` within 24 hours.
`error_code` (optional)stringOn error, a string describing the error.
`error_type` (optional)stringOn error, a high level classification of the error.
`timestamp`stringISO 8601 timestamp of job completion.
`name`stringName of the job.
`id`string_Deprecated_. UUID of the job. _You should use `account_id` as the main identifier._
`link_token_id`string_Deprecated_. UUID of Link token used to initialize Link, or an undefined link token if triggered by a refresh job (such as from DDA Monitoring). _You should use `account_id` as the main identifier._

#### Sample Webhook Event



### direct_deposit_payment.added

A `direct_deposit_payment` job to add new direct deposit allocation completed.

#### Payload Schema

Payload ParamTypeDescription
`id`stringUUID of the job.
`account_id`stringUUID of the payroll account.
`params` (optional)objectParameters of the job, if applicable.
`params.amount` (optional)integerThe amount to allocate per paycheck in pennies, if applicable.
`outcome`stringThe outcome of the job, either `success`, `error`, or `pending`. If `pending` you will receive another webhook with `outcome` as `success` or `error` within 24 hours.
`error_code` (optional)stringOn error, a string describing the error.
`error_type` (optional)stringOn error, a high level classification of the error.
`timestamp`stringISO 8601 timestamp of job completion.
`name`stringName of the job.
`id`string_Deprecated_. UUID of the job. _You should use `account_id` as the main identifier._
`link_token_id`string_Deprecated_. UUID of Link token used to initialize Link, or an undefined link token if triggered by a refresh job (such as from DDA Monitoring). _You should use `account_id` as the main identifier._

#### Sample Webhook Event



### direct_deposit_switch.added

A `direct_deposit_switch` job to add new direct deposit allocation completed. When a user does a full switch `amount` will be `null`.

#### Payload Schema

Payload ParamTypeDescription
`account_id`stringUUID of the payroll account.
`params` (optional)objectParameters of the job, if applicable.
`params.amount` (optional)integerThe amount to allocate per paycheck in pennies, if applicable.
`outcome`stringThe outcome of the job, either `success`, `error`, or `pending`. If `pending` you will receive another webhook with `outcome` as `success` or `error` within 24 hours.
`error_code` (optional)stringOn error, a string describing the error.
`error_type` (optional)stringOn error, a high level classification of the error.
`timestamp`stringISO 8601 timestamp of job completion.
`name`stringName of the job.
`id`string_Deprecated_. UUID of the job. _You should use `account_id` as the main identifier._
`link_token_id`string_Deprecated_. UUID of Link token used to initialize Link, or an undefined link token if triggered by a refresh job (such as from DDA Monitoring). _You should use `account_id` as the main identifier._

#### Sample Webhook Event



## Income and Employment Webhook Events

Income and Employment webhook events will notify you when the data for a given product is ready to be retrieved. The payload is summary information, not the data itself. After receiving a webhook event, call the corresponding endpoint to retrieve the account data.

### employment.added

Employment data for the payroll account is available. Use `account_id` in the payload to query the [Get Employment](🔗) endpoint to fetch the data.

#### Payload Schema

Payload ParamTypeDescription
`account_id`stringUUID of the payroll account.
`outcome`stringThe outcome of the job, either `success`, `error`, or `pending`. If `pending` you will receive another webhook with `outcome` as `success` or `error` within 24 hours.
`error_code` (optional)stringOn error, a string describing the error.
`error_type` (optional)stringOn error, a high level classification of the error.
`params` (optional)objectParameters of the job, if applicable.
`timestamp`stringISO 8601 timestamp of job completion.
`name`stringName of the job.
`id`string_Deprecated_. UUID of the job. _You should use `account_id` as the main identifier._
`link_token_id`string_Deprecated_. UUID of Link token used to initialize Link, or an undefined link token if triggered by a refresh job (such as from DDA Monitoring). _You should use `account_id` as the main identifier._

#### Sample Webhook Event



### identity.added

Identity data for the payroll account is available. Use `account_id` in the payload to query the [Get Identity](🔗) endpoint to fetch the data.

#### Payload Schema

Payload ParamTypeDescription
`account_id`stringUUID of the payroll account.
`outcome`stringThe outcome of the job, either `success`, `error`, or `pending`. If `pending` you will receive another webhook with `outcome` as `success` or `error` within 24 hours.
`error_code` (optional)stringOn error, a string describing the error.
`error_type` (optional)stringOn error, a high level classification of the error.
`params` (optional)objectParameters of the job, if applicable.
`timestamp`stringISO 8601 timestamp of job completion.
`name`stringName of the job.
`id`string_Deprecated_. UUID of the job. _You should use `account_id` as the main identifier._
`link_token_id`string_Deprecated_. UUID of Link token used to initialize Link, or an undefined link token if triggered by a refresh job (such as from DDA Monitoring). _You should use `account_id` as the main identifier._

#### Sample Webhook Event



### income.added

Income data for the payroll account is available. Use `account_id` in the payload to query the [Get Income](🔗) endpoint to fetch the data.

#### Payload Schema

Payload ParamTypeDescription
`account_id`stringUUID of the payroll account.
`outcome`stringThe outcome of the job, either `success`, `error`, or `pending`. If `pending` you will receive another webhook with `outcome` as `success` or `error` within 24 hours.
`error_code` (optional)stringOn error, a string describing the error.
`error_type` (optional)stringOn error, a high level classification of the error.
`params` (optional)objectParameters of the job, if applicable.
`timestamp`stringISO 8601 timestamp of job completion.
`name`stringName of the job.
`id`string_Deprecated_. UUID of the job. _You should use `account_id` as the main identifier._
`link_token_id`string_Deprecated_. UUID of Link token used to initialize Link, or an undefined link token if triggered by a refresh job (such as from DDA Monitoring). _You should use `account_id` as the main identifier._

#### Sample Webhook Event



### paystubs.added

A set of Paystubs are available. The `params` describes which paystubs. Use `account_id` in the payload to query the [Get Paystub](🔗) endpoint to fetch them.

#### Payload Schema

Payload ParamTypeDescription
`account_id`stringUUID of the payroll account.
`outcome`stringThe outcome of the job, either `success`, `error`, or `pending`. If `pending` you will receive another webhook with `outcome` as `success` or `error` within 24 hours.
`params`objectParameters of the job, if applicable.
`error_code` (optional)stringOn error, a string describing the error.
`error_type` (optional)stringOn error, a high level classification of the error.
`timestamp`stringISO 8601 timestamp of job completion.
`name`stringName of the job.
`id`string_Deprecated_. UUID of the job. _You should use `account_id` as the main identifier._
`link_token_id`string_Deprecated_. UUID of Link token used to initialize Link, or an undefined link token if triggered by a refresh job (such as from DDA Monitoring). _You should use `account_id` as the main identifier._

#### Sample Webhook Event



#### Paystubs Sync Events

A `paystubs` sync event will trigger as soon as the relevant data has been retrieved. If there isn't enough data to meet the 30d or 90d threshold, that event will be skipped. The sync status events are:

  • `paystubs.seven_days_synced`: Triggered when 7 days of paystubs have been collected

  • `paystubs.thirty_days_synced`: Triggered when 30 days of paystubs have been collected

  • `paystubs.ninety_days_synced`: Triggered when 90 days of paystubs have been collected

  • `paystubs.fully_synced`: Triggered when all available paystubs have been collected

##### Payload Schema
Payload ParamTypeDescription
`account_id`stringUUID of the payroll account.
`outcome`stringThe outcome of the job, either `success`, `error`, or `pending`. If `pending` you will receive another webhook with `outcome` as `success` or `error` within 24 hours.
`params`objectParameters of the job, if applicable.
`error_code` (optional)stringOn error, a string describing the error.
`error_type` (optional)stringOn error, a high level classification of the error.
`timestamp`stringISO 8601 timestamp of job completion.
`name`stringName of the job.
`id`string_Deprecated_. UUID of the job. _You should use `account_id` as the main identifier._
`link_token_id`string_Deprecated_. UUID of Link token used to initialize Link, or an undefined link token if triggered by a refresh job (such as from DDA Monitoring). _You should use `account_id` as the main identifier._
##### Sample Webhook Events


### shifts.added

A set of Shifts are available. The `params` describes the number of shifts. Use `account_id` in the payload to query the [List Shifts](🔗) endpoint to fetch them.

#### Payload Schema

Payload ParamTypeDescription
`account_id`stringUUID of the payroll account.
`outcome`stringThe outcome of the job, either `success`, `error`, or `pending`. If `pending` you will receive another webhook with `outcome` as `success` or `error` within 24 hours.
`params` (optional)objectInput parameters to the job, if applicable.
`error_code` (optional)stringOn error, a string describing the error.
`timestamp`stringISO 8601 timestamp of job completion.
`name`stringName of the job.
`id`string_Deprecated_. UUID of the job. _You should use `account_id` as the main identifier._
`link_token_id`string_Deprecated_. UUID of Link token used to initialize Link, or an undefined link token if triggered by a refresh job (such as from DDA Monitoring). _You should use `account_id` as the main identifier._

#### Sample Webhook Event



#### Shifts Sync Events

A `shifts` sync event will trigger as soon as the relevant data has been retrieved. If there isn't enough data to meet the 30d or 90d threshold, that event will be skipped. The sync status events are:

  • `shifts.seven_days_synced`: Triggered when 7 days of shifts have been collected

  • `shifts.thirty_days_synced`: Triggered when 30 days of shifts have been collected

  • `shifts.ninety_days_synced`: Triggered when 90 days of shifts have been collected

  • `shifts.fully_synced`: Triggered when all available shifts have been collected

Note that only 90 days of data are collected for shifts. Thus, `shifts.ninety_days_synced` and `shifts.fully_synced` will trigger at the same time.

##### Payload Schema
Payload ParamTypeDescription
`account_id`stringUUID of the payroll account.
`outcome`stringThe outcome of the job, either `success`, `error`, or `pending`. If `pending` you will receive another webhook with `outcome` as `success` or `error` within 24 hours.
`params`objectParameters of the job, if applicable.
`error_code` (optional)stringOn error, a string describing the error.
`error_type` (optional)stringOn error, a high level classification of the error.
`timestamp`stringISO 8601 timestamp of job completion.
`name`stringName of the job.
`id`string_Deprecated_. UUID of the job. _You should use `account_id` as the main identifier._
`link_token_id`string_Deprecated_. UUID of Link token used to initialize Link, or an undefined link token if triggered by a refresh job (such as from DDA Monitoring). _You should use `account_id` as the main identifier._
##### Sample Webhook Event




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