Outgoing Webhooks

Real-time event notifications

ClearView can send real-time HTTP POST notifications to your server whenever important events occur -- such as a new company being identified or a lead reaching a hot score. Use webhooks to integrate ClearView with your own backend, CRM, or automation tools.

# Setting Up Webhooks

Configure outgoing webhooks from your ClearView dashboard:

  1. 1Navigate to Settings > Webhooks in your ClearView dashboard.
  2. 2Click "Add Webhook Endpoint".
  3. 3Enter the URL of your server endpoint (must be HTTPS in production).
  4. 4Select the events you want to subscribe to.
  5. 5Copy the generated webhook signing secret and store it securely.
  6. 6Click "Save" to activate the webhook.

HTTPS required

Webhook endpoints must use HTTPS in production. For local development, you can use tools like ngrok or localtunnel to expose your local server.

# Webhook Events

Subscribe to one or more of the following events:

EventDescriptionDetails
company.identifiedA new company has been identified visiting your siteFires once per company when first resolved from an IP address
lead.hotA lead has reached the hot score thresholdFires when a company's lead score crosses your configured hot threshold (default 70)
lead.score_changedA lead's score has changedFires whenever a company's lead score increases or decreases by 5 or more points
watchlist.hitA watched company has visited your siteFires when a visitor from a company on your Watch List is detected. Includes person-level data if available.
visitor.returningA previously seen visitor has returnedFires when a known company visits again after 24+ hours of inactivity
page_viewA page view was recordedFires on every tracked page view. High volume -- use with caution

High-volume events

The page_view event fires on every tracked page view and can generate a very high volume of webhook calls. Only subscribe to it if your endpoint can handle the load.

# Payload Format

Every webhook delivery is an HTTP POST with a JSON body. All payloads share this structure:

Webhook payload
json
{
"id": "evt_a1b2c3d4e5f6",
"event": "company.identified",
"timestamp": "2025-12-15T14:33:12Z",
"data": {
"company": {
"id": "comp_a1b2c3d4",
"name": "Acme Corp",
"domain": "acme.com",
"industry": "Technology",
"size": "51-200",
"city": "San Francisco",
"region": "California",
"country": "US",
"logoUrl": "https://logo.clearbit.com/acme.com",
"linkedinUrl": "https://linkedin.com/company/acme",
"employeeCount": 142,
"revenue": "$10M-$50M",
"leadScore": 87,
"firstSeen": "2025-12-15T14:33:12Z",
"lastSeen": "2025-12-15T14:33:12Z",
"visitorCount": 1
},
"visitor": {
"city": "San Francisco",
"region": "California",
"country": "US",
"pageUrl": "/pricing",
"referrer": "https://google.com"
}
}
}

Payload fields

FieldTypeDescription
idstringUnique event ID for idempotency
eventstringEvent type (e.g. company.identified)
timestampstringISO 8601 timestamp when event occurred
dataobjectEvent-specific payload data
data.companyobjectFull company object (most events)
data.visitorobjectVisitor context (when available)
data.previousScorenumberPrevious score (lead.score_changed only)
data.newScorenumberNew score (lead.score_changed only)

Event-specific payloads

lead.score_changed

lead.score_changed payload
json
{
"id": "evt_x9y8z7",
"event": "lead.score_changed",
"timestamp": "2025-12-15T16:45:00Z",
"data": {
"company": {
"id": "comp_a1b2c3d4",
"name": "Acme Corp",
"domain": "acme.com",
"leadScore": 92
},
"previousScore": 78,
"newScore": 92
}
}

page_view

page_view payload
json
{
"id": "evt_p1q2r3",
"event": "page_view",
"timestamp": "2025-12-15T14:35:00Z",
"data": {
"company": {
"id": "comp_a1b2c3d4",
"name": "Acme Corp",
"domain": "acme.com"
},
"pageView": {
"url": "/pricing",
"title": "Pricing - Acme Corp",
"referrer": "https://google.com",
"duration": 45,
"timestamp": "2025-12-15T14:35:00Z"
}
}
}

# Security & Verification

Every webhook delivery includes a signature header so you can verify it came from ClearView and was not tampered with.

Signature header

ClearView signs each request body using HMAC-SHA256 with your webhook signing secret. The signature is sent in the X-Webhook-Signature header.

HeaderDescription
X-Webhook-SignatureHMAC-SHA256 hex digest of the raw request body using your signing secret
X-Webhook-EventThe event type (e.g. company.identified)
X-Webhook-IdUnique delivery ID for deduplication

Verifying the signature

To verify, compute the HMAC-SHA256 of the raw request body using your signing secret and compare it to the header value:

Node.js verification
javascript
const crypto = require("crypto");
function verifyWebhookSignature(rawBody, signature, secret) {
const expected = crypto
.createHmac("sha256", secret)
.update(rawBody)
.digest("hex");
return crypto.timingSafeEqual(
Buffer.from(signature),
Buffer.from(expected)
);
}
Python verification
python
import hmac
import hashlib
def verify_webhook_signature(raw_body: bytes, signature: str, secret: str) -> bool:
expected = hmac.new(
secret.encode("utf-8"),
raw_body,
hashlib.sha256,
).hexdigest()
return hmac.compare_digest(signature, expected)

Always verify signatures

Never skip signature verification in production. Without it, anyone can send fake webhook events to your endpoint.

# Retry Policy

If your endpoint returns a non-2xx status code or times out, ClearView retries delivery with exponential backoff:

AttemptDelay
1st retry30 seconds
2nd retry2 minutes
3rd retry10 minutes
4th retry1 hour
5th retry (final)4 hours
  • Your endpoint must respond within 10 seconds or the attempt is marked as timed out.
  • Any 2xx response is treated as successful delivery.
  • After all retries are exhausted, the event is marked as failed in your dashboard.
  • If your endpoint fails consistently, the webhook will be automatically disabled after 7 days of failures.

Idempotency

Use the id field in the webhook payload to deduplicate events. The same event may be delivered more than once during retries.

# Testing Webhooks

You can test your webhook endpoint directly from the ClearView dashboard:

  1. 1Go to Settings > Webhooks and select your endpoint.
  2. 2Click the "Send Test Event" button.
  3. 3Choose an event type from the dropdown.
  4. 4ClearView will send a sample payload to your endpoint.
  5. 5Check the delivery log to confirm your endpoint returned a 2xx response.

Local development

For local testing, use a tunneling service to expose your local server:
Using ngrok
bash
# Install ngrok and start a tunnel
ngrok http 3000
# Copy the HTTPS URL (e.g. https://abc123.ngrok.io)
# Paste it as your webhook URL in ClearView settings

# Example: Express.js Receiver

Here is a complete Express.js server that receives and verifies ClearView webhook events:

server.js
javascript
1const express = require("express");
2const crypto = require("crypto");
3
4const app = express();
5const WEBHOOK_SECRET = process.env.CLEARVIEW_WEBHOOK_SECRET;
6
7// Parse raw body for signature verification
8app.post(
9 "/webhooks/clearview",
10 express.raw({ type: "application/json" }),
11 (req, res) => {
12 const signature = req.headers["x-webhook-signature"];
13 const eventType = req.headers["x-webhook-event"];
14
15 // Verify signature
16 if (!signature || !WEBHOOK_SECRET) {
17 return res.status(401).json({ error: "Missing signature" });
18 }
19
20 const expected = crypto
21 .createHmac("sha256", WEBHOOK_SECRET)
22 .update(req.body)
23 .digest("hex");
24
25 if (!crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected))) {
26 return res.status(401).json({ error: "Invalid signature" });
27 }
28
29 // Parse the verified body
30 const payload = JSON.parse(req.body.toString());
31 console.log(`Received event: ${eventType}`, payload.id);
32
33 // Handle events
34 switch (payload.event) {
35 case "company.identified":
36 console.log(`New company: ${payload.data.company.name}`);
37 // Add to your CRM, notify sales, etc.
38 break;
39
40 case "lead.hot":
41 console.log(`Hot lead: ${payload.data.company.name}`);
42 // Send Slack notification, create task, etc.
43 break;
44
45 case "lead.score_changed":
46 console.log(
47 `Score changed: ${payload.data.company.name} ` +
48 `${payload.data.previousScore} -> ${payload.data.newScore}`
49 );
50 break;
51
52 case "visitor.returning":
53 console.log(`Returning visitor: ${payload.data.company.name}`);
54 break;
55
56 case "page_view":
57 console.log(`Page view: ${payload.data.pageView.url}`);
58 break;
59
60 default:
61 console.log(`Unknown event: ${payload.event}`);
62 }
63
64 // Respond with 200 to acknowledge receipt
65 res.status(200).json({ received: true });
66 }
67);
68
69app.listen(3000, () => {
70 console.log("Webhook receiver listening on port 3000");
71});

Need Help?

Having trouble with webhooks? Check the Troubleshooting guide or reach out to our support team.

Contact Support