Pellio

Webhooks

Updated September 29, 2026
On this page

Add an endpoint in Settings → Developers → Webhooks (owners and admins). It must be a public HTTPS address. Choose which events it receives: leave All events on (this includes events added to Pellio later), or turn it off and pick the events you want. Pellio shows the endpoint’s signing secret once.

Each endpoint lists the events it receives, with these actions:

  • Edit events changes which events it receives. Save events applies the change straight away.
  • Send test sends a webhook.test event to that endpoint, whatever events it receives.
  • Deliveries shows the last 50 attempts (pending, delivered or failed) and their responses.
  • Rotate secret replaces the signing secret. The new one is shown once and the old one stops working immediately, so update your endpoint straight away.
  • Remove stops sending to the endpoint.

Through the API: POST /v1/webhooks takes url and events (an empty list means all events), PATCH /v1/webhooks/{id} changes events, and POST /v1/webhooks/{id}/rotate-secret returns a new secret.

Events

Every request body is { "id", "event", "createdAt", "data" }:

event When data
video.created A video is created by upload, recording or import from a URL. id, title
video.ready A video has processed, including after a replace or a trim. id, title, status, version, durationSeconds, width, height, errorMessage
video.failed A new video couldn’t be processed. as video.ready
video.deleted A video is moved to Trash (trashed: true) or deleted for good. id, title, trashed
video.watched An identified viewer (from an email form, an ?email= link or your WordPress site) starts a video, passes 25%, 50% or 75%, or finishes it (90% watched, across visits). Once per viewer, video and milestone. video (id, title), viewer (email, name), progress (0, 25, 50, 75, 100), milestone (started, 25%, 50%, 75%, completed), completed
lead.captured Someone submitted an email form. id, email, name, fields, video (id, title), createdAt

Delivery

Pellio sends a POST with the header User-Agent: Pellio-Webhooks/1 and waits up to 10 seconds. Any 2xx response counts as delivered. Redirects aren’t followed, so a 3xx counts as a failure. Failed deliveries are tried 6 times in total, waiting 20 seconds before the first retry and doubling up to 320 seconds.

Verifying signatures

Each request has a Pellio-Signature header: t=<unix time>,v1=<hex HMAC-SHA256 of "t.body">, using your endpoint’s secret. Verify it against the raw request body:

import { createHmac, timingSafeEqual } from 'node:crypto';

function verify(header, rawBody, secret) {
  const { t, v1 } = Object.fromEntries(header.split(',').map((p) => p.split('=')));
  if (Math.abs(Date.now() / 1000 - Number(t)) > 300) return false; // 5-minute tolerance
  const expected = createHmac('sha256', secret).update(`${t}.${rawBody}`).digest('hex');
  return timingSafeEqual(Buffer.from(expected), Buffer.from(v1));
}

Was this article helpful?

Still stuck?Send us a message and a person will get back to you.