Pulse Webhooks push platform events to HTTPS endpoints owned by the platform team and by firms: CRM syncs, marketing automation, monitoring. This page is the platform-side control center — every endpoint across every tenant, the delivery log with resend, and the scheduler switch that turns the delivery engine on.
💡 Tip — Who can use this Platform administrators, at Webhooks in the admin navigation (after Connect Keys). Firms manage their own endpoints from their portal's Settings; this page oversees everything.
Quick reference
| Step | Action |
|---|---|
| 1 | Open the Webhooks page |
| 2 | Enable the delivery scheduler |
| 3 | Create and manage endpoints |
| 4 | Read the delivery log and resend |
Step 1: Open the Webhooks page
In the admin portal sidebar, click Webhooks (directly after Connect Keys). The page has three zones: the Delivery Scheduler card, the Webhook Endpoints manager (platform endpoints), and the Recent Deliveries log with filters.

Step 2: Enable the delivery scheduler
Deliveries are processed by a background job that ticks every 30 seconds. On a fresh environment it starts Paused — click Enable on the Delivery Scheduler card and confirm it shows Active with the 30-seconds schedule. While paused, nothing is lost: events accumulate in the outbox and flow when re-enabled. A platform-wide kill switch (WEBHOOKS_ENABLED environment variable) can pause the entire webhook system without touching any endpoints — the page and nav also disappear while it is off.

⚠️ Warning — The scheduler bakes in the internal API key
The cron job calls the processor with the environment's internal key. Set the production INTERNAL_API_KEY before enabling the scheduler — if you rotate the key later, disable and re-enable the schedule so it picks up the new value.
Step 3: Create and manage endpoints
Create Endpoint opens the shared dialog: HTTPS URL, description, and event subscriptions grouped by domain (Lifecycle, Billing, Engagement, Messaging, Platform — messaging events are marked high-volume). Platform endpoints receive every subscribed event across all organizations; firm endpoints created in firm settings receive only their own clients' events. Each endpoint row shows its subscription count, status, consecutive failures, last delivery outcome, and actions: Edit, Reveal/Rotate Secret, Send Test, and enable/disable.

📝 Note — Auto-disable protects everyone An endpoint that fails 25 consecutive deliveries is disabled automatically and its owners are notified (platform admins, or the firm's admins for firm endpoints). Re-enabling resets its failure budget. Dead-lettered deliveries (rows that exhausted the retry ladder) stay in the log for inspection and one-click Resend.
Step 4: Read the delivery log and resend
Recent Deliveries lists every delivery attempt with filters by endpoint and status (pending / succeeded / failed / dead). Use Resend on a failed or dead row to requeue it with a fresh retry ladder — handy after a client fixes their receiving service. Deliveries are at-least-once; consumers deduplicate on the X-Pulse-Delivery header.
❗ Important — Consumers must verify signatures
Every delivery is signed: the X-Pulse-Signature header is t=<unix-seconds>,v1=<hex> where v1 = HMAC-SHA256(secret, "<t>.<rawBody>"), alongside X-Pulse-Event, X-Pulse-Delivery, and X-Pulse-Timestamp. Consumers should verify against the endpoint's secret and reject timestamps older than 5 minutes:
import { createHmac, timingSafeEqual } from 'node:crypto';
export function verifyPulseSignature(secret, header, rawBody, toleranceSec = 300) {
const m = /^t=(\d+),v1=([0-9a-f]+)$/.exec(header);
if (!m) return false;
const [, t, v1] = m;
if (Math.abs(Math.floor(Date.now() / 1000) - Number(t)) > toleranceSec) return false;
const expected = createHmac('sha256', secret).update(`${t}.${rawBody}`).digest('hex');
return expected.length === v1.length && timingSafeEqual(Buffer.from(expected), Buffer.from(v1));
}