pageo
  • Pricing
  • Profiles
Sign inStart free
pageo

Your links, your work, and every message, on one page.

Product

  • Features
  • Pricing
  • Templates
  • Examples
  • Top profiles
  • Integrations
  • Free tools
Compare
  • Linktree
  • bio.fm
  • Beacons
  • Campsite.bio
  • Taplink
  • Lnk.Bio
  • Alternatives

Resources

  • Docs
  • Changelog
  • Blog
  • Glossary
  • Link in bio guides
  • Who it's for

Company

  • About
  • Contact
  • Follow onX

© 2026 pageo

  • Terms
  • Privacy
  • Content policy
PAGEO
PAGEO

Docs

  • Overview
  • Get started
  • GitHub sync and pageo.json
  • Custom domains
  • Forms and inbox
  • Switch to pageo
  • Players and embeds
  • Webhooks
  • Email tools
  • Work with me

Webhooks

Send new subscribers and form messages from your pageo page to Zapier, Make, n8n, or your own server. Events, payloads, and signature checks.

A webhook sends each new subscriber and each form message to an address you choose, a few seconds after it happens. Use it to put subscribers into your newsletter tool, form messages into a spreadsheet or a CRM, or anything else that takes a web request. Webhooks are part of pageo Pro.

Add a webhook

  1. In your pageo admin, open Settings.
  2. Under Webhook, paste your endpoint URL and click Add webhook. The address must start with https://.
  3. Click Send test event. Your endpoint gets a ping event, and the result shows under Recent deliveries.

With Zapier, Make, or n8n, start a new automation with their "Catch hook" or "Webhook" trigger and paste the URL it gives you.

Events

EventSent when
subscriber.createdA visitor confirms their subscription to your updates
form.submittedA visitor sends your contact form or a custom form
pingYou click Send test event

The request

pageo sends a POST with a JSON body and these headers:

HeaderValue
Content-Typeapplication/json
X-Pageo-EventThe event name, for example form.submitted
X-Pageo-DeliveryThe event id, the same as id in the body. Use it to skip an event you already handled
X-Pageo-Signaturet=<unix seconds>,v1=<hex signature>. See Check the signature

Every body has the same envelope:

{
  "id": "evt_6f1c2b9e-3a4d-4c1e-9b7a-2f0d8e5c1a34",
  "type": "subscriber.created",
  "created_at": "2026-10-17T09:30:00.000Z",
  "data": {}
}

subscriber.created

{
  "email": "sam@example.com",
  "name": "Sam",
  "subscribed_at": "2026-10-17T09:30:00.000Z",
  "page": { "username": "yourname", "url": "https://www.pageo.me/yourname" }
}

name is null when the subscriber did not give one.

form.submitted

{
  "submission_id": "3c9a0e1f-7b2d-4f6a-8e5c-1d0b9a7f2e64",
  "form": { "id": "8b2f4c1e-6d3a-4e9b-a7c5-0f1e2d3c4b5a", "title": "Contact" },
  "name": "Sam",
  "email": "sam@example.com",
  "fields": [
    { "label": "Message", "value": "Are you free for a shoot next month?" }
  ],
  "submitted_at": "2026-10-17T09:30:00.000Z",
  "source": null,
  "service": null,
  "page": { "username": "yourname", "url": "https://www.pageo.me/yourname" }
}

fields holds every field the visitor filled in, in the order of the form. A request from your work page has source set to "work" and service set to the service the visitor picked, or null when they picked none.

Check the signature

Each webhook has a signing secret that starts with whsec_. Copy it from Settings, then Webhook. Check the signature before you trust a request, so that only pageo can send events to your endpoint.

The signature is an HMAC-SHA256 of <t>.<raw body>, keyed with your secret, written as hex. Use the raw body exactly as it arrived, before you parse the JSON.

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

export function verifyPageoSignature(secret, header, rawBody) {
  const parts = Object.fromEntries(header.split(",").map((part) => part.split("=")));
  const timestamp = Number(parts.t);
  // reject requests older than five minutes, so an old request cannot be sent again
  if (!timestamp || Math.abs(Date.now() / 1000 - timestamp) > 300) return false;
  const expected = createHmac("sha256", secret).update(`${timestamp}.${rawBody}`).digest("hex");
  const received = Buffer.from(parts.v1 ?? "", "hex");
  return received.length === 32 && timingSafeEqual(received, Buffer.from(expected, "hex"));
}

When you replace the secret in Settings, the old one stops working at once. Update your endpoint with the new secret.

Retries and timeouts

  • Answer with any 2xx status to mark the event as delivered. pageo does not read the response body.
  • pageo waits up to 5 seconds for an answer.
  • When the request fails, times out, or gets a 429 or a 5xx, pageo tries again after 1 second and again after 4 more seconds. A 4xx other than 429 is not retried.
  • pageo does not follow redirects. Use the final address of your endpoint.
  • Events can arrive more than once, and not always in order. Use X-Pageo-Delivery to skip duplicates.

Recent deliveries in Settings shows the last 20 deliveries from the past 7 days, with the status code or the error. pageo does not keep a copy of the payloads.

Turn off a webhook

In Settings, under Webhook, click Remove. If your Pro plan ends, pageo stops sending events until you upgrade again. Your URL and secret stay saved.