Lever
Integrating Incode Identity Verification into Lever ATS
This page covers integrating Incode identity verification into the Lever Applicant Tracking System (ATS). This integration uses Tines, a powerful automation platform, to orchestrate the verification flow between Lever and Incode. When a candidate reaches a designated hiring stage, Tines sends them a personalized verification link, captures the result, and writes it back to their Lever opportunity automatically.
This integration handles the full candidate verification lifecycle. It:
- Validates incoming Lever webhook signatures using HMAC-SHA256.
- Triggers only when a candidate reaches your designated verification stage.
- Fetches candidate details from Lever, generates an Incode verification link, and emails it to the candidate.
- Stores a trace record in Tines to map verification results back to the correct Lever opportunity.
- Listens for Incode verification status updates and writes results, including notes and tags, back to Lever automatically.
Prerequisites
Ensure you have the following before you begin:
| Requirement | Details |
|---|---|
| Tines | An active workspace with permission to create stories, credentials, and records. The Records feature must be enabled. |
| Lever ATS | An account with Admin or Super Admin access to create API keys and configure webhooks. |
| Incode | An active integration with integration ID, secret, and x-api-key available. |
| Email sending | Tines email delivery is used to send verification links. Ensure your workspace domain is allowlisted for outbound email. |
Understand Flows
The automation runs as two independent flows that communicate through a shared Tines Records table.
Flow 1: Trigger and Send Verification
Fires when a candidate moves to the verification stage in Lever.
[Stage change webhook] → [Validate signature] → [Check stage ID]
↓
[GET /candidates/{id}] → [Extract name & email] → [3 min delay]
↓
[GET Incode auth token] → [Generate verification link]
↓
[Capture Tines record] → [Send email to candidate]
Flow 2: Receive Result and Update Lever
Fires when Incode posts a verification status event to your Tines webhook.
[Status update webhook] → [Check event_type == succeeded]
↓
[Match trace ID → OpportunityID]
↓
[Add tag: biometric-verified] → [Post verification note]
Set Up the Lever Integration
Configure Credentials
This Tines story requires five credentials stored in your Tines workspace. Go to Credentials in the Tines sidebar and create each one as a Text credential.
| Credential name | Source | Description |
|---|---|---|
lever_api_key |
Lever > Settings > Integrations > API Credentials | Your Lever API key. Used as a Bearer token to fetch candidate data, post notes, and add tags. |
incode_x_api_key |
Dashboard > API Keys | The x-api-key header value for Incode's authorization endpoint. |
incode_workforce_integrationid |
Dashboard > Integrations | The unique identifier for your Incode integration. |
incode_workforce_secret |
Dashboard > Integrations | The secret for your integration, used for server-side token generation. |
tines_api_key_lever_incode_records |
Tines > Your Profile > API Keys | A Tines API key used by the story to query its own Records table when matching a trace ID to an opportunity. |
Set Up the Lever Webhook
Lever must send a webhook event whenever a candidate's pipeline stage changes.
- Copy the Tines webhook URL: After importing the story, open the
lever_webhookagent and copy the generated webhook URL:
https://<your-tenant>.tines.com/webhook/<story-guid>/871aa415a5da64cdfa3fba63527c374b
- Create the webhook in Lever: In Lever, go to Settings > Integrations > Webhooks and add a new webhook:
| Field | Value |
|---|---|
| URL | Your Tines webhook URL from above |
| Events | candidateStageChange |
| Signing token | Copy this value—you'll need it in the next step |
- Update the HMAC signature secret in the story
Open thevalidate_webhook_signatureagent in Tines and replace the placeholder signing token with your Lever webhook signing token:
{
"calculated_signature_raw": "<<HMAC_SHA256(LOCAL.concatened, \"YOUR_LEVER_SIGNING_TOKEN_HERE\")>>"
}
Set Up the Incode Webhook
Incode must POST verification status events to a second Tines webhook endpoint. This drives Flow 2.
- Copy the verification status webhook URL: After importing the story, open the
Get_verification_status_updatesagent and copy its webhook URL:
https://<your-tenant>.tines.com/webhook/<story-guid>/59ab814228451619d85618e952e62c34
- Register the webhook in Incode: In Dashboard, go to Configuration > Webhooks and configure a webhook pointing to the URL above. The story expects the following fields in the webhook payload:
{
"event_type": "verification.succeeded",
"data": {
"verification_trace_id": "<trace-id>",
"failure_reason": "<status message>",
"ip": "<candidate IP>",
"user_name": "<candidate name>",
"latitude": 0.0,
"longitude": 0.0
}
}
Configure Your Lever Stage ID
The story triggers only when a candidate advances to a specific Lever pipeline stage. You must update the stage ID to match a stage in your own Lever environment.
- Find the stage ID in Lever: Use the Lever API to list your pipeline stages:
curl -X GET https://api.lever.co/v1/stages \
-H "Authorization: Bearer <your-lever-api-key>"
- Update the
validate_stageagent: Open thevalidate_stageagent in Tines and replace the stage ID in the trigger rule:
{
"type": "field==value",
"value": "YOUR-STAGE-UUID-HERE",
"path": "EXTRACT_DATA.TO_STAGE_ID"
}
Import the Tines Story
- Download the story file: Download
lever-incode-candidate-biometric-identity-verification.jsonfrom your Incode account manager. - Import into Tines: In your Tines workspace, click New Story > Import and upload the JSON file. Tines then creates all agents, connections, and the Tines Records table automatically.
- Complete configuration: Before enabling the story, confirm the following:
- All five credentials are created in Tines.
- Lever webhook is configured to POST to
lever_webhook. - Lever HMAC signing token is updated in
validate_webhook_signature. - Stage ID is updated in
validate_stage. - Incode webhook is configured to POST to
Get_verification_status_updates. - Email sender name and reply-to address is updated in the Send Email Action.
- Redirect URL in
incode_verificationis updated to your domain.
- Enable and test: Enable the story in Tines. Move a test candidate to your verification stage in Lever and confirm the story fires, the email is sent, and a record appears in the Tines Records table.
Automation Agents Reference
The story contains 16 agents across both flows.
Flow 1: Send Verification
| Agent | Type | Description |
|---|---|---|
lever_webhook |
WebhookAgent | Receives all candidateStageChange POST events from Lever. Responds with HTTP 200 immediately. |
validate_webhook_signature |
EventTransformationAgent | Computes HMAC-SHA256 of token and triggeredAt using your Lever signing secret and compares it to the received signature. |
check_signature |
TriggerAgent | Gate: passes only events where the computed signature matches the received signature. Rejects forged or replayed webhooks. |
extract_data |
EventTransformationAgent | Extracts candidateId, opportunityId, fromStageId, toStageId, and stageName from the webhook payload. |
validate_stage |
TriggerAgent | Gate: passes only events where toStageId equals your configured verification stage ID. |
get_candidate_details |
HTTPRequestAgent | Calls GET /v1/candidates/{id} on the Lever API to retrieve the candidate's profile. |
extract_candidate_details |
EventTransformationAgent | Parses name, email, and phone from the Lever response. Splits full name into first_name and last_name for Incode. |
Delay sending identity verification message |
EventTransformationAgent (delay) | Waits 3 minutes before continuing. Allows stage transitions to settle in Lever before sending the email. |
get_incode_token |
HTTPRequestAgent | Calls the Incode server-side authorization endpoint to obtain a short-lived session token using your integration credentials. |
incode_verification |
HTTPRequestAgent | Generates a personalized, time-limited verification link for the candidate. The link is valid for 72 hours. |
Capture Record |
RecordAgent | Creates a record in the Lever_Incode_Information table storing the opportunity ID, candidate ID, and Incode trace ID. |
Send Email Action |
EmailAgent | Sends an HTML-formatted email to the candidate with the verification link and instructions. |
Flow 2: Receive Result
| Agent | Type | Description |
|---|---|---|
Get_verification_status_updates |
WebhookAgent | Receives POST callbacks from Incode containing verification results. Second entry point of the story. |
Trigger Action |
TriggerAgent | Gate: passes only events where event_type == "verification.succeeded". |
Match_record_trace_opportunity |
HTTPRequestAgent | Queries the Tines Records API to find the opportunity ID matching the verification_trace_id from the Incode callback. |
update_lever_tag |
HTTPRequestAgent | Calls POST /v1/opportunities/{id}/addTags to add the biometric-verified tag to the candidate's Lever opportunity. |
update_lever_note |
HTTPRequestAgent | Posts a structured note to the Lever opportunity with the event type, status, trace ID, IP, name, and geolocation from the Incode verification result. |
API Reference
Incode APIs
Get Auth Token
POST https://demo-api-incode-id.incodesmile.com/v1/integration/authorize/server
x-api-key: CREDENTIAL.INCODE_X_API_KEY
Request body:
{
"integrationId": "CREDENTIAL.INCODE_WORKFORCE_INTEGRATIONID",
"secret": "CREDENTIAL.INCODE_WORKFORCE_SECRET"
}
Lever APIs
Get Candidate Details
GET https://api.lever.co/v1/candidates/{candidateId}
Authorization: Bearer CREDENTIAL.LEVER_API_KEY
Key response fields used:
data.name // full name — split into first/last
data.emails[0] // primary email address
data.phones[0] // primary phone number