pagefluxer.
DEVELOPER GUIDE · PRO

Put page changes to work.

Receive matching changes at your own HTTPS endpoint, with a signature you can verify and an event ID you can safely process once.

Connect your endpoint

  1. Deploy a receiver at a public HTTPS URL, such as https://your-app.example/pagefluxer. Use a valid TLS certificate and the default HTTPS port.
  2. Open Notification settings, save your endpoint, and enable webhook delivery. Pro includes one account-level endpoint.
  3. Copy the signing secret to your receiving server’s secret configuration. Use the signing secret shown in your PageFluxer Notification settings for this endpoint.
  4. Open each monitor that should send events and enable its webhook notification option.

Webhooks deliver each matching change independently of email batching and quiet hours. The initial baseline does not send an event. Use the Pro API to manage monitors and retrieve changes from your own tools.

Monitors with price, stock, text or listing rules send an event only when a rule matches. Other captured changes remain in history. Selection & rule guide →

The event you receive

Requests use POST with Content-Type: application/json. This example is illustrative.

{
  "api_version": "2026-09-30",
  "type": "monitor.changed",
  "id": "11111111-1111-4111-8111-111111111111",
  "delivery_id": "22222222-2222-4222-8222-222222222222",
  "occurred_at": "2026-10-02T04:00:00.000Z",
  "monitor": {
    "id": "33333333-3333-4333-8333-333333333333",
    "name": "Competitor pricing",
    "url": "https://example.com/pricing"
  },
  "change": {
    "before_excerpt": "Basic costs $10",
    "after_excerpt": "Basic costs $12",
    "excerpts_may_include_unchanged_text": true,
    "url": "https://pagefluxer.com/dashboard/monitors/33333333-3333-4333-8333-333333333333?change=11111111-1111-4111-8111-111111111111"
  }
}

Both excerpts are limited to 500 characters. They may contain unchanged text or omit the changed section; they are not a complete diff. The history URL requires your normal PageFluxer sign-in.

id identifies the change. delivery_id identifies its delivery. Retries keep both IDs and the body unchanged. Ignore unknown additional fields for forward compatibility.

Verify before processing

PageFluxer-Delivery-Id: delivery-uuid
PageFluxer-Signature: t=unix_seconds,v1=hex_hmac_sha256

Calculate HMAC-SHA256 over the timestamp, a literal period, and the exact raw request bytes. Use the signing secret as its literal UTF-8 string, including its prefix. Capture the raw body before JSON middleware; parsing and re-serializing it changes the signature.

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

function verify(rawBody, header, secret) {
  if (!secret || typeof header !== "string") return false;
  const match = /^t=(\d+),v1=([a-f0-9]{64})$/.exec(header);
  if (!match) return false;
  const timestamp = Number(match[1]);
  if (!Number.isSafeInteger(timestamp) ||
      Math.abs(Math.floor(Date.now() / 1000) - timestamp) > 300) return false;
  const expected = createHmac("sha256", secret)
    .update(match[1] + ".").update(rawBody).digest();
  const received = Buffer.from(match[2], "hex");
  return received.length === expected.length &&
    timingSafeEqual(received, expected);
}

Keep the receiving server’s clock synchronized. After verification, validate the event structure and store it durably with a unique constraint on id before returning 2xx. Process work asynchronously and make downstream effects idempotent. Events can arrive out of order.

Download the Node.js + PostgreSQL receiver example. It verifies signatures and stores events with deduplication; connect your own background processor to the stored rows. Set PAGEFLUXER_WEBHOOK_SECRET and WEBHOOK_DATABASE_URL on that receiver, install pg, then run the file with Node 22 or newer. Use a separate receiver database and expose the service through your host’s HTTPS endpoint.

Delivery, retries, and rotation

A 2xx response means your endpoint accepted the event. All other statuses, redirects, and timeouts are failures. Redirects are not followed. Requests have a 12-second HTTP timeout and a bounded DNS lookup; acknowledge promptly after durable storage.

Automatic retries wait approximately 5, 10, 20, 40, 80, 160, then 320 minutes between eligible attempts. The worker stops after 10 attempts or when the 23-hour retry window has expired. Cron timing and backlog can add delay. Each retry has a fresh signature timestamp.

Recent delivery results are available in Notification settings for seven days. A failed webhook can be retried there while its 23-hour window, endpoint version, and Pro access remain valid. Delivery is not guaranteed after the retry window expires.

Rotating a signing secret, changing an endpoint, or toggling that endpoint cancels waiting deliveries for the previous configuration. Update your receiver when you rotate. Already in-flight requests may finish. Keep signing secrets off frontend code and out of logs.

Test your integration

  1. Configure a receiver you control with the signing secret from your PageFluxer Notification settings.
  2. Enable webhook notifications on a monitor for a page you control.
  3. Confirm a baseline in the setup preview (or wait for a legacy monitor’s first check), then change the page so that its alert rule matches.
  4. Wait for PageFluxer to check the page and deliver the notification. Confirm the event and signature on your receiver.
  5. Temporarily return 503, then restore 204. Verify a retry uses the same event and delivery IDs and creates only one stored event.

If delivery fails, check the endpoint’s certificate, public DNS, response status, and raw-body verification. Private network destinations, custom ports, and redirects are rejected. Do not assume a fixed sender IP. A Slack or Teams incoming webhook needs an adapter to translate this payload.

Get help →

Monthly delivery allowance

Pro includes 10,000 outbound attempts per calendar month, including failures and retries. At the limit, deliveries are marked failed in Notifications; they do not automatically replay next month. A manual retry still needs allowance and must be inside the normal retry window. View usage →