# Create a new connect 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 ` # Create a new Connect session for reauthentication 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 ` # 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** 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 7 day SLA for Assisted providers. # 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. 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. ### 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`) | # Get All Deductions get /employer/benefits List all company-wide deductions and contributions. **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 items. # Get Deduction get /employer/benefits/{benefit_id} Lists deductions and contributions information for a given item **Availability: Automated providers only** This is a live request to the provider. Latencies may vary from seconds to minutes depending on the provider. # 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. # 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 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. # 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 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 ## Finch IDs Finch IDs (UUIDs) remain constant for all company connections that utilize the same authentication method. However, if you have multiple access tokens for a company connection, and they were generated via different authentication methods, the Finch IDs *may not* be consistent across these tokens. For instance, if an employer first authenticates with credentials (username/password), and then later authenticates again using an API token auth method, the two access tokens generated from these authentications *may* have different Finch IDs. This is because the underyling employment system IDs used to identify an employee or payment may be different depending on the authentication method, and Finch maps its UUIDs to those underlying employment system IDs. You should keep this in mind when incorporating Finch integrations into your application. ## Null Values API responses can return `null` values for some fields. This can happen for a few different reasons— 1. The employment system does not support the field. 2. The field is supported by the employment system but the data has not been filled in by the payroll administrator of a company. 3. Finch was not able to infer a reasonable value (for example, the categorization of a tax). Ensure your Finch integration is resilient to `null` values. ## 202 Response Codes In some cases, requests to the Finch API may return a [`202 accepted`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/202). This is the response Finch returns when the connection is created, but data is not yet available. After data is available, this response will no longer be sent. This is often the case for async operations. Requests that may 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) which exist but have not yet been fetched * [Authentication fallback](/implementation-guide/Integration-Preparation/Configure-Auth-Methods#set-up-authentication-fallback). * Additional use cases may be added in the future. All applications should be built to account for these 202 responses. The key behaviors your application should exhibit are: * **Retry**: Your application should retry the request after a delay. For assisted connections, keep in mind that the SLA for first data sync is 14 days. * **Backoff**: If the request continues to return a 202 response, your application should increase the delay between retries. * Do not try to process the data until a successful response is received. Examples of 202 Responses: ```json { "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" } ``` # 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:
`success`: the last attempt succeeded
`error`: the last attempt errored
`partial_error`: (batch requests only) the last attempt succeeded for some items in the batch and failed for others. | # 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` | 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 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. **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. 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 | | `individual` | 20 | | `employment` | 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 // 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 // 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 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. **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`** Our current version is **2020-09-17** The `Finch-API-Version` header must be set for every single request to our API. # 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 now deprecated in favor of conforming to our standard error formatting, and will be removed entirely in June 2023.** 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). Ensure your application can handle both types of errors from a batch API call. ```jsx Response level 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 Response HTTP Status Code: 500 Error Body: { "code": 500, "name": "server_error", "message": "Internal server error" } ``` Refer to the API reference to ensure your application handles errors from each batch endpoint correctly as response schemas vary by endpoint. # 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](/api-reference/development-guides/Rate-Limits#finch-connect-rate-limits). | | `rate_limit_exceeded_error` | `upstream_rate_limit_exceeded` | 429 | The application has exceeded [upstream provider rate limits](/api-reference/development-guides/Rate-Limits#upstream-provider-rate-limits). | | `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 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 get /employer/documents **Beta:** This endpoint is in beta and may change. Retrieve a list of company-wide documents. # Create Access Token post /auth/token Exchange the authorization code for an access token # 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. # 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 get /introspect Read account information associated with an `access_token` # 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 get /providers Return details on all available payroll and HR systems. # 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 get /jobs/manual/{job_id} Get a manual job by `job_id`. Manual jobs are completed by a human and include Assisted Benefits jobs. # Retrieve an Automated Job get /jobs/automated/{job_id} Get an automated job by `job_id`. # Company get /employer/company Read basic company data # Directory get /employer/directory Read company directory and organization structure # 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 post /employer/individual Read individual data, excluding income and employment data # Get Pay Group get /employer/pay-groups/{pay_group_id} Read information from a single pay group # Get All Pay Groups get /employer/pay-groups Read company pay groups and frequencies # 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 get /employer/payment Read payroll and contractor related payments by the company. # Create a new sandbox account post /sandbox/connections/accounts Create a new account for an existing connection (company/provider pair) # Create a new Sandbox Connection post /sandbox/connections Create a new connection (new company/provider pair) with a new account # Add new individuals to a sandbox company post /sandbox/directory # Add a new 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 get /sandbox/jobs/configuration # Enqueue a new sandbox job post /sandbox/jobs Analagous to [`POST /jobs/automated`](/api-reference/management/refresh-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. 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. # Update a 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 put /sandbox/company # Update sandbox employment put /sandbox/employment/{individual_id} # Update sandbox individual put /sandbox/individual/{individual_id} # Update configurations for sandbox jobs put /sandbox/jobs/configuration # W-2 Box 1 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 | Occurence | Group | | -- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- | :---------------------------------------------------------------------------------------------------------- | | 1 | "Total wages, bonuses (including signing bonuses), prizes, and (...) full text | ALWAYS | [Earning](https://developer.tryfinch.com/how-finch-works/unified-employment-api-glossary#earning) | | 2 | "Total noncash payments, including certain fringe benefits. See Fringe benefits." | COMMON | [Earning](https://developer.tryfinch.com/how-finch-works/unified-employment-api-glossary#earning) | | 3 | "Total tips reported by the employee to the employer (not allocated tips)." | COMMON | [Earning](https://developer.tryfinch.com/how-finch-works/unified-employment-api-glossary#earning) | | 4 | "Certain employee business expense reimbursements. See Employee business expense reimbursements." | COMMON | [Earning](https://developer.tryfinch.com/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." | RARE | [Contribution](https://developer.tryfinch.com/how-finch-works/unified-employment-api-glossary#contribution) | | 6 | "Taxable benefits from a section 125 (cafeteria) plan if the employee chooses cash." | RARE | [Contribution](https://developer.tryfinch.com/how-finch-works/unified-employment-api-glossary#contribution) | | 7 | "Employee contributions to an Archer MSA." | N/A | [Deduction](https://developer.tryfinch.com/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." | N/A | [Contribution](https://developer.tryfinch.com/how-finch-works/unified-employment-api-glossary#contribution) | | 9 | "Employer contributions for qualified long-term care services to the extent (...) full text | RARE | [Contribution](https://developer.tryfinch.com/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." | COMMON | [Contribution](https://developer.tryfinch.com/how-finch-works/unified-employment-api-glossary#contribution) | | 11 | "Unless excludable under Educational assistance programs, payments for (...) full text | COMMON | [Earning](https://developer.tryfinch.com/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 (...) full text | ALWAYS | [Tax](https://developer.tryfinch.com/how-finch-works/unified-employment-api-glossary#tax) | | 13 | "Designated Roth contributions made under a section 401(k) plan, a section 403(b) salary (...) full text | COMMON | [Deduction](https://developer.tryfinch.com/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." | RARE | [Earning](https://developer.tryfinch.com/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." | RARE | [Earning](https://developer.tryfinch.com/how-finch-works/unified-employment-api-glossary#earning) | | 16 | "Payments to statutory employees who are subject to social security and Medicare taxes but (...) full text | RARE | [Earning](https://developer.tryfinch.com/how-finch-works/unified-employment-api-glossary#earning) | | 17 | "Cost of current insurance protection under a compensatory split-dollar life insurance arrangement." | RARE | [Contribution](https://developer.tryfinch.com/how-finch-works/unified-employment-api-glossary#contribution) | | 18 | "Employee contributions to a health savings account (HSA)." | COMMON | [Deduction](https://developer.tryfinch.com/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](https://developer.tryfinch.com/how-finch-works/unified-employment-api-glossary#contribution) | | 20 | "Amounts includible in income under section 409A from an NQDC because the amounts are (...) full text | RARE | [Earning](https://developer.tryfinch.com/how-finch-works/unified-employment-api-glossary#earning) | | 21 | "Nonqualified moving expenses and expense reimbursements. See Moving expenses." | COMMON | [Earning](https://developer.tryfinch.com/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." | RARE | [Earning](https://developer.tryfinch.com/how-finch-works/unified-employment-api-glossary#earning) | | 23 | "All other compensation, including certain scholarship and fellowship grants (...) full text | COMMON | [Earning](https://developer.tryfinch.com/how-finch-works/unified-employment-api-glossary#earning) | | 24 | "Salary reduction contributions made to a Roth IRA pursuant to a SEP arrangement or (...) full text | RARE | [Deduction](https://developer.tryfinch.com/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 [Finch's Pay Statement data](https://developer.tryfinch.com/api-reference/payroll/pay-statement).** The table above highlights where to find criteria within [Pay Statement object groups (Earning, Tax, Deduction, Contribution)](https://developer.tryfinch.com/api-reference/payroll/pay-statement). The majority of these criteria require simple suming of line-item-amounts over a given calendar year - [Finch's type classification](https://developer.tryfinch.com/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 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 ![ytd-gross-wages.png](https://mintlify.s3.us-west-1.amazonaws.com/finch/images/ytd-gross-wages.png) # 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 available exclusively to **Scale Tier customers**. To enable Data Access Controls for your account, please contact [developers@tryfinch.com](mailto:developers@tryfinch.com). ## 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, address details, and SSN." | 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 | | SSN | SSN | Read employee SSN | ### 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 In this guide, you'll learn about data sync cadences and batch requests. Finch syncs data on a 24-hour or 7-day cadence depending on the integration type. Finch syncs data for [Automated](/integrations/integration-types#automated-integrations) providers on a 24-hour cadence and for [Assisted](/integrations/integration-types#assisted-integrations) providers on a 7-day cadence. Finch API responses will return data from the most recent successful sync. Performing data syncs in this way ensures that latency for all Finch API requests should remain under 200ms. After an employer authorizes your application through Finch Connect, Finch will enqueue an initial data fetch job which will fetch all relevant data for the employer connection. For automated providers, if you attempt to request data before the initial sync has completed, Finch will request live data from the provider. Live request latencies may range from several seconds to minutes for large batch sizes. Once the initial data sync has completed, Finch API responses will return the synced data. You can use several Finch response headers to determine the freshness of the data you receive: | 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. | ### Batch requests For batch endpoints (`/employment`, `/individual`, `/pay-statement`) Finch syncs all of the data for the connection in one atomic operation. This ensures that all items in the batch response you receive are from the same data sync. ### Pay statements Generally, Finch currently fetches pay statements from the start of 2020. However, there are certain providers with restrictions for which Finch can fetch data for shorter time periods. These include: * Paychex Flex: 14 months of pay statement data * Paycom: 2 years of pay statement data Because there is significantly more pay statement data than payment data, it may be the case that individual pay statements take much longer to fetch than payments. Therefore if you have received a `payment_id` from the `/payment` endpoint, and try to use it in a `/pay-statement` request, it is possible the pay statement has not been fetched yet. In this case, Finch will return a 202 in the **body** of the `/pay-statement` request. The response will look like this: ```json { "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 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=` 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-Tokens) 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 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. 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. 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 https://connect.tryfinch.com/authorize? &client_id= &products=company%20directory%20individual%20employment%20payment%20pay_statement%20ssn &redirect_uri=https://example.com &sandbox=true ``` ## Request ```bash 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 { "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 { "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" } } } ] } ``` # 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 Learn what to do if Finch returns a 401 Unauthorized HTTP status code error with a 'finch_code' of 'reauthenticate_user' when a connection fails. If Finch ever loses a connection with an employer's provider system, we will return 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 { "code": 401, "name": "authentication_error", "finch_code": "reauthenticate_user", "message": "Please reauthenticate user" } ``` If an access token is returning this error, follow the [reauthentication process](/implementation-guide/Backend-Application/Mitigate-Errors#reauthentication-errors) to reconnect the employer. # 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. 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. ### 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. Finch's API does not always return emails. We find `first_name`, `last_name`, and `dob` are more consistent than `email`s. ### 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 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. Request Forwarding is available for customers in our Scale tier. To enable Request Forwarding for your account, reach out to your Developer Success Representative or email [developers@tryfinch.com](mailto:developers@tryfinch.com). ### 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. ![finch\_standard\_api.png](https://mintlify.s3.us-west-1.amazonaws.com/finch/images/request-forwarding/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. ![finch\_request\_forwarding.png](https://mintlify.s3.us-west-1.amazonaws.com/finch/images/request-forwarding/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) | | 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) | | Workday1 | `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) | 1 See details on making Workday requests using Request Forwarding [here](/integrations/guides/workday-request-forwarding). ### 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 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 { "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 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 { "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 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 { "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 { 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 Explore our frontend and backend SDK repositories. Finch supports SDKs in JavaScript, React, Node, Python, Java, Kotlin, and Go. ## Frontend SDKs Finch's frontend SDKs allow you to [embed Finch Connect](/implementation-guide/Connect/Set-Up-Finch-Connect#embedded-finch-connect) into your application, enabling you to provide a seamless integration experience for your users. Take a look at our repositories below: ## 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. If you do not see your language here, reach out to us! # Webhooks Get notified when data has changed with Finch Webhooks. You can create, test, and manage Finch Webhooks in the Developer Dashboard. Finch offers webhooks to inform you of changes to data models in a push-notification fashion, rather than you having to rely exclusively on pulling data from our API. A webhook URL is a HTTPS endpoint configured by your application to receive requests from Finch. Webhooks are available for customers in our Scale tier. ## Webhook Registration Webhook endpoints should use HTTPS and expect to receive POST requests with the following headers: ```json { "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/). ![webhooksCreate.png](https://mintlify.s3.us-west-1.amazonaws.com/finch/images/webhooks/webhooksCreate.png) After registering a webhook, you will be provided with a webhook secret. This secret can be used to validate that the webhooks you receive were sent by Finch. ![webhooksSecret](https://mintlify.s3.us-west-1.amazonaws.com/finch/images/webhooks/webhooksSecret.png) This secret will only be displayed once, so we recommend you store it as soon as you receive it. See the Webhook Verification section for more details. ## Webhook Payload Structure ### Common Fields Each webhook event contains the following fields in the response body: | Field Name | Type | Description | | --------------- | ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `company_id` | string\ | Unique Finch id of the company for which data has been updated. | | `account_id` | string\ | Unique Finch id of the employer account that was used to make this connection. | | `connection_id` | string\ | Unique Finch id created when an employer successfully authenticates through Finch Connect that represents a unique connection. Use `connection_id` to represent a connection, as `company_id` and `account_id` are deprecated. | | `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 updates. ### 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_acount_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 { "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" } } ``` ### 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` webhook, your application should use the job\_url provided in the event to retrieve additional details on the job's status. * **`job.data_sync_all.completed`**: Emitted for automated data sync jobs. Additional details can be found in the automated jobs endpoint. * **`job.w4_form_employee_sync.completed`**: Emitted for automated W4 form synchronization jobs. Additional information is available from the automated jobs endpoint. * **`job.benefit_*.completed`**: Emitted for benefit-related jobs. Additional details are accessible via the manual jobs endpoint, which includes both manual and automated benefit jobs. 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\ | The id of the job which has completed. | | `data.job_url` | string | The url to query the result of the job. | Example: ```json { "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" } } ``` ### 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. 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 in 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: #### Company ```json { "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 } ``` \*Company events can only be `updated`. #### Directory ```json { "company_id": "720be419-0293-4d32-a707-32179b0827ab", "account_id": "fa872170-b49d-4fb5-aa39-fb1515db0925", "connection_id": "0057d3d2-fb43-4815-9f71-01ba4862d09f", "event_type": "directory.created", "data": { "individual_id": "59dcedb1-75a4-446c-8ece-4f9ccd53a1f9" } } ``` \*Note that one event will be created for *each* individual that has changed. For example, if 10 new individuals are added, 10 `created` events will be sent. #### Employment ```json { "company_id": "720be419-0293-4d32-a707-32179b0827ab", "account_id": "fa872170-b49d-4fb5-aa39-fb1515db0925", "connection_id": "0057d3d2-fb43-4815-9f71-01ba4862d09f", "event_type": "employment.created", "data": { "individual_id": "9987ecd1-6c6e-4d97-81ae-4d0248dbdb3d" } } ``` #### Individual ```json { "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" } } ``` #### Payment ```json { "company_id": "720be419-0293-4d32-a707-32179b0827ab", "account_id": "fa872170-b49d-4fb5-aa39-fb1515db0925", "connection_id": "0057d3d2-fb43-4815-9f71-01ba4862d09f", "event_type": "payment.created", "data": { "payment_id": "1c5e7bf2-94ce-4041-bf59-98e95677be21", "pay_date": "10-23-2023" } } ``` #### Pay Statement ```json { "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" } } ``` \*Note that one event will be created for *each* pay statement object that has changed. For example a new payrun for 20 individuals will generate 20 unique pay statement events. ## Supported Events ### Automated Webhooks * Account Updates * Job Completion: all endpoints * Data Changes ### Assisted Webhooks * Account Updates * Job Completion: benefit jobs only ## Webhook Verification Finch uses HMAC-SHA256 webhook verification. The following are steps you can use to verify a webhook using the verification 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. ```json v1,g0hM9SsE+OTPJTGt/tmIKtSyZlE3uFJELVlNIOLJ1OE= v1,bm9ldHUjKzFob2VudXRob2VodWUzMjRvdWVvdW9ldQo= v2,MzJsNDk4MzI0K2VvdSMjMTEjQEBAQDEyMzMzMzEyMwo= ``` 2. **Generate the webhook signature**. Using the 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 body of the request. The signature is sensitive to any changes, so even a small change in the body will cause the signature to be completely different. This means that you should not change the body in any way before verifying. If the signature does not match the value received in the `Finch-Signature` header, reject the webhook. **Note: when performing the signature comparison, it is safest to use a constant-time comparison to avoid potential timing attacks.** ```javascript Javascript const crypto = require('crypto'); const signedContent = `${webhook_id}.${webhook_timestamp}.${body}` const SECRET = "5WbX5kEWLlfzsGNjH64I8lOOqUB6e8FH"; // Need to base64 decode the secret const secretBytes = new Buffer(SECRET, "base64"); const signature = crypto .createHmac('sha256', secretBytes) .update(signedContent) .digest('base64'); ``` ```python Python import hmac import base64 signedContent = f"{webhook_id}.{webhook_timestamp}.{body}" SECRET = "5WbX5kEWLlfzsGNjH64I8lOOqUB6e8FH" # Need to base64 decode the secret secretBytes = base64.b64decode(SECRET) signature = base64.b64encode( hmac.new( secretBytes, signedContent.encode(), 'sha256' ).digest() ).decode() ``` ```java Java 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); } } ``` 3. **Verify the webhook timestamp** If the signature is valid, ensure the timestamp is not greater than five minutes in the past or future. 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. ```javascript Javascript (express.js) 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) 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) 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 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) 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) 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)) } ``` ## Testing Webhooks You can send a test request to any webhook through the developer dashboard. ![Test webhooks](https://mintlify.s3.us-west-1.amazonaws.com/finch/images/webhooks/webhooksTest.png) The test webhook will include the same structure as data update webhooks, with the `event_type` set to `test` ## Retries Upon failure, Finch will retry according to the following schedule with exponential backoff: * Immediately * 5 seconds * 5 minutes * 30 minutes * 2 hours ## Best Practices for Handling Webhooks ### Responding to Webhooks In order to prevent unnecessary retries, we recommend receiving webhook events and processing the events in separate processes. Upon receiving the event, you should immediately respond with a `200` indicating that the event was successfully delivered. ### Event delivery and ordering * It is possible that you may occasionally receive the same webhook event more than once. We recommend setting up idempotent event processing by using the `Finch-Event-Id`. * 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 * Webhooks are delivered with a `connection_id` corresponding to the company for which the data changed. You should retrieve this ID from Finch in order to map webhook updates to the correct company. A simple workflow for this is to call the `/introspect` endpoint after exchanging an auth code for an access token via the `/auth/token` endpoint. The `/introspect` endpoint contains the `connection_id` for the connection associated with the token. You can save this ID in your system to map incoming webhook events to companies based on the `connection_id`. # Connect an Employer Finch Connect is an embedded onboarding flow that enables employers to connect their HR or payroll system to your app. In order to recieve 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). ![Open Finch Connect](https://mintlify.s3.us-west-1.amazonaws.com/finch/images/finch-connect/open-finch-connect.jpg) 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. ![Finch Connect Screens](https://mintlify.s3.us-west-1.amazonaws.com/finch/images/finch-connect/finch-connect-screens.jpg) * **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 director and view the full company payroll. ![Finch Connect Screens](https://mintlify.s3.us-west-1.amazonaws.com/finch/images/finch-connect/successful-connection-screen.jpg) That's it! Upon successful authentication, Finch Connect closes and redirects back to your application. Once the connection is established, you will recieve 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. ## 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? The Finch API powers integrations to employment systems through a single, standardized data model. Finch is a Unified Employment API that enables you to build a single integration with Finch and instantly connect to hundreds of employment systems. 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. ![How Finch Works Diagram](https://mintlify.s3.us-west-1.amazonaws.com/finch/images/how-finch-works-diagram.png) ## Products Finch offers three products: Organization, Payroll, and Deductions. 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. ## 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 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 free 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 `client_id` and `client_secret` will only work for the sandbox provider. If you would like to test real providers with live data, you must request developer keys from [developers@tryfinch.com](mailto:developers@tryfinch.com). 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. 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. 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 `` with the client id found in your [Finch Dashboard](https://dashboard.tryfinch.com/signup). Remove the angle brackets when replacing ``. `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 curl https://api.tryfinch.com/connect/sessions \ -X POST \ -H "Content-Type: application/json" \ -U ":" \ --data-raw '{ "customer_id": "", "customer_name": "", "products": ["directory", "individual", "employment"], "redirect_uri": "https://example.com", "sandbox": "finch" }' ``` ```cs { "session_id": "f47ac10b-58cc-4372-a567-0e02b2c3d479", "connect_url": "https://connect.tryfinch.com/authorize?session=f47ac10b-58cc-4372-a567-0e02b2c3d479" } ``` Note that we have set `sandbox=finch`. This is required only when testing in our [sandbox environment](/implementation-guide/Test/Testing-Plan#2-simulate-test-scenarios-in-a-safe-environment) ## 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`. ## 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 `` in the command with the one you saved above (making sure to not include the angle brackets). ```bash curl https://api.tryfinch.com/auth/token \ -X POST \ -H "Content-Type: application/json" \ --data-raw '{ "client_id": "", "client_secret": "", "code": "", "redirect_uri": "https://example.com" }' ``` ```json { "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" } ``` **Congratulations!** You have sent your first request to Finch's API. The next step is to integrate Finch Connect onto your application. # Unified Employment API Glossary Use this glossary to familiarize yourself with employment 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, company, or entity that hires and pays employees. An employer may consist of [one or many sub-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 (or any sub-entities) can be referenced within the Finch APIs by their Finch-issued `connection_id`. If an employer has multiple sub-entities within their payroll system, these may be represented as multiple connections with different `connection_id`. You can use the EIN or Legal Name that returns in the `/company` endpoint to reconcile your records internally. ### 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 three products: [Organization](/products/organization/Overview), [Payroll](/products/payroll/Overview), and [Benefits](/products/deductions/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`. Therefore, an *employer* may have [one or many connections](/implementation-guide/Backend-Application/Manage-Connections) depending on if the employer is made up of sub-entities. ### (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 Learn how to monitor your application’s usage of Finch APIs, optimize your requests, and handle rate limits and errors. It is important to learn how to monitor your application's usage of Finch APIs, optimize your requests, and handle rate limits and errors effectively. Consequently, this will help you maintain a smooth user (and developer) experience by productively managing your application's API requests. Several of Finch's endpoints are “batch” endpoints ([`/individual`](/api-reference/organization/individual), [`/employment`](/api-reference/organization/employment), [`/pay-statement`](/api-reference/payroll/pay-statement)). This means that several IDs can be sent in a single request. Finch will correspondingly return a single response with an array of objects equal to the IDs sent. Determine your optimal batch size for your use case when making batch requests to Finch APIs. If you send 1000 IDs in the request, you will receive a single response containing an array of 1000 responses for each ID sent. Pass all the required IDs in a single batch request to optimize API usage and minimize the risk of hitting [rate limits](/api-reference/development-guides/Rate-Limits). ```json { "requests": [ { "individual_id": "772b3c4f-d764-433d-bd69-ff8bbac33ffe" }, { "individual_id": "a7a77065-0f68-418d-a85a-da24fb2139b7" }, ... { "individual_id": "84364585-c2ce-40aa-bcc0-666ac9577315" } ] } ``` ## Batch Errors When calling the Finch "batch" API endpoints, ensure your application can handle errors returned in the batch format. Finch can return errors in two ways. Both errors will be the same format described in the [Error Types](/api-reference/development-guides/errors/Error-Types) API Reference guide. 1. A possible error per batch request item within the response body. 2. A possible error at the HTTP status code level. Don't assume that if the HTTP status code is OK that the batch response was OK as well ```json // 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 After completing this step, you should be able to efficiently send thousands of IDs in a single HTTP request and managing each individual batched message in the main response body. Batch errors are just one type of error that can be experienced. Next, we will learn how to [mitigate other error types](/implementation-guide/Backend-Application/Mitigate-Errors) that may be experience when calling the Finch APIs. ## Learn more * [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 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. 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**: Depending on the data you need for your application, choose the appropriate Finch API endpoints. 1. Here's a brief overview of Finch's endpoints again: * `/company`: Retrieve company information, such as name, address, and Federal Employer Identification Number (EIN). * `/directory`: List all the employees at the company, both active and inactive. * `/individual`: Obtain individual information, such as name, date of birth, and contact details. * `/employment`: Access employment-related data, like job title, department, and start and end dates, and income. * `/payment`: Get payroll information, including pay frequency and last payment date. * `/pay-statement`: Fetch detailed individual paycheck data, including earnings, taxes, employee deductions, and employer contributions. * `/benefits`: Create and enroll employees in various types of benefits directly in the employer's provider. The “benefits” are applied directly to the employee's next paycheck in the deductions or contributions section. This endpoint is covered more in [Write Data](/implementation-guide/API-Calls/Write-Data). 2. **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 `. Make sure the HTTP request uses the appropriate method (GET, POST, etc.) and includes any required parameters. ```js const url = 'https://api.tryfinch.com/employer/directory'; // Replace with the desired endpoint const accessToken = ''; 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 import requests def fetch_data_from_endpoint(): url = 'https://api.tryfinch.com/employer/directory' 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 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"; private static final String 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()); } } } ``` 3. **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 { "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 } ] } ``` 1. **Handle errors and edge cases**: Be prepared to [mitigate errors](/implementation-guide/Backend-Application/Mitigate-Errors) and edge cases in the API response. For example, Finch may 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, so consider implementing a retry strategy with a delay. If the error persists, submit a support ticket with the `Finch-Request-ID` present in the headers of the response. ```jsx Error handling example 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)); ``` 2. **Handle 401 re-authentication errors**: If Finch returns a `401` HTTP status code and a `finch_code` of `reauthenticate_user`, it indicates Finch has lost access to the employer's provider. If this happens, display a prompt on your frontend to have the end-user [go through Finch Connect again](/implementation-guide/Connect/Set-Up-Finch-Connect) to reconnect the provider. Upon successful re-authentication, [obtain a new access token](/implementation-guide/Connect/Retrieve-Access-Token) and continue making API requests with the new token. The old token can be discarded. 3. **Manage rate limits**: Finch enforces [rate limits](/api-reference/development-guides/Rate-Limits) on a per-product basis for both applications and access tokens. Rate limits are counted on a per-minute basis for each product. Each product has its own "bucket" with a 60-second Time-To-Live (TTL). The first request for a product starts the 60-second TTL for that product's bucket, and rate limits reset after the 60-second period. If Finch returns a `429` HTTP status code, your application has exceeded the rate limit for a product. To [reduce rate limit errors](/implementation-guide/Backend-Application/Mitigate-Errors#rate-limit-errors), you can implement a backoff strategy to retry requests when encountering rate limit errors. *** ### 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. This will enable you to provide a seamless experience to your users while leveraging Finch's powerful API infrastructure. 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 you can [Prepare the Employer Experience](/implementation-guide/Integration-Preparation/Manage-Integrations). ## Learn more * [Mitigate Errors](/implementation-guide/Backend-Application/Mitigate-Errors) * [Monitor Usage](/implementation-guide/Backend-Application/Monitor-Usage) # Write Payroll Deductions & Contributions In this guide, you'll learn how to write deductions and contribution changes to Finch's benefits API endpoint. In addition to [Reading Data](/implementation-guide/API-Calls/Read-Data) via Finch, 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) for retirement, medical, and fringe benefit use cases. Finch `Deductions` APIs operate at two levels: the **company-level** and the **individual-level**. The APIs allow you to: * Create, read, and update benefits at the company-level * Manage enrollment amounts for company contributions and employee deductions at the individual-level > Keep in mind, not every use case will need the ability to write deductions and contributions back to the payroll provider. If you have any questions about if writing data applies to you, contact your Finch account representative. ## Setup Before implementing our Deductions APIs, make sure you consider the unique limitations of each provider: ### Understand Assisted vs Automated Integrations Specific providers are supported by either automated or assisted integations. * [Automated](#automated-deductions) integrations support both the **reading** *and* **writing** of deductions and contributions. * [Assisted](#assisted-deductions) integrations only allow the **writing** of deductions and contributions. This information is available in [our provider documentation](/integrations/providers). ### Using benefits metadata The types and features of each benefit can vary between payroll systems depending on the configuration that the company has set up. For this reason, we provide a `benefits_support` field on the  [`/providers`](/integrations/providers) endpoint, which will provide the types and features available for the employer whose deductions and contributions you are managing. If you try to make a request using an access token that does not allow a certain configuration or benefit 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 Providers have varying limitations on which operations are available and which actions can be performed. For example, you should be prepared for providers which do not allow for automatic benefit creation (Paychex Flex, Paycom, Trinet, etc. ) and design your workflow to accommodate those cases. As Finch encounters new provider limitations, we add them to our [Provider Field Support](/integrations/providers). For each of the limited providers, you should confirm with the employer that the correct benefits are set up in their system prior to enrolling individuals through Finch. If you try to enroll an employee in a benefit that is not set up, you may receive a `422` response code from Finch indicating that the benefit is not set up by the employer. In these cases, you should reach back out to the employer to ensure the benefits have been correctly set up. ## Getting and Creating Company Benefits Our API allows you to both [create new benefits](/api-reference/deductions/create-deduction) in a payroll system and [get existing benefits](/api-reference/deductions/get-all-deductions) from the system. Both of these requests will respond with a `benefit_id` in the response body. For example, a creation request will respond with: ```json { "benefit_id": "e8b90071-0c11-471c-86e8-e303ef2f6782" } ``` You can use this `benefit_id` to perform enrollment, un-enrollment, and benefit retrieval actions on individuals. Read our API Reference docs to understand the functionality and required parameters of each of our Deductions endpoints. Some highlights: * [Create a New Benefit](/api-reference/deductions/create-deduction) * [Enroll Individuals](/api-reference/deductions/enroll-individuals-in-deductions) * [Unenroll Individuals](/api-reference/deductions/unenroll-individuals-from-deductions) ## Enrolling and Unenrolling Individuals ### Creating new enrollments Enrolling a new individual is as simple as using the `benefit_id` returned from the Deductions endpoints above, and using it in a [`POST /benefits/{benefit_id}/individuals`](/api-reference/deductions/enroll-individuals-in-deductions) request. In the body, you should provide a list of objects which specify the enrollment, one per individual. Each object should contain a flexible `configuration` object which specifies the enrollment configuration to applies to that individual. The schema of the configuration varies depending on the type of benefit you are enrolling, so please refer to the docs to ensure you are using the right schema. ### Updating existing enrollments To update enrollment configurations for currently enrolled individuals, you can 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. ## Automated Deductions Requests made for connections to automated providers will be fulfilled synchronously, so the response you receive from the `/employer/benefits` endpoints will contain the results of the request. Automated integrations support the **reading** and **writing** of deductions and contributions from providers: Read: * `GET /employer/benefits` to list all company-wide benefits * `GET /employer/benefits/{benefit_id}` to list benefit information for a given benefit * `GET /employer/benefits/{benefit_id}/enrolled` to list individuals currently enrolled in a given benefit * `GET /employer/benefits/{benefits_id}/individuals` to get enrollment information for the given individuals Write: * `POST /employer/benefits` to create a new company-wide benefit or individual deduction * `POST /employer/benefits/{benefit_id}/individuals` to enroll employee(s) in an existing benefit or deduction * `POST /employer/benefits/{benefit_id}` to update an existing company-wide benefit or individual deduction * `DELETE /employer/benefits/{benefit_id}/individuals`\* to unenroll individuals from a deduction ### Automated Deductions Sequence Diagram ![automated-benefits.png](https://mintlify.s3.us-west-1.amazonaws.com/finch/images/automated-benefits-sequence-diagram.png) ## Assisted Deductions Assisted requests are fulfilled by our operations team, and so have slight differences in behavior and functionality compared to automated integrations. * [Read more about Assisted Deductions](/integrations/integration-types) Assisted integrations only support **writing** of benefits, deductions, and contributions to providers: Write: * `POST /employer/benefits` to create a new company-wide benefit or individual deduction * `POST /employer/benefits/{benefit_id}/individuals` to enroll employee(s) in an existing benefit or deduction * `POST /employer/benefits/{benefit_id}` to update an existing company-wide benefit or individual deduction * `GET /employer/benefits/meta` to list the available benefit types and configurations for the provider associated with the access token * `DELETE /employer/benefits/{benefit_id}/individuals`\* to unenroll individuals from a deduction For providers which support Deductions via Assisted, the response you receive from the `/employer/benefits` endpoints will contain a `job_id`. While our dedicated product operations team makes the necessary changes in the provider's system, you can continue to call  `GET /jobs/{job_id}` 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. Example `POST /employer/benefits` response: ```json { "benefit_id": "264122c0-0216-4f21-a4cd-7b3bcddbe3fc", "job_id": "497d98f3-580a-4ab9-830a-af2346d029b2" } ``` Example `POST /employer/benefits/{benefit_id}/individuals` response: ```json { "job_id": "3a82a144-d168-4207-942a-a5852b11df1c" } ``` This will be the same for `DELETE /employer/benefits/{benefit_id}/individuals` Example `GET /jobs/{job_id}` response after initial job submission: ```json { "job_id": "3a82a144-d168-4207-942a-a5852b11df1c", "code": 202, "status": "pending" } ``` Example `GET /jobs/{job_id}` response after job is completed for a `POST /employer/benefits/individuals` request with multiple individuals: ```json { "job_id": "3a82a144-d168-4207-942a-a5852b11df1c", "code": 207, "status": "complete", "body": [ { "individual_id": "430f9d95-1dcf-4b99-b616-45f814416890", "code": 201, "message": "Successfully enrolled individual in benefit", }, { "individual_id": "647975ac-1e0f-4e9c-b705-e3042da48581", "code": 200, "message": "Successfully updated enrollment for individual", }, { "individual_id": "4a0a3b15-d3d6-41c2-a4a4-ca4ed1b68cf8", "code": 404, "message": "Individual not found" }, ... ] } ``` These diagrams further explain the difference between the assisted and automated workflows: ### Assisted Deductions Sequence Diagram ![assisted-benefits.png](https://mintlify.s3.us-west-1.amazonaws.com/finch/images/assisted-benefts-sequence-diagram.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 8 days to account for the 7 day SLA. Enrollment and un-enrollment requests and responses are batched. This means that some enrollments/un-enrollments could succeed while others fail. For automated providers, you should inspect the `body` object of the response body to discern failures. Note that the top-level response status code will be a 207, but may be individual errors. Example: ```json title=Top-level status code: 207 [ { "individual_id": "d02a6346-1f08-4312-a064-49ff3cafaa7a", "code": 500, "body": { "name": "internal_server_error", "message": "Internal sever error" } }, { "individual_id": "e63c21ab-7cde-49d8-b6d6-ce208e84bf09", "code": 500, "body": { "name": "internal_server_error", "message": "Internal sever error" } } ] ``` Assisted providers will follow a similar format, but on the `/jobs` endpoint instead. Example: ```json title=Top-level status code: 200 { "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 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. ### Timing submissions for assisted connections For assisted connections, it is important to submit payroll deductions to our API 7 days before the customer's payroll close date. This will help ensure that changes can be processed within the current payroll period (unless explicitly specified in your API request via the `effective_date` request parameter). Otherwise, the change will be executed on the next payroll period. **Example** As an example, if the payroll period is **June 1 - 15**. The payroll close date might be **June 16** so payroll can be processed before **Friday, June 17**. Therefore, it would be important to submit payroll deductions via the Finch API by **June 9** for those to take effect during the June 1 - 15 payroll.
  June 2022
  Su Mo Tu We Th Fr Sa
  1  2  3  4
  5  6  7  8  9 10 11
  12 13 14 15 16 17 18
  19 20 21 22 23 24 25
  26 27 28 29 30
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. *** ### 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 benefits 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). ## Learn more * [Deductions API](/products/deductions/Overview) * [Supported Providers](/integrations/providers) * [Integration Types: Assisted](/integrations/integration-types#assisted) # 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) 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 option, 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. ## 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. 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 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). ## Learn more * [Manage Connections](/implementation-guide/Backend-Application/Manage-Connections) * [Reconcile Employees](/developer-resources/Reconcile-Employees) # Disconnect Tokens Learn how Finch defines connections, and how to safely disconnect all access tokens associated with a connection if needed. A connection exists once an access token is obtained and [stored securely](/implementation-guide/Backend-Application/Store-Tokens). Once a connection is no longer needed or requested to be deleted by the customer, calling the [/disconnect](/api-reference/management/disconnect) endpoint will disconnect all associated access tokens for that particular connection. It is important to know how Finch defines a connection to understand what happens when a connection is disconnected. ## Disconnect scenarios Finch defines a connection using a `connection_id`. Let's evaluate three different scenarios... ### 1. Different user credentials | | | | ------------------------------------------------------------ | ----------------------------------------------------- | | Company | Same | | Provider | Same | | User Credentials | Different | In this case, even though different user credentials might be used to login (i.e. different accounts), as long as the same employer is using the same provider to login, it only counts as one connection. Thus, [disconnecting](/api-reference/management/disconnect) the connection will disconnect all tokens for that connection. ### 2. Different companies | | | | ------------------------------------------------------------ | ----------------------------------------------------- | | Company | Different | | Provider | Same | | User Credentials | Same | Alternatively, if a customer had two different companies using the same provider, it would count as two different connections since the `connection_id`s are different. Thus, [disconnecting](/api-reference/management/disconnect) one won’t disconnect the other. ### 3. Different providers | | | | ------------------------------------------------------------ | ----------------------------------------------------- | | Company | Same | | Provider | Different | | User Credentials | Same | Finally, if a customer had the same company using different providers, it would also count as two different connections since the `provider_id`s are different. Thus, [disconnecting](/api-reference/management/disconnect) one won’t disconnect the other. ### Example * **\[1]** User `A` authenticates to the provider Gusto via Finch Connect using Credentials `X` which exists in the Gusto provider for Company `C`. This creates a Connection `1` in Finch and issues an access token. * **\[2]** User `A` authenticates to Gusto again using Credentials `X` for Company `C` (maybe with different product permissions). Another access token is created, but there is still only a single Connection `1` to Company `C`. * **\[3]** User `B` authenticates to Gusto via Finch Connect as well but with Credentials `Y` which also exists in the Gusto provider for Company `C`. A new access token is created, and a new Connection `2` is created. To avoid a new connection being created in this scenario, make sure to use the reauthentication link containing the [connection\_id](/implementation-guide/Connect/Set-Up-Finch-Connect). * **\[4]** User `A` sets up Company `C` using another provider called JustWorks. User `A` then uses Finch Connect to authenticate using Credentials `Z` which exists in the new JustWorks provider for Company `C`. This creates a new Connection `2` in Finch and issues an access token. If any access tokens issued in scenarios 1 or 2 are disconnected, all tokens issued for Company `C` using the provider Gusto will be revoked. These tokens still exist technically, but they can no longer be used to call the Finch API; an `Unauthorized` error will be returned. However, the token is treated as a separate connection in scenarios 3 and 4. Disconnecting tokens associated with Connection `1` will not impact tokens associated with Connection `2`. *** ## Checkpoint + Next Step After completing this step, you should know what will happen to a connection if an access token is disconnected. Your application should give your customers the ability to disconnect their connection, which subsequently calls the Finch Disconnect endpoint from the backend. By storing tokens securely and disconnecting connections when necessary, your application is more secure. If you plan on presenting the data back to the employer via a User Interface, it is crucial to [control user access properly](/implementation-guide/Backend-Application/Control-Access) to ensure employment data is only viewable to the correct customer account. ## Learn more * [Disconnect Endpoint](/api-reference/management/disconnect) * [Manage Connections](/implementation-guide/Backend-Application/Manage-Connections) * [Control Access (Optional)](/implementation-guide/Backend-Application/Control-Access) # 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. ## Define connections Finch defines a connection using a `connection_id`. A connection exists once an access token is obtained. There are three types of scenarios to keep in mind when thinking about connections: 1. **Multi-Account** * *Different Logins* - When two employees at the same company connect to the same provider using different user credentials (or API tokens). * *Permissions* - When a company connects multiple times but with different API permissions (Organization, Payroll, Deductions, etc.). 2. **Multi-Provider** * *Migration* — When a company migrates from one provider to another and partial data is stored in each. * *Foreign workers* — When a company has foreign contractors or employees and utilizes a separate provider to manage those individuals. 3. **Multi-Entity** * *Pay Groups* — When a company has a separate entity per payroll group to pay each group on different cadences. * *Legal Entities* — When a company has separate legal entities usually in the form of divisions (corporations & LLCs), franchises (LLCs), or business units (corporations & LLCs). * *Professional Employer Organizations (PEO)* - When a company is partnered with a PEO that performs various administrative tasks on behalf of multiple companies. In the **1) Multi-Account** scenario, a single connection is created, even though multiple accounts were used to log in. In the **2) Multi-Provider** scenario, a new connection is created for every new provider connected. Even though it is the same company, there are multiple connections because the `provider_id` is different for each access token. In the **3) Multi-Entity** scenario, a new connection may be created for every company “entity” connected. ## 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 { "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`. ![1-To-1 Database Schema](https://mintlify.s3.us-west-1.amazonaws.com/finch/images/manage-connections/single-connection-database.jpg) 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`. ![1-To-Many Database Schema](https://mintlify.s3.us-west-1.amazonaws.com/finch/images/manage-connections/updated-multiple-connection-database.jpg) 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. ![](https://mintlify.s3.us-west-1.amazonaws.com/finch/images/manage-connections/multiple-connections-UI.png) ## 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 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. ## 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 In this guide, you'll learn how to identify and mitigate common errors such as server errors, reauthentication errors, and rate limit errors. Finch aims to ensure our APIs always return the data in the exact format you expected it, but sometimes errors still happen. This guide will discuss our customers' most frequently encountered errors and how to mitigate them. Your application should expect specific [error types](/api-reference/development-guides/errors/Error-Types) and handle errors from the Finch API. ## Handle null values and 202 Response Codes All applications should be built to handle `null` values and `202` responses in order to prevent errors in processing data in your application. The key behaviors your application should exhibit are are described in our [Handling API Responses guide](/api-reference/development-guides/Handling-API-Responses). ### Testing 202s in the Finch Sandbox You can test handling 202 responses in the Finch Sandbox by creating a connection with an provider that is an assisted integration for organization data. You can find the list of assisted integrations on our [Provider Network](/integrations/providers) page. If you are creating the connection using Finch Connect (versus the dashboard or programmatically), include `manual=true` in the params to see assisted integrations in the drop down list of providers. ## Server errors While unlikely, any robust application should still plan to encounter server errors `HTTP 500`. If this type of error occurs, implementing a few error-handling mechanisms in your application can help maintain a good user experience while still allowing you to diagnose the issue. * **Friendly error page** - Always display a user-friendly error message instead of raw server errors. This helps in maintaining user trust. * **Log the error** - Capture detailed server logs including the error message, stack trace, request details, and any other relevant context. Make sure to specifically log the `finch-request-id` found in the HTTP Request headers. This will help in diagnosing and rectifying the error on Finch's side. * **Health checks** - By calling the [/introspect](/api-reference/management/introspect) endpoint on a regular basis, you can implement a health check to provide information about the status and health of your Finch integration and its connections. This can help in identifying the source of `500` errors faster. * **Retry** - Sometimes, simply retrying the request after a specified delay or adjusting the request parameters solves the problem. ### Product Outages Finch reports all API outages and provider integration incidents. You can visit [https://status.tryfinch.com](https://status.tryfinch.com) subscribe to receive email notifications from Finch whenever we create, update, or resolve an incident. If any server error persists, contact the [Finch Support](/implementation-guide/Deploy-and-Manage/Support) team and attach the `finch-request-id` present in the headers of the response for further assistance. ## Reauthentication errors When connections are set up in Finch, a long-lived session is established between you, Finch, and your users' employment systems. There is no need to refresh the connection on a recurring basis. However, if a user changes security settings on their account or an employment system makes changes to its infrastructure, Finch's connection can get disconnected. This will result in an error with the HTTP status code of `401 Unauthorized` and `finch_code` of `reauthenticate_user` (see [Finch API errors](/api-reference/development-guides/errors/Error-Types)). When an access token returns this, your user will need to re-authenticate by going through the Finch Connect flow again. Since a reauthentication error means that a connection is disconnected and the access token is no longer working, your customer must be reengaged to have them reconnect their provider through [Finch Connect](/how-finch-works/finch-connect) again to get a new access token. We recommend using automatic in-app or email notifications to alert your customer that there is an issue with their connection, why reconnecting is beneficial, and the steps they need to follow to reconnect. Finch recommends the following steps to handle reauthentication errors: 1. Catch `401` HTTP status code error responses with the `finch_code` of `reauthenticate_user` in your application while handling Finch API responses. 2. To create a more seamless experience and avoid unintended duplicate connections, create a new Finch Connect session using the `/connect/sessions/reauthenticate` endpoint. The endpoint requires that you pass in `connection_id` of your customer by calling the [/introspect](/api-reference/management/introspect) endpoint with their `access_token`. 3. Notify the customer that their connection is broken, and they can resolve it by reconnecting their account. To increase conversion, we recommend letting your customer know why reconnecting is beneficial to them and the services they will miss out in the interim. You can prompt your user to log on to their application dashboard where they can reconnect through [Finch Connect embedded](/implementation-guide/Connect/Set-Up-Finch-Connect#embedded-finch-connect) in your app or send them an email with the [Finch Connect redirect](/implementation-guide/Connect/Set-Up-Finch-Connect#redirect-flow) link. 4. Once your customer goes through Finch Connect successfully, an authorization `code` is generated which you will need to exchange for a new `access_token` that you can use to send requests to the Finch API again. Make sure to save this new token in your database. > While you will receive a new access token for the employer, everything else will remain the same. All Finch identifiers, like `individual_id` or `payment_id`, are the same across tokens. ## Rate limit errors Finch will return a rate limit error with the HTTP status code `429 To Many Requests` when the request rate limit for an application or an individual IP address has been exceeded. Familiarize yourself with the API [rate limits](/api-reference/development-guides/Rate-Limits) set before continuing. Finch's [rate limits](/api-reference/development-guides/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. 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. Ensure that you stay within these [rate limits](/api-reference/development-guides/Rate-Limits) to avoid API request failures due to exceeding the limits. In case you encounter rate limit errors, implement a [“back-off and retry” strategy](#rate-limit-example) in your application. For example, you could wait for 60 seconds (since Finch's rate limit buckets reset after this period) and then retry the request. You could also exponentially increase the wait time between retries or use a random delay if you prefer. This will allow your application to wait for the rate limit to reset and then resume making API requests. Below are a few ways to fix rate limit errors. ### Leverage batched requests A quick fix if you are hitting rate limit errors is to implement [batched requests](/implementation-guide/API-Calls/Batch-Requests). If you are try to retrieve individual details for a 1000-person company, calling the [/individual](/api-reference/organization/individual) endpoint 1000 times will quickly hit the API's [rate limits](/api-reference/development-guides/Rate-Limits). Since there is no limit to the amount of IDs that you can send in a single request, you can batch the 1000 `individual_ids` and send as a single request. You will receive back a single response from Finch with an array of 1000 objects containing each individual's details. ### Rate Limit Scenario Let's study a hypothetical scenario of how your application would encounter application level [rate limits](/api-reference/development-guides/Rate-Limits). Assume your application has five access tokens (Token A, Token B, Token C, Token D, Token E) and you are making API requests to any of the the `company`, `directory`, `individual`, `employment`, `payment`, and `pay-statement` endpoints. When a request is sent to an endpoint, a single gallon of water is added to the application-level product endpoint "bucket" each time. The bucket counts all requests across all the application's access tokens (Token A, Token B, Token C, Token D, Token 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. We are assuming that each step below happens within the same 60-second (1 minute) time window. 1. Token A makes 5 requests to the [/company](/api-reference/organization/company) endpoint, 4 requests to the [/directory](/api-reference/organization/directory) endpoint, and 3 requests to the [/payment](/api-reference/payroll/payment) endpoint within a minute. Each endpoint (i.e. bucket) is below the 20 and 12 limit capacities, 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 the [/company](/api-reference/organization/company) endpoint, 4 requests to the [/directory](/api-reference/organization/directory) endpoint, and 3 requests to the [/payment](/api-reference/payroll/payment) endpoint within the same minute. Each endpoint is still below the 20 and 12 limit capacities, so all of Token B's requests succeed as well. * 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. Token C and D repeats the same process as Token A and B making 5 requests to the [/company](/api-reference/organization/company) endpoint, 4 requests to the [/directory](/api-reference/organization/directory) endpoint, and 3 requests to the [/payment](/api-reference/payroll/payment) endpoint all within the same minute. The [/company](/api-reference/organization/company) and [/payment](/api-reference/payroll/payment) endpoints are now at full capacity, but all of Token C's and D's request still succeed because the limits have not 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. Now, if Token E makes 1 request to the [/company](/api-reference/organization/company) endpoint and 1 request to the [/directory](/api-reference/organization/directory) endpoint. The `company` and `payment` request will both fail and return a 429 rate limit error because the application-level buckets are now full. No requests from any additional token will succeed either when calling the [/company](/api-reference/organization/company) and [/payment](/api-reference/payroll/payment) endpoints until those bucket's 60-second Time-To-Live (TTL) timer resets. However, Token E's request to the [/directory](/api-reference/organization/directory) endpoint will succeed because the application-level `directory` bucket is not full (yet). Only succeeded requests count towards the application level rate limits. * 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 | Note: Only succeeded requests count towards the application level rate limits. Similarly, every 5th request to the [/company](/api-reference/organization/company) endpoint for each token fails and returns a 429 rate limit error. ### Rate limit example You can use the following code example to enforce this rate limit quota at the application level. The `RateLimiter` class makes requests up to the specified rate limit when initialized (ex: 20 requests per minute for the [/directory](/api-reference/organization/directory) endpoint) and pauses further requests until the rate limit resets after 60 seconds. The `request` method of the rate limiter is used to make API requests to Finch's endpoints, ensuring that you stay within the rate limit “bucket” quota for each endpoint. Simply initialize a new `RateLimiter` class for each endpoint being called. ```js 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 = ''; 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 After completing this step, you should be equipped to handle some of Finch's common error scenarios and how to address them in your application leading to a more resiliant integration. It is easier to mitigate errors if your application has an adequate way to monitor API requests, which is covered in the next section [Monitor API Usage](/implementation-guide/Backend-Application/Monitor-Usage). ## Learn more * [Set Up Finch Connect](/implementation-guide/Connect/Set-Up-Finch-Connect) * [Rate Limits](/api-reference/development-guides/Rate-Limits) * [Error Types](/api-reference/development-guides/errors/Error-Types) # 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. 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. ## 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 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. ## Learn more * [Finch Status Updates](https://status.tryfinch.com) # 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. Finch access tokens are "keys" to sensitive information. You should treat access tokens with the same level of security as you would passwords. ## 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-Tokens), and providing users with the ability to [control their data](/implementation-guide/Backend-Application/Control-Access). *** ## Checkpoint + Next Step 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-Tokens) from Finch then delete it from your system. ## Learn more * [Disconnect Tokens](/implementation-guide/Backend-Application/Disconnect-Tokens) * [Control Access](/implementation-guide/Backend-Application/Control-Access) # Create a Finch Developer 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 Finch Developer account to receive application credentials (a `client_id` and `client_secret`) and pilot how Finch works in our sandbox — a safe testing environment with mock data. ![Sign Up](https://mintlify.s3.us-west-1.amazonaws.com/finch/images/create-account/signup-page.jpg) 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). ![Finch Developer Dashboard](https://mintlify.s3.us-west-1.amazonaws.com/finch/images/create-account/finch-developer-dashboard.jpg) ## 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 Developer Success 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 | `/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 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. ## Learn more * [Store Access Tokens](/implementation-guide/Backend-Application/Store-Tokens) # 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 curl https://api.tryfinch.com/auth/token \ -X POST \ -H "Content-Type: application/json" \ --data-raw '{ "client_id": "", "client_secret": "", "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 { "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" } ``` 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 After completing this step, your application will be able to exchange authorization codes for access tokens securely and automatically. You are now ready to [Develop Your Test Plan](/implementation-guide/Test/Testing-Plan) to ensure your integration is robust and reliable. ## Learn more * [Store Tokens](/implementation-guide/Backend-Application/Store-Tokens) * [Mitigate Errors](/implementation-guide/Backend-Application/Mitigate-Errors) # Integrate Finch Connect Into Your Application Before being able to pull data from an employment provider through Finch, your customer needs to consent to the data being transferred. Without consent, Finch is not authorized to pull the data on behalf of the customer. Finch Connect is our user-facing product to help you obtain customer consent, and it is a prerequisite step before calling Finch APIs. {" "} This section requires that you have registered your application with Finch by completing the [Create a Finch Developer Account](implementation-guide/Connect/Create-Account) section.{" "} {" "} This setup process will enable our default versions of Finch Connect. Later in this implementation guide, we'll walk you though tips and tricks to help you [increase employer adoption](/implementation-guide/Deploy-and-Manage/Increase-Employer-Adoption) in Finch Connect.{" "} # Configure Finch Connect 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). | | `state` | optional | An optional value included as a query parameter in the response back to your application. This value is often used to identify a user and/or prevent cross-site request forgery. | | `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/Testing-Plan). | | `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. | # Choose your preferred authentication flow Finch provides two options to set up Finch Connect. The redirect flow is helpful in instances where you do not have a user interface (such as a link in an email) or you prefer to redirect in order to not host the authorization experience yourself. For the embedded flow, Finch provides several front-end SDKs for easy implementation. Before setting up your preferred Finch Connect flow, you will need to first create a Connect session. ## Create a Connect Session In your backend application, make a call to POST /connect/sessions to create a connect session for your customer. 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 React 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": "", * "connect_url": "" * } **/ console.log(createConnectSessionResponse); } main(); ``` If you call `POST /connect/sessions` and you already have a connection with Finch from the customer\_id you pass 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: . Please use the /connect/sessions/reauthenticate endpoint instead.", "name": "bad_request", "context": { "customer_id": "", "connection_id": "" }, } ``` ## Launch Finch Connect Using the response of the API call above, either launch Finch Connect by passing the `session_id` to the Finch Connect SDK or direct your customer to the provided URL. ### Redirect Flow In this method of integrating Finch Connect, your application redirects your user's browser to Finch Connect hosted by Finch on `https://connect.tryfinch.com`. After a successful connection, Finch Connect will redirect your user back to a URI you specified (`redirect_uri`) with a short-lived authorization `code`. The `redirect_uri` must be set in the [Finch Developer Dashboard](https://dashboard.tryfinch.com/login). Otherwise, the request will fail. Navigate to the URL in `connect_url` from the API response to initiate the redirect flow. The redirect authorization flow consists of four steps: 1. **Open Finch Connect** — Your application redirects your user’s browser to Finch Connect to initiate the authorization flow. 2. **Obtain consent** — Finch Connect prompts your user to log in to their employment system and grant your application access to the permissions you are requesting. 3. **Retrieve the authorization code** — If your user successfully connects and grants your application access to their system, Finch Connect will redirect their browser to a specified `redirect_uri` with a short-lived authorization `code`. 4. **Exchange the code for an access token** — Before sending API requests, your application will exchange the short-lived code for a long-lived `access_token` that represents your application's access to your user's employment system. ### Embedded Finch Connect The Finch-provided SDKs embed the Finch Connect screen into your application. The user will remain entirely on your application throughout the process. When the onSuccess event is called by the SDK, simply pass the code to your internal callback endpoint as a query parameter. > NOTE: You should not include a redirect\_uri if using the embedded flow. Because the entire flow is already self-contained in your app, no redirect is necessary. * [React SDK](https://github.com/Finch-API/react-connect): If you’re using React as your frontend framework, use the React SDK. Import the Finch Connect component and include it in your application. You can find examples and usage instructions in the SDK documentation or continue to follow this tutorial. - `npm install --save @tryfinch/react-connect` - `yarn add @tryfinch/react-connect` * JavaScript SDK: If you’re using a different frontend framework or vanilla JavaScript, use the pure JavaScript SDK. Include the Finch Connect library in your application, either by adding a script tag to your HTML file or by importing it as a module. * `` > Since Finch Connect is an iFrame that requires interactivity, the HTML page that is loading Finch Connect **must be served from a server**. If the page is hosted statically, Finch Connect will not work properly. *React* ```js React import React, { useState } from "react"; import { useFinchConnect } from "@tryfinch/react-connect"; const App = () => { const [code, setCode] = useState(null); const onSuccess = ({ code }) => setCode(code); const onError = ({ errorMessage }) => console.error(errorMessage); const onClose = () => console.log("User exited Finch Connect"); // 1. Initialize Finch Connect const { open } = useFinchConnect({ sessionId: " ``` ## Implement the authentication flow Add a button or a link in your application that triggers the Finch Connect flow. Users will click this button or link to start the authentication process. *React* ```js React const App = () => { // ... // 2. Display Finch Connect return ( ); }; ``` *Javascript* ```html Javascript ``` ## Listen for events Finch Connect emits events that your application should listen for to handle the different stages of the authentication process. The two most important events are `onSuccess` and `onError`. 1. `onSuccess`: This event is triggered when the user completes the authentication process. It returns an authorization `code` that you will use to obtain an `access_token` in the next step. Pass this authorization `code` securely and temporarily to the access token exchange function. 2. `onError`: This event is triggered if there's an issue during the authentication process. Your application should handle this error gracefully, either by displaying an error message to the user or retrying the authentication flow. 3. `onClose`: This event is triggered when a user exits the Finch Connect model, either by closing the modal or clicking outside the modal. *** ## Checkpoint + Next Step 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. ## Learn more * [Finch Connect Best Practices](/implementation-guide/Deploy-and-Manage/Increase-Employer-Adoption) # Increase Employer Adoption Explore our best practices for optimizing employer adoption and conversion in Finch Connect. Finch Connect is our embeddable User Interface (UI) that enables employers to connect their employment system to your application. Employers use Finch Connect to 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). If you’ve [implemented Finch Connect](/implementation-guide/Connect/Set-Up-Finch-Connect), but are seeing drop-off from employers or low connection completion rates, try the following suggestions below to optimize conversion. Before implementing these best practices, make sure you have a mechanism to track conversion rates so you can measure any improvements. The suggestions below are listed in priority order. ## 1. Set Finch Connect as the default integration option Rather than presenting Finch Connect and other manual flows as equal alternatives, encourage your customers to use Finch as the default. You can always include an option to ‘skip this step’, and offer the manual flows as a back up. You can also play with the size, positioning, and color of your entry point to Finch Connect, or test out labels like "Recommended" or "Preferred" to encourage usage. ![Finch Connect Best Practices 1.jpg](https://mintlify.s3.us-west-1.amazonaws.com/finch/images/increase-employer-adoption/finch-connect-best-practices-01.jpg) ## 2. Include extra messaging for context Setting the right expectations is crucial for successful onboarding through Finch Connect. Your app should explain the value of connecting their employment system to your app, what to expect during setup, and how their data will be handled securely. ![Finch Connect Best Practices 4.jpg](https://mintlify.s3.us-west-1.amazonaws.com/finch/images/increase-employer-adoption/finch-connect-best-practices-04.jpg) ### Explain the value of connecting The value for employers will depend on your use case, but may include: * Eliminate security risks associated with sharing PII manually * Remove manual work required to onboard new employee cohorts to the system * Decrease data discrepancies between systems of record * Streamline the onboarding experience for employees * Ensure terminated employees are removed from the system in a timely manner The following are a few examples of how you might introduce Finch Connect in your onboarding flow. ### Tell the user what to expect Before launching the Finch Connect module, explain to the user that they will be prompted to connect their payroll or HRIS system with Finch. Explain what data your app will collect, and why. If the user doesn’t have their credentials on hand, you can give them the option to ‘skip and come back later’ — but make sure to encourage them to [connect later](#3-create-multiple-opportunities-to-connect). ### Emphasize data security Let users know that Finch is secure, and all data is encrypted in transit and at rest. You can share our [What is Finch? FAQ for Employers](https://www.tryfinch.com/for-employers) with any employers who have further questions about Finch. Explain that your app does not have access to their credentials, and that they can choose to disconnect at any time. Feel free to share a link to [Finch's Trust Center](https://finch.secureframetrust.com/#resources) for more information. ## 3. Create multiple opportunities to connect If a user does not connect their employment system during the onboarding process, you can remind them to come back later. Try in-app messaging or email automations to remind them to connect, and why. You can also use these channels to notify users if re-authentication is needed. ## 4. Deploy Finch early in the onboarding process While employer authorization process is quick, a full syncing of the provider's data can take some time. That's why we recommend embedding Finch Connect as early as possible in the onboarding process. While data cannot be retrieved until the synchronization is complete, you can take advantage of this time to continue your core onboarding process, collecting additional information or showing your product tutorial. ![Finch Connect Best Practices 2.jpg](https://mintlify.s3.us-west-1.amazonaws.com/finch/images/increase-employer-adoption/finch-connect-best-practices-02.jpg) You can programmatically add visual cues to show when the data import is complete. Finch provides a [List All Automated Jobs](/api-reference/management/list-automated-jobs) endpoint to monitor the status. Once the job's`status` moves to `complete`, you can now call Finch's various endpoints to read the data. A new job is created to sync the employer's data 24 hours from the previous sync. ```Pending { "paging": { "count": 1, "offset": 0 }, "meta": { "quotas": { "data_sync_all": { "allowed_refreshes": 1, "remaining_refreshes": 1 } } }, "data": [ { "job_id": "a3d1410c-864b-45ce-8d7f-a063914015a0", "job_url": "https://api.tryfinch.com/jobs/automated/a3d1410c-864b-45ce-8d7f-a063914015a0", "status": "pending", "created_at": "2023-08-23T18:05:13.146Z", "scheduled_at": "2023-08-24T18:05:23.282Z", "started_at": "2023-08-24T18:05:27.329Z", "completed_at": null, "type": "data_sync_all" }, ] } ``` ```Complete { "paging": { "count": 1, "offset": 0 }, "meta": { "quotas": { "data_sync_all": { "allowed_refreshes": 1, "remaining_refreshes": 1 } } }, "data": [ { "job_id": "c6d96ca1-01b0-49dd-81af-d354fa7e9cf2", "job_url": "https://api.tryfinch.com/jobs/automated/c6d96ca1-01b0-49dd-81af-d354fa7e9cf2", "status": "pending", "created_at": "2023-08-24T18:07:05.329Z", "scheduled_at": "2023-08-25T18:02:23.282Z", "started_at": null, "completed_at": null, "type": "data_sync_all" }, { "job_id": "a3d1410c-864b-45ce-8d7f-a063914015a0", "job_url": "https://api.tryfinch.com/jobs/automated/a3d1410c-864b-45ce-8d7f-a063914015a0", "status": "complete", "created_at": "2023-08-24T18:05:13.146Z", "scheduled_at": "2023-08-24T18:05:23.282Z", "started_at": "2023-08-24T18:05:27.329Z", "completed_at": 2023-08-24T18:07:05.329Z, "type": "data_sync_all" }, ] } ``` ## 5. Bypass the provider selection screen If you already know which provider(s) your customers use (or want to use), you can skip or limit the provider selection screen in Finch Connect. This removes three possible friction points: 1. If you already know which provider is being used by the customer, you can skip an extra step in the Finch Connect flow. 2. If you want to avoid the customer choosing the wrong provider (e.g. many different [versions of ADP](/integrations/providers)), then you can suggest the right version. 3. If you want to better own the user experience, you can build your own provider selection page and launch Finch Connect with the right provider each time. The provider selection screen can be skipped by providing a valid [provider\_id](/implementation-guide/Connect/Set-Up-Finch-Connect) in the `payroll_provider` option while opening Finch Connect. If you don't know the customer's payroll system upfront or you want to give the customer as many options to connect as possible, then leave the `payroll_provider` option empty while opening Finch Connect. ```bash Bypass Enabled https://connect.tryfinch.com/authorize? &client_id= &products=company directory individual employment payment pay_statement &payroll_provider=gusto &redirect_uri=https://example.com ``` ```bash Bypass Disabled https://connect.tryfinch.com/authorize? &client_id= &products=company directory individual employment payment pay_statement &redirect_uri=https://example.com ``` #### Custom integration page If you want complete control over the user experience, you can also build your own provider selector screen and launch Finch Connect with the right provider each time. ![Finch Connect Best Practices 3.jpg](https://mintlify.s3.us-west-1.amazonaws.com/finch/images/increase-employer-adoption/finch-connect-best-practices-03.jpg) In any case, bypassing the provider selector screen removes friction by eliminating the guesswork for customers during the set up process. *** ## Checkpoint + Next Step After completing this step, your application will have many opportunities to optimize Finch Connection increase the completion rate. Even subtle changes can increase employer adotpion of your application dramatically. Determine which recommendations apply to your application the most and start there. If you have further questions please reach out to our [Support](/implementation-guide/Deploy-and-Manage/Support) team. ## Learn more * [Mitigate Reauthentication Errors](/implementation-guide/Backend-Application/Mitigate-Errors) * [What is Finch? FAQ for Employers](https://www.tryfinch.com/for-employers) # Get Support We have a range of resources available to help you get started with Finch, including our [API Reference](https://developer.tryfinch.com/api-reference/organization/company), [Documentation](https://developer.tryfinch.com/how-finch-works/quickstart), and [Support Center](https://support.tryfinch.com/hc/en-us). Additionally, our Technical Support team is here to help you with any questions you may have about our products. If you have any questions or need help with your integration, please don't hesitate to get in touch with us. We're here to help! ## Information to Include in Support Requests In order to receive the quickest and most accurate responses, please include as much of the following information as possible when submitting a support request: | Information | Description | | -------------- | ------------------------------------------------------------------------------------------------------------------------------ | | request\_id | returned after making a request | | company\_id | associated with the access token, can be found in the developer dashboard or from the `/company`or `/introspect` endpoints | | job\_id | for deductions only, returned after calling the benefits endpoints | | individual\_id | the finch generated id returned from `/directory` endpoint, necessary when asking about specific pay statements or individuals | | benefit\_id | the finch generated id returned from the `/benefits` endpoint, necessary when asking about specific benefits | ## How to Contact Support You can submit tickets to our support team via email, Slack, or our [support portal](https://support.tryfinch.com/hc/en-us). Our support team is available Monday to Friday, 9am to 8pm EST. We aim to respond to all support requests within 24 hours. ### Support Portal When you submit a ticket via our support portal, you will receive an email confirmation with a ticket number. You can use this ticket number to track the status of your request. ### Email You can email our support team at [developers@tryfinch.com](mailto:developers@tryfinch.com) ### Slack If you have a Scale plan and a shared slack channel you can tag our support team in your message using @FinchSupport. ### Developer Success Engineer If you have a Scale plan, you will be assigned a dedicated Developer Success Engineer. Your Developer Success Engineer will be your main point of contact for all technical questions and support requests. They will work with you to ensure that you have everything you need to be successful with Finch. # 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). ![](https://mintlify.s3.us-west-1.amazonaws.com/finch/images/Auth-Methods.png) ### 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. Details for each provider can be found in our [Help Center](https://support.tryfinch.com/hc/en-us/sections/25454225434260-API-Token). 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. ![](https://mintlify.s3.us-west-1.amazonaws.com/finch/images/integration-config/auth-methods.gif) ## 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. ![](https://mintlify.s3.us-west-1.amazonaws.com/finch/images/integration-config/global-auth-methods.png) ## Set Up Authentication Fallback Authentication Fallback is an optional setting that can help employers successfully authenticate through Finch Connect even if we're experiencing intermittent issues with a provider. It can only be enabled for integrations using the [Credentials](https://developer.tryfinch.com/implementation-guide/Integration-Preparation/Configure-Auth-Methods#credentials) authentication method. ![Fallback](https://mintlify.s3.us-west-1.amazonaws.com/finch/images/fallback.png) 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 (default) * 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](https://developer.tryfinch.com/implementation-guide/Connect/Set-Up-Finch-Connect)**. # Email Forwarding Set up email forwarding for ADP Workforce Now and Assisted Integrations. ## Email Forwarding Email forwarding is required if you are going to use ADP Workforce Now or any assisted integrations. 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). Contact your Developer Success Engineer or [developers@tryfinch.com](mailto:developers@tryfinch.com) for set up instructions. This process can take a few days to complete. # 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.