Webhooks
Webhooks let you receive real-time HTTP notifications when events occur in your Lead Hero organization. Configure them from the API Keys section in organization settings.
Event
Every webhook delivery is a POST request with a JSON body containing a standard envelope:
| Field | Type | Description |
|---|---|---|
id | string | Unique event ID (UUID) |
type | string | Event type (e.g. lead.updated) |
createdAt | string | ISO 8601 timestamp of the event |
organizationId | string | Your organization's slug |
data | object | Current snapshot of the affected resource |
{
"id": "event_uuid",
"type": "lead.updated",
"createdAt": "2026-03-22T12:34:56.000Z",
"organizationId": "acme",
"data": {
"lead": {
"id": "lead_uuid",
"status": "answered"
}
}
}
Delivery Headers
Each request includes the following headers:
| Header | Description |
|---|---|
X-LeadHero-Event | The event type (e.g. lead.updated) |
X-LeadHero-Timestamp | Unix timestamp in milliseconds |
X-LeadHero-Webhook-Id | The webhook's ID |
X-LeadHero-Delivery-Id | Unique ID for this delivery attempt |
X-LeadHero-Signature | HMAC SHA-256 signature (sha256=SIGNATURE) |
Signature Verification
If you enable secret generation on a webhook, Lead Hero signs the raw request body with HMAC SHA-256. The signed string is:
timestamp + "." + body
where timestamp is the value from the X-LeadHero-Timestamp header and body is the raw request body string.
Compare the computed signature against the X-LeadHero-Signature header (after stripping the sha256= prefix) to verify authenticity. Always use a constant-time comparison to prevent timing attacks.
Supported Events
| Event | Triggered when |
|---|---|
call.answered | A call is answered |
call.completed | A call ends |
call.initiated | An outbound call is started |
lead.created | A new lead is created |
lead.updated | A lead's data changes |
lead.deleted | A lead is deleted |
enrichment.completed | A lead enrichment job finishes (Webhook URL might be overridden) |
phone_verification.completed | A phone validation job finishes processing |
lead.created — company followers import
When a company followers search completes with Add to Organization enabled, each discovered follower that doesn't already exist fires a lead.created event:
{
"id": "event_uuid",
"type": "lead.created",
"createdAt": "2026-04-23T10:00:00.000Z",
"organizationId": "acme",
"data": {
"lead": {
"id": "lead_uuid",
"name": "Jane Smith",
"jobTitle": "Marketing Manager",
"company": { "name": "Acme Corp" },
"location": "San Francisco, CA",
"linkedinUrl": "https://www.linkedin.com/in/janesmith",
"source": "import",
"organization": "acme",
"createdAt": "2026-04-23T10:00:00.000Z"
}
}
}
If a follower matches an existing lead, a lead.updated event is fired instead with the same shape.
enrichment.completed — phone finding after company followers import
When Find Phone is enabled on a company followers search, a phone enrichment batch runs automatically after the leads are imported. Once every lead in the batch has been processed, an enrichment.completed event fires:
{
"id": "event_uuid",
"type": "enrichment.completed",
"createdAt": "2026-04-23T10:05:00.000Z",
"organizationId": "acme",
"data": {
"enrichment": {
"id": "session_uuid",
"organization": "acme",
"status": "completed",
"totalLength": 42,
"cost": 0.21,
"createdAt": "2026-04-23T10:00:30.000Z"
}
}
}
phone_verification.completed — bulk phone validation finished
Fires when a phone validation batch completes processing. Use this to trigger downstream workflows without polling the API.
{
"id": "event_uuid",
"type": "phone_verification.completed",
"createdAt": "2026-05-04T14:00:00.000Z",
"organizationId": "acme",
"data": {
"jobId": "job_uuid",
"status": "completed",
"totalPhones": 5000,
"validPhones": 3812,
"invalidPhones": 1188,
"cost": 5.00,
"saveLeads": false,
"filename": "my-list.csv"
}
}
| Field | Type | Description |
|---|---|---|
jobId | string | ID of the phone validation job |
status | string | Always "completed" for this event |
totalPhones | number | Number of phone numbers submitted |
validPhones | number | Numbers that passed validation |
invalidPhones | number | Numbers that failed validation |
cost | number | Total cost charged for this job (USD) |
saveLeads | boolean | Whether validated leads were automatically saved to the org |
filename | string | Original filename if uploaded via CSV (omitted when not present) |
Note: Download links are not included in the webhook payload. Use the Download buttons in the LeadHero dashboard or the API to retrieve your results after receiving this event.
Retries and Backoff
Webhook deliveries are queued to protect against spikes and slow receivers.
- Attempts: up to 5 total
- Timeout: 15 seconds per request
- Success criterion: any
2xxresponse — non-2xx responses, timeouts, and network failures are all retried - Backoff: exponential starting at 2 seconds — retry delays are approximately 2s, 4s, 8s, and 16s between attempts