Webhooks are not available on our legacy Free or Build plans. Upgrade to Starter, Pro, or Premier for access.
Webhook Payload Structure
Common payload fields
Each webhook event contains the following fields in the response body:| Field Name | Type | Description |
|---|---|---|
company_id | string<uuid> | Deprecated. Use connection_id instead. |
account_id | string<uuid> | Deprecated. Use connection_id instead. |
connection_id | string<uuid> | Unique Finch id representing the connection between a developer’s application and an employer’s provider. Created when an employer successfully authenticates through Finch Connect. |
entity_id | string<uuid> | Unique Finch id of the entity within the connection for which data has been updated. Present when the connection spans multiple entities; null otherwise. |
event_type | string | The type of webhook being delivered. |
data | object | More information about the associated event. The structure of this object will vary per event type. |
Account Updates
Account update events contain information about account connections, such as when a connection has been established or when a connection has entered an error state. This type of webhook has the following unique schema:| Field Name | Type | Description |
|---|---|---|
event_type | string | Always account.updated. |
data.status | string | The status of the account. This follows our standard connection status schema. Options are pending, processing, connected, reauth, error_permissions, error_no_account_setup, disconnected. |
data.authentication_method | string | The method of authentication used to connect this account. Options follow the standard Finch authentication types: credential, api_token, oauth, and assisted. |
Job Completion
Job completion events fire when a job finishes running, whether the final state is a success or an error. Upon receiving ajob.{job_type}.completed event, use the job_url in the payload to retrieve the job’s final status.
| Event | Description | Values |
|---|---|---|
job.data_sync_all.completed | Emitted for automated data sync jobs. Check status via the automated jobs endpoint. | — |
job.w4_form_employee_sync.completed | Emitted for automated W4 form sync jobs. Check status via the automated jobs endpoint. | — |
job.initial_data_sync_*.succeeded | Emitted when an initial data sync completes successfully for the first time. | initial_data_sync_org, initial_data_sync_payroll |
job.benefit_*.completed | Emitted for benefit-related jobs. Check status via the manual jobs endpoint. | benefit_create, benefit_register, benefit_enroll, benefit_unenroll, benefit_update |
data schema:
| Field Name | Type | Description |
|---|---|---|
event_type | string | Follows the schema job.{job_type}.completed. {job_type} can be any valid Finch job type such as data_sync_all, benefit_create, or benefit_enroll. |
data.job_id | string<uuid> | The id of the job which has completed. |
data.job_url | string | The url to query the result of the job. |
Data Changes
Data change events fire when any data for a connection changes after Finch’s initial data sync. These could becreated, updated, or deleted events on any of our endpoints. One event fires per changed record — for example, if 10 individuals are updated across Directory, Employment, or Individual, Finch sends 10 separate events. This type of event has the following schema:
| Field Name | Type | Description |
|---|---|---|
event_type | string | Follows the schema {endpoint}.{created|updated|deleted}. {endpoint} can be any Finch endpoint such as company, directory, individual, etc. You can see the full up-to-date list of events by registering an endpoint in our developer dashboard. |
data | object | The data object schema will change depending on the endpoint. |
data schemas per endpoint are as follows:
| Endpoint | Event types | data fields |
|---|---|---|
company | company.updated only | null |
directory | directory.created, directory.updated, directory.deleted | individual_id |
employment | employment.created, employment.updated, employment.deleted | individual_id |
individual | individual.created, individual.updated, individual.deleted | individual_id |
payment | payment.created, payment.updated, payment.deleted | payment_id, pay_date |
pay_statement | pay_statement.created, pay_statement.updated, pay_statement.deleted | payment_id, individual_id |
Company
Individual
Pay Statement
Supported Events
| Event | Automated | Assisted |
|---|---|---|
| Account Updates | ✓ | ✓ |
| Job Completion | All events | Benefit jobs only |
| Data Changes | ✓ | — |
Required Events
The following events cover the core connection lifecycle. Any application integrating with Finch must handle them.| Event | When to handle | Action |
|---|---|---|
account.updated | data.status is reauth | Prompt the employer to re-authenticate via Finch Connect. See Reauthentication. |
job.initial_data_sync_org.succeeded | Initial org data sync completes | Begin reading org endpoints. Requests made before this event may return 202 or 500. |
job.initial_data_sync_payroll.succeeded | Initial payroll data sync completes | Begin reading payroll endpoints. Requests made before this event may return 202 or 500. |
job.benefit_*.completed | A benefit write job finishes | Call Retrieve a Manual Job with data.job_id to check the outcome — the event fires on both success and failure. Required if your application writes deductions. |
Webhook Registration
Webhook endpoints should use HTTPS and expect to receive POST requests with the following headers:

Webhook Verification
Finch uses HMAC-SHA256 webhook verification. To verify a webhook using theFinch-Signature header:
- Extract the signature from the header. The
Finch-Signatureheader 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.
- Generate the webhook signature
- First, base64 decode the webhook secret to get the raw bytes.
- Then, using the decoded webhook secret, hash the webhook content in the form
{webhook_id}.{webhook_timestamp}.{body}wherewebhook_idis theFinch-Event-Id,webhook_timestampis theFinch-Timestamp, andbodyis the raw request body. The signature is sensitive to any change in the body — do not modify it before verifying. If the computed signature does not match any signature in theFinch-Signatureheader, reject the webhook. Use a constant-time comparison to avoid timing attacks.
- Verify the webhook timestamp. If the signature is valid, check that the timestamp is within five minutes of the current time. If it is not, reject the webhook. Using outdated webhooks increases susceptibility to replay attacks.
Testing Webhooks
You can send a test request to any webhook through the developer dashboard.
event_type set to test.
Retry schedule
Upon failure, Finch retries according to the following schedule with exponential backoff:- Immediately
- 5 seconds
- 5 minutes
- 30 minutes
- 2 hours
Best practices
Responding to Webhooks
To prevent unnecessary retries, receive and process webhook events in separate processes. Respond immediately with a200 to indicate successful delivery, then process the event asynchronously.
Event Delivery and Ordering
- You may occasionally receive the same webhook event more than once. Use the
Finch-Event-Idto implement idempotent event processing. - Finch does not guarantee delivery of events in the order they happen. For example, you may receive an
updateevent for anindividualbefore acreatedevent. 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 anupdateevent first.
Event Mapping
- Each webhook includes a
connection_ididentifying the employer connection. Use it to route incoming events to the right employer in your system. For details on capturing and storing theconnection_id, see Retrieve Access Token. - Each webhook also includes an
entity_idfor the specific entity within that connection. For multi-entity connections, theentity_idis required in subsequent API requests.