Webhooks
Receive real-time events in your own systems — with Zapier, Make, and signature verification.
Receive real-time events in your own systems when something happens in vitelnk — a lead captured, a video watched, a CTA clicked. Webhooks are available on paid plans.
Every event is delivered as an HTTP POST with a JSON body in this shape:
{
"event": "<event.name>",
"timestamp": "<ISO 8601>",
"data": { ... }
}{
"event": "lead.captured",
"timestamp": "2026-05-03T10:00:00.000Z",
"data": {
"video_id": "my-demo-video",
"video_title": "Product Demo",
"share_token": "abc123xyz",
"share_name": "Prospect Link — Acme",
"email": "[email protected]"
}
}{
"event": "video.watched",
"timestamp": "2026-05-03T10:02:30.000Z",
"data": {
"video_id": "my-demo-video",
"video_title": "Product Demo",
"share_token": "abc123xyz",
"share_name": "Prospect Link — Acme",
"watch_percent": 100,
"threshold_percent": 70
}
}{
"event": "cta.clicked",
"timestamp": "2026-05-03T10:03:10.000Z",
"data": {
"video_id": "my-demo-video",
"video_title": "Product Demo",
"share_token": "abc123xyz",
"share_name": "Prospect Link — Acme"
}
}{
"event": "cta_link.clicked",
"timestamp": "2026-05-03T10:03:20.000Z",
"data": {
"video_id": "my-demo-video",
"video_title": "Product Demo",
"share_token": "abc123xyz",
"share_name": "Prospect Link — Acme"
}
}{
"event": "calendar.clicked",
"timestamp": "2026-05-03T10:04:00.000Z",
"data": {
"video_id": "my-demo-video",
"video_title": "Product Demo",
"share_token": "abc123xyz",
"share_name": "Prospect Link — Acme"
}
}{
"event": "booking.completed",
"timestamp": "2026-05-03T10:05:30.000Z",
"data": {
"video_id": "my-demo-video",
"video_title": "Product Demo",
"share_token": "abc123xyz",
"share_name": "Prospect Link — Acme"
}
}{
"event": "video.downloaded",
"timestamp": "2026-05-03T10:06:00.000Z",
"data": {
"video_id": "my-demo-video",
"video_title": "Product Demo",
"share_token": "abc123xyz",
"share_name": "Prospect Link, Acme",
"file": "original"
}
}{
"event": "message.received",
"timestamp": "2026-05-03T10:07:00.000Z",
"data": {
"video_id": "my-demo-video",
"video_title": "Product Demo",
"share_token": "abc123xyz",
"share_name": "Prospect Link — Acme",
"message": "Loved this, can we hop on a call?"
}
}{
"event": "feedback.received",
"timestamp": "2026-05-03T10:07:30.000Z",
"data": {
"video_id": "my-demo-video",
"video_title": "Product Demo",
"share_token": "abc123xyz",
"share_name": "Prospect Link — Acme"
}
}{
"event": "share.viewed",
"timestamp": "2026-05-03T10:00:00.000Z",
"data": {
"video_id": "my-demo-video",
"video_title": "Product Demo",
"share_token": "abc123xyz",
"share_name": "Prospect Link — Acme"
}
}{
"event": "upload_request.started",
"timestamp": "2026-10-06T14:02:00.000Z",
"data": {
"upload_request_id": 42,
"upload_request_title": "Wedding clips: Hannah & Luis",
"uploader_name": "Jane Guest",
"uploader_email": "[email protected]"
}
}{
"event": "upload_request.completed",
"timestamp": "2026-10-06T14:20:00.000Z",
"data": {
"upload_request_id": 42,
"upload_request_title": "Wedding clips: Hannah & Luis",
"uploader_name": "Jane Guest",
"uploader_email": "[email protected]",
"videos_count": 2,
"files_count": 0,
"awaiting_review_count": 2,
"total_bytes": 1874919424,
"incomplete_count": 0,
"items": [
{ "type": "video", "id": "img-4021", "title": "IMG_4021", "status": "awaiting_approval" },
{ "type": "video", "id": "img-4022", "title": "IMG_4022", "status": "awaiting_approval" }
]
}
}When you set a secret on an endpoint, every delivery includes an X-vitelnk-Signature header. The value is sha256=<hex> where the hex is HMAC-SHA256 of the raw request body signed with your secret. Always verify this before processing an event.
const crypto = require('crypto');
function verifySignature(rawBody, signature, secret) {
const expected = 'sha256=' + crypto
.createHmac('sha256', secret)
.update(rawBody)
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(expected),
Buffer.from(signature)
);
}
// Express example
app.post('/webhook', express.raw({ type: 'application/json' }), (req, res) => {
const sig = req.headers['x-vitelnk-signature'];
if (!verifySignature(req.body, sig, process.env.WEBHOOK_SECRET)) {
return res.status(401).send('Invalid signature');
}
const event = JSON.parse(req.body);
console.log('Event:', event.event, event.data);
res.sendStatus(200);
});If your endpoint returns a non-2xx status or times out, vitelnk retries automatically with exponential backoff.
| Setting | What it does |
|---|---|
| 1st retry | 10 seconds |
| 2nd retry | 30 seconds |
| 3rd retry | 60 seconds |
| 4th retry | 5 minutes |
| 5th retry (final) | 10 minutes |
After 5 failed attempts the delivery is marked failed and no further retries occur. The delivery log in Settings shows the status, HTTP code, and attempt count for every delivery. Each endpoint is limited to 100 deliveries per hour to prevent runaway loops.
