Menu · Webhooks
Webhooks

Webhooks: event catalog

Every lead event kind, the event envelope, the objects inside it, and example payloads.

View as Markdown

Events are sent for known leads only, from the time your brokerage was enabled. Email open and click events cover emails sent in the previous three days; later opens still count in the statistics. Anonymous visitors produce no events; their views show up in listing totals.

Kind Fires when data
lead.created A new lead appears: a registration or a contact synced from your CRM lead, leadType, createdBy
lead.property_view A lead opens a listing page (once per lead, listing and day, with viewsToday) lead, property, viewsToday
lead.favorite A lead saves a listing lead, property
lead.saved_search_created A saved search is created for the lead, by the lead or an agent lead, savedSearch, createdBy
lead.saved_search_updated A lead's saved search changes lead, savedSearch, updatedBy
lead.search A lead runs a listings or rentals search lead, search.type
lead.email_open First human open of a Ruuster email lead, email
lead.email_click First human click in a Ruuster email lead, email
lead.tour_request A lead requests a tour lead, property, tourDate, partOfDay
lead.contact_agent A lead sends the contact-agent form lead, property (if sent from a listing), agentId
lead.login A lead signs in lead, platform (web, ios, android when known)
lead.share A lead shares a listing lead, property, channel
lead.email_status_changed Ruuster's verdict on the lead's email address changes: a check or a send fails, the lead unsubscribes, delivery is turned back on, or a new lead's address gets its first verdict lead, emailStatus
webhook.test You call the test endpoint message, subscriptionId

Subscribe to kinds one by one, or to lead.* for all of them, including kinds added later. lead.search and lead.property_view are high volume.

Envelope

Field Description
id Event id, evt_…. De-duplicate on this
kind One of the kinds above
occurredAt When it happened in Ruuster
brokerageId Whose event it is
apiVersion v1
data Kind-specific, see above
links API URLs for the lead and listing involved

Objects inside data

Object Fields
lead leadId, firstName, lastName, crmExternalId, agentId; email and phone when lead contact details are on
property propertyId, mlsRecordId, mlsName, address, ownedByYou, for any listing a lead engaged with, yours (ownedByYou: true) or another brokerage's (false). links.property points at the listing's engagement for yours and at Get a listing otherwise. A listing that has since left the feed carries propertyId and ownedByYou only
savedSearch savedSearchId, name
email emailId, subject, savedSearchName, sentAt
createdBy, updatedBy { "type": "lead" | "agent", "id": … }
emailStatus status (valid, invalid, blocked, soft_bounce, complaint, unsubscribed, unknown), code, reason, source, failedAt, since, previousStatus. See the Email status guide for what each status means

Example deliveries

Every delivery is a POST with these headers, then one of the bodies below:

POST /ruuster HTTP/1.1
Host: hooks.saguarorealty.com
Content-Type: application/json
User-Agent: Ruuster-Webhooks/1.0
Ruuster-Event-Id: evt_9a17f2c4b8e05d31
Ruuster-Event-Kind: lead.tour_request
Ruuster-Delivery-Id: dlv_4d7b2e90c1
Ruuster-Signature: t=1790869330,v1=6b0f3c2e8a91d4f7b5c0e2a9d8f61b3c7e4a2d0f9b8c6e1a3d5f7b9c2e4a6d8f

Common envelope (shown in full once; the examples after it show only kind, occurredAt and data):

{
  "id": "evt_9a17f2c4b8e05d31",
  "kind": "lead.tour_request",
  "occurredAt": "2026-09-30T02:19:03Z",
  "brokerageId": "4f6c2a9e-8d31-4b57-9a0e-2c7d5e1b8f43",
  "apiVersion": "v1",
  "data": {
    "lead": { "leadId": "user:c0ff3e21-8a4b-4c7d-9e15-2b6f8d3a1c04", "firstName": "Sam", "lastName": "Lee",
              "email": "sam.lee@example.com", "phone": "+15205550142", "crmExternalId": "48213",
              "agentId": "7c1e9b42-3d85-4a6f-9e07-1b2c8d4f5a69" },
    "property": { "propertyId": "5b7e2d94-1c63-4a8f-b5e0-9d3c7a2f1e86", "mlsRecordId": "22418765",
                  "address": "4182 E Saguaro Bloom Dr, Tucson, AZ 85718", "ownedByYou": true },
    "tourDate": "2026-10-04",
    "partOfDay": "morning"
  },
  "links": {
    "lead": "https://api.ruuster.com/v1/leads/user:c0ff3e21-8a4b-4c7d-9e15-2b6f8d3a1c04/activity",
    "property": "https://api.ruuster.com/v1/properties/5b7e2d94-1c63-4a8f-b5e0-9d3c7a2f1e86/engagement"
  }
}

Below, LEAD_SAM stands for the lead object above, LEAD_PRIYA for { "leadId": "unregistered:8d2b6f19-4e37-4a85-b0c9-7f1e3d5a2b68", "firstName": "Priya", "lastName": "Shah", "email": "priya.shah@example.com", "phone": "+15205550187", "crmExternalId": "51907", "agentId": "e5a7d3c1-9b46-4f28-8c0e-6d2a1f7b3e95" }, and PROP_A for the property object above. In real deliveries these are always written out in full.

Lead events

{ "kind": "lead.created", "occurredAt": "2026-09-23T15:44:12Z",
  "data": { "lead": LEAD_PRIYA, "leadType": "unregistered", "createdBy": { "type": "agent", "id": "e5a7d3c1-9b46-4f28-8c0e-6d2a1f7b3e95" } } }
{ "kind": "lead.property_view", "occurredAt": "2026-09-27T23:40:12Z",
  "data": { "lead": LEAD_SAM, "property": PROP_A, "viewsToday": 3 } }
{ "kind": "lead.favorite", "occurredAt": "2026-09-29T14:21:55Z",
  "data": { "lead": LEAD_SAM, "property": PROP_A } }
{ "kind": "lead.saved_search_created", "occurredAt": "2026-09-29T14:30:02Z",
  "data": { "lead": LEAD_SAM, "savedSearch": { "savedSearchId": "b81f4d20-6c3e-4a97-9e15-0d7c2a5f8b36", "name": "Catalina Foothills 3bd" },
            "createdBy": { "type": "lead", "id": "user:c0ff3e21-8a4b-4c7d-9e15-2b6f8d3a1c04" } } }
{ "kind": "lead.saved_search_updated", "occurredAt": "2026-09-30T16:05:41Z",
  "data": { "lead": LEAD_SAM, "savedSearch": { "savedSearchId": "b81f4d20-6c3e-4a97-9e15-0d7c2a5f8b36", "name": "Catalina Foothills 3bd" },
            "updatedBy": { "type": "agent", "id": "7c1e9b42-3d85-4a6f-9e07-1b2c8d4f5a69" } } }
{ "kind": "lead.search", "occurredAt": "2026-09-28T13:04:27Z",
  "data": { "lead": LEAD_SAM, "search": { "type": "listings" } } }
{ "kind": "lead.email_open", "occurredAt": "2026-09-29T14:12:02Z",
  "data": { "lead": LEAD_SAM,
            "email": { "emailId": "em_7Yq2pX8mT4cW", "subject": "3 new homes match \"Catalina Foothills 3bd\"", "savedSearchName": "Catalina Foothills 3bd", "sentAt": "2026-09-29T12:00:31Z" } } }
{ "kind": "lead.email_click", "occurredAt": "2026-09-29T14:15:40Z",
  "data": { "lead": LEAD_SAM,
            "email": { "emailId": "em_7Yq2pX8mT4cW", "subject": "3 new homes match \"Catalina Foothills 3bd\"", "savedSearchName": "Catalina Foothills 3bd", "sentAt": "2026-09-29T12:00:31Z" } } }
{ "kind": "lead.tour_request", "occurredAt": "2026-09-30T02:19:03Z",
  "data": { "lead": LEAD_SAM, "property": PROP_A, "tourDate": "2026-10-04", "partOfDay": "morning" } }
{ "kind": "lead.contact_agent", "occurredAt": "2026-09-30T19:07:56Z",
  "data": { "lead": LEAD_PRIYA,
            "property": { "propertyId": "a03c8f61-7e2b-4d95-8a14-6f0b3e9c2d57", "mlsRecordId": "22419302", "address": "1920 W Mesquite Ridge Ln, Oro Valley, AZ 85737", "ownedByYou": true },
            "agentId": "e5a7d3c1-9b46-4f28-8c0e-6d2a1f7b3e95" } }
{ "kind": "lead.login", "occurredAt": "2026-09-30T02:11:40Z",
  "data": { "lead": LEAD_SAM, "platform": "ios" } }
{ "kind": "lead.share", "occurredAt": "2026-09-30T23:58:44Z",
  "data": { "lead": LEAD_SAM, "property": PROP_A, "channel": "sms" } }
{ "kind": "lead.email_status_changed", "occurredAt": "2026-10-29T14:10:00Z",
  "data": { "lead": LEAD_SAM,
            "emailStatus": { "status": "invalid", "code": "5.1.1 bounce",
                             "reason": "The mailbox does not exist or no longer accepts mail.",
                             "source": "delivery", "failedAt": "2026-10-29T14:02:11Z",
                             "since": "2026-10-29T14:10:00Z", "previousStatus": "valid" } } }

Test event

{ "id": "evt_test_1b6d0c93", "kind": "webhook.test", "occurredAt": "2026-10-01T14:21:30Z",
  "brokerageId": "4f6c2a9e-8d31-4b57-9a0e-2c7d5e1b8f43", "apiVersion": "v1",
  "data": { "message": "Hello from Ruuster", "subscriptionId": "whk_2c7f9a4e1b" } }

Batch (sent when a subscription would receive more than one event per second):

{
  "id": "bat_0e4c7a91d2",
  "kind": "batch",
  "apiVersion": "v1",
  "count": 2,
  "events": [
    { "id": "evt_71c2e9b04d3a8f65", "kind": "lead.property_view", "occurredAt": "2026-09-28T13:05:02Z", "brokerageId": "4f6c2a9e-8d31-4b57-9a0e-2c7d5e1b8f43", "apiVersion": "v1", "data": { "lead": LEAD_SAM, "property": PROP_A, "viewsToday": 1 } },
    { "id": "evt_b4d90f2a6e17c385", "kind": "lead.search", "occurredAt": "2026-09-28T13:05:03Z", "brokerageId": "4f6c2a9e-8d31-4b57-9a0e-2c7d5e1b8f43", "apiVersion": "v1", "data": { "lead": LEAD_SAM, "search": { "type": "listings" } } }
  ]
}

Your endpoint answers any 2xx within 10 seconds, for example 200 with body ok. The body is ignored.