Webhooks
Webhooks allow you to receive real-time notifications when important events occur in the I-9 process. You can use them to trigger downstream workflows, update your internal systems, or monitor form progress without polling our APIs.
Events
When an event occurs, a POST
request is sent to the configured webhook endpoint. All four event types are included—you cannot subscribe to individual events.
Event | eventKey | Description |
---|---|---|
Form I-9 was countersigned | employee.i9Complete | Notifies you when an employee's I-9 is complete and Section 2 is countersigned. |
E-Verify case details updated | employee.everifyCaseUpdate | Triggered when an employee’s E-Verify case is updated. Use this to prompt internal review or next steps. |
I-9 expiring documents | employee.upcomingExpiration | Triggers for EADs and Passport receipts 30 days before expiration, or immediately upon I-9 submission if within 30 days. Excludes original Passports. Applies only to active employees. |
Employee submitted form | employee.section1Complete | Fires when an employee completes Section 1, allowing you to prompt administrative review. |
Webhooks are distinct from the postback service
While webhooks send lightweight notifications about key events (such as form submission or case updates), the postback sends the full completed form data, including the actual form and its values.
The postback is sent to the
postback.target.url
specified in theemployers
object and is typically used for processing the full I-9 record after completion. Read more here: Receive Completed I-9 Data.
Sample Payloads
Form I-9 was countersigned (employee.i9Complete
)
employee.i9Complete
)Sent when Section 2 is countersigned.
{
"eventKey": "employee.i9Complete",
"timestamp": "2025-06-30T08:56:06.971-07:00",
"data": {
"employer": {
"id": "0197b38a-a7ca-77a1-86fb-f090890338d3"
},
"employee": {
"id": "0197b38a-fe6b-7f63-adbe-1f0dd6b2cd99"
},
"submission": {
"id": 435
}
}
}
E-Verify case details updated (employee.everifyCaseUpdate
)
employee.everifyCaseUpdate
)Sent when an employee’s E-Verify case status changes.
{
"eventKey": "employee.everifyCaseUpdate",
"timestamp": "2025-04-18T20:00:09Z",
"data": {
"employer": {
"id": "01964554-ecb6-7e16-9ba8-847a61583323"
},
"employee": {
"id": "01964a6d-82c2-7f41-bcfc-fce93e292ee0"
},
"everifyCase": {
"status": "closed_authorized",
"closed": true,
"submissionId": 14,
"caseId": "201923353824GH"
}
}
}
I-9 expiring documents (employee.upcomingExpiration
)
employee.upcomingExpiration
)Sent 30 days before a document expires, or immediately upon submission if within 30 days.
{
"eventKey": "employee.upcomingExpiration",
"timestamp": "2025-04-18T20:00:09Z",
"data": {
"employer": {
"id": "01964554-ecb6-7e16-9ba8-847a61583323"
},
"employee": {
"id": "01964a6d-82c2-7f41-bcfc-fce93e292ee0"
},
"submission": {
"id": 45,
"documentationExpirationDate": "2024-07-26"
}
}
}
Employee submitted form (employee.section1Complete
)
employee.section1Complete
)Sent when the employee completes Section 1.
{
"eventKey": "employee.section1Complete",
"timestamp": "2025-04-18T20:00:09Z",
"data": {
"employer": {
"id": "01964554-ecb6-7e16-9ba8-847a61583323"
},
"employee": {
"id": "01964a6d-82c2-7f41-bcfc-fce93e292ee0"
},
"submission": {
"id": 435
}
}
}
Configuration
Webhooks are configured at the employer level using the /employers
POST endpoint. You can update the callback URL later using the /employers/{employerId}
PATCH endpoint. When configured, you will receive all four event types.
Request
The webhook
object contains the employee-specific location where the webhook will be sent.
{
"name": "Example Company",
"federalEIN": "98-7654321",
"timezone": "America/New_York",
"address": {
"streetAddress1": "14350 N 87 ST",
"streetAddress2": "STE 310",
"city": "Scottsdale",
"state": "AZ",
"zipCode": "85260"
},
"webhook": {
"callbackUrl": "https://client-system.example.com/callbacks/i9",
"authentication": {
"authType": "BASIC",
"username": "webhook_user",
"password": "webhook_password"
}
}
}
Webhook object fields
Element | Type | Description |
---|---|---|
callbackUrl | string | Endpoint in your system where Symmetry will send the webhook event. This should be a publicly accessible URL that can receive POST requests. |
authentication | object | Specifies how Symmetry should authenticate when sending the webhook request to your system. Supported types include: NONE , BASIC , OAUTH2 . |
authentication.authType | enum | Required. Configures the authentication scheme type to be used: NONE , BASIC , OAUTH2 . |
authentication.username | string | Username to be used for basic authentication and password grant Oauth2 authentication |
authentication.password | string | Password to be used for basic authentication and password grant Oauth2 authentication |
authentication.oauth2ClientId | string | Oauth2 client ID required if using Oauth2 authentication |
authentication.oauth2ClientSecret | string | Oauth2 client secret, required if using Oauth2 authentication |
authentication.oauth2AuthServerUrl | string | URL to the Oauth2 token authentication server, required if using Oauth2 authentication |
authentication.oauth2GrantType | enum | Oauth2 grant type, required if using Oauth2 authentication, supporting password and client credentials type grants: PASSWORD and CLIENT_CREDENTIALS . |
authentication.oauth2AdditionalParameters | object | Additional parameters to be provided to the Oauth2 token authentication server |
For full employer configuration details, see Configure Employers.
Security
Symmetry supports multiple authentication schemes when sending webhook requests:
- None – no authentication header is included
- Basic –
Authorization: Basic <base64(username:password)>
- OAuth2 – Symmetry will request an access token and include it in the
Authorization: Bearer <token>
header
Authentication credentials are included in the request header when Symmetry sends webhook payloads to your system. This ensures secure delivery and proper endpoint validation.
If using OAuth2, ensure your token endpoint supports either the Password or Client Credentials grant type.
Updated about 6 hours ago