Webhooks API
Configure webhook endpoints to receive real-time notifications when LinkedIn profiles and companies change.
Quick Reference
/api/v1/webhooks/configure
/api/v1/webhooks/configuration
/api/v1/webhooks/configure
/api/v1/webhooks/test
/api/v1/webhooks/deliveries
/api/v1/webhooks/rotate-secret
Webhook Event Types
Sales Webhooks monitors and delivers the following event types:
Contact Events
Event Type | Description |
---|---|
contact.position_changed |
Job title changed |
contact.company_changed |
Moved to a new company |
contact.headline_changed |
LinkedIn headline updated |
contact.about_changed |
About section modified |
contact.post_created |
New post published |
contact.comment_created |
Commented on a post |
contact.reaction_added |
Reacted to content |
Company Events
Event Type | Description |
---|---|
company.post_created |
New company post |
company.description_changed |
Company description updated |
company.employee_count_changed |
Employee count changed significantly |
Configure Webhook Endpoint
Set up your webhook endpoint to receive change notifications. You can also configure your webhook URL directly through the Console UI under Settings → Webhooks for a more user-friendly experience.
/api/v1/webhooks/configure
Request Body
{
"endpoint_url": "https://your-domain.com/webhook", // Required: HTTPS URL
"events": ["*"], // Optional: Event types to receive (default: all)
"is_active": true, // Optional: Enable/disable webhook
"initial_webhook": "all" // Optional: "all", "latest", or "none"
}
Event Filtering
Specify which events to receive:
// Receive all events (default)
"events": ["*"]
// Only job changes
"events": ["contact.position_changed", "contact.company_changed"]
// Only content events
"events": ["contact.post_created", "company.post_created"]
// Specific contact events
"events": ["contact.*"]
Response
{
"id": "whc_8Zx6Li1Ko",
"endpoint_url": "https://your-domain.com/webhook",
"events": ["*"],
"secret": "whsec_verySecretKey123", // Save this! Only shown once
"is_active": true,
"initial_webhook": "all",
"created_at": "2025-01-20T10:30:00Z",
"updated_at": "2025-01-20T10:30:00Z"
}
Important: Save the secret
immediately. It's only shown once and is required for webhook signature verification.
Get Webhook Configuration
Retrieve your current webhook configuration.
/api/v1/webhooks/configuration
Response
{
"id": "whc_8Zx6Li1Ko",
"endpoint_url": "https://your-domain.com/webhook",
"events": ["*"],
"is_active": true,
"initial_webhook": "latest",
"created_at": "2025-01-20T10:30:00Z",
"updated_at": "2025-01-20T10:30:00Z",
"last_delivery_at": "2025-01-20T15:45:00Z",
"delivery_stats": {
"total": 1523,
"successful": 1520,
"failed": 3
}
}
Note: The webhook secret is never returned in GET requests for security.
Update Webhook Configuration
Update your webhook endpoint or event subscriptions.
/api/v1/webhooks/configure
Request Body
{
"endpoint_url": "https://new-domain.com/webhook", // Optional
"events": ["contact.position_changed"], // Optional
"is_active": false // Optional: Temporarily disable
}
Response
{
"id": "whc_8Zx6Li1Ko",
"endpoint_url": "https://new-domain.com/webhook",
"events": ["contact.position_changed"],
"is_active": false,
"updated_at": "2025-01-20T16:00:00Z"
}
Tip: To change your webhook secret, use the rotate secret endpoint instead.
Test Webhook
Send a test event to verify your webhook endpoint is working correctly.
/api/v1/webhooks/test
Response
{
"success": true,
"webhook_id": "whc_8Zx6Li1Ko",
"endpoint_url": "https://your-domain.com/webhook",
"response": {
"status": 200,
"headers": {
"content-type": "text/plain"
},
"body": "OK",
"duration_ms": 145
},
"signature_header": "X-Webhook-Signature",
"test_event": {
"id": "evt_test_2Xk9Lm3Np",
"type": "test",
"created": 1705835400,
"data": {
"message": "This is a test webhook from Sales Webhooks"
}
}
}
Error Response
{
"success": false,
"webhook_id": "whc_8Zx6Li1Ko",
"endpoint_url": "https://your-domain.com/webhook",
"error": {
"type": "connection_timeout",
"message": "Connection timeout after 10000ms",
"details": "Unable to connect to webhook endpoint"
}
}
Webhook Payload Format
All webhooks follow this standard format:
{
"id": "evt_2Xk9Lm3Np", // Unique event ID
"type": "contact.position_changed", // Event type
"created": 1705835400, // Unix timestamp
"data": {
"entity": {
"id": "sub_9Yx7Kj2Mn", // Subscription ID
"type": "contact",
"linkedin_id": "jane-smith",
"linkedin_url": "https://linkedin.com/in/jane-smith"
},
"changes": {
// Event-specific data
}
},
"metadata": {
"subscription_id": "sub_9Yx7Kj2Mn",
"sequence_number": 4567,
"polling_timestamp": "2025-01-20T12:00:00Z",
"retry_count": 0
}
}
Example Payloads
Job Change Event
{
"id": "evt_3Yk0Mn4Oq",
"type": "contact.position_changed",
"created": 1705835400,
"data": {
"entity": {
"id": "sub_9Yx7Kj2Mn",
"type": "contact",
"linkedin_id": "jane-smith",
"linkedin_url": "https://linkedin.com/in/jane-smith",
"name": "Jane Smith"
},
"changes": {
"previous_company": "Acme Corp",
"previous_title": "Sales Manager",
"current_company": "TechCo",
"current_title": "VP of Sales",
"is_promotion": false,
"change_date": "2025-01-15"
}
}
}
New Post Event
{
"id": "evt_4Zl1No5Pr",
"type": "contact.post_created",
"created": 1705839000,
"data": {
"entity": {
"id": "sub_9Yx7Kj2Mn",
"type": "contact",
"linkedin_id": "john-doe",
"name": "John Doe"
},
"post": {
"id": "post_123456",
"content": "Excited to announce our new product launch! #innovation #tech",
"url": "https://linkedin.com/posts/john-doe_innovation-tech-123456",
"published_at": "2025-01-20T15:30:00Z",
"engagement": {
"likes": 42,
"comments": 5,
"reposts": 2
},
"media_type": "text" // or "image", "video", "document"
}
}
}
Webhook Request Headers
Every webhook request includes these headers:
Header | Description |
---|---|
X-Webhook-Signature |
HMAC-SHA256 signature of the request body |
X-Webhook-ID |
Unique webhook delivery ID |
X-Webhook-Timestamp |
Unix timestamp (milliseconds) |
X-Event-Type |
Event type (e.g., "contact.position_changed") |
Content-Type |
Always "application/json" |
User-Agent |
SalesWebhooks/1.0 |
List Webhook Deliveries
View recent webhook delivery attempts for debugging and monitoring.
/api/v1/webhooks/deliveries
Query Parameters
Parameter | Type | Description |
---|---|---|
status |
string | Filter by: "pending", "success", "failed" |
event_type |
string | Filter by event type |
limit |
integer | Results per page (default: 20, max: 100) |
offset |
integer | Pagination offset |
Response
{
"data": [
{
"id": "del_5Am2Op6Qs",
"event_id": "evt_4Zl1No5Pr",
"event_type": "contact.post_created",
"status": "success",
"attempts": 1,
"endpoint_url": "https://your-domain.com/webhook",
"request": {
"headers": {
"X-Webhook-Signature": "abc123...",
"X-Event-Type": "contact.post_created"
},
"body_size": 1234
},
"response": {
"status": 200,
"duration_ms": 145,
"body": "OK"
},
"created_at": "2025-01-20T15:30:00Z",
"delivered_at": "2025-01-20T15:30:00Z"
}
],
"pagination": {
"total": 523,
"limit": 20,
"offset": 0
}
}
Rotate Webhook Secret
Generate a new webhook secret for enhanced security.
/api/v1/webhooks/rotate-secret
Response
{
"id": "whc_8Zx6Li1Ko",
"new_secret": "whsec_newSecretKey456", // Save this!
"old_secret_valid_until": "2025-01-21T10:30:00Z", // 24 hours
"rotated_at": "2025-01-20T10:30:00Z"
}
Grace Period: The old secret remains valid for 24 hours to allow you to update your systems without downtime.
Webhook Delivery & Retry Policy
Delivery Requirements
- Your endpoint must return a 2xx status code within 10 seconds
- Response body is ignored (can be empty)
- HTTPS is required (no HTTP endpoints)
- Valid SSL certificate required
Retry Schedule
Failed webhooks are retried with exponential backoff:
Attempt | Delay | Total Time |
---|---|---|
1 | Immediate | 0 seconds |
2 | 1 second | 1 second |
3 | 5 seconds | 6 seconds |
4 | 30 seconds | 36 seconds |
After 4 attempts, the webhook is marked as failed and won't be retried.
Webhook Best Practices
💡 Implementation Tips
- • Always verify signatures - See our security tutorial
- • Process asynchronously - Return 200 immediately, process in background
- • Handle duplicates - Use event ID for idempotency
- • Monitor failures - Check delivery logs regularly
- • Use specific event types - Don't subscribe to "*" unless needed
Next Steps
Ready to implement webhooks?
- Learn webhook security best practices
- Follow the quick start guide
- Use our SDKs for easier integration