Help center
Integrations

Send leads to Zapier and other tools with webhooks

Push every new lead into your CRM, spreadsheet, or Slack the moment it's captured — with a step-by-step Zapier setup.

Webhooks are how leads leave Perch. Whenever a page captures a new lead, Perch immediately POSTs it as signed JSON to every endpoint you’ve added. The payload is Zapier-compatible out of the box, which means any of the thousands of apps Zapier connects — HubSpot, Salesforce, Google Sheets, Slack, Mailchimp — can receive your leads within seconds of capture.

Set up with Zapier

  1. 1

    Create the Zap

    In Zapier, create a new Zap with the trigger Webhooks by Zapier → Catch Hook. Zapier gives you a hook URL like https://hooks.zapier.com/hooks/catch/… — copy it.

  2. 2

    Add the endpoint in Perch

    Go to Settings → Integrations, paste the hook URL, and optionally add a label (e.g. “HubSpot via Zapier”). By default the endpoint receives leads from all companies; pick a company in the scope dropdown if this Zap should only get one client’s leads.

  3. 3

    Store the signing secret

    Perch shows the endpoint’s signing secret (whsec_…) exactly once, right after you create it. Zapier doesn’t verify signatures, so you can dismiss it — but if you might ever point this endpoint at your own server, save it somewhere safe now. It can’t be shown again.

  4. 4

    Send a test event

    Use the endpoint’s Send test action in Perch, then click Test trigger in Zapier. Zapier pulls in a sample lead payload (marked "test": true) so you can see every field.

  5. 5

    Map fields and turn it on

    Add your action step (create a CRM contact, append a spreadsheet row, post to Slack…) and map fields from the sample — lead.name, lead.email, page.title, lead.utmCampaign, and so on. Turn the Zap on, and every new lead flows through automatically.

When webhooks fire

One event exists today: lead.created. It fires when a visitor submits the lead form on one of your published pages and that submission creates a genuinely new lead. Perch keeps one contact per email address per workspace, so a repeat submission from the same email updates the existing lead and does not fire a webhook — your CRM never gets duplicates. Delivery happens right after the visitor’s submission completes and never slows the page down.

Company-scoped endpoints only receive leads captured by that company’s pages. Manual status changes (e.g. marking a lead Qualified) don’t fire webhooks.

The payload

Every delivery is a POST with a JSON body shaped like this:

POST — application/json

{
  "id": "evt_9f2c81d4a7b3",
  "event": "lead.created",
  "version": 1,
  "createdAt": "2026-07-09T17:24:31.812Z",
  "company": { "id": "cmp_4k1…", "name": "Acme Roofing" },
  "page": {
    "id": "pag_8s3…",
    "slug": "acme-roofing-spring-x7k2q1",
    "title": "Spring Roofing Special"
  },
  "lead": {
    "id": "cnt_2m9…",
    "name": "Jamie Rivera",
    "email": "jamie@example.com",
    "phone": "+1 555 0100",
    "status": "NEW",
    "capturedAt": "2026-07-09T17:24:31.640Z",
    "utmSource": "google",
    "utmMedium": "cpc",
    "utmCampaign": "spring-roofing",
    "utmTerm": null,
    "utmContent": null,
    "referrer": "https://www.google.com/",
    "formData": { "message": "Need a quote for a roof replacement." }
  }
}

formData carries any custom form answers (like the message field) that aren’t part of the standard lead fields. Test deliveries include an extra "test": true flag so you can filter them out downstream.

Each request also carries these headers:

HeaderContents
X-Perch-EventThe event type, e.g. lead.created
X-Perch-DeliveryUnique delivery ID — use it to deduplicate if you ever receive a retry twice
X-Perch-TimestampUnix time (seconds) when the delivery was signed
X-Perch-SignatureHMAC signature of the payload (see below)
User-AgentPerch-Webhooks/1

Verifying signatures (your own server)

If you point an endpoint at your own server instead of Zapier, verify each request before trusting it. The signature is an HMAC-SHA256 of <timestamp>.<raw body> keyed with your endpoint’s whsec_… secret:

verify.js

import crypto from "node:crypto";

function verifyPerchSignature(rawBody, headers, secret) {
  const timestamp = headers["x-perch-timestamp"];
  const signature = headers["x-perch-signature"]; // "v1=<hex>"
  const expected =
    "v1=" +
    crypto
      .createHmac("sha256", secret)
      .update(`${timestamp}.${rawBody}`)
      .digest("hex");
  return (
    signature.length === expected.length &&
    crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expected))
  );
}

Zapier users can skip this

Zapier’s Catch Hook accepts deliveries without signature checks, which is why no verification step appears in the setup above. Verification matters when the receiving server is yours.

Delivery, retries, and failures

  • A failed delivery is retried a couple of times within seconds, then automatically retried for up to 24 hours.
  • After 20 consecutive failures an endpoint is auto-disabled so a dead URL doesn’t churn forever. Fix the receiver, then re-enable it from Settings → Integrations.
  • The Recent deliveries log on the same page shows each attempt with its HTTP status or error message.
  • Endpoint URLs must be public HTTPS addresses — local or private network hosts are rejected.

Troubleshooting

  • Zapier isn’t receiving anything: confirm the Zap is turned on, and check Recent deliveries in Perch — a “Delivered (HTTP 200)” row means the lead reached Zapier and the issue is in the Zap’s action step.
  • Endpoint shows “Auto-disabled”: the URL failed 20 times in a row. Verify the receiver is up, then click Enable — the failure counter resets.
  • A form submission didn’t fire: most often the email already existed as a lead in your workspace, so it was an update, not a new lead.

Still need a hand?

We read every message during the beta. Email hello@perchpages.com or browse the rest of the help center.