# Get Plan
Source: https://developer.tryfinch.com/api-reference/benefits/get-plan

get /employer/plans/{plan_id}
**Beta:** This endpoint is in beta and may change.
Read a single benefit plan by its Finch ID.




# Get Dependents
Source: https://developer.tryfinch.com/api-reference/benefits/get-plan-dependents

post /employer/plans-dependents
**Beta:** This endpoint is in beta and may change.
Read dependents by Finch ID. A maximum of 50 dependents can be requested at once.




# Get Enrollments
Source: https://developer.tryfinch.com/api-reference/benefits/get-plan-enrollments

post /employer/plans-enrollments
**Beta:** This endpoint is in beta and may change.
Read enrollments by Finch ID. A maximum of 50 enrollments can be requested at once.




# List Dependents
Source: https://developer.tryfinch.com/api-reference/benefits/list-plan-dependents

get /employer/plans-dependents
**Beta:** This endpoint is in beta and may change.
Read the dependents covered under the benefit plans of the company, including their coverage and enrollments.




# List Enrollments
Source: https://developer.tryfinch.com/api-reference/benefits/list-plan-enrollments

get /employer/plans-enrollments
**Beta:** This endpoint is in beta and may change.
Read individuals' enrollments in the company's benefit plans, including coverage dates and contributions.




# List Plans
Source: https://developer.tryfinch.com/api-reference/benefits/list-plans

get /employer/plans
**Beta:** This endpoint is in beta and may change.
Read the benefit plans offered by the company, including carrier, coverage tiers, and deduction codes.




# Create a new connect session
Source: https://developer.tryfinch.com/api-reference/connect/new-session

post /connect/sessions
Create a new connect session for an employer

NOTE: The connect session uses Basic Auth; in the sample request above use `client_id` as the username and `client_secret` as a password.
For example: `Authorization:  Basic <base64 encoded client_id:client_secret>`


# Create a new Connect session for reauthentication
Source: https://developer.tryfinch.com/api-reference/connect/reauthenticate-session

post /connect/sessions/reauthenticate
Create a new Connect session for reauthenticating an existing connection

NOTE: The connect session uses Basic Auth; in the sample request above use `client_id` as the username and `client_secret` as a password.
For example: `Authorization:  Basic <base64 encoded client_id:client_secret>`


# Create Deduction
Source: https://developer.tryfinch.com/api-reference/deductions/create-deduction

post /employer/benefits
Creates a new company-wide deduction or contribution. Please use the `/providers` endpoint to view available types for each provider.

**Availability: Automated and Assisted providers**

Employer Match capabilities are currently in Beta. Please reach out if you are interested in gaining early access.

If the same request is made more than once with the same `type`, `frequency` and `description`, a new item will not be created. Finch will instead return the `benefit_id` of the existing item.

Latencies may vary depending on whether the provider is Automated or Assisted - new items will be created within minutes for Automated providers and within the 2 business day SLA for Assisted providers.


# Enroll Individuals in Deductions
Source: https://developer.tryfinch.com/api-reference/deductions/enroll-individuals-in-deductions

post /employer/benefits/{benefit_id}/individuals
Enroll an individual into a deduction or contribution. This is an overwrite operation. If the employee is already enrolled, the enrollment amounts will be adjusted. Making the same request multiple times will not create new enrollments, but will continue to set the state of the existing enrollment.

**Availability: Automated and Assisted providers**

This is a live request to the provider. Latencies may vary from seconds to minutes depending on the provider and number of benefits.

<Warning>
  Making changes to an individual's deductions may have tax consequences based
  on IRS regulations. Please consult a tax expert to ensure all changes being
  made to the system are compliant with local, state, and federal law.
</Warning>

<Note>
  The request body is a **bare array** of enrollment objects — `[ { "individual_id": …, "configuration": … } ]`. Do not wrap it in an object: sending `{ "items": [ … ] }` returns `400 Expected array but received object`. In the schema below, the `items.` prefix labels each element of the array, not a top-level `items` field.
</Note>

### Enrollment Bodies

Enrollment bodies have a common format for each benefit type, with a different `configuration` schema based on the benefit type. The configurations for each type are outlined below. These are general configurations and may vary per provider. Please use the `/provider` endpoint to view provider specific supported configurations.

#### Retirement Benefits

Includes 401(k), Roth 401(k), 403(b), Roth 403(b), 457, Roth 457, and Simple IRA

| Field                         | Type                   | Description                                                           |
| ----------------------------- | ---------------------- | --------------------------------------------------------------------- |
| `employee_deduction.type`     | `string`               | Deduction Type (`fixed` or `percent`)                                 |
| `employee_deduction.amount`   | `integer`              | Deduction amount in cents (if `fixed`) or basis points (if `percent`) |
| `company_contribution.type`   | `string`               | Contribution Type (`fixed` or `percent`)                              |
| `company_contribution.amount` | `integer`              | Contribution amount in cents (if `fixed`) or basis points             |
| `catch_up`                    | `boolean`              | Whether to enable catch up for this individual                        |
| `annual_maximum`              | `integer` (`nullable`) | The annual maximum in cents for this individual                       |
| `effective_date`\*            | `string` (`nullable`)  | The date which the benefit should take effect by (`mm/dd/yyyy`)       |

#### HSA

| Field                         | Type                   | Description                                                           |
| ----------------------------- | ---------------------- | --------------------------------------------------------------------- |
| `employee_deduction.type`     | `string`               | Deduction Type (`fixed` or `percent`)                                 |
| `employee_deduction.amount`   | `integer`              | Deduction amount in cents (if `fixed`) or basis points (if `percent`) |
| `company_contribution.type`   | `string`               | Contribution Type (`fixed` or `percent`)                              |
| `company_contribution.amount` | `integer`              | Contribution amount in cents (if `fixed`) or basis points             |
| `catch_up`                    | `boolean`              | Whether to enable catch up for this individual                        |
| `annual_maximum`              | `integer` (`nullable`) | The annual maximum in cents for this individual                       |
| `annual_contribution_limit`   | `string` (`nullable`)  | Whether HSA is applied towards `individual` or `family`               |
| `effective_date`\*            | `string` (`nullable`)  | The date which the benefit should take effect by (`mm/dd/yyyy`)       |

#### Section 125 Benefits, FSA, Custom Benefits

| Field                         | Type                  | Description                                                           |
| ----------------------------- | --------------------- | --------------------------------------------------------------------- |
| `employee_deduction.type`     | `string`              | Deduction Type (`fixed` or `percent`)                                 |
| `employee_deduction.amount`   | `integer`             | Deduction amount in cents (if `fixed`) or basis points (if `percent`) |
| `company_contribution.type`   | `string`              | Contribution Type (`fixed` or `percent`)                              |
| `company_contribution.amount` | `integer`             | Contribution amount in cents (if `fixed`) or basis points             |
| `effective_date`\*            | `string` (`nullable`) | The date which the benefit should take effect by (`mm/dd/yyyy`)       |

* Note: `effective_date`s that are undefined or in the past will default to the date the request was made.
  We recommend grouping enrollments by `effective_date` for a request.
  If multiple distinct `effective_date`s are included, the job will be in pending status until the latest `effective_date` enrollment is processed.
  Sandbox integrations do not currently support multiple distinct `effective_date`s within the same request.


# Get All Deductions
Source: https://developer.tryfinch.com/api-reference/deductions/get-all-deductions

get /employer/benefits
List all company-wide deductions and contributions.

**Availability: Automated providers only**

Employer Match capabilities are currently in Beta. Please reach out if you are interested in gaining early access.

This is a live request to the provider. Latencies may vary from seconds to minutes depending on the provider and number of items.

<Note>
  This endpoint returns a **bare array** of benefits — `[ { … } ]` — not an object. In the schema below, the `items.` prefix labels each element of the array, not a top-level `items` field.
</Note>


# Get Deduction
Source: https://developer.tryfinch.com/api-reference/deductions/get-deduction

get /employer/benefits/{benefit_id}
Lists deductions and contributions information for a given item

**Availability: Automated providers only.**

Employer Match capabilities are currently in Beta. Please reach out if you are interested in gaining early access.

This is a live request to the provider. Latencies may vary from seconds to minutes depending on the provider.


# Get Deductions for Individuals
Source: https://developer.tryfinch.com/api-reference/deductions/get-deductions-for-individuals

get /employer/benefits/{benefit_id}/individuals
Get enrollment information for the given individuals.

**Availability: Automated providers only**

This is a live request to the provider. Latencies may vary from seconds to minutes depending on the provider and number of benefits.

<Note>
  This endpoint returns a **bare array** — `[ { … } ]` — not an object. In the schema below, the `items.` prefix labels each element of the array, not a top-level `items` field.
</Note>


# Get Enrolled Individuals
Source: https://developer.tryfinch.com/api-reference/deductions/get-enrolled-individuals

get /employer/benefits/{benefit_id}/enrolled
Lists individuals currently enrolled in a given deduction.

**Availability: Automated providers only**

This is a live request to the provider. Latencies may vary from seconds to minutes depending on the provider and number of benefits.


# Register Deduction
Source: https://developer.tryfinch.com/api-reference/deductions/register-deduction

post /employer/benefits/register
Register existing benefits from the customer on the provider, on Finch's end. Please use the `/provider` endpoint to view available types for each provider.

**Availability: Assisted providers only**


# Unenroll Individuals from Deductions
Source: https://developer.tryfinch.com/api-reference/deductions/unenroll-individuals-from-deductions

delete /employer/benefits/{benefit_id}/individuals
Unenroll individuals from a deduction or contribution

**Availability: Automated and Assisted providers**

This is a live request to the provider. Latencies may vary from seconds to minutes depending on the provider.


# Update Deduction
Source: https://developer.tryfinch.com/api-reference/deductions/update-deduction

post /employer/benefits/{benefit_id}
Updates an existing company-wide deduction or contribution

**Availability: Automated and Assisted providers**

This is a live request to the provider. Latencies may vary from seconds to minutes depending on the provider.


# Handling API Responses
Source: https://developer.tryfinch.com/api-reference/development-guides/Handling-API-Responses

Handle null values and 202 responses from the Finch API — why each occurs and the retry, backoff, and null-check behavior your application should implement.

## Null Values

Finch returns `null` for a field on a record when:

1. the employment system doesn't support the field,
2. the employment system supports the field but the payroll administrator hasn't filled in the data, or
3. Finch can't infer a reasonable value (for example, the categorization of a tax).

Null-ness is per record, not per field — one individual may have a value where another doesn't. Check a field's value for `null` before operating on it — for example, before calling a string method or accessing a nested property — rather than assuming every record has a value.

<Check>
  Check a field's value for `null` before operating on it. Don't assume every record has a value just because other records do.
</Check>

## 202 Response Codes

Requests to the Finch API can return a [`202 Accepted`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/202) response. This means the connection exists but the data isn't available yet — common for async operations. Once the data is available, Finch stops returning `202` for that request.

Requests that can return a `202` response include:

* [Assisted Connect](/integrations/providers#integration-types), including [Assisted Deductions](/implementation-guide/API-Calls/Write-Data#assisted-deductions)
* [Pay statements](/developer-resources/Data-Syncs#pay-statements) that exist but haven't been fetched yet
* [Authentication fallback](/implementation-guide/Integration-Preparation/Configure-Auth-Methods#set-up-authentication-fallback)

Handle a `202` response by:

* **Retrying** the request after a delay. For assisted connections, the SLA for the first data sync is 14 days.
* **Backing off** — increase the delay between retries if the response keeps returning `202`.
* Not processing the response body as data until you receive a successful response.

Examples of 202 Responses:

```json theme={null}
{
  "code": 202,
  "name": "accepted",
  "finch_code": "data_sync_in_progress",
  "message": "The pay statements for this payment are being fetched. Please check back later."
}

{
   "code": 202,
   "name": "authorization_pending",
   "finch_code": "pending",
   "message": "Authorization to this company's data is pending"
}
```

See [Testing assisted integrations](/implementation-guide/Test/Finch-Sandbox#testing-assisted-integrations) to simulate the pending state that produces a `202` response in the Finch Sandbox.


# Headers
Source: https://developer.tryfinch.com/api-reference/development-guides/Headers



## Request Headers

Every request to Finch's API requires the following headers—

| Header              | Description                                                                                                                  |
| ------------------- | ---------------------------------------------------------------------------------------------------------------------------- |
| `Authorization`     | Bearer authorization header, which is formed by concatenating the word “Bearer” with the access token, separated by a space. |
| `Finch-API-Version` | Header used to specify the version for a given API request. Current version is **2020-09-17**.                               |

***

## Response Headers

Finch's additional response headers provide information about the data contained in responses.

| Header                               | Description                                                                                                                                                                                                                                                               |
| ------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `Finch-Request-Id`                   | Each response from Finch's API has a unique request identifier. If you need to contact us about a specific request, providing the request identifier will ensure the fastest possible resolution.                                                                         |
| `Finch-Data-Retrieved`               | The date/time in ISO-8601 format that the data was retrieved from the employment system.                                                                                                                                                                                  |
| `Finch-Last-Attempted-Update-Date`   | The date/time in ISO-8601 format that Finch last attempted to update this data.                                                                                                                                                                                           |
| `Finch-Last-Attempted-Update-Result` | The result of Finch's last attempted update. Possible values:<br />`success`: the last attempt succeeded<br />`error`: the last attempt errored<br />`partial_error`: (batch requests only) the last attempt succeeded for some items in the batch and failed for others. |


# Permissions
Source: https://developer.tryfinch.com/api-reference/development-guides/Permissions



Each Finch `access_token` can only make API calls to endpoints the end-user has granted an application permission to. Permissions are specified by the `product` parameter when launching Connect. Valid permissions are—

| Permission      | Endpoints                                       | Description                                                        |
| --------------- | ----------------------------------------------- | ------------------------------------------------------------------ |
| `company`       | `/employer/company`                             | Read basic company data                                            |
| `directory`     | `/employer/directory`                           | Read company directory and organization structure                  |
| `individual`    | `/employer/individual`                          | Read individual data, excluding income and employment data         |
| `ssn`           | `/employer/individual`                          | Read SSN for individuals.                                          |
| `employment`    | `/employer/employment`                          | Read individual employment and income data                         |
| `payment`       | `/employer/payment`<br />`/employer/pay-groups` | Read payroll and contractor related payments by the company        |
| `pay_statement` | `/employer/pay-statement`                       | Read detailed pay statements for each individual                   |
| `benefits`      | `/employer/benefits/*`                          | Create and manage benefits and benefit enrollment within a company |
| `documents`     | `/employer/documents/*`                         | Read company documents                                             |


# Rate Limits
Source: https://developer.tryfinch.com/api-reference/development-guides/Rate-Limits

In this guide, you'll learn about total rate limits for Finch, rate limits for specific IP Addresses, and how to handle rate limit errors.

Finch's rate limits work on a per-endpoint basis for applications, and we refer to each distinct endpoint as a unique `product`. Rate limits are summed on a rolling 60-second basis for each unique `product`. This is commonly referred to as a Sliding or Rolling Window rate limit.

<Info>
  **Access Token rate limits** Finch previously enforced rate limits at the
  access token level but this is no longer the case as of August 2023.
</Info>

You can think of a `product` rate limit like a "bucket". Therefore, when a request is made to a `product` (which corresponds directly to an API endpoint), a single gallon of water is added to that endpoint's bucket, thus starting that bucket's 60-second time-to-live (TTL) timer.

After the product's rate limit is reset after 60 seconds, the first request to that `product` starts the 60-second TTL again.

***

## Application Rate Limits

A Finch application has its own rate limits and all access tokens associated with the application will be subject to the application's rate limits. For application-level rate limits, each `product` manages a bucket simultaneously counting all requests across all access tokens created by that application. Multiple access tokens can be created from a single Finch application as more employers are connected. (A Finch application corresponds to a unique `client_id`. You may have several `client_id`s if you use a development or sandbox application in addition to production).

| Product              | Max requests initiated per minute |
| -------------------- | --------------------------------- |
| `company`            | 20                                |
| `directory`          | 20                                |
| `documents`          | 20                                |
| `individual`         | 20                                |
| `employment`         | 20                                |
| `pay-statement-item` | 20                                |
| `payment`            | 12                                |
| `pay-groups`         | 12                                |
| `pay-statement`      | 12                                |

If an application rate limit is encountered, it will contain the `finch_code`: [finch\_application\_rl](/api-reference/development-guides/errors/Error-Types#error-types-1) in the response body.

```json theme={null}
// HTTP 429 response body for application rate limit exceeded
{
    "statusCode": 429,
    "status": 429,
    "code”: 429,
    "message": "Too many requests for token",
    "name": "rate_limit_exceeded_error",
    "finch_code": "finch_application_rl"
}
```

## IP Address Rate Limits

Finch also enforces individual IP Address rate limits. An IP address is a unique address that identifies a device on the internet or a local network. If the number of `max requests` are sent from the same IP Address within the `duration` time set, a `penalty` is enforced. No more requests are allowed once the penalty is enforced. Once the penalty duration is complete, requests will be accepted again.

| Type  | Max requests | Duration  | Penalty    |
| ----- | ------------ | --------- | ---------- |
| `API` | 1000         | 5 minutes | 60 minutes |

If an IP Address rate limit is encountered, it will contain the `finch_code`: [finch\_api\_ip\_rl](/api-reference/development-guides/errors/Error-Types#error-types-1) in the response body.

```json theme={null}
// HTTP 429 response body for application rate limit exceeded
{
    "statusCode": 429,
    "status": 429,
    "code”: 429,
    "message": "Too many requests for token",
    "name": "rate_limit_exceeded_error",
    "finch_code": "finch_api_ip_rl"
}
```

***

## Handling Rate Limit Errors

If you are experiencing rate limits, there are several ways to minimize the risk of hitting rate limits highlighted in our [Handling Rate Limit Errors](/implementation-guide/Backend-Application/Mitigate-Errors#rate-limit-errors) Best Practices guide.


# API Versioning
Source: https://developer.tryfinch.com/api-reference/development-guides/Versioning



We periodically release new, dated versions of the API whenever we make breaking changes. Although we try to only make backward-compatible changes, sometimes we have to make a breaking change to iterate on the API. In addition to the below, please also reference our [API Changes](/developer-resources/api-changes) page for more details and creating a robust integration.

**We consider the following changes backward compatible**

* Adding new API endpoints
* Adding new optional parameters to existing endpoints
* Adding new data elements to existing responses
* Adding new error types

Our current version is **2020-09-17**

The `Finch-API-Version` header must be set for every single request to our API.


# Error Handling
Source: https://developer.tryfinch.com/api-reference/development-guides/errors/Error-Handling



## Errors

### 500 Internal Server Errors

Server errors indicate an error on Finch's side and return an HTTP response with a `500` status code.

**Common causes**

* Finch is experiencing internal system issues. This is rare.
* The underlying employment system is experiencing internal system issues.
* Finch received an unsupported response from the underlying employment system and is unable to process it. These are usually quickly resolved by our support team.
* The end-user has intentionally or unintentionally revoked Finch's access to their system. This is usually returned as a `401 - reauthenticate_user` error but can sometimes be returned as `500 - server_error`.

**Troubleshooting steps**

* Retrying immediately usually will not resolve the issue. We recommend retrying the API request in a few hours.
* If the error persists, submit a support ticket with the `Finch-Request-ID` present in the headers of the response.

### 401 re-authentication errors

Authentication errors indicate an error on the end user's side. See the [re-authentication docs](/developer-resources/Reauthentication) for more on common causes and troubleshooting steps.

### 408 client connection errors

Timeout errors occur when a client connection is closed while the API server is still processing the request. Currently, our server timeout is set to 6 minutes. Therefore, our recommendation is to increase the configured client timeout to 6 minutes to ensure that the client does not timeout prematurely. If you have not configured one explicitly, there is likely a default depending on the request library you're using. Note, it's not common that our API takes this long to service a request.

## Batch Requests

A number of Finch endpoints (like `/individual`, `/employment`, and `/pay-statement`) are batch endpoints.

For such endpoints, Finch can return errors in two ways:

1. Return an error per batch request item within the response body. The error will be in the same format described in the [Error Types guide](/api-reference/development-guides/errors/Error-Types).
   * Finch also returns an `error_name` and `error_message` in the response body. **These fields are deprecated in favor of conforming to our standard error formatting.**
2. Return an error at the HTTP status code level. The error will be in the same format described in the [Error Types guide](/api-reference/development-guides/errors/Error-Types).

<Info>
  Ensure your application can handle both types of errors from a batch API call.
</Info>

```jsx Response level theme={null}
Response HTTP Status Code: 200

Response Body:
{
  "responses": [
    {
      // this id varies by endpoint, could also be payment_id or benefit_id
      "individual_id": "fbeabe51-e6d2-45aa-a460-4c8482528f41",
      // corresponds to the `code` parameter of the error schema in the Error Types guide
      "code": 404,
      "body": {
        "name": "not_found_error",
        "code": 404,
        "finch_code": "individual_not_found",
        "message": "The individual with id 'fbeabe51-e6d2-45aa-a460-4c8482528f41' could not be found",
        // deprecated field. corresponds to the `name` parameter of the error schema in the Error Types guide
        "error_name": "not_found_error",
        // deprecated field. corresponds to the `message` parameter of the error schema in the Error Types guide
        "error_message": "The individual with id 'fbeabe51-e6d2-45aa-a460-4c8482528f41' could not be found"
      }
    }
  ]
}
```

```jsx Status code level theme={null}
Response HTTP Status Code: 500

Error Body:
{
  "code": 500,
  "name": "server_error",
  "message": "Internal server error"
}
```

<Warning>
  Refer to the API reference to ensure your application handles errors from each
  batch endpoint correctly as response schemas vary by endpoint.
</Warning>


# Error Types
Source: https://developer.tryfinch.com/api-reference/development-guides/errors/Error-Types



In case of an error, Finch's API will respond with an appropriate HTTP status code and error body.

Finch uses HTTP status codes to indicate the success or failure of an API request.

* `2xx`: indicates success
* `4xx`: indicates developer or user-related errors
* `5xx`: indicates Finch-related issues

## Error Schema

| Name         | Type      | Description                                                                                  |
| ------------ | --------- | -------------------------------------------------------------------------------------------- |
| `code`       | `integer` | The HTTP status code of the response.                                                        |
| `name`       | `string`  | An identifier, safe for programmatic use, describing the broad error category.               |
| `finch_code` | `string`  | An optional identifier describing the error in more detail. It is safe for programmatic use. |
| `message`    | `string`  | A developer friendly message explaining the error.                                           |

## Error Types

| Name                          | Finch Code                         | Code | Description                                                                                                                                                             |
| ----------------------------- | ---------------------------------- | ---- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `invalid_grant_error`         |                                    | 400  | The authorization code is invalid.                                                                                                                                      |
| `bad_request`                 | `invalid_request`                  | 400  | Failed to validate request.                                                                                                                                             |
| `bad_request`                 | `enrollment_not_found`             | 404  | Failed find the enrollment for an individual in a benefit.                                                                                                              |
| `invalid_token_error`         |                                    | 401  | The `access_token` is incorrect.                                                                                                                                        |
| `invalid_request_error`       |                                    | 401  | The request does not match the docs. Example: the request is missing a query parameter.                                                                                 |
| `authentication_error`        | `reauthenticate_user`              | 401  | The user will need to reconnect their employment system. [See more here](/implementation-guide/Backend-Application/Mitigate-Errors#reauthentication-errors).            |
| `authentication_error`        | `account_setup_required`           | 401  | The user will need to connect their employment system.                                                                                                                  |
| `invalid_client_error`        |                                    | 401  | The provided application credentials were incorrect. Relevant to the `/auth/token` endpoint.                                                                            |
| `unauthorized_request_error`  |                                    | 401  | The `access_token` is missing from the header.                                                                                                                          |
| `payment_required`            | `payment_required`                 | 402  | The application has unpaid invoices and cannot access the Finch API until payment is settled.                                                                           |
| `error_permissions`           | `insufficient_account_permissions` | 403  | The user will need to update the permissions assigned to the third-party admin account.                                                                                 |
| `insufficient_scope_error`    |                                    | 403  | The application credentials have insufficient permissions to access the requested product.                                                                              |
| `not_found_error`             | `item_not_found`                   | 404  | The requested resource could not be found.                                                                                                                              |
| `not_found_error`             | `benefit_not_found`                | 404  | The requested benefit could not be found.                                                                                                                               |
| `not_found_error`             | `individual_not_found`             | 404  | The requested individual could not be found.                                                                                                                            |
| `not_found_error`             | `payment_not_found`                | 404  | The requested payment could not be found.                                                                                                                               |
| `client_connection_closed`    |                                    | 408  | The client connection is closed while the API server is still processing the request. Currently, our server timeout is set to 6 minutes.                                |
| `unprocessable_request_error` | `unsupported_parameters`           | 422  | Parameters provided are not supported by the provider or benefit. Relevant to the `/employer/benefits/*` endpoints.                                                     |
| `unprocessable_request_error` | `invalid_employee_enrollment`      | 422  | The employee is unable to be enrolled in a benefit due specific to constraints on the provider side. Relevant to the `/employer/benefits/*` endpoints.                  |
| `rate_limit_exceeded_error`   | `finch_application_rl`             | 429  | The application has exceeded Finch's [application rate limits](/api-reference/development-guides/Rate-Limits#application-rate-limits).                                  |
| `rate_limit_exceeded_error`   | `finch_api_ip_rl`                  | 429  | The application has exceeded Finch's [IP Address rate limits](/api-reference/development-guides/Rate-Limits#ip-address-rate-limits).                                    |
| `rate_limit_exceeded_error`   | `finch_auth_ip_rl`                 | 429  | The application has exceeded Finch Connect rate limits. See [rate limit errors](/implementation-guide/Backend-Application/Mitigate-Errors#rate-limit-errors).           |
| `rate_limit_exceeded_error`   | `upstream_rate_limit_exceeded`     | 429  | The application has exceeded the upstream provider's rate limits. See [rate limit errors](/implementation-guide/Backend-Application/Mitigate-Errors#rate-limit-errors). |
| `server_error`                |                                    | 500  | The server experienced an unexpected error.                                                                                                                             |
| `not_implemented_error`       |                                    | 501  | Finch does not support this specific endpoint for this specific provider.                                                                                               |
| `bad_gateway_error`           | `upstream_provider_error`          | 502  | The server experienced an unexpected error while interacting with an upstream service, such as a provider.                                                              |


# Get Document
Source: https://developer.tryfinch.com/api-reference/documents/get-document

get /employer/documents/{document_id}
**Beta:** This endpoint is in beta and may change.
Retrieve details of a specific document by its ID.




# List Documents
Source: https://developer.tryfinch.com/api-reference/documents/get-documents

get /employer/documents
**Beta:** This endpoint is in beta and may change.
Retrieve a list of company-wide documents.




# Create Access Token
Source: https://developer.tryfinch.com/api-reference/management/create-access-token

post /auth/token
Exchange the authorization code for an access token



# Disconnect
Source: https://developer.tryfinch.com/api-reference/management/disconnect

post /disconnect
Disconnect one or more `access_token`s from your application.

Deletion is based on both the employer and provider of the `access_token` used to call this endpoint, and will also delete all tokens with the same employer/provider pair. Other tokens for the same employer, but connected to a different provider, require a separate call.

We require applications to implement the Disconnect endpoint for billing and security purposes.


# Disconnect Entity
Source: https://developer.tryfinch.com/api-reference/management/disconnect-entity

post /disconnect-entity
Disconnect entity(s) from a connection without affecting other entities associated with the same connection.

Disconnection is scoped to the `entity_id(s)` provided in the request body. The entity(s) must belong to the connection associated with the `access_token` used to call this endpoint. All other entities linked to the same connection remain active and unaffected. If you need to disconnect all entities under a connection at once, use the [Disconnect](/api-reference/management/disconnect) endpoint instead.


# Enqueue a New Automated Job
Source: https://developer.tryfinch.com/api-reference/management/enqueue-a-new-automated-job

post /jobs/automated
Enqueue an automated job.

`data_sync_all`: Enqueue a job to re-sync all data for a connection. `data_sync_all` has a concurrency limit of 1 job at a time per connection. This means that if this endpoint is called while a job is already in progress for this connection, Finch will return the `job_id` of the job that is currently in progress. Finch allows a fixed window rate limit of 1 forced refresh per hour per connection.

`w4_form_employee_sync`: Enqueues a job for sync W-4 data for a particular individual, identified by `individual_id`. This feature is currently in beta.

This endpoint is available for *Scale* tier customers as an add-on. To request access to this endpoint, please contact your Finch account manager.



# Introspect
Source: https://developer.tryfinch.com/api-reference/management/introspect

get /introspect
Read account information associated with an `access_token`



# List All Automated Jobs
Source: https://developer.tryfinch.com/api-reference/management/list-all-automated-jobs

get /jobs/automated
Get all automated jobs. Automated jobs are completed by a machine. By default, jobs are sorted in descending order by submission time. For scheduled jobs such as data syncs, only the next scheduled job is shown.



# Providers
Source: https://developer.tryfinch.com/api-reference/management/providers

get /providers
Return details on all available payroll and HR systems.



# Request Forwarding
Source: https://developer.tryfinch.com/api-reference/management/request-forwarding

post /forward
The Forward API allows you to make direct requests to an employment system. If Finch's unified API
doesn't have a data model that cleanly fits your needs, then Forward allows you to push or pull
data models directly against an integration's API.



# Retrieve a Manual Job
Source: https://developer.tryfinch.com/api-reference/management/retrieve-a-manual-job

get /jobs/manual/{job_id}
Check the status and outcome of a job by `job_id`. This includes all deductions jobs including those for both automated and assisted integrations.



# Retrieve an Automated Job
Source: https://developer.tryfinch.com/api-reference/management/retrieve-an-automated-job

get /jobs/automated/{job_id}
Get an automated job by `job_id`.



# Company
Source: https://developer.tryfinch.com/api-reference/organization/company

get /employer/company
Read basic company data



# Directory
Source: https://developer.tryfinch.com/api-reference/organization/directory

get /employer/directory
Read company directory and organization structure



# Employment
Source: https://developer.tryfinch.com/api-reference/organization/employment

post /employer/employment
Read individual employment and income data

Note: Income information is returned as reported by the provider. This may not always be annualized income, but may be in units of bi-weekly, semi-monthly, daily, etc, depending on what information the provider returns.


# Individual
Source: https://developer.tryfinch.com/api-reference/organization/individual

post /employer/individual
Read individual data, excluding income and employment data



# Create Rule
Source: https://developer.tryfinch.com/api-reference/payroll/create-rule

post /employer/pay-statement-item/rule
Custom rules can be created to associate specific attributes to pay statement items depending on the use case. For example, pay statement items that meet certain conditions can be labeled as a pre-tax 401k. This metadata can be retrieved where pay statement item information is available.




# Delete Rule
Source: https://developer.tryfinch.com/api-reference/payroll/delete-rule

delete /employer/pay-statement-item/rule/{rule_id}
Delete a rule for a pay statement item.



# Ledger Items
Source: https://developer.tryfinch.com/api-reference/payroll/get-ledger-items

post /employer/ledger-items
Read the ledger entries for one or more payments.

<Note>
  **Beta** — This endpoint is currently available for **Gusto** only. Endpoint paths and field names may change before general availability.
</Note>


# Get Pay Group
Source: https://developer.tryfinch.com/api-reference/payroll/get-pay-group

get /employer/pay-groups/{pay_group_id}
Read information from a single pay group



# Get All Pay Groups
Source: https://developer.tryfinch.com/api-reference/payroll/get-pay-groups

get /employer/pay-groups
Read company pay groups and frequencies



# Pay Statement Item
Source: https://developer.tryfinch.com/api-reference/payroll/get-pay-statement-items

get /employer/pay-statement-item
Retrieve a list of detailed pay statement items for the access token's connection account.




# Get Rules
Source: https://developer.tryfinch.com/api-reference/payroll/get-rules

get /employer/pay-statement-item/rule
List all rules of a connection account.



# Pay Statement
Source: https://developer.tryfinch.com/api-reference/payroll/pay-statement

post /employer/pay-statement
Read detailed pay statements for each individual.

Deduction and contribution types are supported by the payroll systems that supports Benefits.



# Payment
Source: https://developer.tryfinch.com/api-reference/payroll/payment

get /employer/payment
Read payroll and contractor related payments by the company.



# Update Rule
Source: https://developer.tryfinch.com/api-reference/payroll/update-rule

put /employer/pay-statement-item/rule/{rule_id}
Update a rule for a pay statement item.



# Create a new sandbox account
Source: https://developer.tryfinch.com/api-reference/sandbox/create-sandbox-account

post /sandbox/connections/accounts
Create a new account for an existing connection (company/provider pair)



# Create a new Sandbox Connection
Source: https://developer.tryfinch.com/api-reference/sandbox/create-sandbox-connection

post /sandbox/connections
Create a new connection (new company/provider pair) with a new account



# Add new individuals to a sandbox company
Source: https://developer.tryfinch.com/api-reference/sandbox/create-sandbox-employee

post /sandbox/directory

<Warning>
  Note that requests using the SDK will require a JSON object with a key of `body` and a value of an array of individuals.

  ```
  // JavaScript example
  await client.sandbox.directory.create({
    body: [
      // list of individual objects
    ]
  })
  ```
</Warning>


# Add a new sandbox payment
Source: https://developer.tryfinch.com/api-reference/sandbox/create-sandbox-payment

post /sandbox/payment

All fields are optional. If you don't provide a start and end date, the default `start_date` is one business day after the `end_date` of the most recently created payment, and the default `end_date` is `start_date` + 14 business days. The default `pay_date` is the `end_date` and the default `debit_date` is one business day after the `pay_date`.

You may override any fields in the pay statements you would like. By default, no taxes, earnings or deductions are created (unless an individual is enrolled in deductions via the `/benefits` endpoints).


# Get configurations for sandbox jobs
Source: https://developer.tryfinch.com/api-reference/sandbox/get-sandbox-jobs-configuration

get /sandbox/jobs/configuration



# Enqueue a new sandbox job
Source: https://developer.tryfinch.com/api-reference/sandbox/refresh-job

post /sandbox/jobs

Analogous to [`POST /jobs/automated`](/api-reference/management/enqueue-a-new-automated-job), but for automated and assisted Finch Sandbox connections. Use this endpoint after updating a Finch Sandbox connection's data to "sync" the data with Finch and see it reflected in `/employer` data API calls.

<Note>
  Assisted connections will return `null` for `job_id` and `job_url`, since no job is actually being created. Simply call this endpoint, and then call the `/employer` API to see the updated data.
</Note>


# Update a sandbox account
Source: https://developer.tryfinch.com/api-reference/sandbox/update-sandbox-account

put /sandbox/connections/accounts
Update an existing sandbox account. Change the connection status to understand how the Finch API responds.



# Update a sandbox company's data
Source: https://developer.tryfinch.com/api-reference/sandbox/update-sandbox-company

put /sandbox/company



# Update sandbox employment
Source: https://developer.tryfinch.com/api-reference/sandbox/update-sandbox-employment

put /sandbox/employment/{individual_id}



# Update sandbox individual
Source: https://developer.tryfinch.com/api-reference/sandbox/update-sandbox-individual

put /sandbox/individual/{individual_id}



# Update configurations for sandbox jobs
Source: https://developer.tryfinch.com/api-reference/sandbox/update-sandbox-jobs-configuration

put /sandbox/jobs/configuration



# Build or audit a Finch integration with AI agents
Source: https://developer.tryfinch.com/developer-resources/Build-or-Audit-with-AI

Finch Integration Skills guide an AI agent through building a new Finch integration or auditing an existing one — answer questions about your stack and get reviewable code, or point the agent at your repo and get a findings report.

The Finch Integration Skills are a set of AI agent skills that guide an AI coding agent through building or auditing a Finch integration.

Two skills — one backend, one frontend — build a new integration. You answer about ten questions about your stack and use case, and the agent generates the integration code and tests for each component: Finch Connect, token management, API calls, webhooks, and reauthentication.

A third skill audits an integration you already have. Point it at your repo instead of answering setup questions, and it checks your existing backend and/or frontend code against the same rules the build skills use to generate code, then produces a severity-rated findings report — no code changes unless you ask for them afterward. See [Audit an existing integration](#audit-an-existing-integration).

The skills handle the integration plumbing. The application logic on top of the data — how you process, display, and act on it — remains yours to build.

<Note>
  **Beta.** The Finch Integration Skills are in active development. The Finch team continues to test and improve them. As with all AI-generated code, treat the output as a starting point, not production-ready code. Review it against the [Finch docs](/how-finch-works/finch-overview) and [API reference](/api-reference), test it thoroughly, and revise it before you deploy.
</Note>

## What the skills generate

There are three skills: backend, frontend, and audit. Load the backend and frontend skills together for a fullstack build, or load only the one for the layer you own — the backend skill ends at "return the session token to the frontend"; the frontend skill starts there. Load the audit skill instead of either when you already have an integration and want it reviewed, not rebuilt.

**Backend skill** generates:

* Finch Connect session creation for the embedded and redirect flows, with reauthentication routing when a connection breaks
* Authorization code exchange, access token encryption, and database persistence
* A reusable Finch API client with rate limiting, pagination, and error handling
* A data fetcher for each product scope you select, with upsert logic
* A webhook handler with signature verification and event routing
* A database schema and tests — unit tests with mocked HTTP, plus integration tests against the Finch Sandbox

**Frontend skill** generates:

* A Connect button that fetches a session and launches Finch Connect
* Embedded launch through the Finch React or JavaScript SDK, or the redirect flow with no SDK
* Authorization code handoff to your backend on success
* A reauthentication UI — a banner or settings-page component that re-launches Finch Connect when a connection breaks
* Tests — component tests and end-to-end tests against the Finch Sandbox

**Audit skill** produces, instead of code:

* An inventory of what's actually implemented — Connect flow type, product scopes, entity handling, reauthentication, disconnect, webhooks, token storage, test coverage — for the backend, frontend, or both in one pass
* A check of that inventory against the backend and frontend skills' own correctness rules, plus a set of known deprecated patterns
* A severity-rated findings report, with file:line evidence and a fix recommendation for each finding, cross-referenced to the relevant backend or frontend skill step
* Fixes, only for findings you explicitly ask it to address afterward, implemented one at a time following the corresponding backend/frontend skill guidance

The backend and frontend skills are language- and framework-agnostic. Generated code is tailored to the stack you name.

<Note>
  The backend skill generates native HTTP implementations and does not use a Finch backend SDK. This keeps the generated code self-contained and consistent across languages. The frontend skill does use the Finch Connect SDK for the embedded flow.
</Note>

## Prerequisites

<Steps>
  <Step title="An AI coding agent that supports agent skills">
    You need an AI tool that can load a `SKILL.md` file — for example, Claude Code, Cursor, or Codex CLI. The skill drives the workflow; your agent generates the code.
  </Step>

  <Step title="The Finch documentation MCP server connected to your agent">
    **Required.** The skill provides the workflow structure; the Finch documentation MCP server supplies the specifics — current endpoint details, field names, response shapes, error codes, and SDK versions — while your agent generates code. The two are designed to work together, and the skill assumes the MCP server is connected.

    The server URL is `https://developer.tryfinch.com/mcp`. It's public — no credentials or Finch account required to connect.

    <Tabs>
      <Tab title="Claude Code">
        Add the server from the terminal:

        ```bash theme={null}
        claude mcp add --transport http finch-docs https://developer.tryfinch.com/mcp
        ```

        Confirm it connected:

        ```bash theme={null}
        claude mcp list
        ```

        `finch-docs` should show as connected. This adds the server at the user level, so it's available in any project — add `--scope project` instead if you only want it in the current one.
      </Tab>

      <Tab title="Claude (claude.ai / Desktop)">
        1. Go to [claude.ai/settings/connectors](https://claude.ai/settings/connectors).
        2. Click **Add custom connector**.
        3. Enter a name (for example, `Finch docs`) and the URL `https://developer.tryfinch.com/mcp`.
        4. Click **Add**.
        5. In a chat, click the attachments (plus) icon and select the connector to make it available.
      </Tab>

      <Tab title="Other tools">
        Most MCP-capable tools support adding a remote server by URL — for example, Cursor and VS Code take a `url` entry in an `mcp.json` file. Check your tool's documentation for the exact syntax; the value you need in every case is the same URL above.
      </Tab>
    </Tabs>
  </Step>

  <Step title="A Finch developer account with a Sandbox application">
    You need a Sandbox application and its `client_id` and `client_secret`. The generated integration tests run against the Finch Sandbox. Sandbox and Production are separate applications with separate credentials — register redirect URIs and webhook endpoints in each. Create an account at [dashboard.tryfinch.com](https://dashboard.tryfinch.com).
  </Step>
</Steps>

<Warning>
  **If the MCP server isn't connected, the skill still runs — but expect gaps.** The skill falls back to web search or its own training data to fill in specifics it would otherwise look up live. This can produce code that references outdated field names or response shapes, an outdated SDK version or API surface, or an incomplete set of product scopes or webhook events — errors that surface as failed tests or runtime errors against the Sandbox, not as warnings during code generation. Connect the MCP server before starting the skill, not after something breaks.
</Warning>

<Info>
  **This is not the same MCP as the [Finch MCP Server](/developer-resources/Finch-MCP-Server).** Finch has two separate MCP servers with similar names:

  |              | Finch documentation MCP                | [Finch MCP Server](/developer-resources/Finch-MCP-Server)         |
  | ------------ | -------------------------------------- | ----------------------------------------------------------------- |
  | **Purpose**  | Searches Finch's documentation         | Calls the live Finch API                                          |
  | **Acts on**  | Published docs and API reference       | A specific employer connection's real data                        |
  | **Requires** | Nothing — no credentials               | A Finch `access_token` for that connection                        |
  | **Used for** | Building this integration (this guide) | Querying employee/payroll data in natural language once connected |

  The Finch Integration Skills use the **documentation MCP server** described above. Connecting the Finch MCP Server instead won't give the skill what it needs — it has no way to look up documentation.
</Info>

## Load the skills

Because the [Finch documentation MCP server](#prerequisites) is already required, the simplest way to load a skill is straight from that connection — the server exposes all three skills as MCP resources, so your agent can pull the one it needs with no separate install:

* **Claude Code:** in the prompt, type `@` to open the resource picker and select the skill you need — backend, frontend, or audit — from the `finch-docs` server (whatever name you gave it in [Step 2](#prerequisites)). Load backend and frontend together for a fullstack build; load audit on its own to review an existing integration.
* **Other MCP clients:** look for the resource or attachment picker tied to the connected server. The UI varies by tool, but the mechanism — an MCP resource, not a downloaded file — is the same.

If your agent isn't connected to the MCP server or doesn't support MCP resources, point it at the raw `SKILL.md` files directly:

* Backend — `https://developer.tryfinch.com/.well-known/agent-skills/finch-integration-backend/SKILL.md`
* Frontend — `https://developer.tryfinch.com/.well-known/agent-skills/finch-integration-frontend/SKILL.md`
* Audit — `https://developer.tryfinch.com/.well-known/agent-skills/finch-integration-audit/SKILL.md`

<Note>
  You don't need `npx skills add` for these skills. The documentation MCP server is already required and serves the skills as MCP resources, so connecting it is enough. The [skills CLI](https://www.npmjs.com/package/skills) (`npx skills add https://developer.tryfinch.com`) is an optional alternative if you'd rather install the skills into your agent's context instead of pulling them from the MCP connection.
</Note>

## How it works

This section describes the backend and frontend skills' build flow. For the audit skill, which doesn't ask setup questions, see [Audit an existing integration](#audit-an-existing-integration) below.

<Steps>
  <Step title="Start the skill">
    Tell your agent you want to build a Finch integration and point it at the skill. The backend and frontend skills each open with a short setup questionnaire.
  </Step>

  <Step title="Answer the setup questions">
    Each skill runs through a short setup questionnaire before generating anything. Expect to cover:

    * Your stack — language, framework, database, and test framework
    * Your integration setup — new app or existing one, product scopes, and Connect flow
    * Your operational choices — how you identify each employer, reauthentication and webhook strategy, token storage, and test coverage

    Answer each section before the agent continues. Your answers shape the generated code.
  </Step>

  <Step title="Review the generated code">
    The agent generates each component as a labeled, copy-ready section, with comments that link back to the relevant Finch documentation. Read it against the docs, adjust with follow-up prompts, and run the tests.
  </Step>

  <Step title="Test against the Sandbox">
    Run the generated integration tests against your Sandbox application. Complete a full Connect flow in the Sandbox before you point the integration at Production.
  </Step>
</Steps>

## Audit an existing integration

Use the audit skill instead of the backend or frontend skill when you already have a Finch integration and want it checked for gaps — not built from scratch. Reach for it when the question is "is our existing integration missing anything?" rather than "help me build this."

The audit skill covers both layers in a single pass — point it at your backend, your frontend, or both, and it reports findings for whichever you include. You don't need to run the backend and frontend skills separately to get equivalent coverage; the audit skill loads their checklists itself and evaluates your code against both.

<Info>
  The audit skill still depends on the backend and frontend skills — it fetches their audit criteria directly from the skill files, rather than duplicating them, via the Finch documentation MCP server or directly from the [backend](https://developer.tryfinch.com/.well-known/agent-skills/finch-integration-backend/SKILL.md) and [frontend](https://developer.tryfinch.com/.well-known/agent-skills/finch-integration-frontend/SKILL.md) skill URLs. If that fetch fails, expect your agent to say so before proceeding — a report built only from general knowledge of Finch Connect is lower-confidence and shouldn't be presented as a full audit against the current checklist.
</Info>

To prompt it, tell your agent what to audit and point it at the skill — for example:

> Audit my existing Finch integration for gaps using the Finch integration audit skill. It's in `src/integrations/finch` on the backend and `src/components/connect` on the frontend — check both.

Or, if you already suspect a specific issue:

> Run the Finch integration audit skill on our backend only. Reauthentication doesn't seem to be triggering when a connection breaks — investigate that end-to-end, and check everything else too.

Even when you lead with a bug you're confident is real and expect a quick patch, expect the same discovery pass and a written report first, not an immediate fix — the audit skill investigates and confirms every finding, including one you already suspected, before changing any code.

The skill produces a written report only — findings with file:line evidence, severity, and remediation guidance. Review the report, then ask it to implement specific fixes one at a time as a separate, explicit follow-up if you want it to; it follows the corresponding backend or frontend skill's guidance for each fix rather than improvising one.

## What's yours to build

* **Application logic is yours.** The skills handle the integration plumbing — authentication, token management, API calls, webhooks — the high-effort work that looks similar across most Finch integrations. How your application processes, displays, and acts on the data takes additional development tailored to your use case.
* **Verify against the docs.** Use the [Implementation Guide](/implementation-guide/go-live-checklist) and [API reference](/api-reference) to confirm the generated code matches current Finch API behavior. Response shapes change across API versions.
* **The skills work best together.** A fullstack developer should load both — the backend skill ends at the session token, the frontend skill starts there.

Expect to iterate with additional prompts to fit the generated code to your application.

## Time to integrate

You can answer the setup questions in under an hour and receive every component, then shift your time from writing integration code to reviewing, testing, and adapting it. Actual savings vary with your application's complexity and how many revision cycles it takes, but most teams save several days to a few weeks compared to writing the plumbing by hand. For the audit skill, a pass is typically one agent conversation instead of a multi-day manual review.

## Next steps

<CardGroup>
  <Card title="Finch Connect setup" href="/implementation-guide/Connect/Set-Up-Finch-Connect">
    How Finch Connect sessions and the embedded and redirect flows work.
  </Card>

  <Card title="API reference" href="/api-reference">
    Endpoint details, field definitions, and response shapes to verify generated code.
  </Card>

  <Card title="Reauthentication" href="/developer-resources/Reauthentication">
    What happens when a connection breaks and how to recover it.
  </Card>

  <Card title="Finch Sandbox" href="/implementation-guide/Test/Finch-Sandbox">
    Test your integration end-to-end before going to Production.
  </Card>
</CardGroup>


# W-2 Box 1
Source: https://developer.tryfinch.com/developer-resources/Calculating-W2-Box1-value

Finch's data can be used to run an individual's W-2 Box 1 calculation using data returned from Finch Pay endpoints.

**Box 1 is defined in the IRS' ["2024 General Instructions for Forms W-2 and W-3" published guidance](https://www.irs.gov/pub/irs-pdf/iw2w3.pdf) as:**

> Wages, tips, other compensation. Show the total taxable wages, tips, and other compensation that you paid to your employee during the year. However, do not include elective deferrals (such as employee contributions to a section 401(k) or 403(b) plan) except section 501(c) (18) contributions.
> Include the following. 1. Total wages, bonuses (including signing bonuses), prizes, and awards paid to employees during the year. See Calendar year basis. 2. Total noncash payments, including (...) 24. Salary reduction contributions made to a Roth IRA pursuant to a SEP arrangement or SIMPLE IRA plan. See SEP arrangements and SIMPLE IRA plans.

### Tabulated IRS criteria:

| #  | IRS Text                                                                                                                                | <Tooltip>Occurence</Tooltip> | <Tooltip>Group</Tooltip>                                                      |
| -- | :-------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------- | :---------------------------------------------------------------------------- |
| 1  | "Total wages, bonuses (including signing bonuses), prizes, and (...) <Tooltip>full text</Tooltip>                                       | <Tooltip>ALWAYS</Tooltip>    | [Earning](/how-finch-works/unified-employment-api-glossary#earning)           |
| 2  | "Total noncash payments, including certain fringe benefits. See Fringe benefits."                                                       | <Tooltip>COMMON</Tooltip>    | [Earning](/how-finch-works/unified-employment-api-glossary#earning)           |
| 3  | "Total tips reported by the employee to the employer (not allocated tips)."                                                             | <Tooltip>COMMON</Tooltip>    | [Earning](/how-finch-works/unified-employment-api-glossary#earning)           |
| 4  | "Certain employee business expense reimbursements. See Employee business expense reimbursements."                                       | <Tooltip>COMMON</Tooltip>    | [Earning](/how-finch-works/unified-employment-api-glossary#earning)           |
| 5  | "The cost of accident and health insurance premiums for 2%-or-more shareholder-employees paid by an S corporation."                     | <Tooltip>RARE</Tooltip>      | [Contribution](/how-finch-works/unified-employment-api-glossary#contribution) |
| 6  | "Taxable benefits from a section 125 (cafeteria) plan if the employee chooses cash."                                                    | <Tooltip>RARE</Tooltip>      | [Contribution](/how-finch-works/unified-employment-api-glossary#contribution) |
| 7  | "Employee contributions to an Archer MSA."                                                                                              | <Tooltip>N/A</Tooltip>       | [Deduction](/how-finch-works/unified-employment-api-glossary#deduction)       |
| 8  | "Employer contributions to an Archer MSA if includible in the income of the employee. See Archer MSA."                                  | <Tooltip>N/A</Tooltip>       | [Contribution](/how-finch-works/unified-employment-api-glossary#contribution) |
| 9  | "Employer contributions for qualified long-term care services to the extent (...) <Tooltip>full text</Tooltip>                          | <Tooltip>RARE</Tooltip>      | [Contribution](/how-finch-works/unified-employment-api-glossary#contribution) |
| 10 | "Taxable cost of group-term life insurance in excess of \$50,000. See Group-term life insurance."                                       | <Tooltip>COMMON</Tooltip>    | [Contribution](/how-finch-works/unified-employment-api-glossary#contribution) |
| 11 | "Unless excludable under Educational assistance programs, payments for (...) <Tooltip>full text</Tooltip>                               | <Tooltip>COMMON</Tooltip>    | [Earning](/how-finch-works/unified-employment-api-glossary#earning)           |
| 12 | “The amount includible as wages because you paid your employee’s share of social security and (...) <Tooltip>full text</Tooltip>        | <Tooltip>ALWAYS</Tooltip>    | [Tax](/how-finch-works/unified-employment-api-glossary#tax)                   |
| 13 | "Designated Roth contributions made under a section 401(k) plan, a section 403(b) salary (...) <Tooltip>full text</Tooltip>             | <Tooltip>COMMON</Tooltip>    | [Deduction](/how-finch-works/unified-employment-api-glossary#deduction)       |
| 14 | "Distributions to an employee or former employee from an NQDC plan (including a rabbi trust) or a nongovernmental section 457(b) plan." | <Tooltip>RARE</Tooltip>      | [Earning](/how-finch-works/unified-employment-api-glossary#earning)           |
| 15 | "Amounts includible in income under section 457(f) because the amounts are no longer subject to a substantial risk of forfeiture."      | <Tooltip>RARE</Tooltip>      | [Earning](/how-finch-works/unified-employment-api-glossary#earning)           |
| 16 | "Payments to statutory employees who are subject to social security and Medicare taxes but (...) <Tooltip>full text</Tooltip>           | <Tooltip>RARE</Tooltip>      | [Earning](/how-finch-works/unified-employment-api-glossary#earning)           |
| 17 | "Cost of current insurance protection under a compensatory split-dollar life insurance arrangement."                                    | <Tooltip>RARE</Tooltip>      | [Contribution](/how-finch-works/unified-employment-api-glossary#contribution) |
| 18 | "Employee contributions to a health savings account (HSA)."                                                                             | COMMON                       | [Deduction](/how-finch-works/unified-employment-api-glossary#deduction)       |
| 19 | "Employer contributions to an HSA if includible in the income of the employee. See Health savings account (HSA)."                       | COMMON                       | [Contribution](/how-finch-works/unified-employment-api-glossary#contribution) |
| 20 | "Amounts includible in income under section 409A from an NQDC because the amounts are (...) <Tooltip>full text</Tooltip>                | <Tooltip>RARE</Tooltip>      | [Earning](/how-finch-works/unified-employment-api-glossary#earning)           |
| 21 | "Nonqualified moving expenses and expense reimbursements. See Moving expenses."                                                         | <Tooltip>COMMON</Tooltip>    | [Earning](/how-finch-works/unified-employment-api-glossary#earning)           |
| 22 | "Payments made to former employees while they are on active duty in the U.S. Armed Forces or other uniformed services."                 | <Tooltip>RARE</Tooltip>      | [Earning](/how-finch-works/unified-employment-api-glossary#earning)           |
| 23 | "All other compensation, including certain scholarship and fellowship grants (...) <Tooltip>full text</Tooltip>                         | <Tooltip>COMMON</Tooltip>    | [Earning](/how-finch-works/unified-employment-api-glossary#earning)           |
| 24 | "Salary reduction contributions made to a Roth IRA pursuant to a SEP arrangement or (...) <Tooltip>full text</Tooltip>                  | <Tooltip>RARE</Tooltip>      | [Deduction](/how-finch-works/unified-employment-api-glossary#deduction)       |

### Finch implementation:

**All of the information necessary to run an individual’s W-2 Box 1 calculation can be found in [Finch’s Pay Statement data](/api-reference/payroll/pay-statement).**

The table above highlights where to find criteria within [Pay Statement object groups (Earning, Tax, Deduction, Contribution)](/api-reference/payroll/pay-statement). The majority of these criteria require simple summing of line-item-amounts over a given calendar year - [Finch’s type classification](/developer-resources/Pay-Statement-Type-Classification#pay-statement-type-classification) is invaluable for properly aggregating criteria values.

### Nuanced criteria guidance:

10. Calculate per pay-period OR on 12/31 check - determine the cost of group-term life insurance provided over the \$50,000 income exclusion threshold.

Want to talk through how to do this with a Finch teammate? Reach out to your DSE or AM.

***this general guidance must be used at the discretion of Finch's developers***


# Calculate Year-To-Date (YTD) Wages
Source: https://developer.tryfinch.com/developer-resources/Calculating-YTD-Wages

Learn how to calculate year-to-date (YTD) gross wages for individual employees using data returned from Finch Organization endpoints.

A common use case for Finch APIs is to calculate YTD gross wages for individual employees. This useful and powerful information can be calculated easily by using the right approach.

### Logic Flow

The general flow for calculating individual YTD wages works like this:

1. Call the `/payment` endpoint and pass a `start_date` of the first day of the year (January 01) and an `end_date` of the current date.
2. Loop over the array of returned payment objects and collect all of the payment `id`s.
3. Call the `/pay-statement` endpoint and pass all of the `payment_id`s as a batched request.
4. Loop over the array of returned pay statements and aggregate each individual's gross pay amounts.

### Sequence Diagram

<img alt="ytd-gross-wages.png" />


# Data Access Controls
Source: https://developer.tryfinch.com/developer-resources/Data-Access-Controls

Learn how to disable fields from API responses.

## Overview

Data Access Controls allow developers to selectively disable specific fields from API responses. This ensures that only the necessary data is retrieved, improving transparency and reducing over-permissioning concerns for employers during the Finch Connect flow.

When a field is disabled:

* It will **not** appear in the API response, returning `null` instead.

* It will **not** be displayed on the permissions screen in Finch Connect.

This feature is only available to customers on a Pro or Premier plan, and will not affect data returned by flat file.

## How It Works

Each endpoint's fields are grouped into logical categories. If a developer includes **any** fields within a group, the recommended Finch Connect verbiage for that group will be displayed. If **all** fields in a group are excluded, the verbiage will be omitted from Finch Connect to provide a streamlined experience.

### Company Data

If a developer is requesting **all** fields, the Connect verbiage will display:

> "Read basic company data, company contact info, address details, and bank account data."

| Group               | Fields                                                  | Connect Verbiage          |
| ------------------- | ------------------------------------------------------- | ------------------------- |
| Basic Company Data  | Legal name, Entity type, Subtype, Departments, EIN      | Read basic company data   |
| Contact Info        | Primary Email, Primary Phone Number                     | Read company contact info |
| Address Details     | Location Line 1, Location Line 2, City, State, Zip Code | Read address details      |
| Banking Information | Bank Account Routing, Bank Account Number               | Read bank account data    |

### Directory Data

If a developer is requesting **all** fields, the Connect verbiage will display:

> ""Read company directory and organization structure."

| Group                  | Fields                   | Connect Verbiage            |
| ---------------------- | ------------------------ | --------------------------- |
| Company Directory      | Employee Name, Is Active | Read company directory      |
| Organization Structure | Manager, Department      | Read organization structure |

### Individual Data

If a developer is requesting **all** fields, the Connect verbiage will display:

> "Read individual data, contact info, and address details."

| Group                        | Fields                                                | Connect Verbiage     |
| ---------------------------- | ----------------------------------------------------- | -------------------- |
| Employee Identification      | Employee Name, Preferred Name, DOB, Gender, Ethnicity | Read individual data |
| Employee Contact Information | Email, Phone Number                                   | Read contact info    |
| Employee Address Details     | Address Line 1, Address Line 2, City, State, Zip Code | Read address details |

### Employment Data

If a developer is requesting **all** fields, the Connect verbiage will display:

> "Read individual employment and income data."

| Group                  | Fields                                                                                                                                                                   | Connect Verbiage                                  |
| ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------- |
| Employment Details     | Title, Manager, Department, Employment Type, Subtype, Start Date, End Date, Latest Rehire Date, Is Active, Employment Status, Work Location Line 1, Work Location Line 2 | Read individual employment data, excluding income |
| Compensation           | Income                                                                                                                                                                   | Read income data                                  |
| Additional Information | Class Code, Custom Fields                                                                                                                                                | -                                                 |

## Getting Started

To configure Data Access Controls for your application:

1. Review the available field groupings above and determine which fields you need.

2. Contact

   [developers@tryfinch.com](mailto:developers@tryfinch.com)

   with your selected field restrictions.

3. Once enabled, your API responses will return

   `null`

   for any disabled fields, and Finch Connect will dynamically adjust permission verbiage accordingly.

4. For any questions or additional support, reach out to your Developer Success Engineer.


# Data Syncs
Source: https://developer.tryfinch.com/developer-resources/Data-Syncs

Learn how Finch syncs data after an employer connects and how you can verify the freshness and scope of the data you receive.

## Initial Data Syncs

After an employer connects through Finch Connect, Finch automatically initiates an initial sync to retrieve available data across supported endpoints.

Effective June 11, 2025 Finch will fetch the following for Pay data:

* 2 full years of historical data
* Year-to-date for the current calendar year

**Example:** If an employer connects on June 1, 2025, Finch will sync data starting from January 1, 2023. If an employer connects on January 2, 2026, Finch will sync data starting from January 1, 2024.

Finch defaults to a 2-year plus year-to-date lookback to ensure fast, reliable first-time syncs. Longer lookbacks are available on our Premier plan but may increase the risk of time-outs. To request a custom lookback, contact [developers@tryfinch.com](mailto:developers@tryfinch.com).

Finch will fetch Organization data going as far back as is available in the payroll system.

### Provider limitations

Some providers restrict how much historical data is available.

* Paychex Flex: up to 14 months of pay statement data
* Paycom: up to 2 years of pay statement data

If a request is made before the initial sync is complete, Finch will attempt a live fetch from the provider. These requests may take longer, depending on the size and structure of the data.

## Ongoing data syncs

After the initial sync, Finch keeps data fresh by syncing on the following schedule:

* [Automated](/integrations/integration-types#automated-integrations) providers: every 24 hours
* [Assisted](/integrations/integration-types#assisted-integrations) providers: every 7 days

Finch API responses always return the most recent successful sync. Most requests complete in under 200 milliseconds.

## Verify data freshness

Finch includes response headers that indicate the freshness of the data:

| Response Header                    | Description                                                                 |
| ---------------------------------- | --------------------------------------------------------------------------- |
| `Finch-Data-Retrieved`             | The date/time that the data was retrieved from the employment system.       |
| `Finch-Last-Attempted-Update-Date` | The date/time that Finch last attempted to sync the data for this endpoint. |

**Multi-Entity data freshness**: For connections that include multiple entities, Finch runs a separate data sync for each entity. To confirm that all entities have fresh data, check the same response headers (`Finch-Data-Retrieved` and `Finch-Last-Attempted-Update-Date`) on a per-entity basis.

## Batch sync behavior

For batch endpoints like `/employment`,` /individual`, and `/pay-statement`, Finch syncs all records in a single operation. This ensures that all data returned in the response reflects the same point in time.

## Pay statement sync behavior

Pay statements are larger and may take longer to sync than other data types. If you query a pay statement using a payment\_id from the /payment endpoint before it has been fetched, Finch will return a 202 Accepted status with the following response:

```json theme={null}
{
  "responses": [
    {
      "payment_id": "9c8626e3-6d97-48a0-883c-f4c65e736321",
      "code": 202,
      "body": {
        "code": 202,
        "name": "accepted",
        "finch_code": "data_sync_in_progress",
        "message": "The pay statements for this payment are being fetched. Please check back later."
      }
    },
    ...
  ]
}
```


# Finch Developer FAQs
Source: https://developer.tryfinch.com/developer-resources/Developer-FAQs

Explore Finch developers' most frequently asked questions (FAQ) and answers. Topics include Products & Integrations, API & Data Model, Security, and more.

## Can you describe Automated vs Assisted connections?

Finch is a unified API for employment systems, meaning that the developer is only ever interacting with our single API to GET or POST data to any provider. Depending on which provider is set up, Finch will do one of two things:

1. If the provider supplies an *automated* API, Finch will instantaneously access the data and return it.
2. If the provider has not built an API to access their data easily, a real Finch employee will *assist* in getting this data manually by contacting and retrieving the requested data on a scheduled basis (usually one week) and uploading it so it can be returned instantaneously on every subsequent call. The process of getting this set up for the first time is a few weeks. After the initial setup, new employee data will be refreshed every week without the need to be involved. Our Assisted Connections are particularly powerful since they allow the developer to only interact with Finch APIs without having to deal with SFTP servers, report uploads, or other synchronous data updates for each provider supported. Therefore, your team does not need to build a product operations team that has to filter, map, or ingest data in system-specific formats; Finch does this for you. No other platform offers this level of service and allows for a high level of coverage that would take years to build in-house.

***

## Why are some Finch API endpoints GET requests while others are POST requests?

In the Finch API, some endpoints are GET requests (/company and /directory endpoints) while some are POST requests (/individual and /employment endpoints). The latter are POSTs because a request body containing ids needs to be sent.

Additionally, the `/individual`, `/employment`, and `/pay-statement` endpoints are special because they are “batch” endpoints, meaning you can send as many ids as you want in the body, and get a single response back containing the information for as many individuals/pay-statements as you sent. Query parameters can’t handle 1000 ids in the URL, hence the need for POSTs using request bodies.

***

## Does Finch display payments to business/vendor subcontractors?

No, Finch only includes payments to persons who show up in the employee directory with an associated individual\_id. This applies across all providers.

***

## How can I determine the “Payroll Close Date”?

It is usually 1-2 days after payroll end date between `end_date` and `debit_date`.

***

## How is the data returned by Finch validated for accuracy?

Finch looks at two broad categories when defining data quality:

1. rate of `NULL` fields when values exist in the system and
2. rate of incorrect fields. Measuring the rate at which we return value = `NULL` can be potentially indicative of 4 things:

* The data is unavailable in the system — not a Finch error
* The data is available in the system, but the format does not cleanly fit our endpoint — error
* We parsed the wrong field and the data we parsed does not fit the expected format — error
* We parsed information, but we did not know how to classify it — error

The goal is to decrease the rate of `NULL` over time; if the data is available in the provider's system, Finch should be returning that data. Keep in mind that the status of an employee (full-time vs contractor) can also affect which fields return NULL.

Finch defines the “rate of incorrect data” as data that does not match what is reported in the provider's system. This could either mean the field returns blank indicating a potential bug in our code (e.g.: a pay statement array returns empty), or the field returns a value that does not reflect what is reported in the system. We have an internal dashboard where we track data field coverage and correctness in real-time. We have alerts defined to notify us of any anomalies detected which we proactively investigate and fix.

There are several ways developers can validate data coming from Finch:

1. Implementing “quality checks” on all pay statements to make sure financial data is not missing, duplicated, or inaccurate.
2. Running a series of “blind” audits on a semi-regular schedule. The audits should focus on the two categories mentioned above: rate of nulls and the rate of incorrect data. Employee employment status, currency amounts, and field type categorizations are important data points to watch.

There are two ways to conduct an audit of Finch data:

1. The data returned from Finch is compared with previous Finch-connected employer data that have similar providers, use cases, and sizes. Any discrepancies are alerted to Finch. This method is beneficial if you have thorough historical data to pull from.
2. If you do not have enough historical data to use, the data returned from Finch can be compared directly with the data in the provider's system. This method requires contacting the employer and asking either pointed questions about possible data discrepancies or exchanging data extensively.

Similarly, if a customer notices a potential data discrepancy, building and including a way for customers to report errors to you is also beneficial. Any errors reported to you can be directly forwarded to Finch for internal investigation. While we don’t ever want inaccurate data returned by our API, we are committed to fixing any errors rapidly and continue to proactively invest in automated tests, checks, and audits internally to catch any data quality errors proactively.

If there are any audits or data fields that are important to your business, we want to hear from you so that we can better support you.

***

## Can I bypass the provider selection screen in Finch Connect?

You can [bypass the provider screen](/implementation-guide/Deploy-and-Manage/Increase-Employer-Adoption) if you already know the provider name by passing `payroll_provider=<your_provider_name>` into the `/authorize` url when opening Finch Connect.

***

## How long is the access token lifetime?

A Finch `access_token` lifetime is infinite; it does not expire⁠, unless you [disconnect](/implementation-guide/Backend-Application/Disconnect-Connections) it. If a `401 Re-authentication` error is received (either by a user changing their security setting or an employment system makes an infrastructure change), Finch's connection can get disconnected, which requires a user to [reauthenticate](/implementation-guide/Backend-Application/Mitigate-Errors) and a new Finch access\_token will be created and sent back to your app.

***

## How does Finch encrypt data? What type of encryption is used?

Finch utilizes various encryption protocols to protect data at rest and in transit.

* **Encryption at rest** — All data in our datastores are encrypted using AES-256 with keys managed via AWS KMS.
* **Encryption in transit** — All data to or from the Finch infrastructure is encrypted in transit using TLS 1.2.
* **Application-level encryption** — Other Highly Restricted fields are additionally encrypted at the application level using AES-256.


# Enable Social Security Number (SSN) Field
Source: https://developer.tryfinch.com/developer-resources/Enable-SSN-Field

In this guide, you'll learn how to enable the social security number (SSN) field in Finch. The SSN field must be explicitly authorized by the employer.

<Warning>
  SSN is a secure field in the Finch API. Your use case needs to be approved by your Developer Success Representative before enabling. However, you can test SSN via the [Finch Sandbox](/implementation-guide/Test/Finch-Sandbox) without any approval.
</Warning>

Finch returns Social Security Number (SSN) as a field in the [/individual](/api-reference/organization/individual) endpoint. However, the SSN field is not returned by default; you must enable it first.

To enable SSN, the `ssn` product scope (along with `individual`) must be included in the `/authorize` URL when launching Finch Connect. This ensures that the connection's access tokens that are generated are capable of accessing this field.

## Authorization

Make sure to include the `ssn` scope in your authorization URL.

```bash theme={null}
https://connect.tryfinch.com/authorize?
&client_id=<your_client_id>
&products=company%20directory%20individual%20employment%20payment%20pay_statement%20ssn
&redirect_uri=https://example.com
&sandbox=true
```

## Request

```bash theme={null}
curl https://api.tryfinch.com/employer/individual \
-H "Authorization: Bearer {token}" \
-H "Finch-API-Version: 2020-09-17" \
-X "POST" \
-H "Content-Type: application/json" \
-d '{
  "options": {
    "include": ["ssn"]
  },
  "requests": [{ "individual_id": "f3ddb1f4-dfa4-4e1d-bfed-bdfd0645b613"}]
}'
```

## Response

SSN values returned from the Finch API can either be in raw or encrypted format, depending on the provider. Please refer to each provider's field support documentation for details on whether SSN is supported in raw or encrypted format, including how to decrypt encrypted values. If you require further assistance, reach out to your Finch Developer Success representative.

### Response with Raw SSN

```json theme={null}
{
  "responses": [
    {
      "individual_id": "f3ddb1f4-dfa4-4e1d-bfed-bdfd0645b613",
      "code": 200,
      "body": {
        "id": "f3ddb1f4-dfa4-4e1d-bfed-bdfd0645b613",
        "ssn": "143782004", // Don't worry, this value is not a real SSN
        "encrypted_ssn": null,
        "first_name": "Angelica",
        "middle_name": "Aretha",
        "last_name": "Flatley",
        "preferred_name": null,
        "dob": "1968-05-15",
        "emails": [
          {
            "data": "Angelica.Flatley18@impressive-coinsurance-inc.com",
            "type": "work"
          }
        ],
        "phone_numbers": [
          {
            "data": "098-478-0472",
            "type": "work"
          }
        ],
        "gender": "female",
        "ethnicity": "hispanic_or_latino",
        "residence": {
          "line1": "341 Kuphal Lodge",
          "line2": "Suite 896",
          "city": "Swiftshire",
          "state": "AL",
          "postal_code": "83712-2670",
          "country": "US"
        }
      }
    }
  ]
}
```

### Response with Encrypted SSN

```bash theme={null}
{
  "responses": [
    {
      "individual_id": "f3ddb1f4-dfa4-4e1d-bfed-bdfd0645b613",
      "code": 200,
      "body": {
        "id": "f3ddb1f4-dfa4-4e1d-bfed-bdfd0645b613",
        "ssn": null,
        "encrypted_ssn": "vlIRzYJ5jk3TDanW3T0Fg2cVyHXPvBbtm.zymmLpbVlrnDUsaW0kbmNnkneTyYJRsJKozu", // This value will need to be decrypted to attain the raw SSN value
        "first_name": "Angelica",
        "middle_name": "Aretha",
        "last_name": "Flatley",
        "preferred_name": null,
        "dob": "1968-05-15",
        "emails": [
          {
            "data": "Angelica.Flatley18@impressive-coinsurance-inc.com",
            "type": "work"
          }
        ],
        "phone_numbers": [
          {
            "data": "098-478-0472",
            "type": "work"
          }
        ],
        "gender": "female",
        "ethnicity": "hispanic_or_latino",
        "residence": {
          "line1": "341 Kuphal Lodge",
          "line2": "Suite 896",
          "city": "Swiftshire",
          "state": "AL",
          "postal_code": "83712-2670",
          "country": "US"
        }
      }
    }
  ]
}
```


# MCP
Source: https://developer.tryfinch.com/developer-resources/Finch-MCP-Server

Use the Finch MCP Server to enable natural language access to the Finch API via large language models (LLMs).

<Info>The Finch MCP Server is currently in **beta**. Features and behavior may change.</Info>

## Overview

The Finch MCP Server makes it simple to integrate Large Language Models (LLMs) with the Finch API using natural language. Rather than writing custom API calls, you can describe your intent, and the LLM will handle the rest by issuing calls to the Finch API to get the information you need or take action on your behalf.

The Finch MCP Server exposes structured tools to LLMs, making it possible to use Finch's API without understanding its full surface area. This unlocks powerful, intuitive workflows for developers, finance teams, support agents, and more.

> **MCP** stands for **Model Context Protocol**, a mechanism that defines how LLMs can safely interact with external APIs and tools.

### 💾 Installation

Install the MCP Server via npm:

```bash theme={null}
npm install @tryfinch/finch-api-mcp
```

### ⚙️ LLM Configuration

To connect the Finch MCP Server to an MCP Client, you will need to add the appropriate configuration to your client. Below is an example of what that may look like.

```json theme={null}
{
  "mcpServers": {
    "finch_api": {
      "command": "npx",
      "args": ["-y", "@tryfinch/finch-api-mcp"],
      "env": {
        "FINCH_ACCESS_TOKEN": "<a specific connection's access token>"
      }
    }
  }
}
```

> 💡 Replace `<a specific connection's access token>` with a valid Finch API access token for the connection you want the LLM to access.

> 🔐 **Security Note**: Use a token scoped to only the data required for your use case. Read-only tokens are recommended for most applications. Depending on your use case, and due to the sensitive nature of employment data, take extra caution when deciding what LLMs you choose to share your data with and the usage policies of the LLM provider. Finch's general recommendation is to use a self-hosted LLM for usage with the Finch MCP Server.

## Example Use Cases

### 🧑‍💼 Employee Directory Lookup

**Sample Prompt:**

> Find all employees in the engineering department who started after January 1st, 2023.

### 💼 Job Titles & Compensation

**Sample Prompt:**

> What are the current titles and base salaries of everyone on the sales team?

### 📊 Workforce Demographics

**Sample Prompt:**

> How many employees are full-time vs part-time across all locations?

## Need Help?

If you run into issues or have questions, reach out to us at **[support@tryfinch.com](mailto:support@tryfinch.com)**.


# Pay Statement Items & Rules
Source: https://developer.tryfinch.com/developer-resources/Pay-Statement-Items-Rules

Assign labels, categories, and metadata to pay statement items based on custom rules. 

## Overview

Finch allows you to define how pay statement items are processed, categorized, or modified based on custom rules. This enables more customized payroll data management and streamlined operations. You can associate specific labels, track eligibilities, or perform reconciliation depending on your needs.

## How It Works

To create a rule:

1. Identify the metadata attributes that you would like to track for pay statement items (eg. item eligibility or source code).
2. Fetch all the unique pay statement items for a given connection from the /pay-statement-item endpoint to identify what the rules can be applied on for the connection.
3. Identify what the rule should be (eg. for pay statement deduction items that are called "401k", assign a label called "Pre-Tax EE Deferral").
4. Call the Finch [POST /pay-statement-item/rules](/api-reference/payroll/create-rule) endpoint to create a rule.
5. Use the other management endpoints (GET, PUT, DEL) to maintain those rules.

Once a rule has been created, Finch applies that rule for all pay statement items for that connection. When the rule conditions are met, metadata attributes will be appended to that pay statement item, which can be retrieved as part of [/pay-statement](/api-reference/payroll/pay-statement) or [/pay-statement-item](/api-reference/payroll/get-pay-statement-items) endpoints.

Note that pay statement item rules can only be applied to a specific connection. Universal rules are not supported currently.

## Use Cases

1. Categorizing Pay Statement Items Automatically: You can use rules to assign labels or categories to payroll items
   * If the name field is "Salary", label it as "Base Compensation".
   * If the name field is "Bonus", label it as "Variable Pay".

2. Enforcing Deduction Policies: Automatically flag or process specific deductions
   * If the name field is "401k", ensure it is categorized as a pre-tax deduction.
   * If the name field is "HSA", add a metadata tag for tax-exempt handling.

3. Managing Employer Contributions: You can use rules to track employer contributions separately
   * If the name field is "Health Insurance", classify it as an employer contribution.
   * If the name field is "Retirement Match", ensure proper tax treatment.

4. Custom Payroll Data Processing
   * Apply a custom label to specific pay statement items to align with internal reporting.
   * Automatically reformat certain pay statement items for easier integration with reconciliation software.

## Best Practices

* Use clear and specific conditions: Avoid broad conditions that may unintentionally apply to multiple pay statement items.
* Test rules before production use: Validate sample pay statements to ensure rules behave as expected.
* Monitor rule execution: Regularly audit payroll processing results to identify any unexpected behaviors.


# Pay Statement Type Classification
Source: https://developer.tryfinch.com/developer-resources/Pay-Statement-Type-Classification

Learn how to classify Contributions and Deductions retrieved from the Finch Payroll endpoints.

Pay statement items may need to be classified with specific types, such as 401(k), safe-harbor, HSA, etc. Finch attempts to classify individual pay statement items into four categories (Earnings, Taxes, Employer Contributions, Employee Deductions) with a specific type based on the description of the item. However, Finch may not be able to appropriately classify a contribution or deduction if there are not enough details available in the description. For example, instead of naming an item '401k plan', an employer may use an internal code '1j7dfp'. Finch is unable to classify items in this scenario.

In instances when Finch is unable to classify a Contribution or Deduction, the best practice is:

1. Identify the names/descriptions that the employer has set up the Contributions or Deductions as in their payroll system
2. Have the employer go through Finch Connect, authorizing Finch to retrieve data from the payroll system
3. Retrieve pay statements for the past 2-3 months via the `/pay-statement` endpoint
4. Parse through the results to get the `employee_deductions.name` and `employer_contributions.name`
5. Create an internal mapping to associate the `name` with the appropriate Deduction or Contribution


# Reauthentication
Source: https://developer.tryfinch.com/developer-resources/Reauthentication

Reauthenticate a connection after Finch returns a 401 reauthenticate_user error. Covers multi-entity connections, employee permissions, and scope updates.

A Finch connection breaks when the authentication credentials Finch uses to access the employer's provider system no longer work. When this happens, the connection's status changes to `reauth`, and Finch returns a `401 Unauthorized` HTTP status code with a `finch_code` of `reauthenticate_user` (see [Finch API errors](/api-reference/development-guides/errors/Error-Types)).

```js theme={null}
{
  "code": 401,
  "name": "authentication_error",
  "finch_code": "reauthenticate_user",
  "message": "Please reauthenticate user"
}
```

If an access token returns this error, the employer must reauthenticate by completing a Finch Connect Reauthentication session. Make sure your application uses the [reauthentication session](/api-reference/connect/reauthenticate-session) endpoint with the `connection_id` instead of creating a new connection session. See [Reauthentication errors](/implementation-guide/Backend-Application/Mitigate-Errors#reauthentication-errors) for more details about this error.

## Notify the employer to reauthenticate

Notify the employer as soon as a connection needs reauthentication — for example with an in-app banner or email — so they can reauthenticate before missing a data sync. Prompt them to reauthenticate through your existing Finch Connect flow, whether that's directly in your app or by sending them a link.

<Note>
  Reauthenticating only replaces the `access_token`. Other Finch identifiers, like `individual_id` or `payment_id`, stay the same across tokens.
</Note>

## Reauthenticate multi-entity connections

If some entities in a multi-entity connection require reauthentication while others remain connected, developers can continue retrieving data for the entities that are still connected. Employers using a multi-entity payroll system can add additional entities during reauthentication.

Finch also verifies that the reauthenticating employee has access to all entities originally connected. If the employee does not have access to one or more of those entities, the reauthentication attempt fails and Finch returns an error. To resolve this:

* The employee must gain access to the missing entities in the payroll system, or
* The developer uses `/disconnect-entity` to remove the entities the employee cannot access, then reauthenticates the connection for the remaining entities

If an entity is in `reauth` status and the employer wants to remove it instead of reauthenticating it, use [`/disconnect-entity`](/api-reference/management/disconnect-entity) to remove that entity from the connection. The other entities and the access token are not affected.

## Reauthenticate with a different employee

The employee who reauthenticates a connection does not have to be the employee who originally connected it — any employee can reauthenticate, as long as they have sufficient permissions in the payroll system to access the data the connection is authorized for. This commonly comes up when the original employee leaves the company or when their role or permissions change.

If the reauthenticating employee does not have sufficient permissions, the reauthentication attempt fails and Finch returns an error. To resolve this:

* The employee gains the required permissions in the payroll system, or
* A different employee with sufficient permissions reauthenticates the connection instead

## Update product scopes using a reauthentication session

A reauthentication session can be initiated specifically to update product scopes — the connection does not need to be in `reauth` status to do this. Pass the desired `products` array to [reauthenticate a session](/api-reference/connect/reauthenticate-session) to add or remove scopes on an existing connection without creating a new one.

## Add entities using a reauthentication session

A reauthentication session can also be initiated to let an employer add entities to an existing connection — the connection does not need to be in `reauth` status to do this. Create a [reauthentication session](/api-reference/connect/reauthenticate-session) and prompt the employer to complete it in Finch Connect. If entities exist that aren't yet connected, the employer can select them there.

After the employer completes Finch Connect, exchange the resulting authorization code through [`/auth/token`](/api-reference/management/create-access-token) as usual. The response's `entity_ids` array includes the newly added entities. Call [`/introspect`](/api-reference/management/introspect) at any time to see the full list of connected entities, including each one's `status`.


# Reconcile Employees
Source: https://developer.tryfinch.com/developer-resources/Reconcile-Employees

Learn how to reconcile employee profiles in Finch using PII such as full name and date of birth (DOB), email, or SSN.

If you have employees or contractors in your database that you need to match with Finch's `individual_id`s, you will need a reliable method to reconcile the two. The following are two best practices for developers building with Finch.

### Recommended: full name + date of birth

All payroll systems require at least a first and last name, therefore, finding a match by full name is a good way of reconciling individuals. However, on rare occasions, naming collisions do happen even within the same company. Therefore, we recommend using a concatenation of `first_name`, `last_name`, and `dob`, all data points available from the `/individual` endpoint.

<Warning>
  Finch returns `first_name`, `last_name`, and `dob` for all systems we support. However, sometimes all the data points not inputted into the system by the payroll administrator of a company. We recommend confirming with your customer that the data points are inputted into the system for all employees before reconciliation.
</Warning>

### Alternative: email address

Finch returns email addresses from the `/individual` endpoint. The uniqueness of emails, *if they are returned by the underlying employment system*, makes it a good data point to reconcile employees against.

<Warning>
  Finch's API does not always return emails. We find `first_name`, `last_name`, and `dob` are more consistent than `email`s.
</Warning>

### Alternative: Social Security Number

Finch returns Social Security Number (SSN) of an individual, which can be helpful in identifying unique individuals. However, SSN is not returned by default since it is a sensitive field; you must [enable SSN](/developer-resources/Enable-SSN-Field) for your application first.


# Request Forwarding
Source: https://developer.tryfinch.com/developer-resources/Request-Forwarding

Finch Request Forwarding is a passthrough API feature that enables you to issue raw requests directly against an employment system’s API.

## Enabling Custom Data Requests

With Request Forwarding, you have the ability to access any functionality that is natively supported by an integration, including data elements that are outside of Finch's existing API structure and standard data model. You’ll also be able to write data elements that are outside the scope of what is supported through one of Finch's standardized APIs.

<Info>
  Request Forwarding is only available to customers on a Pro or Premier plan. To enable Request Forwarding for your account, reach out to your Developer Success Representative or email [developers@tryfinch.com](mailto:developers@tryfinch.com).
</Info>

### Using Request Forwarding

You can [watch a video demonstration](https://www.loom.com/share/15ca7fb93c2d43b9a052362fd3368e37) that exhibits how to use the [/forward](/developer-resources/Request-Forwarding) API for accessing deeper data sets within an employment system.

### How it Works

**Standard Finch API Request** - Requests to one of Finch's standard API endpoints go through a data transformation layer to ensure that you have a consistent request and response structure to work with, regardless of the system you’re extracting data from.

<img alt="finch_standard_api.png" />

**Finch Request Forwarding** - Request Forwarding bypasses the data transformation layer, giving you access to the raw data exposed by an integration and leaving the data mapping fully in your control.

<img alt="finch_request_forwarding.png" />

### Why Request Forwarding?

For each supported integration, Finch provides a standardized set of API endpoints and data models. However, if you require additional information outside these standard models, Request Forwarding enables your application to read or write specific fields from provider-supported API endpoints. This supplements Finch's standardized endpoints and fields without you needing to handle the complexities of building and managing a separate integration yourself for accessing non-standardized fields.

For example, consider a situation where Finch's data model supports 95% of the fields your application needs. Instead of having to build a direct integration with the provider to get the other 5% of fields you need, you can look to Request Forwarding. After all, building and maintaining a single integration is the reason you chose Finch in the first place! With Request Forwarding, you can gain access to the other 5% of the data you need.

When using Request Forwarding, Finch leverages the existing connection that was established via Finch Connect, forwards the request to the provider, and then forwards the provider's response back to your application. It is important to note that Request Forwarding does not alter requests or responses, it simply forwards them between you and the provider while Finch manages credentials and authentication for you.

### Supported Integrations

The integrations and associated API documentation for the systems that are currently supported by Request Forwarding are referenced below.

In order to use Request Forwarding for a particular provider you must ensure that connections are established using the appropriate [authentication method](/how-finch-works/unified-employment-api-glossary#authentication-method).

| **Integration**     | **Authentication Method** | **API Documentation**                                                                                                                                                              |
| ------------------- | ------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| BambooHR            | `oauth`                   | [https://documentation.bamboohr.com/reference](https://documentation.bamboohr.com/reference)                                                                                       |
| Factorial HR        | `oauth`                   | [https://apidoc.factorialhr.com/reference](https://apidoc.factorialhr.com/reference)                                                                                               |
| Gusto               | `oauth`                   | [https://docs.gusto.com/app-integrations/reference](https://docs.gusto.com/app-integrations/reference)                                                                             |
| HiBob               | `credential` `api_token`  | [https://apidocs.hibob.com/reference](https://apidocs.hibob.com/reference)                                                                                                         |
| Justworks           | `oauth`                   | [https://public-api.justworks.com/v1/docs](https://public-api.justworks.com/v1/docs)                                                                                               |
| Paycom              | `api_token`               | [https://drive.google.com/file/d/1aC9C4W1mZo4oFxNIZUtS1zkfJ4tH6WjD/view?usp=sharing](https://drive.google.com/file/d/1aC9C4W1mZo4oFxNIZUtS1zkfJ4tH6WjD/view?usp=sharing)           |
| Personio            | `api_token`               | [https://developer.personio.de/reference](https://developer.personio.de/reference)                                                                                                 |
| Rippling            | `oauth`                   | [https://developer.rippling.com/documentation/base-api](https://developer.rippling.com/documentation/base-api)                                                                     |
| TriNet              | `api_token`               | [https://developers.trinet.com/explore-trinet-apis](https://developers.trinet.com/explore-trinet-apis)                                                                             |
| UKG Pro             | `api_token`               | [https://developer.ukg.com/hcm/reference/welcome-to-the-ukg-pro-api](https://developer.ukg.com/hcm/reference/welcome-to-the-ukg-pro-api)                                           |
| Workday<sup>1</sup> | `api_token`               | [https://community.workday.com/sites/default/files/file-hosting/productionapi/index.html](https://community.workday.com/sites/default/files/file-hosting/productionapi/index.html) |
| UKG Ready           | `api_token`               | [https://secure7.saashr.com/ta/docs/rest/public/](https://secure7.saashr.com/ta/docs/rest/public/)                                                                                 |

<sub><sup>1</sup> See details on making Workday requests using Request Forwarding [here](/integrations/guides/workday-request-forwarding).</sub>

### Example Usage

Let's walk through a simple example use case for Request Forwarding.

Let's say you want to access the termination details for an inactive individual in an HRIS system. Finch's [/employment](/api-reference/organization/employment) data model includes information related to an individual's employment, such as their name, title, department, start and end date, and employment status, but does not include information specific to their termination, such as the reason for their termination.

In this example, we illustrate how to use Request Forwarding with an active **Personio** connection to access the **termination reason** for an inactive individual by the name of **Myriam Smith**.

**Step 1:** Make a request to Finch's **/directory** endpoint to gather details of this company's employee directory.

Request:

```bash theme={null}
curl --location 'https://api.tryfinch.com/employer/directory' \
--header 'Authorization: Bearer {{FINCH_ACCESS_TOKEN}}' \
--header 'Content-Type: application/json' \
--header 'Finch-API-Version: 2020-09-17'
```

Response:

```bash theme={null}
{
    "paging": {
        "count": 148,
        "offset": 0
    },
    "individuals": [
        {
            "id": "51834db6-94e4-4e34-bc5d-76bc8456fb55",
            "first_name": "Myriam",
            "last_name": "Smith",
            "middle_name": null,
            "department": {
                "name": "Customer Service"
            },
            "manager": {
                "id": "8b59db87-1b44-4a84-82f4-763885e2b99b"
            },
            "is_active": false
        },
        [...],
        {
            "id": "ed535ff8-6f61-4756-8cb9-edba67c87766",
            "first_name": "Yajaira",
            "last_name": "Borton",
            "middle_name": null,
            "department": {
                "name": "HR"
            },
            "manager": {
                "id": "03ab76b5-d158-4c7f-aaf6-a82894e66790"
            },
            "is_active": true
        }
    ]
}
```

**Step 2:** Given the individual's unique ID, make a request to Finch's **/employment** endpoint to gather holistic details of their employment.

Request:

```bash theme={null}
curl --location 'https://api.tryfinch.com/employer/employment' \
--header 'Authorization: Bearer {{FINCH_ACCESS_TOKEN}}' \
--header 'Content-Type: application/json' \
--header 'Finch-API-Version: 2020-09-17' \
--data '{
  "requests": [
    { "individual_id": "51834db6-94e4-4e34-bc5d-76bc8456fb55" }
  ]
}
'
```

Response:

```bash theme={null}
{
    "responses": [
        {
            "individual_id": "51834db6-94e4-4e34-bc5d-76bc8456fb55",
            "code": 200,
            "body": {
                "id": "51834db6-94e4-4e34-bc5d-76bc8456fb55",
                "first_name": "Myriam",
                "last_name": "Smith",
                "middle_name": null,
                "title": "IT-Customer Service Manager",
                "employment": {
                    "type": "employee",
                    "subtype": null
                },
                "manager": {
                    "id": "8b59db87-1b44-4a84-82f4-763885e2b99b"
                },
                "department": {
                    "name": "Customer Service"
                },
                "start_date": "2014-11-01",
                "end_date": "2020-11-30",
                "is_active": false,
                "class_code": null,
                "location": null,
                "income": {
                    "unit": "monthly",
                    "amount": 412500,
                    "currency": "SEK",
                    "effective_date": null
                },
                "income_history": null,
                "custom_fields": [
                    {
                        "name": "Trainings",
                        "value": "Data security training,Product training"
                    },
                    {
                        "name": "Marital status",
                        "value": "single"
                    },
                    {
                        "name": "Language Skills",
                        "value": "English,German"
                    }
                ],
                "source_id": "12907776"
            }
        }
    ]
}
```

**Step 3:** Given the `source_id` field in Finch's /employment response, use the **/forward** endpoint to access additional details directly from Personio's API, including this individual's `termination_reason`.

Request:

```bash theme={null}
curl --location 'https://api.tryfinch.com/forward' \
--header 'Authorization: Bearer {{FINCH_ACCESS_TOKEN}}' \
--header 'Content-Type: application/json' \
--header 'Finch-API-Version: 2020-09-17' \
--data '{
  "method": "GET",
  "route": "/company/employees/12907776",
  "headers": null,
  "params": null,
  "data": null
}
'
```

Response:

```bash theme={null}
{
    "request": {
        "headers": null,
        "method": "GET",
        "route": "/company/employees/12907776",
        "data": null,
        "params": null
    },
    "headers": {
        "date": "Wed, 04 Oct 2023 20:21:27 GMT",
        "content-type": "application/json",
        "transfer-encoding": "chunked",
        "connection": "close",
        "x-is-preview": "false",
        "x-is-shadow": "false",
        "vary": "Accept-Encoding, Origin",
        "cache-control": "no-cache, private",
        "content-security-policy": "frame-ancestors 'none'",
        "strict-transport-security": "max-age=31536000",
        "x-xss-protection": "1; mode=block",
        "x-content-type-options": "nosniff"
    },
    "statusCode": 200,
    "data": "{\"success\":true,\"data\":{\"type\":\"Employee\",\"attributes\":{\"id\":{\"label\":\"ID\",\"value\":12907776,\"type\":\"integer\",\"universal_id\":\"id\"},\"first_name\":{\"label\":\"First name\",\"value\":\"Myriam\",\"type\":\"standard\",\"universal_id\":\"first_name\"},\"last_name\":{\"label\":\"Last name\",\"value\":\"Smith\",\"type\":\"standard\",\"universal_id\":\"last_name\"},\"email\":{\"label\":\"Email\",\"value\":\"myriam.smith@demo-sample.com\",\"type\":\"standard\",\"universal_id\":\"email\"},\"gender\":{\"label\":\"Gender\",\"value\":\"female\",\"type\":\"standard\",\"universal_id\":\"gender\"},\"status\":{\"label\":\"Status\",\"value\":\"inactive\",\"type\":\"standard\",\"universal_id\":\"status\"},\"position\":{\"label\":\"Position\",\"value\":\"IT-Customer Service Manager\",\"type\":\"standard\",\"universal_id\":\"position\"},\"supervisor\":{\"label\":\"Supervisor\",\"value\":{\"type\":\"Employee\",\"attributes\":{\"id\":{\"label\":\"ID\",\"value\":12907741,\"type\":\"integer\",\"universal_id\":\"id\"},\"first_name\":{\"label\":\"First name\",\"value\":\"Max\",\"type\":\"standard\",\"universal_id\":\"first_name\"},\"last_name\":{\"label\":\"Last name\",\"value\":\"Schmiedel\",\"type\":\"standard\",\"universal_id\":\"last_name\"},\"email\":{\"label\":\"Email\",\"value\":\"max.schmiedel@demo-sample.com\",\"type\":\"standard\",\"universal_id\":\"email\"}}},\"type\":\"standard\",\"universal_id\":\"supervisor\"},\"employment_type\":{\"label\":\"Employment type\",\"value\":\"internal\",\"type\":\"standard\",\"universal_id\":\"employment_type\"},\"weekly_working_hours\":{\"label\":\"Weekly hours\",\"value\":\"40\",\"type\":\"standard\",\"universal_id\":\"weekly_working_hours\"},\"hire_date\":{\"label\":\"Hire date\",\"value\":\"2014-11-01T00:00:00+01:00\",\"type\":\"date\",\"universal_id\":\"hire_date\"},\"contract_end_date\":{\"label\":\"Contract ends\",\"value\":null,\"type\":\"date\",\"universal_id\":\"contract_end_date\"},\"termination_date\":{\"label\":\"Termination date\",\"value\":\"2020-11-30T00:00:00+01:00\",\"type\":\"date\",\"universal_id\":\"termination_date\"},\"termination_type\":{\"label\":\"Termination type\",\"value\":\"employee-quit\",\"type\":\"standard\",\"universal_id\":\"termination_type\"},\"termination_reason\":{\"label\":\"Termination reason\",\"value\":\"employee-quit\",\"type\":\"standard\",\"universal_id\":\"termination_reason\"},\"probation_period_end\":{\"label\":\"Probation period end\",\"value\":\"2015-04-30T00:00:00+02:00\",\"type\":\"date\",\"universal_id\":\"probation_period_end\"},\"created_at\":{\"label\":\"Created at\",\"value\":\"2020-09-21T10:48:14+02:00\",\"type\":\"date\",\"universal_id\":\"created_at\"},\"last_modified_at\":{\"label\":\"Last modified\",\"value\":\"2022-12-09T17:34:50+01:00\",\"type\":\"date\",\"universal_id\":\"last_modified_at\"},\"subcompany\":{\"label\":\"Subcompany\",\"value\":{\"type\":\"Subcompany\",\"attributes\":{\"id\":127825,\"name\":\"Subsidiary SE\"}},\"type\":\"standard\",\"universal_id\":\"subcompany\"},\"office\":{\"label\":\"Office\",\"value\":{\"type\":\"Office\",\"attributes\":{\"id\":1466964,\"name\":\"Gothenburg\"}},\"type\":\"standard\",\"universal_id\":\"office\"},\"department\":{\"label\":\"Department\",\"value\":{\"type\":\"Department\",\"attributes\":{\"id\":3853110,\"name\":\"Customer Service\"}},\"type\":\"standard\",\"universal_id\":\"department\"},\"cost_centers\":{\"label\":\"Cost center\",\"value\":[{\"type\":\"CostCenter\",\"attributes\":{\"id\":730214,\"name\":\"Cost center 2\",\"percentage\":100}}],\"type\":\"standard\",\"universal_id\":\"cost_centers\"},\"holiday_calendar\":{\"label\":\"Public holidays\",\"value\":{\"type\":\"HolidayCalendar\",\"attributes\":{\"id\":2015,\"name\":\"Sweden public holidays\",\"country\":null,\"state\":null}},\"type\":\"standard\",\"universal_id\":\"holiday_calendar\"},\"absence_entitlement\":{\"label\":\"Absence entitlement\",\"value\":[{\"type\":\"TimeOffType\",\"attributes\":{\"id\":2135006,\"name\":\"Paid Vacation UK\",\"category\":\"paid_vacation\",\"entitlement\":0}},{\"type\":\"TimeOffType\",\"attributes\":{\"id\":2135005,\"name\":\"Paid Vacation SE\",\"category\":\"paid_vacation\",\"entitlement\":0}},{\"type\":\"TimeOffType\",\"attributes\":{\"id\":2135004,\"name\":\"Paid Vacation NL\",\"category\":\"paid_vacation\",\"entitlement\":0}}],\"type\":\"standard\",\"universal_id\":\"absence_entitlement\"},\"work_schedule\":{\"label\":\"Work schedule\",\"value\":{\"type\":\"WorkSchedule\",\"attributes\":{\"id\":1248089,\"name\":\"Full-time, 40 hours without time tracking, (mon,tue,wed,thu,fri)\",\"valid_from\":null,\"monday\":\"08:00\",\"tuesday\":\"08:00\",\"wednesday\":\"08:00\",\"thursday\":\"08:00\",\"friday\":\"08:00\",\"saturday\":\"00:00\",\"sunday\":\"00:00\"}},\"type\":\"standard\",\"universal_id\":\"work_schedule\"},\"fix_salary\":{\"label\":\"Fixed salary\",\"value\":4125,\"type\":\"decimal\",\"universal_id\":\"fix_salary\",\"currency\":\"SEK\"},\"fix_salary_interval\":{\"label\":\"Salary interval\",\"value\":\"monthly\",\"type\":\"standard\",\"universal_id\":\"fix_salary_interval\"},\"hourly_salary\":{\"label\":\"Hourly salary\",\"value\":0,\"type\":\"decimal\",\"universal_id\":\"hourly_salary\",\"currency\":\"SEK\"},\"vacation_day_balance\":{\"label\":\"Vacation day balance\",\"value\":0,\"type\":\"decimal\",\"universal_id\":\"vacation_day_balance\"},\"last_working_day\":{\"label\":\"Last day of work\",\"value\":null,\"type\":\"date\",\"universal_id\":\"last_working_day\"},\"profile_picture\":{\"label\":\"Profile Picture\",\"value\":\"https://api.personio.de/v1/company/employees/12907776/profile-picture\",\"type\":\"standard\",\"universal_id\":\"profile_picture\"},\"team\":{\"label\":\"Team\",\"value\":{\"type\":\"Team\",\"attributes\":{\"id\":1674017,\"name\":\"Customer Service\"}},\"type\":\"standard\",\"universal_id\":\"team\"},\"dynamic_6726179\":{\"label\":\"Type of Visa\",\"value\":\"\",\"type\":\"standard\",\"universal_id\":null},\"dynamic_6726181\":{\"label\":\"Employee ID\",\"value\":\"11617\",\"type\":\"standard\",\"universal_id\":null},\"dynamic_6726182\":{\"label\":\"National Insurance Number\",\"value\":\"99999999999\",\"type\":\"standard\",\"universal_id\":null},\"dynamic_6726188\":{\"label\":\"Holder of bank account\",\"value\":\"Myriam Smith\",\"type\":\"standard\",\"universal_id\":null},\"dynamic_6726191\":{\"label\":\"Emergency contact name\",\"value\":\"Sabina Smith\",\"type\":\"standard\",\"universal_id\":null},\"dynamic_6726195\":{\"label\":\"Address\",\"value\":\"Kössö Bryggväg 33\",\"type\":\"standard\",\"universal_id\":null},\"dynamic_6726165\":{\"label\":\"Birthday\",\"value\":\"1988-05-10T00:00:00+02:00\",\"type\":\"date\",\"universal_id\":\"date_of_birth\"},\"dynamic_6726173\":{\"label\":\"Trainings\",\"value\":\"Data security training,Product training\",\"type\":\"tags\",\"universal_id\":null},\"dynamic_6726180\":{\"label\":\"Visa expiry date\",\"value\":null,\"type\":\"date\",\"universal_id\":null},\"dynamic_6726189\":{\"label\":\"IBAN\",\"value\":\"SE45 5000 0000 0583 9825 7490\",\"type\":\"standard\",\"universal_id\":null},\"dynamic_6726193\":{\"label\":\"Marital status\",\"value\":\"single\",\"type\":\"list\",\"universal_id\":null},\"dynamic_6726197\":{\"label\":\"City\",\"value\":\"Gothenburg\",\"type\":\"standard\",\"universal_id\":null},\"dynamic_6726203\":{\"label\":\"Company car\",\"value\":\"\",\"type\":\"list\",\"universal_id\":null},\"dynamic_6726175\":{\"label\":\"Language Skills\",\"value\":\"English,German\",\"type\":\"tags\",\"universal_id\":null},\"dynamic_6726186\":{\"label\":\"Type of health insurance\",\"value\":\"compulsory\",\"type\":\"list\",\"universal_id\":null},\"dynamic_6726190\":{\"label\":\"BIC\",\"value\":\"XXAADEFF\",\"type\":\"standard\",\"universal_id\":null},\"dynamic_6726192\":{\"label\":\"Emergency contact phone number\",\"value\":\"(+49) 1601234567\",\"type\":\"standard\",\"universal_id\":null},\"dynamic_6726196\":{\"label\":\"Postcode\",\"value\":\"405 10\",\"type\":\"standard\",\"universal_id\":null},\"dynamic_6726204\":{\"label\":\"Laptop model\",\"value\":\"\",\"type\":\"list\",\"universal_id\":null},\"dynamic_6726166\":{\"label\":\"LinkedIn\",\"value\":\"https://www.linkedin.com/\",\"type\":\"link\",\"universal_id\":null},\"dynamic_6726176\":{\"label\":\"First Aider\",\"value\":\"no\",\"type\":\"list\",\"universal_id\":null},\"dynamic_6726187\":{\"label\":\"Name of health insurance\",\"value\":\"Example Insurance\",\"type\":\"standard\",\"universal_id\":null},\"dynamic_6726194\":{\"label\":\"Personal email\",\"value\":\"Myriam@Smith.com\",\"type\":\"standard\",\"universal_id\":null},\"dynamic_6726171\":{\"label\":\"Emergency contact relationship to the employee\",\"value\":\"mother\",\"type\":\"list\",\"universal_id\":null},\"dynamic_6726198\":{\"label\":\"Main or secondary occupation\",\"value\":\"main occupation\",\"type\":\"list\",\"universal_id\":null},\"dynamic_6726202\":{\"label\":\"Nationality\",\"value\":\"Swedish\",\"type\":\"list\",\"universal_id\":null},\"dynamic_6726199\":{\"label\":\"Child allowance\",\"value\":\"0\",\"type\":\"list\",\"universal_id\":null},\"dynamic_6726170\":{\"label\":\"Salary type\",\"value\":\"fix salary\",\"type\":\"list\",\"universal_id\":null},\"dynamic_6726168\":{\"label\":\"Notice period\",\"value\":\"3 months to end of month\",\"type\":\"standard\",\"universal_id\":null},\"dynamic_6726169\":{\"label\":\"Occupation type\",\"value\":\"permanent employment\",\"type\":\"list\",\"universal_id\":null}}}}"
}
```

The /forward API response includes details of the original `request`, alongside the forwarded response details from Personio's API. The response body that was retrieved from Personio is provided in raw format in the `data` response field. Myriam's **termination\_reason** can be extracted from here.

```js theme={null}
{
  label: 'Termination reason',
  value: 'employee-quit',
  type: 'standard',
  universal_id: 'termination_reason'
}
```

To recap, we've illustrated an example of how to use Request Forwarding to complement Finch's standardized data models, providing you with the most comprehensive view of the data you need, without having to incur the burden of managing an additional integration, all using a single Finch access token!


# SDKs
Source: https://developer.tryfinch.com/developer-resources/SDKs

Explore our frontend and backend SDK repositories. Finch supports SDKs in JavaScript, React, Node, Python, Java, Kotlin, Go, and Ruby.

## Frontend SDK

Finch's frontend SDK allows you to [embed Finch Connect](/implementation-guide/Connect/Set-Up-Finch-Connect#embedded-flow) into your application, enabling you to provide a seamless integration experience for your users.

We offer both a JavaScript and React frontend SDK, both of which can be viewed at the repository below:

<CardGroup>
  <Card title="Finch Connect SDK" icon="toolbox" href="https://github.com/Finch-API/finch-connect-sdk" />
</CardGroup>

## Backend SDKs

Finch maintains SDKs in several popular languages to make it easy to integrate with Finch APIs. These SDKs are regularly updated for breaking and non-breaking API changes. In addition to installation and quickstart information, each repository contains an `api.md` that documents available methods and data models.

<CardGroup>
  <Card title="Node" icon="node-js" href="https://github.com/Finch-API/finch-api-node" />

  <Card title="Python" icon="python" href="https://github.com/Finch-API/finch-api-python" />

  <Card title="Java" icon="java" href="https://github.com/Finch-API/finch-api-java" />

  <Card title="Kotlin" icon="k" href="https://github.com/Finch-API/finch-api-kotlin" />

  <Card title="Go" icon="golang" href="https://github.com/Finch-API/finch-api-go" />

  <Card title="Ruby" icon="gem" href="https://github.com/Finch-API/finch-api-ruby" />
</CardGroup>

If you do not see your language here, reach out to us!


# Tiered Employer Matching
Source: https://developer.tryfinch.com/developer-resources/Tiered-Employer-Matching

Learn how to manage tiered employer contributions (employer match) with Finch.

A 'tiered' company match is a structure where an employer matches employee retirement contributions at different rates across “tiers” of employee deferrals. Instead of one flat match rate, the match changes once the employee’s contribution crosses certain percentage thresholds.

Example

> “100% of the first 3% and 50% of the next 2% of the employee’s contributions.”

This means:

* On the first **3%** of pay the employee contributes, the employer matches **100%** (dollar-for-dollar).
* On the next **2%** of pay the employee contributes, the employer matches **50%** (50 cents on the dollar)

### Tiered Matching Examples

Tiered matching is common in retirement plans like 401(k), 403(b), and similar plans. Some examples of tiered match include:

* **Traditional Safe Harbor, Basic Match:**
  * 100% of the first 3% of compensation deferred, plus 50% of the next 2%
* **Traditional Safe Harbor, Enhanced Match**
  * 100% of the first 4% of compensation (4% max)
  * 100% of the first 5% of compensation (5% max)
  * 100% of the first 6% of compensation (6% max)
* **QACA Safe Harbor, Basic Match**
  * 100% of the first 1% of compensation deferred, plus 50% of the next 5%
* **QACA Safe Harbor – Enhanced Match**
  * 100% of the first 3.5% of compensation (3.5% max)
  * 100% of the first 4% of compensation (4% max)
  * 200% of the first 2% of compensation (4% max)

## Finch Integrations that Support Tiered Matching

Find the list of providers that support percent, fixed, and tiered employer matching [here](https://dashboard.tryfinch.com/docs/components/field-support?mode=dark\&group=deductions\&subgroup=features\&field=company_contribution%3Atiered%2Ccompany_contribution%3Apercent%2Ccompany_contribution%3Afixed\&endpoint=\&provider=\&authorization_type=).

You can also visit our Field Support page and follow these steps:

1. From the dropdown, select **“Field Support for Deductions.”**
2. Go to the **“Supported Features for Deductions”** tab.
3. Under **“Benefit Feature,”** select all applicable options:
   * `company_contribution:percent`
   * `company_contribution:fixed`
   * `company_contribution:tiered`

## How to Convert a Tiered Match Into a Single Match Percentage

Some payroll systems only support employer contributions as a single percentage of gross compensation (e.g., “x% of gross comp”), not as a tiered match based on employee contributions. If Finch support percentage contributions for a provider, you can convert the tiered match into a single % number to achieve the same outcome.

This section explains how to calculate that single percentage per employee, for each payroll, when your plan formula is:

> 100% of the first 3% of compensation deferred, and 50% of the next 2%

### Step 1: Find the employee’s contribution rate (R)

Get the employee’s contribution rate (R). Note that this “conversion” works reliably for %-based employee contributions only.

### Step 2: Convert R into a single employer percentage of gross comp

For this match formula (100% of first 3%, 50% of next 2%), the employer contribution as a single % of gross compensation can be found following the calculations below:

Let R = employee contribution rate (%):

* If R ≤ 0% → Employer % = **0%**
* If 0% \< R ≤ 3% → Employer % = **R**
* If 3% \< R ≤ 5% → Employer % = **3% + 0.5 × (R − 3%)**
* If R > 5% → Employer % = **4%** (the maximum match)

### Examples

Using the same formula (100% of first 3% and 50% of the next 2%):

* Employee defers 2% of pay
  * Falls in the 0–3% range
  * Employer % = R = **2% of gross comp**
* Employee defers 4% of pay
  * Falls in the 3–5% range
  * Employer % = 3% + 0.5 × (4% − 3%)
  * Employer % = 3% + 0.5% = **3.5% of gross comp**
* Employee defers 6% of pay
  * Above 5%, match is capped
  * Employer % = **4% of gross comp**

This approach gives you a single, per-employee employer contribution rate that correctly reflects the tiered match formula for each payroll period.


# Webhooks
Source: https://developer.tryfinch.com/developer-resources/Webhooks

Finch sends account update, job completion, and data change events via webhook. Register an endpoint in the Developer Dashboard to get your webhook secret.

New to Finch webhooks? Start with [Webhook Registration](/developer-resources/Webhooks#webhook-registration) to set up your endpoint and get your secret, then see [Webhook Verification](/developer-resources/Webhooks#webhook-verification) to learn how to validate incoming webhooks.

Your webhook endpoint, and the secret used to verify it, must live on your backend — for the same reason your Finch access token does. See [Backend Security](/implementation-guide/Backend-Application/Backend-Security).

<Info>
  Webhooks are not available on our legacy Free or Build plans. [Upgrade](https://www.tryfinch.com/pricing) to Starter, Pro, or Premier for access.
</Info>

## Webhook Payload Structure

### Common payload fields

Each webhook event contains the following fields in the response body:

| Field Name      | Type          | Description                                                                                                                                                                          |
| --------------- | ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `company_id`    | string\<uuid> | Unique Finch ID of the company for which data has been updated.                                                                                                                      |
| `account_id`    | string\<uuid> | **Deprecated.** Use `connection_id` instead.                                                                                                                                         |
| `connection_id` | string\<uuid> | Unique Finch id representing the connection between a developer's application and an employer's provider. Created when an employer successfully authenticates through Finch Connect. |
| `entity_id`     | string\<uuid> | Unique Finch id of the entity within the connection for which data has been updated. Present when the connection spans multiple entities; `null` otherwise.                          |
| `event_type`    | string        | The type of webhook being delivered.                                                                                                                                                 |
| `data`          | object        | More information about the associated event. The structure of this object will vary per event type.                                                                                  |

Finch provides three general types of webhook events: account updates, job completions, and data changes.

### Account Updates

Account update events contain information about account connections, such as when a connection has been established or when a connection has entered an error state. This type of webhook has the following unique schema:

| Field Name                   | Type   | Description                                                                                                                                                                                               |
| ---------------------------- | ------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `event_type`                 | string | Always `account.updated`.                                                                                                                                                                                 |
| `data.status`                | string | The status of the account. This follows our standard connection status schema. Options are `pending`, `processing`, `connected`, `reauth`, `error_permissions`, `error_no_account_setup`, `disconnected`. |
| `data.authentication_method` | string | The method of authentication used to connect this account. Options follow the standard Finch authentication types: `credential`, `api_token`, `oauth`, and `assisted`.                                    |

Example:

```json theme={null}
{
  "company_id": "720be419-0293-4d32-a707-32179b0827ab",
  "account_id": "fa872170-b49d-4fb5-aa39-fb1515db0925",
  "connection_id": "0057d3d2-fb43-4815-9f71-01ba4862d09f",
  "event_type": "account.updated",
  "data": {
    "status": "connected",
    "authentication_method": "assisted"
  },
  "entity_id": "61a9f5ba-95be-465d-a19b-34e19a07dd1c"
}
```

### Job Completion

Job completion events fire when a job finishes running, whether the final state is a success or an error.

Upon receiving a `job.{job_type}.completed` event, use the `job_url` in the payload to retrieve the job's final status.

| Event                                 | Description                                                                            | Values                                                                                       |
| ------------------------------------- | -------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------- |
| `job.data_sync_all.completed`         | Emitted for automated data sync jobs. Check status via the automated jobs endpoint.    | —                                                                                            |
| `job.w4_form_employee_sync.completed` | Emitted for automated W4 form sync jobs. Check status via the automated jobs endpoint. | —                                                                                            |
| `job.initial_data_sync_*.succeeded`   | Emitted when an initial data sync completes successfully for the first time.           | `initial_data_sync_org`, `initial_data_sync_payroll`                                         |
| `job.benefit_*.completed`             | Emitted for benefit-related jobs. Check status via the manual jobs endpoint.           | `benefit_create`, `benefit_register`, `benefit_enroll`, `benefit_unenroll`, `benefit_update` |

This type of webhook has the following `data` schema:

| Field Name     | Type          | Description                                                                                                                                                 |
| -------------- | ------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `event_type`   | string        | Follows the schema `job.{job_type}.completed`. `{job_type}` can be any valid Finch job type such as `data_sync_all`, `benefit_create`, or `benefit_enroll`. |
| `data.job_id`  | string\<uuid> | The id of the job which has completed.                                                                                                                      |
| `data.job_url` | string        | The url to query the result of the job.                                                                                                                     |

Example:

```json theme={null}
{
  "company_id": "720be419-0293-4d32-a707-32179b0827ab",
  "account_id": "fa872170-b49d-4fb5-aa39-fb1515db0925",
  "connection_id": "0057d3d2-fb43-4815-9f71-01ba4862d09f",
  "event_type": "job.benefit_enroll.completed",
  "data": {
    "job_id": "10f249d5-c974-4ce3-979a-31164323a34f",
    "job_url": "https://api.tryfinch.com/jobs/10f249d5-c974-4ce3-979a-31164323a34f"
  },
  "entity_id": "282e6177-e2ec-4197-801d-7ab16c2b0c99"
}
```

### Data Changes

Data change events fire when any data for a connection changes after Finch's initial data sync. These could be `created`, `updated`, or `deleted` events on any of our endpoints. One event fires per changed record — for example, if 10 individuals are updated across Directory, Employment, or Individual, Finch sends 10 separate events. This type of event has the following schema:

| Field Name   | Type   | Description                                                                                                                                                                                                                                                                                          |
| ------------ | ------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `event_type` | string | Follows the schema `{endpoint}.{created\|updated\|deleted}`. `{endpoint}` can be any Finch endpoint such as `company`, `directory`, `individual`, etc. You can see the full up-to-date list of events by registering an endpoint in our [developer dashboard](https://dashboard.tryfinch.com/login). |
| `data`       | object | The data object schema will change depending on the endpoint.                                                                                                                                                                                                                                        |

The possible `data` schemas per endpoint are as follows:

| Endpoint        | Event types                                                               | `data` fields                 |
| --------------- | ------------------------------------------------------------------------- | ----------------------------- |
| `company`       | `company.updated` only                                                    | `null`                        |
| `directory`     | `directory.created`, `directory.updated`, `directory.deleted`             | `individual_id`               |
| `employment`    | `employment.created`, `employment.updated`, `employment.deleted`          | `individual_id`               |
| `individual`    | `individual.created`, `individual.updated`, `individual.deleted`          | `individual_id`               |
| `payment`       | `payment.created`, `payment.updated`, `payment.deleted`                   | `payment_id`, `pay_date`      |
| `pay_statement` | `pay_statement.created`, `pay_statement.updated`, `pay_statement.deleted` | `payment_id`, `individual_id` |

Examples:

```json Company theme={null}
{
  "company_id": "720be419-0293-4d32-a707-32179b0827ab",
  "account_id": "fa872170-b49d-4fb5-aa39-fb1515db0925",
  "connection_id": "0057d3d2-fb43-4815-9f71-01ba4862d09f",
  "event_type": "company.updated",
  "data": null,
  "entity_id": "61a9f5ba-95be-465d-a19b-34e19a07dd1c"
}
```

```json Individual theme={null}
{
  "company_id": "720be419-0293-4d32-a707-32179b0827ab",
  "account_id": "fa872170-b49d-4fb5-aa39-fb1515db0925",
  "connection_id": "0057d3d2-fb43-4815-9f71-01ba4862d09f",
  "event_type": "individual.updated",
  "data": {
    "individual_id": "9987ecd1-6c6e-4d97-81ae-4d0248dbdb3d"
  },
  "entity_id": "61a9f5ba-95be-465d-a19b-34e19a07dd1c"
}
```

```json Pay Statement theme={null}
{
  "company_id": "720be419-0293-4d32-a707-32179b0827ab",
  "account_id": "fa872170-b49d-4fb5-aa39-fb1515db0925",
  "connection_id": "0057d3d2-fb43-4815-9f71-01ba4862d09f",
  "event_type": "pay_statement.created",
  "data": {
    "payment_id": "1c5e7bf2-94ce-4041-bf59-98e95677be21",
    "individual_id": "9987ecd1-6c6e-4d97-81ae-4d0248dbdb3d"
  },
  "entity_id": "61a9f5ba-95be-465d-a19b-34e19a07dd1c"
}
```

**Note:** One event is created for each pay statement object that has changed. For example, a new pay run for 20 individuals generates 20 unique pay statement events.

## Supported Events

| Event           | Automated  | Assisted          |
| --------------- | ---------- | ----------------- |
| Account Updates | ✓          | ✓                 |
| Job Completion  | All events | Benefit jobs only |
| Data Changes    | ✓          | —                 |

## Required Events

The following events cover the core connection lifecycle. Which ones apply depends on your product scopes:

| Event                                     | When to handle                                                                                                           | Action                                                                                                                                                               |
| ----------------------------------------- | ------------------------------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `account.updated`                         | `data.status` is `reauth`                                                                                                | Prompt the employer to re-authenticate via Finch Connect. See [Reauthentication](/developer-resources/Reauthentication).                                             |
| `job.initial_data_sync_org.succeeded`     | Initial org data sync completes — applies if your application uses `company`, `directory`, `individual`, or `employment` | Begin reading org endpoints. Requests made before this event may return `202` or `500`.                                                                              |
| `job.initial_data_sync_payroll.succeeded` | Initial payroll data sync completes — applies if your application uses `payment` or `pay_statement`                      | Begin reading payroll endpoints. Requests made before this event may return `202` or `500`.                                                                          |
| `job.benefit_*.completed`                 | A benefit write job finishes — applies if your application uses `benefits`                                               | Call [Retrieve a Manual Job](/api-reference/management/retrieve-a-manual-job) with `data.job_id` to check the outcome — the event fires on both success and failure. |

## Webhook Registration

Webhook endpoints should use HTTPS and expect to receive POST requests with the following headers:

```json theme={null}
{
  "Content-Type": "application/json",
  "Finch-Event-Id": "msg_2SFMDibF3lmRw8DzX4t1JjiEZQl",
  "Finch-Signature": "v1,8rFENj/WpNAMx+Kh5R1NLQunmpaBx4vOntjJdbGKbvM=",
  "Finch-Timestamp": "1688737757"
}
```

You can create webhooks via the [Finch Developer Dashboard](https://dashboard.tryfinch.com/).

<img alt="webhooksCreate.png" />

After registering a webhook, Finch displays a **webhook secret**. This **secret** validates that incoming webhooks were sent by Finch.

<img alt="webhooksSecret" />

The **secret** is displayed only once. Store it immediately. See the Webhook Verification section for more details.

## Webhook Verification

Finch uses HMAC-SHA256 webhook verification. To verify a webhook using the `Finch-Signature` header:

1. **Extract the signature from the header**. The `Finch-Signature` header consists of a list of signatures (where the signature content begins after "v1," and is space delimited) to account for secret rotations; there may be multiple signatures present for cases where a secret was rotated. During the verification process, the signature must match at least one signature in the list to be considered valid.

```text theme={null}
v1,g0hM9SsE+OTPJTGt/tmIKtSyZlE3uFJELVlNIOLJ1OE= v1,bm9ldHUjKzFob2VudXRob2VodWUzMjRvdWVvdW9ldQo= v2,MzJsNDk4MzI0K2VvdSMjMTEjQEBAQDEyMzMzMzEyMwo=
```

2. **Generate the webhook signature**

* First, base64 decode the webhook secret to get the raw bytes.
* Then, using the decoded webhook secret, hash the webhook content in the form `{webhook_id}.{webhook_timestamp}.{body}` where `webhook_id` is the `Finch-Event-Id`, `webhook_timestamp` is the `Finch-Timestamp`, and `body` is the raw request body. The signature is sensitive to any change in the body — do not modify it before verifying. If the computed signature does not match any signature in the `Finch-Signature` header, reject the webhook. Use a constant-time comparison to avoid timing attacks.

<CodeGroup>
  ```javascript Javascript theme={null}
  const crypto = require("crypto");

  const signedContent = `${webhook_id}.${webhook_timestamp}.${body}`;
  const SECRET = "5WbX5kEWLlfzsGNjH64I8lOOqUB6e8FH";

  // base64 decode the secret before use
  const secretBytes = new Buffer(SECRET, "base64");
  const signature = crypto
    .createHmac("sha256", secretBytes)
    .update(signedContent)
    .digest("base64");
  ```

  ```python Python theme={null}
  import hmac
  import base64

  signedContent = f"{webhook_id}.{webhook_timestamp}.{body}"
  SECRET = "5WbX5kEWLlfzsGNjH64I8lOOqUB6e8FH"

  # base64 decode the secret before use
  secretBytes = base64.b64decode(SECRET)
  signature = base64.b64encode(
      hmac.new(
          secretBytes,
          signedContent.encode(),
          'sha256'
      ).digest()
  ).decode()

  ```

  ```java Java theme={null}
  import javax.crypto.Mac;
  import javax.crypto.spec.SecretKeySpec;
  import java.nio.charset.StandardCharsets;
  import java.util.Base64;

  public class Main {
      public static void main(String[] args) throws Exception {
          String signedContent = webhook_id + "." + webhook_timestamp + "." + body;
          String SECRET = "5WbX5kEWLlfzsGNjH64I8lOOqUB6e8FH";

          // Need to base64 decode the secret
          byte[] secretBytes = Base64.getDecoder().decode(SECRET);

          Mac sha256_HMAC = Mac.getInstance("HmacSHA256");
          SecretKeySpec secret_key = new SecretKeySpec(secretBytes, "HmacSHA256");
          sha256_HMAC.init(secret_key);

          byte[] rawHmac = sha256_HMAC.doFinal(signedContent.getBytes(StandardCharsets.UTF_8));

          // base64 encode the result
          String signature = Base64.getEncoder().encodeToString(rawHmac);
          System.out.println(signature);
      }
  }
  ```
</CodeGroup>

3. **Verify the webhook timestamp.** If the signature is valid, check that the timestamp is within five minutes of the current time. If it is not, reject the webhook. Using outdated webhooks increases susceptibility to [replay attacks](https://en.wikipedia.org/wiki/Replay_attack).

The [Finch Backend SDKs](/developer-resources/SDKs) encapsulate all of this logic to simplify the webhook verification process.

<CodeGroup>
  ```javascript Javascript (express.js) theme={null}
  import Finch from '@tryfinch/finch-api';
  ...

  app.use('/webhooks/finch', bodyParser.text({ type: '_/_' }), function (req, res) {
  const finch = new Finch();
  const payload = finch.webhooks.unwrap(req.body, req.headers, process.env['FINCH_WEBHOOK_SECRET']); // env var used by default; explicit here.
  console.log(payload);
  res.json({ ok: true });
  });

  ```

  ```python Python (FastAPI) theme={null}
  from finch import Finch
  ...

  @app.post('/webhooks/finch')
  async def handler(request: Request):
      body = await request.body() # raw JSON string sent from the server
      secret = os.environ['FINCH_WEBHOOK_SECRET']  # env var used by default; explicit here.
      client = Finch()
      payload = client.webhooks.unwrap(body, request.headers, secret)
      print(payload)

      return {'ok': True}
  ```

  ```java Java (SpringBoot) theme={null}
  import com.tryfinch.api.client.FinchClient;
  import com.tryfinch.api.client.okhttp.FinchOkHttpClient;
  ...

  @RestController
  public class WebhookController {

      @PostMapping("/webhooks/finch")
      public HttpStatus handleWebhook(HttpServletRequest request, @RequestBody String payload) {
          try {
              FinchClient finch = FinchOkHttpClient.builder().webhookSecret("your-secret").build();

              // Implement this to get headers from request as a ListMultimap
              ListMultimap<String, String> headers = this.getHeadersFromRequest(request);

              // Validate signature
              finch.webhooks().verifySignature(payload, headers, null);

              // Implement this to handle webhook payload
              this.handleWebhookPayload(payload);
          } catch (Exception e) {
              // Handle exception
              return HttpStatus.INTERNAL_SERVER_ERROR;
          }

          return HttpStatus.OK;
      }
  }
  ```

  ```kotlin Kotlin (SpringBoot) theme={null}
  import com.tryfinch.api.client.FinchClient
  import com.tryfinch.api.client.okhttp.FinchOkHttpClient
  ...

  @RestController
  class WebhookController {

    @PostMapping("/webhooks/finch")
    fun handleWebhook(request: HttpServletRequest, @RequestBody payload: String): HttpStatus {
        try {
            val finch = FinchOkHttpClient.builder().webhookSecret("your-secret").build()

            // Implement this function to get headers from request as a ListMultimap
            val headers = getHeadersFromRequest(request)

            // Validate signature
            finch.webhooks().verifySignature(payload, headers, null)

            // Implement this to handle webhook payload
            handleWebhookPayload(payload)
        } catch (e: Exception) {
            // Handle exception
            return HttpStatus.INTERNAL_SERVER_ERROR
        }

        return HttpStatus.OK
    }
  }
  ```

  ```go Go (net/http) theme={null}
  import (
    finchgo "github.com/Finch-API/finch-api-go"
    ...
  )


  func webhookHandler(w http.ResponseWriter, r *http.Request) {
    header := r.Header
    secret :=  os.Getenv("FINCH_WEBHOOK_SECRET")
    now := time.Now()
    b, err := ioutil.ReadAll(r.Body)
    if err != nil {
      panic(err)
    }

    client := finchgo.NewClient()
    err = client.Webhooks.VerifySignature([]byte(b), header, secret, now)
    if err != nil {
      fmt.Println("Error with signature")
      os.Exit(1)
    }
      fmt.Fprintf(w, "Response to finch webhook")
  }

  func TestAppServer() {
    http.HandleFunc("/webhooks/finch", webhookHandler)

    log.Fatal(http.ListenAndServe(":8081", nil))
  }
  ```
</CodeGroup>

## Testing Webhooks

You can send a test request to any webhook through the developer dashboard.

<img alt="Test webhooks" />

The test webhook uses the same structure as data change webhooks, with `event_type` set to `test`.

## Retry schedule

Upon failure, Finch retries according to the following schedule with exponential backoff:

* Immediately
* 5 seconds
* 5 minutes
* 30 minutes
* 2 hours

If all retries are exhausted without a successful delivery, the event is dropped. Use the Finch API to fetch current data for any records you suspect may have been missed.

## Best practices

### Pair Webhooks with a Recurring Sync

No webhook system can guarantee delivery. Network issues, service outages, and exhausted retries can all result in a missed event.

Alongside webhooks, schedule a recurring job that reads the Finch endpoints your application uses. This keeps every connection up to date, including [assisted](/integrations/integration-types#assisted-integrations) connections, which do not emit data change events. See [Data Syncs](/developer-resources/Data-Syncs#ongoing-data-syncs) for how often Finch refreshes data.

### Responding to Webhooks

To prevent unnecessary retries, receive and process webhook events in separate processes. Respond immediately with a `200` to indicate successful delivery, then process the event asynchronously.

### Event Delivery and Ordering

* You may occasionally receive the same webhook event more than once. Use the `Finch-Event-Id` to implement idempotent event processing.
* Finch does not guarantee delivery of events in the order they happen. For example, you may receive an `update` event for an `individual` before a `created` event. You should also use the Finch API to occasionally fetch any missing data. For example, you can fetch an individual if you happen to receive an `update` event first.

### Event Mapping

* Each webhook includes a `connection_id` identifying the employer connection. Use it to route incoming events to the right employer in your system. For details on capturing and storing the `connection_id`, see [Retrieve Access Token](/implementation-guide/Connect/Retrieve-Access-Token).
* Each webhook also includes an `entity_id` for the specific entity within that connection. For multi-entity connections, the `entity_id` is required in subsequent API requests.


# API Changes and Updates
Source: https://developer.tryfinch.com/developer-resources/api-changes

 Keep track of changes and upgrades to the Finch API 

At Finch, we are committed to ensuring API stability. We design our APIs with backward compatibility in mind, and we want to make it clear what types of changes we consider non-breaking - changes that should not impact existing client integrations.

This page outlines the changes we may introduce without a new API version or advance warning.

### Additive Changes

* Adding new optional request fields: We may introduce new fields that are not required. Your existing requests will continue to work as-is.
* Adding new response fields: You may start seeing additional fields in API responses. These will not change the structure of existing fields and can be safely ignored by clients that don’t use them.
* Introducing new endpoints: New endpoints do not interfere with existing functionality.
* Adding new enum values: If you're using enums, we may add new values. Make sure your implementation doesn’t break when unknown enum values are returned.
* Adding new errors: New error types and codes can be added to accurately indicate the success or failure of a task. These will not change existing errors.

### Documentation Updates

* Clarifying descriptions: We may refine or clarify descriptions, usage examples, or error codes in our documentation.
* Improving examples or formatting: These changes help improve readability and developer experience, but do not impact functionality.

### Performance Upgrades

* Improving response time: Backend optimizations or caching mechanisms that improve performance without changing behavior.
* Upgrading infrastructure: These are internal changes and do not affect how the API behaves or how it should be used.

To ensure your integration with Finch is as robust as possible, we recommend:

* Use tolerant JSON parsers that ignore unknown fields
* Don’t rely on the exact order of response fields
* Make your code resilient to new enum values or unexpected optional fields


# How the Finch API is organized
Source: https://developer.tryfinch.com/how-finch-works/data-model

Finch's API data model normalizes payroll, HR, and benefits data from 250+ providers. Walk through the core entities and how they connect in one map.

The diagrams below give you a working mental model of the Finch API. Each section explains the high-level functionality of Finch's products, each of which contains multiple endpoints.

## Organization: company, individual, and employment

<Frame>
  <img alt="Company maps one-to-many to Individual and Employment, which share an individual_id" />
</Frame>

A Finch [connection](/implementation-guide/Backend-Application/Manage-Connections) typically covers one [Company](/api-reference/organization/company), which can include one or many entities (separate EINs, divisions, or subsidiaries) with one or many employees. Each employee has two records that share the same `individual_id`: an [Individual](/api-reference/organization/individual) record for identity data (name, DOB, SSN, home address) and an [Employment](/api-reference/organization/employment) record for job data (title, manager, start date, income). Querying them separately means you can pull only what you need.

To enumerate everyone at a connection, call [`GET /employer/directory`](/api-reference/organization/directory) first. It returns a paginated list of `individual_id`s you can then fetch in detail via the endpoints above.

<Tip>
  The same person can have multiple Employment records over time (rehires, role changes, multi-EIN setups). Treat `individual_id` as the stable identity key and Employment as historical job state.
</Tip>

## Payroll: payments and pay statements

<Frame>
  <img alt="Payment contains pay statements, which contain earnings, taxes, employee deductions, and employer contributions, all flattened into pay statement items" />
</Frame>

A [Payment](/api-reference/payroll/payment) is one payrun, and it's the starting point for all payroll data. Each Payment contains one [Pay Statement](/api-reference/payroll/pay-statement) per person, broken down into earnings (base, overtime, bonus), taxes (federal, state, FICA), employee deductions (401k, health premiums, FSA), and employer contributions (401k match, employer-paid benefits). Deductions and contributions live in separate fields on the Pay Statement so you can read or aggregate each side cleanly.

Use the [Pay Statement Item](/api-reference/payroll/get-pay-statement-items) endpoint to retrieve all payroll items that have appeared in a company's processed payroll, including taxes, deductions, earnings, and employer contributions. For example, if your customer's organization labels a health deduction as `EE_MED_PPO_PREM` in the provider system, this endpoint surfaces that name alongside its category and type. From there you can use the [Rules endpoint](/api-reference/payroll/get-rules) to apply the right labels and context in your system.

## Deductions: company benefits and per-employee contributions

<Frame>
  <img alt="Company deduction maps to per-individual deduction records, which are referenced by pay statement items as deduction or contribution lines" />
</Frame>

Finch's [Deductions](/products/deductions/Overview) product represents benefits from the payroll side, in two connected views. A company-level deduction defines the benefit at the company: type (401k, HSA, FSA, etc.), frequency, and the employer's contribution rule. An [individual deduction record](/api-reference/deductions/get-enrolled-individuals) then holds the per-person amounts: employee contribution, employer contribution, and annual maximum. The per-paycheck amount itself lives on the Pay Statement Item. The deduction record tells you what should happen each pay period; the pay statement item tells you what actually happened.

You can [add individuals to a deduction](/api-reference/deductions/enroll-individuals-in-deductions), [update contribution amounts](/api-reference/deductions/update-deduction), and [remove individuals](/api-reference/deductions/unenroll-individuals-from-deductions) where the provider allows it. Call the [`/providers`](/api-reference/management/providers) endpoint to see which deduction types and operations each provider supports before you build against them.

## Benefits: plans, enrollments, and dependents

<Note>
  Benefits is in closed beta. Endpoint paths and field names are subject to change before general availability.
</Note>

<Frame>
  <img alt="Plan maps one-to-many to Enrollment records, which link bidirectionally to Dependent records" />
</Frame>

[Benefits](/products/benefits/Overview) is Finch's source-of-truth product for benefits enrollment. Where Deductions (above) shows the payroll-side evidence of a benefit, like what's being withheld each paycheck, Benefits returns the canonical plan and enrollment data directly from the benefits administration side of the employer's system:

* **Plan**: the company-level benefit plan, including type, carrier, plan year, deduction code, and available coverage tiers.
* **Enrollment**: the individual's actual enrollment in a plan, with coverage tier, effective dates, contribution amounts, and covered dependents.
* **Dependent**: a spouse or child covered under an individual's enrollment, linked back to its enrollment records.

Use Benefits when you need authoritative enrollment state, for example to verify coverage before quoting a benefit or to retrieve dependent details for compliance. Use Deductions when you need to see what's actually being withheld each pay period. The two are complementary.

## Documents: parsed data from HR forms

<Frame>
  <img alt="Queue a job leads to a documents list, then drill into a specific document to read parsed fields" />
</Frame>

Finch's [Documents](/products/documents/Overview) product reads structured data out of HR documents using ML-based parsing. Two endpoints carry the data: [`GET /employer/documents`](/api-reference/documents/get-documents) returns a list of available documents (filterable by individual or document type), and [`GET /employer/documents/{document_id}`](/api-reference/documents/get-document) returns the parsed fields for one document.

Documents is async. Before either read endpoint will return fresh data, queue an automated job with [`POST /jobs/automated`](/api-reference/management/enqueue-a-new-automated-job) so Finch can sync from the provider. The product is currently in beta with W-4 support; expect more document types over time.

## Next steps

<CardGroup>
  <Card title="Quickstart" icon="rocket" href="/how-finch-works/quickstart">
    Mint a sandbox token and pull your first employer record.
  </Card>

  <Card title="API reference" icon="code" href="/api-reference">
    Every endpoint, request shape, and response field.
  </Card>

  <Card title="Finch Sandbox" icon="flask" href="/implementation-guide/Test/Finch-Sandbox">
    Test the data model with realistic fixtures before wiring up production.
  </Card>

  <Card title="Glossary" icon="book" href="/how-finch-works/unified-employment-api-glossary">
    Reference for every term used across the Finch API.
  </Card>
</CardGroup>


# Connect an Employer
Source: https://developer.tryfinch.com/how-finch-works/finch-connect

Finch Connect is an embedded onboarding flow that enables employers to connect their HR or payroll system to your app.

In order to receive data from any employment system, you'll first need to connect an employer. Finch Connect is an embedded onboarding flow that enables employers to connect their data through the following steps.
See our [Implementation Guide](/implementation-guide/go-live-checklist) for more detailed instructions on how to [set up Finch Connect](/implementation-guide/Connect/Set-Up-Finch-Connect).

<Steps>
  <Step title="Open Finch Connect">
    <img alt="Open Finch Connect" />

    Employers access Finch Connect from within your application. We suggest launching Finch Connect during the employer onboarding process. There are many ways to [Increase Employer Adoption](/implementation-guide/Deploy-and-Manage/Increase-Employer-Adoption) of Finch Connect.
  </Step>

  <Step title="Connect a provider">
    <img alt="Finch Connect Screens" />

    * **Read privacy disclosures** - Finch Connect discloses data privacy practices right from the start, so your customers know where and how their data is used.
    * **Confirm permissions** - Finch Connect displays the granular permissions needed to access the requested data. Finch only shares data that has been approved.
    * **Select a provider** - Your customer can then select their employment system from Finch's list of 200+ integrations.
    * **Authenticate access** - Finch Connect prompts your customer to log in to their employment system, and grant you access to requested data. Finch Connect will only succeed if the user is an employer admin with permissions to view the full employee directory and view the full company payroll.
  </Step>

  <Step title="Receive Data">
    <img alt="Finch Connect Screens" />

    That's it! Upon successful authentication, Finch Connect closes and redirects back to your application.

    Once the connection is established, you will receive a Finch access token and can call the Finch API. At this point you can assure your users that the connection has been set up successfully, and redirect them to other tasks.
  </Step>
</Steps>

## Learn More

More information about how Finch Connect works and how to implement it into your application can be found in the  [Set Up Finch Connect](/implementation-guide/Connect/Set-Up-Finch-Connect) of the Finch Implementation Guide.


# What is Finch?
Source: https://developer.tryfinch.com/how-finch-works/finch-overview

The Finch API powers integrations to employment systems through a single, standardized data model.

Finch is a connectivity platform that enables you to connect to hundreds of employment systems through a unified API. Once Finch is integrated into your application, you can access your customers' company details, employment history, employee count, individual contact information, income details, company pay periods, and individual paycheck details like earnings, taxes, deductions, and contributions.

Finch works by allowing your customers (employers) to connect their employment systems (HRIS, Payroll, etc.) to your application. This connection process is facilitated through [Finch Connect](/how-finch-works/finch-connect), our employer-facing user interface which provides an elegant and secure authorization flow where your customers (employers) approve permissions, select their provider, and authorize access to their employment systems. Upon a successful connection, Finch will issue an access token to your application which is used to make API requests to Finch API endpoints.

<img alt="How Finch Works Diagram" />

## Products

Finch offers four products: Organization, Payroll, Deductions, and Documents. Each product has its own set of endpoints, which provide specific data related to HRIS and payroll employment systems.

* Our [Organization](/products/organization/Overview) product provides APIs to read company directory and employee data including contact information, demographics, departmental hierarchy, income history, and more.
* Our [Payroll](/products/payroll/Overview) product provides APIs for retrieving company payroll and inspecting individual paycheck information such as earnings, taxes, deductions, and contributions.
* Our [Deductions](/products/deductions/Overview) product provides APIs for creating, enrolling, and unenrolling individuals in deductions and contributions directly within the payroll provider.
* Our [Documents](/products/documents/Overview) product provides APIs to read data from employee and employer documents like W-4 forms.

## Finch Connect

Employers connect their data to your application in 4 easy steps, facilitated through [Finch Connect](/how-finch-works/finch-connect).

* **Prioritize privacy**: Finch Connect discloses data privacy practices right from the start, so your customers know where and how their data is used.
* **Confirm permissions**: Finch Connect displays the granular permissions needed to access the requested data. Finch only shares data that has been approved.
* **Select a provider**: Once the user approves, they select their employment system from Finch's list of 200+ integrations.
* **Authenticate access**: The user is prompted to log into their account (via credentials or API key if available), granting your application access to their employment data.

## Integration Types

Finch offers two [Integration Types](/integrations/integration-types) that enable you to optimize for either data refresh cadence or long-tail provider coverage. This allows you to service *all* of your customers via Finch, no matter which employment systems they are using. Employers will go through different Finch Connect experiences depending on the integration type.

## Connections

After an employer authenticates via Finch Connect, a connection is established between you and the employer via Finch. A [connection](/how-finch-works/unified-employment-api-glossary#connection) is a unique *Provider* + *App* + *Company* pairing.


# Quickstart
Source: https://developer.tryfinch.com/how-finch-works/quickstart

This API Quickstart guide will help you send your first request to Finch, the unified API for HR and payroll.

To get started, sign up for a sandbox account [here](https://dashboard.tryfinch.com/signup). After registration, you will have access to a sandbox application `client_id` and `client_secret` to build and test how Finch works using simulated data.

This guide will help you send your first request to Finch's API while the following guides dive deeper into the concepts and help you integrate Finch into your production application.

## Open Finch Connect in sandbox mode

Finch Connect provides a secure and elegant authorization flow for your users to grant your application access to their systems.

<Warning>Note: this quickstart guide is a simplified, but manual way of generating an authorization `code` and exchanging it for an `access_token`, which can be used to subsequently call our APIs. In a true production environment, you will want to automate this process completely inside your application's code.</Warning>

Since this quickstart assumes you have not built an application yet, we must make sure that a proper `redirect_uri` is set up before continuing or our authorization code generation will fail. In your [Finch Dashboard](https://dashboard.tryfinch.com/signup), go to the "Redirect URIs" section and select `+ Add Redirect URI`. We are going to use [https://example.com](https://example.com) for testing purposes. In production, you will want to use your own application's urls for the Redirect Uris (and remove all mentions of [https://example.com](https://example.com) or [http://localhost](http://localhost)).

Redirect URIs are only needed if you are redirecting to Finch Connect. If you decide to use our embedded Finch Connect flow, you do not need to specify a redirect\_uri; the SDK does this for you.

We will launch [Finch Connect](/how-finch-works/finch-connect) - our secure authorization flow for your users to grant your application access to their systems - by making an API call to the endpoint below. Make sure to replace `<your_client_id>` with the client id found in your [Finch Dashboard](https://dashboard.tryfinch.com/signup). Remove the angle brackets when replacing `<your_client_id>`. `customer_id` and `customer_name` can be any identifiers you have internally for your end users. After the API call succeeds, navigate to the URL found in the response body on your browser.

```cs theme={null}
curl https://api.tryfinch.com/connect/sessions \
-X POST \
-H "Content-Type: application/json" \
-u "<your_client_id>:<your_client_secret>" \
--data-raw '{
		"customer_id": "<your_client_id>",
		"customer_name": "<your_customers_name>",
    "products": ["directory", "individual", "employment"],
		"redirect_uri": "https://example.com",
    "sandbox": "finch"
}'
```

```cs theme={null}
{
	"session_id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
	"connect_url": "https://connect.tryfinch.com/authorize?session=f47ac10b-58cc-4372-a567-0e02b2c3d479"
}
```

<Note>
  Note that we have set `sandbox=finch`. This is required only when testing in our [sandbox environment](/implementation-guide/Test/Finch-Sandbox)
</Note>

## Log in to the Finch sandbox account

Select any provider on the selector page and log in with [valid mock credentials](/implementation-guide/Test/Finch-Sandbox#simulating-credential-flows). For example, you can choose ADP Workforce Now and log in with the credentials `good_user` and `good_pass`.

<img />

## Exchange the authorization code for an access token

After successfully logging in via Finch Connect, your browser will be redirected to `https://example.com` with the query parameter `code` in the browser URL. Copy the `code` from the url and save it in your text editor. In a production system, however, the browser will redirect to your url and your application will automatically copy the `code` and perform the remaining steps programmatically.

To exchange the `code` for a token, we use the `curl` command below. Copy the code below, paste into your text editor, replace the `<your_authorization_code>` in the command with the one you saved above (making sure to not include the angle brackets).

<Tabs>
  <Tab title="Request">
    ```bash theme={null}
    curl https://api.tryfinch.com/auth/token \
    -X POST \
    -H "Content-Type: application/json" \
    --data-raw '{
        "client_id": "<your_client_id>",
        "client_secret": "<your_client_secret>",
        "code": "<your_authorization_code>",
        "redirect_uri": "https://example.com"
    }'
    ```
  </Tab>

  <Tab title="Response">
    ```json theme={null}
    {
      "company_id": "4ab15e51-11ad-49f4-acae-f343b7794375",
      "account_id": "ac3a2af9-ce03-46c4-9142-81abe789c64d",
      "connection_id": "bc3a2af9-ce03-46c4-9142-81abe789c64d",
      "provider_id": "adp_workforce_now",
      "products": ["directory", "individual", "employment"],
      "client_type": "production",
      "connection_type": "provider",
      "access_token": "7e965183-9332-423c-9259-3edafb332ad2",
      "customer_id": "7ff74b71-0413-4dbb-a18f-18b1afef4ce6",
      "token_type": "bearer"
    }
    ```
  </Tab>
</Tabs>

<Check>
  **Congratulations!**

  You have sent your first request to Finch's API. The next step is to embed [Finch Connect](/implementation-guide/Connect/Set-Up-Finch-Connect) into your application.
</Check>


# Unified API Glossary
Source: https://developer.tryfinch.com/how-finch-works/unified-employment-api-glossary

Use this glossary to familiarize yourself with terminology used in Finch's documentation and API reference.

### Provider

A *provider* is an employer's HRIS, Payroll, or other employment system. The provider is the system of record for the data connected to the Finch APIs. Providers can be referenced within the Finch APIs by their `payroll_provider_id`.

### Employer

An *employer* is an organization or company that hires and pays employees. An employer may consist of [one or many entities](/implementation-guide/Backend-Application/Manage-Connections) and use one or many systems of record (i.e. [payroll providers](/integrations/providers)) to manage and pay employees. Employers can be referenced within the Finch APIs by their Finch-issued `connection_id`.

### Entity

An *entity* is a grouping of employees within a payroll system. Entities vary by payroll provider and may be configured by the employer. For example, an entity could be defined by:

* EIN
* Company code
* Division
* Location
* Or any other grouping of employees defined by the payroll system

If an employer has multiple entities within their payroll system, they may connect one or more entities to a connection. This would be represented as a single Finch connection with the same `connection_id` and managed using a single access token.

### Individual

An *individual* is a unique person with distinctive attributes, represented as *fields*, who is currently or formerly employed at an *employer*. Individuals can be referenced within the Finch APIs by their finch-issued `individual_id`. Contractors are also considered individuals.

### Field

A *field* is a specific employment data element or attribute displayed within Finch's standardized data model pulled directly from an employment system.

### Product

A *product* is a subgroup of Finch's standardized data model related to a particular segment or workflow of an employment system. Finch currently has four products: [Organization](/products/organization/Overview), [Payroll](/products/payroll/Overview), [Deductions](/products/deductions/Overview), and [Documents](/products/documents/Overview).

### Connection

A *connection* is the link created between your application and the employer's provider through Finch. A connection is established after an employer authenticates via [Finch Connect](/how-finch-works/finch-connect). A connection is defined by a unique `connection_id`. An *employer* may have [one or many connections](/implementation-guide/Backend-Application/Manage-Connections) depending on if the employer uses multiple payroll providers. For example, if the employer uses Provider A to manage US-based employees and Provider B to manage international employees, the employer would need to create two Finch connections.

### (Employer) Account

An employer *account* is used to connect their company's data to Finch. Employers can connect with various *authentication methods* such as an HR admin's account, an API service account (i.e. API token), or a third-party administrator account.

### Access Token

An *access token* represents a single *connection* with an employer entity and allows the developer to query data from the associated employment system of the employer entity. You should treat access tokens with the same [level of security](/implementation-guide/Backend-Application/Store-Tokens) as you would passwords.

### Product scope

A *product scope* determines the specific data your *application* can access from the employer's provider. Each product scope refers directly to a Finch API endpoint. If a connection's access token does not have the product included, the request will be blocked with a 401 Unauthorized error.

### Application

An *application* is a unique set of `client_id` and `client_secret` credentials that enable you to launch [Finch Connect](/implementation-guide/Connect/Set-Up-Finch-Connect) and [receive access tokens](/implementation-guide/Connect/Retrieve-Access-Token). An application essentially groups your *connections* with your Finch "environment". Finch has three environments: sandbox, testing, and production. The sandbox application connects only mock providers. The testing application connects live providers, but in a limited capacity. The production application connects live providers without any limitations.

### Authentication Method

An *authentication method* is the specific technique that an employer account uses to connect their provider. Finch supports OAuth 2.0, API token, user credentials, and assisted as authentication methods to allow you maximum flexibility in offering integrations to your end customer. Each method provides a distinct balance between reliability and data accessibility depending on the needs of your application and your customer. See the "Products" section in the [Provider Field Support](/integrations/providers) for each provider's supported authentication methods. You can also use the `authentication_methods` field on the [Providers](/integrations/providers) endpoint of the API.

### Integration Type

An *integration type* refers to one of two ways that Finch organizes our provider integrations. *Automated integrations* are the primary integration type offered by Finch, and offer the highest level of data responsiveness. *Assisted integrations* enable Finch to offer the highest level of provider coverage, while maintaining an API-first experience for developers. See our [Integration Types](/integrations/integration-types) page for more details.

### Automated Integration

An *automated integration* syncs data automatically from the employment system once a connection is created. Finch will then proactively sync with the employment system on our periodic [Data Sync](/developer-resources/Data-Syncs) cadence. A full list of Finch's automated integrations can be referenced on the [Providers](/integrations/providers) overview.

### Assisted Integration

An *assisted integration* syncs data through a manual service model powered by Finch's Product Operations team. The data is synced on a slower cadence compared to automated integrations. Assisted integrations help expand coverage to the long tail of providers not otherwise covered by automated integrations. Finch is continuously updating assisted integrations to automated integrations based on customer demand and provider availability. A full list of Finch's assisted integrations can be referenced on the [Providers](/integrations/providers) overview.

### Data Sync

A *data sync* is the cadence that Finch synchronizes our system with the employer's provider system to ensure consistent, up-to-date data. Finch's API responses will return employer data from the most recent successful data sync to increase performance and reduce latency.

### Job

A *job* is a reference object to an API request submitted to Finch which is scheduled to be asynchronously completed. Jobs can be completed automatically (such as data syncs or automated benefit tasks) or asynchronously (such as assisted benefit tasks). A job can be referenced within the Finch APIs by its Finch-issued `job_id`.

### Payment

A *payment* is the summary of the monetary transactions an employer provides to employees in return for their work during a specified period of time. Types of payments can include regular payments (salary, wages, etc.) or off-cycle payments (bonuses, commissions, etc.). Payments can be referenced by their Finch-issued `payment_id`.

### Pay Statement

A *pay statement* is a detailed breakdown of the *payment* by employee. Pay statements, also known in the industry as "paystub" or "payslip" provide comprehensive information on an individual's gross pay, net pay, earnings, taxes, employee deductions, and employer contributions for a specified pay period. Pay statements can be referenced by their Finch-issued `payment_id`.

### Pay Groups

A *pay group* refers to a group of employees within an employer that are paid on the same payroll frequency for on-cycle payments. An employer can have multiple pay groups. Each pay group retrieved by Finch will have a description and the payroll frequency associated with it, as obtained from the payroll system.

### Earning

An *earning* refers to the various types of compensation an employee receives in exchange for their services during a specific pay period. Some examples of earnings are salary, wage, bonus, commissions, tips, and allowances. Earnings are the detailed breakdown of an employee's `gross_pay` found on the *pay statement*.

### Tax

A *tax* refers to the mandatory financial charges imposed by government entities that are withheld from an employee's earnings based on several factors like earnings amount, the employee's tax bracket, and more. These amounts are deducted from the employee's gross earnings and are remitted directly to the relevant tax authorities by the employer on behalf of the employee. Several types of taxes commonly found on a pay statement include federal income tax, state income tax, and social security tax.

### Benefit

A *benefit* is a non-wage form of compensation available to employees often aimed at enhancing the overall well-being, financial security, or work-life balance of the employee. Some benefits can be available company-wide or individual only.

### Deduction

An employee *deduction* refers to withholdings that are subtracted from an employee's gross earnings in return for benefits or services rendered by the employer on behalf of the employee. Common employee deductions include health insurance premiums, retirement contributions, voluntary benefits, and any type of custom benefit.

### Contribution

An employer *contribution* refers to amounts that the employer pays on behalf of the employee, typically towards benefits or specific programs. Unlike deductions, which are taken from the employee's gross earnings, employer contributions represent additional amounts that the employer is contributing over and above the employee's salary or wages (but not included in the employee's gross earnings).


# Batch Requests
Source: https://developer.tryfinch.com/implementation-guide/API-Calls/Batch-Requests

Batch multiple IDs into a single request to Finch's individual, employment, pay-statement, and deductions endpoints to cut API calls and rate limit risk.

## How batching works

Several Finch endpoints — [`/individual`](/api-reference/organization/individual), [`/employment`](/api-reference/organization/employment), and [`/pay-statement`](/api-reference/payroll/pay-statement) — accept multiple IDs in a single request. Finch returns one response with an array of objects, one per ID sent.

For example, retrieving individual details for a 1,000-person company by calling `/individual` 1,000 times quickly exhausts your [rate limit](/api-reference/development-guides/Rate-Limits). Since there's no limit on the number of IDs per request, batch all 1,000 `individual_ids` into a single call instead — Finch returns one response with an array of 1,000 individual detail objects. Batching also cuts down the number of round trips your application makes, on top of helping you stay within your rate limit.

Each batch endpoint enforces a maximum batch size. Build your application to split `requests[]` into chunks that stay within these limits before sending — a request over the limit fails before Finch processes any item in the batch.

| Endpoint                                                 | Max batch size               |
| -------------------------------------------------------- | ---------------------------- |
| [`/individual`](/api-reference/organization/individual)  | 10,000 items per request     |
| [`/employment`](/api-reference/organization/employment)  | 10,000 items per request     |
| [`/pay-statement`](/api-reference/payroll/pay-statement) | 10 `payment_id`s per request |

For example, to request 25,000 individuals from `/individual`, split the `individual_id`s into three requests of 10,000, 10,000, and 5,000 items rather than sending all 25,000 in one call.

```json theme={null}
{
  "requests": [
    {
      "individual_id": "772b3c4f-d764-433d-bd69-ff8bbac33ffe"
    },
    {
      "individual_id": "a7a77065-0f68-418d-a85a-da24fb2139b7"
    },
    ...
    {
      "individual_id": "84364585-c2ce-40aa-bcc0-666ac9577315"
    }
  ]
}
```

### Batching deductions requests

Three deductions endpoints also accept multiple individuals in a single call, but with different request shapes than `/individual`, `/employment`, and `/pay-statement`:

* [Get Deductions for Individuals](/api-reference/deductions/get-deductions-for-individuals) (`GET /benefits/{benefit_id}/individuals`) — pass a comma-delimited `individual_ids` query parameter instead of a request body. Finch returns an array of `{individual_id, code, body}` objects, one per ID.
* [Enroll Individuals in Deductions](/api-reference/deductions/enroll-individuals-in-deductions) (`POST /benefits/{benefit_id}/individuals`) — pass an array of enrollment objects directly as the request body, one per individual. This is an asynchronous batch write: Finch returns a single `job_id` for the whole batch instead of a per-item response. See [Write Data](/implementation-guide/API-Calls/Write-Data) for the enrollment request format and how to verify the job.
* [Unenroll Individuals from Deductions](/api-reference/deductions/unenroll-individuals-from-deductions) (`DELETE /benefits/{benefit_id}/individuals`) — pass an `individual_ids` array in the request body. Like enrollment, this is an asynchronous batch write that returns a single `job_id` for the whole batch.

## Batch limit errors

A request with more items than an endpoint's max batch size returns a `422` with a `finch_code` of `batch_limit_exceeded`, and Finch does not process any item in the batch:

```json theme={null}
{
  "code": 422,
  "name": "unprocessable_entity_error",
  "finch_code": "batch_limit_exceeded",
  "message": "Batch size exceeds the maximum of 10000 items. Please reduce the number of items in your request."
}
```

Split the request into smaller batches — retrying the same request without changing it fails again. See [Mitigate Errors](/implementation-guide/Backend-Application/Mitigate-Errors#batch-and-page-size-limit-errors) for the full error format.

## Per-item errors

When a batch request is within the size limit, Finch can still return errors for individual items inside it. Finch returns these errors two ways, both in the format described in [Error Types](/api-reference/development-guides/errors/Error-Types):

1. An error per batch request item within the response body.
2. An error at the HTTP status code level.

A `200` HTTP status code doesn't mean every item in the batch succeeded — check each item's own `code` in the response body.

```json theme={null}
// HTTP 200 status code
{
  "responses": [
    {
      "individual_id": "4f66ec6e-f73c-41e6-bc14-bb2ae53288a0",
      "code": 404,
      "body": {
        "code": 404,
        "name": "not_found_error",
        "finch_code": "individual_not_found",
        "message": "No individual with id 4f66ec6e-f73c-41e6-bc14-bb2ae53288a0 found"
      }
    }
  ]
}
```

***

## Checkpoint + Next Step

<Check>
  After completing this step, your application can send thousands of IDs in a single HTTP request and handle each item's result in the response body. Batch errors are one type of error your application can encounter — see [Mitigate Errors](/implementation-guide/Backend-Application/Mitigate-Errors) for the others.
</Check>

## Learn more

* [Read Data](/implementation-guide/API-Calls/Read-Data)
* [Error Types](/api-reference/development-guides/errors/Error-Types)
* [Error Handling](/api-reference/development-guides/errors/Error-Handling)
* [Rate Limits](/api-reference/development-guides/Rate-Limits)


# Read Organization and Payroll Data
Source: https://developer.tryfinch.com/implementation-guide/API-Calls/Read-Data

In this guide, you'll learn how to read data from Finch's company, directory, individual, employment, payment, and pay statement API endpoints.

You can now make API requests to Finch's various endpoints, such as `/company`, `/directory`, `/individual`, `/employment`, `/payment`, and `/pay-statement`. These endpoints only allow the reading of data from employment providers; they do not permit the writing of data back to the system. Writing deductions and contributions back to the provider is covered in [Write Data](/implementation-guide/API-Calls/Write-Data) step.

These calls must be made from your backend using the access token obtained after Finch Connect — see [Backend Security](/implementation-guide/Backend-Application/Backend-Security) for why the access token should never be exposed to your frontend.

In this step, you will learn how to make API requests, handle responses, and manage request rate limits.

1. **Choose the appropriate Finch API endpoints**: Pick the endpoint(s) that match the data your application needs. See [Verify Product Scopes](/implementation-guide/Connect/Create-Account#verify-product-scopes) for what each product/endpoint returns, or [How Finch's API is organized](/how-finch-works/data-model) for the full data model.

2. **Batch your requests**: For endpoints that accept multiple IDs — `/individual`, `/employment`, `/pay-statement` — send all the IDs you need in a single call instead of one request per ID. This reduces the number of API calls your application makes and, as a result, helps you stay within your [rate limits](/api-reference/development-guides/Rate-Limits). See [Batch Requests](/implementation-guide/API-Calls/Batch-Requests) for the request and response format.

3. **Set up the HTTP request**: Use an HTTP library such as [Fetch](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch) or [Axios](https://axios-http.com/docs/intro) (or another suitable package) to create an HTTP request. Include the access token in the `Authorization` header using the format `Bearer <your_access_token>`. Make sure the HTTP request uses the appropriate method (GET, POST, etc.) and includes any required parameters.

   ```js theme={null}
   const url = 'https://api.tryfinch.com/employer/directory?entity_ids[]=64267987-6213-42d1-af2f-d2aa0614e222'; // Replace with the desired endpoint
   const accessToken = '<your_access_token>';

   fetch(url, {
     method: 'GET',
     headers: {
       'Authorization': `Bearer ${accessToken}`,
       'Content-Type': 'application/json',
     },
   })
   .then(response => response.json())
   .then(data => console.log(data))
   .catch(error => console.error('Error:', error));
   ```

   ```python theme={null}
   import requests

   def fetch_data_from_endpoint():
       url = 'https://api.tryfinch.com/employer/directory?entity_ids[]=64267987-6213-42d1-af2f-d2aa0614e222'
       access_token = '<your_access_token>'
       
       headers = {
           'Authorization': f'Bearer {access_token}',
           'Content-Type': 'application/json',
       }
       
       try:
           response = requests.get(url, headers=headers)
           response.raise_for_status()
           data = response.json()
           print(data)
       except requests.RequestException as error:
           print(f'Error: {error}')

   # Call the function to test
   # fetch_data_from_endpoint()
   ```

   ```java theme={null}
   import java.io.BufferedReader;
   import java.io.InputStreamReader;
   import java.net.HttpURLConnection;
   import java.net.URL;

   public class APIClient {

       private static final String ENDPOINT_URL = "https://api.tryfinch.com/employer/directory?entity_ids[]=64267987-6213-42d1-af2f-d2aa0614e222";
       private static final String ACCESS_TOKEN = "<your_access_token>";

       public static void main(String[] args) {
           fetchFromEndpoint();
       }

       public static void fetchFromEndpoint() {
           try {
               URL url = new URL(ENDPOINT_URL);
               HttpURLConnection connection = (HttpURLConnection) url.openConnection();
               connection.setRequestMethod("GET");
               connection.setRequestProperty("Authorization", "Bearer " + ACCESS_TOKEN);
               connection.setRequestProperty("Content-Type", "application/json");

               int responseCode = connection.getResponseCode();
               if (responseCode == HttpURLConnection.HTTP_OK) { // success
                   BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
                   String inputLine;
                   StringBuilder response = new StringBuilder();

                   while ((inputLine = in.readLine()) != null) {
                       response.append(inputLine);
                   }
                   in.close();
                   System.out.println(response.toString());
               } else {
                   System.out.println("GET request failed. Response code: " + responseCode);
               }
           } catch (Exception e) {
               System.out.println("Error: " + e.getMessage());
           }
       }
   }
   ```

4. **Include `entity_ids` query parameter in requests**: When using an access token associated with multiple entities, you must include the `entity_ids` query parameter in all API requests. If you do not provide the `entity_ids` query parameter, Finch will return the following error:

```
{
  "error": "entity_id_required",
  "message": "Multi-entity connection requires entity_ids query parameter when multiple entities exist"
}
```

Despite the plural name, the API currently accepts exactly one entity ID per request (`entity_ids[]=<entity_id>`) — to fetch data for multiple entities, make one request per entity.

5. **Handle API responses**: When Finch returns a response, parse the JSON data and extract the relevant information needed for your application. All API responses include a header that includes date the data was retrieved. See our Development Guide on [Headers](/api-reference/development-guides/Headers#response-headers) for more details. Store or display the data as needed for your application.

   ```json Example response theme={null}
   {
     "paging": {
       "count": 15,
       "offset": 0
     },
     "individuals": [
       {
         "id": "01220ee6-d32e-4973-8646-c5a197935535",
         "first_name": "Adrian",
         "middle_name": "Kylo",
         "last_name": "Baumbach",
         "manager": {
           "id": "c0e619df-77b7-481c-8669-210ba2af97ad"
         },
         "department": {
           "name": "Quality"
         },
         "is_active": true
       },
       ...
       {
         "id": "daac88bc-6ade-459b-9630-68ed7bac5ae9",
         "first_name": "Glen",
         "middle_name": "Beckham",
         "last_name": "Blanda",
         "manager": {
           "id": "94917285-773f-4e9f-9018-d919af77c997"
         },
         "department": {
           "name": "Quality"
         },
         "is_active": true
       }
     ]
   }
   ```

   The `id` values in a response (like the `individual` and `manager` IDs above) stay constant across access tokens generated via the same authentication method. If a connection has multiple access tokens from different authentication methods — for example, one from credentials and another from an API token — those IDs can differ between tokens, since Finch maps its IDs to the underlying employment system's own identifiers, which vary by authentication method.

   Responses can include `null` field values or, for some requests, a `202` status instead of the shape above. See [Handling API Responses](/api-reference/development-guides/Handling-API-Responses) for why these occur and how to handle each.

6. **Paginate `GET /directory` and `POST /pay-statement` responses**: `GET /directory` and each entry in a `POST /pay-statement` request return paginated results using `limit` and `offset`. Set `limit` explicitly — if you omit it, Finch returns only the default page size, not the full result set.

   | Endpoint                                 | Default `limit` | Max `limit` |
   | ---------------------------------------- | --------------- | ----------- |
   | `GET /directory`                         | 10,000          | 10,000      |
   | `POST /pay-statement` (per `payment_id`) | 5,000           | 5,000       |

   Loop on `offset`, adding the number of items received each time, until the response's `paging.count` shows there are no more records to fetch:

   ```js theme={null}
   async function fetchAllDirectory(accessToken) {
     const individuals = [];
     const limit = 10000;
     let offset = 0;

     while (true) {
       const url = `https://api.tryfinch.com/employer/directory?limit=${limit}&offset=${offset}`;
       const response = await fetch(url, {
         headers: { 'Authorization': `Bearer ${accessToken}` },
       });
       const data = await response.json();
       individuals.push(...data.individuals);

       if (data.individuals.length < limit) break;
       offset += limit;
     }

     return individuals;
   }
   ```

   A `limit` above the max returns a `422` with a `finch_code` of `page_size_limit_exceeded`. See [Mitigate Errors](/implementation-guide/Backend-Application/Mitigate-Errors#batch-and-page-size-limit-errors) for the error format.

7. **Handle errors and edge cases**: Finch returns `4XX` or `5XX` [error types](/api-reference/development-guides/errors/Error-Types) when a request fails, sometimes due to an unsupported response from the underlying employment system. See [Server errors](/implementation-guide/Backend-Application/Mitigate-Errors#server-errors) in Mitigate Errors for a retry-with-backoff implementation and when to contact support with the `Finch-Request-ID`.

8. **Handle 401 re-authentication errors**: A `401` response with a `finch_code` of `reauthenticate_user` means Finch lost access to the employer's provider and the employer must reauthenticate. See [Reauthentication errors](/implementation-guide/Backend-Application/Mitigate-Errors#reauthentication-errors) in Mitigate Errors for the full flow.

9. **Manage rate limits**: Finch enforces [rate limits](/api-reference/development-guides/Rate-Limits) per product on a rolling 60-second basis, for both applications and access tokens. Batching your requests (see step 2 above) is the main way to stay within these limits. If Finch returns a `429` HTTP status code, back off and retry — see [Rate limit errors](/implementation-guide/Backend-Application/Mitigate-Errors#rate-limit-errors) in Mitigate Errors for the full model and a retry implementation.

***

<Check>
  ### Checkpoint + Next Step

  After completing this step, your application will be able to interact with the Finch API endpoints, read the necessary data, and handle various error scenarios. If all you need is to read data, the next step is to [batch requests](/implementation-guide/API-Calls/Batch-Requests). If you need the ability to write data back to the provider, follow the [Write Data](/implementation-guide/API-Calls/Write-Data) step. Otherwise, you can move on to [Prepare the Employer Experience](/implementation-guide/Integration-Preparation/Manage-Integrations).
</Check>

## Learn more

* [Handling API Responses](/api-reference/development-guides/Handling-API-Responses)
* [Mitigate Errors](/implementation-guide/Backend-Application/Mitigate-Errors)
* [Monitor Usage](/implementation-guide/Backend-Application/Monitor-Usage)


# Write Deductions
Source: https://developer.tryfinch.com/implementation-guide/API-Calls/Write-Data

In this guide, you'll learn how to write deduction and contribution changes to Finch's deductions API endpoints.

<Tip>
  ## Quick Start Checklist

  1. ✓ Identify supported providers
  2. ✓ Get, register, or create company-level deduction to receive `benefit_id` and `job_id`
  3. ✓ **Wait for company-level deduction job to complete** (poll GET /jobs/manual/ or use webhook)
  4. ✓ **Call GET /jobs/manual/ to verify job succeeded** (check response body for errors)
  5. ✓ **If job failed, alert personnel and retry with corrections** (do NOT proceed to enrollments)
  6. ✓ Enroll individuals using verified `benefit_id` from successful job
  7. ✓ **Verify individual enrollment jobs succeeded** (call GET /jobs/manual/ for each enrollment job)
</Tip>

As with all Finch API calls, these requests must be made from your backend — see [Backend Security](/implementation-guide/Backend-Application/Backend-Security).

Our Deductions product allows developers to write payroll [contributions](/how-finch-works/unified-employment-api-glossary#contribution) and [deductions](/how-finch-works/unified-employment-api-glossary#deduction) changes for retirement, medical, and other benefit use cases.

Finch Deductions APIs operate at two levels: the **company-level** and the **individual-level**.

**Company-level** APIs allow you to create and update deductions at the company-level. For automated integrations you can also read company-level deductions.

**Individual-level** APIs allow you to enroll and un-enroll individuals in deductions, and update their individual-level configurations. For automated integrations you can also read individual-level enrollments.

## Identify Supported Providers

Before implementing our Deductions APIs, make sure you identify providers that support the types of deductions and features your use case requires.

### Assisted vs Automated Integrations Deductions Support

You can identify which providers are automated and assisted using our [Provider Network](/integrations/providers).

#### Automated Integrations

* Both **reading** *and* **writing** are supported.
* Writing is performed near-real-time in the provider.
* Reading provides state of the system when the request is executed.
* No configuration period.

#### Assisted Integrations

* Only **writing** is supported.
* See [Integration Types: Assisted](/integrations/integration-types#assisted) for the most up to date SLAs for configuration period and data syncs.

### Use the providers endpoint or field support matrix to identify provider that support your use case

The types and features of each deduction can vary between providers. Providers have varying limitations on which operations are available and which actions can be performed.

Finch provides two tools to help you identify the types and features of deductions available for a given provider.

1. **Providers Endpoint** - The [providers](/api-reference/management/providers) endpoint provides a list of all providers and the types of deductions they support.
2. **Field Support Matrix** - The [Field Support Matrix](/integrations/field-support) provides a list of all providers and the types of deductions they support, as well as the features available for each deduction type.

If you try to make a request using an access token that does not allow a certain configuration or deduction type, our API will respond with a 400 or 422 status code (see [Errors](/api-reference/development-guides/errors/Error-Types)), depending on the error. This endpoint can help you avoid those errors by understanding beforehand what types of requests you can make.

### Prepare for provider limitations when creating company level deductions

Some providers do not allow creation of company level deductions using the Finch API ([Create Deduction](/api-reference/deductions/create-deduction)). Use the providers endpoint or field support matrix explained above to identify providers that do not support this for deductions.
For those providers, you should confirm with the employer that the correct deduction is set up in their system prior to enrolling individuals through Finch. Then use the Register (assisted integrations) or Get All Deductions (automated integrations) endpoints to get the `deduction_id` for the company level deduction. Then you can enroll and update invidual level deductions.

If you try to enroll an employee in a deduction that is not set up, you may receive a `422` response code from Finch indicating that the deduction is not set up by the employer. In these cases, you should reach back out to the employer to ensure the deduction has been correctly set up.

## Verify successful deduction job completion using jobs endpoint

For all deduction write requests, both automated and assisted, call either  `GET /jobs/{job_id}` or the [retrieve a manual job endpoint](/api-reference/management/retrieve-a-manual-job) to check the job status and response body which will include a message with details about the cause of any errors.

## Getting and Creating Company Level Deductions

Before your application can manage individual enrollments and updates for individuals, your system needs the Finch `benefit_id` for the company wide deduction that the individual is or will be enrolled in.
The Finch Deduction API has three endpoints that return a `benefit_id` in the response body. For example, a creation request will respond with:

```json theme={null}
{
  "benefit_id": "e8b90071-0c11-471c-86e8-e303ef2f6782",
  "job_id": "be1b3351-a88e-46c2-96e4-c2cf38e529a7"
}
```

Your application will use this `benefit_id` to perform enrollment, un-enrollment, and deduction retrieval actions on individuals.

Your application can use the `job_id` and the [Retrieve a Manual Job](/api-reference/management/retrieve-a-manual-job) endpoint to get the status of the job. The valid job status responses will be either `pending`, `in_progress`, `complete`, or `error` with a response body further explaining the response.

**Create Deduction**, **Register Deduction**, and **Get All Deductions** are the endpoints that return a `benefit_id` to use for enrolling and updating individual deductions and contributions. Your application should use the appropriate endpoint based on if the connection is automated or assisted for deductions and if the deduction already exists in the provider system.

| Endpoint                                                           | Description                                                                           | Automated/Assited Support |
| ------------------------------------------------------------------ | ------------------------------------------------------------------------------------- | ------------------------- |
| [Get All Deductions](/api-reference/deductions/get-all-deductions) | Get all existing company-wide deductions and contributions                            | Automated Only            |
| [Register Deduction](/api-reference/deductions/register-deduction) | Register one existing company-wide deduction or contribution                          | Automated and Assisted    |
| [Create Deduction](/api-reference/deductions/create-deduction)     | Create a new company-wide deduction or contribution (not supported for all providers) | Automated and Assisted    |

<Warning>
  **CRITICAL: Always verify job SUCCESS before enrolling individuals**

  After receiving a `benefit_id` from Create Deduction or Register Deduction, you MUST verify the job completed successfully before making any enrollment requests with that `benefit_id`.

  **How to verify:**

  1. Wait for the job to complete by either:
     * Polling [GET /jobs/manual/](/api-reference/management/retrieve-a-manual-job) until `status` is `complete`, OR
     * Listening for the [job completion webhook](/developer-resources/Webhooks#job-completion)
  2. Once complete, call [GET /jobs/manual/](/api-reference/management/retrieve-a-manual-job) to check the response `body` for error codes and messages
  3. **If the job has an error, alert appropriate personnel and do not proceed with enrollments**

  **Why this matters:** A job status of `complete` does NOT mean success—it means the job finished processing. The job could complete with an error. If there was an error, the response body will contain details about what went wrong. You must correct the issue and submit a new request—Finch will not automatically retry failed jobs.

  If you enroll individuals using a `benefit_id` from a failed job, all enrollment requests will fail. Recovering from this scenario requires complex retry logic that most applications are not designed to handle.

  **Always call the jobs endpoint to verify success after completion.**
</Warning>

## Enrolling and Unenrolling Individuals

### Creating new individual enrollments

To enroll a new individual for a contribution or deduction, use the `benefit_id` returned from the appropriate deductions endpoints above, and make a request to [`POST /benefits/{benefit_id}/individuals`](/api-reference/deductions/enroll-individuals-in-deductions) request.
This is a batch request endpoint. In the request body, you should provide a list of objects. Each object will specify the `individual_id` (from the directory endpoint in Organization), and a `configuration` object which specifies the enrollment configuration to applies to that individual
Use the API Reference to identify which fields should be included in the object for specific types of deductions. Note that none are required by our API, but the provider may require specific fields and return an error if they are not included.

### Updating existing individual enrollments

To update the enrollment for currently enrolled individuals, use the same `POST /benefits/{benefit_id}/individuals` endpoint that you use to enroll new individuals. When updating an existing enrollment for an individual, the enrollment configuration will be completely overwritten with the new configuration provided in the request, so please make sure to include the entire desired configuration. Since they both use the same endpoint, these update requests can be submitted in the same batch request as new enrollment requests.

### Un-enrolling individuals

You can unenroll individuals by using the [`DELETE /benefits/{benefit_id}/individuals`](/api-reference/deductions/unenroll-individuals-from-deductions) endpoint. This will remove the enrollment configuration for an individual.

### Deduction Sequence Diagram

The following diagram shows the basic deductions flow. It can be used with either [Register](/api-reference/deductions/register-deduction) or [Create](/api-reference/deductions/create-deduction) endpoints to obtain the benefit\_id. The flow is very similar for use with the [Get All Deductions](/api-reference/deductions/get-all-deductions) (automated integrations only) except that your application will need to handle a response with multiple benefit objects (see the API reference for response fields and examples).

<img alt="deductions flow.png" />

## Handling Failures

Managing deductions and contributions is a time and money-sensitive activity. Therefore, in the unlikely event that a request through Finch fails, we recommend that your team have a process in place to handle enrollments or to inform employers. We recommend leaving adequate buffer between request submission via Finch and payroll cutoff dates to account for time to address issues. Our recommendation is that you submit a request with enough time to have at least 1 day between the response from Finch and the cutoff date. For an automated connection, that means submitting the request at least 24 hours before the cutoff. For an assisted connection, the recommended time is 3 days to account for the 2 day SLA.

Enrollment and un-enrollment requests and responses are batched. This means that some enrollments/un-enrollments could succeed while others fail. For both automated and assisted integrations expect a job\_id in the response body. You can use this job\_id to get the status of the job and see which individuals were successfully enrolled or un-enrolled.

```json title=Top-level status code: 200 theme={null}
{
  "job_id": "497d98f3-580a-4ab9-830a-af2346d029b2",
  "status": "complete",
  "body": [
    {
      "individual_id": "430f9d95-1dcf-4b99-b616-45f814416890",
      "code": 500,
      "message": "Internal server error"
    },
    {
      "individual_id": "647975ac-1e0f-4e9c-b705-e3042da48581",
      "code": 404,
      "message": "Individual not found"
    }
  ]
}
```

## General Deductions Schedule

Since enrolling individuals in deductions and contributions can be a sensitive activity, it is helpful to understand some of the nuances around payroll in general.

### How do payroll deductions work?

Each payroll contains four important dates to know.

1. **Payroll Start Date** - The first day of the pay period
2. **Payroll End Date** - The last day of the pay period
3. **Payroll Close Date** - The last date to make changes for that pay period
4. **Paycheck Date** - The date on which employees are paid

Note - You can get the payroll `start_date`, `end_date`, and the `pay_date` for past pay statements using our pay statement API, but our system cannnot provide the payroll close date. You will need to either get that information from the employer or set expectations for update based on their close date generically

### Timing submissions

It is important to submit any employee deductions and contribution changes before the pay close date in order to take affect for the current pay period. If any changes are submitted after the payroll close date, they will only affect the next pay period, not the current. Since each payroll close date is different per provider, it is important to know this date and set proper expectations with your customers.

For assisted connections, it is important to submit payroll deductions to our API 3 days before the customer's payroll close date. This will help ensure that changes can be processed within the current payroll period (unless an `effective_date` for a future payroll period is explicitly specified in your API request). Otherwise, the change will be executed on the next payroll period.

### Effective Date

The `effective_date` parameter allows you to control when deduction or contribution changes take effect in an employee's payroll. Use this parameter to schedule changes for an employee that will apply in future pay periods.

*Effective date is not supported for Justworks or QuickBooks. It is supported for all other providers where Deductions is enabled.*

#### How To Use Effective Dates

When you submit a deduction or contribution change with an `effective_date`, Finch processes your request within 2 business days of the specified effective date.

**Immediate Changes**

* Scenario: You need a change to take effect as soon as possible.
* How to do it: Don't specify any `effective_date` parameter.
* What happens
  * Finch submits the change to the payroll provider immediately for Automated providers, or within the 2 day SLA for Assisted providers.
  * The change should be reflected in the current or next pay period, depending on the provider's payroll cutoff date

**Example**

```json title=Top-level status code: 200 theme={null}
{
  "amount": 500,
  "type": "401k"
  // No effective_date specified
}
```

**Scheduled Changes**

* Scenario: You want a change to begin on a specific date.
* How to do it: Set `effective_date` to a date more than 2 business days in the future.
* What happens
  * Finch schedules the change and submits it to the payroll provider on or up to 1 business day before your specified date.
  * The change will be included in the pay period containing your effective\_date. If that pay period has already closed by the time Finch submits the change, it will apply to the next available pay period instead.
  * Your job will show a `pending` status until Finch submits it.

**Example**

```json title=Top-level status code: 200 theme={null}
{
  "amount": 300,
  "type": "401k",
  "effective_date": "2026-02-15"
}
```

**Scheduling Limits**

* Effective dates in the past or within the next 2 business days will be processed immediately for Automated providers and within the 2 day SLA for Assisted providers.
* There is no hard limit on how far in the future you can schedule changes, but we recommend scheduling changes no more than 90 days in advance. The job will be stay in `pending` for this duration.

**Batch Requests with Effective Dates**

You can include an effective date when submitting multiple deduction or contribution changes in a single batch request. Note that the entire batch should have the same effective date.

When all updates in a batch share the same effective date:

* All changes are processed together as a group
* They follow the same timing rules as single requests:
  * Historical dates: Submitted immediately
  * Future dates: Scheduled and submitted on or shortly before the effective date
  * No date: Submitted immediately

#### Tracking Request Status

**Monitoring Scheduled Changes**

Use the job status endpoint to check on scheduled changes:

```json title=Top-level status code: 200 theme={null}
GET /api/jobs/{job_id}
```

#### Understanding Request States

When you submit a change with a future effective date, you can check the status of that change via the manual job status endpoint:

1. `pending`: The change is scheduled but not yet submitted to the provider
2. `in_progress`: Finch is submitting the change to the provider
3. `complete`: The change has been successfully submitted into the payroll system
4. `error`: Something went wrong (see error details for resolution steps)

For batch requests, ensure that all individuals in the batch have been processed successfully. Submit another request for any individuals that were not successful.

#### Cancel or Modify a Request

Requests will remain in `pending` status until submitted to the provider. You can use the update or cancel endpoints to modify scheduled changes as long as the request is still pending.

**Example**

As an example, if the payroll period is **June 1 - 15**. The payroll close date might be <span>June 16</span> so payroll can be processed before <span>Tuesday, June 17</span>.  Therefore, it would be important to submit payroll deductions via the Finch API by <span>June 11</span> for those to take effect during the **June 1 - 15** payroll.

<pre>
  June 2022
  Su Mo Tu We Th Fr Sa
  <mark>01 02 03 04 05 06 07
  08 09 10</mark> <mark>11</mark> <mark>12 13 14
  15</mark> <mark>16</mark> <mark>17</mark> 18 19 20 21
  22 23 24 25 26 27 28
  29 30
</pre>

Some payroll providers offer a dedicated payroll representative to help with making payroll changes. If a payroll rep is helping your customer's HR admin with changes in their system, it is important that you make it explicitly clear who does what so that the payroll rep does not overwrite any changes Finch has previously made. Calling out Benefit Code types and using thoughtful descriptions (e.g. with your company name) help.

**Best Practices**

Do:

* **Use future effective dates for planned changes** like new hire benefits or scheduled contribution increases
* **Omit effective\_date for urgent changes** that should apply as soon as possible
* **Allow at least 2 business days lead time** when scheduling future changes
* **Monitor job status** for scheduled requests to ensure they're processed on time
* **Check provider-specific behavior** if you need precise timing guarantees

Don't:

* **Rely on retroactive processing** for past effective dates - most providers don't support this
* **Specify effective dates within 2 business days** if you need a guaranteed future date (they'll be processed immediately)
* **Assume immediate application** even without an effective date - payroll cutoff dates may delay application to the next period
* **Create a batch request with different effective dates**

## FAQs

**Question** Are all deductions requests processed First In First Out (FIFO)?

**Answer** If requests do not include an `effective_date`, the requests are processed in the order they are received. If you submit multiple requests for the same individual the last request processed will overwrite any previous requests.

For requests that include an `effective_date`, those enroll requests will be processed on the future `effective_date` rather than the order in which they are received.

**Question** What happens if I submit an enroll request for an individual who is already enrolled in a deduction?

**Answer** If you submit an enroll request for an individual who is already enrolled in a deduction, the existing enrollment will be updated with the new configuration provided in the request. The status of the request will be a 200 instead of a 201.

**Question** How does including an `effective_date` affect when the request is processed? For example, if for the same individual we submit multiple requests with different effective dates, will the requests still be processed in the order they are received or by `effective_date`?

**Answer** The `effective_date` parameter determines when the request is processed in the provider system. The request will be processed on the `effective_date`, which must be in the future. Requests should be batched by `effective_date`, and the order of processing will be based on the `effective_date` rather than the order in which they are received. If you submit multiple requests with different `effective_date`s for the same individual, the last request with the latest `effective_date` will overwrite any previous requests.

**Question** Is the `effective_date` that is included in the request, the date that is input into the provider's system?

**Answer** For *assisted integrations* The `effective_date` that is submitted will be entered into the provider system if the provider has the capabilities to ingest a future effective date and the date is within the allowed range. In case the provider does not have this capability, we will apply the change on the effective date. Note that `effective_date` is not supported across all providers, some do not accept past effective dates, and some have a limited future window for dates.

For *automated integrations*, we apply the changes on the effective date and do not enter an effective date into the provider system.

You can expect that the enrollment will be effective for the pay period that the request is processed if it is processed before the close date of that pay period. Include an `effective_date` in a future pay period if you want the enrollment to be effective for that pay period.

### Why Job Verification Matters

When you create or register a company-level deduction, Finch returns both a `benefit_id` and a `job_id` immediately. However, this does not mean the deduction has been successfully created in the provider system yet. The job may still be processing (`pending` or `in_progress` status), or it could complete with an error.

**Understanding Job Status:** A critical distinction exists between job completion and job success:

* `status: complete` means the job finished processing—it does NOT guarantee success
* You must call [GET /jobs/manual/](/api-reference/management/retrieve-a-manual-job) and inspect the response `body` for error `code` and `message` fields to determine if the job actually succeeded
* Common failure scenarios include: provider validation errors, missing required fields, duplicate deductions, or provider system issues

**Determining When to Check:** You have two options for knowing when to check the job status:

* **Polling:** Repeatedly call GET /jobs/manual/ until `status` changes to `complete`, then examine the response body. This is not recommended. If you opt to use the approach we recommend polling every 1 hour for automated integrations and once per day for assisted integrations.
* **Webhooks:** RECOMMENDED Subscribe to the [job completion webhook event job.benefit\_\*.completed](/developer-resources/Webhooks#job-completion) to be notified when the job completes, then call GET /jobs/manual/ to examine the response body

**Both approaches require calling the jobs endpoint** to verify success and retrieve error details. The webhook simply eliminates the need to poll repeatedly.

**The Problem:** If you use the `benefit_id` to enroll individuals before confirming the company-level deduction job succeeded, you're submitting enrollment requests for a deduction that may not exist or may have failed to create. These enrollment attempts will be queued as jobs, but they will all fail because the underlying `benefit_id` is invalid.

**Handling Failures:** If the company-level deduction register or create job completes with an error:

1. Review the `code` and `message` in the response body to understand what went wrong
2. **Alert appropriate personnel** (e.g., log the error, notify your support team, or surface the error to the user) so the issue can be addressed promptly
3. Correct the issue in your request (e.g., fix validation errors, adjust deduction configuration)
4. Submit a new Create Deduction or Register Deduction request
5. **Finch will not automatically retry failed jobs—you must handle retries in your application**

**Important:** Do not silently fail. Many developers discover job failures only after attempting enrollments and wondering why nothing worked. Implement proper error handling and alerting when company-level deduction jobs fail.

**Why This Is Complex to Fix After the Fact:** Once you've sent 50+ enrollment requests based on a failed `benefit_id`, you must:

1. Detect that the original deduction creation failed (by finally checking the job body)
2. Retry creating the company-level deduction with corrections based on the error message
3. Track which individual enrollments failed
4. Retry all failed enrollments with the new `benefit_id`
5. Handle any individuals whose status may have changed during this process

Most applications are not designed to queue and retry batch operations in this way, leading to incomplete enrollments and data inconsistencies.

**The Solution:** Always verify job success before proceeding with individual enrollments by calling [GET /jobs/manual/](/api-reference/management/retrieve-a-manual-job) after the job completes. This simple check prevents cascading failures and ensures your enrollments are based on valid deductions.

<Check>
  ### Checkpoint + Next Step

  After completing this step, you will have a good understanding of how to utilize the Finch Deductions API to manage company-level deductions and employee-level enrollments in a robust manner accommodating various provider limitations. Now that you have everything in place for full 360° read/write integrations, you can [Prepare the Employer Experience](/implementation-guide/Integration-Preparation/Manage-Integrations).
</Check>

## Learn more

* [Deductions API](/products/deductions/Overview)
* [Supported Providers](/integrations/providers)
* [Integration Types: Assisted](/integrations/integration-types#assisted)


# Backend Security
Source: https://developer.tryfinch.com/implementation-guide/Backend-Application/Backend-Security

Finch takes security seriously, so we require a backend server to manage all requests and responses to and from Finch APIs. Once the connection has been created via Finch Connect, you can obtain an `access_token` which will be used to call the Finch APIs. We offer several [backend SDKs](/developer-resources/SDKs#backend-sdks) to make the backend integration smoother.

We require a backend for several reasons:

1. Since the data from payroll providers is sensitive, making API requests from the backend and storing that data on the backend reduces the likelihood of this data being exposed to malicious persons.
2. Exchanging the authorization `code` for an `access_token` should always take place in your backend to ensure your `client_secret` and `access_token` are never publicly exposed.
3. Likewise, your backend should always [store the access token](/implementation-guide/Backend-Application/Store-Tokens) in a secure database and should never return the access token to the frontend application.


# Control Access (Optional)
Source: https://developer.tryfinch.com/implementation-guide/Backend-Application/Control-Access

Learn how to control data access within multi-tenancy applications through role-based access control (RBAC) or other authorization methods.

If you have [set up a connection properly](/implementation-guide/Backend-Application/Manage-Connections) and [retrieved data from Finch APIs](/implementation-guide/API-Calls/Read-Data), you may also want to confirm that you are only displaying or processing data relevant to the authenticated user. While this is optional, it's recommended to avoid mixing up data from different customers or employers.

For instance, only fetching specific customer data using *their* access token, then only displaying *their* data on *their* account dashboard.

If your application is deployed individually per customer (often called **single-tenancy**), there is natural isolation of employer data since each tenant is on a separate instance running on its own set of servers, databases, and other infrastructure.

However, if your application serves multiple customers in a single instance (often called **multi-tenancy**), each employer's data should remain isolated from other employers either through authorization, database partitioning, separate schemas, or other techniques.

## Application authorization

In order to control user's access to the right data, you can apply **role-based access control (RBAC)** or another authorization permission systems in your application. We will specifically focus on multi-employer RBAC authorization.

Multi-employer RBAC involves 4 core elements:

* **Users**: A user is an individual who is trying to access their employment data which they granted you access to via Finch Connect. A `user` is assigned `roles`, which in turn grant them the `permissions` they need to access resources. In a multi-employer RBAC, users typically belong to a particular `employer` and their permissions and roles are scoped to that employer. A user in one employer should not, by default, have any permissions or roles in another employer unless explicitly granted.
* **Roles** - A role is a collection of permissions that define the actions a user can perform in your application. A role is assigned to a user, and a user can have multiple roles. In a multi-employer environment, roles are typically scoped to a particular employer so that an "Admin" role in Employer A might have different permissions than an "Admin" role in Employer B.
* **Permissions** - A permission is a right to perform a specific action or access a specific resource in your application. Permissions are assigned to roles. In a multi-employer context, permissions should be defined in a way that they are also scoped to specific employers. This ensures that granting a permission in one employer doesn't inadvertently grant access to resources in another employer.
* **Employers**: An employer is the foundational element of multi-employer scenarios. Each employer represents an isolated unit or environment in your application, like a separate company or organization. Your application must be able to separate and manage data, configurations, and roles for each employer independently, ensuring there's no overlap or unintended sharing.

The RBAC system follows a simple logic: A user requests access to a resource, and the system checks if the user has the necessary permissions to access that resource based on the roles assigned to them.

> ### Cross-Employer Authorization
>
> There may be scenarios where a user needs access across multiple employers (maybe they manage multiple employers for a PEO, or Professional Employer Organization. In such cases, your RBAC authorization system must support cross-employer roles and permissions without compromising the security or isolation of individual employers.

Building upon the database tables `customers` & `finch_connections` defined in the [Manage Connections](/implementation-guide/Backend-Application/Manage-Connections) guide, in order to implement multi-employer RBAC, we need a few additional tables.

* `customers`: Represents the "entities" who use your system.
* `finch_connections`: Represents the different connections (i.e. employers) a customer might have in your system.
* `users`: Represents individual users within a particular employer. Each user is associated with a specific connection, which defines the context of their roles and permissions.
* `roles`: Represents different roles that can be assigned to users within an employer. Each role is associated with a particular connection, signifying the context in which the role exists.
* `permissions`: Represents the different actions or operations that can be performed within your system. Permissions are not directly linked to a connection as permissions are typically more generic and can be used across multiple connections.
* `role_permissions`: A junction (or associative) table that establishes a many-to-many relationship between roles and permissions. Allows you to assign multiple permissions to a single role and vice versa.
* `user_roles`: Another junction table, but this one links users and roles. It determines which roles are assigned to a user in the context of a connection. Each combination signifies the roles a user has within a particular connection, which in turn dictates what actions they can perform with their employment data.

Once the database is set up, to implement data access controls, you can use a combination of JOIN statements in your SQL queries to enforce access restrictions based on the user's role or permissions.

At a minimum, your application should have an `Admin` role since it is the employer's HR & Payroll admin who should only have the permissions to go through Finch Connect and establish a connection with their employment system. Since a regular employee does not have the permissions to see the whole company-wide details or payroll, they should not be shown the option to connect via Finch.

<Info>
  ## Reminder

  SQL queries via JOIN statements are only one way of implementing multi-employer role-based access control. There are many ways to implement access control that allow more fine-grained authorization or robust permissioning. Choose the best option for your application's needs.
</Info>

Wether you choose to maintain separate environments for each employer or a shared instance with secure access control, being able to minimize the risk of unauthorized data access or mixing up data from different customers or employers is highly valuable.

***

## Checkpoint + Next Step

<Check>
  After completing this step, you should be familiar with the database techniques necessary to effectively track the relationship between user accounts and access tokens and implement data access controls based on user roles or permissions. You are now ready to [Manage Connections](/implementation-guide/Backend-Application/Manage-Connections).
</Check>

## Learn more

* [Manage Connections](/implementation-guide/Backend-Application/Manage-Connections)
* [Reconcile Employees](/developer-resources/Reconcile-Employees)


# Disconnect Connections
Source: https://developer.tryfinch.com/implementation-guide/Backend-Application/Disconnect-Connections

Learn how to disconnect an entire connection or remove specific entities from a connection.

A connection exists once an access token is obtained and [stored securely](/implementation-guide/Backend-Application/Store-Tokens). A connection may include one or more entities — for example, separate legal entities or divisions managed by the same employer within the same payroll system. (For more on how connections and entities relate, see [Manage Connections](https://developer.tryfinch.com/implementation-guide/Backend-Application/Manage-Connections).

Like all Finch API calls, disconnecting a connection must be done from your backend — see [Backend Security](/implementation-guide/Backend-Application/Backend-Security) for why the access token this requires should never reach the frontend.

Finch provides two endpoints depending on whether you need to disconnect an entire connection or just certain entities within it.

## Disconnect an Entire Connection

Calling the [`/disconnect`](https://developer.tryfinch.com/api-reference/management/disconnect) endpoint will disconnect all entities associated with the connection tied to the provided access token. Once disconnected, the connection is permanently terminated and the access token is revoked.

Use this when you intend to stop syncing data for an employer entirely.

## Disconnect Specific Entities

If a connection includes multiple entities, you can remove specific entities without affecting the rest of the connection by calling [`/disconnect-entity`](https://developer.tryfinch.com/api-reference/management/disconnect-entity) with the `entity_ids` you want to remove in the request body. All other entities remain active and the access token stays valid.

Use this when an employer connected an entity by mistake, or when your application needs to stop syncing a particular entity while continuing to operate normally for others under the same connection.

An `account.updated` webhook will fire for each disconnected entity. If you disconnect multiple entities in one call, you'll receive a separate webhook per entity.

## Choosing Between /disconnect and /disconnect-entity

|                     | `/disconnect`                                                                                              | `/disconnect-entity`                                                                                                         |
| ------------------- | ---------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------- |
| **Scope**           | Disconnects the entire connection and all entities                                                         | Disconnects only the specified entities; others remain active                                                                |
| **Required input**  | Access token only                                                                                          | Access token + `entity_ids`                                                                                                  |
| **Reversibility**   | If you disconnect an entity you did not intend to, a new connect session must be created                   | If you disconnect an entity you did not intend to, a re-auth session can be used to add the entity(s) back to the connection |
| **Employer impact** | The employer will then need to establish a new connection and select the desired entities in Finch Connect | Employer re-authenticates to add the entity back to the existing connection in Finch Connect                                 |

If your intent is to disconnect every entity under a connection, use /disconnect directly rather than calling /disconnect-entity for each one.

## Best Practices

### Before You Disconnect

**Choose the right endpoint.** Use `/disconnect` to fully offboard an employer. Use `/disconnect-entity` to remove specific entities from a multi-entity connection while preserving the rest.

**Disconnect before deleting tokens.** `/disconnect` requires the access token. Always call it before you discard the token from your system.

### Understanding Disconnect Behavior

**Billing.** Billing is based on unique `connection_id`s — simply ceasing API calls does not stop billing. Only `/disconnect` removes a connection from billing. (`/disconnect-entity` does not, unless you remove every entity, but `/disconnect` is simpler if that's your intent.)

**No reconnect endpoint.** Once a connection is fully disconnected via `/disconnect`, it cannot be reactivated. The employer must go through Finch Connect again, creating a new `connection_id` and a new billable connection.

**Only disconnect when you mean it.** A connection in `reauth` status is not a disconnect — prompt the employer to reauthenticate instead. Only call `/disconnect` or `/disconnect-entity` when you're confident you no longer need the data. If you do disconnect an entity by mistake, the employer can re-add it via a reauth session. (Note: reauth lets employers *add* entities but not *remove* them — removal requires `/disconnect-entity`.)

**Update your database after a successful `/disconnect-entity` call.** When you receive a `200` response from `/disconnect-entity`, remove the corresponding `entity_id`(s) from your database. If you retain disconnected `entity_id`(s) and continue making data requests with them, those requests will fail with an invalid `entity_id` error.

**Updated entity arrays in API responses.** After disconnecting one or more entities, any subsequent call to `/auth-token` performed during re-authentication will only return the entities that are still actively connected. Disconnected entities will no longer appear in the response. If you need the historical context of every entity that was every linked to a connection, use the `/introspect` endpoint. This will return both actively connected and disconnected entities.

**Viewing disconnected entities via `/introspect`.** You can always use the `introspect` endpoint to see a full history of entities that have ever been associated with a connection -- including those that have since been disconnected. Each entity in the `entities` object will include an individual `status` field indicating its current status.

***

## Checkpoint + Next Step

<Check>
  After completing this step, you should understand when to use `/disconnect` vs. `/disconnect-entity` and what happens to connections and entities in each case. Your application should give customers the ability to disconnect their connection (or specific entities), calling the appropriate Finch endpoint from your backend.
  Next, learn how to [control user access](/implementation-guide/Backend-Application/Control-Access). If you plan on presenting the data back to the employer via a User Interface, it is crucial to control user access properly to ensure employment data is only viewable by the correct customer account.
</Check>

## Learn more

* [Disconnect Endpoint](/api-reference/management/disconnect)
* [Disconnect Entity Endpoint](/api-reference/management/disconnect-entity)
* [Manage Connections](/implementation-guide/Backend-Application/Manage-Connections)
* [Control Access (Optional)](/implementation-guide/Backend-Application/Control-Access)


# Manage Connections
Source: https://developer.tryfinch.com/implementation-guide/Backend-Application/Manage-Connections

In this guide, you’ll learn how to define and manage multi-account, multi-provider, and multi-entity connections based on your customers’ needs.

Every [access token obtained](/implementation-guide/Connect/Retrieve-Access-Token) is associated with a connection. Therefore, to prevent mixing up data across different users or employers, it is important to make sure you associate each access token with the correct connections in your application. Implementing a system to track the relationship between your customers and their corresponding access tokens is recommended.

Like all Finch API calls, this happens from your backend — see [Backend Security](/implementation-guide/Backend-Application/Backend-Security) for why access tokens should never reach the frontend.

## Define connections

Finch defines a connection using a `connection_id`. A connection exists once an access token is obtained.

There are a couple scenarios to keep in mind when thinking about connections:

1. **Multi-Provider** <br />
   Employers may be using multiple payroll systems to manage employees within their company. For example, an employer may use Payroll Provider A to manage foreign contractors, and Payroll Provider B to manage US-based employees. The employer can only connect one provider in one Finch Connect session; a connection is created for each connected provider. Even though the employer is connecting the same company, Finch will create multiple connections because the underlying `provider_id` is different for each connection.
2. **Multi-Entity** <br />
   An employer’s payroll system may consist of one or many entities. An entity is a grouping of employees within a payroll system (e.g.: divisions, EINs). Employers have the ability to select one or multiple entities to connect at once. If an employer selects multiple entities, Finch will create a single connection with one `connection_id` and access token.

## Isolate connections

Given these scenarios, your application must be able to manage multiple connections per customer and keep each connection and its corresponding access tokens isolated from the rest.

You should store access tokens in your system using the `connection_id`.

* `provider_id` = the payroll provider associated with the access token.
* `customer_id` = a unique identifier that you create to manage your customers internally

> You define the `customer_id`; Finch defines the `connection_id` (more on this below).

### Introspect endpoint

The best way to retrieve the unique ids associated with an access token is by calling the [Introspect](/api-reference/management/introspect) endpoint. It will return a JSON body containing account information associated with the `access_token`.

```json Example /introspect response theme={null}
{
  "account_id": "d8ef1814-5913-492f-b5c0-a16e2d6432c9",
  "client_id": "25ea8bd8-f76b-41f9-96e3-1e6162021c50",
  "connection_id": "6dab009c-77c8-43d9-8f81-e093f7c65bc1",
  "company_id": "87eb4bc3-f76b-35e7-78d2-8f7822021d73",
  "payroll_provider_id": "gusto",
  "products": [...],
  ...
}
```

### Example

A simple example is a `1:1` connection association. It can be represented by a single database table with columns for `customer_id` and the associated `access_token`. You can use a unique constraint on the `customer_id` column to ensure that each user can have only one associated `access_token`.

<img alt="1-To-1 Database Schema" />

However, in production, you will want to handle the more [complex connection scenarios](#define-connections) above which have a `1:Many` relationship.

This can be represented by two database tables: the *Customers* table one stores the `customer_id` and the *Connections* table stores the `connection_id` which references back to a `customer_id`.

<img alt="1-To-Many Database Schema" />

In this realistic example:

* `connection_id` represents the unique finch variables that define a connection.
* A “composite unique constraint” can be set on `connection_id`  values which means that while each of these connections can contain the same values individually, the combination of these values must be unique (hence a unique connection).

Now, when you insert data into the *Connections* table, you'll need to ensure that the `connection_id` is unique for each row, while the `access_token` inherently remains unique for each row as well. The `connection_id` (when combined with data from the Finch [/company](/api-reference/organization/company) endpoint) is going to be able to tell you which employers are attached to each customer.

## Enabling multiple connections with Finch Connect

To have your customer create multiple connections in your application, your "onboarding" flow or "connections" page must allow them to go through [Finch Connect](/implementation-guide/Connect/Set-Up-Finch-Connect) multiple times.

Below is an example User Interface. You can present your customers with a page showing all of their current connections and provide the option to connect more accounts, providers, or company entities.

<img alt="" />

## Edge cases

### Reauthentication

In [reauthentication](/developer-resources/Reauthentication) situations, your customer should be prompted to reconnect their provider again before continuing to use the application. When the Finch Connect flow is completed, a new access token will be generated. Simply replace the old token with the new token and start making Finch API requests with the updated token like before.

### Repeating employees

In the [multi-provider or multi-company](#define-connections) scenarios, if your application is combining data across multiple access tokens, you may need to [reconcile employees](/developer-resources/Reconcile-Employees) between responses in order to merge employee data properly.

***

## Checkpoint + Next Step

<Check>
  After completing this step, you should know how to associate access tokens with multiple accounts for each new connection. With proper connection organization, you are ready to use the access token to [make API requests](/implementation-guide/API-Calls/Read-Data) to Finch's various endpoints.
</Check>

## Learn more

* [Control User Access](/implementation-guide/Backend-Application/Control-Access)
* [Set Up Finch Connect](/implementation-guide/Connect/Set-Up-Finch-Connect)
* [Reauthenticating Connections](/developer-resources/Reauthentication)
* [Reconcile Employees](/developer-resources/Reconcile-Employees)
* [Integration Types: Automated](/integrations/integration-types#automated)


# Mitigate Errors
Source: https://developer.tryfinch.com/implementation-guide/Backend-Application/Mitigate-Errors

Identify and handle Finch API responses and errors — null values, 202 responses, server errors, reauthentication errors, and rate limit errors — with mitigation steps for each.

This guide covers the responses and errors developers most frequently encounter with the Finch API. Null values and 202 responses are expected parts of a normal response — but your application can misbehave if it doesn't handle them. Server errors, reauthentication errors, and rate limit errors are true error conditions Finch returns when something goes wrong. Your application should expect and handle the [error types](/api-reference/development-guides/errors/Error-Types) documented in the API reference.

## Null values

A `null` value isn't an error — it's an expected response value. See [Null Values](/api-reference/development-guides/Handling-API-Responses#null-values) for why Finch returns `null` and how to check for it.

## 202 responses

A `202` response isn't an error either — it means the connection exists but data isn't available yet. See [202 Response Codes](/api-reference/development-guides/Handling-API-Responses#202-response-codes) for the retry and backoff behavior your application should implement, or [Testing assisted integrations](/implementation-guide/Test/Finch-Sandbox#testing-assisted-integrations) to reproduce a `202` response in the Finch Sandbox.

## Server errors

Server errors (`HTTP 500`) are uncommon but possible. A few error-handling mechanisms help you maintain a good user experience while diagnosing the issue:

* **Friendly error page.** Display a user-friendly message instead of the raw server error to maintain user trust.
* **Log the error.** Capture the error message, stack trace, request details, and other relevant context. Always log the `finch-request-id` from the HTTP response headers — Finch needs it to diagnose the issue on our side.
* **Health checks.** Call the [/introspect](/api-reference/management/introspect) endpoint on a regular basis to monitor the status of your Finch integration and its connections — this helps you identify the source of `500` errors faster.
* **Retry.** Retry the request after a delay, or adjust the request parameters — this resolves many transient server errors.

<Warning>
  **Product outages.** Finch reports all API outages and provider integration incidents at [status.tryfinch.com](https://status.tryfinch.com) — subscribe there for email notifications when Finch creates, updates, or resolves an incident.
</Warning>

If a server error persists, contact [Finch Support](/implementation-guide/Deploy-and-Manage/Support) and attach the `finch-request-id` from the response headers.

### Retry example

Finch may also return `4XX` or `5XX` [error types](/api-reference/development-guides/errors/Error-Types) due to unsupported responses from the underlying employment system. Retrying immediately may not resolve the issue — the following example retries a failed request with a fixed delay:

```jsx Error handling example theme={null}
function fetchDataWithRetry(url, options, retries = 3, delay = 2000) {
  return fetch(url, options)
    .then(response => {
      if (response.status === 500 && retries > 0) {
        return new Promise(resolve => setTimeout(resolve, delay))
          .then(() => fetchDataWithRetry(url, options, retries - 1, delay));
      } else {
        return response;
      }
    })
    .catch(error => console.error('Error:', error));
}

fetchDataWithRetry(url, {
  method: 'GET',
  headers: {
    'Authorization': `Bearer ${accessToken}`,
    'Content-Type': 'application/json',
  },
})
.then(response => response.json())
.then(data => console.log(data));
```

## Reauthentication errors

A reauthentication error means the credentials Finch uses to access an employer's provider system no longer work, and the employer must reauthenticate. This returns an HTTP status code of `401 Unauthorized` with a `finch_code` of `reauthenticate_user` (see [Finch API errors](/api-reference/development-guides/errors/Error-Types)).

To handle this error:

1. Catch `401` responses with a `finch_code` of `reauthenticate_user` in your Finch API error handling.
2. Create a new Finch Connect session for the connection using the [`/connect/sessions/reauthenticate`](/api-reference/connect/reauthenticate-session) endpoint, passing the connection's `connection_id`. If your application doesn't already store the `connection_id`, retrieve it by calling [/introspect](/api-reference/management/introspect) with the connection's `access_token`.
3. Direct the employer to complete Finch Connect through your existing flow — for example, prompt them to log in to your application dashboard, or send them a link to reauthenticate.
4. Exchange the resulting authorization code for a new access token — this is the same [access token exchange](/implementation-guide/Connect/Retrieve-Access-Token) used during initial setup.

See [Reauthentication](/developer-resources/Reauthentication) for what causes this error and how to handle multi-entity connections, employee permissions, and product scopes when reauthenticating.

## Batch and page size limit errors

Finch enforces a maximum batch size on `POST /individual`, `POST /employment`, and `POST /pay-statement`, and a maximum page size on `GET /directory` and `POST /pay-statement`. See [Batch Requests](/implementation-guide/API-Calls/Batch-Requests) for batch size limits and [Read Data](/implementation-guide/API-Calls/Read-Data) for page size limits and the pagination pattern.

### Batch limit errors

A request with more items than an endpoint's max batch size returns a `422` with a `finch_code` of `batch_limit_exceeded`:

```json theme={null}
{
  "code": 422,
  "name": "unprocessable_entity_error",
  "finch_code": "batch_limit_exceeded",
  "message": "Batch size exceeds the maximum of 10000 items. Please reduce the number of items in your request."
}
```

Split the request into smaller batches. Retrying the same request without changing it fails again — this isn't a rate limit, so a backoff-and-retry strategy won't resolve it.

### Page size limit errors

A `limit` above an endpoint's max page size returns a `422` with a `finch_code` of `page_size_limit_exceeded`:

```json theme={null}
{
  "code": 422,
  "name": "unprocessable_entity_error",
  "finch_code": "page_size_limit_exceeded",
  "message": "Page size exceeds the maximum of 10000 items. Please reduce the limit parameter."
}
```

Lower `limit` to the endpoint's max and paginate with `offset` to retrieve the remaining records.

<Warning>
  If your application omits `limit` entirely, `GET /directory` and `POST /pay-statement` return a default page size rather than every record, and no error is returned. Set `limit` explicitly and paginate with `offset` — see [Read Data](/implementation-guide/API-Calls/Read-Data) — otherwise your application will silently process incomplete data.
</Warning>

## Rate limit errors

Finch returns a rate limit error with the HTTP status code `429 Too Many Requests` when an application or IP address exceeds its request limit. Review the API [rate limits](/api-reference/development-guides/Rate-Limits) before continuing.

Finch's [rate limits](/api-reference/development-guides/Rate-Limits) work on a per-endpoint basis for applications. Finch calls each distinct endpoint a unique product, and sums rate limits on a rolling 60-second basis per product — commonly called a sliding or rolling window rate limit.

Think of each product's rate limit as a bucket. Every request to a product (which maps to an API endpoint) adds a gallon of water to that endpoint's bucket and starts a 60-second time-to-live (TTL) timer. When the bucket empties after 60 seconds, the next request restarts the TTL.

Stay within these [rate limits](/api-reference/development-guides/Rate-Limits) to avoid request failures. If you hit a rate limit error, implement a [back-off and retry strategy](#rate-limit-example): wait 60 seconds for the bucket to reset, then retry, increasing the wait time exponentially on repeated failures.

### Batch requests

[Batch requests](/implementation-guide/API-Calls/Batch-Requests) instead of calling an endpoint once per ID, to reduce your request count and avoid exhausting your rate limit.

### Rate Limit Scenario

This scenario shows how an application encounters application-level [rate limits](/api-reference/development-guides/Rate-Limits). Assume your application has five access tokens (Token A–E) making requests to the `company`, `directory`, `individual`, `employment`, `payment`, and `pay-statement` endpoints.

Each request to an endpoint adds a gallon of water to that product's application-level bucket. The bucket counts requests across all of the application's access tokens (Token A–E).

Organization endpoints have a [capacity](/api-reference/development-guides/Rate-Limits) of 20 max requests per minute. Pay endpoints have a [capacity](/api-reference/development-guides/Rate-Limits) of 12 max requests per minute.

<Warning>Each step below happens within the same 60-second (1-minute) time window.</Warning>

1. Token A makes 5 requests to [/company](/api-reference/organization/company), 4 to [/directory](/api-reference/organization/directory), and 3 to [/payment](/api-reference/payroll/payment) within a minute. Each bucket is below its capacity, so all of Token A's requests succeed.
   * Application-level rate limits
     | Bucket          | Capacity       |
     | --------------- | -------------- |
     | `company`       | 5/20 - success |
     | `directory`     | 4/20 - success |
     | `individual`    | 0/20           |
     | `employment`    | 0/20           |
     | `payment`       | 3/12 - success |
     | `pay-statement` | 0/12           |
2. Token B makes 5 more requests to [/company](/api-reference/organization/company), 4 to [/directory](/api-reference/organization/directory), and 3 to [/payment](/api-reference/payroll/payment) within the same minute. Each bucket is still below capacity, so all of Token B's requests succeed.
   * Application-level rate limits
     | Bucket          | Capacity        |
     | --------------- | --------------- |
     | `company`       | 10/20 - success |
     | `directory`     | 8/20 - success  |
     | `individual`    | 0/20            |
     | `employment`    | 0/20            |
     | `payment`       | 6/12 - success  |
     | `pay-statement` | 0/12            |
3. Tokens C and D each repeat the same pattern — 5 requests to [/company](/api-reference/organization/company), 4 to [/directory](/api-reference/organization/directory), and 3 to [/payment](/api-reference/payroll/payment) — within the same minute. The `company` and `payment` buckets reach full capacity, but Token C's and D's requests still succeed because the limits haven't been exceeded yet.
   * Application-level rate limits
     | Bucket          | Capacity               |
     | --------------- | ---------------------- |
     | `company`       | 20/20 (FULL) - success |
     | `directory`     | 16/20 - success        |
     | `individual`    | 0/20                   |
     | `employment`    | 0/20                   |
     | `payment`       | 12/12 (FULL) - success |
     | `pay-statement` | 0/12                   |
4. Token E then makes 1 request to [/company](/api-reference/organization/company) and 1 to [/directory](/api-reference/organization/directory). The `company` and `payment` buckets are now full, so any further request to those endpoints — including Token E's `/company` request — returns a 429 rate limit error until the 60-second TTL resets. Token E's `/directory` request succeeds because that bucket isn't full yet. Only successful requests count toward the application-level limit.
   * Application-level rate limits
     | Bucket          | Capacity             |
     | --------------- | -------------------- |
     | `company`       | 20/20 (FULL) - error |
     | `directory`     | 16/20 - success      |
     | `individual`    | 0/20                 |
     | `employment`    | 0/20                 |
     | `payment`       | 12/12 (FULL) - error |
     | `pay-statement` | 0/12                 |

Every fifth request to [/company](/api-reference/organization/company) for each token fails with a 429 rate limit error once its bucket is full.

### Rate limit example

The following `RateLimiter` class enforces this quota at the application level. Initialized with a limit (for example, 20 requests per minute for [/directory](/api-reference/organization/directory)), it makes requests up to that limit and pauses further requests until the bucket resets after 60 seconds. Call its `request` method to make API requests through the rate limiter, and initialize a separate `RateLimiter` instance for each endpoint you call.

```js theme={null}
class RateLimiter {
  constructor(limit) {
    this.limit = limit;
    this.requests = [];
  }

  async request(fn) {
    const now = Date.now();
    this.requests = this.requests.filter((timestamp) => now - timestamp < 60000);

    if (this.requests.length >= this.limit) {
      const delay = this.requests[0] + 60000 - now;
      await new Promise((resolve) => setTimeout(resolve, delay));
      this.requests.shift();
    }

    this.requests.push(now);
    return fn();
  }
}

const directoryRateLimiter = new RateLimiter(20); // 20 requests per minute
const url = 'https://api.tryfinch.com/employer/directory'; // Replace with the desired endpoint
const accessToken = '<your_access_token>';

const fetchIndividualData = (
) =>
  fetch(url, {
    method: 'GET',
    headers: {
      Authorization: `Bearer ${accessToken}`,
      'Content-Type': 'application/json',
    },
  });

// Use the rate limiter to make API requests
directoryRateLimiter
  .request(fetchIndividualData)
  .then((response) => response.json())
  .then((data) => console.log(data))
  .catch((error) => console.error('Error:', error));
```

## Checkpoint + Next Step

<Check>
  Your application can now handle Finch's most common error scenarios, making your integration more resilient. Monitoring API requests makes error mitigation easier — see [Monitor API Usage](/implementation-guide/Backend-Application/Monitor-Usage) next.
</Check>

## Learn more

* [Handling API Responses](/api-reference/development-guides/Handling-API-Responses)
* [Set Up Finch Connect](/implementation-guide/Connect/Set-Up-Finch-Connect)
* [Batch Requests](/implementation-guide/API-Calls/Batch-Requests)
* [Rate Limits](/api-reference/development-guides/Rate-Limits)
* [Error Types](/api-reference/development-guides/errors/Error-Types)


# Monitor Usage
Source: https://developer.tryfinch.com/implementation-guide/Backend-Application/Monitor-Usage

In this guide, you'll find best practices for monitoring your application's usage of Finch to identify patterns and potential issues.

Implementing monitoring tools or processes to keep track of your application's usage of the Finch APIs will help you identify patterns and potential issues (see [Mitigate Errors](/implementation-guide/Backend-Application/Mitigate-Errors) for more details). Events such as frequent rate limit overages or a sudden increases in error rates can be quickly identified and actioned if proper monitoring is in place.

## Use the Introspect Endpoint

The [`/introspect`](/api-reference/management/introspect)  endpoint is an extremely important tool when using Finch, allowing you to read account information associated with an access\_token such as the connection status.

## Log finch request id

It is best practice to log the `finch-request-id` for every response, whether successful or unsuccessful. The `finch-request-id` can be found in every HTTP response Header. The `finch-request-id` is required by the Finch Support team for debugging request issues.

## Store the connection id

Each Finch `access_token` is associated with a static Finch `connection_id`. You can find the id using the [`/introspect`](/api-reference/management/introspect) endpoint. Save this in your data store alongside the access token and use it when contacting Finch Support about an issue.

## Monitor API requests

Track API response times to and from Finch. A spike in latency can indicate network problems or possible Finch performance degradations.

Continuously check for increases in error rate responses from Finch. This can indicate problems with the Finch APIs or issues with how your application sends requests to the Finch APIs.

Track `422` responses by `finch_code` separately from other error rates. A rise in `batch_limit_exceeded` or `page_size_limit_exceeded` means your application is sending requests that exceed [batch or page size limits](/implementation-guide/Backend-Application/Mitigate-Errors#batch-and-page-size-limit-errors) — this won't resolve on retry and needs a code change, not a backoff strategy.

<Info>
  Finch reports all API outages and provider integration incidents. You can subscribe to receive email notifications from [https://status.tryfinch.com](https://status.tryfinch.com) whenever we create, update, or resolve an incident.
</Info>

## Optimize API usage

Regularly review your application's usage of Finch APIs and identify opportunities to optimize and improve performance. This may include refining batch request sizes to improve latency, improving error handling, or adjusting request patterns to avoid rate limits.

***

## Checkpoint + Next Step

<Check>
  After completing this step, you should be equipped to preemptively identify and address potential issues in your application and your Finch integration, helping you get the most value from Finch's services. Now that you have an application that is connected, secure, please review the [Control Access](/implementation-guide/Backend-Application/Control-Access) and [Manage Connections](/implementation-guide/Backend-Application/Manage-Connections) guides to make sure your application is set up to handle your specific use case.
</Check>

## Learn more

* [Finch Status Updates](https://status.tryfinch.com)


# Store Tokens
Source: https://developer.tryfinch.com/implementation-guide/Backend-Application/Store-Tokens

***Finch requires developers to store tokens on the backend server for improved security controls***. To reduce the likelihood of unitentional exposure of employer access tokens or other private information, you'll need to ensure all access tokens are stored securely.

<Warning>
  Finch access tokens are "keys" to sensitive information. You should treat access tokens with the same level of security as you would passwords.
</Warning>

## Secure storage best practices

Storing tokens securely should be done on the backend (server-side) of your application, not on the frontend (client-side). A frontend application is more susceptible to potential security threats such as Cross-Site Scripting (XSS) attacks or unauthorized access if the client is compromised.

No application is 100% secure, but there are ways to reduce the potential of an exposure (and its impact) by following a few best practices:

1. Store tokens on the backend of your application.
2. Encrypt the access token before storing it.
3. Use environment variables or a secure configuration management system to store static sensitive information that needs to be referenced like `client_secret`.
4. Never store access tokens in code files or easily accessible directories with human access.
5. Ensure that tokens are not exposed in URLs, logs, or error messages.
6. Keep all server-side components, libraries, and frameworks up-to-date with security patches to mitigate potential vulnerabilities.

Determine the best method for securely storing access tokens in your application's backend. Reference the sections below if you need additional help.

## Encryption

To add an extra layer of security, you can encrypt the access token before storing it. Select a strong symmetric encryption algorithm, such as AES-256. Avoid using weak algorithms like DES, as they are susceptible to brute-force attacks due to its small key size (56 bits).

## Never expose access tokens

Ensure that tokens are not exposed in URLs, log files, or error messages. Regularly review logs for any exposure.

Ensure your frontend application never receives the access token to avoid incidental exposure. Your frontend, client-side application should only receive employment data, never the token itself.

## Stay compliant with data privacy regulations

Familiarize yourself with any applicable data privacy regulations, such as GDPR, CCPA, or other regional laws. Implement necessary measures to stay compliant with these regulations when handling, storing, and processing data obtained from the Finch APIs. This includes obtaining user consent when necessary (handled by [Finch Connect](/implementation-guide/Connect/Set-Up-Finch-Connect)), [managing data deletion requests](/implementation-guide/Backend-Application/Disconnect-Connections), and providing users with the ability to [control their data](/implementation-guide/Backend-Application/Control-Access).

***

## Checkpoint + Next Step

<Check>
  After completing this step, you should know how to store access tokens on the backend server, reduce the impact of their exposure, and comply with any data privacy regulations. When a connection is no longer needed, it is best practice to [disconnect the token](/implementation-guide/Backend-Application/Disconnect-Connections) from Finch then delete it from your system.
</Check>

## Learn more

* [Disconnect Tokens](/implementation-guide/Backend-Application/Disconnect-Connections)
* [Control Access](/implementation-guide/Backend-Application/Control-Access)


# Create a Finch Developer Account
Source: https://developer.tryfinch.com/implementation-guide/Connect/Create-Account

Create your Finch Developer Account, recieve your application credentials, and pilot how Finch works in our sandbox environment.

To get started using the Finch APIs, sign up for a free sandbox account to receive application credentials (a `client_id` and `client_secret`) and pilot how Finch works in a safe testing environment with mock data.

<img alt="Sign Up" />

1. Go to the [Finch Developer Dashboard](https://dashboard.tryfinch.com/) and sign up for a new account. You'll need to provide your name, company name, email address, and create a password.
2. Once you have created an account and logged in, locate the sandbox application in the upper left which was automatically created.
3. Upon creating the application, you'll be provided with a `client_id` and `client_secret`. You will use these credentials to authenticate your application to obtain access tokens in order to call the Finch APIs.
4. Set up a secure method for storing your `client_id`, `client_secret`, and future `access_token`s to prevent unauthorized access. Here are some methods to securely store these credentials:
   * **Environment Variables**: Store your `client_id` and `client_secret` as environment variables within your application. When your application needs to use these credentials, it can access them from the environment variables without exposing them in your source code.
   * **Secure Database**: [Store the access tokens](/implementation-guide/Backend-Application/Store-Tokens) in a secure database with proper encryption and access controls in place. Make sure to use a database that supports encryption at rest and in transit to ensure the security of the stored tokens.
   * **Secrets Management Solutions**: Utilize a specialized secrets management solution, such as HashiCorp Vault or AWS Secrets Manager. These tools provide additional layers of security, access control, and auditing capabilities to ensure the safe storage of your `client_id`, `client_secret`, and `access_token`.
   * When storing access tokens, also store any relevant metadata, such as the associated employer ID. This will help you maintain data integrity and prevent mixing up tokens across different employers. This topic is covered in more detail in [Store Tokens](/implementation-guide/Backend-Application/Store-Tokens).

<img alt="Finch Developer Dashboard" />

## Familiarize Yourself With the Finch Developer Dashboard

The Finch Developer Dashboard is your centralized place to manage your Finch Applications, view current connections, review request activity, and set up webhook alerts.
We will cover these tabs in more detail in the following sections, but here is a quick overview.

* Credentials: View your application credentials, including your `client_id` and `client_secret`, and product scopes.
* Connections: View the status of your connections, including the last sync time and any errors that occurred.
* Integrations: Manage providers that you have integrated with, including the ability to enable or disable specific providers.
* Activity: Review the activity log to see a history of requests made by your application, including the request type, status, and timestamp.
* Webhooks: Set up webhook alerts to receive notifications when specific events occur, such as a connection error or a successful sync.

## Verify Product Scopes

On the Credentials tab, verify the correct products (commonly called “scopes”) are checked that your application will need access to. Products determine the specific data your application can access and the actions it can perform. Each product refers directly to a Finch endpoint. If the products are not correct, reach out to your Implementation Engineer or [developers@tryfinch.com](mailto:developers@tryfinch.com).

| Product Scope | Description                                                                                                                                                                                                    | API Endpoint     | Read/Write |
| ------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------- | ---------- |
| Company       | Company data, such as company legal name, office addresses, or Employer Identification Number (EIN)                                                                                                            | `/company`       | Read Only  |
| Directory     | List all active and inactive employee employees at the company                                                                                                                                                 | `/directory`     | Read Only  |
| Individual    | Individual employee data, such as names, contact information, or dates of birth                                                                                                                                | `/individual`    | Read Only  |
| Employment    | Employment data, such as job title, department, start and end dates, or employee income                                                                                                                        | `/employment`    | Read Only  |
| Payment       | Company payroll data, such as payment data, such as payment dates or total amounts                                                                                                                             | `/payment`       | Read Only  |
| Pay-Statement | Detailed pay statement data, such as gross pay, earnings, employee deductions, or employer contributions. Requires the Payment scope also be selected — there's no supported use case for Pay-Statement alone. | `/pay-statement` | Read Only  |
| Benefits      | Ability to write back employee deductions or employer contributions directly to the employer's provider. This is our Deductions product.                                                                       | `/benefits`      | Read/Write |
| Documents     | Read company documents such as W4 Forms                                                                                                                                                                        | `/documents`     | Read Only  |

## Add Redirect URIs

(Optional) if you are using the [Finch Connect Redirect Flow](/implementation-guide/Connect/Set-Up-Finch-Connect#redirect-finch-connect), specify any [Redirect URIs](#redirect-uris) for your application. This URL must be hosted on your own server or a trusted domain. Example: `https://your-trusted-domain.com/api/finch/callback`

To authorize with Finch, you'll need to provide one or more redirect URIs. The user will be redirected to the specified URI upon successfully authorizing your application access to their employment system. On redirect, the URI will contain an authorization `code` query parameter that must be exchanged with Finch's authorization server for an access token.

Finch's embedded Frontend SDKs don't need to set up a redirect URI. The default redirect URI **`https://tryfinch.com`** is already applied.

The redirect URIs must match one of the following formats—

| Protocol | Format                                  | Examples                |
| -------- | --------------------------------------- | ----------------------- |
| HTTP     | A localhost URI with protocol `http://` | `http://localhost:8000` |
| HTTPS    | A URI with protocol `https://`          | `https://example.com`   |

***

## Checkpoint + Next Step

<Check>
  After completing this step, you should have registered for a Finch Developer Dashboard account and set up a sandbox application, using your unique `client_id` and `client_secret`. You should also have a clear understanding of the Finch products that your application requires. You now have everything necessary to [Integrate Finch Connect Into Your Application](/implementation-guide/Connect/Set-Up-Finch-Connect) to begin connecting to employment providers.
</Check>

## Learn more

* [Store Access Tokens](/implementation-guide/Backend-Application/Store-Tokens)


# Retrieve Access Token
Source: https://developer.tryfinch.com/implementation-guide/Connect/Retrieve-Access-Token

In this guide, you’ll exchange the authorization code for an access token. Access tokens are required for making API requests to Finch endpoints.

Now that you have successfully [integrated Finch Connect](/implementation-guide/Connect/Set-Up-Finch-Connect) into your application's frontend and obtained an authorization code, you will need to exchange it for an access token. Access tokens are required for making API requests to Finch's various endpoints. In this step, you'll set up a secure server-side process to exchange the authorization code for an access token.

1. **Create a server-side “callback” endpoint**: Set up a secure server-side endpoint in your application to handle the exchange of authorization codes for access tokens. This endpoint should be accessible only by your application's backend to ensure the security of the process. This endpoint will receive the authorization code as a query parameter from your frontend and communicate with Finch's API to obtain the access token. Example: `https://example.com/api/finch/callback`.
   > You can reuse this same endpoint to support a Redirect Finch Connect flow as well. Just make sure to add the `redirect_uri` to the whitelist in your Finch Developer Dashboard.

2. **Exchange the authorization code for an access token**: In your server-side code, make a POST request to the `/auth/token` endpoint. The request should include the following fields in the request body's JSON payload:
   * `client_id`: Your unique client ID from the Finch developer dashboard.
   * `client_secret`: Your unique client secret from the Finch developer dashboard.
   * `code`: The authorization code obtained from Finch Connect in the [Set Up Finch Connect](/implementation-guide/Connect/Set-Up-Finch-Connect).
   * `redirect_uri` (optional): If using the Redirect Finch Connect Flow, include the `redirect_uri`. This is the same redirect URI you used when setting up Finch Connect. If you using Embedded Flow, do not include `redirect_uri` in the payload.
   ```bash Token exchange example theme={null}
   curl https://api.tryfinch.com/auth/token \
     -X POST \
     -H "Content-Type: application/json" \
     --data-raw '{
       "client_id": "<your_client_id>",
       "client_secret": "<your_client_secret>",
       "code": "<your_authorization_code>",
   }'
   ```

3. **Handle the response**: Finch's `/auth/token` endpoint will respond with a JSON object containing an `access_token` if the request is successful. Parse the JSON response body and extract the `access_token`.

   ```json theme={null}
   {
     "company_id": "4ab15e51-11ad-49f4-acae-f343b7794375",
     "account_id": "ac3a2af9-ce03-46c4-9142-81abe789c64d",
     "connection_id": "6dab009c-77c8-43d9-8f81-e093f7c65bc1",
     "provider_id": "gusto",
     "products": ["directory", "employment", "individual"],
     "client_type": "production",
     "connection_type": "provider",
     "access_token": "7e965183-9332-423c-9259-3edafb332ad2",
     "customer_id": "1234567890",
     "token_type": "bearer",
     "entity_ids": [
       "ba9c617b-3446-447a-9dc9-4a8c108ecf2e",
       "82db13aa-700f-478b-a677-c9177f0b2ac6"
       ]
   }
   ```

4. **Securely store the access token**: It is critical to store access tokens securely, as they grant access to sensitive user data. Implement a secure storage solution to store access tokens, treating them with the same level of security as passwords. Do not log or expose access tokens to your frontend application. Storing access tokens is covered in more depth in [Store Tokens](/implementation-guide/Backend-Application/Store-Tokens).

5. **Handle errors**: If the `/auth/token` endpoint returns an error, your server-side code should handle it gracefully. Common error scenarios include invalid or expired authorization codes, incorrect client IDs or secrets, or mismatched redirect URIs. Display a helpful error message to the user or retry the authentication flow as needed.

***

## Checkpoint + Next Step

<Check>
  After completing this step, your application will be able to exchange authorization codes for access tokens securely and automatically. You are now ready to [test your integration](/implementation-guide/Test/Environments) to ensure your integration is robust and reliable.
</Check>

## Learn more

* [Store Tokens](/implementation-guide/Backend-Application/Store-Tokens)
* [Mitigate Errors](/implementation-guide/Backend-Application/Mitigate-Errors)


# Create a Finch Connect Session
Source: https://developer.tryfinch.com/implementation-guide/Connect/Set-Up-Finch-Connect

Set up Finch Connect to collect consent from your customers and begin syncing data from their HR or payroll system.

[Finch Connect](/how-finch-works/finch-connect) is the interface your customers will use to provide consent, approve permissions, connect their HR or payroll system, and authenticate. Finch will walk each employer through the appropriate flow based on the provider and [auth method](/implementation-guide/Integration-Preparation/Configure-Auth-Methods).  Finch Connect is supported via our [Frontend SDKs](/developer-resources/SDKs) for Javascript and React.

You can [embed Finch Connect](/implementation-guide/Connect/Set-Up-Finch-Connect#embedded-flow) into your application, or set up a [redirect flow](/implementation-guide/Connect/Set-Up-Finch-Connect#redirect-flow).

<Note>
  This section requires that you have created a Finch application and have access to a client\_id and client\_secret by completing
  the [Create a Finch Developer Account](implementation-guide/Connect/Create-Account)
  section.
</Note>

## Session Configuration

Every flow requires you to create a Finch Connect session with your `client_id` and `client_secret` and is configurable with the following parameters:

| Parameter                 | Required              | Description                                                                                                                                                                                                                                                                                                           |
| ------------------------- | --------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `customer_id`             | true                  | A unique identifier for your customer.                                                                                                                                                                                                                                                                                |
| `customer_name`           | true                  | The name of your customer.                                                                                                                                                                                                                                                                                            |
| `customer_email`          | false                 | The email associated to your customer.                                                                                                                                                                                                                                                                                |
| `products`                | true                  | A space-separated list of permissions your application is requesting access to. See [Product Permissions](/api-reference/development-guides/Permissions) for a list of valid permissions. Please note that SSN is its own product scope.                                                                              |
| `redirect_uri`            | redirect only         | The URI your user is redirected to after successfully granting your application access to their system. This value must match one of your application's configured [redirect URIs](/implementation-guide/Connect/Create-Account#redirect-uris).                                                                       |
| `integration.provider`    | optional              | An optional parameter that allows you to bypass the provider selection screen by providing a valid `provider_id` from our list of [Providers](/integrations/providers).                                                                                                                                               |
| `integration.auth_method` | optional              | An optional parameter that allows you to bypass the provider selection screen by providing a valid `auth_method` for a provider from our list of [Providers](/integrations/providers).                                                                                                                                |
| `sandbox`                 | false                 | An optional value that allows users to switch on sandbox mode to connect to test environments. Allowed values: `finch` and `provider`. For more information, read our [testing guide](/implementation-guide/Test/Finch-Sandbox).                                                                                      |
| `manual`                  | false                 | An optional value which when set to true displays both [Automated and Assisted Providers](/integrations/integration-types) on the selection screen.                                                                                                                                                                   |
| `minutes_to_expire`       | false                 | An optional value which allows you to set the number of minutes the connect session should be valid for. Defaults to 30 days.                                                                                                                                                                                         |
| `connection_id`           | reauthentication only | A unique identifier created when an employer successfully authenticates through Finch Connect. This ID is only used for reauthentication. You will not have a `connection_id` for the first call. For all reauthentication flows you should include the `connection_id` to avoid duplicate connections being created. |

## Create a Connect Session

Using the configuration params described in the above sections, your **backend application** will make a call to [Create a New Connect Session](/api-reference/connect/new-session) `POST /connect/sessions`. When creating the connect session, include your internal customer\_id for your customer, the customer’s name and any of the optional fields listed below.

```js theme={null}
import Finch from '@tryfinch/finch-api';

const client = new Finch({
  clientId: 'My Client ID',
  clientSecret: 'My Client Secret',
});

async function main() {
  const createConnectSessionResponse = await finch.connect.sessions.new({
	  products: ["company", "directory", "individual", "employment", "payment", "pay_statement"],
	  customer_id: customer.id, // Your internal customer ID
	  customer_name: customer.name, // Your customer's name
	  customer_email: customer.email, // The email associated to your customer (optional)
	  integration: { // (optional)
			  provider: 'adp_run', // The provider you wand to show up in connect (optional)
			  auth_method: 'credential' // The auth method of the provider to show up (optional)
	  },
	  minutes_to_expire: 43200, // How long you want the session to last for (defaults to 30 days)
	  redirect_uri: '' // The URI to redirect to for the redirect connect flow (optional)
	  sandbox: false // create a sandbox session for a sandbox app (optional)
	  manual: false // A value that, when set to true, displays both Automated and Assisted providers on the selection screen (optional)
  });

	/**
	 * {
	 *   "session_id": "<A unique session ID that can be used with embedded connect>",
   *   "connect_url": "<The url of the connect session for the redirect flow>"
   * }
	**/
  console.log(createConnectSessionResponse);
}

main();
```

If your customer has successfully authenticated (completed Finch Connect and you see a Live connection on your dashboard) and you call `POST /connect/sessions` using the same `customer_id` you passed in, Finch will prompt you to re-authenticate instead and return the following error:

```
{
    "code": 400,
    "finch_code": "connection_already_exists",
    "message": "There's an existing connection for the customer_id: <session.customer_id>. Please use the /connect/sessions/reauthenticate endpoint instead.",
    "name": "bad_request",
    "context": {
      "customer_id": "<session.customer_id>",
      "connection_id": "<connection.id>"
    },
  }
```

If your customer has not yet successfully authenticated and you call `POST / connect/sessions` using the same `customer_id` you passed in, Finch will simply refresh the connect session and return the same `session_id`. You can do this if you wish to update the Customer Name or any other parameter before your customer connects. If you wish to update any parameters after the customer has connected, you will need to use `POST / connect/sessions/reauthenticate`.

### Best Practices: Creating Sessions

#### DO

* Always pass in a **stable and unique** `customer_id` for a given employer, and **reuse the same `customer_id` across retries or drop-offs.** Even if an employer opens the Connect session multiple times before successfully connecting, using the same `customer_id` ensures all attempts are tracked as a single staged session.
* If you think an employer intends to connect multiple entities or payroll systems, you can append an identifier to the `customer_id` to differentiate the Connect sessions (e.g.: `acme-1`, `acme-2`). Visit this [Help Center article](https://support.tryfinch.com/hc/en-us/articles/31148519242772-FAQs-Connection-ID-Session-ID) for more details.

#### DON'T

* Avoid generating new `customer_ids` on retries or failed connection attempts - this results in multiple redundant staged connections and could result in unintended behavior:
  * If an employer converts using Session\_Link\_1, Session\_Link\_2 will eventually expire
  * If an employer converts using both Session\_Link\_1 and Session\_Link\_2, they will inadvertently create two connections.

### Reauthentication Sessions

Your application should be able to generate a Finch Connect session for reathentication. This will avoid creating duplicate connections and ensure that the user is able to reauthenticate successfully to continue syncing data.

If a connection goes into a status of `reauth`, you will need to create a reauthentication session. This is done by calling [Create a new Connect session for reauthentication](/api-reference/connect/reauthenticate-session) (`POST /connect/sessions/reauthenticate`) endpoint with the `connection_id` of the connection that requires reauthentication. The response will include a new `session_id` and `connect_url` for the reauthentication session.

## Launch Finch Connect

Finch provides two options to launch Finch Connect: redirect and embedded. For both options, your customer will go through the same authentication flow in Finch Connect.

When launching either flow, you may optionally pass a state parameter. Finch Connect sessions are created server-side using your client credentials, so they are not vulnerable to the CSRF attacks that `state` is traditionally used to prevent. The `state` parameter is not required, but you may use it to carry context through the authorization code exchange or for additional security requirements specific to your application.

**Note that `state` is not a parameter accepted by `POST /connect/sessions` and will be silently ignored if passed — see the redirect and embedded flow sections below for how to include it in each flow.**

### Redirect Flow

Use the redirect flow if you are not using the Finch Frontend SDK or need to share a link directly with your customer, such as via email or a URL redirect.

1. **Configure Finch Connect** — Create a connect session using `POST /connect/sessions`. See [Create a Connect Session](#create-a-connect-session) above for details.
2. **Share Finch Connect** — Provide your customer with a link or button pointing to the `connect_url`. Your customer clicks it to redirect their browser to Finch Connect, hosted by Finch at `https://connect.tryfinch.com`, and initiate the authorization flow.
3. **Request access** — Finch Connect prompts your customer to approve the permissions your application is requesting and provide the credentials or information needed to connect their employment system.
4. **Retrieve the authorization code** — After your customer authenticates and grants access, Finch Connect redirects their browser to your `redirect_uri` with a short-lived authorization `code`.
5. **Exchange the code for an access token** — Your application exchanges the short-lived `code` for a long-lived `access_token`. See [Retrieve An Access Token](/implementation-guide/Connect/Retrieve-Access-Token) for details. The `access_token` is then used to make Finch API calls.

The `connect_url` supports an optional `state` parameter, which will be returned as-is to your `redirect_uri` after your customer authenticates. To use it, append it to the URL:

```
https://connect.tryfinch.com/authorize?session=<session_id>&state=foo
```

Finch Connect sessions are created server-side using your client credentials, so they are not vulnerable to the CSRF attacks that state is traditionally used to prevent. The state parameter is not required, but you may use it to carry context through the authorization code exchange or for additional security purposes specific to your application.

### Embedded Flow

Use the embedded flow if you are integrating via the Finch Frontend SDK and want your customer to complete the authorization flow within your application.

1. **Configure Finch Connect** — Create a connect session using `POST /connect/sessions`. See [Create a Connect Session](#create-a-connect-session) above for details.
2. **Share Finch Connect** — Provide your customer with a button that calls `connect.open()` with the `session_id`. Your customer clicks it to launch the Connect modal within your application and initiate the authorization flow.
3. **Request access** — Finch Connect prompts your customer to approve the permissions your application is requesting and provide the credentials or information needed to connect their employment system.
4. **Retrieve the authorization code** — Your application receives a short-lived authorization `code` via the SDK's `onSuccess` callback after your customer successfully authenticates.
5. **Exchange the code for an access token** — Your application exchanges the short-lived `code` for a long-lived `access_token`. See [Retrieve An Access Token](/implementation-guide/Connect/Retrieve-Access-Token) for details. The `access_token` is then used to make Finch API calls.

The `open` call accepts an optional `state` parameter if you need to carry context through the authorization flow:

```js theme={null}
connect.open({ sessionId, state });
```

We offer both a JavaScript and React frontend SDK, both of which can be viewed at the repository below. See the README in the repository for installation and usage instructions.

<CardGroup>
  <Card title="Finch Connect SDK" icon="toolbox" href="https://github.com/Finch-API/finch-connect-sdk" />
</CardGroup>

***

## Checkpoint + Next Step

<Check>
  After completing this step, you will have successfully integrated Finch
  Connect into your application's front end. This will enable users to
  authenticate with their employment systems, providing your application with
  the necessary authorization to [Retrieve An Access
  Token](/implementation-guide/Connect/Retrieve-Access-Token) in the next
  section.
</Check>

## Learn more

* [Finch Connect Best Practices](/implementation-guide/Deploy-and-Manage/Increase-Employer-Adoption)


# Increase Employer Adoption
Source: https://developer.tryfinch.com/implementation-guide/Deploy-and-Manage/Increase-Employer-Adoption

Best practices for improving employer completion rates in Finch Connect through in-app messaging, UI defaults, and re-engagement at key decision points.

Finch Connect is an embeddable UI that employers use to connect their employment system to your application, approve permissions, select their provider, and authorize access.

> New to Finch Connect or looking for help getting started? Read the [Finch Overview](/how-finch-works/finch-overview).

Apply the following best practices when implementing Finch Connect to maximize employer completion rates.

## 1. Set Finch Connect as the default integration option

Present Finch Connect as the primary option rather than listing it alongside manual flows as equal alternatives. Give it visual prominence through size, positioning, and a label like "Recommended" or "Preferred". Any manual alternatives should be clearly secondary.

<img alt="Finch Connect Best Practices 1.jpg" />

## 2. Communicate the value of connecting

The value for employers will depend on your use case, but may include:

* **Save time:** Finch is easy to set up, and eliminates the need to create or reformat any files.
* **Enable automation:** Automatically share updates with us each day or week.
* **More accurate:** Avoid common errors (eg. typos, formatting errors, corrupted files, etc.).

> 💡 **Tip:** Finch's [Sales & Marketing Best Practices](https://support.tryfinch.com/collections/5213481409-for-sales-%26-marketing) collection includes ready-to-use messaging examples for different employer types and use cases. Available on Starter, Pro, and Premier plans.

<img alt="Finch Connect Best Practices 4.jpg" />

## 3. Set expectations before the connection flow

Before employers open Finch Connect, give them the context they need to proceed confidently.

### Tell the employer what to expect

Before launching Finch Connect, tell the employer they'll connect their payroll or HRIS system, what data your app will access, and why. If credentials aren't available, offer a 'skip and come back later' option and prompt them to [connect later](#4-create-multiple-opportunities-to-connect).

Finch Connect guides employers through their provider's authentication flow — including credential entry, OAuth steps, and other provider-specific requirements. You don't need to send separate setup instructions or build per-provider guidance. Finch handles authentication differences across all supported providers directly in the UI.

### Emphasize data security

Let employers know that Finch encrypts all data in transit and at rest. Share the [What is Finch? FAQ for Employers](https://www.tryfinch.com/for-employers) with employers who have further questions. Clarify that your app does not have access to their credentials, and that they can disconnect at any time. Link to [Finch's Trust Center](https://finch.secureframetrust.com/#resources) for additional detail.

## 4. Create multiple opportunities to connect

If an employer does not connect their employment system during onboarding, remind them to return. Use in-app messaging or email automations to prompt reconnection and explain the value. These same channels can notify employers when re-authentication is needed.

## 5. Deploy Finch Connect early in the onboarding process

Authorization through Finch Connect completes quickly, but the initial data sync job can take time depending on the provider and data volume. Embed Finch Connect early in onboarding so the sync runs in parallel while employers complete other setup steps. While the data sync job is running, continue onboarding — collect additional information or show a product tutorial.

<img alt="Finch Connect Best Practices 2.jpg" />

Once the employer connects, Finch begins the initial data sync. Listen for the `job.initial_data_sync_org` and `job.initial_data_sync_payroll` webhook events to know when each sync completes — at that point, the corresponding Finch data endpoints are available for that connection. See [Webhooks](/developer-resources/Webhooks) for setup and event details.

## 6. Bypass the provider selection screen

If your application already has a place where employers select or manage their integrations, you can pass the provider directly to Finch Connect instead of using the built-in selection screen.

Pass a valid provider ID in the `integration.provider` field when creating the Connect session. See the [Providers](/api-reference/management/providers) endpoint for a full list of valid provider IDs. Omit `integration` to use the default Finch Connect provider selection screen.

```js Bypass Enabled theme={null}
const session = await finch.connect.sessions.new({
  products: ["company", "directory", "individual", "employment", "payment", "pay_statement"],
  customer_id: customer.id,
  customer_name: customer.name,
  integration: {
    provider: "gusto"
  }
});
```

```js Bypass Disabled theme={null}
const session = await finch.connect.sessions.new({
  products: ["company", "directory", "individual", "employment", "payment", "pay_statement"],
  customer_id: customer.id,
  customer_name: customer.name
});
```

<img alt="Finch Connect Best Practices 3.jpg" />

***

## Checkpoint + Next Step

<Check>
  Your application now has the messaging, defaults, and re-engagement flows in place to guide employers through Finch Connect and increase completion rates. For technical questions, the [Support](/implementation-guide/Deploy-and-Manage/Support) page covers how to reach the Finch support team.
</Check>

## Learn more

* [What is Finch? FAQ for Employers](https://www.tryfinch.com/for-employers)


# Get support
Source: https://developer.tryfinch.com/implementation-guide/Deploy-and-Manage/Support

Reach Finch Technical Support via email, Slack, or the support portal. Include request_id and other identifiers in your ticket for faster, accurate responses.

## Information to include in support requests

Include the following in your support request — the more context you can provide, the faster we can help:

| Field           | Description                                                                                                                        |
| --------------- | ---------------------------------------------------------------------------------------------------------------------------------- |
| `request_id`    | Returned in the response header of every API request.                                                                              |
| `company_id`    | Associated with the access token. Available in the developer dashboard or from the `/company` or `/introspect` endpoints.          |
| `job_id`        | For Deductions requests only. Returned after calling the benefits endpoints.                                                       |
| `individual_id` | The Finch-generated ID returned from the `/directory` endpoint. Required when asking about specific pay statements or individuals. |
| `benefit_id`    | The Finch-generated ID returned from the `/benefits` endpoint. Required when asking about specific benefits.                       |

## How to contact support

You can reach the support team via email, Slack, or the [support portal](https://support.tryfinch.com/hc/en-us). The team is available Monday–Friday, 9 am–8 pm EST and responds to requests within 24 hours.

### Support portal

When you submit a ticket through the portal, you'll receive an email confirmation with a ticket number you can use to track your request.

### Email

You can email the support team at [developers@tryfinch.com](mailto:developers@tryfinch.com).

### Slack

If you're on a Pro or Premier plan, you can tag the support team in your shared Slack channel using @FinchSupport.

### Developer Success Engineer

If you're on a Pro or Premier plan, you're assigned a dedicated Developer Success Engineer (DSE) as your primary point of contact for technical questions and integration support.


# Configure Auth Methods
Source: https://developer.tryfinch.com/implementation-guide/Integration-Preparation/Configure-Auth-Methods

Learn more about the four authentication methods offered by Finch -- OAuth, Credentials, API token, and Assisted.

In this guide, we’ll cover everything you need to know about Finch’s Authentication Methods, including Authentication Fallback and Re-authentication.

## Authentication Methods

Finch offers 4 ways for employers to authenticate through Finch Connect: OAuth, Credentials, API Token, or Assisted.

Authentication method will vary by provider, and will impact the fields and functionality available to you. Find field support for each provider by authentication method [here](/integrations/field-support).

<img alt="" />

### OAuth

**OAuth** allows access tokens to be securely issued to Finch via the provider’s own authorization flow. This is the preferred authentication method for all parties.

Finch is constantly working to increase the number of providers supported through OAuth, which offers superior speed and survivability. However, OAuth support is heavily dependent on the underlying provider.

### Credentials

The **credentials** method enables employers to simply log in with an administrator username and password to set up a connection. It’s a very low friction option for employers to connect their provider through Finch.

When possible, Finch will automatically set up a separate third-party administrator or accountant user behind the scenes to keep this connection active indefinitely. This will be noted on the credentials log in screen.

If for some reason an employer is unable to log in with credentials after 3 attempts, they can still establish a connection through [Authentication Fallback](/implementation-guide/Integration-Preparation/Configure-Auth-Methods#set-up-authentication-fallback).

### API Token

The **API token** method leverages API keys supplied by the provider to establish a connection. Once set up, these connections very rarely need [re-authentication](/implementation-guide/Integration-Preparation/Configure-Auth-Methods#manage-re-authentication).

Finch will guide employers through each step required to obtain an API key from their provider. See our [authentication guides](https://support.tryfinch.com/collections/9565019353-authentication-guides) for details.

In a few cases, employers will be charged for access to their API token. If you have a Help Center login, you can see the (short) list of providers that charge employer fees [here](https://support.tryfinch.com/hc/en-us/articles/25312473665428-Costs-Fees-for-Employers).

### Assisted

**Assisted** is an authentication method available to customers using [Finch Assist](/integrations/integration-types#assisted-integrations). In this method, Finch asks employers to create a new admin or accountant user in their system. Finch’s operations team then uses that connection to refresh data every 7 days.

[Re-authentication](/implementation-guide/Integration-Preparation/Configure-Auth-Methods#manage-re-authentication) will only be required if the user is removed or loses the necessary permissions.

## Set Up Preferred Authentication Methods Per Provider

While authentication method will often come down to which fields or functionality is needed, you have the flexibility to decide which to make available for your end customers and their order of priority. You can set primary and secondary authentication methods for each provider, and even hide specific methods if desired. All of this is possible through the Finch Dashboard.

For example, if you want to present only the API token method to Bob customers, Finch can conceal the credentials-based authentication method in Finch Connect.

<img alt="" />

## Enable or Disable Authentication Methods Globally

You can also disable an authentication method globally using the Settings page in the Dashboard. These settings will apply automatically to any new integrations.

<img alt="" />

## Set Up Authentication Fallback

Authentication Fallback enables employers to authorize through Finch Connect even when Finch is experiencing intermittent issues with a provider. Please note [Email Forwarding](/implementation-guide/Integration-Preparation/Email-Forwarding) is a prerequisite for Authentication Fallback. Please refer to this [Help Center article](https://support.tryfinch.com/hc/en-us/articles/28708518221204-Authentication-with-Auth-Fallback) for recommendations on how to best manage connections created through Authentication Fallback.

<img alt="Fallback" />

If Authentication Fallback is enabled, Finch Connect will still attempt to authenticate with Credentials first. If this fails, Finch Connect will prompt the employer to set up Finch as a third-party administrator in their HRIS or payroll system using a set of manual instructions. Depending on the provider this can happen by default, or after a set number of failed attempts.

Until Finch processes this invitation, you will receive a 202 response code when making requests with the token. Once Finch has established the connection, data will flow through the Finch API just like any other automated connection.

Authentication Fallback can be enabled for the following providers:

* ADP Workforce Now
* ADP Run
* Quickbooks
* Paychex
* Paycom
* Sequoia One
* Square Payroll

To enable Authentication Fallback, please reach out to your Developer Success Representative. You will need to set up [Email Forwarding](/implementation-guide/Integration-Preparation/Email-Forwarding) and ensure your application is configured to handle 202 response codes from Finch.

## Manage Re-Authentication

Finch aims to maintain connections as long as possible. However, there are a few situations where connections may be broken. For example, connections may be broken if a user changes security settings or permissions on their account. Or if an underlying provider makes a breaking change to their infrastructure. If this happens, the employer will need to go through Finch Connect again (re-authenticate). The `connection_id` parameter allows the employer to bypass the steps of Finch Connect they’ve already completed when re-authenticating.

Remember this will create a new **`access_token`** for your user that will be to be updated. Make sure to save this new token in your database.

### Identify connections that require re-authentication

In the API, broken connections will result in an error with the HTTP status code **`401`** and a **`finch_code`** of **`reauthenticate_user`.**

In the Finch Dashboard, you can view all connections that require re-authentication on the Connections page. If any connections require re-authentication, a banner will appear at the top of the page. Simply click the banner to filter the connections that require action from the employer.

### Set up re-auth notifications

To increase conversion, we recommend either using in-app or email notifications to notify your user there is an issue with their connection, why re-connecting is beneficial, and the steps they need to follow to re-connect. To create a more seamless experience and avoid unintended duplicate connections, use the `connection_id` parameter. You can find the `connection_id` of your customer by calling the **[/introspect](/api-reference/management/introspect)** endpoint with their **`access_token`**.

Below are a couple of options to present the re-connection flow to your users:

1. Prompt your user to log on to their application dashboard where you can present them the UI to go through Finch Connect again.
2. Send your user an authorization URL with a **`redirect_uri`** that redirects them back to their application dashboard after a successful reconnection. Learn more about **[redirecting your users to Finch Connect](/implementation-guide/Connect/Set-Up-Finch-Connect)**.


# Email Forwarding
Source: https://developer.tryfinch.com/implementation-guide/Integration-Preparation/Email-Forwarding

Set up email forwarding to ensure successful authentication with providers.

## Email Forwarding

Email forwarding is required for all assisted integrations. Our automated integrations also use the email forwarding address when setting up accountant accounts for providers that require an accountant user to be set up in order to access data. In the case that you have not setup email forwarding, the automated integrations will use our standard Finch payroll email address.

More information about email forwarding is in our Help Center article, [Why do I need to set up email forwarding?](https://support.tryfinch.com/hc/en-us/articles/24177472738324-Why-do-I-need-to-set-up-email-forwarding).

Directions for setting up email forwarding can be found in our Help Center article, [Email Forwarding Setup](https://support.tryfinch.com/hc/en-us/articles/27241619992980-Email-Forwarding-Setup-Overview).


# Manage Integrations
Source: https://developer.tryfinch.com/implementation-guide/Integration-Preparation/Manage-Integrations

Customize the list of Providers your customers see in Finch Connect. Validate field support for each provider you plan to use, and disable any that don't fit your use case.

## Manage Integrations in the Developer Dashboard

The Integrations tab of the Dashboard is where you can manage the providers that are available to your customers in Finch Connect. You can enable or disable providers, customize the order in which providers are displayed, and preview changes in Finch Connect.

<iframe />

## Verify Products, Field Support, and Authentication Methods for Providers

Head to our [Field Support](/integrations/field-support) page to check which providers can support the products, fields, and authentication methods required for your use case.

* You can filter by Product using the dropdown in the top corner of the screen.
* You can filter by Fields and Authentication Method using the filters on the top left of the matrix.

Please disable any providers that do not fit your use case.

Please note some providers support multiple authentication methods with different field support. Please verify field support for all available authentication methods and disable specific authentication methods that do not meet your use case. Directions for how to do this are in [Set Up Preferred Authentication Methods](/implementation-guide/Integration-Preparation/Configure-Auth-Methods#set-up-preferred-authentication-methods).

## Disable, Pin, and Re-Order Providers

By default, providers will be listed in Finch Connect in alphabetical order. If you want, you can pin and re-order providers as you see fit. This can help you highlight providers that are most relevant to your customer base and reduce the friction of connecting.

To re-order providers, simply click the pin icon and then drag and drop to your desired order.

<img alt="" />

You can also use this feature to hide providers that are not relevant to your customer base. This will reduce the number of options your customers have to choose from, and reduce the likelihood of them selecting the wrong provider.

## Preview Changes in Finch Connect

To preview how your integrations will appear in Finch Connect, make your changes on the Integrations page in the Dashboard, and click 'Preview in Connect'.

Please train any team members who will be working with Finch Connect on how to use the 'Preview in Connect' feature. This feature allows you to preview the authentication instructions your employers will see for each provider in Finch Connect.


# Security Reviews
Source: https://developer.tryfinch.com/implementation-guide/Integration-Preparation/Security-Reviews

Some providers, including Gusto and TriNet, require a security review or other one-time setup before you can go live with them. See [Provider Setup Instructions](/integrations/provider-setup) for which providers require this and what's involved.



# Environments
Source: https://developer.tryfinch.com/implementation-guide/Test/Environments

Choose between Finch Sandbox, Provider Sandbox, and Development for testing. Compare connection limits, assisted support, and provider availability per environment.

Finch supports three environments — Sandbox, Development, and Production — each with different connection limits, provider support, and capabilities. Use the comparison table and environment descriptions below to choose the right one for each stage of testing.

Each environment uses separate credentials. In the [Finch Dashboard](https://dashboard.tryfinch.com/), select your environment from the dropdown and copy the `client_id` from the **Credentials** tab before launching Finch Connect.

## Sandbox, Development, and Production compared

| Features                      | Finch Sandbox                                                              | Provider Sandbox | Development                   | Production     |
| ----------------------------- | -------------------------------------------------------------------------- | ---------------- | ----------------------------- | -------------- |
| **Availability**              | All plans                                                                  | All plans        | Pro and Premier, upon request | All plans      |
| **Allowed connections**       | 100                                                                        | 5                | 5 \*                          | Unlimited      |
| **Connect to real providers** | —                                                                          | <span>✓</span>   | <span>✓</span>                | <span>✓</span> |
| **Scheduled data syncs**      | — [(?)](/implementation-guide/Test/Finch-Sandbox#configuring-sandbox-data) | <span>✓</span>   | <span>✓</span>                | <span>✓</span> |
| **Assisted integrations**     | <span>✓</span>                                                             | —                | —                             | <span>✓</span> |
| **Webhooks**                  | <span>✓</span>                                                             | <span>✓</span>   | <span>✓</span>                | <span>✓</span> |

\*Work with your implementation engineer to discuss more than 5 Development connections.

## Sandbox environment

<Note>
  You don't need to test against every provider in Finch's network. Finch normalizes data across all providers into a consistent schema — your application code does not change based on which provider an employer uses. Use the [Field Support matrix](/integrations/field-support) to identify which fields are supported for the providers most relevant to your use case.
</Note>

[**Finch Sandbox**](/implementation-guide/Test/Finch-Sandbox) (`sandbox=finch`) — fully mock data generated and managed by Finch:

* Create and configure connections programmatically using [sandbox-only API endpoints](/api-reference/sandbox/create-sandbox-connection) — there is no backing provider system; all data is managed through the Finch API
* Tests the full authorization flow
* Supports automated and assisted integrations

[**Provider Sandboxes**](/implementation-guide/Test/Provider-Sandboxes) (`sandbox=provider`) — connects to a real provider's demo or trial account. Recommended for end-to-end testing of automated integrations. Available for a limited number of providers. Data changes are made by logging into the provider's demo account directly.

<Info>
  A Sandbox application is required to initiate sandbox connections. A free sandbox environment is included with every Finch Developer Dashboard account. If someone on your team has already created one, ask them to add you. If your organization does not have one, [sign up](https://dashboard.tryfinch.com/signup) or [reach out to us](https://www.tryfinch.com/sales).
</Info>

## Development environment

Development is a production-like environment for testing with live data, available to Pro and Premier plan customers upon request. Contact your implementation engineer or email [implementation-team@tryfinch.com](mailto:implementation-team@tryfinch.com) to request access.

Before connecting live customer accounts in Development:

* Development connections cannot be migrated to Production — customers must reauthenticate using your Production `client_id`.
* Finch UUIDs are not shared across environments. A Production connection will have entirely new IDs.
* Gusto and all assisted providers are not supported in Development.
* Some providers may charge for additional seats created during testing.

## Production environment

<Warning>
  Sandbox and Development connections cannot be used in Production — each environment requires its own credentials and a separate authorization flow. Development connections cannot be migrated to Production; customers must reauthenticate using your Production `client_id`.
</Warning>

* Make your first Production connections with friendly customers to complete final validation with real data.
* Demo or trial provider accounts may successfully connect in Production. All Production connections are billable regardless of account type.
* Do not use Gusto Production connections for testing. All Gusto testing must be done in the Sandbox environment.
* Use the [disconnect endpoint](/api-reference/management/disconnect) to disconnect any test, duplicate, or unused connections promptly.
* Set both `client_id` and `client_secret` to your Production values from the [Finch Dashboard](https://dashboard.tryfinch.com/). Connections cannot move between environments — each requires its own credentials and a new authorization flow.

## Postman collection

The Finch API Postman collection includes pre-configured requests for all endpoints across Organization, Payroll, Deductions, Documents, and Management. Use environment variables to switch between sandbox and production without reconfiguring requests.

<CardGroup>
  <Card title="Postman Collection" icon="rocket" href="https://documenter.getpostman.com/view/50241421/2sB3dQupP9" />
</CardGroup>


# Finch Sandbox
Source: https://developer.tryfinch.com/implementation-guide/Test/Finch-Sandbox

Test automated and assisted integrations with mock connections. Use sandbox API endpoints to configure mock data and test scenarios before going live.

The Finch Sandbox is a testing environment with mock connections that mirror the field and functionality of Finch's production integrations. You can configure connections to test scenarios your application needs to handle.

New to Finch? Start with [How the Finch API is organized](/how-finch-works/data-model). The four-diagram tour covers every core entity and how they connect in about five minutes.

<Note>
  Sandbox connections require your **sandbox** `client_id` and `client_secret`. Find these in the [Finch Dashboard](https://dashboard.tryfinch.com) under your sandbox application's settings. Production credentials will not work for sandbox connections.
</Note>

## Creating a sandbox connection

| Method                                                          | How                                                           | Notes                                                                                              | To test assisted                                           |
| --------------------------------------------------------------- | ------------------------------------------------------------- | -------------------------------------------------------------------------------------------------- | ---------------------------------------------------------- |
| Finch Dashboard                                                 | Connections tab → **Actions** → **Create a New Connect Link** | Does not test token exchange                                                                       | Enable **Show assisted providers** above the URL generator |
| [Finch Connect](/api-reference/connect/new-session)             | Create a session with `"sandbox": "finch"`, then launch       | Exercises the full auth code exchange flow                                                         | Set `manual=true`                                          |
| [Sandbox API](/api-reference/sandbox/create-sandbox-connection) | Call with your sandbox `client_id` and `client_secret`        | Bypasses Finch Connect — best for automated or repeatable testing. Cannot test multi-entity flows. | Include the `assisted` parameter                           |

<Warning>
  `finch` and `provider` are the only accepted values for the `sandbox` parameter. See [Provider Sandboxes](/implementation-guide/Test/Provider-Sandboxes) for `provider` mode.
</Warning>

<Note>
  The Sandbox API sets the connection's authentication method from the `authentication_type` you pass — it does not go through Finch Connect, which in production only offers the method a provider supports. A provider can support different products across its authentication methods: one method may support Deductions while another does not. When the method you choose does not support a product on your session, `/employer` requests for that product return a `501 not_implemented_error`.

  Confirm your `authentication_type` supports the `products` you are testing before you create the connection. Check the provider's `authentication_methods` — and each method's `benefits_support` for Deductions — through the [`/providers` endpoint](/api-reference/management/providers) or the [Field Support matrix](/integrations/field-support).
</Note>

## Sandbox credentials

Finch Connect presents the authentication method supported by the provider and handles the flow — your application has no logic to implement for authentication. Use the credentials below that match the authentication method shown in Finch Connect for your test.

<Note>
  In production, Finch Connect presents only the authentication method supported by the connected provider. Most providers support a single method. The sandbox exposes all flows so you can understand how each one behaves.
</Note>

### Credential flows

| Username    | Password       | Simulated flow                                   |
| ----------- | -------------- | ------------------------------------------------ |
| `good_user` | `good_pass`    | Standard credential flow                         |
| `good_user` | `mfa`          | Credential flow with MFA step                    |
| `good_user` | `multi_entity` | Account selection screen (multi-entity employer) |

### API token flows

| Field                     | Value                                                        |
| ------------------------- | ------------------------------------------------------------ |
| Token                     | `good_token` — any other value returns an error              |
| Client ID / Client Secret | `good_user` / `good_pass` — any other values return an error |

### OAuth flows

All OAuth auth methods bypass the provider OAuth flow in sandbox mode. Clicking **Connect** immediately succeeds. OAuth providers do not support multi-entity testing — use providers with credential-based authentication to test multi-entity flows.

## Testing multi-entity employers

Use the `multi_entity` password to simulate a payroll system where a single login manages multiple entities. Finch Connect displays an account selection screen with each entity as a separate option.

<Note>
  Providers that use OAuth flows cannot be used for multi-entity testing. The `multi_entity` password only applies to credential-based authentication.
</Note>

To create multiple connections with the same provider where each connection has entities available, use distinct company usernames — see [Testing distinct companies](#testing-distinct-companies).

An entity can only be authenticated on one connection at a time. Using the same base username across connections maps to the same underlying company — entities already connected under that company will not be available on new connections.

<Info>
  Additional technical detail on multi-entity testing behavior is available in the [Finch Help Center](https://support.tryfinch.com/articles/8146190155-how-multi-entity-works), accessible to current customers on any Finch plan.
</Info>

## Testing distinct companies

To test multiple distinct companies with the same provider, append a number to the base username when creating each connection:

| Username      | Result         |
| ------------- | -------------- |
| `good_user`   | First company  |
| `good_user_1` | Second company |
| `good_user_2` | Third company  |

Each numbered username generates a unique company with its own ID and data set. This mirrors production behavior — the username an employer uses to authenticate determines which company Finch connects to. Two connections authenticated with the same username will always map to the same company for that provider.

## Configuring sandbox data

Each sandbox connection is pre-populated with 20 randomly generated employees, corresponding `employment` and `individual` records, and one company payment dated to the current date with one pay statement per full-time employee.

Use the `/sandbox` endpoints to modify connection data:

* [`PUT /sandbox/company`](/api-reference/sandbox/update-sandbox-company) — modify company data
* [`POST /sandbox/directory`](/api-reference/sandbox/create-sandbox-employee) — add individuals
* [`PUT /sandbox/employment/{individual_id}`](/api-reference/sandbox/update-sandbox-individual) — modify employment data
* [`PUT /sandbox/individual/{individual_id}`](/api-reference/sandbox/update-sandbox-employment) — modify individual data
* [`POST /sandbox/payment`](/api-reference/sandbox/create-sandbox-payment) — add a payment
* [`PUT /sandbox/connections/accounts`](/api-reference/sandbox/update-sandbox-account) — modify connection status

<Note>
  After modifying data, run a [refresh data sync](/api-reference/sandbox/refresh-job) to see changes reflected in `/employer` API responses. Data syncs do not run automatically in the Finch Sandbox.
</Note>

## Testing job failures

Use the sandbox to test how your application handles asynchronous job failures before encountering them in production. This applies to [data syncs](/developer-resources/Data-Syncs) and [write-back operations](/implementation-guide/API-Calls/Write-Data) such as deductions enrollments.

Use [Configure Sandbox Job](/api-reference/sandbox/update-sandbox-jobs-configuration) to set the expected `completion_status` for a job type, then trigger it with [Enqueue a New Sandbox Job](/api-reference/sandbox/refresh-job). Verify your application handles the failure response correctly. Job configurations persist until you explicitly change them.

## Testing webhooks

The Finch Sandbox fires webhook events for sandbox connections the same way it does in production. See [Webhooks](/developer-resources/Webhooks) for the full list of events and payload shapes.

To receive webhook events, set up a webhook endpoint in the [Finch Dashboard](https://dashboard.tryfinch.com) under the **Webhooks** tab for the Sandbox application/environment.

<Note>
  If the Webhooks tab is not visible, confirm you have an Editor or Admin role in the dashboard — any Admin member can update your role. If you have the correct role and still don't see the tab, contact [developers@tryfinch.com](mailto:developers@tryfinch.com) with your `client_id` to request that webhooks be enabled.
</Note>

## Testing assisted integrations

Organization and Payroll endpoints behave the same way in sandbox regardless of integration type. Some Deductions endpoints are only available for automated integrations.

When an sandbox connection is created for an **automated integrations**, the connection is active immediately.

Assisted integration connections start in a `pending` state in sandbox, reflecting the manual processing they require in production. To simulate a full assisted integration:

1. Create a connection using any of the [three methods](#creating-a-sandbox-connection), following the assisted setup for each method in the table above.
2. The connection status starts as `pending`. For connections that are assisted for deductions and automated for organization and payroll, the organization and payroll statuses will be connected. If you do not complete the following steps within 3 days, the pending status will change to `Error No Account Setup`, which matches behavior in production. `/employer` requests made while the connection is `pending` return a [`202` response](/api-reference/development-guides/Handling-API-Responses#202-response-codes), matching production behavior for assisted integrations.
3. Call [Update a sandbox account](/api-reference/sandbox/update-sandbox-account) to set the status to `connected`.
4. Call any `/employer` endpoint to retrieve data for the connection.
5. Use the `/sandbox` endpoints to [configure connection data](#configuring-sandbox-data). Run a refresh data sync after each change.

<Note>
  The `manual` parameter defaults to `false`, which excludes assisted integrations from the Finch Connect provider list. Set `manual=true` and `sandbox=finch` in your [session](/implementation-guide/Connect/Set-Up-Finch-Connect#session-configuration) to include them.
</Note>

## Testing deductions

<Note>
  Some integrations are automated for Organization and Payroll but assisted for Deductions. To test this scenario, create a connection using the assisted setup above, then follow the assisted path in step 1 below.
</Note>

<Note>
  Deductions endpoints work only when the connection's authentication method supports Deductions. If Get All Deductions returns a `501`, verify the method through the [`/providers` endpoint](/api-reference/management/providers) — see [Creating a sandbox connection](#creating-a-sandbox-connection).
</Note>

1. Get a `benefit_id`:
   * **Automated** — Call Get All Deductions or Create Deduction. Get All Deductions returns the `benefit_id` directly with no job to track.
   * **Assisted** — Call Create Deduction or Register Deduction. This returns a `job_id` — call [Retrieve a Manual Job](/api-reference/management/retrieve-a-manual-job) and confirm the status is `complete` before continuing.
2. Call Enroll Individuals in Deduction with the `benefit_id`. This returns a `job_id`.
3. Call [Retrieve a Manual Job](/api-reference/management/retrieve-a-manual-job) with the `job_id` to verify enrollment status and result codes.

<Note>
  In the Finch Sandbox, benefits created through the deductions endpoints do not appear on pay statements. To add specific benefits to pay statements, use the [sandbox payment endpoints](/api-reference/sandbox/create-sandbox-payment) when configuring sandbox data.
</Note>

## Connection limits

The Finch Sandbox supports up to 100 connections. Disconnected and staged connections do not count toward the limit.

There is no disconnect option in the Finch Dashboard UI. Use the [Disconnect endpoint](/api-reference/management/disconnect) to disconnect a connection. Store your access tokens so you can disconnect connections when testing is complete.

## Rate limits

* API rate limits are doubled compared to production.
* Sandbox connections allow 10 [refresh data syncs](/api-reference/management/refresh-job) per hour (production allows 1).

***

## Checkpoint + Next Step

<Check>
  After completing this step, you can simulate the employment scenarios your application will encounter with live employers. Once your integration is ready, move on to [testing with provider demo accounts](/implementation-guide/Test/Provider-Sandboxes).
</Check>

## Learn more

* [Quickstart](/how-finch-works/quickstart)
* [Set Up Finch Connect](/implementation-guide/Connect/Set-Up-Finch-Connect)
* [Finch Sandbox — Advanced Testing](https://support.tryfinch.com/articles/8148933505-finch-sandbox-general-best-practices)


# Provider Sandboxes
Source: https://developer.tryfinch.com/implementation-guide/Test/Provider-Sandboxes

Use Provider Sandboxes to test up to five connections with live providers for free. Test with demo accounts or trial accounts that you create in the provider system.

Provider sandboxes allow you to test a full end to end flow including connect to an external system via Finch, modify data directly in that system, and see those changes reflected in API calls to Finch. This can be extremely valuable in the early days of testing to understand the end to end flow of data and to ensure that your application is working as expected.

<Info>Assisted functionality is not supported in the Provider Sandbox.</Info>

## Connecting to a Provider Sandbox

<Warning>
  A Connect session must be created before launching Connect, and the session must declare what type of sandbox connection is being created.

  `finch` and `provider` are the only acceptable values for the `sandbox` key when creating a session.

  See [Finch Sandbox](/implementation-guide/Test/Finch-Sandbox) for how to use `finch` mode.
</Warning>

[Create a new Connect session](/api-reference/connect/new-session) and set `"sandbox": "provider"` in the request body. Launch the session to connect to the provider's test environment.

<Info>
  Because these are external provider connections, Finch allows a maximum of 5
  active provider sandbox connections per application.
</Info>

## Demo Accounts

Some providers support sandbox environments which allow you to create companies, add and modify employees, and often even run payroll, enabling you to understand the true behavior of the system in a safe environment. Finch supports connecting to several of these sandboxes via your Sandbox application.

### Gusto

Complete the following steps to connect to Gusto's sandbox environment:

1. [Sign up for a developer account](https://dev.gusto.com/accounts/sign_up). If you already have a developer acccount from following the [Gusto integration setup instructions](/integrations/guides/Gusto), you may skip this step.<img alt="gusto-signup.gif" />

2. Under the "Demo Companies" tab, select "Create demo company".

3. Once this company is created, you will be provided with a set of credentials. <img alt="" /> You may log in to this sandbox company at [https://app.gusto-demo.com/login](https://app.gusto-demo.com/login). This will allow you to view the company and make any modifications you wish to test various scenarios.

4. To connect to this company via Finch, follow the steps outlined above to configure Finch Connect to display provider sandboxes, select Gusto, and input the credentials into Gusto's OAuth flow. Upon successfull completion of Connect, you will have a working Gusto sandbox connection!

### Deel

Complete the following steps to connect to Deel's sandbox environment. See the [Deel developer docs](https://developer.deel.com/docs/sandbox) for information on Deel sandbox limitations.

1. [Sign up for a demo account](https://demo.letsdeel.com/create-profile?user-type=client). You may fill in any dummy information in the signup forms, including a dummy company name and tax ID.<img alt="" />

2. To connect to this company via Finch, follow the steps outlined [above](#connecting-to-a-provider-sandbox) to configure Finch Connect to display provider sandboxes, select Deel, and input your Deel credentials into Deel's OAuth flow.

### Square

Complete the following steps to connect to Square's sandbox environment. See the [Square developer docs](https://developer.squareup.com/docs/devtools/sandbox/overview#sandbox-limitations) for information on Square sandbox limitations.

1. [Sign up for a free Square developer account](https://squareup.com/login?app=developer\&lang_code=en-US\&return_to=https://developer.squareup.com/apps?lang=en-US\&country=us).

2. After configuring your sandbox application, navigate to Sandbox Test Accounts and open the Square Dashboard for the application you created.
   You must have this dashboard open in another window in order for the OAuth flow to work properly
   <img alt="sqaure-demo.png" />

3. Use the OAuth flow in Finch Connect to connect your new account.

## Trial Accounts

Though not all employment systems offer the test environments described above, many offer self-serve trial accounts. The difference is that these accounts are not in a separate sandbox environment and are meant to eventually convert into real production accounts. However, for testing purposes they can function in much the same way as provider sandbox accounts. Finch also supports connecting to these trial accounts via your Sandbox application. **Note that many of these trial accounts are only offered for a limited period of time, so testing should be performed within that trial period.**

#### Bamboo HR

[Sign up for a free Bamboo HR demo account](https://www.bamboohr.com/signup/) and follow the instructions in Finch Connect to connect your account.

#### Bob

To get a test account for Bob, [fill out an application](https://dash.partnerstack.com/application?company=hibob\&group=techpartnerapplication\&gref=page) and accept Bob's Terms and Conditions. In the notes section, let them know you are a Finch customer and are looking for a test instance.

#### Sage

[Sign up for a free Sage account](https://sage.hr/register). Follow the instructions in Finch Connect to create an API token for your Sage account. **Make sure to hit "Start Fresh" at the top of the page before following the instructions to obtain an API token.** Otherwise, the Integrations tab will not be present under Settings

#### Personio

[Sign up for a Personio partner trial](https://www.personio.com/partner-trial/) and follow the instructions to create an account. Once you have an account, follow the instructions in Finch Connect to generate an API token for your Personio account.

#### Humaans

[Sign up for a free Humaans account](https://app.humaans.io/signup). Follow the instructions in Finch Connect to create an API token for your Humaans account.

***

## Checkpoint + Next Step

<Check>
  After completing this step, you will have tested your application thoroughly
  with mock data from the sandbox and any live providers you set up. You are now
  ready to connect employers in bulk. Therefore, since you will be [managing
  multiple connections](/implementation-guide/Backend-Application/Manage-Connections)
  simultaneously, you must make sure to [store the connection's access
  token](/implementation-guide/Backend-Application/Store-Tokens) properly. This reduces the
  risk of sensative employer data being exposed.
</Check>

## Learn more

* [Finch Sandbox](/implementation-guide/Test/Finch-Sandbox)


# Implementation with Finch
Source: https://developer.tryfinch.com/implementation-guide/go-live-checklist

Finch's Implementation Program is designed to take you from your first API call to a production-ready integration. The resources in this guide were developed by Finch's Implementation Engineering team based on best practices and experience working with hundreds of developers.
The best way to build with Finch is to work through the Implementation Guide in order. Each section below is scoped to a distinct phase of your integration.

## The Implementation Guide

**Implement Finch Connect**
Set up Finch Connect, our embedded authorization flow. This is how your users grant Finch access to their employment systems — getting this right is foundational to everything else.

**Test**
Validate your integration end-to-end before touching production data. Finch's sandbox lets you test against a normalized data model that reflects real provider behavior — so you don't need to test against individual providers to build confidence. For end-to-end flow testing, provider sandboxes are available for a limited set of providers.

**Build Backend Application**
Configure your server-side integration — handling tokens, webhooks, and data storage. This is where most of the core engineering work happens.

**Make Finch API Calls**
A reference for making effective API calls across Finch's product surfaces. Covers pagination, rate limits, and working with the data you care about.

**Integration Preparation**
Fine-tune how your integration behaves in production — configure data access controls and manage your integrations so your users have a seamless experience from day one.

**Deploy and Manage**
Guidance for operating your integration in production — monitoring connections, handling reauthentication, and supporting your end users.

***

## Working with an Implementation Engineer

Customers on Pro and Premier plans are assigned a dedicated Implementation Engineer. Your IE serves as your primary technical point of contact throughout the implementation — providing prescriptive guidance to get you to a healthy, production-ready integration as quickly as possible.

Your IE will lead a structured technical implementation series with your engineering team, answer technical questions, and provide timely advice to prevent blockers and keep your implementation on schedule. Where issues require escalation, your IE will drive urgency internally to keep things moving. They also work with your sales, marketing, and customer success teams to ensure they have the enablement resources they need to support the Finch integration.

**Already a customer?** Your IE will walk you through the Customer Portal and your implementation projects during your Kickoff Call. Once your Kickoff Call is scheduled, you'll have access to your personalized milestones and tasks in the [Customer portal](https://portal.usepylon.com/finch).

***

## Starter plan customers

Starter plan customers don't work with a dedicated Implementation Engineer but have access to two self-guided projects in the Tasks tab of the Customer Portal:  **Starter Plan Implementation Checklist** and **GTM Implementation Milestones & Checklist**. These projects walk you through the same key steps at your own pace.

If you don't see these projects in your portal, email [implementation-team@tryfinch.com](mailto:implementation-team@tryfinch.com) to get access.

***

## Getting started without a contract

Evaluating Finch? The Implementation Guide and sandbox are fully accessible. Start with Implement Finch Connect and work through the guide — it's the same path customers take.


# Field Support
Source: https://developer.tryfinch.com/integrations/field-support

Explore and compare field support across integrations.

<FieldSupportMatrix />


# Integration Types
Source: https://developer.tryfinch.com/integrations/integration-types

Finch automated integrations sync data from HR and payroll providers every 24 hours. For our assisted integrations, data is refreshed every 7 days.

## Automated Integrations

Automated integrations are the primary integration type offered by Finch. With automated integrations, your user authenticates via Finch Connect using OAuth, Credentials, or an API token.

Once authenticated, Finch kicks off an initial data sync, which populates data for all requested products. After that, Finch will sync data with the provider on a 24 hour refresh cadence.

## Assisted Integrations

Assisted integrations are a unique offering from Finch, designed specifically to help employers connect HRIS and payroll systems that are otherwise inaccessible by API.

Assisted integrations are available for customers using Finch Assist, a feature available to customers on our Pro and Premier plans. With this feature, you unlock every integration in our Provider Network and the ability to [add net new integrations](https://support.tryfinch.com/articles/8555609223-how-to-request-new-integrations).

Assisted integrations require employers to set up a 3rd party administrator in their system of record. Once the connection is established, data is refreshed every 7 days and changes can be written back within 2 business days.

The table below summarizes the key differences between the automated and assisted experience:

|                              | **Automated**                    | **Assisted**                |
| ---------------------------- | -------------------------------- | --------------------------- |
| **Coverage (Read)**          | 30+ Providers                    | 175+ Providers              |
| **Coverage (Write)**         | 5 Providers                      | 20+ Providers               |
| **Request new providers**    | No                               | Yes                         |
| **Default data syncs**       | 24 hours                         | 7 days                      |
| **Write deductions**         | 24 hours                         | 2 business days             |
| **On-demand data syncs**     | Yes                              | No                          |
| **Configuration period**     | None                             | 1-2 weeks                   |
| **Custom fields**            | Yes                              | No                          |
| **Authentication Method(s)** | OAuth, API token, or Credentials | 3rd-Party Admin Credentials |
| **Connection Monitoring**    | Yes                              | Yes                         |
| **Pricing**                  | All plans                        | Pro & Premier plans only    |

To see a full list of assisted integrations, see [Providers](/integrations/providers).

To see field support for our assisted integrations, filter by *Authentication Type* > *Assisted* in our [Field Support](/integrations/field-support).

To enable Finch Assist, please reach out to your Developer Success Representative.

## Assisted Connect Flow

### For your user

As with our automated integrations, your user will need to go through [Finch Connect](/how-finch-works/finch-connect) to authenticate. However, instead of our standard login flow the user will follow a set of instructions to set up a new 3rd party administrator. Step-by-step instructions for each provider can be found in our [Authentication Guides](https://support.tryfinch.com/collections/9565019353-authentication-guides).

### For you

Once admin permissions have been verified by Finch, there is a one-time configuration period where you will be unable to pull data or push changes to your users' system. During this time, Finch's product operations team will pull in the requested data and set up the weekly sync. After the initial pull, the data will be refreshed every 7 days.

### Configuration Periods

All assisted integrations require a one-time configuration period before data can be retrieved. See the configuration periods for each product below.

| Product          | Integration Type | Configuration Period |
| ---------------- | ---------------- | -------------------- |
| **Organization** | Assisted         | 2 weeks              |
| **Payroll**      | Assisted         | 2 weeks              |
| **Deductions**   | Assisted         | 1 week               |

Please note that configuration periods can only begin once Finch has verified that the employer has granted the required level of permissions.

### Integrate the Assisted Connect Flow Into Your App

Reach out to **`developers@tryfinch.com`** to enable the Assisted Connect Flow. Then follow the instructions below.

#### 1. Launch Finch Connect with the `manual` flag

Launch [Finch Connect](/implementation-guide/Connect/Set-Up-Finch-Connect) with **`manual=true`** so your user can see all providers that support assisted integrations. After granting your application access, you can retrieve an authorization **`code`** and exchange it for an **`access_token`** as usual.

```bash theme={null}
import Finch from '@tryfinch/finch-api';

const client = new Finch({
  accessToken: 'My Access Token',
});

async function main() {
  const createConnectSessionResponse = await client.connect.sessions.new({
	  products: ["company", "directory", "individual", "employment", "payment", "pay_statement"],
	  customer_id: customer.id, // Your internal customer ID 
	  customer_name: customer.name, // Your customer's name
	  customer_email: customer.email, // The email associated to your customer (optional)
	  integration: { // (optional)
			  provider: 'adp_run', // The provider you want to show up in connect (optional)
			  auth_method: 'credential' // The auth method of the provider to show up (optional)
	  },
	  minutes_to_expire: 20160, // How long you want the session to last for (defaults to 14 days)
	  redirect_uri: '' // The URI to redirect to for the redirect connect flow (optional)
	  sandbox: false // create a sandbox session for a sandbox app (optional)
	  manual: false // A value that, when set to true, displays both Automated and Assisted providers on the selection screen (optional) 
  });

	/**
	 * { 
	 *   "session_id": "<A unique session ID that can be used with embedded connect>",
   *   "connect_url": "<The url of the connect session for the redirect flow>"
   * }
	**/
  console.log(createConnectSessionResponse); 
}

main();
```

#### 2. Handle API Responses

**202 status code response**

With automated integrations, you can create an **`access_token`** and begin making pull and push requests immediately. However, with assisted integrations, there is a delay from when the **`access_token`** is created to when you can use it to make data requests.

Until the **`access_token`** is ready for use, Finch will return an empty response from data endpoints with the HTTP status code **`202`** indicating the request is valid but data is still pending. When the **`access_token`** is ready, data endpoints will return data with the HTTP status code **`200`** as usual.

**Finch Data Retrieved Header**

Since the data is retrieved and refreshed on a periodic cadence, you may want to know the freshness of the data returned by an API call. You can use the **`Finch-Data-Retrieved`** [header](/api-reference/development-guides/Headers) to get the date and time in ISO-8601 format the data was retrieved.

#### 3. Monitor the setup and status of assisted connections

To view the status of your connected employers, you can use either view the Connections page in the [Finch Dashboard](https://dashboard.tryfinch.com/) or the `connection_status` on the [`/introspect`](/api-reference/management/introspect) endpoint.

```json theme={null}
{
  ...
  "authentication_methods": [
    {
      "type": "assisted",
      "connection_status": {
        "status": "pending",
        "message": "The employer has created a token, and we are waiting for access to its provider."
      }
    },
    ...
  ],
  ...
}
```

The status of the connection will be one of the following:

| STATUS               | DESCRIPTION                                                                                                                                                                                           |
| -------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Pending              | The employer has created a token, and we are waiting for access to its provider.                                                                                                                      |
| Processing           | We have received an invitation from the employer's provider with the correct permissions and are in the process of pulling their data for the first time.                                             |
| No Account Set Up    | The employer has created a token, but we have not received an invitation to its system. Please instruct the employer to follow the instructions in Finch Connect to add Finch as a third-party admin. |
| Improper Permissions | The employer has added Finch successfully, but with improper permissions. Please instruct the employer to re-add Finch following the instructions in Finch Connect.                                   |
| Connected            | The connection is set up and Finch is able to access the required data.                                                                                                                               |
| Disconnected         | All accounts for this employer have been disconnected.                                                                                                                                                |


# Provider Setup Instructions
Source: https://developer.tryfinch.com/integrations/provider-setup

Learn about provider-specific instructions required for initial integration setup and deductions setup.

Before setting up any integration through Finch, review the provider's setup requirements below — not all providers require additional setup, only those listed here.

* [Initial Setup Instructions](/integrations/provider-setup#initial-setup-instructions)
* [Deductions Setup Instructions](/integrations/provider-setup#deductions-setup-instructions)

If you can't access a guide in our Help Center, sign up for an account [here](https://support.tryfinch.com).

## Initial Setup Instructions

### ADP Workforce Now Cloud

Finch does not support an integration with ADP Workforce Now Cloud. The [authentication guide](https://support.tryfinch.com/hc/en-us/articles/26207026920084-ADP-Workforce-Now-Add-an-administrator) reminds employers of this when they attempt to connect.

### AlphaStaff

To connect to AlphaStaff, employers provide their 6-digit Client ID in Finch Connect.

After providing this, the employer receives a notification from AlphaStaff within 7 business days confirming Finch's access to their data. Once confirmed, Finch can start fetching data for the employer. During this setup period, any requests to the Finch API using the employer's access tokens return a `202` response with the message "Authorization to this company's data is pending".

If an employer does not know their Client ID, they can [contact AlphaStaff](https://www.alphastaff.com/contact/) to retrieve it.

### Bob

If you have a direct partnership with Bob, provide your Partner Token to Finch so Finch can use that token when sending requests to Bob on your behalf. You can do this directly in the Client Dashboard by going to Integrations, selecting Bob, and providing the value in the Partner Token field.

Being a partner does not change your integration or usage with Finch — this requirement lets Bob track requests it receives on behalf of its direct partners.

<img alt="image" />

### Deel

To integrate with Deel, create a Deel account and OAuth application, then connect your Deel OAuth application to Finch. See the [Deel Onboarding Guide](/integrations/guides/Deel) for detailed instructions.

### FactorialHR

To integrate with Factorial, create a Factorial account and OAuth application, then connect your Factorial OAuth application to Finch. See the [Factorial Onboarding Guide](/integrations/guides/Factorial-HR) for detailed instructions.

### Gusto

Gusto requires a one-time security review before you can access their production API. Finch first vets your security requirements, then provides you with Gusto's security questionnaire to complete. Gusto's review typically takes 2–4 weeks, plus any additional time for follow-up requests from Gusto.

Follow the [Gusto Onboarding Guide](/integrations/guides/Gusto) for the full process, including creating a Gusto Developer Portal account. You'll also be asked to agree to [Gusto's Terms of Service](https://gusto.com/about/terms/developer-terms-of-service).

### Rippling

Enabling a Rippling integration requires an onboarding process that includes a review by Rippling for eligibility to become a Rippling partner. Finch submits the application on your behalf and keeps you updated. See the [Rippling Setup Guide for Developers](https://support.tryfinch.com/articles/1100654962-rippling-setup-requirements-and-overview-for-developers) for more information.

Employers need the Identity & Access Management package for Finch to retrieve data from Rippling.

### TriNet PEO

TriNet requires a one-time security review before you can integrate.

1. **Start the review.** Contact your Implementation Engineer or email [implementation-team@tryfinch.com](mailto:implementation-team@tryfinch.com) to initiate the TriNet security review with Finch.
2. **Complete the field validation spreadsheet.** Finch shares a field validation spreadsheet — fill it out and notify your Implementation Engineer or Finch Technical Support when it's done.
3. **Wait for TriNet's approval.** Finch submits the review to TriNet. Once TriNet approves it, your application appears in their integration center.
4. **Connect employers.** Employers can now authenticate with TriNet by following the directions in Finch Connect.

### Workday

A handful of Workday department fields can be made available upon request. See our [field support](/integrations/field-support) for all fields supported by default.

For [Company](/api-reference/organization/company) data, `departments[].source_id` is populated with the IDs of the Workday supervisory organizations for the **company** and is available **upon request**. `departments[].name` is available for the company by default.

For [Directory](/api-reference/organization/directory) data, `department.source_id` is populated with the ID of Workday supervisory organization for the **worker** and is available **upon request**. `department.name` is available for the worker by default.

For [Employment](/api-reference/organization/employment) data, `department.name` is populated with the name of the Workday supervisory organization for the **worker** and is available by default.

## Deductions Setup Instructions

### Justworks

The `description` field for new Deductions in Justworks must be under 30 characters. Finch's [Create Deduction](/api-reference/deductions/create-deduction) endpoint returns an error if the description exceeds that limit.

### Paychex

Before enabling Deductions for Paychex, confirm that each employer has configured their benefits appropriately in their Paychex account. See our instructions for employers to [configure their Paychex deductions](https://support.tryfinch.com/articles/9462714213-paychex-flex-setup-guide-for-employers).

<Warning>
  Paychex has a 20-character limit for Component Type Description.
</Warning>

### TriNet PEO

To create or edit any employee benefits in TriNet, the employer must contact TriNet directly — the TriNet API can't accommodate creating or editing employer-wide benefits. Employers instead submit a Retirement Plan Summary Setup Form with TriNet's retirement team at least 12 days before the first pay date where a deduction would apply.

Finch currently supports 401k and 401k Roth retirement savings plans. Once the benefit is created, Finch can enroll users into the benefit automatically. TriNet does not support `custom_pre_tax` or `custom_post_tax` deductions and contributions.

### QuickBooks

To enroll an individual in a Roth 401(k) with employer match, QuickBooks requires this approach since match isn't supported on the Roth 401(k) enrollment directly:

1. Create a traditional 401(k) enrollment alongside the Roth enrollment
2. Set the employee deduction amount to \$0 on the traditional enrollment
3. Configure the intended employer match amount as the contribution value on this traditional enrollment


# Provider Network
Source: https://developer.tryfinch.com/integrations/providers

Search 250+ supported HRIS and payroll integrations. See data refresh speeds, supported products, and integration types for each provider.

<Info>
  Badges indicate data refresh cadence per [integration type](/integrations/integration-types):

  * 🟢 **24 hours** / **12 hours** — Automated integrations with daily or faster refreshes
  * 🟠 **7 days** / **2 business days** — Assisted integrations available on Pro and Premier
  * **Request** — Not yet supported, request expanded coverage below.
</Info>

<ProviderNetwork />

<Note>
  **Don't see the provider you're looking for?** Finch can add new providers (in beta) in 7 business days. Learn how you can request new data providers <a href={REQUEST_URL}>here</a>.
</Note>

## FAQ

<AccordionGroup>
  <Accordion title="What does it mean for an integration to be in Beta?">
    If a provider is marked Beta in Finch Connect or in our documentation, it means the integration is ready for an employer to connect, but Finch is waiting for a larger number of established connections before releasing as generally available (GA).
  </Accordion>

  <Accordion title="How is the Beta experience different than GA?">
    A Beta status may mean that the field support and authentication guide for that provider are not yet finalized.

    **For the employer (end-user):** Finch may ask them to contact their HRIS or payroll account representative in order to set up an administrator or request their API keys rather than offering step-by-step instructions to do this self-serve.

    **For the developer:** This means Finch cannot guarantee which fields will be supported for the provider until after the employer has successfully completed Finch Connect.
  </Accordion>

  <Accordion title="What is the difference between Automated and Assisted integrations?">
    Integration types indicate whether the data syncing process is entirely automated or semi-automated (assisted). Automated integrations typically offer faster data sync frequencies, but require the underlying system to have an available API. Assisted integrations extend the coverage Finch can offer by supplementing data collection or management through our product operations team.

    For more details, see [Integration Types](/integrations/integration-types).
  </Accordion>
</AccordionGroup>


# Benefits
Source: https://developer.tryfinch.com/products/benefits/Overview

Read benefit plans, employee enrollments, and covered dependents from an employer's benefits administration system with Finch's Benefits APIs.

Finch's Benefits product reads structured benefits enrollment data from an employer's HCM (human capital management) system: the benefit plans the company offers, each employee's enrollment in those plans, and the dependents covered under each enrollment.

<Note>
  Benefits is in closed beta. To join the beta, contact [developers@tryfinch.com](mailto:developers@tryfinch.com). Endpoint paths and field names may change before general availability.
</Note>

## What you can do

* **Read the plan catalog** — list every benefit plan the employer offers, with plan type, carrier, plan year, and coverage tiers.
* **Read enrollment state** — see who is enrolled in which plan, at what coverage tier, with effective dates, waiver status, and employee and employer contribution amounts.
* **Read covered dependents** — read demographic details for the spouses and children covered under an enrollment.
* **Read enrollment changes** — enrollment records reflect new elections, qualifying life events, and terminations; compare reads to detect changes in your system.

## Data model: Plans, Enrollments, and Dependents

The Benefits product introduces three objects:

| Object         | What it represents                                                                                                                                                                                                                                                                                   |
| -------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Plan**       | The employer's benefit catalog — static reference data for each plan: type (`medical`, `dental`, `vision`, `life`, `disability_short_term`, `disability_long_term`, `other`), name, carrier, plan year, deduction code, and available coverage tiers. Nothing about individual employees lives here. |
| **Enrollment** | The link between an individual and a plan: enrollment status, coverage tier, effective and termination dates, contribution amounts, and the covered `dependent_id`s. An employee enrolled in a medical plan and a dental plan has two enrollment records.                                            |
| **Dependent**  | A person covered under an employee's enrollment: name, date of birth, and relationship, with links back to the `individual_id` and `enrollment_id`s.                                                                                                                                                 |

Coverage tiers (`employee_only`, `employee_spouse`, `employee_child`, `employee_children`, `employee_family`) apply to health plans. Life and disability plans express coverage as a dollar amount or percentage of salary instead, so `coverage_tier` returns the value as it is represented in the provider system.

## Benefits endpoints

| Endpoint                                                                           | Description                                                                                  |
| ---------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------- |
| [`GET /employer/plans`](/api-reference/benefits/list-plans)                        | List all plans for the company, filterable by plan type.                                     |
| [`GET /employer/plans/{plan_id}`](/api-reference/benefits/get-plan)                | Details for a single plan.                                                                   |
| [`GET /employer/plans-enrollments`](/api-reference/benefits/list-plan-enrollments) | List enrollments across all plans.                                                           |
| [`POST /employer/plans-enrollments`](/api-reference/benefits/get-plan-enrollments) | Batch read enrollments by ID — for example, from the `enrollment_id`s on a dependent record. |
| [`GET /employer/plans-dependents`](/api-reference/benefits/list-plan-dependents)   | List dependents across all plans.                                                            |
| [`POST /employer/plans-dependents`](/api-reference/benefits/get-plan-dependents)   | Batch read dependents by ID.                                                                 |

## How Benefits differs from Deductions

Finch's [Deductions](/products/deductions/Overview) product is payroll-centric and write-oriented:a deduction is a payroll line item that withholds money from an employee's paycheck, a contribution is the employer-paid amount that funds the same benefit. The Deductions API creates and manages both. Benefits is benefits-centric and read-only: it returns the canonical plan and enrollment records from the benefits administration side of the employer's system.

The two overlap but are not one-to-one. A fully employer-paid plan produces an enrollment with no employee deduction, and a generic pre-tax deduction code may not map to any benefit plan. Use Benefits when you need authoritative enrollment state — coverage tier, carrier, covered dependents. Use Deductions when you need to see or change what is withheld each pay period.

## Permissions

Benefits data is scoped as its own Finch product, separate from Organization and Payroll. Plans, enrollments, and dependents each have a distinct scope, and the dependents scope is permissioned separately because dependent records contain sensitive personal information.

Benefits uses the same connection you already have for Organization and Payroll data — no separate authentication flow for the employer. To add Benefits scopes to an existing connection, send the employer through [re-authentication](/developer-resources/Reauthentication).

## Beta providers and limitations

Benefits reads from HCM platforms where the employer manages benefits in the same system as payroll and HR. Employers who administer benefits in a separate, standalone platform are not supported during the beta.

* ADP Workforce Now is the first provider available in the beta. Workday and UKG are coming soon, with additional providers to follow.
* For field availability, check the [Field Support matrix](/integrations/field-support).
* Benefits does not return beneficiary designations, evidence-of-insurability status, or enrollment history, so workflows that depend on those need another data source.

## Common use cases

* **Benefits navigation and enrollment** — show employees their plans, coverage tiers, and covered dependents, and identify unenrolled employees for enrollment outreach.
* **Insurance carriers** — confirm an employee was covered on a given date, in a given plan, at a given tier, for group life, disability, and supplemental claims.
* **Dependent eligibility verification** — confirm a dependent was covered under an enrollment at claim time.
* **Post-enrollment reporting** — report participation and premium totals per plan from employee and employer contribution amounts.

## Next steps

<CardGroup>
  <Card title="Join the beta" icon="envelope" href="mailto:developers@tryfinch.com">
    Contact [developers@tryfinch.com](mailto:developers@tryfinch.com) for beta access.
  </Card>

  <Card title="Data model" icon="diagram-project" href="/how-finch-works/data-model#benefits-plans-enrollments-and-dependents">
    How Plans, Enrollments, and Dependents fit Finch's data model.
  </Card>

  <Card title="Reauthentication" icon="key" href="/developer-resources/Reauthentication">
    Add Benefits scopes to existing connections.
  </Card>

  <Card title="Deductions" icon="hand-holding-dollar" href="/products/deductions/Overview">
    Read and write the payroll side of benefits.
  </Card>
</CardGroup>


# Deductions
Source: https://developer.tryfinch.com/products/deductions/Overview

Read and write payroll deductions and contributions across providers with Finch's Deductions API — manage 401(k), HSA, FSA, and other benefit deductions.

Finch's Deductions product reads and writes benefit deductions and contributions in an employer's payroll system. You can create company-level deductions, enroll and unenroll individuals, and update contribution amounts across providers with one set of endpoints — no SFTP or per-provider file exchange required.

A  deduction is a payroll line item that withholds money from an employee's paycheck. A contribution is the related employer-paid amount that goes into the same benefit — it's paid on the employee's behalf and does not affect take-home pay. Finch supports deduction types for retirement, medical, and fringe benefits, such as 401(k), HSA, FSA, and Section 125 plans.

<Info>
  For historical reasons, Deductions endpoints live under the `/employer/benefits` path.
</Info>

## What you can do

* **Create deductions** — set up a new company-level deduction in the payroll system, or register one that already exists.
* **Manage enrollments** — enroll individuals in a deduction with per-person amounts, update their configurations, and unenroll them.
* **Read deduction state** — list all company-level deductions, see who is enrolled, and read each individual's employee and employer amounts.

## Read endpoints

| Endpoint                                                                                                      | Description                                                                        |
| ------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------- |
| [`GET /employer/benefits`](/api-reference/deductions/get-all-deductions)                                      | All company-level deductions for the employer.                                     |
| [`GET /employer/benefits/{benefit_id}`](/api-reference/deductions/get-deduction)                              | Details for a single deduction: type, description, and frequency.                  |
| [`GET /employer/benefits/{benefit_id}/enrolled`](/api-reference/deductions/get-enrolled-individuals)          | The individuals currently enrolled in a deduction.                                 |
| [`GET /employer/benefits/{benefit_id}/individuals`](/api-reference/deductions/get-deductions-for-individuals) | Enrollment configurations — employee and employer amounts — for given individuals. |

## Write endpoints

| Endpoint                                                                                                               | Description                                                                                  |
| ---------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------- |
| [`POST /employer/benefits`](/api-reference/deductions/create-deduction)                                                | Create a new company-level deduction in the payroll system.                                  |
| [`POST /employer/benefits/register`](/api-reference/deductions/register-deduction)                                     | Register a deduction that already exists in the provider so you can manage it through Finch. |
| [`POST /employer/benefits/{benefit_id}`](/api-reference/deductions/update-deduction)                                   | Update an existing deduction.                                                                |
| [`POST /employer/benefits/{benefit_id}/individuals`](/api-reference/deductions/enroll-individuals-in-deductions)       | Enroll individuals, or overwrite existing enrollment configurations.                         |
| [`DELETE /employer/benefits/{benefit_id}/individuals`](/api-reference/deductions/unenroll-individuals-from-deductions) | Unenroll individuals from a deduction.                                                       |

Write requests are asynchronous: each returns a `job_id` you poll for completion, and batched enrollments can partially succeed. Read the [async Deductions guide](/products/deductions/Async-Deductions) for job polling, batch response handling, and payroll cutoff timing.

## Provider coverage

Supported deduction types and operations vary by provider — for example, some providers do not allow Finch to create new deductions, only to manage existing ones. Call the [`/providers`](/api-reference/management/providers) endpoint and check its `benefits_support` field, or review the [Providers page](/integrations/providers), before you build. Some providers also require [deductions setup steps](/integrations/provider-setup#deductions-setup-instructions) before the first write.

## Combine with Organization and Payroll

Deductions pairs with Finch's read products for end-to-end control: [Organization](/products/organization/Overview) shows employment changes that affect eligibility, [Payroll](/products/payroll/Overview) pay statements show whether a deduction was actually applied to a paycheck, and Deductions writes the change itself.

Looking for plan and enrollment data, such as carrier, coverage tier, or covered dependents, rather than paycheck withholding? That is Finch's [Benefits](/products/benefits/Overview) product, currently in closed beta. Deductions is payroll-centric and write-oriented; Benefits is benefits-centric and read-only. The two are complementary.

## Common use cases

* **Retirement and 401(k)** — set up and update employee 401(k) contributions directly in payroll.
* **Tax-advantaged accounts** — manage pre- and post-tax deductions for HSA, FSA, and commuter benefits.
* **Employer-sponsored benefits** — create and manage employer contributions alongside employee deductions.

## Next steps

<CardGroup>
  <Card title="Deductions API reference" icon="code" href="/api-reference/deductions/get-all-deductions">
    Request and response schemas for all Deductions endpoints.
  </Card>

  <Card title="Async Deductions guide" icon="arrows-rotate" href="/products/deductions/Async-Deductions">
    Job polling, batch responses, and payroll cutoff timing.
  </Card>

  <Card title="Write data" icon="pen-to-square" href="/implementation-guide/API-Calls/Write-Data">
    Implementation patterns for writing to payroll systems.
  </Card>

  <Card title="Provider setup" icon="wrench" href="/integrations/provider-setup#deductions-setup-instructions">
    Provider-specific requirements before your first write.
  </Card>
</CardGroup>

Questions about whether Deductions fits your use case? Contact [developers@tryfinch.com](mailto:developers@tryfinch.com) or [talk to our team](https://www.tryfinch.com/sales).


# Documents
Source: https://developer.tryfinch.com/products/documents/Overview

Read structured data from employee tax documents in HR and payroll systems with Finch's Documents API. In beta with support for W-4 forms.

Finch's Documents product reads structured data out of employee documents stored in an employer's HR or payroll system. Finch parses each document with ML-based extraction and returns standardized, classified fields — across multiple document formats — so you don't have to collect the data manually.

<Note>
  Documents is in beta. W-4 forms are supported today, and the API is designed to expand to additional document types such as W-2 and 941 forms.
</Note>

## What you can do

* **List available documents** — see which documents exist for an individual employee or the whole company, filtered by document type.
* **Read parsed W-4 data** — filing status, dependent withholding, and additional withholding details, without asking employees to re-enter them.

## Documents endpoints

| Endpoint                                                                         | Description                                                                                                               |
| -------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------- |
| [`GET /employer/documents`](/api-reference/documents/get-documents)              | The list of documents available in the HR or payroll system, filterable by individual and document type.                  |
| [`GET /employer/documents/{document_id}`](/api-reference/documents/get-document) | Parsed field data for a single document. For W-4 forms: filing status, dependent withholding, and additional withholding. |

Documents is asynchronous: queue a job with [`POST /jobs/automated`](/api-reference/management/enqueue-a-new-automated-job) before reading, so Finch syncs the latest documents from the provider.

## Permissions

Employers grant access to Documents alongside your other product scopes when they confirm permissions in Finch Connect. To add Documents to an existing connection, send the employer through [re-authentication](/developer-resources/Reauthentication) to approve the additional scope.

## Common use cases

* **Retirement and 401(k)** — enrich participant records with automatically collected W-4 data.
* **Benefits quoting** — speed up quoting with filing status and dependent information straight from the W-4.
* **Financial planning and analysis** — summarize additional withholdings and exemptions across the workforce.

## Next steps

<CardGroup>
  <Card title="Documents API reference" icon="code" href="/api-reference/documents/get-documents">
    Request and response schemas for both Documents endpoints.
  </Card>

  <Card title="Automated jobs" icon="arrows-rotate" href="/api-reference/management/enqueue-a-new-automated-job">
    Queue the document sync that powers these endpoints.
  </Card>

  <Card title="Reauthentication" icon="key" href="/developer-resources/Reauthentication">
    Add the Documents scope to existing connections.
  </Card>

  <Card title="Data syncs" icon="clock" href="/developer-resources/Data-Syncs">
    How and when Finch refreshes data from providers.
  </Card>
</CardGroup>

Questions about whether Documents fits your use case? Contact [developers@tryfinch.com](mailto:developers@tryfinch.com) or [talk to our team](https://www.tryfinch.com/sales).


# Organization
Source: https://developer.tryfinch.com/products/organization/Overview

Read company, directory, individual, and employment data from an employer's HRIS or payroll system through Finch's four Organization API endpoints.

Finch's Organization product reads company and employee data from an employer's HRIS or payroll system. Four read-only endpoints return the employer's company details, a directory of the entire workforce, and personal and employment records for each individual.

## What you can do

* **Read the workforce directory** — list every individual at the company, active and terminated; compare reads to detect new hires, terminations, and reporting-structure changes in your system.
* **Read employment details** — title, department, employment status, compensation, start date, and work location for every employee.
* **Read company information** — Finch returns the employer's legal name, Employer Identification Number (EIN), and corporate address; use them to verify the employer in your records.
* **Trigger downstream workflows** — subscribe to [webhooks](/developer-resources/Webhooks) to start onboarding, offboarding, or eligibility processes in your product when employment data changes.

## Organization endpoints

| Endpoint                                                              | Description                                                                                                                                          |
| --------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
| [`GET /employer/company`](/api-reference/organization/company)        | Company-level details: legal name, EIN, entity type, primary address, and bank accounts.                                                             |
| [`GET /employer/directory`](/api-reference/organization/directory)    | A paginated list of every individual at the company — active and terminated — with department and manager relationships.                             |
| [`POST /employer/individual`](/api-reference/organization/individual) | Personal details for one or more individuals: name, date of birth, residence, emails, and phone numbers.                                             |
| [`POST /employer/employment`](/api-reference/organization/employment) | Employment details for one or more individuals: title, department, employment type and status, start and end dates, compensation, and work location. |

`/individual` and `/employment` are batch read endpoints: pass the `individual_id` values returned by `/directory` in the request body. See [Read data](/implementation-guide/API-Calls/Read-Data) for the request pattern.

## Provider coverage

Field availability varies by provider. Check the [Field Support matrix](/integrations/field-support) to confirm that the fields your use case requires are available from the providers your customers use.

## Common use cases

* **Workforce management** — trigger onboarding and offboarding processes when employees join or leave.
* **Compensation management** — benchmark compensation by title, department, location, and tenure.
* **Workers' compensation** — improve premium accuracy with job title, location, and pay data read directly from the employer's system.
* **Security and compliance** — keep certification and access requirements current with live directory data.
* **People analytics** — power workforce insights with organization and demographic data.

## Next steps

<CardGroup>
  <Card title="Organization API reference" icon="code" href="/api-reference/organization/company">
    Request and response schemas for all four endpoints.
  </Card>

  <Card title="Data model" icon="diagram-project" href="/how-finch-works/data-model#organization-company-individual-and-employment">
    How Company, Individual, and Employment records relate.
  </Card>

  <Card title="Quickstart" icon="rocket" href="/how-finch-works/quickstart">
    Make your first API call with sandbox data.
  </Card>

  <Card title="Payroll" icon="money-check-dollar" href="/products/payroll/Overview">
    Pair Organization with pay run and pay statement data.
  </Card>
</CardGroup>

Questions about whether Organization fits your use case? Contact [developers@tryfinch.com](mailto:developers@tryfinch.com) or [talk to our team](https://www.tryfinch.com/sales).


# Payroll
Source: https://developer.tryfinch.com/products/payroll/Overview

Read company pay runs, employee pay statements, and pay groups from an employer's payroll system through Finch's Payroll API endpoints.

Finch's Payroll product reads an employer's payroll history — from company-level pay runs down to the individual line items on each employee's pay statement. Finch classifies every line item with standard types for earnings, taxes, employee deductions, and employer contributions, so the data is consistent across providers.

## What you can do

* **Read pay run history** — list every payment in a date range with gross and net totals and the individuals paid.
* **Read pay statement detail** — earnings, taxes, deductions, and contributions line by line; use them to verify in your system what was withheld and contributed each pay period.
* **Calculate year-to-date earnings** — aggregate pay statements to compute [YTD wages](/developer-resources/Calculating-YTD-Wages) for compliance and reporting.
* **Determine pay frequency** — read pay groups to know each employee's on-cycle payment schedule.
* **Standardize line items** — use Finch's [pay statement item classification](/developer-resources/Pay-Statement-Type-Classification) and [custom rules](/developer-resources/Pay-Statement-Items-Rules) to label items for your use case.

## Payroll endpoints

| Endpoint                                                                             | Description                                                                                                                                     |
| ------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------- |
| [`GET /employer/payment`](/api-reference/payroll/payment)                            | Company pay runs for a date range: pay period, pay date, totals, and the `individual_id`s included in each pay run.                             |
| [`POST /employer/pay-statement`](/api-reference/payroll/pay-statement)               | Pay statements for one or more payments: earnings, taxes, employee deductions, and employer contributions, with amounts, currencies, and types. |
| [`GET /employer/pay-groups`](/api-reference/payroll/get-pay-groups)                  | All pay groups for the employer, including name and pay frequency. Filterable by individual.                                                    |
| [`GET /employer/pay-groups/{pay_group_id}`](/api-reference/payroll/get-pay-group)    | Details for a single pay group.                                                                                                                 |
| [`GET /employer/pay-statement-item`](/api-reference/payroll/get-pay-statement-items) | Distinct pay statement items for the connection — useful for discovering the earning, tax, and deduction labels a provider uses.                |

To read pay statements, first call `/payment` for your date range, then pass the returned `payment_id`s to `/pay-statement`. See [Read data](/implementation-guide/API-Calls/Read-Data) for the request pattern.

You can also create [rules](/api-reference/payroll/create-rule) that attach custom attributes to pay statement items — for example, labeling items that meet certain conditions as a pre-tax 401(k).

## Provider coverage

Field availability varies by provider. Check the [Field Support matrix](/integrations/field-support) to confirm that the fields your use case requires are available from the providers your customers use.

## Common use cases

* **Retirement and 401(k)** — run recordkeeping audits against standardized, historical payroll data.
* **Benefits administration** — confirm deductions and contributions were applied by reading pay statement line items.
* **Financial planning and analysis** — base headcount and cost calculations on payroll data from hundreds of providers.
* **Compensation management** — build compensation benchmarks from actual pay data.
* **Tax credits** — determine what percentage of payroll expense went to qualifying activities.

## Next steps

<CardGroup>
  <Card title="Payroll API reference" icon="code" href="/api-reference/payroll/payment">
    Request and response schemas for all Payroll endpoints.
  </Card>

  <Card title="Data model" icon="diagram-project" href="/how-finch-works/data-model#payroll-payments-and-pay-statements">
    How Payments, Pay Statements, and Pay Statement Items relate.
  </Card>

  <Card title="Batch requests" icon="layer-group" href="/implementation-guide/API-Calls/Batch-Requests">
    Read pay statements efficiently at scale.
  </Card>

  <Card title="Deductions" icon="hand-holding-dollar" href="/products/deductions/Overview">
    Write the deductions and contributions you read here.
  </Card>
</CardGroup>

Questions about whether Payroll fits your use case? Contact [developers@tryfinch.com](mailto:developers@tryfinch.com) or [talk to our team](https://www.tryfinch.com/sales).