EasyAgentIDX

Webhooks

Webhooks send real-time EasyAgentIDX activity to your server. They are available on Pro and higher plans and use encrypted signing secrets, public HTTPS destinations, and automatic retry delivery.

Create an endpoint

  1. Open Developer in the customer dashboard.
  2. Select Webhooks and then Add Webhook.
  3. Enter a public HTTPS endpoint and choose the events to receive.
  4. Copy the signing secret immediately. It is shown only once.

Warning

Store the signing secret in a server environment variable. Never place it in browser code, a mobile bundle, version control, logs, or an AI prompt.

Events

EventSent when
lead.createdA widget, registration flow, or Developer API request creates a lead
lead.updatedA dashboard user or Developer API request updates a lead
valuation.createdA homeowner or Developer API request completes a home valuation
visitor.registeredA visitor creates an account through an approved widget
search.savedAn authenticated visitor saves a search
widget.createdThe public API creates a widget
widget.updatedThe public API changes a widget
widget.deletedThe public API removes a widget

Widget events contain id and the issuing key's public site_id. They do not contain configuration, lead rules, or secrets. These events are queued in the widget transaction and delivered by the webhook worker. Normal first delivery is within the next scheduled worker run. Retried widget requests do not enqueue the event again.

New widget events include schema_version: "1", a stable event_id, and the original occurred_at timestamp. The event ID is shared across subscribed destinations. Each destination has its own stable delivery ID. These identifiers and the occurrence time stay unchanged across retries. The signed delivery timestamp is refreshed on each attempt. Existing lead and valuation event envelopes are unchanged.

Request headers

HeaderPurpose
X-EasyAgentIDX-Signaturesha256= followed by the HMAC digest
X-EasyAgentIDX-TimestampISO timestamp included in the signed message
X-EasyAgentIDX-DeliveryStable delivery ID used across retries
X-EasyAgentIDX-EventEvent name

Payload

{
  "deliveryId": "b6e7b3df-53ba-4bbc-a657-8a0eb8b7fa54",
  "event": "lead.created",
  "timestamp": "2026-08-25T18:30:00.000Z",
  "data": {
    "id": "cm...",
    "name": "Jane Smith",
    "email": "jane@example.com"
  }
}

Verify every request

Reject stale timestamps, calculate the HMAC over timestamp.rawBody, and compare the complete sha256= value with a timing-safe function. Parse JSON only after verification.

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

export function verifyEasyAgentIDXWebhook(
  rawBody: string,
  signature: string,
  timestamp: string,
  secret: string
) {
  const age = Math.abs(Date.now() - Date.parse(timestamp));
  if (!Number.isFinite(age) || age > 5 * 60 * 1000) return false;

  const expected = "sha256=" + createHmac("sha256", secret)
    .update(timestamp + "." + rawBody)
    .digest("hex");

  const receivedBytes = Buffer.from(signature);
  const expectedBytes = Buffer.from(expected);
  return receivedBytes.length === expectedBytes.length &&
    timingSafeEqual(receivedBytes, expectedBytes);
}

Retries and idempotency

Return a 2xx response within 10 seconds. Failed deliveries are retried three times after approximately 1 minute, 5 minutes, and 15 minutes. Store processed X-EasyAgentIDX-Delivery values so a retry cannot create duplicate work.

Destination security

Endpoints must use HTTPS on port 443. Localhost, private networks, cloud metadata addresses, URL credentials, oversized responses, and redirects are rejected. DNS is resolved and pinned to the validated public address for each delivery attempt.