Webhooks
Webhooks are available starting from the Starter plan.
Last updated
Was this helpful?
Was this helpful?
const crypto = require('crypto');
app.post('/webhook', (req, res) => {
const signature = req.headers['x-storylane-signature'];
const secret = process.env.STORYLANE_WEBHOOK_SECRET;
// 'req.rawBody' should be the unparsed string of the request body
const hmac = crypto.createHmac('sha256', secret);
const digest = hmac.update(req.rawBody).digest('base64');
if (signature === digest) {
// Valid signature
console.log('Webhook verified');
res.status(200).send('Verified');
} else {
// Invalid signature
res.status(401).send('Unauthorized');
}
});require 'openssl'
require 'base64'
def verify_signature(payload, secret, received_signature)
hmac = OpenSSL::HMAC.digest(
'sha256',
secret.to_s,
payload
)
expected_signature = Base64.strict_encode64(hmac)
# Use secure comparison to prevent timing attacks
Rack::Utils.secure_compare(expected_signature, received_signature)
endimport hmac
import hashlib
import base64
from flask import request
@app.route('/webhook', methods=['POST'])
def handle_webhook():
secret = "your_verification_secret"
received_signature = request.headers.get('x-storylane-signature')
# Get raw data
payload = request.get_data()
# Create hash
digest = hmac.new(
secret.encode('utf-8'),
payload,
hashlib.sha256
).digest()
expected_signature = base64.b64encode(digest).decode()
if hmac.compare_digest(expected_signature, received_signature):
return "OK", 200
else:
return "Unauthorized", 401{
"id": "a61a8af4-8a33-4b4d-9861-d8542bcb4d36",
"analytics_url": "https://app.storylane.io/audience/sessions/a61a8af4-8a33-4b4d-9861-d8542bcb4d36",
"buyer_reveal": {
"company_name": "Acme Inc",
"company_domain": "example.com",
"company_annual_revenue_range": "$1B-$10B",
"company_employee_range": "1K-5K",
"confidence_score": "low"
},
"checklist_completed": false,
"completion": 100,
"cta_opened": null,
"host_url": "https://app.storylane.io/share/lcmplr8qd0rj",
"intent_level": "high",
"lead": {
"id": "dcc7997a-c811-4778-a065-cc009ad6b46e",
"client_source": "none",
"client_tracking_id": null,
"email": "webhooktest@test.com",
"first_name": "",
"last_name": "",
"lead_source": "Nurtured"
},
"link": "https://app.storylane.io/share/lcmplr8qd0rj",
"link_name": "Default",
"location": {
"city": "Pune",
"country": "India",
"state": "MH"
},
"name": "test for Pardot",
"referers": [
"https://app.storylane.io/share/lcmplr8qd0rj?email=webhooktest@test.com"
],
"time_spent": 10,
"utm_params": {},
"viewed_at": "2026-05-20T03:27:29.246-07:00",
"event": "demo_viewed"
}{
"id": "b88dce43-555e-454c-82e2-0b5c092a85c0",
"analytics_url": "https://app.storylane.io/audience/sessions/b88dce43-555e-454c-82e2-0b5c092a85c0",
"buyer_reveal": {
"company_name": "Acme Inc",
"company_domain": "example.com",
"company_annual_revenue_range": "$1B-$10B",
"company_employee_range": "1K-5K",
"confidence_score": "low"
},
"checklist_completed": false,
"completion": 100,
"cta_opened": null,
"host_url": "https://app.storylane.io/share/i9k15ivebdkv",
"intent_level": "high",
"lead": null,
"link": "https://app.storylane.io/share/i9k15ivebdkv",
"link_name": "Default",
"location": {
"city": "Pune",
"country": "India",
"state": "MH"
},
"name": "Test 2 for Marketo",
"referers": [
"https://app.storylane.io/share/i9k15ivebdkv",
"https://app.storylane.io/projects"
],
"time_spent": 3,
"utm_params": {},
"viewed_at": "2026-05-20T03:21:32.937-07:00",
"event": "demo_viewed"
}