Webhooks

Webivio can send webinar events to any URL (JSON) - Make, Zapier, Pabbly, n8n, or your own system.

This is the outbound direction (Webivio -> your endpoint). The reverse direction (your system registers a participant in Webivio) is described in Registration API.

Mailing and CRM in the webinar creator are a separate path - account webhooks do not replace them.

How to set it up

  1. Settings menu -> Integrations.
  2. Webhooks tab.
  3. Add a destination URL and select events.
  4. Optionally scope the endpoint to one webinar (or leave "all webinars on the account").
  5. Save the HMAC secret - shown on create; you can rotate it later in the panel.
  6. Test with webhook.site or a Zapier Catch Hook.

Live URL, secret, and delivery logs: /auth/settings/integrations (Webhooks tab).

Partner example: Webivio × beTiMES integration — webhooks for countdown timers and automations in beTiMES.

Request format (envelope)

Every POST body is JSON:

{
  "id": "event-uuid",
  "type": "webinar.registration.created",
  "created_at": "2026-07-24T12:00:00.000Z",
  "user_id": "account-owner-uuid",
  "webinar_id": "webinar-uuid",
  "data": {}
}
FieldDescription
idEvent id (delivery deduplication)
typeEvent type (see table below)
created_atEvent time (ISO UTC)
user_idWebivio account owner id
webinar_idWebinar id
dataType-specific fields

HTTP headers and HMAC signature

HeaderValue
Content-Typeapplication/json
User-AgentWebivio-Webhooks/1.0
X-Webivio-EventSame string as body type
X-Webivio-TimestampUnix time (seconds) as string
X-Webivio-Signaturev1= + HMAC-SHA256 hex

Signature: HMAC-SHA256 with the endpoint secret over:

{timestamp}.{rawBody}

where rawBody is the exact JSON body bytes sent.

Response timeout: 8 seconds. Success: HTTP 2xx.

Retries

On network errors or 5xx / timeout responses, Webivio queues the delivery and retries (max 4 attempts). Backoff in minutes: 1 -> 5 -> 15 -> 60.

401, 403, 404, 410 fail that delivery immediately. After three consecutive 401 or 410 responses the endpoint is disabled (fix the URL/auth and re-enable it in the panel). One-off 403/404 (e.g. WAF) do not disable the whole endpoint.

Status and history: in the panel for that endpoint.

Event list

typeWhenIn UI (selectable)
webinar.registration.createdNew registration (form, widget, registration API, series)Yes
webinar.attendance.joinedParticipant joined the roomYes
webinar.attendance.leftParticipant left the room before the webinar ended (not on natural end or presence heartbeat)Yes
webinar.attendance.not_attendedMarked as not attendedYes
webinar.offer.clickedOffer click in the roomYes
webinar.watch.milestone_25 / _50 / _75 / _100Watch % thresholdYes
webinar.watch.custom_minuteWatch minute reached (when subscribed)Yes
webinar.replay.watchedFirst replay openYes
webinar.purchase.completedPurchase recorded (pixel / post-sale webhook)Yes
webinar.email.unsubscribedUnsubscribed from webinar emails (email link or participants table)Yes
webinar.chat.messageNew participant chat message in the room (requires Chat AI API grant)Yes (when enabled)

data fields - registration

{
  "participant_id": "…",
  "email": "jane@example.com",
  "name": "Jane",
  "surname": "Doe",
  "phone": "+48123456789",
  "access_code": "a1b2c3d4",
  "registered_at": "2026-07-24T12:00:00.000Z",
  "registered_at_local_time": "…",
  "registration_time_zone": "Europe/Warsaw",
  "utm_source": "…",
  "utm_medium": "…",
  "utm_campaign": "…",
  "utm_term": null,
  "utm_content": null,
  "referrer": null,
  "assigned_variant": "A",
  "custom_fields": {
    "who_are_you": "Entrepreneur",
    "team_size": "1-3"
  }
}

custom_fields is an object of answers from custom registration form fields (key = field key from the creator). Empty object {} when there are no custom fields or answers.

For series registrations, fields such as series_id and series_registration_id may be included.

data fields - attendance and offer

  • joined: participant_id, email, name, surname, access_code, joined_at, variant
  • left: participant_id, email, name, surname, access_code, joined_at, left_at, variant
  • not_attended: participant_id, email, access_code, detected_at, variant
  • offer.clicked: participant_id, email, access_code, offer_id, offer_url, clicked_at, variant

data fields - watch / replay / purchase

  • milestone_*: participant_id, email, access_code, milestone_percent, previous_percent, current_percent, current_minute, duration_minutes, occurred_at, variant
  • custom_minute: participant_id, email, access_code, minute, current_percent, duration_minutes, occurred_at, variant
  • replay.watched: participant_id, email, access_code, watched_at
  • purchase.completed: participant_id, email, access_code, order_id, amount, currency, buyer_email, source, attribution, raw_payload
  • email.unsubscribed: participant_id, email, name, surname, phone, access_code, unsubscribed_at
  • chat.message: message_id, text, inbox_kind, participant_id, email, name, surname, access_code, instance_id, display_time, is_moderator_message

Moderator / external AI replies do not emit webinar.chat.message (avoids loops). To reply from your system: Chat reply API.

In Make/Zapier/GetResponse map data.email to unsubscribe the contact from extra lists (separate from the list added at registration).

Zapier (Webivio -> Zapier)

  1. In Zapier create a Zap -> trigger Webhooks by Zapier -> Catch Hook.
  2. Copy the Catch Hook URL.
  3. In Webivio: Settings -> Integrations -> Webhooks -> add that URL and select events (e.g. webinar.registration.created).
  4. Trigger a test (register a test participant) or wait for a real event.
  5. In later Zap steps map data.email, data.name, type, webinar_id.

HMAC verification in Zapier: optional Code step computing HMAC-SHA256 over X-Webivio-Timestamp + raw body vs X-Webivio-Signature.

Make / n8n

  • Make: Custom webhook module -> paste URL into Webivio -> map data.*.
  • n8n: Webhook node (POST) -> use body.data.email etc. in the workflow.

Example flow

Typical funnel: registration in Webivio -> outbound webinar.registration.created -> Zapier adds a contact to MailerLite / ActiveCampaign / Google Sheets.
Or: offer click -> webinar.offer.clicked -> CRM tag "clicked offer".
Or: early leave -> webinar.attendance.left -> Make/Zapier notifies CRM that the participant left the webinar.

Related: post-sale webhook (inbound)

To report a purchase from an external checkout into Webivio, use the inbound post-sale URL (separate token in the creator Finish step) - POST /api/public/post-sale-webhook?webinarId=&token=.

Full guide (WebToLearn, JSON fields, website scripts): Sales tracking (conversion pixel). On success Webivio may emit outbound webinar.purchase.completed.

See also

Future ideas (non-production)

The following is not available in the product - only directions we are considering:

  • HMAC verification snippets in docs
  • OpenAPI / Postman collection

More ideas (account API key, GET participants): internal product roadmap.

Verifying the signature in Node.js

Verify the signature against the raw body before calling JSON.parse:

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

export function verifyWebivio(rawBody, timestamp, header, secret) {
  const expected = `v1=${createHmac("sha256", secret)
    .update(`${timestamp}.${rawBody}`)
    .digest("hex")}`;
  const a = Buffer.from(expected);
  const b = Buffer.from(header || "");
  return a.length === b.length && timingSafeEqual(a, b);
}

Pass the X-Webivio-Timestamp and X-Webivio-Signature header values. In production, also reject timestamps that are too old to reduce replay risk.