Webhooks and Real-Time Lead Notifications: A Technical Guide
Webhooks and Real-Time Lead Notifications: A Technical Guide
Polling is expensive, slow, and fragile. Webhooks let your lead system push updates to every connected tool the moment something changes.
Polling is expensive, slow, and fragile. Every time your application makes an API call to check whether something has changed, "Did any new leads come in? Did any scores change?", you are paying for that request whether or not anything happened. At low scale, this is barely noticeable. At high scale, polling-based integrations become a significant source of API cost, latency, and race conditions.
Webhooks invert this model. Instead of your system asking "did anything change?", your lead system tells your downstream systems "something just changed, here is what." The event is pushed to your endpoint the moment it occurs: no polling, no delay, no wasted requests. For lead management at scale, webhooks are the difference between integrations that feel real-time and integrations that feel like they are running five minutes behind.
This article covers how to implement webhooks correctly, both as a provider configuring them in your lead system and as a consumer building endpoints to receive them.
Webhook Architecture and Event Design
The webhook lifecycle:
A webhook starts with an event: something meaningful that happened in your lead system. A new lead was created. An existing lead was updated. A lead was deleted. A score was recalculated. The system serializes the event as a JSON payload and makes an HTTP POST request to each registered endpoint URL for that event type.
The consuming system, your CRM, your Slack integration, your scoring pipeline, your sales automation tool, receives the POST request, validates it, processes the payload, and returns an HTTP 200 response. If it returns anything other than a 2xx response, the webhook system treats the delivery as failed and schedules a retry.
Event taxonomy:
For lead management, the minimal useful event set is:
lead.created: fires when a new lead is added to the database, including the full lead payloadlead.updated: fires when any field on an existing lead changes, including the changed fields and their new valueslead.deleted: fires when a lead is permanently removed, including the lead ID and any metadata needed for downstream cleanuplead.scored: fires when a lead's score is recalculated, including the new score, the previous score, and optionally the rule contributions that produced itlead.merged: fires when a duplicate is detected and merged into an existing record, including both the source and target lead IDs
Each event should carry a consistent structure: an event ID, an event type, a timestamp, the API version that produced it, and the payload. The event ID is critical. It allows consuming systems to implement idempotency so that processing the same event twice does not cause duplicate side effects.
Payload design decisions:
Two design choices significantly affect how useful your webhooks are.
Fat versus thin payloads. A fat payload includes the full current state of the lead in every event. A thin payload includes only the event metadata and the changed fields, requiring the consumer to make a follow-up API call for the full record. Fat payloads are simpler for consumers since no follow-up call is required. Thin payloads are smaller and give consumers flexibility to decide whether they need the full record. For most lead management use cases, fat payloads are preferable. The extra data is almost always useful, and eliminating the follow-up API call reduces latency and complexity.
Including old values. For lead.updated events, including the previous values of changed fields allows consuming systems to implement intelligent conditional logic: "only update the CRM record if the lead's email changed, not if just a tag was added." This diff pattern is more complex to generate but significantly more useful to consumers.
Building a Reliable Webhook Consumer
Receiving webhooks correctly is harder than it looks. Most integrations that fail in production fail because the consumer was not built to handle the reliability challenges inherent in HTTP-based event delivery.
Step 1: Validate the signature.
Every webhook request should include a cryptographic signature that proves it came from your lead system and not from a malicious third party. The standard pattern: the webhook provider generates an HMAC-SHA256 signature of the payload using a shared secret and includes it in a header (X-Webhook-Signature or X-Hub-Signature-256). Your consumer validates the signature before processing the payload:
const crypto = require('crypto'); function validateWebhookSignature(payload, signature, secret) { const expectedSignature = crypto .createHmac('sha256', secret) .update(payload, 'utf8') .digest('hex'); return crypto.timingSafeEqual( Buffer.from(signature), Buffer.from(`sha256=${expectedSignature}`) ); }
Use timingSafeEqual to prevent timing attacks. Reject any request that does not pass signature validation with a 401.
Step 2: Respond immediately, process asynchronously.
The webhook provider is waiting for your HTTP response. If your endpoint takes more than a few seconds to respond (typically a 5-30 second timeout depending on the provider), the delivery will be treated as failed and retried. This is a common failure mode: the consumer tries to complete all its processing synchronously within the HTTP request, the processing takes too long, the provider times out, retries the delivery, and the consumer processes the same event multiple times.
The correct pattern: respond with HTTP 200 immediately upon receiving and validating the request. Put the payload on an internal queue (a database table, Redis queue, or message broker like SQS). A separate worker process dequeues and processes events asynchronously. This pattern decouples delivery acknowledgment from processing and makes your consumer resilient to processing failures.
Step 3: Implement idempotency.
Webhooks are delivered at-least-once, not exactly-once. Your endpoint will receive duplicate deliveries due to provider retries, network hiccups, and timeout edge cases. Every event includes a unique event_id. Your consumer should store processed event IDs and check before processing: if the event ID has already been processed, skip it and return 200. Without idempotency, duplicate deliveries create duplicate records, double-charged processing, and incorrect state in downstream systems.
Step 4: Handle out-of-order delivery.
Events are not guaranteed to arrive in the order they were generated. A lead.updated event may arrive before the lead.created event for the same lead due to retry timing. Your consumer must handle this gracefully. Use the event timestamp and the lead ID to determine the correct order, and implement an event buffer pattern if strict ordering is required.
Step 5: Build a dead letter queue.
Some events will fail processing after all retries are exhausted due to bugs in your processing logic, downstream system unavailability, or data conditions your code did not anticipate. Build a dead letter queue where failed events are stored for manual review and replay. Without a dead letter queue, failed events are silently dropped and the data inconsistency compounds over time.
Free resource
The first 2 chapters of the Lead Management Bible — free.
90+ pages, 150+ actionable steps to fix your pipeline today.
Webhook Operations in Production
Retry strategies:
Webhook providers should implement exponential backoff for retry scheduling. If the first delivery fails, retry after 30 seconds. If that fails, retry after 2 minutes, then 10 minutes, then 1 hour, then 6 hours. Cap retries at 24-72 hours depending on the criticality of the event type. Log all retry attempts and their outcomes.
Monitoring and alerting:
Track three metrics for each webhook endpoint:
- Delivery success rate (2xx responses divided by total attempts): alert if below 95%.
- Average delivery latency: alert if above 2 seconds.
- Dead letter queue depth: alert if growing.
Testing webhooks locally:
Use a tool like ngrok or Cloudflare Tunnel to expose your local development server to the public internet for webhook delivery during development. Most webhook providers also offer a test mode that sends synthetic events to registered endpoints. Use it to validate your consumer logic before connecting live data.
Practical Application: Setting Up Your First Webhook Consumer
-
Register your endpoint. In your lead system's webhook settings, register the URL of your consumer endpoint and select which event types you want to receive.
-
Store the signing secret securely. Copy the signing secret from your lead system and store it in your environment variables. Never hardcode it in your application source code.
-
Build the signature validation middleware. Write a middleware function that extracts the signature from the request header, recomputes it from the raw request body, and returns a 401 if they do not match. Apply this middleware to all webhook routes.
-
Acknowledge immediately. Your endpoint's first action after validation should be returning HTTP 200. Enqueue the raw payload with the event ID for async processing.
-
Build the async processor. Write a worker that reads from your queue, checks whether the event ID has already been processed, and executes the appropriate business logic if not. Mark the event as processed after successful completion.
-
Set up the dead letter queue. Any event that fails processing after 3-5 retries should move to a dead letter queue table in your database. Build a simple admin view to see failed events and replay them individually.
-
Add monitoring. Write a daily report or a real-time alert that fires if your delivery success rate drops below 95% or your dead letter queue grows beyond a threshold.
Webhooks are the infrastructure that makes real-time lead operations possible. Every minute of delay in syncing a new lead to your CRM, notifying your sales team, or triggering a scoring update is a minute of competitive disadvantage. Building a reliable webhook consumer with signature validation, async processing, idempotency, and dead letter queues is a half-day engineering project that pays dividends for the lifetime of the integration. Do it right the first time.
Put it into practice
Ready to build your lead system?
Klozeo gives you a lead database, scoring rules, and MCP integration — all in one API-first platform. Free to start.
No credit card required · Free up to 100 leads
Part of The Leads Bible — 100 strategies to find, qualify, and convert leads.
Browse all 100 strategies →