Property Activity & Viewings

Register and manage own-listing viewings, and read the merged property activity feed.

The property-activity API manages viewings and returns a merged chronological feed for a Fondaro listing owned by the caller's organization. These routes require a Clerk session JWT and active organization. They do not accept a Fondaro property API key.

Authorization: Bearer CLERK_SESSION_JWT
x-organization-id: ORGANIZATION_ID

All listing and viewing identifiers are UUIDs. A listing outside the active organization is returned as 404, the same as a missing listing.

Route catalogue

MethodRoutePurpose
GET/properties/:id/viewingsList registered viewings for one own listing
POST/properties/:id/viewingsRegister a viewing
PATCH/viewings/:viewingIdChange a viewing
DELETE/viewings/:viewingIdDelete a viewing
GET/properties/:id/activityRead viewings, listing changes, deal events, and brochure links as one feed

Any member of the owning organization can read the routes and register a viewing. A non-admin can edit or delete only a viewing whose createdBy is their Clerk user id; an organization admin can change any viewing in the organization.

Viewing object

{
  "id": "67444de5-bfa4-4aa4-87c3-a1b2f1a4af59",
  "organizationId": "69e9323f-e150-4317-9a8b-e952d0704fc4",
  "propertyListingId": "29a1e184-237a-40c8-a1fe-624b0bcbb2f4",
  "leadId": 4312,
  "collaboratorLeadId": 8821,
  "agentUserId": "user_2abc123",
  "dealId": "5a149be6-e22f-4633-8f13-e8ddb169cd4d",
  "viewingAt": "2026-07-28T09:30:00.000Z",
  "kind": "in_person",
  "status": "scheduled",
  "notes": "Meet at reception.",
  "source": "user",
  "createdBy": "user_2abc123",
  "createdAt": "2026-07-23T14:12:09.000Z",
  "updatedAt": "2026-07-23T14:12:09.000Z"
}

Closed vocabularies:

  • kind: in_person or virtual
  • status: scheduled, completed, cancelled, or no_show
  • source: user, mcp, import, n8n, or system; HTTP creation always writes user

The client, collaborator, hosting member, and deal links are nullable. Deleting a linked lead or deal clears that link without deleting the viewing.

List viewings

GET /properties/29a1e184-237a-40c8-a1fe-624b0bcbb2f4/viewings?limit=20&offset=0
Authorization: Bearer CLERK_SESSION_JWT
x-organization-id: ORGANIZATION_ID
QueryTypeDefaultConstraints
limitinteger201–100
offsetinteger00 or greater

The response is newest first by viewingAt:

{
  "viewings": [],
  "total": 0,
  "hasMore": false
}

This flat list returns viewing rows only. Use the Activity endpoint when you need client and collaborator name labels or the listing's other event types.

Register a viewing

POST /properties/29a1e184-237a-40c8-a1fe-624b0bcbb2f4/viewings
Authorization: Bearer CLERK_SESSION_JWT
x-organization-id: ORGANIZATION_ID
Content-Type: application/json
{
  "viewingAt": "2026-07-28T09:30:00.000Z",
  "kind": "in_person",
  "leadId": 4312,
  "collaboratorLeadId": 8821,
  "agentUserId": "user_2abc123",
  "dealId": "5a149be6-e22f-4633-8f13-e8ddb169cd4d",
  "notes": "Meet at reception."
}
FieldTypeRequiredRules
viewingAtISO 8601 stringYesDate and time of the viewing
kindstringYesin_person or virtual
statusstringNoOmit to derive it from viewingAt
leadIdinteger or nullNoClient CRM lead
collaboratorLeadIdinteger or nullNoReferring external-agent lead
agentUserIdstring or nullNoHosting Clerk user id, maximum 255 characters; omission defaults to the caller
dealIdUUID or nullNoOptional deal in the organization
notesstring or nullNoMaximum 5,000 characters

When status is omitted, a time at or before the request time becomes completed; a future time becomes scheduled.

If a lead id is supplied, it must identify a purchased CRM lead with a CRM status in the active organization. A member must already be assigned to that lead; an organization admin may attach any eligible lead in the organization. The same visibility rule is applied to collaboratorLeadId. Attaching a lead does not grant CRM access. The dashboard filters the collaborator picker to collaborator-type leads; callers should preserve that convention.

The response is the created viewing object.

Update a viewing

PATCH /viewings/:viewingId accepts the same fields as create, all optional. An omitted key remains unchanged. Explicit null clears leadId, collaboratorLeadId, agentUserId, dealId, or notes.

{
  "status": "completed",
  "notes": "Client requested a second visit."
}

Changing viewingAt does not re-derive the status on update. Send the intended status in the same patch when moving a viewing across past/future boundaries.

Delete a viewing

DELETE /viewings/67444de5-bfa4-4aa4-87c3-a1b2f1a4af59
Authorization: Bearer CLERK_SESSION_JWT
x-organization-id: ORGANIZATION_ID
{
  "success": true
}

Read property activity

GET /properties/29a1e184-237a-40c8-a1fe-624b0bcbb2f4/activity?types=viewing,deal&limit=20&offset=0
Authorization: Bearer CLERK_SESSION_JWT
x-organization-id: ORGANIZATION_ID
QueryTypeDefaultDescription
typesstring or repeated string[]allviewing, change, deal, and/or brochure; comma-separated and repeated forms are both accepted
limitinteger201–100
offsetinteger00 or greater

The response merges four data sources, sorts them newest first, then applies the requested page:

{
  "entries": [
    {
      "type": "viewing",
      "date": "2026-07-28T09:30:00.000Z",
      "viewing": {
        "id": "67444de5-bfa4-4aa4-87c3-a1b2f1a4af59",
        "propertyListingId": "29a1e184-237a-40c8-a1fe-624b0bcbb2f4",
        "leadId": 4312,
        "collaboratorLeadId": 8821,
        "viewingAt": "2026-07-28T09:30:00.000Z",
        "kind": "in_person",
        "status": "scheduled"
      },
      "lead": { "id": 4312, "firstName": "Alex", "lastName": "Morgan" },
      "collaborator": { "id": 8821, "firstName": "Sam", "lastName": "Lee" }
    }
  ],
  "total": 1,
  "hasMore": false
}

Entry type values are finer-grained than the filter:

  • viewing, with viewing and nullable lead/collaborator name labels;
  • change, with a server-written change event and field-level changes;
  • deal-stage-change, deal-won, or deal-lost, each selected by the deal filter; and
  • brochure, with brochureId, slug, title, listing reference, and creation time.

total is the number of merged entries loaded for the requested window and can be a lower bound when a source has more history than the per-source cap. Use hasMore and advance offset rather than relying on total as an exact all-time count.

Common errors

StatusCondition
400Invalid UUID, query value, enum value, date, or field constraint
403A member tries to attach a lead they cannot access, or change another member's viewing
404Listing, viewing, eligible lead, or deal is unavailable in the active organization

Fondaro Help

Docs & support

Hi there, how can we help?

Browse popular articles or ask a question below.

Popular articles

Powered by Claude

Or ask a question